Repository: coollabsio/coolify Branch: v4.x Commit: 89aecc28a9ef Files: 2199 Total size: 29.0 MB Directory structure: gitextract_ds_ksj1y/ ├── .agents/ │ └── skills/ │ ├── debugging-output-and-previewing-html-using-ray/ │ │ └── SKILL.md │ ├── developing-with-fortify/ │ │ └── SKILL.md │ ├── livewire-development/ │ │ └── SKILL.md │ ├── pest-testing/ │ │ └── SKILL.md │ └── tailwindcss-development/ │ └── SKILL.md ├── .ai/ │ └── design-system.md ├── .claude/ │ └── skills/ │ ├── debugging-output-and-previewing-html-using-ray/ │ │ └── SKILL.md │ ├── developing-with-fortify/ │ │ └── SKILL.md │ ├── livewire-development/ │ │ └── SKILL.md │ ├── pest-testing/ │ │ └── SKILL.md │ └── tailwindcss-development/ │ └── SKILL.md ├── .codex/ │ └── config.toml ├── .coolify-logo ├── .cursor/ │ ├── mcp.json │ ├── rules/ │ │ └── coolify-ai-docs.mdc │ └── skills/ │ ├── debugging-output-and-previewing-html-using-ray/ │ │ └── SKILL.md │ ├── developing-with-fortify/ │ │ └── SKILL.md │ ├── livewire-development/ │ │ └── SKILL.md │ ├── pest-testing/ │ │ └── SKILL.md │ └── tailwindcss-development/ │ └── SKILL.md ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── FUNDING.yaml │ ├── ISSUE_TEMPLATE/ │ │ ├── 01_BUG_REPORT.yml │ │ ├── 02_ENHANCEMENT_BOUNTY.yml │ │ └── config.yml │ ├── pull_request_template.md │ └── workflows/ │ ├── chore-lock-closed-issues-discussions-and-prs.yml │ ├── chore-manage-stale-issues-and-prs.yml │ ├── chore-pr-comments.yml │ ├── claude.yml │ ├── cleanup-ghcr-untagged.yml │ ├── coolify-helper-next.yml │ ├── coolify-helper.yml │ ├── coolify-production-build.yml │ ├── coolify-realtime-next.yml │ ├── coolify-realtime.yml │ ├── coolify-staging-build.yml │ ├── coolify-testing-host.yml │ ├── generate-changelog.yml │ └── pr-quality.yaml ├── .mcp.json ├── .phpactor.json ├── AGENTS.md ├── CLAUDE.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASE.md ├── SECURITY.md ├── TECH_STACK.md ├── app/ │ ├── Actions/ │ │ ├── Application/ │ │ │ ├── CleanupPreviewDeployment.php │ │ │ ├── GenerateConfig.php │ │ │ ├── IsHorizonQueueEmpty.php │ │ │ ├── LoadComposeFile.php │ │ │ ├── StopApplication.php │ │ │ └── StopApplicationOneServer.php │ │ ├── CoolifyTask/ │ │ │ ├── PrepareCoolifyTask.php │ │ │ └── RunRemoteProcess.php │ │ ├── Database/ │ │ │ ├── RestartDatabase.php │ │ │ ├── StartClickhouse.php │ │ │ ├── StartDatabase.php │ │ │ ├── StartDatabaseProxy.php │ │ │ ├── StartDragonfly.php │ │ │ ├── StartKeydb.php │ │ │ ├── StartMariadb.php │ │ │ ├── StartMongodb.php │ │ │ ├── StartMysql.php │ │ │ ├── StartPostgresql.php │ │ │ ├── StartRedis.php │ │ │ ├── StopDatabase.php │ │ │ └── StopDatabaseProxy.php │ │ ├── Docker/ │ │ │ └── GetContainersStatus.php │ │ ├── Fortify/ │ │ │ ├── CreateNewUser.php │ │ │ ├── ResetUserPassword.php │ │ │ ├── UpdateUserPassword.php │ │ │ └── UpdateUserProfileInformation.php │ │ ├── Proxy/ │ │ │ ├── CheckProxy.php │ │ │ ├── GetProxyConfiguration.php │ │ │ ├── SaveProxyConfiguration.php │ │ │ ├── StartProxy.php │ │ │ └── StopProxy.php │ │ ├── Server/ │ │ │ ├── CheckUpdates.php │ │ │ ├── CleanupDocker.php │ │ │ ├── ConfigureCloudflared.php │ │ │ ├── DeleteServer.php │ │ │ ├── InstallDocker.php │ │ │ ├── InstallPrerequisites.php │ │ │ ├── ResourcesCheck.php │ │ │ ├── RestartContainer.php │ │ │ ├── RunCommand.php │ │ │ ├── StartLogDrain.php │ │ │ ├── StartSentinel.php │ │ │ ├── StopLogDrain.php │ │ │ ├── StopSentinel.php │ │ │ ├── UpdateCoolify.php │ │ │ ├── UpdatePackage.php │ │ │ ├── ValidatePrerequisites.php │ │ │ └── ValidateServer.php │ │ ├── Service/ │ │ │ ├── DeleteService.php │ │ │ ├── RestartService.php │ │ │ ├── StartService.php │ │ │ └── StopService.php │ │ ├── Shared/ │ │ │ └── ComplexStatusCheck.php │ │ ├── Stripe/ │ │ │ ├── CancelSubscription.php │ │ │ ├── CancelSubscriptionAtPeriodEnd.php │ │ │ ├── RefundSubscription.php │ │ │ ├── ResumeSubscription.php │ │ │ └── UpdateSubscriptionQuantity.php │ │ └── User/ │ │ ├── DeleteUserResources.php │ │ ├── DeleteUserServers.php │ │ └── DeleteUserTeams.php │ ├── Console/ │ │ ├── Commands/ │ │ │ ├── AdminDeleteUser.php │ │ │ ├── CheckApplicationDeploymentQueue.php │ │ │ ├── CheckTraefikVersionCommand.php │ │ │ ├── CleanupApplicationDeploymentQueue.php │ │ │ ├── CleanupDatabase.php │ │ │ ├── CleanupNames.php │ │ │ ├── CleanupRedis.php │ │ │ ├── CleanupStuckedResources.php │ │ │ ├── CleanupUnreachableServers.php │ │ │ ├── ClearGlobalSearchCache.php │ │ │ ├── Cloud/ │ │ │ │ ├── CloudFixSubscription.php │ │ │ │ ├── RestoreDatabase.php │ │ │ │ └── SyncStripeSubscriptions.php │ │ │ ├── Dev.php │ │ │ ├── Emails.php │ │ │ ├── Generate/ │ │ │ │ ├── OpenApi.php │ │ │ │ └── Services.php │ │ │ ├── GenerateTestingSchema.php │ │ │ ├── Horizon.php │ │ │ ├── HorizonManage.php │ │ │ ├── Init.php │ │ │ ├── Migration.php │ │ │ ├── NotifyDemo.php │ │ │ ├── RootChangeEmail.php │ │ │ ├── RootResetPassword.php │ │ │ ├── RunScheduledJobsManually.php │ │ │ ├── Scheduler.php │ │ │ ├── Seeder.php │ │ │ ├── ServicesDelete.php │ │ │ ├── SyncBunny.php │ │ │ ├── UpdateServiceVersions.php │ │ │ └── ViewScheduledLogs.php │ │ └── Kernel.php │ ├── Contracts/ │ │ └── CustomJobRepositoryInterface.php │ ├── Data/ │ │ ├── CoolifyTaskArgs.php │ │ └── ServerMetadata.php │ ├── Enums/ │ │ ├── ActivityTypes.php │ │ ├── ApplicationDeploymentStatus.php │ │ ├── BuildPackTypes.php │ │ ├── ContainerStatusTypes.php │ │ ├── NewDatabaseTypes.php │ │ ├── NewResourceTypes.php │ │ ├── ProcessStatus.php │ │ ├── ProxyTypes.php │ │ ├── RedirectTypes.php │ │ ├── Role.php │ │ └── StaticImageTypes.php │ ├── Events/ │ │ ├── ApplicationConfigurationChanged.php │ │ ├── ApplicationStatusChanged.php │ │ ├── BackupCreated.php │ │ ├── CloudflareTunnelChanged.php │ │ ├── CloudflareTunnelConfigured.php │ │ ├── DatabaseProxyStopped.php │ │ ├── DatabaseStatusChanged.php │ │ ├── DockerCleanupDone.php │ │ ├── FileStorageChanged.php │ │ ├── ProxyStatusChanged.php │ │ ├── ProxyStatusChangedUI.php │ │ ├── RestoreJobFinished.php │ │ ├── S3RestoreJobFinished.php │ │ ├── ScheduledTaskDone.php │ │ ├── SentinelRestarted.php │ │ ├── ServerPackageUpdated.php │ │ ├── ServerReachabilityChanged.php │ │ ├── ServerValidated.php │ │ ├── ServiceChecked.php │ │ ├── ServiceStatusChanged.php │ │ └── TestEvent.php │ ├── Exceptions/ │ │ ├── DeploymentException.php │ │ ├── Handler.php │ │ ├── NonReportableException.php │ │ ├── ProcessException.php │ │ └── RateLimitException.php │ ├── Helpers/ │ │ ├── SshMultiplexingHelper.php │ │ ├── SshRetryHandler.php │ │ └── SslHelper.php │ ├── Http/ │ │ ├── Controllers/ │ │ │ ├── Api/ │ │ │ │ ├── ApplicationsController.php │ │ │ │ ├── CloudProviderTokensController.php │ │ │ │ ├── DatabasesController.php │ │ │ │ ├── DeployController.php │ │ │ │ ├── GithubController.php │ │ │ │ ├── HetznerController.php │ │ │ │ ├── OpenApi.php │ │ │ │ ├── OtherController.php │ │ │ │ ├── ProjectController.php │ │ │ │ ├── ResourcesController.php │ │ │ │ ├── ScheduledTasksController.php │ │ │ │ ├── SecurityController.php │ │ │ │ ├── ServersController.php │ │ │ │ ├── ServicesController.php │ │ │ │ └── TeamController.php │ │ │ ├── Controller.php │ │ │ ├── OauthController.php │ │ │ ├── UploadController.php │ │ │ └── Webhook/ │ │ │ ├── Bitbucket.php │ │ │ ├── Gitea.php │ │ │ ├── Github.php │ │ │ ├── Gitlab.php │ │ │ └── Stripe.php │ │ ├── Kernel.php │ │ └── Middleware/ │ │ ├── ApiAbility.php │ │ ├── ApiAllowed.php │ │ ├── ApiSensitiveData.php │ │ ├── Authenticate.php │ │ ├── CanAccessTerminal.php │ │ ├── CanCreateResources.php │ │ ├── CanUpdateResource.php │ │ ├── CheckForcePasswordReset.php │ │ ├── DecideWhatToDoWithUser.php │ │ ├── EncryptCookies.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ ├── ValidateSignature.php │ │ └── VerifyCsrfToken.php │ ├── Jobs/ │ │ ├── ApplicationDeploymentJob.php │ │ ├── ApplicationPullRequestUpdateJob.php │ │ ├── CheckAndStartSentinelJob.php │ │ ├── CheckForUpdatesJob.php │ │ ├── CheckHelperImageJob.php │ │ ├── CheckTraefikVersionForServerJob.php │ │ ├── CheckTraefikVersionJob.php │ │ ├── CleanupHelperContainersJob.php │ │ ├── CleanupInstanceStuffsJob.php │ │ ├── CleanupOrphanedPreviewContainersJob.php │ │ ├── CleanupStaleMultiplexedConnections.php │ │ ├── ConnectProxyToNetworksJob.php │ │ ├── CoolifyTask.php │ │ ├── DatabaseBackupJob.php │ │ ├── DeleteResourceJob.php │ │ ├── DockerCleanupJob.php │ │ ├── GithubAppPermissionJob.php │ │ ├── ProcessGithubPullRequestWebhook.php │ │ ├── PullChangelog.php │ │ ├── PullTemplatesFromCDN.php │ │ ├── PushServerUpdateJob.php │ │ ├── RegenerateSslCertJob.php │ │ ├── RestartProxyJob.php │ │ ├── ScheduledJobManager.php │ │ ├── ScheduledTaskJob.php │ │ ├── SendMessageToDiscordJob.php │ │ ├── SendMessageToPushoverJob.php │ │ ├── SendMessageToSlackJob.php │ │ ├── SendMessageToTelegramJob.php │ │ ├── SendWebhookJob.php │ │ ├── ServerCheckJob.php │ │ ├── ServerCleanupMux.php │ │ ├── ServerConnectionCheckJob.php │ │ ├── ServerFilesFromServerJob.php │ │ ├── ServerLimitCheckJob.php │ │ ├── ServerManagerJob.php │ │ ├── ServerPatchCheckJob.php │ │ ├── ServerStorageCheckJob.php │ │ ├── ServerStorageSaveJob.php │ │ ├── StripeProcessJob.php │ │ ├── SubscriptionInvoiceFailedJob.php │ │ ├── SyncStripeSubscriptionsJob.php │ │ ├── UpdateCoolifyJob.php │ │ ├── UpdateStripeCustomerEmailJob.php │ │ ├── ValidateAndInstallServerJob.php │ │ ├── VerifyStripeSubscriptionStatusJob.php │ │ └── VolumeCloneJob.php │ ├── Listeners/ │ │ ├── CloudflareTunnelChangedNotification.php │ │ └── ProxyStatusChangedNotification.php │ ├── Livewire/ │ │ ├── ActivityMonitor.php │ │ ├── Admin/ │ │ │ └── Index.php │ │ ├── Boarding/ │ │ │ └── Index.php │ │ ├── Dashboard.php │ │ ├── DeploymentsIndicator.php │ │ ├── Destination/ │ │ │ ├── Index.php │ │ │ ├── New/ │ │ │ │ └── Docker.php │ │ │ └── Show.php │ │ ├── ForcePasswordReset.php │ │ ├── GlobalSearch.php │ │ ├── Help.php │ │ ├── LayoutPopups.php │ │ ├── MonacoEditor.php │ │ ├── NavbarDeleteTeam.php │ │ ├── Notifications/ │ │ │ ├── Discord.php │ │ │ ├── Email.php │ │ │ ├── Pushover.php │ │ │ ├── Slack.php │ │ │ ├── Telegram.php │ │ │ └── Webhook.php │ │ ├── Profile/ │ │ │ └── Index.php │ │ ├── Project/ │ │ │ ├── AddEmpty.php │ │ │ ├── Application/ │ │ │ │ ├── Advanced.php │ │ │ │ ├── Configuration.php │ │ │ │ ├── Deployment/ │ │ │ │ │ ├── Index.php │ │ │ │ │ └── Show.php │ │ │ │ ├── DeploymentNavbar.php │ │ │ │ ├── General.php │ │ │ │ ├── Heading.php │ │ │ │ ├── Preview/ │ │ │ │ │ └── Form.php │ │ │ │ ├── Previews.php │ │ │ │ ├── PreviewsCompose.php │ │ │ │ ├── Rollback.php │ │ │ │ ├── Source.php │ │ │ │ └── Swarm.php │ │ │ ├── CloneMe.php │ │ │ ├── Database/ │ │ │ │ ├── Backup/ │ │ │ │ │ ├── Execution.php │ │ │ │ │ └── Index.php │ │ │ │ ├── BackupEdit.php │ │ │ │ ├── BackupExecutions.php │ │ │ │ ├── BackupNow.php │ │ │ │ ├── Clickhouse/ │ │ │ │ │ └── General.php │ │ │ │ ├── Configuration.php │ │ │ │ ├── CreateScheduledBackup.php │ │ │ │ ├── Dragonfly/ │ │ │ │ │ └── General.php │ │ │ │ ├── Heading.php │ │ │ │ ├── Import.php │ │ │ │ ├── InitScript.php │ │ │ │ ├── Keydb/ │ │ │ │ │ └── General.php │ │ │ │ ├── Mariadb/ │ │ │ │ │ └── General.php │ │ │ │ ├── Mongodb/ │ │ │ │ │ └── General.php │ │ │ │ ├── Mysql/ │ │ │ │ │ └── General.php │ │ │ │ ├── Postgresql/ │ │ │ │ │ └── General.php │ │ │ │ ├── Redis/ │ │ │ │ │ └── General.php │ │ │ │ └── ScheduledBackups.php │ │ │ ├── DeleteEnvironment.php │ │ │ ├── DeleteProject.php │ │ │ ├── Edit.php │ │ │ ├── EnvironmentEdit.php │ │ │ ├── Index.php │ │ │ ├── New/ │ │ │ │ ├── DockerCompose.php │ │ │ │ ├── DockerImage.php │ │ │ │ ├── EmptyProject.php │ │ │ │ ├── GithubPrivateRepository.php │ │ │ │ ├── GithubPrivateRepositoryDeployKey.php │ │ │ │ ├── PublicGitRepository.php │ │ │ │ ├── Select.php │ │ │ │ └── SimpleDockerfile.php │ │ │ ├── Resource/ │ │ │ │ ├── Create.php │ │ │ │ └── Index.php │ │ │ ├── Service/ │ │ │ │ ├── Configuration.php │ │ │ │ ├── DatabaseBackups.php │ │ │ │ ├── EditCompose.php │ │ │ │ ├── EditDomain.php │ │ │ │ ├── FileStorage.php │ │ │ │ ├── Heading.php │ │ │ │ ├── Index.php │ │ │ │ ├── StackForm.php │ │ │ │ └── Storage.php │ │ │ ├── Shared/ │ │ │ │ ├── ConfigurationChecker.php │ │ │ │ ├── Danger.php │ │ │ │ ├── Destination.php │ │ │ │ ├── EnvironmentVariable/ │ │ │ │ │ ├── Add.php │ │ │ │ │ ├── All.php │ │ │ │ │ ├── Show.php │ │ │ │ │ └── ShowHardcoded.php │ │ │ │ ├── ExecuteContainerCommand.php │ │ │ │ ├── GetLogs.php │ │ │ │ ├── HealthChecks.php │ │ │ │ ├── Logs.php │ │ │ │ ├── Metrics.php │ │ │ │ ├── ResourceLimits.php │ │ │ │ ├── ResourceOperations.php │ │ │ │ ├── ScheduledTask/ │ │ │ │ │ ├── Add.php │ │ │ │ │ ├── All.php │ │ │ │ │ ├── Executions.php │ │ │ │ │ └── Show.php │ │ │ │ ├── Storages/ │ │ │ │ │ ├── All.php │ │ │ │ │ └── Show.php │ │ │ │ ├── Tags.php │ │ │ │ ├── Terminal.php │ │ │ │ ├── UploadConfig.php │ │ │ │ └── Webhooks.php │ │ │ └── Show.php │ │ ├── Security/ │ │ │ ├── ApiTokens.php │ │ │ ├── CloudInitScriptForm.php │ │ │ ├── CloudInitScripts.php │ │ │ ├── CloudProviderTokenForm.php │ │ │ ├── CloudProviderTokens.php │ │ │ ├── CloudTokens.php │ │ │ └── PrivateKey/ │ │ │ ├── Create.php │ │ │ ├── Index.php │ │ │ └── Show.php │ │ ├── Server/ │ │ │ ├── Advanced.php │ │ │ ├── CaCertificate/ │ │ │ │ └── Show.php │ │ │ ├── Charts.php │ │ │ ├── CloudProviderToken/ │ │ │ │ └── Show.php │ │ │ ├── CloudflareTunnel.php │ │ │ ├── Create.php │ │ │ ├── Delete.php │ │ │ ├── Destinations.php │ │ │ ├── DockerCleanup.php │ │ │ ├── DockerCleanupExecutions.php │ │ │ ├── Index.php │ │ │ ├── LogDrains.php │ │ │ ├── Navbar.php │ │ │ ├── New/ │ │ │ │ ├── ByHetzner.php │ │ │ │ └── ByIp.php │ │ │ ├── PrivateKey/ │ │ │ │ └── Show.php │ │ │ ├── Proxy/ │ │ │ │ ├── DynamicConfigurationNavbar.php │ │ │ │ ├── DynamicConfigurations.php │ │ │ │ ├── Logs.php │ │ │ │ ├── NewDynamicConfiguration.php │ │ │ │ └── Show.php │ │ │ ├── Proxy.php │ │ │ ├── Resources.php │ │ │ ├── Security/ │ │ │ │ ├── Patches.php │ │ │ │ └── TerminalAccess.php │ │ │ ├── Sentinel.php │ │ │ ├── Show.php │ │ │ ├── Swarm.php │ │ │ └── ValidateAndInstall.php │ │ ├── Settings/ │ │ │ ├── Advanced.php │ │ │ ├── Index.php │ │ │ ├── ScheduledJobs.php │ │ │ └── Updates.php │ │ ├── SettingsBackup.php │ │ ├── SettingsDropdown.php │ │ ├── SettingsEmail.php │ │ ├── SettingsOauth.php │ │ ├── SharedVariables/ │ │ │ ├── Environment/ │ │ │ │ ├── Index.php │ │ │ │ └── Show.php │ │ │ ├── Index.php │ │ │ ├── Project/ │ │ │ │ ├── Index.php │ │ │ │ └── Show.php │ │ │ └── Team/ │ │ │ └── Index.php │ │ ├── Source/ │ │ │ └── Github/ │ │ │ ├── Change.php │ │ │ └── Create.php │ │ ├── Storage/ │ │ │ ├── Create.php │ │ │ ├── Form.php │ │ │ ├── Index.php │ │ │ └── Show.php │ │ ├── Subscription/ │ │ │ ├── Actions.php │ │ │ ├── Index.php │ │ │ ├── PricingPlans.php │ │ │ └── Show.php │ │ ├── SwitchTeam.php │ │ ├── Tags/ │ │ │ ├── Deployments.php │ │ │ └── Show.php │ │ ├── Team/ │ │ │ ├── AdminView.php │ │ │ ├── Create.php │ │ │ ├── Index.php │ │ │ ├── Invitations.php │ │ │ ├── InviteLink.php │ │ │ ├── Member/ │ │ │ │ └── Index.php │ │ │ ├── Member.php │ │ │ └── Storage/ │ │ │ └── Show.php │ │ ├── Terminal/ │ │ │ └── Index.php │ │ ├── Upgrade.php │ │ └── VerifyEmail.php │ ├── Models/ │ │ ├── Application.php │ │ ├── ApplicationDeploymentQueue.php │ │ ├── ApplicationPreview.php │ │ ├── ApplicationSetting.php │ │ ├── BaseModel.php │ │ ├── CloudInitScript.php │ │ ├── CloudProviderToken.php │ │ ├── DiscordNotificationSettings.php │ │ ├── DockerCleanupExecution.php │ │ ├── EmailNotificationSettings.php │ │ ├── Environment.php │ │ ├── EnvironmentVariable.php │ │ ├── GithubApp.php │ │ ├── GitlabApp.php │ │ ├── InstanceSettings.php │ │ ├── LocalFileVolume.php │ │ ├── LocalPersistentVolume.php │ │ ├── OauthSetting.php │ │ ├── PersonalAccessToken.php │ │ ├── PrivateKey.php │ │ ├── Project.php │ │ ├── ProjectSetting.php │ │ ├── PushoverNotificationSettings.php │ │ ├── S3Storage.php │ │ ├── ScheduledDatabaseBackup.php │ │ ├── ScheduledDatabaseBackupExecution.php │ │ ├── ScheduledTask.php │ │ ├── ScheduledTaskExecution.php │ │ ├── Server.php │ │ ├── ServerSetting.php │ │ ├── Service.php │ │ ├── ServiceApplication.php │ │ ├── ServiceDatabase.php │ │ ├── SharedEnvironmentVariable.php │ │ ├── SlackNotificationSettings.php │ │ ├── SslCertificate.php │ │ ├── StandaloneClickhouse.php │ │ ├── StandaloneDocker.php │ │ ├── StandaloneDragonfly.php │ │ ├── StandaloneKeydb.php │ │ ├── StandaloneMariadb.php │ │ ├── StandaloneMongodb.php │ │ ├── StandaloneMysql.php │ │ ├── StandalonePostgresql.php │ │ ├── StandaloneRedis.php │ │ ├── Subscription.php │ │ ├── SwarmDocker.php │ │ ├── Tag.php │ │ ├── Team.php │ │ ├── TeamInvitation.php │ │ ├── TelegramNotificationSettings.php │ │ ├── User.php │ │ ├── UserChangelogRead.php │ │ └── WebhookNotificationSettings.php │ ├── Notifications/ │ │ ├── Application/ │ │ │ ├── DeploymentFailed.php │ │ │ ├── DeploymentSuccess.php │ │ │ └── StatusChanged.php │ │ ├── Channels/ │ │ │ ├── DiscordChannel.php │ │ │ ├── EmailChannel.php │ │ │ ├── PushoverChannel.php │ │ │ ├── SendsDiscord.php │ │ │ ├── SendsEmail.php │ │ │ ├── SendsPushover.php │ │ │ ├── SendsSlack.php │ │ │ ├── SendsTelegram.php │ │ │ ├── SlackChannel.php │ │ │ ├── TelegramChannel.php │ │ │ ├── TransactionalEmailChannel.php │ │ │ └── WebhookChannel.php │ │ ├── Container/ │ │ │ ├── ContainerRestarted.php │ │ │ └── ContainerStopped.php │ │ ├── CustomEmailNotification.php │ │ ├── Database/ │ │ │ ├── BackupFailed.php │ │ │ ├── BackupSuccess.php │ │ │ └── BackupSuccessWithS3Warning.php │ │ ├── Dto/ │ │ │ ├── DiscordMessage.php │ │ │ ├── PushoverMessage.php │ │ │ └── SlackMessage.php │ │ ├── Internal/ │ │ │ └── GeneralNotification.php │ │ ├── Notification.php │ │ ├── ScheduledTask/ │ │ │ ├── TaskFailed.php │ │ │ └── TaskSuccess.php │ │ ├── Server/ │ │ │ ├── DockerCleanupFailed.php │ │ │ ├── DockerCleanupSuccess.php │ │ │ ├── ForceDisabled.php │ │ │ ├── ForceEnabled.php │ │ │ ├── HetznerDeletionFailed.php │ │ │ ├── HighDiskUsage.php │ │ │ ├── Reachable.php │ │ │ ├── ServerPatchCheck.php │ │ │ ├── TraefikVersionOutdated.php │ │ │ └── Unreachable.php │ │ ├── SslExpirationNotification.php │ │ ├── Test.php │ │ └── TransactionalEmails/ │ │ ├── EmailChangeVerification.php │ │ ├── InvitationLink.php │ │ ├── ResetPassword.php │ │ └── Test.php │ ├── Policies/ │ │ ├── ApiTokenPolicy.php │ │ ├── ApplicationPolicy.php │ │ ├── ApplicationPreviewPolicy.php │ │ ├── ApplicationSettingPolicy.php │ │ ├── CloudInitScriptPolicy.php │ │ ├── CloudProviderTokenPolicy.php │ │ ├── DatabasePolicy.php │ │ ├── EnvironmentPolicy.php │ │ ├── EnvironmentVariablePolicy.php │ │ ├── GithubAppPolicy.php │ │ ├── InstanceSettingsPolicy.php │ │ ├── NotificationPolicy.php │ │ ├── PrivateKeyPolicy.php │ │ ├── ProjectPolicy.php │ │ ├── ResourceCreatePolicy.php │ │ ├── S3StoragePolicy.php │ │ ├── ServerPolicy.php │ │ ├── ServiceApplicationPolicy.php │ │ ├── ServiceDatabasePolicy.php │ │ ├── ServicePolicy.php │ │ ├── SharedEnvironmentVariablePolicy.php │ │ ├── StandaloneDockerPolicy.php │ │ ├── SwarmDockerPolicy.php │ │ └── TeamPolicy.php │ ├── Providers/ │ │ ├── AppServiceProvider.php │ │ ├── AuthServiceProvider.php │ │ ├── BroadcastServiceProvider.php │ │ ├── ConfigurationServiceProvider.php │ │ ├── DuskServiceProvider.php │ │ ├── EventServiceProvider.php │ │ ├── FortifyServiceProvider.php │ │ ├── HorizonServiceProvider.php │ │ ├── RouteServiceProvider.php │ │ └── TelescopeServiceProvider.php │ ├── Repositories/ │ │ └── CustomJobRepository.php │ ├── Rules/ │ │ ├── DockerImageFormat.php │ │ ├── ValidCloudInitYaml.php │ │ ├── ValidGitBranch.php │ │ ├── ValidGitRepositoryUrl.php │ │ ├── ValidHostname.php │ │ ├── ValidIpOrCidr.php │ │ ├── ValidProxyConfigFilename.php │ │ └── ValidServerIp.php │ ├── Services/ │ │ ├── ChangelogService.php │ │ ├── ConfigurationGenerator.php │ │ ├── ConfigurationRepository.php │ │ ├── ContainerStatusAggregator.php │ │ ├── DockerImageParser.php │ │ ├── HetznerService.php │ │ ├── ProxyDashboardCacheService.php │ │ └── SchedulerLogParser.php │ ├── Support/ │ │ └── ValidationPatterns.php │ ├── Traits/ │ │ ├── AuthorizesResourceCreation.php │ │ ├── CalculatesExcludedStatus.php │ │ ├── ClearsGlobalSearchCache.php │ │ ├── DeletesUserSessions.php │ │ ├── EnvironmentVariableAnalyzer.php │ │ ├── EnvironmentVariableProtection.php │ │ ├── ExecuteRemoteCommand.php │ │ ├── HasConfiguration.php │ │ ├── HasMetrics.php │ │ ├── HasNotificationSettings.php │ │ ├── HasSafeStringAttribute.php │ │ ├── SaveFromRedirect.php │ │ └── SshRetryable.php │ └── View/ │ └── Components/ │ ├── Forms/ │ │ ├── Button.php │ │ ├── Checkbox.php │ │ ├── Datalist.php │ │ ├── EnvVarInput.php │ │ ├── Input.php │ │ ├── Select.php │ │ └── Textarea.php │ ├── Modal.php │ ├── ResourceView.php │ ├── Services/ │ │ ├── Advanced.php │ │ ├── Explanation.php │ │ └── Links.php │ └── Status/ │ ├── Index.php │ └── Services.php ├── artisan ├── backlog/ │ ├── config.yml │ └── tasks/ │ ├── task-00001 - Implement-Docker-build-caching-for-Coolify-staging-builds.md │ ├── task-00001.01 - Add-BuildKit-cache-mounts-to-Dockerfile.md │ ├── task-00001.02 - Configure-BuildX-and-registry-caching-for-AMD64-staging-builds.md │ ├── task-00001.03 - Configure-BuildX-and-registry-caching-for-AARCH64-staging-builds.md │ ├── task-00001.04 - Establish-build-time-baseline-measurements.md │ ├── task-00001.05 - Validate-caching-implementation-and-measure-performance-improvements.md │ ├── task-00001.06 - Document-cache-optimization-results-and-create-production-workflow-plan.md │ ├── task-00002 - Fix-Docker-cleanup-irregular-scheduling-in-cloud-environment.md │ └── task-00003 - Simplify-resource-operations-UI-replace-boxes-with-dropdown-selections.md ├── boost.json ├── bootstrap/ │ ├── app.php │ ├── cache/ │ │ └── .gitignore │ ├── getHelperVersion.php │ ├── getRealtimeVersion.php │ ├── getVersion.php │ ├── helpers/ │ │ ├── api.php │ │ ├── applications.php │ │ ├── constants.php │ │ ├── databases.php │ │ ├── docker.php │ │ ├── domains.php │ │ ├── github.php │ │ ├── notifications.php │ │ ├── parsers.php │ │ ├── proxy.php │ │ ├── remoteProcess.php │ │ ├── services.php │ │ ├── shared.php │ │ ├── socialite.php │ │ ├── subscriptions.php │ │ ├── sudo.php │ │ ├── timezone.php │ │ └── versions.php │ └── includeHelpers.php ├── changelogs/ │ └── .gitignore ├── cliff.toml ├── composer.json ├── conductor.json ├── config/ │ ├── api.php │ ├── app.php │ ├── auth.php │ ├── broadcasting.php │ ├── cache.php │ ├── chunk-upload.php │ ├── constants.php │ ├── cors.php │ ├── database.php │ ├── debugbar.php │ ├── filesystems.php │ ├── fortify.php │ ├── hashing.php │ ├── horizon.php │ ├── livewire.php │ ├── logging.php │ ├── mail.php │ ├── purify.php │ ├── queue.php │ ├── ray.php │ ├── sanctum.php │ ├── sentry.php │ ├── services.php │ ├── session.php │ ├── subscription.php │ ├── telescope.php │ ├── testing.php │ └── view.php ├── database/ │ ├── factories/ │ │ ├── ApplicationFactory.php │ │ ├── EnvironmentFactory.php │ │ ├── ProjectFactory.php │ │ ├── ScheduledTaskFactory.php │ │ ├── ServerFactory.php │ │ ├── ServiceFactory.php │ │ ├── StandaloneDockerFactory.php │ │ ├── TeamFactory.php │ │ └── UserFactory.php │ ├── migrations/ │ │ ├── 2014_10_12_000000_create_users_table.php │ │ ├── 2014_10_12_100000_create_password_reset_tokens_table.php │ │ ├── 2014_10_12_200000_add_two_factor_columns_to_users_table.php │ │ ├── 2018_08_08_100000_create_telescope_entries_table.php │ │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ │ ├── 2023_03_20_112410_create_activity_log_table.php │ │ ├── 2023_03_20_112411_add_event_column_to_activity_log_table.php │ │ ├── 2023_03_20_112412_add_batch_uuid_column_to_activity_log_table.php │ │ ├── 2023_03_20_112809_create_sessions_table.php │ │ ├── 2023_03_20_112811_create_teams_table.php │ │ ├── 2023_03_20_112812_create_team_user_table.php │ │ ├── 2023_03_20_112813_create_team_invitations_table.php │ │ ├── 2023_03_20_112814_create_instance_settings_table.php │ │ ├── 2023_03_24_140711_create_servers_table.php │ │ ├── 2023_03_24_140712_create_server_settings_table.php │ │ ├── 2023_03_24_140853_create_private_keys_table.php │ │ ├── 2023_03_27_075351_create_projects_table.php │ │ ├── 2023_03_27_075443_create_project_settings_table.php │ │ ├── 2023_03_27_075444_create_environments_table.php │ │ ├── 2023_03_27_081716_create_applications_table.php │ │ ├── 2023_03_27_081717_create_application_settings_table.php │ │ ├── 2023_03_27_081718_create_application_previews_table.php │ │ ├── 2023_03_27_083621_create_services_table.php │ │ ├── 2023_03_27_085020_create_standalone_dockers_table.php │ │ ├── 2023_03_27_085022_create_swarm_dockers_table.php │ │ ├── 2023_03_28_062150_create_kubernetes_table.php │ │ ├── 2023_03_28_083723_create_github_apps_table.php │ │ ├── 2023_03_28_083726_create_gitlab_apps_table.php │ │ ├── 2023_04_03_111012_create_local_persistent_volumes_table.php │ │ ├── 2023_05_04_194548_create_environment_variables_table.php │ │ ├── 2023_05_17_104039_create_failed_jobs_table.php │ │ ├── 2023_05_24_083426_create_application_deployment_queues_table.php │ │ ├── 2023_06_22_131459_move_wildcard_to_server.php │ │ ├── 2023_06_23_084605_remove_wildcard_domain_from_instancesettings.php │ │ ├── 2023_06_23_110548_next_channel_updates.php │ │ ├── 2023_06_23_114131_change_env_var_value_length.php │ │ ├── 2023_06_23_114132_remove_default_redirect_from_instance_settings.php │ │ ├── 2023_06_23_114133_use_application_deployment_queues_as_activity.php │ │ ├── 2023_06_23_114134_add_disk_usage_percentage_to_servers.php │ │ ├── 2023_07_13_115117_create_subscriptions_table.php │ │ ├── 2023_07_13_120719_create_webhooks_table.php │ │ ├── 2023_07_13_120721_add_license_to_instance_settings.php │ │ ├── 2023_07_27_182013_smtp_discord_schemaless_to_normal.php │ │ ├── 2023_08_06_142951_add_description_field_to_applications_table.php │ │ ├── 2023_08_06_142952_remove_foreignId_environment_variables.php │ │ ├── 2023_08_06_142954_add_readonly_localpersistentvolumes.php │ │ ├── 2023_08_07_073651_create_s3_storages_table.php │ │ ├── 2023_08_07_142950_create_standalone_postgresqls_table.php │ │ ├── 2023_08_08_150103_create_scheduled_database_backups_table.php │ │ ├── 2023_08_10_113306_create_scheduled_database_backup_executions_table.php │ │ ├── 2023_08_10_201311_add_backup_notifications_to_teams.php │ │ ├── 2023_08_11_190528_add_dockerfile_to_applications_table.php │ │ ├── 2023_08_15_095902_create_waitlists_table.php │ │ ├── 2023_08_15_111125_update_users_table.php │ │ ├── 2023_08_15_111126_update_servers_add_unreachable_count_table.php │ │ ├── 2023_08_22_071048_add_boarding_to_teams.php │ │ ├── 2023_08_22_071049_update_webhooks_type.php │ │ ├── 2023_08_22_071050_update_subscriptions_stripe.php │ │ ├── 2023_08_22_071051_add_stripe_plan_to_subscriptions.php │ │ ├── 2023_08_22_071052_add_resend_as_email.php │ │ ├── 2023_08_22_071053_add_resend_as_email_to_teams.php │ │ ├── 2023_08_22_071054_add_stripe_reasons.php │ │ ├── 2023_08_22_071055_add_discord_notifications_to_teams.php │ │ ├── 2023_08_22_071056_update_telegram_notifications.php │ │ ├── 2023_08_22_071057_add_nixpkgsarchive_to_applications.php │ │ ├── 2023_08_22_071058_add_nixpkgsarchive_to_applications_remove.php │ │ ├── 2023_08_22_071059_add_stripe_trial_ended.php │ │ ├── 2023_08_22_071060_change_invitation_link_length.php │ │ ├── 2023_09_20_082541_update_services_table.php │ │ ├── 2023_09_20_082733_create_service_databases_table.php │ │ ├── 2023_09_20_082737_create_service_applications_table.php │ │ ├── 2023_09_20_083549_update_environment_variables_table.php │ │ ├── 2023_09_22_185356_create_local_file_volumes_table.php │ │ ├── 2023_09_23_111808_update_servers_with_cloudflared.php │ │ ├── 2023_09_23_111809_remove_destination_from_services_table.php │ │ ├── 2023_09_23_111811_update_service_applications_table.php │ │ ├── 2023_09_23_111812_update_service_databases_table.php │ │ ├── 2023_09_23_111813_update_users_databases_table.php │ │ ├── 2023_09_23_111814_update_local_file_volumes_table.php │ │ ├── 2023_09_23_111815_add_healthcheck_disable_to_apps_table.php │ │ ├── 2023_09_23_111816_add_destination_to_services_table.php │ │ ├── 2023_09_23_111817_use_instance_email_settings_by_default.php │ │ ├── 2023_09_23_111818_set_notifications_on_by_default.php │ │ ├── 2023_09_23_111819_add_server_emails.php │ │ ├── 2023_10_08_111819_add_server_unreachable_count.php │ │ ├── 2023_10_10_100320_update_s3_storages_table.php │ │ ├── 2023_10_10_113144_add_dockerfile_location_applications_table.php │ │ ├── 2023_10_12_132430_create_standalone_redis_table.php │ │ ├── 2023_10_12_132431_add_standalone_redis_to_environment_variables_table.php │ │ ├── 2023_10_12_132432_add_database_selection_to_backups.php │ │ ├── 2023_10_18_072519_add_custom_labels_applications_table.php │ │ ├── 2023_10_19_101331_create_standalone_mongodbs_table.php │ │ ├── 2023_10_19_101332_add_standalone_mongodb_to_environment_variables_table.php │ │ ├── 2023_10_24_103548_create_standalone_mysqls_table.php │ │ ├── 2023_10_24_120523_create_standalone_mariadbs_table.php │ │ ├── 2023_10_24_120524_add_standalone_mysql_to_environment_variables_table.php │ │ ├── 2023_10_24_124934_add_is_shown_once_to_environment_variables_table.php │ │ ├── 2023_11_01_100437_add_restart_to_deployment_queue.php │ │ ├── 2023_11_07_123731_add_target_build_dockerfile.php │ │ ├── 2023_11_08_112815_add_custom_config_standalone_postgresql.php │ │ ├── 2023_11_09_133332_add_public_port_to_service_databases.php │ │ ├── 2023_11_12_180605_change_fqdn_to_longer_field.php │ │ ├── 2023_11_13_133059_add_sponsorship_disable.php │ │ ├── 2023_11_14_103450_add_manual_webhook_secret.php │ │ ├── 2023_11_14_121416_add_git_type.php │ │ ├── 2023_11_16_101819_add_high_disk_usage_notification.php │ │ ├── 2023_11_16_220647_add_log_drains.php │ │ ├── 2023_11_17_160437_add_drain_log_enable_by_service.php │ │ ├── 2023_11_20_094628_add_gpu_settings.php │ │ ├── 2023_11_21_121920_add_additional_destinations_to_apps.php │ │ ├── 2023_11_24_080341_add_docker_compose_location.php │ │ ├── 2023_11_28_143533_add_fields_to_swarm_dockers.php │ │ ├── 2023_11_29_075937_change_swarm_properties.php │ │ ├── 2023_12_01_091723_save_logs_view_settings.php │ │ ├── 2023_12_01_095356_add_custom_fluentd_config_for_logdrains.php │ │ ├── 2023_12_08_162228_add_soft_delete_services.php │ │ ├── 2023_12_11_103611_add_realtime_connection_problem.php │ │ ├── 2023_12_13_110214_add_soft_deletes.php │ │ ├── 2023_12_17_155616_add_custom_docker_compose_start_command.php │ │ ├── 2023_12_18_093514_add_swarm_related_things.php │ │ ├── 2023_12_19_124111_add_swarm_cluster_grouping.php │ │ ├── 2023_12_30_134507_add_description_to_environments.php │ │ ├── 2023_12_31_173041_create_scheduled_tasks_table.php │ │ ├── 2024_01_01_231053_create_scheduled_task_executions_table.php │ │ ├── 2024_01_02_113855_add_raw_compose_deployment.php │ │ ├── 2024_01_12_123422_update_cpuset_limits.php │ │ ├── 2024_01_15_084609_add_custom_dns_server.php │ │ ├── 2024_01_16_115005_add_build_server_enable.php │ │ ├── 2024_01_21_130328_add_docker_network_to_services.php │ │ ├── 2024_01_23_095832_add_manual_webhook_secret_bitbucket.php │ │ ├── 2024_01_23_113129_create_shared_environment_variables_table.php │ │ ├── 2024_01_24_095449_add_concurrent_number_of_builds_per_server.php │ │ ├── 2024_01_25_073212_add_server_id_to_queues.php │ │ ├── 2024_01_27_164724_add_application_name_and_deployment_url_to_queue.php │ │ ├── 2024_01_29_072322_change_env_variable_length.php │ │ ├── 2024_01_29_145200_add_custom_docker_run_options.php │ │ ├── 2024_02_01_111228_create_tags_table.php │ │ ├── 2024_02_05_105215_add_destination_to_app_deployments.php │ │ ├── 2024_02_06_132748_add_additional_destinations.php │ │ ├── 2024_02_08_075523_add_post_deployment_to_applications.php │ │ ├── 2024_02_08_112304_add_dynamic_timeout_for_deployments.php │ │ ├── 2024_02_15_101921_add_consistent_application_container_name.php │ │ ├── 2024_02_15_192025_add_is_gzip_enabled_to_services.php │ │ ├── 2024_02_20_165045_add_permissions_to_github_app.php │ │ ├── 2024_02_22_090900_add_only_this_server_deployment.php │ │ ├── 2024_02_23_143119_add_custom_server_limits_to_teams_ultimate.php │ │ ├── 2024_02_25_222150_add_server_force_disabled_field.php │ │ ├── 2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php │ │ ├── 2024_03_07_115054_add_notifications_notification_disable.php │ │ ├── 2024_03_08_180457_nullable_password.php │ │ ├── 2024_03_11_150013_create_oauth_settings.php │ │ ├── 2024_03_14_214402_add_multiline_envs.php │ │ ├── 2024_03_18_101440_add_version_of_envs.php │ │ ├── 2024_03_22_080914_remove_popup_notifications.php │ │ ├── 2024_03_26_122110_remove_realtime_notifications.php │ │ ├── 2024_03_28_114620_add_watch_paths_to_apps.php │ │ ├── 2024_04_09_095517_make_custom_docker_commands_longer.php │ │ ├── 2024_04_10_071920_create_standalone_keydbs_table.php │ │ ├── 2024_04_10_082220_create_standalone_dragonflies_table.php │ │ ├── 2024_04_10_091519_create_standalone_clickhouses_table.php │ │ ├── 2024_04_10_124015_add_permission_local_file_volumes.php │ │ ├── 2024_04_12_092337_add_config_hash_to_other_resources.php │ │ ├── 2024_04_15_094703_add_literal_variables.php │ │ ├── 2024_04_16_083919_add_service_type_on_creation.php │ │ ├── 2024_04_17_132541_add_rollback_queues.php │ │ ├── 2024_04_25_073615_add_docker_network_to_application_settings.php │ │ ├── 2024_04_29_111956_add_custom_hc_indicator_apps.php │ │ ├── 2024_05_06_093236_add_custom_name_to_application_settings.php │ │ ├── 2024_05_07_124019_add_server_metrics.php │ │ ├── 2024_05_10_085215_make_stripe_comment_longer.php │ │ ├── 2024_05_15_091757_add_commit_message_to_app_deployment_queue.php │ │ ├── 2024_05_15_151236_add_container_escape_toggle.php │ │ ├── 2024_05_17_082012_add_env_sorting_toggle.php │ │ ├── 2024_05_21_125739_add_scheduled_tasks_notification_to_teams.php │ │ ├── 2024_05_22_103942_change_pre_post_deployment_commands_length_in_applications.php │ │ ├── 2024_05_23_091713_add_gitea_webhook_to_applications.php │ │ ├── 2024_06_05_101019_add_docker_compose_pr_domains.php │ │ ├── 2024_06_06_103938_change_pr_issue_commend_id_type.php │ │ ├── 2024_06_11_081614_add_www_non_www_redirect.php │ │ ├── 2024_06_18_105948_move_server_metrics.php │ │ ├── 2024_06_20_102551_add_server_api_sentinel.php │ │ ├── 2024_06_21_143358_add_api_deployment_type.php │ │ ├── 2024_06_22_081140_alter_instance_settings_add_instance_name.php │ │ ├── 2024_06_25_184323_update_db.php │ │ ├── 2024_07_01_115528_add_is_api_allowed_and_iplist.php │ │ ├── 2024_07_05_120217_remove_unique_from_tag_names.php │ │ ├── 2024_07_11_083719_application_compose_versions.php │ │ ├── 2024_07_17_123828_add_is_container_labels_readonly.php │ │ ├── 2024_07_18_110424_create_application_settings_is_preserve_repository_enabled.php │ │ ├── 2024_07_18_123458_add_force_cleanup_server.php │ │ ├── 2024_07_19_132617_disable_healtcheck_by_default.php │ │ ├── 2024_07_23_112710_add_validation_logs_to_servers.php │ │ ├── 2024_08_05_142659_add_update_frequency_settings.php │ │ ├── 2024_08_07_155324_add_proxy_label_chooser.php │ │ ├── 2024_08_09_215659_add_server_cleanup_fields_to_server_settings_table.php │ │ ├── 2024_08_12_131659_add_local_file_volume_based_on_git.php │ │ ├── 2024_08_12_155023_add_timezone_to_server_and_instance_settings.php │ │ ├── 2024_08_14_183120_add_order_to_environment_variables_table.php │ │ ├── 2024_08_15_115907_add_build_server_id_to_deployment_queue.php │ │ ├── 2024_08_16_105649_add_custom_docker_options_to_dbs.php │ │ ├── 2024_08_27_090528_add_compose_parsing_version_to_services.php │ │ ├── 2024_09_05_085700_add_helper_version_to_instance_settings.php │ │ ├── 2024_09_06_062534_change_server_cleanup_to_forced.php │ │ ├── 2024_09_07_185402_change_cleanup_schedule.php │ │ ├── 2024_09_08_130756_update_server_settings_default_timezone.php │ │ ├── 2024_09_16_111428_encrypt_existing_private_keys.php │ │ ├── 2024_09_17_111226_add_ssh_key_fingerprint_to_private_keys_table.php │ │ ├── 2024_09_22_165240_add_advanced_options_to_cleanup_options_to_servers_settings_table.php │ │ ├── 2024_09_26_083441_disable_api_by_default.php │ │ ├── 2024_10_03_095427_add_dump_all_to_standalone_postgresqls.php │ │ ├── 2024_10_10_081444_remove_constraint_from_service_applications_fqdn.php │ │ ├── 2024_10_11_114331_add_required_env_variables.php │ │ ├── 2024_10_14_090416_update_metrics_token_in_server_settings.php │ │ ├── 2024_10_15_172139_add_is_shared_to_environment_variables.php │ │ ├── 2024_10_16_120026_move_redis_password_to_envs.php │ │ ├── 2024_10_16_192133_add_confirmation_settings_to_instance_settings_table.php │ │ ├── 2024_10_17_093722_add_soft_delete_to_servers.php │ │ ├── 2024_10_22_105745_add_server_disk_usage_threshold.php │ │ ├── 2024_10_22_121223_add_server_disk_usage_notification.php │ │ ├── 2024_10_29_093927_add_is_sentinel_debug_enabled_to_server_settings.php │ │ ├── 2024_10_30_074601_rename_token_permissions.php │ │ ├── 2024_11_02_213214_add_last_online_at_to_resources.php │ │ ├── 2024_11_11_125335_add_custom_nginx_configuration_to_static.php │ │ ├── 2024_11_11_125366_add_index_to_activity_log.php │ │ ├── 2024_11_22_124742_add_uuid_to_environments_table.php │ │ ├── 2024_12_05_091823_add_disable_build_cache_advanced_option.php │ │ ├── 2024_12_05_212355_create_email_notification_settings_table.php │ │ ├── 2024_12_05_212416_create_discord_notification_settings_table.php │ │ ├── 2024_12_05_212440_create_telegram_notification_settings_table.php │ │ ├── 2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php │ │ ├── 2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php │ │ ├── 2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php │ │ ├── 2024_12_06_142014_create_slack_notification_settings_table.php │ │ ├── 2024_12_09_105711_drop_waitlists_table.php │ │ ├── 2024_12_10_122142_encrypt_instance_settings_email_columns.php │ │ ├── 2024_12_10_122143_drop_resale_license.php │ │ ├── 2024_12_11_135026_create_pushover_notification_settings_table.php │ │ ├── 2024_12_11_161418_add_authentik_base_url_to_oauth_settings_table.php │ │ ├── 2024_12_13_103007_encrypt_resend_api_key_in_instance_settings.php │ │ ├── 2024_12_16_134437_add_resourceable_columns_to_environment_variables_table.php │ │ ├── 2024_12_17_140637_add_server_disk_usage_check_frequency_to_server_settings_table.php │ │ ├── 2024_12_23_142402_update_email_encryption_values.php │ │ ├── 2025_01_05_050736_add_network_aliases_to_applications_table.php │ │ ├── 2025_01_08_154008_switch_up_readonly_labels.php │ │ ├── 2025_01_10_135244_add_horizon_job_details_to_queue.php │ │ ├── 2025_01_13_130238_add_backup_retention_fields_to_scheduled_database_backups_table.php │ │ ├── 2025_01_15_130416_create_docker_cleanup_executions_table.php │ │ ├── 2025_01_16_110406_change_commit_message_to_text_in_application_deployment_queues.php │ │ ├── 2025_01_16_130238_add_finished_at_to_executions_tables.php │ │ ├── 2025_01_21_125205_update_finished_at_timestamps_if_not_set.php │ │ ├── 2025_01_22_101105_remove_wrongly_created_envs.php │ │ ├── 2025_01_27_102616_add_ssl_fields_to_database_tables.php │ │ ├── 2025_01_27_153741_create_ssl_certificates_table.php │ │ ├── 2025_01_30_125223_encrypt_local_file_volumes_fields.php │ │ ├── 2025_02_27_125249_add_index_to_scheduled_task_executions.php │ │ ├── 2025_03_01_112617_add_stripe_past_due.php │ │ ├── 2025_03_14_140150_add_storage_deletion_tracking_to_backup_executions.php │ │ ├── 2025_03_21_104103_disable_discord_here.php │ │ ├── 2025_03_26_104103_disable_mongodb_ssl_by_default.php │ │ ├── 2025_03_29_204400_revert_some_local_volume_encryption.php │ │ ├── 2025_03_31_124212_add_specific_spa_configuration.php │ │ ├── 2025_04_01_124212_stripe_comment_nullable.php │ │ ├── 2025_04_17_110026_add_application_http_basic_auth_fields.php │ │ ├── 2025_04_30_134146_add_is_migrated_to_services.php │ │ ├── 2025_05_26_100258_add_server_patch_notifications.php │ │ ├── 2025_05_29_100258_add_terminal_enabled_to_server_settings.php │ │ ├── 2025_06_06_073345_create_server_previous_ip.php │ │ ├── 2025_06_16_123532_change_sentinel_on_by_default.php │ │ ├── 2025_06_25_131350_add_is_sponsorship_popup_enabled_to_instance_settings_table.php │ │ ├── 2025_06_26_131350_optimize_activity_log_indexes.php │ │ ├── 2025_07_14_191016_add_deleted_at_to_application_previews_table.php │ │ ├── 2025_07_16_202201_add_timeout_to_scheduled_database_backups_table.php │ │ ├── 2025_08_07_142403_create_user_changelog_reads_table.php │ │ ├── 2025_08_17_102422_add_disable_local_backup_to_scheduled_database_backups_table.php │ │ ├── 2025_08_18_104146_add_email_change_fields_to_users_table.php │ │ ├── 2025_08_18_154244_change_env_sorting_default_to_false.php │ │ ├── 2025_08_21_080234_add_git_shallow_clone_to_application_settings_table.php │ │ ├── 2025_09_05_142446_add_pr_deployments_public_enabled_to_application_settings.php │ │ ├── 2025_09_10_172952_remove_is_readonly_from_local_persistent_volumes_table.php │ │ ├── 2025_09_10_173300_drop_webhooks_table.php │ │ ├── 2025_09_10_173402_drop_kubernetes_table.php │ │ ├── 2025_09_11_143432_remove_is_build_time_from_environment_variables_table.php │ │ ├── 2025_09_11_150344_add_is_buildtime_only_to_environment_variables_table.php │ │ ├── 2025_09_17_081112_add_use_build_secrets_to_application_settings.php │ │ ├── 2025_09_18_080152_add_runtime_and_buildtime_to_environment_variables_table.php │ │ ├── 2025_10_03_154100_update_clickhouse_image.php │ │ ├── 2025_10_07_120723_add_s3_uploaded_to_scheduled_database_backup_executions_table.php │ │ ├── 2025_10_08_181125_create_cloud_provider_tokens_table.php │ │ ├── 2025_10_08_185203_add_hetzner_server_id_to_servers_table.php │ │ ├── 2025_10_09_095905_add_cloud_provider_token_id_to_servers_table.php │ │ ├── 2025_10_09_113602_add_hetzner_server_status_to_servers_table.php │ │ ├── 2025_10_09_125036_add_is_validating_to_servers_table.php │ │ ├── 2025_11_02_161923_add_dev_helper_version_to_instance_settings.php │ │ ├── 2025_11_09_000001_add_timeout_to_scheduled_tasks_table.php │ │ ├── 2025_11_09_000002_improve_scheduled_task_executions_tracking.php │ │ ├── 2025_11_10_112500_add_restart_tracking_to_applications_table.php │ │ ├── 2025_11_12_130931_add_traefik_version_tracking_to_servers_table.php │ │ ├── 2025_11_12_131252_add_traefik_outdated_to_email_notification_settings.php │ │ ├── 2025_11_12_133400_add_traefik_outdated_thread_id_to_telegram_notification_settings.php │ │ ├── 2025_11_14_114632_add_traefik_outdated_info_to_servers_table.php │ │ ├── 2025_11_16_000001_create_webhook_notification_settings_table.php │ │ ├── 2025_11_16_000002_create_cloud_init_scripts_table.php │ │ ├── 2025_11_17_092707_add_traefik_outdated_to_notification_settings.php │ │ ├── 2025_11_17_145255_add_comment_to_environment_variables_table.php │ │ ├── 2025_11_18_083747_cleanup_dockerfile_data_for_non_dockerfile_buildpacks.php │ │ ├── 2025_11_26_124200_add_build_cache_settings_to_application_settings.php │ │ ├── 2025_11_28_000001_migrate_clickhouse_to_official_image.php │ │ ├── 2025_12_04_134435_add_deployment_queue_limit_to_server_settings.php │ │ ├── 2025_12_05_000000_add_docker_images_to_keep_to_application_settings.php │ │ ├── 2025_12_05_100000_add_disable_application_image_retention_to_server_settings.php │ │ ├── 2025_12_08_135600_add_performance_indexes.php │ │ ├── 2025_12_10_135600_add_uuid_to_cloud_provider_tokens.php │ │ ├── 2025_12_15_143052_trim_s3_storage_credentials.php │ │ ├── 2025_12_17_000001_add_is_wire_navigate_enabled_to_instance_settings_table.php │ │ ├── 2025_12_17_000002_add_restart_tracking_to_standalone_databases.php │ │ ├── 2025_12_25_072315_add_cmd_healthcheck_to_applications_table.php │ │ ├── 2026_02_26_163035_add_stripe_refunded_at_to_subscriptions_table.php │ │ ├── 2026_02_27_000000_add_public_port_timeout_to_databases.php │ │ └── 2026_03_11_000000_add_server_metadata_to_servers_table.php │ ├── schema/ │ │ └── testing-schema.sql │ └── seeders/ │ ├── ApplicationSeeder.php │ ├── ApplicationSettingsSeeder.php │ ├── CaSslCertSeeder.php │ ├── DatabaseSeeder.php │ ├── DisableTwoStepConfirmationSeeder.php │ ├── GithubAppSeeder.php │ ├── GitlabAppSeeder.php │ ├── InstanceSettingsSeeder.php │ ├── LocalPersistentVolumeSeeder.php │ ├── OauthSettingSeeder.php │ ├── PersonalAccessTokenSeeder.php │ ├── PopulateSshKeysDirectorySeeder.php │ ├── PrivateKeySeeder.php │ ├── ProductionSeeder.php │ ├── ProjectSeeder.php │ ├── RootUserSeeder.php │ ├── S3StorageSeeder.php │ ├── SentinelSeeder.php │ ├── ServerSeeder.php │ ├── ServerSettingSeeder.php │ ├── SharedEnvironmentVariableSeeder.php │ ├── StandaloneDockerSeeder.php │ ├── StandalonePostgresqlSeeder.php │ ├── StandaloneRedisSeeder.php │ ├── TeamSeeder.php │ └── UserSeeder.php ├── docker/ │ ├── coolify-helper/ │ │ └── Dockerfile │ ├── coolify-realtime/ │ │ ├── Dockerfile │ │ ├── package.json │ │ ├── soketi-entrypoint.sh │ │ ├── terminal-server.js │ │ ├── terminal-utils.js │ │ └── terminal-utils.test.js │ ├── development/ │ │ ├── Dockerfile │ │ └── etc/ │ │ ├── nginx/ │ │ │ ├── conf.d/ │ │ │ │ └── custom.conf │ │ │ └── site-opts.d/ │ │ │ └── http.conf │ │ ├── php/ │ │ │ └── conf.d/ │ │ │ └── zzz-custom-php.ini │ │ └── s6-overlay/ │ │ └── s6-rc.d/ │ │ ├── horizon/ │ │ │ ├── dependencies.d/ │ │ │ │ └── init-setup │ │ │ ├── run │ │ │ └── type │ │ ├── init-setup/ │ │ │ ├── type │ │ │ └── up │ │ ├── scheduler-worker/ │ │ │ ├── dependencies.d/ │ │ │ │ └── init-setup │ │ │ ├── run │ │ │ └── type │ │ └── user/ │ │ └── contents.d/ │ │ ├── horizon │ │ ├── init-setup │ │ └── scheduler-worker │ ├── production/ │ │ ├── Dockerfile │ │ ├── entrypoint.d/ │ │ │ └── 99-debug-mode.sh │ │ └── etc/ │ │ ├── nginx/ │ │ │ ├── conf.d/ │ │ │ │ └── custom.conf │ │ │ └── site-opts.d/ │ │ │ └── http.conf │ │ ├── php/ │ │ │ └── conf.d/ │ │ │ └── zzz-custom-php.ini │ │ └── s6-overlay/ │ │ └── s6-rc.d/ │ │ ├── db-migration/ │ │ │ ├── type │ │ │ └── up │ │ ├── horizon/ │ │ │ ├── dependencies.d/ │ │ │ │ └── init-script │ │ │ ├── run │ │ │ └── type │ │ ├── init-script/ │ │ │ ├── dependencies.d/ │ │ │ │ └── init-seeder │ │ │ ├── type │ │ │ └── up │ │ ├── init-seeder/ │ │ │ ├── dependencies.d/ │ │ │ │ └── db-migration │ │ │ ├── type │ │ │ └── up │ │ ├── scheduler-worker/ │ │ │ ├── dependencies.d/ │ │ │ │ └── init-script │ │ │ ├── run │ │ │ └── type │ │ └── user/ │ │ └── contents.d/ │ │ ├── db-migration │ │ ├── horizon │ │ ├── init-script │ │ ├── init-seeder │ │ └── scheduler-worker │ └── testing-host/ │ └── Dockerfile ├── docker-compose-maxio.dev.yml ├── docker-compose.dev.yml ├── docker-compose.prod.yml ├── docker-compose.windows.yml ├── docker-compose.yml ├── jean.json ├── lang/ │ ├── ar.json │ ├── az.json │ ├── cs.json │ ├── de.json │ ├── en/ │ │ └── passwords.php │ ├── en.json │ ├── es.json │ ├── fa.json │ ├── fr.json │ ├── id.json │ ├── it.json │ ├── ja.json │ ├── no.json │ ├── pl.json │ ├── pt-br.json │ ├── pt.json │ ├── ro.json │ ├── tr.json │ ├── vi.json │ ├── zh-cn.json │ └── zh-tw.json ├── openapi.json ├── openapi.yaml ├── opencode.json ├── other/ │ └── nightly/ │ ├── docker-compose.prod.yml │ ├── docker-compose.windows.yml │ ├── docker-compose.yml │ ├── install.sh │ ├── upgrade.sh │ └── versions.json ├── package.json ├── phpunit.dusk.xml ├── phpunit.xml ├── pint.json ├── postcss.config.cjs ├── public/ │ ├── index.php │ ├── js/ │ │ ├── apexcharts.js │ │ ├── dropzone.js │ │ ├── echo.js │ │ ├── monaco-editor-0.52.2/ │ │ │ └── min/ │ │ │ └── vs/ │ │ │ ├── base/ │ │ │ │ └── worker/ │ │ │ │ └── workerMain.js │ │ │ ├── basic-languages/ │ │ │ │ ├── abap/ │ │ │ │ │ └── abap.js │ │ │ │ ├── apex/ │ │ │ │ │ └── apex.js │ │ │ │ ├── azcli/ │ │ │ │ │ └── azcli.js │ │ │ │ ├── bat/ │ │ │ │ │ └── bat.js │ │ │ │ ├── bicep/ │ │ │ │ │ └── bicep.js │ │ │ │ ├── cameligo/ │ │ │ │ │ └── cameligo.js │ │ │ │ ├── clojure/ │ │ │ │ │ └── clojure.js │ │ │ │ ├── coffee/ │ │ │ │ │ └── coffee.js │ │ │ │ ├── cpp/ │ │ │ │ │ └── cpp.js │ │ │ │ ├── csharp/ │ │ │ │ │ └── csharp.js │ │ │ │ ├── csp/ │ │ │ │ │ └── csp.js │ │ │ │ ├── css/ │ │ │ │ │ └── css.js │ │ │ │ ├── cypher/ │ │ │ │ │ └── cypher.js │ │ │ │ ├── dart/ │ │ │ │ │ └── dart.js │ │ │ │ ├── dockerfile/ │ │ │ │ │ └── dockerfile.js │ │ │ │ ├── ecl/ │ │ │ │ │ └── ecl.js │ │ │ │ ├── elixir/ │ │ │ │ │ └── elixir.js │ │ │ │ ├── flow9/ │ │ │ │ │ └── flow9.js │ │ │ │ ├── freemarker2/ │ │ │ │ │ └── freemarker2.js │ │ │ │ ├── fsharp/ │ │ │ │ │ └── fsharp.js │ │ │ │ ├── go/ │ │ │ │ │ └── go.js │ │ │ │ ├── graphql/ │ │ │ │ │ └── graphql.js │ │ │ │ ├── handlebars/ │ │ │ │ │ └── handlebars.js │ │ │ │ ├── hcl/ │ │ │ │ │ └── hcl.js │ │ │ │ ├── html/ │ │ │ │ │ └── html.js │ │ │ │ ├── ini/ │ │ │ │ │ └── ini.js │ │ │ │ ├── java/ │ │ │ │ │ └── java.js │ │ │ │ ├── javascript/ │ │ │ │ │ └── javascript.js │ │ │ │ ├── julia/ │ │ │ │ │ └── julia.js │ │ │ │ ├── kotlin/ │ │ │ │ │ └── kotlin.js │ │ │ │ ├── less/ │ │ │ │ │ └── less.js │ │ │ │ ├── lexon/ │ │ │ │ │ └── lexon.js │ │ │ │ ├── liquid/ │ │ │ │ │ └── liquid.js │ │ │ │ ├── lua/ │ │ │ │ │ └── lua.js │ │ │ │ ├── m3/ │ │ │ │ │ └── m3.js │ │ │ │ ├── markdown/ │ │ │ │ │ └── markdown.js │ │ │ │ ├── mdx/ │ │ │ │ │ └── mdx.js │ │ │ │ ├── mips/ │ │ │ │ │ └── mips.js │ │ │ │ ├── msdax/ │ │ │ │ │ └── msdax.js │ │ │ │ ├── mysql/ │ │ │ │ │ └── mysql.js │ │ │ │ ├── objective-c/ │ │ │ │ │ └── objective-c.js │ │ │ │ ├── pascal/ │ │ │ │ │ └── pascal.js │ │ │ │ ├── pascaligo/ │ │ │ │ │ └── pascaligo.js │ │ │ │ ├── perl/ │ │ │ │ │ └── perl.js │ │ │ │ ├── pgsql/ │ │ │ │ │ └── pgsql.js │ │ │ │ ├── php/ │ │ │ │ │ └── php.js │ │ │ │ ├── pla/ │ │ │ │ │ └── pla.js │ │ │ │ ├── postiats/ │ │ │ │ │ └── postiats.js │ │ │ │ ├── powerquery/ │ │ │ │ │ └── powerquery.js │ │ │ │ ├── powershell/ │ │ │ │ │ └── powershell.js │ │ │ │ ├── protobuf/ │ │ │ │ │ └── protobuf.js │ │ │ │ ├── pug/ │ │ │ │ │ └── pug.js │ │ │ │ ├── python/ │ │ │ │ │ └── python.js │ │ │ │ ├── qsharp/ │ │ │ │ │ └── qsharp.js │ │ │ │ ├── r/ │ │ │ │ │ └── r.js │ │ │ │ ├── razor/ │ │ │ │ │ └── razor.js │ │ │ │ ├── redis/ │ │ │ │ │ └── redis.js │ │ │ │ ├── redshift/ │ │ │ │ │ └── redshift.js │ │ │ │ ├── restructuredtext/ │ │ │ │ │ └── restructuredtext.js │ │ │ │ ├── ruby/ │ │ │ │ │ └── ruby.js │ │ │ │ ├── rust/ │ │ │ │ │ └── rust.js │ │ │ │ ├── sb/ │ │ │ │ │ └── sb.js │ │ │ │ ├── scala/ │ │ │ │ │ └── scala.js │ │ │ │ ├── scheme/ │ │ │ │ │ └── scheme.js │ │ │ │ ├── scss/ │ │ │ │ │ └── scss.js │ │ │ │ ├── shell/ │ │ │ │ │ └── shell.js │ │ │ │ ├── solidity/ │ │ │ │ │ └── solidity.js │ │ │ │ ├── sophia/ │ │ │ │ │ └── sophia.js │ │ │ │ ├── sparql/ │ │ │ │ │ └── sparql.js │ │ │ │ ├── sql/ │ │ │ │ │ └── sql.js │ │ │ │ ├── st/ │ │ │ │ │ └── st.js │ │ │ │ ├── swift/ │ │ │ │ │ └── swift.js │ │ │ │ ├── systemverilog/ │ │ │ │ │ └── systemverilog.js │ │ │ │ ├── tcl/ │ │ │ │ │ └── tcl.js │ │ │ │ ├── twig/ │ │ │ │ │ └── twig.js │ │ │ │ ├── typescript/ │ │ │ │ │ └── typescript.js │ │ │ │ ├── typespec/ │ │ │ │ │ └── typespec.js │ │ │ │ ├── vb/ │ │ │ │ │ └── vb.js │ │ │ │ ├── wgsl/ │ │ │ │ │ └── wgsl.js │ │ │ │ ├── xml/ │ │ │ │ │ └── xml.js │ │ │ │ └── yaml/ │ │ │ │ └── yaml.js │ │ │ ├── editor/ │ │ │ │ ├── editor.main.css │ │ │ │ └── editor.main.js │ │ │ ├── language/ │ │ │ │ ├── css/ │ │ │ │ │ ├── cssMode.js │ │ │ │ │ └── cssWorker.js │ │ │ │ ├── html/ │ │ │ │ │ ├── htmlMode.js │ │ │ │ │ └── htmlWorker.js │ │ │ │ ├── json/ │ │ │ │ │ ├── jsonMode.js │ │ │ │ │ └── jsonWorker.js │ │ │ │ └── typescript/ │ │ │ │ ├── tsMode.js │ │ │ │ └── tsWorker.js │ │ │ ├── loader.js │ │ │ ├── nls.messages.de.js │ │ │ ├── nls.messages.es.js │ │ │ ├── nls.messages.fr.js │ │ │ ├── nls.messages.it.js │ │ │ ├── nls.messages.ja.js │ │ │ ├── nls.messages.ko.js │ │ │ ├── nls.messages.ru.js │ │ │ ├── nls.messages.zh-cn.js │ │ │ └── nls.messages.zh-tw.js │ │ └── pusher.js │ ├── robots.txt │ └── vendor/ │ ├── horizon/ │ │ ├── app-dark.css │ │ ├── app.css │ │ ├── app.js │ │ └── mix-manifest.json │ └── telescope/ │ ├── app-dark.css │ ├── app.css │ ├── app.js │ └── mix-manifest.json ├── rector.php ├── resources/ │ ├── css/ │ │ ├── app.css │ │ ├── fonts.css │ │ └── utilities.css │ ├── js/ │ │ ├── app.js │ │ └── terminal.js │ └── views/ │ ├── auth/ │ │ ├── confirm-password.blade.php │ │ ├── forgot-password.blade.php │ │ ├── login.blade.php │ │ ├── register.blade.php │ │ ├── reset-password.blade.php │ │ ├── two-factor-challenge.blade.php │ │ └── verify-email.blade.php │ ├── components/ │ │ ├── applications/ │ │ │ ├── advanced.blade.php │ │ │ └── links.blade.php │ │ ├── banner.blade.php │ │ ├── boarding-progress.blade.php │ │ ├── boarding-step.blade.php │ │ ├── callout.blade.php │ │ ├── chevron-down.blade.php │ │ ├── confirm-modal.blade.php │ │ ├── domain-conflict-modal.blade.php │ │ ├── dropdown.blade.php │ │ ├── emails/ │ │ │ ├── footer.blade.php │ │ │ ├── header.blade.php │ │ │ └── layout.blade.php │ │ ├── environment-variable-warning.blade.php │ │ ├── external-link.blade.php │ │ ├── forms/ │ │ │ ├── button.blade.php │ │ │ ├── checkbox.blade.php │ │ │ ├── copy-button.blade.php │ │ │ ├── datalist.blade.php │ │ │ ├── env-var-input.blade.php │ │ │ ├── input.blade.php │ │ │ ├── monaco-editor.blade.php │ │ │ ├── select.blade.php │ │ │ └── textarea.blade.php │ │ ├── git-icon.blade.php │ │ ├── helper.blade.php │ │ ├── highlighted.blade.php │ │ ├── internal-link.blade.php │ │ ├── layout-simple.blade.php │ │ ├── layout.blade.php │ │ ├── limit-reached.blade.php │ │ ├── loading-on-button.blade.php │ │ ├── loading.blade.php │ │ ├── modal-confirmation.blade.php │ │ ├── modal-input.blade.php │ │ ├── modal.blade.php │ │ ├── navbar.blade.php │ │ ├── notification/ │ │ │ └── navbar.blade.php │ │ ├── page-loading.blade.php │ │ ├── popup-small.blade.php │ │ ├── popup.blade.php │ │ ├── pricing-plans.blade.php │ │ ├── resource-view.blade.php │ │ ├── resources/ │ │ │ └── breadcrumbs.blade.php │ │ ├── security/ │ │ │ └── navbar.blade.php │ │ ├── server/ │ │ │ ├── sidebar-proxy.blade.php │ │ │ ├── sidebar-security.blade.php │ │ │ └── sidebar.blade.php │ │ ├── service-database/ │ │ │ └── sidebar.blade.php │ │ ├── services/ │ │ │ ├── advanced.blade.php │ │ │ └── links.blade.php │ │ ├── settings/ │ │ │ ├── navbar.blade.php │ │ │ └── sidebar.blade.php │ │ ├── slide-over.blade.php │ │ ├── status/ │ │ │ ├── degraded.blade.php │ │ │ ├── index.blade.php │ │ │ ├── restarting.blade.php │ │ │ ├── running.blade.php │ │ │ ├── services.blade.php │ │ │ └── stopped.blade.php │ │ ├── team/ │ │ │ └── navbar.blade.php │ │ ├── toast.blade.php │ │ ├── upgrade-progress.blade.php │ │ ├── use-magic-bar.blade.php │ │ └── version.blade.php │ ├── emails/ │ │ ├── application-deployment-failed.blade.php │ │ ├── application-deployment-success.blade.php │ │ ├── application-status-changes.blade.php │ │ ├── backup-failed.blade.php │ │ ├── backup-success-with-s3-warning.blade.php │ │ ├── backup-success.blade.php │ │ ├── before-trial-conversion.blade.php │ │ ├── container-restarted.blade.php │ │ ├── container-stopped.blade.php │ │ ├── daily-backup.blade.php │ │ ├── docker-cleanup-failed.blade.php │ │ ├── docker-cleanup-success.blade.php │ │ ├── email-change-verification.blade.php │ │ ├── email-verification.blade.php │ │ ├── help.blade.php │ │ ├── hetzner-deletion-failed.blade.php │ │ ├── high-disk-usage.blade.php │ │ ├── invitation-link.blade.php │ │ ├── reset-password.blade.php │ │ ├── s3-connection-error.blade.php │ │ ├── scheduled-task-failed.blade.php │ │ ├── scheduled-task-success.blade.php │ │ ├── server-force-disabled.blade.php │ │ ├── server-force-enabled.blade.php │ │ ├── server-lost-connection.blade.php │ │ ├── server-patches-error.blade.php │ │ ├── server-patches.blade.php │ │ ├── server-revived.blade.php │ │ ├── ssl-certificate-renewed.blade.php │ │ ├── subscription-invoice-failed.blade.php │ │ ├── test.blade.php │ │ ├── traefik-version-outdated.blade.php │ │ ├── trial-ended.blade.php │ │ ├── trial-ends-soon.blade.php │ │ └── updates.blade.php │ ├── errors/ │ │ ├── 400.blade.php │ │ ├── 401.blade.php │ │ ├── 402.blade.php │ │ ├── 403.blade.php │ │ ├── 404.blade.php │ │ ├── 419.blade.php │ │ ├── 429.blade.php │ │ ├── 500.blade.php │ │ └── 503.blade.php │ ├── layouts/ │ │ ├── app.blade.php │ │ ├── base.blade.php │ │ ├── boarding.blade.php │ │ └── simple.blade.php │ ├── livewire/ │ │ ├── activity-monitor.blade.php │ │ ├── admin/ │ │ │ └── index.blade.php │ │ ├── boarding/ │ │ │ └── index.blade.php │ │ ├── dashboard.blade.php │ │ ├── deployments-indicator.blade.php │ │ ├── destination/ │ │ │ ├── index.blade.php │ │ │ ├── new/ │ │ │ │ └── docker.blade.php │ │ │ └── show.blade.php │ │ ├── force-password-reset.blade.php │ │ ├── global-search.blade.php │ │ ├── help.blade.php │ │ ├── layout-popups.blade.php │ │ ├── navbar-delete-team.blade.php │ │ ├── notifications/ │ │ │ ├── discord.blade.php │ │ │ ├── email.blade.php │ │ │ ├── pushover.blade.php │ │ │ ├── slack.blade.php │ │ │ ├── telegram.blade.php │ │ │ └── webhook.blade.php │ │ ├── profile/ │ │ │ └── index.blade.php │ │ ├── project/ │ │ │ ├── add-empty.blade.php │ │ │ ├── application/ │ │ │ │ ├── advanced.blade.php │ │ │ │ ├── configuration.blade.php │ │ │ │ ├── deployment/ │ │ │ │ │ ├── index.blade.php │ │ │ │ │ └── show.blade.php │ │ │ │ ├── deployment-navbar.blade.php │ │ │ │ ├── destination.blade.php │ │ │ │ ├── general.blade.php │ │ │ │ ├── heading.blade.php │ │ │ │ ├── preview/ │ │ │ │ │ └── form.blade.php │ │ │ │ ├── previews-compose.blade.php │ │ │ │ ├── previews.blade.php │ │ │ │ ├── rollback.blade.php │ │ │ │ ├── source.blade.php │ │ │ │ └── swarm.blade.php │ │ │ ├── clone-me.blade.php │ │ │ ├── database/ │ │ │ │ ├── backup/ │ │ │ │ │ ├── execution.blade.php │ │ │ │ │ └── index.blade.php │ │ │ │ ├── backup-edit.blade.php │ │ │ │ ├── backup-executions.blade.php │ │ │ │ ├── backup-now.blade.php │ │ │ │ ├── clickhouse/ │ │ │ │ │ └── general.blade.php │ │ │ │ ├── configuration.blade.php │ │ │ │ ├── create-scheduled-backup.blade.php │ │ │ │ ├── dragonfly/ │ │ │ │ │ └── general.blade.php │ │ │ │ ├── heading.blade.php │ │ │ │ ├── import.blade.php │ │ │ │ ├── init-script.blade.php │ │ │ │ ├── keydb/ │ │ │ │ │ └── general.blade.php │ │ │ │ ├── mariadb/ │ │ │ │ │ └── general.blade.php │ │ │ │ ├── mongodb/ │ │ │ │ │ └── general.blade.php │ │ │ │ ├── mysql/ │ │ │ │ │ └── general.blade.php │ │ │ │ ├── postgresql/ │ │ │ │ │ └── general.blade.php │ │ │ │ ├── redis/ │ │ │ │ │ └── general.blade.php │ │ │ │ └── scheduled-backups.blade.php │ │ │ ├── delete-environment.blade.php │ │ │ ├── delete-project.blade.php │ │ │ ├── edit.blade.php │ │ │ ├── environment-edit.blade.php │ │ │ ├── index.blade.php │ │ │ ├── new/ │ │ │ │ ├── docker-compose.blade.php │ │ │ │ ├── docker-image.blade.php │ │ │ │ ├── empty-project.blade.php │ │ │ │ ├── github-private-repository-deploy-key.blade.php │ │ │ │ ├── github-private-repository.blade.php │ │ │ │ ├── public-git-repository.blade.php │ │ │ │ ├── select.blade.php │ │ │ │ └── simple-dockerfile.blade.php │ │ │ ├── resource/ │ │ │ │ ├── create.blade.php │ │ │ │ └── index.blade.php │ │ │ ├── service/ │ │ │ │ ├── configuration.blade.php │ │ │ │ ├── database-backups.blade.php │ │ │ │ ├── edit-compose.blade.php │ │ │ │ ├── edit-domain.blade.php │ │ │ │ ├── file-storage.blade.php │ │ │ │ ├── heading.blade.php │ │ │ │ ├── index.blade.php │ │ │ │ ├── stack-form.blade.php │ │ │ │ └── storage.blade.php │ │ │ ├── shared/ │ │ │ │ ├── configuration-checker.blade.php │ │ │ │ ├── danger.blade.php │ │ │ │ ├── destination.blade.php │ │ │ │ ├── environment-variable/ │ │ │ │ │ ├── add.blade.php │ │ │ │ │ ├── all.blade.php │ │ │ │ │ ├── show-hardcoded.blade.php │ │ │ │ │ └── show.blade.php │ │ │ │ ├── execute-container-command.blade.php │ │ │ │ ├── get-logs.blade.php │ │ │ │ ├── health-checks.blade.php │ │ │ │ ├── logs.blade.php │ │ │ │ ├── metrics.blade.php │ │ │ │ ├── resource-limits.blade.php │ │ │ │ ├── resource-operations.blade.php │ │ │ │ ├── scheduled-task/ │ │ │ │ │ ├── add.blade.php │ │ │ │ │ ├── all.blade.php │ │ │ │ │ ├── executions.blade.php │ │ │ │ │ └── show.blade.php │ │ │ │ ├── storages/ │ │ │ │ │ ├── all.blade.php │ │ │ │ │ └── show.blade.php │ │ │ │ ├── tags.blade.php │ │ │ │ ├── terminal.blade.php │ │ │ │ ├── upload-config.blade.php │ │ │ │ └── webhooks.blade.php │ │ │ └── show.blade.php │ │ ├── security/ │ │ │ ├── api-tokens.blade.php │ │ │ ├── cloud-init-script-form.blade.php │ │ │ ├── cloud-init-scripts.blade.php │ │ │ ├── cloud-provider-token-form.blade.php │ │ │ ├── cloud-provider-tokens.blade.php │ │ │ ├── cloud-tokens.blade.php │ │ │ └── private-key/ │ │ │ ├── create.blade.php │ │ │ ├── index.blade.php │ │ │ └── show.blade.php │ │ ├── server/ │ │ │ ├── advanced.blade.php │ │ │ ├── ca-certificate/ │ │ │ │ └── show.blade.php │ │ │ ├── charts.blade.php │ │ │ ├── cloud-provider-token/ │ │ │ │ └── show.blade.php │ │ │ ├── cloudflare-tunnel.blade.php │ │ │ ├── create.blade.php │ │ │ ├── delete.blade.php │ │ │ ├── destinations.blade.php │ │ │ ├── docker-cleanup-executions.blade.php │ │ │ ├── docker-cleanup.blade.php │ │ │ ├── index.blade.php │ │ │ ├── log-drains.blade.php │ │ │ ├── navbar.blade.php │ │ │ ├── new/ │ │ │ │ ├── by-hetzner.blade.php │ │ │ │ └── by-ip.blade.php │ │ │ ├── private-key/ │ │ │ │ └── show.blade.php │ │ │ ├── proxy/ │ │ │ │ ├── dynamic-configuration-navbar.blade.php │ │ │ │ ├── dynamic-configurations.blade.php │ │ │ │ ├── logs.blade.php │ │ │ │ ├── new-dynamic-configuration.blade.php │ │ │ │ └── show.blade.php │ │ │ ├── proxy.blade.php │ │ │ ├── resources.blade.php │ │ │ ├── security/ │ │ │ │ ├── patches.blade.php │ │ │ │ └── terminal-access.blade.php │ │ │ ├── sentinel.blade.php │ │ │ ├── show.blade.php │ │ │ ├── swarm.blade.php │ │ │ └── validate-and-install.blade.php │ │ ├── settings/ │ │ │ ├── advanced.blade.php │ │ │ ├── index.blade.php │ │ │ ├── scheduled-jobs.blade.php │ │ │ └── updates.blade.php │ │ ├── settings-backup.blade.php │ │ ├── settings-dropdown.blade.php │ │ ├── settings-email.blade.php │ │ ├── settings-oauth.blade.php │ │ ├── shared-variables/ │ │ │ ├── environment/ │ │ │ │ ├── index.blade.php │ │ │ │ └── show.blade.php │ │ │ ├── index.blade.php │ │ │ ├── project/ │ │ │ │ ├── index.blade.php │ │ │ │ └── show.blade.php │ │ │ └── team/ │ │ │ └── index.blade.php │ │ ├── source/ │ │ │ └── github/ │ │ │ ├── change.blade.php │ │ │ └── create.blade.php │ │ ├── storage/ │ │ │ ├── create.blade.php │ │ │ ├── form.blade.php │ │ │ ├── index.blade.php │ │ │ └── show.blade.php │ │ ├── subscription/ │ │ │ ├── actions.blade.php │ │ │ ├── index.blade.php │ │ │ ├── pricing-plans.blade.php │ │ │ └── show.blade.php │ │ ├── switch-team.blade.php │ │ ├── tags/ │ │ │ ├── deployments.blade.php │ │ │ └── show.blade.php │ │ ├── team/ │ │ │ ├── admin-view.blade.php │ │ │ ├── create.blade.php │ │ │ ├── index.blade.php │ │ │ ├── invitations.blade.php │ │ │ ├── invite-link.blade.php │ │ │ ├── member/ │ │ │ │ └── index.blade.php │ │ │ └── member.blade.php │ │ ├── terminal/ │ │ │ └── index.blade.php │ │ ├── upgrade.blade.php │ │ └── verify-email.blade.php │ ├── server/ │ │ └── create.blade.php │ ├── source/ │ │ ├── all.blade.php │ │ └── github/ │ │ └── show.blade.php │ └── vendor/ │ └── mail/ │ ├── html/ │ │ ├── button.blade.php │ │ ├── footer.blade.php │ │ ├── header.blade.php │ │ ├── layout.blade.php │ │ ├── message.blade.php │ │ ├── panel.blade.php │ │ ├── subcopy.blade.php │ │ ├── table.blade.php │ │ └── themes/ │ │ └── default.css │ └── text/ │ ├── button.blade.php │ ├── footer.blade.php │ ├── header.blade.php │ ├── layout.blade.php │ ├── message.blade.php │ ├── panel.blade.php │ ├── subcopy.blade.php │ └── table.blade.php ├── routes/ │ ├── api.php │ ├── channels.php │ ├── console.php │ ├── web.php │ └── webhooks.php ├── scripts/ │ ├── cloud_upgrade.sh │ ├── conductor-setup.sh │ ├── install.sh │ ├── run │ ├── sync_volume.sh │ └── upgrade.sh ├── storage/ │ ├── app/ │ │ └── .gitignore │ ├── debugbar/ │ │ └── .gitignore │ ├── framework/ │ │ ├── cache/ │ │ │ └── .gitignore │ │ ├── sessions/ │ │ │ └── .gitignore │ │ ├── testing/ │ │ │ └── .gitignore │ │ └── views/ │ │ └── .gitignore │ ├── logs/ │ │ └── .gitignore │ └── pail/ │ └── .gitignore ├── templates/ │ ├── compose/ │ │ ├── activepieces.yaml │ │ ├── actualbudget.yaml │ │ ├── affine.yaml │ │ ├── alexandrie.yaml │ │ ├── anythingllm.yaml │ │ ├── appflowy.yaml │ │ ├── apprise-api.yaml │ │ ├── appsmith.yaml │ │ ├── appwrite.yaml │ │ ├── argilla.yaml │ │ ├── audiobookshelf.yaml │ │ ├── authentik.yaml │ │ ├── autobase.yaml │ │ ├── azimutt.yaml │ │ ├── babybuddy.yaml │ │ ├── bento-pdf.yaml │ │ ├── beszel-agent.yaml │ │ ├── beszel.yaml │ │ ├── bitcoin-core.yaml │ │ ├── bluesky-pds.yaml │ │ ├── booklore.yaml │ │ ├── bookstack.yaml │ │ ├── browserless.yaml │ │ ├── budge.yaml │ │ ├── budibase.yaml │ │ ├── bugsink.yaml │ │ ├── calcom.yaml │ │ ├── calibre-web-automated-book-downloader.yaml │ │ ├── calibre-web.yaml │ │ ├── cap.yaml │ │ ├── castopod.yaml │ │ ├── changedetection.yaml │ │ ├── chaskiq.yaml │ │ ├── chatwoot.yaml │ │ ├── checkmate.yaml │ │ ├── chibisafe.yaml │ │ ├── chroma.yaml │ │ ├── classicpress-with-mariadb.yaml │ │ ├── classicpress-with-mysql.yaml │ │ ├── classicpress-without-database.yaml │ │ ├── cloudbeaver.yaml │ │ ├── cloudflared.yaml │ │ ├── cloudreve.yaml │ │ ├── cockpit.yaml │ │ ├── code-server.yaml │ │ ├── coder.yaml │ │ ├── codimd.yaml │ │ ├── convertx.yml │ │ ├── convex.yaml │ │ ├── cryptgeon.yaml │ │ ├── cyberchef.yaml │ │ ├── dashy.yaml │ │ ├── databasus.yaml │ │ ├── denoKV.yaml │ │ ├── dify.yaml │ │ ├── directus-with-postgresql.yaml │ │ ├── directus.yaml │ │ ├── diun.yaml │ │ ├── docker-registry.yaml │ │ ├── docmost.yaml │ │ ├── documenso.yaml │ │ ├── docuseal-with-postgres.yaml │ │ ├── docuseal.yaml │ │ ├── dokuwiki.yaml │ │ ├── dolibarr.yaml │ │ ├── dozzle-with-auth.yaml │ │ ├── dozzle.yaml │ │ ├── drizzle-gateway.yaml │ │ ├── drupal-with-postgresql.yaml │ │ ├── duplicati.yaml │ │ ├── easyappointments.yaml │ │ ├── edgedb.yaml │ │ ├── elasticsearch-with-kibana.yaml │ │ ├── elasticsearch.yaml │ │ ├── emby.yaml │ │ ├── embystat.yaml │ │ ├── ente-photos-with-s3.yaml │ │ ├── ente-photos.yaml │ │ ├── esphome.yaml │ │ ├── evolution-api.yaml │ │ ├── excalidraw.yaml │ │ ├── faraday.yaml │ │ ├── fider.yaml │ │ ├── filebrowser.yaml │ │ ├── fileflows.yaml │ │ ├── firefly.yaml │ │ ├── firefox.yaml │ │ ├── fizzy.yaml │ │ ├── flipt.yaml │ │ ├── flowise-with-databases.yaml │ │ ├── flowise.yaml │ │ ├── forgejo-with-mariadb.yaml │ │ ├── forgejo-with-mysql.yaml │ │ ├── forgejo-with-postgresql.yaml │ │ ├── forgejo-with-runner-with-mariadb.yaml │ │ ├── forgejo-with-runner-with-mysql.yaml │ │ ├── forgejo-with-runner-with-postgresql.yaml │ │ ├── forgejo-with-runner.yaml │ │ ├── forgejo.yaml │ │ ├── formbricks.yaml │ │ ├── foundryvtt.yaml │ │ ├── freescout.yaml │ │ ├── freshrss-with-mariadb.yaml │ │ ├── freshrss-with-mysql.yaml │ │ ├── freshrss-with-postgresql.yaml │ │ ├── freshrss.yaml │ │ ├── garage.yaml │ │ ├── getoutline.yaml │ │ ├── ghost.yaml │ │ ├── gitea-with-mariadb.yaml │ │ ├── gitea-with-mysql.yaml │ │ ├── gitea-with-postgresql.yaml │ │ ├── gitea.yaml │ │ ├── github-runner.yaml │ │ ├── gitlab.yaml │ │ ├── glance.yaml │ │ ├── glances.yaml │ │ ├── glitchtip.yaml │ │ ├── glpi.yaml │ │ ├── goatcounter.yaml │ │ ├── gotenberg.yaml │ │ ├── gotify.yaml │ │ ├── gowa.yaml │ │ ├── grafana-with-postgresql.yaml │ │ ├── grafana.yaml │ │ ├── gramps-web.yaml │ │ ├── grist.yaml │ │ ├── grocy.yaml │ │ ├── hatchet.yaml │ │ ├── heimdall.yaml │ │ ├── heyform.yaml │ │ ├── homarr.yaml │ │ ├── home-assistant.yaml │ │ ├── homebox.yaml │ │ ├── homepage.yaml │ │ ├── hoppscotch.yaml │ │ ├── huly.yaml │ │ ├── immich.yaml │ │ ├── infisical.yaml │ │ ├── invoice-ninja.yaml │ │ ├── it-tools.yaml │ │ ├── jellyfin.yaml │ │ ├── jenkins.yaml │ │ ├── jitsi.yaml │ │ ├── joomla-with-mariadb.yaml │ │ ├── joplin.yaml │ │ ├── jupyter-notebook-python.yaml │ │ ├── karakeep.yaml │ │ ├── keycloak-with-postgres.yaml │ │ ├── keycloak.yaml │ │ ├── kimai.yaml │ │ ├── kuzzle.yaml │ │ ├── labelstudio.yaml │ │ ├── langflow.yaml │ │ ├── langfuse.yaml │ │ ├── leantime.yaml │ │ ├── librechat.yaml │ │ ├── libreoffice.yaml │ │ ├── libretranslate.yaml │ │ ├── limesurvey.yaml │ │ ├── linkding-plus.yaml │ │ ├── linkding.yaml │ │ ├── listmonk.yaml │ │ ├── litellm.yaml │ │ ├── litequeen.yaml │ │ ├── lobe-chat.yaml │ │ ├── logto.yaml │ │ ├── lowcoder.yaml │ │ ├── macos.yaml │ │ ├── mage-ai.yaml │ │ ├── mailpit.yaml │ │ ├── marimo.yml │ │ ├── martin.yaml │ │ ├── matrix-synapse-with-postgresql.yaml │ │ ├── matrix-synapse-with-sqlite.yaml │ │ ├── mattermost.yaml │ │ ├── mautic5.yaml │ │ ├── maybe.yaml │ │ ├── mealie.yaml │ │ ├── mediawiki.yaml │ │ ├── meilisearch.yaml │ │ ├── memos.yaml │ │ ├── metabase.yaml │ │ ├── metamcp.yaml │ │ ├── metube.yaml │ │ ├── mindsdb.yaml │ │ ├── minecraft.yaml │ │ ├── miniflux.yaml │ │ ├── minio-community-edition.yaml │ │ ├── minio.yaml │ │ ├── mixpost.yaml │ │ ├── moodle.yaml │ │ ├── mosquitto.yaml │ │ ├── n8n-with-postgres-and-worker.yaml │ │ ├── n8n-with-postgresql.yaml │ │ ├── n8n.yaml │ │ ├── navidrome.yaml │ │ ├── neon-ws-proxy.yaml │ │ ├── netbird-client.yaml │ │ ├── newapi.yaml │ │ ├── newt-pangolin.yaml │ │ ├── next-image-transformation.yaml │ │ ├── nextcloud-with-mariadb.yaml │ │ ├── nextcloud-with-mysql.yaml │ │ ├── nextcloud-with-postgres.yaml │ │ ├── nextcloud.yaml │ │ ├── nexus-arm.yaml │ │ ├── nexus.yaml │ │ ├── nitropage-with-postgresql.yaml │ │ ├── nitropage.yaml │ │ ├── nocobase.yaml │ │ ├── nocodb.yaml │ │ ├── nodebb.yaml │ │ ├── ntfy.yaml │ │ ├── observium.yaml │ │ ├── odoo.yaml │ │ ├── ollama-with-open-webui.yaml │ │ ├── once-campfire.yaml │ │ ├── onedev.yaml │ │ ├── onetimesecret.yaml │ │ ├── open-archiver.yaml │ │ ├── open-webui.yaml │ │ ├── openclaw.yaml │ │ ├── openpanel.yaml │ │ ├── opnform.yaml │ │ ├── orangehrm.yaml │ │ ├── organizr.yaml │ │ ├── osticket.yaml │ │ ├── overseerr.yaml │ │ ├── owncloud.yaml │ │ ├── pairdrop.yaml │ │ ├── palworld.yaml │ │ ├── paperless.yaml │ │ ├── passbolt.yaml │ │ ├── paymenter.yaml │ │ ├── penpot-with-s3.yaml │ │ ├── penpot.yaml │ │ ├── peppermint.yaml │ │ ├── pgadmin.yaml │ │ ├── pgbackweb.yaml │ │ ├── phpmyadmin.yaml │ │ ├── pi-hole.yaml │ │ ├── pingvinshare-with-clamav.yaml │ │ ├── pingvinshare.yaml │ │ ├── plane.yaml │ │ ├── plausible.yaml │ │ ├── plex.yaml │ │ ├── plunk.yaml │ │ ├── pocket-id-with-postgresql.yaml │ │ ├── pocket-id.yaml │ │ ├── pocketbase.yaml │ │ ├── portainer.yaml │ │ ├── posthog.yaml │ │ ├── postiz.yaml │ │ ├── prefect.yaml │ │ ├── privatebin.yaml │ │ ├── prowlarr.yaml │ │ ├── proxyscotch.yaml │ │ ├── pterodactyl-panel.yaml │ │ ├── pterodactyl-with-wings.yaml │ │ ├── pydio-cells.yml │ │ ├── qbittorrent.yaml │ │ ├── qdrant.yaml │ │ ├── rabbitmq.yaml │ │ ├── radarr.yaml │ │ ├── rallly.yaml │ │ ├── reactive-resume.yaml │ │ ├── readeck.yaml │ │ ├── redis-insight.yaml │ │ ├── redlib.yaml │ │ ├── redmine.yaml │ │ ├── rivet-engine.yaml │ │ ├── rocketchat.yaml │ │ ├── rustfs.yaml │ │ ├── rybbit.yaml │ │ ├── ryot.yaml │ │ ├── satisfactory.yaml │ │ ├── seafile.yaml │ │ ├── searxng.yaml │ │ ├── seaweedfs.yaml │ │ ├── sequin.yaml │ │ ├── sessy.yaml │ │ ├── sftpgo.yaml │ │ ├── shlink.yaml │ │ ├── signoz.yaml │ │ ├── silverbullet.yaml │ │ ├── siyuan.yaml │ │ ├── slash.yaml │ │ ├── snapdrop.yaml │ │ ├── soju.yaml │ │ ├── soketi-app-manager.yaml │ │ ├── soketi.yaml │ │ ├── sonarqube.yaml │ │ ├── sonarr.yaml │ │ ├── spacebot.yaml │ │ ├── sparkyfitness.yaml │ │ ├── statusnook.yaml │ │ ├── stirling-pdf.yaml │ │ ├── strapi.yaml │ │ ├── supabase.yaml │ │ ├── superset-with-postgresql.yaml │ │ ├── supertokens-with-mysql.yaml │ │ ├── supertokens-with-postgresql.yaml │ │ ├── sure.yaml │ │ ├── swetrix.yaml │ │ ├── syncthing.yaml │ │ ├── tailscale-client.yaml │ │ ├── teable.yaml │ │ ├── terraria-server.yaml │ │ ├── tolgee.yaml │ │ ├── traccar.yaml │ │ ├── trailbase.yaml │ │ ├── transmission.yaml │ │ ├── trigger.yaml │ │ ├── triliumnext.yaml │ │ ├── twenty.yaml │ │ ├── typesense.yaml │ │ ├── umami.yaml │ │ ├── unleash-with-postgresql.yaml │ │ ├── unleash-without-database.yaml │ │ ├── unstructured.yaml │ │ ├── uptime-kuma-with-mariadb.yaml │ │ ├── uptime-kuma-with-mysql.yaml │ │ ├── uptime-kuma.yaml │ │ ├── usesend.yaml │ │ ├── vaultwarden.yaml │ │ ├── vert.yaml │ │ ├── vikunja-with-postgresql.yaml │ │ ├── vikunja.yaml │ │ ├── vvveb-with-mariadb.yaml │ │ ├── vvveb-with-mysql.yaml │ │ ├── vvveb.yaml │ │ ├── wakapi.yaml │ │ ├── weaviate.yaml │ │ ├── web-check.yaml │ │ ├── weblate.yaml │ │ ├── whoogle.yaml │ │ ├── wikijs.yaml │ │ ├── windmill.yaml │ │ ├── windows.yaml │ │ ├── wings.yaml │ │ ├── wireguard-easy.yaml │ │ ├── wordpress-with-mariadb.yaml │ │ ├── wordpress-with-mysql.yaml │ │ ├── wordpress-without-database.yaml │ │ ├── yamtrack-with-postgresql.yaml │ │ ├── yamtrack.yaml │ │ ├── zep.yaml │ │ └── zipline.yaml │ ├── service-templates-latest.json │ ├── service-templates.json │ └── test-database-detection.yaml ├── tests/ │ ├── Browser/ │ │ ├── LoginTest.php │ │ ├── Project/ │ │ │ ├── ProjectAddNewTest.php │ │ │ ├── ProjectSearchTest.php │ │ │ └── ProjectTest.php │ │ ├── console/ │ │ │ └── .gitignore │ │ └── source/ │ │ └── .gitignore │ ├── CreatesApplication.php │ ├── DuskTestCase.php │ ├── Feature/ │ │ ├── ApiTokenPermissionTest.php │ │ ├── ApplicationBuildpackCleanupTest.php │ │ ├── ApplicationHealthCheckApiTest.php │ │ ├── ApplicationRollbackTest.php │ │ ├── ApplicationSourceLocalhostKeyTest.php │ │ ├── BuildpackSwitchCleanupTest.php │ │ ├── CaCertificateCommandInjectionTest.php │ │ ├── CheckTraefikVersionJobTest.php │ │ ├── CleanupRedisTest.php │ │ ├── CleanupUnreachableServersTest.php │ │ ├── CloudInitScriptTest.php │ │ ├── CloudProviderTokenApiTest.php │ │ ├── CmdHealthCheckValidationTest.php │ │ ├── CommandInjectionSecurityTest.php │ │ ├── ConvertArraysTest.php │ │ ├── ConvertContainerEnvsToArray.php │ │ ├── ConvertingGitUrlsTest.php │ │ ├── CoolifyTaskRetryTest.php │ │ ├── CrossTeamIdorLogsTest.php │ │ ├── DatabaseBackupCreationApiTest.php │ │ ├── DatabaseBackupJobTest.php │ │ ├── DeletesUserSessionsTest.php │ │ ├── DeploymentByUuidApiTest.php │ │ ├── DeploymentCancellationApiTest.php │ │ ├── DockerCustomCommandsTest.php │ │ ├── DomainsByServerApiTest.php │ │ ├── EnvironmentVariableCommentTest.php │ │ ├── EnvironmentVariableMassAssignmentTest.php │ │ ├── EnvironmentVariableSharedSpacingTest.php │ │ ├── EnvironmentVariableUpdateApiTest.php │ │ ├── ExecuteContainerCommandTest.php │ │ ├── GithubAppsListApiTest.php │ │ ├── GithubSourceChangeTest.php │ │ ├── GithubSourceCreateTest.php │ │ ├── HetznerApiTest.php │ │ ├── HetznerServerCreationTest.php │ │ ├── IpAllowlistTest.php │ │ ├── LoginRateLimitIPTest.php │ │ ├── MultilineEnvironmentVariableTest.php │ │ ├── Proxy/ │ │ │ └── RestartProxyTest.php │ │ ├── PushServerUpdateJobLastOnlineTest.php │ │ ├── PushServerUpdateJobOptimizationTest.php │ │ ├── PushServerUpdateJobTest.php │ │ ├── RealtimeTerminalPackagingTest.php │ │ ├── ResourceOperationsCrossTenantTest.php │ │ ├── ScheduledJobManagerShouldRunNowTest.php │ │ ├── ScheduledJobManagerStaleLockTest.php │ │ ├── ScheduledJobMonitoringTest.php │ │ ├── ScheduledTaskApiTest.php │ │ ├── SecureCookieAutoDetectionTest.php │ │ ├── SentinelTokenValidationTest.php │ │ ├── SentinelUpdateCheckIndependenceTest.php │ │ ├── ServerIpUniquenessTest.php │ │ ├── ServerLimitCheckJobTest.php │ │ ├── ServerMetadataTest.php │ │ ├── ServerPatchCheckNotificationTest.php │ │ ├── ServerSettingSentinelRestartTest.php │ │ ├── ServerSettingWasChangedTest.php │ │ ├── ServerStorageCheckIndependenceTest.php │ │ ├── Service/ │ │ │ └── EditDomainPortValidationTest.php │ │ ├── ServiceDatabaseTeamTest.php │ │ ├── ServiceFqdnUpdatePathTest.php │ │ ├── ServiceMagicVariableOverwriteTest.php │ │ ├── SharedVariableComposeResolutionTest.php │ │ ├── SharedVariableDevViewTest.php │ │ ├── StartDatabaseProxyTest.php │ │ ├── StartupExecutionCleanupTest.php │ │ ├── Subscription/ │ │ │ ├── CancelSubscriptionActionsTest.php │ │ │ ├── RefundSubscriptionTest.php │ │ │ ├── ResumeSubscriptionTest.php │ │ │ └── UpdateSubscriptionQuantityTest.php │ │ ├── TeamInvitationEmailNormalizationTest.php │ │ ├── TeamInvitationPrivilegeEscalationTest.php │ │ ├── TeamNotificationCheckTest.php │ │ ├── TeamPolicyTest.php │ │ ├── TerminalAuthIpsRouteTest.php │ │ ├── TrustHostsMiddlewareTest.php │ │ ├── TwoFactorChallengeAccessTest.php │ │ └── Utf8HandlingTest.php │ ├── Pest.php │ ├── TestCase.php │ ├── Traits/ │ │ └── HandlesTestDatabase.php │ ├── Unit/ │ │ ├── Actions/ │ │ │ ├── Server/ │ │ │ │ ├── CleanupDockerTest.php │ │ │ │ └── ValidatePrerequisitesTest.php │ │ │ └── User/ │ │ │ └── DeleteUserResourcesTest.php │ │ ├── AllExcludedContainersConsistencyTest.php │ │ ├── Api/ │ │ │ └── ApplicationAutogenerateDomainTest.php │ │ ├── ApplicationComposeEditorLoadTest.php │ │ ├── ApplicationConfigurationChangeTest.php │ │ ├── ApplicationDeploymentCustomBuildCommandTest.php │ │ ├── ApplicationDeploymentEmptyEnvTest.php │ │ ├── ApplicationDeploymentErrorLoggingTest.php │ │ ├── ApplicationDeploymentNixpacksNullEnvTest.php │ │ ├── ApplicationDeploymentTypeTest.php │ │ ├── ApplicationGitSecurityTest.php │ │ ├── ApplicationHealthcheckRemovalTest.php │ │ ├── ApplicationNetworkAliasesSyncTest.php │ │ ├── ApplicationParserStringableTest.php │ │ ├── ApplicationPortDetectionTest.php │ │ ├── ApplicationServiceEnvironmentVariablesTest.php │ │ ├── ApplicationSettingStaticCastTest.php │ │ ├── ApplicationWatchPathsTest.php │ │ ├── BashEnvEscapingTest.php │ │ ├── CheckForUpdatesJobTest.php │ │ ├── CheckTraefikVersionForServerJobTest.php │ │ ├── CheckTraefikVersionJobTest.php │ │ ├── ClickhouseOfficialImageMigrationTest.php │ │ ├── CloudInitScriptValidationTest.php │ │ ├── ComposerAuthEnvEscapingTest.php │ │ ├── ContainerHealthStatusTest.php │ │ ├── ContainerStatusAggregatorTest.php │ │ ├── CoolifyTaskCleanupTest.php │ │ ├── DatabaseBackupSecurityTest.php │ │ ├── DatalistComponentTest.php │ │ ├── DeploymentExceptionTest.php │ │ ├── DockerComposeEmptyStringPreservationTest.php │ │ ├── DockerComposeEmptyTopLevelSectionsTest.php │ │ ├── DockerComposeLabelParsingTest.php │ │ ├── DockerComposePreserveRepositoryStartCommandTest.php │ │ ├── DockerComposeRawContentRemovalTest.php │ │ ├── DockerComposeRawSeparationTest.php │ │ ├── DockerImageAutoParseTest.php │ │ ├── DockerImageParserTest.php │ │ ├── DockerfileArgInsertionTest.php │ │ ├── EnvVarInputComponentTest.php │ │ ├── EnvironmentVariableFillableTest.php │ │ ├── EnvironmentVariableMagicVariableTest.php │ │ ├── EnvironmentVariableParsingEdgeCasesTest.php │ │ ├── ExcludeFromHealthCheckTest.php │ │ ├── ExecuteInDockerEscapingTest.php │ │ ├── ExtractHardcodedEnvironmentVariablesTest.php │ │ ├── ExtractYamlEnvironmentCommentsTest.php │ │ ├── FileStorageSecurityTest.php │ │ ├── FormatBytesTest.php │ │ ├── FormatContainerStatusTest.php │ │ ├── GetContainersStatusEmptyContainerSafeguardTest.php │ │ ├── GetContainersStatusServiceAggregationTest.php │ │ ├── GitLsRemoteParsingTest.php │ │ ├── GitRefValidationTest.php │ │ ├── GitlabSourceCommandsTest.php │ │ ├── GlobalSearchNewImageQuickActionTest.php │ │ ├── HealthCheckCommandInjectionTest.php │ │ ├── HetznerDeletionFailedNotificationTest.php │ │ ├── HetznerServiceTest.php │ │ ├── HetznerSshKeysTest.php │ │ ├── Jobs/ │ │ │ └── RestartProxyJobTest.php │ │ ├── Livewire/ │ │ │ ├── ApplicationGeneralPreviewTest.php │ │ │ ├── BoardingPrerequisitesTest.php │ │ │ ├── Database/ │ │ │ │ └── S3RestoreTest.php │ │ │ ├── EnvironmentVariableAutocompleteTest.php │ │ │ └── Project/ │ │ │ └── New/ │ │ │ └── DockerComposeEnvVariableHandlingTest.php │ │ ├── LocalFileVolumeReadOnlyTest.php │ │ ├── LogDrainCommandInjectionTest.php │ │ ├── LogViewerXssSecurityTest.php │ │ ├── MetricsDownsamplingTest.php │ │ ├── NestedEnvironmentVariableParsingTest.php │ │ ├── NestedEnvironmentVariableTest.php │ │ ├── Notifications/ │ │ │ └── Channels/ │ │ │ └── EmailChannelTest.php │ │ ├── NotifyOutdatedTraefikServersJobTest.php │ │ ├── ParseCommandsByLineForSudoTest.php │ │ ├── ParseDockerVolumeStringTest.php │ │ ├── ParseEnvFormatToArrayTest.php │ │ ├── Parsers/ │ │ │ └── ApplicationParserImageTagTest.php │ │ ├── PathTraversalSecurityTest.php │ │ ├── Policies/ │ │ │ ├── GithubAppPolicyTest.php │ │ │ ├── PrivateKeyPolicyTest.php │ │ │ ├── S3StoragePolicyTest.php │ │ │ └── SharedEnvironmentVariablePolicyTest.php │ │ ├── PostgRESTDetectionTest.php │ │ ├── PostgresqlInitScriptSecurityTest.php │ │ ├── PreSaveValidationTest.php │ │ ├── PreviewDeploymentPortTest.php │ │ ├── PrivateKeyStorageTest.php │ │ ├── Project/ │ │ │ └── Database/ │ │ │ └── ImportCheckFileButtonTest.php │ │ ├── ProxyConfigRecoveryTest.php │ │ ├── ProxyConfigurationSecurityTest.php │ │ ├── ProxyCustomCommandsTest.php │ │ ├── ProxyHelperTest.php │ │ ├── RestartCountTrackingTest.php │ │ ├── RestoreJobFinishedNullServerTest.php │ │ ├── RestoreJobFinishedSecurityTest.php │ │ ├── RestoreJobFinishedShellEscapingTest.php │ │ ├── Rules/ │ │ │ └── ValidCloudInitYamlTest.php │ │ ├── S3RestoreSecurityTest.php │ │ ├── S3RestoreTest.php │ │ ├── S3StorageTest.php │ │ ├── SanitizeLogsForExportTest.php │ │ ├── ScheduledJobManagerLockTest.php │ │ ├── ScheduledJobsRetryConfigTest.php │ │ ├── ScheduledTaskJobTimeoutTest.php │ │ ├── ServerManagerJobExecutionTimeTest.php │ │ ├── ServerManagerJobSentinelCheckTest.php │ │ ├── ServerQueryScopeTest.php │ │ ├── ServerStatusAccessorTest.php │ │ ├── ServiceApplicationPrerequisitesTest.php │ │ ├── ServiceConfigurationRefreshTest.php │ │ ├── ServiceExcludedStatusTest.php │ │ ├── ServiceIndexValidationTest.php │ │ ├── ServiceNameSecurityTest.php │ │ ├── ServiceParserEnvVarPreservationTest.php │ │ ├── ServiceParserImageUpdateTest.php │ │ ├── ServiceParserPathDuplicationTest.php │ │ ├── ServiceParserPortDetectionLogicTest.php │ │ ├── ServicePortSpecificVariablesTest.php │ │ ├── ServiceRequiredPortTest.php │ │ ├── SshCommandInjectionTest.php │ │ ├── SshMultiplexingDisableTest.php │ │ ├── SshRetryMechanismTest.php │ │ ├── StartKeydbConfigPermissionTest.php │ │ ├── StartProxyTest.php │ │ ├── StartRedisConfigPermissionTest.php │ │ ├── StartupExecutionCleanupTest.php │ │ ├── StopProxyTest.php │ │ ├── StripCoolifyCustomFieldsTest.php │ │ ├── TimescaleDbDetectionTest.php │ │ ├── UpdateComposeAbbreviatedVariablesTest.php │ │ ├── UpdateCoolifyTest.php │ │ ├── ValidGitRepositoryUrlTest.php │ │ ├── ValidHostnameTest.php │ │ ├── ValidProxyConfigFilenameTest.php │ │ ├── ValidateShellSafePathTest.php │ │ ├── VolumeArrayFormatSecurityTest.php │ │ ├── VolumeSecurityTest.php │ │ └── WindowsPathVolumeTest.php │ └── v4/ │ ├── Browser/ │ │ ├── DashboardTest.php │ │ ├── LoginTest.php │ │ └── RegistrationTest.php │ └── Feature/ │ ├── DangerDeleteResourceTest.php │ └── SqliteDatabaseTest.php ├── versions.json └── vite.config.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .agents/skills/debugging-output-and-previewing-html-using-ray/SKILL.md ================================================ --- name: debugging-output-and-previewing-html-using-ray description: Use when user says "send to Ray," "show in Ray," "debug in Ray," "log to Ray," "display in Ray," or wants to visualize data, debug output, or show diagrams in the Ray desktop application. metadata: author: Spatie tags: - debugging - logging - visualization - ray --- # Ray Skill ## Overview Ray is Spatie's desktop debugging application for developers. Send data directly to Ray by making HTTP requests to its local server. This can be useful for debugging applications, or to preview design, logos, or other visual content. This is what the `ray()` PHP function does under the hood. ## Connection Details | Setting | Default | Environment Variable | |---------|---------|---------------------| | Host | `localhost` | `RAY_HOST` | | Port | `23517` | `RAY_PORT` | | URL | `http://localhost:23517/` | - | ## Request Format **Method:** POST **Content-Type:** `application/json` **User-Agent:** `Ray 1.0` ### Basic Request Structure ```json { "uuid": "unique-identifier-for-this-ray-instance", "payloads": [ { "type": "log", "content": { }, "origin": { "file": "/path/to/file.php", "line_number": 42, "hostname": "my-machine" } } ], "meta": { "ray_package_version": "1.0.0" } } ``` ### Fields | Field | Type | Description | |-------|------|-------------| | `uuid` | string | Unique identifier for this Ray instance. Reuse the same UUID to update an existing entry. | | `payloads` | array | Array of payload objects to send | | `meta` | object | Optional metadata (ray_package_version, project_name, php_version) | ### Origin Object Every payload includes origin information: ```json { "file": "/Users/dev/project/app/Controller.php", "line_number": 42, "hostname": "dev-machine" } ``` ## Payload Types ### Log (Send Values) ```json { "type": "log", "content": { "values": ["Hello World", 42, {"key": "value"}] }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Custom (HTML/Text Content) ```json { "type": "custom", "content": { "content": "

HTML Content

With formatting

", "label": "My Label" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Table ```json { "type": "table", "content": { "values": {"name": "John", "email": "john@example.com", "age": 30}, "label": "User Data" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Color Set the color of the preceding log entry: ```json { "type": "color", "content": { "color": "green" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` **Available colors:** `green`, `orange`, `red`, `purple`, `blue`, `gray` ### Screen Color Set the background color of the screen: ```json { "type": "screen_color", "content": { "color": "green" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Label Add a label to the entry: ```json { "type": "label", "content": { "label": "Important" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Size Set the size of the entry: ```json { "type": "size", "content": { "size": "lg" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` **Available sizes:** `sm`, `lg` ### Notify (Desktop Notification) ```json { "type": "notify", "content": { "value": "Task completed!" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### New Screen ```json { "type": "new_screen", "content": { "name": "Debug Session" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Measure (Timing) ```json { "type": "measure", "content": { "name": "my-timer", "is_new_timer": true, "total_time": 0, "time_since_last_call": 0, "max_memory_usage_during_total_time": 0, "max_memory_usage_since_last_call": 0 }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` For subsequent measurements, set `is_new_timer: false` and provide actual timing values. ### Simple Payloads (No Content) These payloads only need a `type` and empty `content`: ```json { "type": "separator", "content": {}, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` | Type | Purpose | |------|---------| | `separator` | Add visual divider | | `clear_all` | Clear all entries | | `hide` | Hide this entry | | `remove` | Remove this entry | | `confetti` | Show confetti animation | | `show_app` | Bring Ray to foreground | | `hide_app` | Hide Ray window | ## Combining Multiple Payloads Send multiple payloads in one request. Use the same `uuid` to apply modifiers (color, label, size) to a log entry: ```json { "uuid": "abc-123", "payloads": [ { "type": "log", "content": { "values": ["Important message"] }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "color", "content": { "color": "red" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "label", "content": { "label": "ERROR" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "size", "content": { "size": "lg" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ], "meta": {} } ``` ## Example: Complete Request Send a green, labeled log message: ```bash curl -X POST http://localhost:23517/ \ -H "Content-Type: application/json" \ -H "User-Agent: Ray 1.0" \ -d '{ "uuid": "my-unique-id-123", "payloads": [ { "type": "log", "content": { "values": ["User logged in", {"user_id": 42, "name": "John"}] }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } }, { "type": "color", "content": { "color": "green" }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } }, { "type": "label", "content": { "label": "Auth" }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } } ], "meta": { "project_name": "my-app" } }' ``` ## Availability Check Before sending data, you can check if Ray is running: ``` GET http://localhost:23517/_availability_check ``` Ray responds with HTTP 404 when available (the endpoint doesn't exist, but the server is running). ## Getting Ray Information ### Get Windows Retrieve information about all open Ray windows: ``` GET http://localhost:23517/windows ``` Returns an array of window objects with their IDs and names: ```json [ {"id": 1, "name": "Window 1"}, {"id": 2, "name": "Debug Session"} ] ``` ### Get Theme Colors Retrieve the current theme colors being used by Ray: ``` GET http://localhost:23517/theme ``` Returns the theme information including color palette: ```json { "name": "Dark", "colors": { "primary": "#000000", "secondary": "#1a1a1a", "accent": "#3b82f6" } } ``` **Use Case:** When sending custom HTML content to Ray, use these theme colors to ensure your content matches Ray's current theme and looks visually integrated. **Example:** Send HTML with matching colors: ```bash # First, get the theme THEME=$(curl -s http://localhost:23517/theme) PRIMARY_COLOR=$(echo $THEME | jq -r '.colors.primary') # Then send HTML using those colors curl -X POST http://localhost:23517/ \ -H "Content-Type: application/json" \ -d '{ "uuid": "theme-matched-html", "payloads": [{ "type": "custom", "content": { "content": "

Themed Content

", "label": "Themed HTML" }, "origin": {"file": "script.sh", "line_number": 1, "hostname": "localhost"} }] }' ``` ## Payload Type Reference | Type | Content Fields | Purpose | |------|----------------|---------| | `log` | `values` (array) | Send values to Ray | | `custom` | `content`, `label` | HTML or text content | | `table` | `values`, `label` | Display as table | | `color` | `color` | Set entry color | | `screen_color` | `color` | Set screen background | | `label` | `label` | Add label to entry | | `size` | `size` | Set entry size (sm/lg) | | `notify` | `value` | Desktop notification | | `new_screen` | `name` | Create new screen | | `measure` | `name`, `is_new_timer`, timing fields | Performance timing | | `separator` | (empty) | Visual divider | | `clear_all` | (empty) | Clear all entries | | `hide` | (empty) | Hide entry | | `remove` | (empty) | Remove entry | | `confetti` | (empty) | Confetti animation | | `show_app` | (empty) | Show Ray window | | `hide_app` | (empty) | Hide Ray window | ================================================ FILE: .agents/skills/developing-with-fortify/SKILL.md ================================================ --- name: developing-with-fortify description: Laravel Fortify headless authentication backend development. Activate when implementing authentication features including login, registration, password reset, email verification, two-factor authentication (2FA/TOTP), profile updates, headless auth, authentication scaffolding, or auth guards in Laravel applications. --- # Laravel Fortify Development Fortify is a headless authentication backend that provides authentication routes and controllers for Laravel applications. ## Documentation Use `search-docs` for detailed Laravel Fortify patterns and documentation. ## Usage - **Routes**: Use `list-routes` with `only_vendor: true` and `action: "Fortify"` to see all registered endpoints - **Actions**: Check `app/Actions/Fortify/` for customizable business logic (user creation, password validation, etc.) - **Config**: See `config/fortify.php` for all options including features, guards, rate limiters, and username field - **Contracts**: Look in `Laravel\Fortify\Contracts\` for overridable response classes (`LoginResponse`, `LogoutResponse`, etc.) - **Views**: All view callbacks are set in `FortifyServiceProvider::boot()` using `Fortify::loginView()`, `Fortify::registerView()`, etc. ## Available Features Enable in `config/fortify.php` features array: - `Features::registration()` - User registration - `Features::resetPasswords()` - Password reset via email - `Features::emailVerification()` - Requires User to implement `MustVerifyEmail` - `Features::updateProfileInformation()` - Profile updates - `Features::updatePasswords()` - Password changes - `Features::twoFactorAuthentication()` - 2FA with QR codes and recovery codes > Use `search-docs` for feature configuration options and customization patterns. ## Setup Workflows ### Two-Factor Authentication Setup ``` - [ ] Add TwoFactorAuthenticatable trait to User model - [ ] Enable feature in config/fortify.php - [ ] Run migrations for 2FA columns - [ ] Set up view callbacks in FortifyServiceProvider - [ ] Create 2FA management UI - [ ] Test QR code and recovery codes ``` > Use `search-docs` for TOTP implementation and recovery code handling patterns. ### Email Verification Setup ``` - [ ] Enable emailVerification feature in config - [ ] Implement MustVerifyEmail interface on User model - [ ] Set up verifyEmailView callback - [ ] Add verified middleware to protected routes - [ ] Test verification email flow ``` > Use `search-docs` for MustVerifyEmail implementation patterns. ### Password Reset Setup ``` - [ ] Enable resetPasswords feature in config - [ ] Set up requestPasswordResetLinkView callback - [ ] Set up resetPasswordView callback - [ ] Define password.reset named route (if views disabled) - [ ] Test reset email and link flow ``` > Use `search-docs` for custom password reset flow patterns. ### SPA Authentication Setup ``` - [ ] Set 'views' => false in config/fortify.php - [ ] Install and configure Laravel Sanctum - [ ] Use 'web' guard in fortify config - [ ] Set up CSRF token handling - [ ] Test XHR authentication flows ``` > Use `search-docs` for integration and SPA authentication patterns. ## Best Practices ### Custom Authentication Logic Override authentication behavior using `Fortify::authenticateUsing()` for custom user retrieval or `Fortify::authenticateThrough()` to customize the authentication pipeline. Override response contracts in `AppServiceProvider` for custom redirects. ### Registration Customization Modify `app/Actions/Fortify/CreateNewUser.php` to customize user creation logic, validation rules, and additional fields. ### Rate Limiting Configure via `fortify.limiters.login` in config. Default configuration throttles by username + IP combination. ## Key Endpoints | Feature | Method | Endpoint | |------------------------|----------|---------------------------------------------| | Login | POST | `/login` | | Logout | POST | `/logout` | | Register | POST | `/register` | | Password Reset Request | POST | `/forgot-password` | | Password Reset | POST | `/reset-password` | | Email Verify Notice | GET | `/email/verify` | | Resend Verification | POST | `/email/verification-notification` | | Password Confirm | POST | `/user/confirm-password` | | Enable 2FA | POST | `/user/two-factor-authentication` | | Confirm 2FA | POST | `/user/confirmed-two-factor-authentication` | | 2FA Challenge | POST | `/two-factor-challenge` | | Get QR Code | GET | `/user/two-factor-qr-code` | | Recovery Codes | GET/POST | `/user/two-factor-recovery-codes` | ================================================ FILE: .agents/skills/livewire-development/SKILL.md ================================================ --- name: livewire-development description: >- Develops reactive Livewire 3 components. Activates when creating, updating, or modifying Livewire components; working with wire:model, wire:click, wire:loading, or any wire: directives; adding real-time updates, loading states, or reactivity; debugging component behavior; writing Livewire tests; or when the user mentions Livewire, component, counter, or reactive UI. --- # Livewire Development ## When to Apply Activate this skill when: - Creating new Livewire components - Modifying existing component state or behavior - Debugging reactivity or lifecycle issues - Writing Livewire component tests - Adding Alpine.js interactivity to components - Working with wire: directives ## Documentation Use `search-docs` for detailed Livewire 3 patterns and documentation. ## Basic Usage ### Creating Components Use the `php artisan make:livewire [Posts\CreatePost]` Artisan command to create new components. ### Fundamental Concepts - State should live on the server, with the UI reflecting it. - All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions. ## Livewire 3 Specifics ### Key Changes From Livewire 2 These things changed in Livewire 3, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions. - Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default. - Components now use the `App\Livewire` namespace (not `App\Http\Livewire`). - Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`). - Use the `components.layouts.app` view as the typical layout path (not `layouts.app`). ### New Directives - `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use. ### Alpine Integration - Alpine is now included with Livewire; don't manually include Alpine.js. - Plugins included with Alpine: persist, intersect, collapse, and focus. ## Best Practices ### Component Structure - Livewire components require a single root element. - Use `wire:loading` and `wire:dirty` for delightful loading states. ### Using Keys in Loops @foreach ($items as $item)
{{ $item->name }}
@endforeach
### Lifecycle Hooks Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects: public function mount(User $user) { $this->user = $user; } public function updatedSearch() { $this->resetPage(); } ## JavaScript Hooks You can listen for `livewire:init` to hook into Livewire initialization: document.addEventListener('livewire:init', function () { Livewire.hook('request', ({ fail }) => { if (fail && fail.status === 419) { alert('Your session expired'); } }); Livewire.hook('message.failed', (message, component) => { console.error(message); }); }); ## Testing Livewire::test(Counter::class) ->assertSet('count', 0) ->call('increment') ->assertSet('count', 1) ->assertSee(1) ->assertStatus(200); $this->get('/posts/create') ->assertSeeLivewire(CreatePost::class); ## Common Pitfalls - Forgetting `wire:key` in loops causes unexpected behavior when items change - Using `wire:model` expecting real-time updates (use `wire:model.live` instead in v3) - Not validating/authorizing in Livewire actions (treat them like HTTP requests) - Including Alpine.js separately when it's already bundled with Livewire 3 ================================================ FILE: .agents/skills/pest-testing/SKILL.md ================================================ --- name: pest-testing description: >- Tests applications using the Pest 4 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, browser testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. --- # Pest Testing 4 ## When to Apply Activate this skill when: - Creating new tests (unit, feature, or browser) - Modifying existing tests - Debugging test failures - Working with browser testing or smoke testing - Writing architecture tests or visual regression tests ## Documentation Use `search-docs` for detailed Pest 4 patterns and documentation. ## Basic Usage ### Creating Tests All tests must be written using Pest. Use `php artisan make:test --pest {name}`. ### Test Organization - Unit/Feature tests: `tests/Feature` and `tests/Unit` directories. - Browser tests: `tests/Browser/` directory. - Do NOT remove tests without approval - these are core application code. ### Basic Test Structure it('is true', function () { expect(true)->toBeTrue(); }); ### Running Tests - Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. - Run all tests: `php artisan test --compact`. - Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. ## Assertions Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: it('returns all', function () { $this->postJson('/api/docs', [])->assertSuccessful(); }); | Use | Instead of | |-----|------------| | `assertSuccessful()` | `assertStatus(200)` | | `assertNotFound()` | `assertStatus(404)` | | `assertForbidden()` | `assertStatus(403)` | ## Mocking Import mock function before use: `use function Pest\Laravel\mock;` ## Datasets Use datasets for repetitive tests (validation rules, etc.): it('has emails', function (string $email) { expect($email)->not->toBeEmpty(); })->with([ 'james' => 'james@laravel.com', 'taylor' => 'taylor@laravel.com', ]); ## Pest 4 Features | Feature | Purpose | |---------|---------| | Browser Testing | Full integration tests in real browsers | | Smoke Testing | Validate multiple pages quickly | | Visual Regression | Compare screenshots for visual changes | | Test Sharding | Parallel CI runs | | Architecture Testing | Enforce code conventions | ### Browser Test Example Browser tests run in real browsers for full integration testing: - Browser tests live in `tests/Browser/`. - Use Laravel features like `Event::fake()`, `assertAuthenticated()`, and model factories. - Use `RefreshDatabase` for clean state per test. - Interact with page: click, type, scroll, select, submit, drag-and-drop, touch gestures. - Test on multiple browsers (Chrome, Firefox, Safari) if requested. - Test on different devices/viewports (iPhone 14 Pro, tablets) if requested. - Switch color schemes (light/dark mode) when appropriate. - Take screenshots or pause tests for debugging. it('may reset the password', function () { Notification::fake(); $this->actingAs(User::factory()->create()); $page = visit('/sign-in'); $page->assertSee('Sign In') ->assertNoJavaScriptErrors() ->click('Forgot Password?') ->fill('email', 'nuno@laravel.com') ->click('Send Reset Link') ->assertSee('We have emailed your password reset link!'); Notification::assertSent(ResetPassword::class); }); ### Smoke Testing Quickly validate multiple pages have no JavaScript errors: $pages = visit(['/', '/about', '/contact']); $pages->assertNoJavaScriptErrors()->assertNoConsoleLogs(); ### Visual Regression Testing Capture and compare screenshots to detect visual changes. ### Test Sharding Split tests across parallel processes for faster CI runs. ### Architecture Testing Pest 4 includes architecture testing (from Pest 3): arch('controllers') ->expect('App\Http\Controllers') ->toExtendNothing() ->toHaveSuffix('Controller'); ## Common Pitfalls - Not importing `use function Pest\Laravel\mock;` before using mock - Using `assertStatus(200)` instead of `assertSuccessful()` - Forgetting datasets for repetitive validation tests - Deleting tests without approval - Forgetting `assertNoJavaScriptErrors()` in browser tests ================================================ FILE: .agents/skills/tailwindcss-development/SKILL.md ================================================ --- name: tailwindcss-development description: >- Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. --- # Tailwind CSS Development ## When to Apply Activate this skill when: - Adding styles to components or pages - Working with responsive design - Implementing dark mode - Extracting repeated patterns into components - Debugging spacing or layout issues ## Documentation Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. ## Basic Usage - Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. - Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). - Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. ## Tailwind CSS v4 Specifics - Always use Tailwind CSS v4 and avoid deprecated utilities. - `corePlugins` is not supported in Tailwind v4. ### CSS-First Configuration In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: @theme { --color-brand: oklch(0.72 0.11 178); } ### Import Syntax In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: - @tailwind base; - @tailwind components; - @tailwind utilities; + @import "tailwindcss"; ### Replaced Utilities Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain numeric. | Deprecated | Replacement | |------------|-------------| | bg-opacity-* | bg-black/* | | text-opacity-* | text-black/* | | border-opacity-* | border-black/* | | divide-opacity-* | divide-black/* | | ring-opacity-* | ring-black/* | | placeholder-opacity-* | placeholder-black/* | | flex-shrink-* | shrink-* | | flex-grow-* | grow-* | | overflow-ellipsis | text-ellipsis | | decoration-slice | box-decoration-slice | | decoration-clone | box-decoration-clone | ## Spacing Use `gap` utilities instead of margins for spacing between siblings:
Item 1
Item 2
## Dark Mode If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant:
Content adapts to color scheme
## Common Patterns ### Flexbox Layout
Left content
Right content
### Grid Layout
Card 1
Card 2
Card 3
## Common Pitfalls - Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) - Using `@tailwind` directives instead of `@import "tailwindcss"` - Trying to use `tailwind.config.js` instead of CSS `@theme` directive - Using margins for spacing between siblings instead of gap utilities - Forgetting to add dark mode variants when the project uses dark mode ================================================ FILE: .ai/design-system.md ================================================ # Coolify Design System > **Purpose**: AI/LLM-consumable reference for replicating Coolify's visual design in new applications. Contains design tokens, component styles, and interactive states — with both Tailwind CSS classes and plain CSS equivalents. --- ## 1. Design Tokens ### 1.1 Colors #### Brand / Accent | Token | Hex | Usage | |---|---|---| | `coollabs` | `#6b16ed` | Primary accent (light mode) | | `coollabs-50` | `#f5f0ff` | Highlighted button bg (light) | | `coollabs-100` | `#7317ff` | Highlighted button hover (dark) | | `coollabs-200` | `#5a12c7` | Highlighted button text (light) | | `coollabs-300` | `#4a0fa3` | Deepest brand shade | | `warning` / `warning-400` | `#fcd452` | Primary accent (dark mode) | #### Warning Scale (used for dark-mode accent + callouts) | Token | Hex | |---|---| | `warning-50` | `#fefce8` | | `warning-100` | `#fef9c3` | | `warning-200` | `#fef08a` | | `warning-300` | `#fde047` | | `warning-400` | `#fcd452` | | `warning-500` | `#facc15` | | `warning-600` | `#ca8a04` | | `warning-700` | `#a16207` | | `warning-800` | `#854d0e` | | `warning-900` | `#713f12` | #### Neutral Grays (dark mode backgrounds) | Token | Hex | Usage | |---|---|---| | `base` | `#101010` | Page background (dark) | | `coolgray-100` | `#181818` | Component background (dark) | | `coolgray-200` | `#202020` | Elevated surface / borders (dark) | | `coolgray-300` | `#242424` | Input border shadow / hover (dark) | | `coolgray-400` | `#282828` | Tooltip background (dark) | | `coolgray-500` | `#323232` | Subtle hover overlays (dark) | #### Semantic | Token | Hex | Usage | |---|---|---| | `success` | `#22C55E` | Running status, success alerts | | `error` | `#dc2626` | Stopped status, danger actions, error alerts | #### Light Mode Defaults | Element | Color | |---|---| | Page background | `gray-50` (`#f9fafb`) | | Component background | `white` (`#ffffff`) | | Borders | `neutral-200` (`#e5e5e5`) | | Primary text | `black` (`#000000`) | | Muted text | `neutral-500` (`#737373`) | | Placeholder text | `neutral-300` (`#d4d4d4`) | ### 1.2 Typography **Font family**: Inter, sans-serif (weights 100–900, woff2, `font-display: swap`) #### Heading Hierarchy > **CRITICAL**: All headings and titles (h1–h4, card titles, modal titles) MUST be `white` (`#fff`) in dark mode. The default body text color is `neutral-400` (`#a3a3a3`) — headings must override this to white or they will be nearly invisible on dark backgrounds. | Element | Tailwind | Plain CSS (light) | Plain CSS (dark) | |---|---|---|---| | `h1` | `text-3xl font-bold dark:text-white` | `font-size: 1.875rem; font-weight: 700; color: #000;` | `color: #fff;` | | `h2` | `text-xl font-bold dark:text-white` | `font-size: 1.25rem; font-weight: 700; color: #000;` | `color: #fff;` | | `h3` | `text-lg font-bold dark:text-white` | `font-size: 1.125rem; font-weight: 700; color: #000;` | `color: #fff;` | | `h4` | `text-base font-bold dark:text-white` | `font-size: 1rem; font-weight: 700; color: #000;` | `color: #fff;` | #### Body Text | Context | Tailwind | Plain CSS | |---|---|---| | Body default | `text-sm antialiased` | `font-size: 0.875rem; line-height: 1.25rem; -webkit-font-smoothing: antialiased;` | | Labels | `text-sm font-medium` | `font-size: 0.875rem; font-weight: 500;` | | Badge/status text | `text-xs font-bold` | `font-size: 0.75rem; line-height: 1rem; font-weight: 700;` | | Box description | `text-xs font-bold text-neutral-500` | `font-size: 0.75rem; font-weight: 700; color: #737373;` | ### 1.3 Spacing Patterns | Context | Value | CSS | |---|---|---| | Component internal padding | `p-2` | `padding: 0.5rem;` | | Callout padding | `p-4` | `padding: 1rem;` | | Input vertical padding | `py-1.5` | `padding-top: 0.375rem; padding-bottom: 0.375rem;` | | Button height | `h-8` | `height: 2rem;` | | Button horizontal padding | `px-2` | `padding-left: 0.5rem; padding-right: 0.5rem;` | | Button gap | `gap-2` | `gap: 0.5rem;` | | Menu item padding | `px-2 py-1` | `padding: 0.25rem 0.5rem;` | | Menu item gap | `gap-3` | `gap: 0.75rem;` | | Section margin | `mb-12` | `margin-bottom: 3rem;` | | Card min-height | `min-h-[4rem]` | `min-height: 4rem;` | ### 1.4 Border Radius | Context | Tailwind | Plain CSS | |---|---|---| | Default (inputs, buttons, cards, modals) | `rounded-sm` | `border-radius: 0.125rem;` | | Callouts | `rounded-lg` | `border-radius: 0.5rem;` | | Badges | `rounded-full` | `border-radius: 9999px;` | | Cards (coolbox variant) | `rounded` | `border-radius: 0.25rem;` | ### 1.5 Shadows #### Input / Select Box-Shadow System Coolify uses **inset box-shadows instead of borders** for inputs and selects. This enables a unique "dirty indicator" — a colored left-edge bar. ```css /* Default state */ box-shadow: inset 4px 0 0 transparent, inset 0 0 0 2px #e5e5e5; /* Default state (dark) */ box-shadow: inset 4px 0 0 transparent, inset 0 0 0 2px #242424; /* Focus state (light) — purple left bar */ box-shadow: inset 4px 0 0 #6b16ed, inset 0 0 0 2px #e5e5e5; /* Focus state (dark) — yellow left bar */ box-shadow: inset 4px 0 0 #fcd452, inset 0 0 0 2px #242424; /* Dirty (modified) state — same as focus */ box-shadow: inset 4px 0 0 #6b16ed, inset 0 0 0 2px #e5e5e5; /* light */ box-shadow: inset 4px 0 0 #fcd452, inset 0 0 0 2px #242424; /* dark */ /* Disabled / Readonly */ box-shadow: none; ``` #### Input-Sticky Variant (thinner border) ```css /* Uses 1px border instead of 2px */ box-shadow: inset 4px 0 0 transparent, inset 0 0 0 1px #e5e5e5; ``` ### 1.6 Focus Ring System All interactive elements (buttons, links, checkboxes) share this focus pattern: **Tailwind:** ``` focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-base ``` **Plain CSS:** ```css :focus-visible { outline: none; box-shadow: 0 0 0 2px #101010, 0 0 0 4px #6b16ed; /* light */ } /* dark mode */ .dark :focus-visible { box-shadow: 0 0 0 2px #101010, 0 0 0 4px #fcd452; } ``` > **Note**: Inputs use the inset box-shadow system (section 1.5) instead of the ring system. --- ## 2. Dark Mode Strategy - **Toggle method**: Class-based — `.dark` class on `` element - **CSS variant**: `@custom-variant dark (&:where(.dark, .dark *));` - **Default border override**: All elements default to `border-color: var(--color-coolgray-200)` (`#202020`) instead of `currentcolor` ### Accent Color Swap | Context | Light | Dark | |---|---|---| | Primary accent | `coollabs` (`#6b16ed`) | `warning` (`#fcd452`) | | Focus ring | `ring-coollabs` | `ring-warning` | | Input focus bar | `#6b16ed` (purple) | `#fcd452` (yellow) | | Active nav text | `text-black` | `text-warning` | | Helper/highlight text | `text-coollabs` | `text-warning` | | Loading spinner | `text-coollabs` | `text-warning` | | Scrollbar thumb | `coollabs-100` | `coollabs-100` | ### Background Hierarchy (dark) ``` #101010 (base) — page background └─ #181818 (coolgray-100) — cards, inputs, components └─ #202020 (coolgray-200) — elevated surfaces, borders, nav active └─ #242424 (coolgray-300) — input borders (via box-shadow), button borders └─ #282828 (coolgray-400) — tooltips, hover states └─ #323232 (coolgray-500) — subtle overlays ``` ### Background Hierarchy (light) ``` #f9fafb (gray-50) — page background └─ #ffffff (white) — cards, inputs, components └─ #e5e5e5 (neutral-200) — borders └─ #f5f5f5 (neutral-100) — hover backgrounds └─ #d4d4d4 (neutral-300) — deeper hover, nav active ``` --- ## 3. Component Catalog ### 3.1 Button #### Default **Tailwind:** ``` flex gap-2 justify-center items-center px-2 h-8 text-sm text-black normal-case rounded-sm border-2 outline-0 cursor-pointer font-medium bg-white border-neutral-200 hover:bg-neutral-100 dark:bg-coolgray-100 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-200 dark:border-coolgray-300 hover:text-black disabled:cursor-not-allowed min-w-fit dark:disabled:text-neutral-600 disabled:border-transparent disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-base ``` **Plain CSS:** ```css .button { display: flex; gap: 0.5rem; justify-content: center; align-items: center; padding: 0 0.5rem; height: 2rem; font-size: 0.875rem; font-weight: 500; text-transform: none; color: #000; background: #fff; border: 2px solid #e5e5e5; border-radius: 0.125rem; outline: 0; cursor: pointer; min-width: fit-content; } .button:hover { background: #f5f5f5; } /* Dark */ .dark .button { background: #181818; color: #fff; border-color: #242424; } .dark .button:hover { background: #202020; color: #fff; } /* Disabled */ .button:disabled { cursor: not-allowed; border-color: transparent; background: transparent; color: #d4d4d4; } .dark .button:disabled { color: #525252; } ``` #### Highlighted (Primary Action) **Tailwind** (via `isHighlighted` attribute): ``` text-coollabs-200 dark:text-white bg-coollabs-50 dark:bg-coollabs/20 border-coollabs dark:border-coollabs-100 hover:bg-coollabs hover:text-white dark:hover:bg-coollabs-100 dark:hover:text-white ``` **Plain CSS:** ```css .button-highlighted { color: #5a12c7; background: #f5f0ff; border-color: #6b16ed; } .button-highlighted:hover { background: #6b16ed; color: #fff; } .dark .button-highlighted { color: #fff; background: rgba(107, 22, 237, 0.2); border-color: #7317ff; } .dark .button-highlighted:hover { background: #7317ff; color: #fff; } ``` #### Error / Danger **Tailwind** (via `isError` attribute): ``` text-red-800 dark:text-red-300 bg-red-50 dark:bg-red-900/30 border-red-300 dark:border-red-800 hover:bg-red-300 hover:text-white dark:hover:bg-red-800 dark:hover:text-white ``` **Plain CSS:** ```css .button-error { color: #991b1b; background: #fef2f2; border-color: #fca5a5; } .button-error:hover { background: #fca5a5; color: #fff; } .dark .button-error { color: #fca5a5; background: rgba(127, 29, 29, 0.3); border-color: #991b1b; } .dark .button-error:hover { background: #991b1b; color: #fff; } ``` #### Loading Indicator Buttons automatically show a spinner (SVG with `animate-spin`) next to their content during async operations. The spinner uses the accent color (`text-coollabs` / `text-warning`). --- ### 3.2 Input **Tailwind:** ``` block py-1.5 w-full text-sm text-black rounded-sm border-0 dark:bg-coolgray-100 dark:text-white disabled:bg-neutral-200 disabled:text-neutral-500 dark:disabled:bg-coolgray-100/40 dark:read-only:text-neutral-500 dark:read-only:bg-coolgray-100/40 placeholder:text-neutral-300 dark:placeholder:text-neutral-700 read-only:text-neutral-500 read-only:bg-neutral-200 focus-visible:outline-none ``` **Plain CSS:** ```css .input { display: block; padding: 0.375rem 0.5rem; width: 100%; font-size: 0.875rem; color: #000; background: #fff; border: 0; border-radius: 0.125rem; box-shadow: inset 4px 0 0 transparent, inset 0 0 0 2px #e5e5e5; } .input:focus-visible { outline: none; box-shadow: inset 4px 0 0 #6b16ed, inset 0 0 0 2px #e5e5e5; } .input::placeholder { color: #d4d4d4; } .input:disabled { background: #e5e5e5; color: #737373; box-shadow: none; } .input:read-only { color: #737373; background: #e5e5e5; box-shadow: none; } .input[type="password"] { padding-right: 2.4rem; } /* Dark */ .dark .input { background: #181818; color: #fff; box-shadow: inset 4px 0 0 transparent, inset 0 0 0 2px #242424; } .dark .input:focus-visible { box-shadow: inset 4px 0 0 #fcd452, inset 0 0 0 2px #242424; } .dark .input::placeholder { color: #404040; } .dark .input:disabled { background: rgba(24, 24, 24, 0.4); box-shadow: none; } .dark .input:read-only { color: #737373; background: rgba(24, 24, 24, 0.4); box-shadow: none; } ``` #### Dirty (Modified) State When an input value has been changed but not saved, a 4px colored left bar appears via box-shadow — same colors as focus state. This provides a visual indicator that the field has unsaved changes. --- ### 3.3 Select Same base styles as Input, plus a custom dropdown arrow SVG: **Tailwind:** ``` w-full block py-1.5 text-sm text-black rounded-sm border-0 dark:bg-coolgray-100 dark:text-white disabled:bg-neutral-200 disabled:text-neutral-500 dark:disabled:bg-coolgray-100/40 focus-visible:outline-none ``` **Additional plain CSS for the dropdown arrow:** ```css .select { /* ...same as .input base... */ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='%23000000'%3e%3cpath stroke-linecap='round' stroke-linejoin='round' d='M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9'/%3e%3c/svg%3e"); background-position: right 0.5rem center; background-repeat: no-repeat; background-size: 1rem 1rem; padding-right: 2.5rem; appearance: none; } /* Dark mode: white stroke arrow */ .dark .select { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='%23ffffff'%3e%3cpath stroke-linecap='round' stroke-linejoin='round' d='M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9'/%3e%3c/svg%3e"); } ``` --- ### 3.4 Checkbox **Tailwind:** ``` dark:border-neutral-700 text-coolgray-400 dark:bg-coolgray-100 rounded-sm cursor-pointer dark:disabled:bg-base dark:disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-base ``` **Container:** ``` flex flex-row items-center gap-4 pr-2 py-1 form-control min-w-fit dark:hover:bg-coolgray-100 cursor-pointer ``` **Plain CSS:** ```css .checkbox { border-color: #404040; color: #282828; background: #181818; border-radius: 0.125rem; cursor: pointer; } .checkbox:focus-visible { outline: none; box-shadow: 0 0 0 2px #101010, 0 0 0 4px #fcd452; } .checkbox-container { display: flex; flex-direction: row; align-items: center; gap: 1rem; padding: 0.25rem 0.5rem 0.25rem 0; min-width: fit-content; cursor: pointer; } .dark .checkbox-container:hover { background: #181818; } ``` --- ### 3.5 Textarea Uses `font-mono` for monospace text. Supports tab key insertion (2 spaces). **Important**: Large/multiline textareas should NOT use the inset box-shadow left-border system from `.input`. Use a simple border instead: **Tailwind:** ``` block w-full text-sm text-black rounded-sm border border-neutral-200 dark:bg-coolgray-100 dark:text-white dark:border-coolgray-300 font-mono focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-base ``` **Plain CSS:** ```css .textarea { display: block; width: 100%; font-size: 0.875rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; color: #000; background: #fff; border: 1px solid #e5e5e5; border-radius: 0.125rem; } .textarea:focus-visible { outline: none; box-shadow: 0 0 0 2px #fff, 0 0 0 4px #6b16ed; } .dark .textarea { background: #181818; color: #fff; border-color: #242424; } .dark .textarea:focus-visible { box-shadow: 0 0 0 2px #101010, 0 0 0 4px #fcd452; } ``` > **Note**: The 4px inset left-border (dirty/focus indicator) is only for single-line inputs and selects, not textareas. --- ### 3.6 Box / Card #### Standard Box **Tailwind:** ``` relative flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 shadow-sm bg-white border text-black dark:text-white hover:text-black border-neutral-200 dark:border-coolgray-300 hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:no-underline rounded-sm ``` **Plain CSS:** ```css .box { position: relative; display: flex; flex-direction: column; padding: 0.5rem; min-height: 4rem; background: #fff; border: 1px solid #e5e5e5; border-radius: 0.125rem; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); color: #000; cursor: pointer; transition: background-color 150ms, color 150ms; text-decoration: none; } .box:hover { background: #f5f5f5; color: #000; } .dark .box { background: #181818; border-color: #242424; color: #fff; } .dark .box:hover { background: #7317ff; color: #fff; } /* IMPORTANT: child text must also turn white/black on hover, since description text (#737373) is invisible on purple bg */ .box:hover .box-title { color: #000; } .box:hover .box-description { color: #000; } .dark .box:hover .box-title { color: #fff; } .dark .box:hover .box-description { color: #fff; } /* Desktop: row layout */ @media (min-width: 1024px) { .box { flex-direction: row; } } ``` #### Coolbox (Ring Hover) **Tailwind:** ``` relative flex transition-all duration-150 dark:bg-coolgray-100 bg-white p-2 rounded border border-neutral-200 dark:border-coolgray-400 hover:ring-2 dark:hover:ring-warning hover:ring-coollabs cursor-pointer min-h-[4rem] ``` **Plain CSS:** ```css .coolbox { position: relative; display: flex; padding: 0.5rem; min-height: 4rem; background: #fff; border: 1px solid #e5e5e5; border-radius: 0.25rem; cursor: pointer; transition: all 150ms; } .coolbox:hover { box-shadow: 0 0 0 2px #6b16ed; } .dark .coolbox { background: #181818; border-color: #282828; } .dark .coolbox:hover { box-shadow: 0 0 0 2px #fcd452; } ``` #### Box Text > **IMPORTANT — Dark mode titles**: Card/box titles MUST be `#fff` (white) in dark mode, not the default body text color (`#a3a3a3` / neutral-400). A black or grey title is nearly invisible on dark backgrounds (`#181818`). This applies to all heading-level text inside cards. ```css .box-title { font-weight: 700; color: #000; /* light mode: black */ } .dark .box-title { color: #fff; /* dark mode: MUST be white, not grey */ } .box-description { font-size: 0.75rem; font-weight: 700; color: #737373; } /* On hover: description must become visible against colored bg */ .box:hover .box-description { color: #000; } .dark .box:hover .box-description { color: #fff; } ``` --- ### 3.7 Badge / Status Indicator **Tailwind:** ``` inline-block w-3 h-3 text-xs font-bold rounded-full leading-none border border-neutral-200 dark:border-black ``` **Variants**: `badge-success` (`bg-success`), `badge-warning` (`bg-warning`), `badge-error` (`bg-error`) **Plain CSS:** ```css .badge { display: inline-block; width: 0.75rem; height: 0.75rem; border-radius: 9999px; border: 1px solid #e5e5e5; } .dark .badge { border-color: #000; } .badge-success { background: #22C55E; } .badge-warning { background: #fcd452; } .badge-error { background: #dc2626; } ``` #### Status Text Pattern Status indicators combine a badge dot with text: ```html
Running
``` | Status | Badge Class | Text Color | |---|---|---| | Running | `badge-success` | `text-success` (`#22C55E`) | | Stopped | `badge-error` | `text-error` (`#dc2626`) | | Degraded | `badge-warning` | `dark:text-warning` (`#fcd452`) | | Restarting | `badge-warning` | `dark:text-warning` (`#fcd452`) | --- ### 3.8 Dropdown **Container Tailwind:** ``` p-1 mt-1 bg-white border rounded-sm shadow-sm dark:bg-coolgray-200 dark:border-coolgray-300 border-neutral-300 ``` **Item Tailwind:** ``` flex relative gap-2 justify-start items-center py-1 pr-4 pl-2 w-full text-xs transition-colors cursor-pointer select-none dark:text-white hover:bg-neutral-100 dark:hover:bg-coollabs outline-none focus-visible:bg-neutral-100 dark:focus-visible:bg-coollabs ``` **Plain CSS:** ```css .dropdown { padding: 0.25rem; margin-top: 0.25rem; background: #fff; border: 1px solid #d4d4d4; border-radius: 0.125rem; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); } .dark .dropdown { background: #202020; border-color: #242424; } .dropdown-item { display: flex; position: relative; gap: 0.5rem; justify-content: flex-start; align-items: center; padding: 0.25rem 1rem 0.25rem 0.5rem; width: 100%; font-size: 0.75rem; cursor: pointer; user-select: none; transition: background-color 150ms; } .dropdown-item:hover { background: #f5f5f5; } .dark .dropdown-item { color: #fff; } .dark .dropdown-item:hover { background: #6b16ed; } ``` --- ### 3.9 Sidebar / Navigation #### Sidebar Container + Page Layout The navbar is a **fixed left sidebar** (14rem / 224px wide on desktop), with main content offset to the right. **Tailwind (sidebar wrapper — desktop):** ``` hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-56 lg:flex-col min-w-0 ``` **Tailwind (sidebar inner — scrollable):** ``` flex flex-col overflow-y-auto grow gap-y-5 scrollbar min-w-0 ``` **Tailwind (nav element):** ``` flex flex-col flex-1 px-2 bg-white border-r dark:border-coolgray-200 border-neutral-300 dark:bg-base ``` **Tailwind (main content area):** ``` lg:pl-56 ``` **Tailwind (main content padding):** ``` p-4 sm:px-6 lg:px-8 lg:py-6 ``` **Tailwind (mobile top bar — shown on small screens, hidden on lg+):** ``` sticky top-0 z-40 flex items-center justify-between px-4 py-4 gap-x-6 sm:px-6 lg:hidden bg-white/95 dark:bg-base/95 backdrop-blur-sm border-b border-neutral-300/50 dark:border-coolgray-200/50 ``` **Tailwind (mobile hamburger icon):** ``` -m-2.5 p-2.5 dark:text-warning ``` **Plain CSS:** ```css /* Sidebar — desktop only */ .sidebar { display: none; } @media (min-width: 1024px) { .sidebar { display: flex; flex-direction: column; position: fixed; top: 0; bottom: 0; left: 0; z-index: 50; width: 14rem; /* 224px */ min-width: 0; } } .sidebar-inner { display: flex; flex-direction: column; flex-grow: 1; overflow-y: auto; gap: 1.25rem; min-width: 0; } /* Nav element */ .sidebar-nav { display: flex; flex-direction: column; flex: 1; padding: 0 0.5rem; background: #fff; border-right: 1px solid #d4d4d4; } .dark .sidebar-nav { background: #101010; border-right-color: #202020; } /* Main content offset */ @media (min-width: 1024px) { .main-content { padding-left: 14rem; } } .main-content-inner { padding: 1rem; } @media (min-width: 640px) { .main-content-inner { padding: 1rem 1.5rem; } } @media (min-width: 1024px) { .main-content-inner { padding: 1.5rem 2rem; } } /* Mobile top bar — visible below lg breakpoint */ .mobile-topbar { position: sticky; top: 0; z-index: 40; display: flex; align-items: center; justify-content: space-between; padding: 1rem; gap: 1.5rem; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(12px); border-bottom: 1px solid rgba(212, 212, 212, 0.5); } .dark .mobile-topbar { background: rgba(16, 16, 16, 0.95); border-bottom-color: rgba(32, 32, 32, 0.5); } @media (min-width: 1024px) { .mobile-topbar { display: none; } } /* Mobile sidebar overlay (shown when hamburger is tapped) */ .sidebar-mobile { position: relative; display: flex; flex: 1; width: 100%; max-width: 14rem; min-width: 0; } .sidebar-mobile-scroll { display: flex; flex-direction: column; padding-bottom: 0.5rem; overflow-y: auto; min-width: 14rem; gap: 1.25rem; min-width: 0; } .dark .sidebar-mobile-scroll { background: #181818; } ``` #### Sidebar Header (Logo + Search) **Tailwind:** ``` flex lg:pt-6 pt-4 pb-4 pl-2 ``` **Logo:** ``` text-2xl font-bold tracking-wide dark:text-white hover:opacity-80 transition-opacity ``` **Search button:** ``` flex items-center gap-1.5 px-2.5 py-1.5 bg-neutral-100 dark:bg-coolgray-100 border border-neutral-300 dark:border-coolgray-200 rounded-md hover:bg-neutral-200 dark:hover:bg-coolgray-200 transition-colors ``` **Search kbd hint:** ``` px-1 py-0.5 text-xs font-semibold text-neutral-500 dark:text-neutral-400 bg-neutral-200 dark:bg-coolgray-200 rounded ``` **Plain CSS:** ```css .sidebar-header { display: flex; padding: 1rem 0 1rem 0.5rem; } @media (min-width: 1024px) { .sidebar-header { padding-top: 1.5rem; } } .sidebar-logo { font-size: 1.5rem; font-weight: 700; letter-spacing: 0.025em; color: #000; text-decoration: none; } .dark .sidebar-logo { color: #fff; } .sidebar-logo:hover { opacity: 0.8; } .sidebar-search-btn { display: flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.625rem; background: #f5f5f5; border: 1px solid #d4d4d4; border-radius: 0.375rem; cursor: pointer; transition: background-color 150ms; } .sidebar-search-btn:hover { background: #e5e5e5; } .dark .sidebar-search-btn { background: #181818; border-color: #202020; } .dark .sidebar-search-btn:hover { background: #202020; } .sidebar-search-kbd { padding: 0.125rem 0.25rem; font-size: 0.75rem; font-weight: 600; color: #737373; background: #e5e5e5; border-radius: 0.25rem; } .dark .sidebar-search-kbd { color: #a3a3a3; background: #202020; } ``` #### Menu Item List **Tailwind (list container):** ``` flex flex-col flex-1 gap-y-7 ``` **Tailwind (inner list):** ``` flex flex-col h-full space-y-1.5 ``` **Plain CSS:** ```css .menu-list { display: flex; flex-direction: column; flex: 1; gap: 1.75rem; list-style: none; padding: 0; margin: 0; } .menu-list-inner { display: flex; flex-direction: column; height: 100%; gap: 0.375rem; list-style: none; padding: 0; margin: 0; } ``` #### Menu Item **Tailwind:** ``` flex gap-3 items-center px-2 py-1 w-full text-sm dark:hover:bg-coolgray-100 dark:hover:text-white hover:bg-neutral-300 rounded-sm truncate min-w-0 ``` #### Menu Item Active **Tailwind:** ``` text-black rounded-sm dark:bg-coolgray-200 dark:text-warning bg-neutral-200 overflow-hidden ``` #### Menu Item Icon / Label ``` /* Icon */ flex-shrink-0 w-6 h-6 dark:hover:text-white /* Label */ min-w-0 flex-1 truncate ``` **Plain CSS:** ```css .menu-item { display: flex; gap: 0.75rem; align-items: center; padding: 0.25rem 0.5rem; width: 100%; font-size: 0.875rem; border-radius: 0.125rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .menu-item:hover { background: #d4d4d4; } .dark .menu-item:hover { background: #181818; color: #fff; } .menu-item-active { color: #000; background: #e5e5e5; border-radius: 0.125rem; } .dark .menu-item-active { background: #202020; color: #fcd452; } .menu-item-icon { flex-shrink: 0; width: 1.5rem; height: 1.5rem; } .menu-item-label { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } ``` #### Sub-Menu Item ```css .sub-menu-item { /* Same as menu-item but with gap: 0.5rem and icon size 1rem */ display: flex; gap: 0.5rem; align-items: center; padding: 0.25rem 0.5rem; width: 100%; font-size: 0.875rem; border-radius: 0.125rem; } .sub-menu-item-icon { flex-shrink: 0; width: 1rem; height: 1rem; } ``` --- ### 3.10 Callout / Alert Four types: `warning`, `danger`, `info`, `success`. **Structure:** ```html
Title
Content
``` **Base Tailwind:** ``` relative p-4 border rounded-lg ``` **Type Colors:** | Type | Background | Border | Title Text | Body Text | |---|---|---|---|---| | **warning** | `bg-warning-50 dark:bg-warning-900/30` | `border-warning-300 dark:border-warning-800` | `text-warning-800 dark:text-warning-300` | `text-warning-700 dark:text-warning-200` | | **danger** | `bg-red-50 dark:bg-red-900/30` | `border-red-300 dark:border-red-800` | `text-red-800 dark:text-red-300` | `text-red-700 dark:text-red-200` | | **info** | `bg-blue-50 dark:bg-blue-900/30` | `border-blue-300 dark:border-blue-800` | `text-blue-800 dark:text-blue-300` | `text-blue-700 dark:text-blue-200` | | **success** | `bg-green-50 dark:bg-green-900/30` | `border-green-300 dark:border-green-800` | `text-green-800 dark:text-green-300` | `text-green-700 dark:text-green-200` | **Plain CSS (warning example):** ```css .callout { position: relative; padding: 1rem; border: 1px solid; border-radius: 0.5rem; } .callout-warning { background: #fefce8; border-color: #fde047; } .dark .callout-warning { background: rgba(113, 63, 18, 0.3); border-color: #854d0e; } .callout-title { font-size: 1rem; font-weight: 700; } .callout-warning .callout-title { color: #854d0e; } .dark .callout-warning .callout-title { color: #fde047; } .callout-text { margin-top: 0.5rem; font-size: 0.875rem; } .callout-warning .callout-text { color: #a16207; } .dark .callout-warning .callout-text { color: #fef08a; } ``` **Icon colors per type:** - Warning: `text-warning-600 dark:text-warning-400` (`#ca8a04` / `#fcd452`) - Danger: `text-red-600 dark:text-red-400` (`#dc2626` / `#f87171`) - Info: `text-blue-600 dark:text-blue-400` (`#2563eb` / `#60a5fa`) - Success: `text-green-600 dark:text-green-400` (`#16a34a` / `#4ade80`) --- ### 3.11 Toast / Notification **Container Tailwind:** ``` relative flex flex-col items-start shadow-[0_5px_15px_-3px_rgb(0_0_0_/_0.08)] w-full transition-all duration-100 ease-out dark:bg-coolgray-100 bg-white dark:border dark:border-coolgray-200 rounded-sm sm:max-w-xs ``` **Plain CSS:** ```css .toast { position: relative; display: flex; flex-direction: column; align-items: flex-start; width: 100%; max-width: 20rem; background: #fff; border-radius: 0.125rem; box-shadow: 0 5px 15px -3px rgba(0, 0, 0, 0.08); transition: all 100ms ease-out; } .dark .toast { background: #181818; border: 1px solid #202020; } ``` **Icon colors per toast type:** | Type | Color | Hex | |---|---|---| | Success | `text-green-500` | `#22c55e` | | Info | `text-blue-500` | `#3b82f6` | | Warning | `text-orange-400` | `#fb923c` | | Danger | `text-red-500` | `#ef4444` | **Behavior**: Stacks up to 4 toasts, auto-dismisses after 4 seconds, positioned bottom-right. --- ### 3.12 Modal **Tailwind (dialog-based):** ``` rounded-sm modal-box max-h-[calc(100vh-5rem)] flex flex-col ``` **Modal Input variant container:** ``` relative w-full lg:w-auto lg:min-w-2xl lg:max-w-4xl border rounded-sm drop-shadow-sm bg-white border-neutral-200 dark:bg-base dark:border-coolgray-300 flex flex-col ``` **Modal Confirmation container:** ``` relative w-full border rounded-sm min-w-full lg:min-w-[36rem] max-w-[48rem] max-h-[calc(100vh-2rem)] bg-neutral-100 border-neutral-400 dark:bg-base dark:border-coolgray-300 flex flex-col ``` **Plain CSS:** ```css .modal-box { border-radius: 0.125rem; max-height: calc(100vh - 5rem); display: flex; flex-direction: column; } .modal-input { position: relative; width: 100%; border: 1px solid #e5e5e5; border-radius: 0.125rem; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.05)); background: #fff; display: flex; flex-direction: column; } .dark .modal-input { background: #101010; border-color: #242424; } /* Desktop sizing */ @media (min-width: 1024px) { .modal-input { width: auto; min-width: 42rem; max-width: 56rem; } } ``` **Modal header:** ```css .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 1.5rem; flex-shrink: 0; } .modal-header h3 { font-size: 1.5rem; font-weight: 700; } ``` **Close button:** ```css .modal-close { width: 2rem; height: 2rem; border-radius: 9999px; color: #fff; } .modal-close:hover { background: #242424; } ``` --- ### 3.13 Slide-Over Panel **Tailwind:** ``` fixed inset-y-0 right-0 flex max-w-full pl-10 ``` **Inner panel:** ``` max-w-xl w-screen flex flex-col h-full py-6 border-l shadow-lg bg-neutral-50 dark:bg-base dark:border-neutral-800 border-neutral-200 ``` **Plain CSS:** ```css .slide-over { position: fixed; top: 0; bottom: 0; right: 0; display: flex; max-width: 100%; padding-left: 2.5rem; } .slide-over-panel { max-width: 36rem; width: 100vw; display: flex; flex-direction: column; height: 100%; padding: 1.5rem 0; border-left: 1px solid #e5e5e5; box-shadow: -10px 0 15px -3px rgba(0, 0, 0, 0.1); background: #fafafa; } .dark .slide-over-panel { background: #101010; border-color: #262626; } ``` --- ### 3.14 Tag **Tailwind:** ``` px-2 py-1 cursor-pointer text-xs font-bold text-neutral-500 dark:bg-coolgray-100 dark:hover:bg-coolgray-300 bg-neutral-100 hover:bg-neutral-200 ``` **Plain CSS:** ```css .tag { padding: 0.25rem 0.5rem; font-size: 0.75rem; font-weight: 700; color: #737373; background: #f5f5f5; cursor: pointer; } .tag:hover { background: #e5e5e5; } .dark .tag { background: #181818; } .dark .tag:hover { background: #242424; } ``` --- ### 3.15 Loading Spinner **Tailwind:** ``` w-4 h-4 text-coollabs dark:text-warning animate-spin ``` **Plain CSS + SVG:** ```css .loading-spinner { width: 1rem; height: 1rem; color: #6b16ed; animation: spin 1s linear infinite; } .dark .loading-spinner { color: #fcd452; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } ``` **SVG structure:** ```html ``` --- ### 3.16 Helper / Tooltip **Tailwind (trigger icon):** ``` cursor-pointer text-coollabs dark:text-warning ``` **Tailwind (popup):** ``` hidden absolute z-40 text-xs rounded-sm text-neutral-700 group-hover:block dark:border-coolgray-500 border-neutral-900 dark:bg-coolgray-400 bg-neutral-200 dark:text-neutral-300 max-w-sm whitespace-normal break-words ``` **Plain CSS:** ```css .helper-icon { cursor: pointer; color: #6b16ed; } .dark .helper-icon { color: #fcd452; } .helper-popup { display: none; position: absolute; z-index: 40; font-size: 0.75rem; border-radius: 0.125rem; color: #404040; background: #e5e5e5; max-width: 24rem; white-space: normal; word-break: break-word; padding: 1rem; } .dark .helper-popup { background: #282828; color: #d4d4d4; border: 1px solid #323232; } /* Show on parent hover */ .helper:hover .helper-popup { display: block; } ``` --- ### 3.17 Highlighted Text **Tailwind:** ``` inline-block font-bold text-coollabs dark:text-warning ``` **Plain CSS:** ```css .text-highlight { display: inline-block; font-weight: 700; color: #6b16ed; } .dark .text-highlight { color: #fcd452; } ``` --- ### 3.18 Scrollbar **Tailwind:** ``` scrollbar-thumb-coollabs-100 scrollbar-track-neutral-200 dark:scrollbar-track-coolgray-200 scrollbar-thin ``` **Plain CSS:** ```css ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: #e5e5e5; } ::-webkit-scrollbar-thumb { background: #7317ff; } .dark ::-webkit-scrollbar-track { background: #202020; } ``` --- ### 3.19 Table **Plain CSS:** ```css table { min-width: 100%; border-collapse: separate; } table, tbody { border-bottom: 1px solid #d4d4d4; } .dark table, .dark tbody { border-color: #202020; } thead { text-transform: uppercase; } tr { color: #000; } tr:hover { background: #e5e5e5; } .dark tr { color: #a3a3a3; } .dark tr:hover { background: #000; } th { padding: 0.875rem 0.75rem; text-align: left; color: #000; } .dark th { color: #fff; } th:first-child { padding-left: 1.5rem; } td { padding: 1rem 0.75rem; white-space: nowrap; } td:first-child { padding-left: 1.5rem; font-weight: 700; } ``` --- ### 3.20 Keyboard Shortcut Indicator **Tailwind:** ``` px-2 text-xs rounded-sm border border-dashed border-neutral-700 dark:text-warning ``` **Plain CSS:** ```css .kbd { padding: 0 0.5rem; font-size: 0.75rem; border-radius: 0.125rem; border: 1px dashed #404040; } .dark .kbd { color: #fcd452; } ``` --- ## 4. Base Element Styles These global styles are applied to all HTML elements: ```css /* Page */ html, body { width: 100%; min-height: 100%; background: #f9fafb; font-family: Inter, sans-serif; } .dark html, .dark body { background: #101010; color: #a3a3a3; } body { min-height: 100vh; font-size: 0.875rem; -webkit-font-smoothing: antialiased; overflow-x: hidden; } /* Links */ a:hover { color: #000; } .dark a:hover { color: #fff; } /* Labels */ .dark label { color: #a3a3a3; } /* Sections */ section { margin-bottom: 3rem; } /* Default border color override */ *, ::after, ::before, ::backdrop { border-color: #202020; /* coolgray-200 */ } /* Select options */ .dark option { color: #fff; background: #181818; } ``` --- ## 5. Interactive State Reference ### Focus | Element Type | Mechanism | Light | Dark | |---|---|---|---| | Buttons, links, checkboxes | `ring-2` offset | Purple `#6b16ed` | Yellow `#fcd452` | | Inputs, selects, textareas | Inset box-shadow (4px left bar) | Purple `#6b16ed` | Yellow `#fcd452` | | Dropdown items | Background change | `bg-neutral-100` | `bg-coollabs` (`#6b16ed`) | ### Hover | Element | Light | Dark | |---|---|---| | Button (default) | `bg-neutral-100` | `bg-coolgray-200` | | Button (highlighted) | `bg-coollabs` (`#6b16ed`) | `bg-coollabs-100` (`#7317ff`) | | Button (error) | `bg-red-300` | `bg-red-800` | | Box card | `bg-neutral-100` + all child text `#000` | `bg-coollabs-100` (`#7317ff`) + all child text `#fff` | | Coolbox card | Ring: `ring-coollabs` | Ring: `ring-warning` | | Menu item | `bg-neutral-300` | `bg-coolgray-100` | | Dropdown item | `bg-neutral-100` | `bg-coollabs` | | Table row | `bg-neutral-200` | `bg-black` | | Link | `text-black` | `text-white` | | Checkbox container | — | `bg-coolgray-100` | ### Disabled ```css /* Universal disabled pattern */ :disabled { cursor: not-allowed; color: #d4d4d4; /* neutral-300 */ background: transparent; border-color: transparent; } .dark :disabled { color: #525252; /* neutral-600 */ } /* Input-specific */ .input:disabled { background: #e5e5e5; /* neutral-200 */ color: #737373; /* neutral-500 */ box-shadow: none; } .dark .input:disabled { background: rgba(24, 24, 24, 0.4); box-shadow: none; } ``` ### Readonly ```css .input:read-only { color: #737373; background: #e5e5e5; box-shadow: none; } .dark .input:read-only { color: #737373; background: rgba(24, 24, 24, 0.4); box-shadow: none; } ``` --- ## 6. CSS Custom Properties (Theme Tokens) For use in any CSS framework or plain CSS: ```css :root { /* Font */ --font-sans: Inter, sans-serif; /* Brand */ --color-base: #101010; --color-coollabs: #6b16ed; --color-coollabs-50: #f5f0ff; --color-coollabs-100: #7317ff; --color-coollabs-200: #5a12c7; --color-coollabs-300: #4a0fa3; /* Neutral grays (dark backgrounds) */ --color-coolgray-100: #181818; --color-coolgray-200: #202020; --color-coolgray-300: #242424; --color-coolgray-400: #282828; --color-coolgray-500: #323232; /* Warning / dark accent */ --color-warning: #fcd452; --color-warning-50: #fefce8; --color-warning-100: #fef9c3; --color-warning-200: #fef08a; --color-warning-300: #fde047; --color-warning-400: #fcd452; --color-warning-500: #facc15; --color-warning-600: #ca8a04; --color-warning-700: #a16207; --color-warning-800: #854d0e; --color-warning-900: #713f12; /* Semantic */ --color-success: #22C55E; --color-error: #dc2626; } ``` ================================================ FILE: .claude/skills/debugging-output-and-previewing-html-using-ray/SKILL.md ================================================ --- name: debugging-output-and-previewing-html-using-ray description: Use when user says "send to Ray," "show in Ray," "debug in Ray," "log to Ray," "display in Ray," or wants to visualize data, debug output, or show diagrams in the Ray desktop application. metadata: author: Spatie tags: - debugging - logging - visualization - ray --- # Ray Skill ## Overview Ray is Spatie's desktop debugging application for developers. Send data directly to Ray by making HTTP requests to its local server. This can be useful for debugging applications, or to preview design, logos, or other visual content. This is what the `ray()` PHP function does under the hood. ## Connection Details | Setting | Default | Environment Variable | |---------|---------|---------------------| | Host | `localhost` | `RAY_HOST` | | Port | `23517` | `RAY_PORT` | | URL | `http://localhost:23517/` | - | ## Request Format **Method:** POST **Content-Type:** `application/json` **User-Agent:** `Ray 1.0` ### Basic Request Structure ```json { "uuid": "unique-identifier-for-this-ray-instance", "payloads": [ { "type": "log", "content": { }, "origin": { "file": "/path/to/file.php", "line_number": 42, "hostname": "my-machine" } } ], "meta": { "ray_package_version": "1.0.0" } } ``` ### Fields | Field | Type | Description | |-------|------|-------------| | `uuid` | string | Unique identifier for this Ray instance. Reuse the same UUID to update an existing entry. | | `payloads` | array | Array of payload objects to send | | `meta` | object | Optional metadata (ray_package_version, project_name, php_version) | ### Origin Object Every payload includes origin information: ```json { "file": "/Users/dev/project/app/Controller.php", "line_number": 42, "hostname": "dev-machine" } ``` ## Payload Types ### Log (Send Values) ```json { "type": "log", "content": { "values": ["Hello World", 42, {"key": "value"}] }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Custom (HTML/Text Content) ```json { "type": "custom", "content": { "content": "

HTML Content

With formatting

", "label": "My Label" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Table ```json { "type": "table", "content": { "values": {"name": "John", "email": "john@example.com", "age": 30}, "label": "User Data" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Color Set the color of the preceding log entry: ```json { "type": "color", "content": { "color": "green" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` **Available colors:** `green`, `orange`, `red`, `purple`, `blue`, `gray` ### Screen Color Set the background color of the screen: ```json { "type": "screen_color", "content": { "color": "green" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Label Add a label to the entry: ```json { "type": "label", "content": { "label": "Important" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Size Set the size of the entry: ```json { "type": "size", "content": { "size": "lg" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` **Available sizes:** `sm`, `lg` ### Notify (Desktop Notification) ```json { "type": "notify", "content": { "value": "Task completed!" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### New Screen ```json { "type": "new_screen", "content": { "name": "Debug Session" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Measure (Timing) ```json { "type": "measure", "content": { "name": "my-timer", "is_new_timer": true, "total_time": 0, "time_since_last_call": 0, "max_memory_usage_during_total_time": 0, "max_memory_usage_since_last_call": 0 }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` For subsequent measurements, set `is_new_timer: false` and provide actual timing values. ### Simple Payloads (No Content) These payloads only need a `type` and empty `content`: ```json { "type": "separator", "content": {}, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` | Type | Purpose | |------|---------| | `separator` | Add visual divider | | `clear_all` | Clear all entries | | `hide` | Hide this entry | | `remove` | Remove this entry | | `confetti` | Show confetti animation | | `show_app` | Bring Ray to foreground | | `hide_app` | Hide Ray window | ## Combining Multiple Payloads Send multiple payloads in one request. Use the same `uuid` to apply modifiers (color, label, size) to a log entry: ```json { "uuid": "abc-123", "payloads": [ { "type": "log", "content": { "values": ["Important message"] }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "color", "content": { "color": "red" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "label", "content": { "label": "ERROR" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "size", "content": { "size": "lg" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ], "meta": {} } ``` ## Example: Complete Request Send a green, labeled log message: ```bash curl -X POST http://localhost:23517/ \ -H "Content-Type: application/json" \ -H "User-Agent: Ray 1.0" \ -d '{ "uuid": "my-unique-id-123", "payloads": [ { "type": "log", "content": { "values": ["User logged in", {"user_id": 42, "name": "John"}] }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } }, { "type": "color", "content": { "color": "green" }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } }, { "type": "label", "content": { "label": "Auth" }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } } ], "meta": { "project_name": "my-app" } }' ``` ## Availability Check Before sending data, you can check if Ray is running: ``` GET http://localhost:23517/_availability_check ``` Ray responds with HTTP 404 when available (the endpoint doesn't exist, but the server is running). ## Getting Ray Information ### Get Windows Retrieve information about all open Ray windows: ``` GET http://localhost:23517/windows ``` Returns an array of window objects with their IDs and names: ```json [ {"id": 1, "name": "Window 1"}, {"id": 2, "name": "Debug Session"} ] ``` ### Get Theme Colors Retrieve the current theme colors being used by Ray: ``` GET http://localhost:23517/theme ``` Returns the theme information including color palette: ```json { "name": "Dark", "colors": { "primary": "#000000", "secondary": "#1a1a1a", "accent": "#3b82f6" } } ``` **Use Case:** When sending custom HTML content to Ray, use these theme colors to ensure your content matches Ray's current theme and looks visually integrated. **Example:** Send HTML with matching colors: ```bash # First, get the theme THEME=$(curl -s http://localhost:23517/theme) PRIMARY_COLOR=$(echo $THEME | jq -r '.colors.primary') # Then send HTML using those colors curl -X POST http://localhost:23517/ \ -H "Content-Type: application/json" \ -d '{ "uuid": "theme-matched-html", "payloads": [{ "type": "custom", "content": { "content": "

Themed Content

", "label": "Themed HTML" }, "origin": {"file": "script.sh", "line_number": 1, "hostname": "localhost"} }] }' ``` ## Payload Type Reference | Type | Content Fields | Purpose | |------|----------------|---------| | `log` | `values` (array) | Send values to Ray | | `custom` | `content`, `label` | HTML or text content | | `table` | `values`, `label` | Display as table | | `color` | `color` | Set entry color | | `screen_color` | `color` | Set screen background | | `label` | `label` | Add label to entry | | `size` | `size` | Set entry size (sm/lg) | | `notify` | `value` | Desktop notification | | `new_screen` | `name` | Create new screen | | `measure` | `name`, `is_new_timer`, timing fields | Performance timing | | `separator` | (empty) | Visual divider | | `clear_all` | (empty) | Clear all entries | | `hide` | (empty) | Hide entry | | `remove` | (empty) | Remove entry | | `confetti` | (empty) | Confetti animation | | `show_app` | (empty) | Show Ray window | | `hide_app` | (empty) | Hide Ray window | ================================================ FILE: .claude/skills/developing-with-fortify/SKILL.md ================================================ --- name: developing-with-fortify description: Laravel Fortify headless authentication backend development. Activate when implementing authentication features including login, registration, password reset, email verification, two-factor authentication (2FA/TOTP), profile updates, headless auth, authentication scaffolding, or auth guards in Laravel applications. --- # Laravel Fortify Development Fortify is a headless authentication backend that provides authentication routes and controllers for Laravel applications. ## Documentation Use `search-docs` for detailed Laravel Fortify patterns and documentation. ## Usage - **Routes**: Use `list-routes` with `only_vendor: true` and `action: "Fortify"` to see all registered endpoints - **Actions**: Check `app/Actions/Fortify/` for customizable business logic (user creation, password validation, etc.) - **Config**: See `config/fortify.php` for all options including features, guards, rate limiters, and username field - **Contracts**: Look in `Laravel\Fortify\Contracts\` for overridable response classes (`LoginResponse`, `LogoutResponse`, etc.) - **Views**: All view callbacks are set in `FortifyServiceProvider::boot()` using `Fortify::loginView()`, `Fortify::registerView()`, etc. ## Available Features Enable in `config/fortify.php` features array: - `Features::registration()` - User registration - `Features::resetPasswords()` - Password reset via email - `Features::emailVerification()` - Requires User to implement `MustVerifyEmail` - `Features::updateProfileInformation()` - Profile updates - `Features::updatePasswords()` - Password changes - `Features::twoFactorAuthentication()` - 2FA with QR codes and recovery codes > Use `search-docs` for feature configuration options and customization patterns. ## Setup Workflows ### Two-Factor Authentication Setup ``` - [ ] Add TwoFactorAuthenticatable trait to User model - [ ] Enable feature in config/fortify.php - [ ] Run migrations for 2FA columns - [ ] Set up view callbacks in FortifyServiceProvider - [ ] Create 2FA management UI - [ ] Test QR code and recovery codes ``` > Use `search-docs` for TOTP implementation and recovery code handling patterns. ### Email Verification Setup ``` - [ ] Enable emailVerification feature in config - [ ] Implement MustVerifyEmail interface on User model - [ ] Set up verifyEmailView callback - [ ] Add verified middleware to protected routes - [ ] Test verification email flow ``` > Use `search-docs` for MustVerifyEmail implementation patterns. ### Password Reset Setup ``` - [ ] Enable resetPasswords feature in config - [ ] Set up requestPasswordResetLinkView callback - [ ] Set up resetPasswordView callback - [ ] Define password.reset named route (if views disabled) - [ ] Test reset email and link flow ``` > Use `search-docs` for custom password reset flow patterns. ### SPA Authentication Setup ``` - [ ] Set 'views' => false in config/fortify.php - [ ] Install and configure Laravel Sanctum - [ ] Use 'web' guard in fortify config - [ ] Set up CSRF token handling - [ ] Test XHR authentication flows ``` > Use `search-docs` for integration and SPA authentication patterns. ## Best Practices ### Custom Authentication Logic Override authentication behavior using `Fortify::authenticateUsing()` for custom user retrieval or `Fortify::authenticateThrough()` to customize the authentication pipeline. Override response contracts in `AppServiceProvider` for custom redirects. ### Registration Customization Modify `app/Actions/Fortify/CreateNewUser.php` to customize user creation logic, validation rules, and additional fields. ### Rate Limiting Configure via `fortify.limiters.login` in config. Default configuration throttles by username + IP combination. ## Key Endpoints | Feature | Method | Endpoint | |------------------------|----------|---------------------------------------------| | Login | POST | `/login` | | Logout | POST | `/logout` | | Register | POST | `/register` | | Password Reset Request | POST | `/forgot-password` | | Password Reset | POST | `/reset-password` | | Email Verify Notice | GET | `/email/verify` | | Resend Verification | POST | `/email/verification-notification` | | Password Confirm | POST | `/user/confirm-password` | | Enable 2FA | POST | `/user/two-factor-authentication` | | Confirm 2FA | POST | `/user/confirmed-two-factor-authentication` | | 2FA Challenge | POST | `/two-factor-challenge` | | Get QR Code | GET | `/user/two-factor-qr-code` | | Recovery Codes | GET/POST | `/user/two-factor-recovery-codes` | ================================================ FILE: .claude/skills/livewire-development/SKILL.md ================================================ --- name: livewire-development description: >- Develops reactive Livewire 3 components. Activates when creating, updating, or modifying Livewire components; working with wire:model, wire:click, wire:loading, or any wire: directives; adding real-time updates, loading states, or reactivity; debugging component behavior; writing Livewire tests; or when the user mentions Livewire, component, counter, or reactive UI. --- # Livewire Development ## When to Apply Activate this skill when: - Creating new Livewire components - Modifying existing component state or behavior - Debugging reactivity or lifecycle issues - Writing Livewire component tests - Adding Alpine.js interactivity to components - Working with wire: directives ## Documentation Use `search-docs` for detailed Livewire 3 patterns and documentation. ## Basic Usage ### Creating Components Use the `php artisan make:livewire [Posts\CreatePost]` Artisan command to create new components. ### Fundamental Concepts - State should live on the server, with the UI reflecting it. - All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions. ## Livewire 3 Specifics ### Key Changes From Livewire 2 These things changed in Livewire 3, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions. - Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default. - Components now use the `App\Livewire` namespace (not `App\Http\Livewire`). - Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`). - Use the `components.layouts.app` view as the typical layout path (not `layouts.app`). ### New Directives - `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use. ### Alpine Integration - Alpine is now included with Livewire; don't manually include Alpine.js. - Plugins included with Alpine: persist, intersect, collapse, and focus. ## Best Practices ### Component Structure - Livewire components require a single root element. - Use `wire:loading` and `wire:dirty` for delightful loading states. ### Using Keys in Loops @foreach ($items as $item)
{{ $item->name }}
@endforeach
### Lifecycle Hooks Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects: public function mount(User $user) { $this->user = $user; } public function updatedSearch() { $this->resetPage(); } ## JavaScript Hooks You can listen for `livewire:init` to hook into Livewire initialization: document.addEventListener('livewire:init', function () { Livewire.hook('request', ({ fail }) => { if (fail && fail.status === 419) { alert('Your session expired'); } }); Livewire.hook('message.failed', (message, component) => { console.error(message); }); }); ## Testing Livewire::test(Counter::class) ->assertSet('count', 0) ->call('increment') ->assertSet('count', 1) ->assertSee(1) ->assertStatus(200); $this->get('/posts/create') ->assertSeeLivewire(CreatePost::class); ## Common Pitfalls - Forgetting `wire:key` in loops causes unexpected behavior when items change - Using `wire:model` expecting real-time updates (use `wire:model.live` instead in v3) - Not validating/authorizing in Livewire actions (treat them like HTTP requests) - Including Alpine.js separately when it's already bundled with Livewire 3 ================================================ FILE: .claude/skills/pest-testing/SKILL.md ================================================ --- name: pest-testing description: >- Tests applications using the Pest 4 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, browser testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. --- # Pest Testing 4 ## When to Apply Activate this skill when: - Creating new tests (unit, feature, or browser) - Modifying existing tests - Debugging test failures - Working with browser testing or smoke testing - Writing architecture tests or visual regression tests ## Documentation Use `search-docs` for detailed Pest 4 patterns and documentation. ## Test Directory Structure - `tests/Feature/` and `tests/Unit/` — Legacy tests (keep, don't delete) - `tests/v4/Feature/` — New feature tests (SQLite :memory: database) - `tests/v4/Browser/` — Browser tests (Pest Browser Plugin + Playwright) - `tests/Browser/` — Legacy Dusk browser tests (keep, don't delete) New tests go in `tests/v4/`. The v4 suite uses SQLite :memory: with a schema dump (`database/schema/testing-schema.sql`) instead of running migrations. Do NOT remove tests without approval. ## Running Tests - All v4 tests: `php artisan test --compact tests/v4/` - Browser tests: `php artisan test --compact tests/v4/Browser/` - Feature tests: `php artisan test --compact tests/v4/Feature/` - Specific file: `php artisan test --compact tests/v4/Browser/LoginTest.php` - Filter: `php artisan test --compact --filter=testName` - Headed (see browser): `./vendor/bin/pest tests/v4/Browser/ --headed` - Debug (pause on failure): `./vendor/bin/pest tests/v4/Browser/ --debug` ## Basic Test Structure it('is true', function () { expect(true)->toBeTrue(); }); ## Assertions Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: | Use | Instead of | |-----|------------| | `assertSuccessful()` | `assertStatus(200)` | | `assertNotFound()` | `assertStatus(404)` | | `assertForbidden()` | `assertStatus(403)` | ## Mocking Import mock function before use: `use function Pest\Laravel\mock;` ## Datasets Use datasets for repetitive tests: it('has emails', function (string $email) { expect($email)->not->toBeEmpty(); })->with([ 'james' => 'james@laravel.com', 'taylor' => 'taylor@laravel.com', ]); ## Browser Testing (Pest Browser Plugin + Playwright) Browser tests use `pestphp/pest-plugin-browser` with Playwright. They run **outside Docker** — the plugin starts an in-process HTTP server and Playwright browser automatically. ### Key Rules 1. **Always use `RefreshDatabase`** — the in-process server uses SQLite :memory: 2. **Always seed `InstanceSettings::create(['id' => 0])` in `beforeEach`** — most pages crash without it 3. **Use `User::factory()` for auth tests** — create users with `id => 0` for root user 4. **No Dusk, no Selenium** — use `visit()`, `fill()`, `click()`, `assertSee()` from the Pest Browser API 5. **Place tests in `tests/v4/Browser/`** 6. **Views with bare `function` declarations** will crash on the second request in the same process — wrap with `function_exists()` guard if you encounter this ### Browser Test Template 0]); }); it('can visit the page', function () { $page = visit('/login'); $page->assertSee('Login'); }); ### Browser Test with Form Interaction it('fails login with invalid credentials', function () { User::factory()->create([ 'id' => 0, 'email' => 'test@example.com', 'password' => Hash::make('password'), ]); $page = visit('/login'); $page->fill('email', 'random@email.com') ->fill('password', 'wrongpassword123') ->click('Login') ->assertSee('These credentials do not match our records'); }); ### Browser API Reference | Method | Purpose | |--------|---------| | `visit('/path')` | Navigate to a page | | `->fill('field', 'value')` | Fill an input by name | | `->click('Button Text')` | Click a button/link by text | | `->assertSee('text')` | Assert visible text | | `->assertDontSee('text')` | Assert text is not visible | | `->assertPathIs('/path')` | Assert current URL path | | `->assertSeeIn('.selector', 'text')` | Assert text in element | | `->screenshot()` | Capture screenshot | | `->debug()` | Pause test, keep browser open | | `->wait(seconds)` | Wait N seconds | ### Debugging - Screenshots auto-saved to `tests/Browser/Screenshots/` on failure - `->debug()` pauses and keeps browser open (press Enter to continue) - `->screenshot()` captures state at any point - `--headed` flag shows browser, `--debug` pauses on failure ## SQLite Testing Setup v4 tests use SQLite :memory: instead of PostgreSQL. Schema loaded from `database/schema/testing-schema.sql`. ### Regenerating the Schema When migrations change, regenerate from the running PostgreSQL database: ```bash docker exec coolify php artisan schema:generate-testing ``` ## Architecture Testing arch('controllers') ->expect('App\Http\Controllers') ->toExtendNothing() ->toHaveSuffix('Controller'); ## Common Pitfalls - Not importing `use function Pest\Laravel\mock;` before using mock - Using `assertStatus(200)` instead of `assertSuccessful()` - Forgetting datasets for repetitive validation tests - Deleting tests without approval - Forgetting `assertNoJavaScriptErrors()` in browser tests - **Browser tests: forgetting `InstanceSettings::create(['id' => 0])` — most pages crash without it** - **Browser tests: forgetting `RefreshDatabase` — SQLite :memory: starts empty** - **Browser tests: views with bare `function` declarations crash on second request — wrap with `function_exists()` guard** ================================================ FILE: .claude/skills/tailwindcss-development/SKILL.md ================================================ --- name: tailwindcss-development description: >- Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. --- # Tailwind CSS Development ## When to Apply Activate this skill when: - Adding styles to components or pages - Working with responsive design - Implementing dark mode - Extracting repeated patterns into components - Debugging spacing or layout issues ## Documentation Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. ## Basic Usage - Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. - Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). - Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. ## Tailwind CSS v4 Specifics - Always use Tailwind CSS v4 and avoid deprecated utilities. - `corePlugins` is not supported in Tailwind v4. ### CSS-First Configuration In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: @theme { --color-brand: oklch(0.72 0.11 178); } ### Import Syntax In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: - @tailwind base; - @tailwind components; - @tailwind utilities; + @import "tailwindcss"; ### Replaced Utilities Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain numeric. | Deprecated | Replacement | |------------|-------------| | bg-opacity-* | bg-black/* | | text-opacity-* | text-black/* | | border-opacity-* | border-black/* | | divide-opacity-* | divide-black/* | | ring-opacity-* | ring-black/* | | placeholder-opacity-* | placeholder-black/* | | flex-shrink-* | shrink-* | | flex-grow-* | grow-* | | overflow-ellipsis | text-ellipsis | | decoration-slice | box-decoration-slice | | decoration-clone | box-decoration-clone | ## Spacing Use `gap` utilities instead of margins for spacing between siblings:
Item 1
Item 2
## Dark Mode If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant:
Content adapts to color scheme
## Common Patterns ### Flexbox Layout
Left content
Right content
### Grid Layout
Card 1
Card 2
Card 3
## Common Pitfalls - Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) - Using `@tailwind` directives instead of `@import "tailwindcss"` - Trying to use `tailwind.config.js` instead of CSS `@theme` directive - Using margins for spacing between siblings instead of gap utilities - Forgetting to add dark mode variants when the project uses dark mode ================================================ FILE: .codex/config.toml ================================================ [mcp_servers.laravel-boost] command = "php" args = ["artisan", "boost:mcp"] cwd = "/Users/heyandras/devel/coolify" ================================================ FILE: .coolify-logo ================================================ _____ _ _ __ / ____| | (_)/ _| | | ___ ___ | |_| |_ _ _ | | / _ \ / _ \| | | _| | | | | |___| (_) | (_) | | | | | |_| | \_____\___/ \___/|_|_|_| \__, | __/ | |___/ ================================================ FILE: .cursor/mcp.json ================================================ { "mcpServers": { "laravel-boost": { "command": "php", "args": [ "artisan", "boost:mcp" ] } } } ================================================ FILE: .cursor/rules/coolify-ai-docs.mdc ================================================ --- title: Coolify AI Documentation description: Master reference to all Coolify AI documentation in .ai/ directory globs: **/* alwaysApply: true --- # Coolify AI Documentation All Coolify AI documentation has been consolidated in the **`.ai/`** directory for better organization and single source of truth. ## Quick Start - **For Claude Code**: Start with `CLAUDE.md` in the root directory - **For Cursor IDE**: Start with `.ai/README.md` for navigation - **For All AI Tools**: Browse `.ai/` directory by topic ## Documentation Structure All detailed documentation lives in `.ai/` with the following organization: ### 📚 Core Documentation - **[Technology Stack](.ai/core/technology-stack.md)** - All versions, packages, dependencies (SINGLE SOURCE OF TRUTH for versions) - **[Project Overview](.ai/core/project-overview.md)** - What Coolify is, high-level architecture - **[Application Architecture](.ai/core/application-architecture.md)** - System design, components, relationships - **[Deployment Architecture](.ai/core/deployment-architecture.md)** - Deployment flows, Docker, proxies ### 💻 Development - **[Development Workflow](.ai/development/development-workflow.md)** - Dev setup, commands, daily workflows - **[Testing Patterns](.ai/development/testing-patterns.md)** - How to write/run tests, Docker requirements - **[Laravel Boost](.ai/development/laravel-boost.md)** - Laravel-specific guidelines (SINGLE SOURCE for Laravel Boost) ### 🎨 Code Patterns - **[Database Patterns](.ai/patterns/database-patterns.md)** - Eloquent, migrations, relationships - **[Frontend Patterns](.ai/patterns/frontend-patterns.md)** - Livewire, Alpine.js, Tailwind CSS - **[Security Patterns](.ai/patterns/security-patterns.md)** - Auth, authorization, security - **[Form Components](.ai/patterns/form-components.md)** - Enhanced forms with authorization - **[API & Routing](.ai/patterns/api-and-routing.md)** - API design, routing conventions ### 📖 Meta - **[Maintaining Docs](.ai/meta/maintaining-docs.md)** - How to update/improve documentation - **[Sync Guide](.ai/meta/sync-guide.md)** - Keeping docs synchronized ## Quick Decision Tree **What are you working on?** ### Running Commands → `.ai/development/development-workflow.md` - `npm run dev` / `npm run build` - Frontend - `php artisan serve` / `php artisan migrate` - Backend - `docker exec coolify php artisan test` - Feature tests (requires Docker) - `./vendor/bin/pest tests/Unit` - Unit tests (no Docker needed) - `./vendor/bin/pint` - Code formatting ### Writing Tests → `.ai/development/testing-patterns.md` - **Unit tests**: No database, use mocking, run outside Docker - **Feature tests**: Can use database, MUST run inside Docker - Critical: Docker execution requirements prevent database connection errors ### Building UI → `.ai/patterns/frontend-patterns.md` + `.ai/patterns/form-components.md` - Livewire 3.5.20 with server-side state - Alpine.js for client interactions - Tailwind CSS 4.1.4 styling - Form components with `canGate` authorization ### Database Work → `.ai/patterns/database-patterns.md` - Eloquent ORM patterns - Migration best practices - Relationship definitions - Query optimization ### Security & Authorization → `.ai/patterns/security-patterns.md` + `.ai/patterns/form-components.md` - Team-based access control - Policy and gate patterns - Form authorization (`canGate`, `canResource`) - API security with Sanctum ### Laravel-Specific → `.ai/development/laravel-boost.md` - Laravel 12.4.1 patterns - Livewire 3 best practices - Pest testing patterns - Laravel conventions ### Version Numbers → `.ai/core/technology-stack.md` - **SINGLE SOURCE OF TRUTH** for all version numbers - Laravel 12.4.1, PHP 8.4.7, Tailwind 4.1.4, etc. - Never duplicate versions - always reference this file ## Critical Patterns (Always Follow) ### Testing Commands ```bash # Unit tests (no database, outside Docker) ./vendor/bin/pest tests/Unit # Feature tests (requires database, inside Docker) docker exec coolify php artisan test ``` **NEVER** run Feature tests outside Docker - they will fail with database connection errors. ### Form Authorization ALWAYS include authorization on form components: ```blade ``` ### Livewire Components MUST have exactly ONE root element. No exceptions. ### Version Numbers Use exact versions from `technology-stack.md`: - ✅ Laravel 12.4.1 - ❌ Laravel 12 or "v12" ### Code Style ```bash # Always run before committing ./vendor/bin/pint ``` ## For AI Assistants ### Important Notes 1. **Single Source of Truth**: Each piece of information exists in ONE location only 2. **Cross-Reference, Don't Duplicate**: Link to other files instead of copying content 3. **Version Precision**: Always use exact versions from `technology-stack.md` 4. **Docker for Feature Tests**: This is non-negotiable for database-dependent tests 5. **Form Authorization**: Security requirement, not optional ### When to Use Which File - **Quick commands**: `CLAUDE.md` or `development-workflow.md` - **Detailed patterns**: Topic-specific files in `.ai/patterns/` - **Testing**: `.ai/development/testing-patterns.md` - **Laravel specifics**: `.ai/development/laravel-boost.md` - **Versions**: `.ai/core/technology-stack.md` ## Maintaining Documentation When updating documentation: 1. Read `.ai/meta/maintaining-docs.md` first 2. Follow single source of truth principle 3. Update cross-references when moving content 4. Test all links work 5. See `.ai/meta/sync-guide.md` for sync guidelines ## Migration Note This file replaces all previous `.cursor/rules/*.mdc` files. All content has been migrated to `.ai/` directory for better organization and to serve as single source of truth for all AI tools (Claude Code, Cursor IDE, etc.). ================================================ FILE: .cursor/skills/debugging-output-and-previewing-html-using-ray/SKILL.md ================================================ --- name: debugging-output-and-previewing-html-using-ray description: Use when user says "send to Ray," "show in Ray," "debug in Ray," "log to Ray," "display in Ray," or wants to visualize data, debug output, or show diagrams in the Ray desktop application. metadata: author: Spatie tags: - debugging - logging - visualization - ray --- # Ray Skill ## Overview Ray is Spatie's desktop debugging application for developers. Send data directly to Ray by making HTTP requests to its local server. This can be useful for debugging applications, or to preview design, logos, or other visual content. This is what the `ray()` PHP function does under the hood. ## Connection Details | Setting | Default | Environment Variable | |---------|---------|---------------------| | Host | `localhost` | `RAY_HOST` | | Port | `23517` | `RAY_PORT` | | URL | `http://localhost:23517/` | - | ## Request Format **Method:** POST **Content-Type:** `application/json` **User-Agent:** `Ray 1.0` ### Basic Request Structure ```json { "uuid": "unique-identifier-for-this-ray-instance", "payloads": [ { "type": "log", "content": { }, "origin": { "file": "/path/to/file.php", "line_number": 42, "hostname": "my-machine" } } ], "meta": { "ray_package_version": "1.0.0" } } ``` ### Fields | Field | Type | Description | |-------|------|-------------| | `uuid` | string | Unique identifier for this Ray instance. Reuse the same UUID to update an existing entry. | | `payloads` | array | Array of payload objects to send | | `meta` | object | Optional metadata (ray_package_version, project_name, php_version) | ### Origin Object Every payload includes origin information: ```json { "file": "/Users/dev/project/app/Controller.php", "line_number": 42, "hostname": "dev-machine" } ``` ## Payload Types ### Log (Send Values) ```json { "type": "log", "content": { "values": ["Hello World", 42, {"key": "value"}] }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Custom (HTML/Text Content) ```json { "type": "custom", "content": { "content": "

HTML Content

With formatting

", "label": "My Label" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Table ```json { "type": "table", "content": { "values": {"name": "John", "email": "john@example.com", "age": 30}, "label": "User Data" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Color Set the color of the preceding log entry: ```json { "type": "color", "content": { "color": "green" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` **Available colors:** `green`, `orange`, `red`, `purple`, `blue`, `gray` ### Screen Color Set the background color of the screen: ```json { "type": "screen_color", "content": { "color": "green" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Label Add a label to the entry: ```json { "type": "label", "content": { "label": "Important" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Size Set the size of the entry: ```json { "type": "size", "content": { "size": "lg" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` **Available sizes:** `sm`, `lg` ### Notify (Desktop Notification) ```json { "type": "notify", "content": { "value": "Task completed!" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### New Screen ```json { "type": "new_screen", "content": { "name": "Debug Session" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` ### Measure (Timing) ```json { "type": "measure", "content": { "name": "my-timer", "is_new_timer": true, "total_time": 0, "time_since_last_call": 0, "max_memory_usage_during_total_time": 0, "max_memory_usage_since_last_call": 0 }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` For subsequent measurements, set `is_new_timer: false` and provide actual timing values. ### Simple Payloads (No Content) These payloads only need a `type` and empty `content`: ```json { "type": "separator", "content": {}, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ``` | Type | Purpose | |------|---------| | `separator` | Add visual divider | | `clear_all` | Clear all entries | | `hide` | Hide this entry | | `remove` | Remove this entry | | `confetti` | Show confetti animation | | `show_app` | Bring Ray to foreground | | `hide_app` | Hide Ray window | ## Combining Multiple Payloads Send multiple payloads in one request. Use the same `uuid` to apply modifiers (color, label, size) to a log entry: ```json { "uuid": "abc-123", "payloads": [ { "type": "log", "content": { "values": ["Important message"] }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "color", "content": { "color": "red" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "label", "content": { "label": "ERROR" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } }, { "type": "size", "content": { "size": "lg" }, "origin": { "file": "test.php", "line_number": 1, "hostname": "localhost" } } ], "meta": {} } ``` ## Example: Complete Request Send a green, labeled log message: ```bash curl -X POST http://localhost:23517/ \ -H "Content-Type: application/json" \ -H "User-Agent: Ray 1.0" \ -d '{ "uuid": "my-unique-id-123", "payloads": [ { "type": "log", "content": { "values": ["User logged in", {"user_id": 42, "name": "John"}] }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } }, { "type": "color", "content": { "color": "green" }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } }, { "type": "label", "content": { "label": "Auth" }, "origin": { "file": "/app/AuthController.php", "line_number": 55, "hostname": "dev-server" } } ], "meta": { "project_name": "my-app" } }' ``` ## Availability Check Before sending data, you can check if Ray is running: ``` GET http://localhost:23517/_availability_check ``` Ray responds with HTTP 404 when available (the endpoint doesn't exist, but the server is running). ## Getting Ray Information ### Get Windows Retrieve information about all open Ray windows: ``` GET http://localhost:23517/windows ``` Returns an array of window objects with their IDs and names: ```json [ {"id": 1, "name": "Window 1"}, {"id": 2, "name": "Debug Session"} ] ``` ### Get Theme Colors Retrieve the current theme colors being used by Ray: ``` GET http://localhost:23517/theme ``` Returns the theme information including color palette: ```json { "name": "Dark", "colors": { "primary": "#000000", "secondary": "#1a1a1a", "accent": "#3b82f6" } } ``` **Use Case:** When sending custom HTML content to Ray, use these theme colors to ensure your content matches Ray's current theme and looks visually integrated. **Example:** Send HTML with matching colors: ```bash # First, get the theme THEME=$(curl -s http://localhost:23517/theme) PRIMARY_COLOR=$(echo $THEME | jq -r '.colors.primary') # Then send HTML using those colors curl -X POST http://localhost:23517/ \ -H "Content-Type: application/json" \ -d '{ "uuid": "theme-matched-html", "payloads": [{ "type": "custom", "content": { "content": "

Themed Content

", "label": "Themed HTML" }, "origin": {"file": "script.sh", "line_number": 1, "hostname": "localhost"} }] }' ``` ## Payload Type Reference | Type | Content Fields | Purpose | |------|----------------|---------| | `log` | `values` (array) | Send values to Ray | | `custom` | `content`, `label` | HTML or text content | | `table` | `values`, `label` | Display as table | | `color` | `color` | Set entry color | | `screen_color` | `color` | Set screen background | | `label` | `label` | Add label to entry | | `size` | `size` | Set entry size (sm/lg) | | `notify` | `value` | Desktop notification | | `new_screen` | `name` | Create new screen | | `measure` | `name`, `is_new_timer`, timing fields | Performance timing | | `separator` | (empty) | Visual divider | | `clear_all` | (empty) | Clear all entries | | `hide` | (empty) | Hide entry | | `remove` | (empty) | Remove entry | | `confetti` | (empty) | Confetti animation | | `show_app` | (empty) | Show Ray window | | `hide_app` | (empty) | Hide Ray window | ================================================ FILE: .cursor/skills/developing-with-fortify/SKILL.md ================================================ --- name: developing-with-fortify description: Laravel Fortify headless authentication backend development. Activate when implementing authentication features including login, registration, password reset, email verification, two-factor authentication (2FA/TOTP), profile updates, headless auth, authentication scaffolding, or auth guards in Laravel applications. --- # Laravel Fortify Development Fortify is a headless authentication backend that provides authentication routes and controllers for Laravel applications. ## Documentation Use `search-docs` for detailed Laravel Fortify patterns and documentation. ## Usage - **Routes**: Use `list-routes` with `only_vendor: true` and `action: "Fortify"` to see all registered endpoints - **Actions**: Check `app/Actions/Fortify/` for customizable business logic (user creation, password validation, etc.) - **Config**: See `config/fortify.php` for all options including features, guards, rate limiters, and username field - **Contracts**: Look in `Laravel\Fortify\Contracts\` for overridable response classes (`LoginResponse`, `LogoutResponse`, etc.) - **Views**: All view callbacks are set in `FortifyServiceProvider::boot()` using `Fortify::loginView()`, `Fortify::registerView()`, etc. ## Available Features Enable in `config/fortify.php` features array: - `Features::registration()` - User registration - `Features::resetPasswords()` - Password reset via email - `Features::emailVerification()` - Requires User to implement `MustVerifyEmail` - `Features::updateProfileInformation()` - Profile updates - `Features::updatePasswords()` - Password changes - `Features::twoFactorAuthentication()` - 2FA with QR codes and recovery codes > Use `search-docs` for feature configuration options and customization patterns. ## Setup Workflows ### Two-Factor Authentication Setup ``` - [ ] Add TwoFactorAuthenticatable trait to User model - [ ] Enable feature in config/fortify.php - [ ] Run migrations for 2FA columns - [ ] Set up view callbacks in FortifyServiceProvider - [ ] Create 2FA management UI - [ ] Test QR code and recovery codes ``` > Use `search-docs` for TOTP implementation and recovery code handling patterns. ### Email Verification Setup ``` - [ ] Enable emailVerification feature in config - [ ] Implement MustVerifyEmail interface on User model - [ ] Set up verifyEmailView callback - [ ] Add verified middleware to protected routes - [ ] Test verification email flow ``` > Use `search-docs` for MustVerifyEmail implementation patterns. ### Password Reset Setup ``` - [ ] Enable resetPasswords feature in config - [ ] Set up requestPasswordResetLinkView callback - [ ] Set up resetPasswordView callback - [ ] Define password.reset named route (if views disabled) - [ ] Test reset email and link flow ``` > Use `search-docs` for custom password reset flow patterns. ### SPA Authentication Setup ``` - [ ] Set 'views' => false in config/fortify.php - [ ] Install and configure Laravel Sanctum - [ ] Use 'web' guard in fortify config - [ ] Set up CSRF token handling - [ ] Test XHR authentication flows ``` > Use `search-docs` for integration and SPA authentication patterns. ## Best Practices ### Custom Authentication Logic Override authentication behavior using `Fortify::authenticateUsing()` for custom user retrieval or `Fortify::authenticateThrough()` to customize the authentication pipeline. Override response contracts in `AppServiceProvider` for custom redirects. ### Registration Customization Modify `app/Actions/Fortify/CreateNewUser.php` to customize user creation logic, validation rules, and additional fields. ### Rate Limiting Configure via `fortify.limiters.login` in config. Default configuration throttles by username + IP combination. ## Key Endpoints | Feature | Method | Endpoint | |------------------------|----------|---------------------------------------------| | Login | POST | `/login` | | Logout | POST | `/logout` | | Register | POST | `/register` | | Password Reset Request | POST | `/forgot-password` | | Password Reset | POST | `/reset-password` | | Email Verify Notice | GET | `/email/verify` | | Resend Verification | POST | `/email/verification-notification` | | Password Confirm | POST | `/user/confirm-password` | | Enable 2FA | POST | `/user/two-factor-authentication` | | Confirm 2FA | POST | `/user/confirmed-two-factor-authentication` | | 2FA Challenge | POST | `/two-factor-challenge` | | Get QR Code | GET | `/user/two-factor-qr-code` | | Recovery Codes | GET/POST | `/user/two-factor-recovery-codes` | ================================================ FILE: .cursor/skills/livewire-development/SKILL.md ================================================ --- name: livewire-development description: >- Develops reactive Livewire 3 components. Activates when creating, updating, or modifying Livewire components; working with wire:model, wire:click, wire:loading, or any wire: directives; adding real-time updates, loading states, or reactivity; debugging component behavior; writing Livewire tests; or when the user mentions Livewire, component, counter, or reactive UI. --- # Livewire Development ## When to Apply Activate this skill when: - Creating new Livewire components - Modifying existing component state or behavior - Debugging reactivity or lifecycle issues - Writing Livewire component tests - Adding Alpine.js interactivity to components - Working with wire: directives ## Documentation Use `search-docs` for detailed Livewire 3 patterns and documentation. ## Basic Usage ### Creating Components Use the `php artisan make:livewire [Posts\CreatePost]` Artisan command to create new components. ### Fundamental Concepts - State should live on the server, with the UI reflecting it. - All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions. ## Livewire 3 Specifics ### Key Changes From Livewire 2 These things changed in Livewire 3, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions. - Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default. - Components now use the `App\Livewire` namespace (not `App\Http\Livewire`). - Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`). - Use the `components.layouts.app` view as the typical layout path (not `layouts.app`). ### New Directives - `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use. ### Alpine Integration - Alpine is now included with Livewire; don't manually include Alpine.js. - Plugins included with Alpine: persist, intersect, collapse, and focus. ## Best Practices ### Component Structure - Livewire components require a single root element. - Use `wire:loading` and `wire:dirty` for delightful loading states. ### Using Keys in Loops @foreach ($items as $item)
{{ $item->name }}
@endforeach
### Lifecycle Hooks Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects: public function mount(User $user) { $this->user = $user; } public function updatedSearch() { $this->resetPage(); } ## JavaScript Hooks You can listen for `livewire:init` to hook into Livewire initialization: document.addEventListener('livewire:init', function () { Livewire.hook('request', ({ fail }) => { if (fail && fail.status === 419) { alert('Your session expired'); } }); Livewire.hook('message.failed', (message, component) => { console.error(message); }); }); ## Testing Livewire::test(Counter::class) ->assertSet('count', 0) ->call('increment') ->assertSet('count', 1) ->assertSee(1) ->assertStatus(200); $this->get('/posts/create') ->assertSeeLivewire(CreatePost::class); ## Common Pitfalls - Forgetting `wire:key` in loops causes unexpected behavior when items change - Using `wire:model` expecting real-time updates (use `wire:model.live` instead in v3) - Not validating/authorizing in Livewire actions (treat them like HTTP requests) - Including Alpine.js separately when it's already bundled with Livewire 3 ================================================ FILE: .cursor/skills/pest-testing/SKILL.md ================================================ --- name: pest-testing description: >- Tests applications using the Pest 4 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, browser testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. --- # Pest Testing 4 ## When to Apply Activate this skill when: - Creating new tests (unit, feature, or browser) - Modifying existing tests - Debugging test failures - Working with browser testing or smoke testing - Writing architecture tests or visual regression tests ## Documentation Use `search-docs` for detailed Pest 4 patterns and documentation. ## Basic Usage ### Creating Tests All tests must be written using Pest. Use `php artisan make:test --pest {name}`. ### Test Organization - Unit/Feature tests: `tests/Feature` and `tests/Unit` directories. - Browser tests: `tests/Browser/` directory. - Do NOT remove tests without approval - these are core application code. ### Basic Test Structure it('is true', function () { expect(true)->toBeTrue(); }); ### Running Tests - Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`. - Run all tests: `php artisan test --compact`. - Run file: `php artisan test --compact tests/Feature/ExampleTest.php`. ## Assertions Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`: it('returns all', function () { $this->postJson('/api/docs', [])->assertSuccessful(); }); | Use | Instead of | |-----|------------| | `assertSuccessful()` | `assertStatus(200)` | | `assertNotFound()` | `assertStatus(404)` | | `assertForbidden()` | `assertStatus(403)` | ## Mocking Import mock function before use: `use function Pest\Laravel\mock;` ## Datasets Use datasets for repetitive tests (validation rules, etc.): it('has emails', function (string $email) { expect($email)->not->toBeEmpty(); })->with([ 'james' => 'james@laravel.com', 'taylor' => 'taylor@laravel.com', ]); ## Pest 4 Features | Feature | Purpose | |---------|---------| | Browser Testing | Full integration tests in real browsers | | Smoke Testing | Validate multiple pages quickly | | Visual Regression | Compare screenshots for visual changes | | Test Sharding | Parallel CI runs | | Architecture Testing | Enforce code conventions | ### Browser Test Example Browser tests run in real browsers for full integration testing: - Browser tests live in `tests/Browser/`. - Use Laravel features like `Event::fake()`, `assertAuthenticated()`, and model factories. - Use `RefreshDatabase` for clean state per test. - Interact with page: click, type, scroll, select, submit, drag-and-drop, touch gestures. - Test on multiple browsers (Chrome, Firefox, Safari) if requested. - Test on different devices/viewports (iPhone 14 Pro, tablets) if requested. - Switch color schemes (light/dark mode) when appropriate. - Take screenshots or pause tests for debugging. it('may reset the password', function () { Notification::fake(); $this->actingAs(User::factory()->create()); $page = visit('/sign-in'); $page->assertSee('Sign In') ->assertNoJavaScriptErrors() ->click('Forgot Password?') ->fill('email', 'nuno@laravel.com') ->click('Send Reset Link') ->assertSee('We have emailed your password reset link!'); Notification::assertSent(ResetPassword::class); }); ### Smoke Testing Quickly validate multiple pages have no JavaScript errors: $pages = visit(['/', '/about', '/contact']); $pages->assertNoJavaScriptErrors()->assertNoConsoleLogs(); ### Visual Regression Testing Capture and compare screenshots to detect visual changes. ### Test Sharding Split tests across parallel processes for faster CI runs. ### Architecture Testing Pest 4 includes architecture testing (from Pest 3): arch('controllers') ->expect('App\Http\Controllers') ->toExtendNothing() ->toHaveSuffix('Controller'); ## Common Pitfalls - Not importing `use function Pest\Laravel\mock;` before using mock - Using `assertStatus(200)` instead of `assertSuccessful()` - Forgetting datasets for repetitive validation tests - Deleting tests without approval - Forgetting `assertNoJavaScriptErrors()` in browser tests ================================================ FILE: .cursor/skills/tailwindcss-development/SKILL.md ================================================ --- name: tailwindcss-development description: >- Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. --- # Tailwind CSS Development ## When to Apply Activate this skill when: - Adding styles to components or pages - Working with responsive design - Implementing dark mode - Extracting repeated patterns into components - Debugging spacing or layout issues ## Documentation Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation. ## Basic Usage - Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns. - Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue). - Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically. ## Tailwind CSS v4 Specifics - Always use Tailwind CSS v4 and avoid deprecated utilities. - `corePlugins` is not supported in Tailwind v4. ### CSS-First Configuration In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed: @theme { --color-brand: oklch(0.72 0.11 178); } ### Import Syntax In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3: - @tailwind base; - @tailwind components; - @tailwind utilities; + @import "tailwindcss"; ### Replaced Utilities Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain numeric. | Deprecated | Replacement | |------------|-------------| | bg-opacity-* | bg-black/* | | text-opacity-* | text-black/* | | border-opacity-* | border-black/* | | divide-opacity-* | divide-black/* | | ring-opacity-* | ring-black/* | | placeholder-opacity-* | placeholder-black/* | | flex-shrink-* | shrink-* | | flex-grow-* | grow-* | | overflow-ellipsis | text-ellipsis | | decoration-slice | box-decoration-slice | | decoration-clone | box-decoration-clone | ## Spacing Use `gap` utilities instead of margins for spacing between siblings:
Item 1
Item 2
## Dark Mode If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant:
Content adapts to color scheme
## Common Patterns ### Flexbox Layout
Left content
Right content
### Grid Layout
Card 1
Card 2
Card 3
## Common Pitfalls - Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) - Using `@tailwind` directives instead of `@import "tailwindcss"` - Trying to use `tailwind.config.js` instead of CSS `@theme` directive - Using margins for spacing between siblings instead of gap utilities - Forgetting to add dark mode variants when the project uses dark mode ================================================ FILE: .dockerignore ================================================ /.phpunit.cache /node_modules /public/build /public/hot /public/storage /vendor .env .env.backup .env.secrets .phpunit.result.cache Homestead.json Homestead.yaml auth.json npm-debug.log yarn-error.log /.fleet /.idea /.vscode /.npm /.bash_history /_data .rnd /.ssh .ignition.json .env.dusk.local docker/coolify-realtime/node_modules /storage/*.key /storage/app/backups /storage/app/ssh/keys /storage/app/ssh/mux /storage/app/tmp /storage/app/debugbar /storage/logs /storage/pail ================================================ FILE: .editorconfig ================================================ 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 ================================================ FILE: .gitattributes ================================================ * 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 ================================================ FILE: .github/FUNDING.yaml ================================================ open_collective: coollabsio github: coollabsio ================================================ FILE: .github/ISSUE_TEMPLATE/01_BUG_REPORT.yml ================================================ name: 🐞 Bug Report description: "File a new bug report." title: "[Bug]: " labels: ["🐛 Bug", "🔍 Triage"] body: - type: markdown attributes: value: | > [!IMPORTANT] > **Please ensure you are using the latest version of Coolify before submitting an issue, as the bug may have already been fixed in a recent update.** (Of course, if you're experiencing an issue on the latest version that wasn't present in a previous version, please let us know.) # 💎 Bounty Program (with [algora.io](https://console.algora.io/org/coollabsio/bounties/new)) - If you would like to prioritize the issue resolution, consider adding a bounty to this issue through our [Bounty Program](https://console.algora.io/org/coollabsio/bounties/new). - type: textarea attributes: label: Error Message and Logs description: Provide a detailed description of the error or exception you encountered, along with any relevant log output. validations: required: true - type: textarea attributes: label: Steps to Reproduce description: Please provide a step-by-step guide to reproduce the issue. Be as detailed as possible, otherwise we may not be able to assist you. value: | 1. 2. 3. 4. validations: required: true - type: input attributes: label: Example Repository URL description: If applicable, provide a URL to a repository demonstrating the issue. - type: input attributes: label: Coolify Version description: Please provide the Coolify version you are using. This can be found in the top left corner of your Coolify dashboard. placeholder: "v4.0.0-beta.335" validations: required: true - type: dropdown attributes: label: Are you using Coolify Cloud? options: - "No (self-hosted)" - "Yes (Coolify Cloud)" validations: required: true - type: input attributes: label: Operating System and Version (self-hosted) description: Run `cat /etc/os-release` or `lsb_release -a` in your terminal and provide the operating system and version. placeholder: "Ubuntu 22.04" - type: textarea attributes: label: Additional Information description: Any other relevant details about the issue. ================================================ FILE: .github/ISSUE_TEMPLATE/02_ENHANCEMENT_BOUNTY.yml ================================================ name: 💎 Enhancement Bounty description: "Propose a new feature, service, or improvement with an attached bounty." title: "[Enhancement]: " labels: ["✨ Enhancement", "🔍 Triage"] body: - type: markdown attributes: value: | > [!IMPORTANT] > **This issue template is exclusively for proposing new features, services, or improvements with an attached bounty.** Enhancements without a bounty can be discussed in the appropriate category of [Github Discussions](https://github.com/coollabsio/coolify/discussions). # 💎 Add a Bounty (with [algora.io](https://console.algora.io/org/coollabsio/bounties/new)) - [Click here to add the required bounty](https://console.algora.io/org/coollabsio/bounties/new) - type: dropdown attributes: label: Request Type description: Select the type of request you are making. options: - New Feature - New Service - Improvement validations: required: true - type: textarea attributes: label: Description description: Provide a detailed description of the feature, improvement, or service you are proposing. validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: 🤔 Questions and Community Support url: https://coollabs.io/discord about: If you have any questions, reach out to us on Discord inside the "#support" channel. - name: 💡 Feature Request url: https://github.com/coollabsio/coolify/discussions/categories/feature-requests about: Suggest a new feature for Coolify. - name: ⚙️ Service Request url: https://github.com/coollabsio/coolify/discussions/categories/service-requests about: Request a new service integration for Coolify. - name: 🔧 Improvements url: https://github.com/coollabsio/coolify/discussions/categories/improvements about: Suggest improvements to existing features for Coolify. ================================================ FILE: .github/pull_request_template.md ================================================ ## Changes - ## Issues - Fixes ## Category - [ ] Bug fix - [ ] Improvement - [ ] New feature - [ ] Adding new one click service - [ ] Fixing or updating existing one click service ## Preview ## AI Assistance - [ ] AI was NOT used to create this PR - [ ] AI was used (please describe below) **If AI was used:** - Tools used: - How extensively: ## Testing ## Contributor Agreement > [!IMPORTANT] > > - [ ] I have read and understood the [contributor guidelines](https://github.com/coollabsio/coolify/blob/v4.x/CONTRIBUTING.md). If I have failed to follow any guideline, I understand that this PR may be closed without review. > - [ ] I have searched [existing issues](https://github.com/coollabsio/coolify/issues) and [pull requests](https://github.com/coollabsio/coolify/pulls) (including closed ones) to ensure this isn't a duplicate. > - [ ] I have tested all the changes thoroughly with a local development instance of Coolify and I am confident that they will work as expected when a maintainer tests them. ================================================ FILE: .github/workflows/chore-lock-closed-issues-discussions-and-prs.yml ================================================ name: Lock closed Issues, Discussions, and PRs on: schedule: - cron: '0 1 * * *' permissions: issues: write discussions: write pull-requests: write jobs: lock-threads: runs-on: ubuntu-latest steps: - name: Lock threads after 30 days of inactivity uses: dessant/lock-threads@v5 with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-inactive-days: '30' discussion-inactive-days: '30' pr-inactive-days: '30' ================================================ FILE: .github/workflows/chore-manage-stale-issues-and-prs.yml ================================================ name: Manage Stale Issues and PRs on: schedule: - cron: '0 2 * * *' permissions: issues: write pull-requests: write jobs: manage-stale: runs-on: ubuntu-latest steps: - name: Manage stale issues and PRs uses: actions/stale@v9 id: stale with: stale-issue-message: 'This issue will be automatically closed in a few days if no response is received. Please provide an update with the requested information.' stale-pr-message: 'This pull request requires attention. If no changes or response is received within the next few days, it will be automatically closed. Please update your PR or leave a comment with the requested information.' close-issue-message: 'This issue has been automatically closed due to inactivity.' close-pr-message: 'Thank you for your contribution. Due to inactivity, this PR was automatically closed. If you would like to continue working on this change in the future, feel free to reopen this PR or submit a new one.' days-before-stale: 14 days-before-close: 7 stale-issue-label: '⏱︎ Stale' stale-pr-label: '⏱︎ Stale' only-labels: '💤 Waiting for feedback, 💤 Waiting for changes' remove-stale-when-updated: true operations-per-run: 100 labels-to-remove-when-unstale: '⏱︎ Stale, 💤 Waiting for feedback, 💤 Waiting for changes' close-issue-reason: 'not_planned' exempt-all-milestones: false ================================================ FILE: .github/workflows/chore-pr-comments.yml ================================================ name: Add comment based on label on: pull_request_target: types: - labeled permissions: pull-requests: write jobs: add-comment: runs-on: ubuntu-latest strategy: matrix: include: - label: "⚙️ Service" body: | Hi @${{ github.event.pull_request.user.login }}! 👋 It appears to us that you are either adding a new service or making changes to an existing one. We kindly ask you to also review and update the **Coolify Documentation** to include this new service or it's new configuration needs. This will help ensure that our documentation remains accurate and up-to-date for all users. Coolify Docs Repository: https://github.com/coollabsio/coolify-docs How to Contribute a new Service to the Docs: https://coolify.io/docs/get-started/contribute/service#adding-a-new-service-template-to-the-coolify-documentation - label: "🛠️ Feature" body: | Hi @${{ github.event.pull_request.user.login }}! 👋 It appears to us that you are adding a new feature to Coolify. We kindly ask you to also update the **Coolify Documentation** to include information about this new feature. This will help ensure that our documentation remains accurate and up-to-date for all users. Coolify Docs Repository: https://github.com/coollabsio/coolify-docs How to Contribute to the Docs: https://coolify.io/docs/get-started/contribute/documentation # - label: "✨ Enhancement" # body: | # It appears to us that you are making an enhancement to Coolify. # We kindly ask you to also review and update the Coolify Documentation to include information about this enhancement if applicable. # This will help ensure that our documentation remains accurate and up-to-date for all users. steps: - name: Add comment if: github.event.label.name == matrix.label run: gh pr comment "$NUMBER" --body "$BODY" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} NUMBER: ${{ github.event.pull_request.number }} BODY: ${{ matrix.body }} ================================================ FILE: .github/workflows/claude.yml ================================================ name: Claude Code on: issue_comment: types: [created] pull_request_review_comment: types: [created] issues: types: [opened, assigned] pull_request_review: types: [submitted] jobs: claude: if: | (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) runs-on: ubuntu-latest permissions: contents: write pull-requests: write issues: write id-token: write steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 1 - name: Run Claude Code id: claude uses: anthropics/claude-code-action@v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} claude_args: '--model opus' ================================================ FILE: .github/workflows/cleanup-ghcr-untagged.yml ================================================ name: Cleanup Untagged GHCR Images on: workflow_dispatch: permissions: packages: write jobs: cleanup-all-packages: runs-on: ubuntu-latest strategy: matrix: package: ['coolify', 'coolify-helper', 'coolify-realtime', 'coolify-testing-host'] steps: - name: Delete untagged ${{ matrix.package }} images uses: actions/delete-package-versions@v5 with: package-name: ${{ matrix.package }} package-type: 'container' min-versions-to-keep: 0 delete-only-untagged-versions: 'true' ================================================ FILE: .github/workflows/coolify-helper-next.yml ================================================ name: Coolify Helper Image Development on: push: branches: [ "next" ] paths: - .github/workflows/coolify-helper-next.yml - docker/coolify-helper/Dockerfile permissions: contents: read packages: write env: GITHUB_REGISTRY: ghcr.io DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-helper" jobs: build-push: strategy: matrix: include: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - arch: aarch64 platform: linux/aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Build and Push Image (${{ matrix.arch }}) uses: docker/build-push-action@v6 with: context: . file: docker/coolify-helper/Dockerfile platforms: ${{ matrix.platform }} push: true tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} labels: | coolify.managed=true merge-manifest: runs-on: ubuntu-24.04 needs: build-push steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:next - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:next - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} ================================================ FILE: .github/workflows/coolify-helper.yml ================================================ name: Coolify Helper Image on: push: branches: [ "v4.x" ] paths: - .github/workflows/coolify-helper.yml - docker/coolify-helper/Dockerfile permissions: contents: read packages: write env: GITHUB_REGISTRY: ghcr.io DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-helper" jobs: build-push: strategy: matrix: include: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - arch: aarch64 platform: linux/aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Build and Push Image (${{ matrix.arch }}) uses: docker/build-push-action@v6 with: context: . file: docker/coolify-helper/Dockerfile platforms: ${{ matrix.platform }} push: true tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} labels: | coolify.managed=true merge-manifest: runs-on: ubuntu-24.04 needs: build-push steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }} ================================================ FILE: .github/workflows/coolify-production-build.yml ================================================ name: Production Build (v4) on: push: branches: ["v4.x"] paths-ignore: - .github/workflows/coolify-helper.yml - .github/workflows/coolify-helper-next.yml - .github/workflows/coolify-realtime.yml - .github/workflows/coolify-realtime-next.yml - .github/workflows/pr-quality.yaml - docker/coolify-helper/Dockerfile - docker/coolify-realtime/Dockerfile - docker/testing-host/Dockerfile - templates/** - CHANGELOG.md permissions: contents: read packages: write env: GITHUB_REGISTRY: ghcr.io DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify" jobs: build-push: strategy: matrix: include: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - arch: aarch64 platform: linux/aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Build and Push Image (${{ matrix.arch }}) uses: docker/build-push-action@v6 with: context: . file: docker/production/Dockerfile platforms: ${{ matrix.platform }} push: true tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} merge-manifest: runs-on: ubuntu-24.04 needs: build-push steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }} ================================================ FILE: .github/workflows/coolify-realtime-next.yml ================================================ name: Coolify Realtime Development on: push: branches: [ "next" ] paths: - .github/workflows/coolify-realtime-next.yml - docker/coolify-realtime/Dockerfile - docker/coolify-realtime/terminal-server.js - docker/coolify-realtime/package.json - docker/coolify-realtime/package-lock.json - docker/coolify-realtime/soketi-entrypoint.sh permissions: contents: read packages: write env: GITHUB_REGISTRY: ghcr.io DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-realtime" jobs: build-push: strategy: matrix: include: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - arch: aarch64 platform: linux/aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Build and Push Image (${{ matrix.arch }}) uses: docker/build-push-action@v6 with: context: . file: docker/coolify-realtime/Dockerfile platforms: ${{ matrix.platform }} push: true tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} labels: | coolify.managed=true merge-manifest: runs-on: ubuntu-24.04 needs: build-push steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:next - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:next - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} ================================================ FILE: .github/workflows/coolify-realtime.yml ================================================ name: Coolify Realtime on: push: branches: [ "v4.x" ] paths: - .github/workflows/coolify-realtime.yml - docker/coolify-realtime/Dockerfile - docker/coolify-realtime/terminal-server.js - docker/coolify-realtime/package.json - docker/coolify-realtime/package-lock.json - docker/coolify-realtime/soketi-entrypoint.sh permissions: contents: read packages: write env: GITHUB_REGISTRY: ghcr.io DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-realtime" jobs: build-push: strategy: matrix: include: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - arch: aarch64 platform: linux/aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Build and Push Image (${{ matrix.arch }}) uses: docker/build-push-action@v6 with: context: . file: docker/coolify-realtime/Dockerfile platforms: ${{ matrix.platform }} push: true tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} labels: | coolify.managed=true merge-manifest: runs-on: ubuntu-24.04 needs: build-push steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Get Version id: version run: | echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }} ================================================ FILE: .github/workflows/coolify-staging-build.yml ================================================ name: Staging Build on: push: branches-ignore: - v4.x - v3.x - '**v5.x**' paths-ignore: - .github/workflows/coolify-helper.yml - .github/workflows/coolify-helper-next.yml - .github/workflows/coolify-realtime.yml - .github/workflows/coolify-realtime-next.yml - .github/workflows/pr-quality.yaml - docker/coolify-helper/Dockerfile - docker/coolify-realtime/Dockerfile - docker/testing-host/Dockerfile - templates/** - CHANGELOG.md permissions: contents: read packages: write env: GITHUB_REGISTRY: ghcr.io DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify" jobs: build-push: strategy: matrix: include: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - arch: aarch64 platform: linux/aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Sanitize branch name for Docker tag id: sanitize run: | # Replace slashes and other invalid characters with dashes SANITIZED_NAME=$(echo "${{ github.ref_name }}" | sed 's/[\/]/-/g') echo "tag=${SANITIZED_NAME}" >> $GITHUB_OUTPUT - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and Push Image (${{ matrix.arch }}) uses: docker/build-push-action@v6 with: context: . file: docker/production/Dockerfile platforms: ${{ matrix.platform }} push: true tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-${{ matrix.arch }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-${{ matrix.arch }} cache-from: | type=gha,scope=build-${{ matrix.arch }} type=registry,ref=${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.arch }} cache-to: type=gha,mode=max,scope=build-${{ matrix.arch }} merge-manifest: runs-on: ubuntu-24.04 needs: build-push steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Sanitize branch name for Docker tag id: sanitize run: | # Replace slashes and other invalid characters with dashes SANITIZED_NAME=$(echo "${{ github.ref_name }}" | sed 's/[\/]/-/g') echo "tag=${SANITIZED_NAME}" >> $GITHUB_OUTPUT - uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-amd64 \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-aarch64 \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }} - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-amd64 \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-aarch64 \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }} - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} ================================================ FILE: .github/workflows/coolify-testing-host.yml ================================================ name: Coolify Testing Host on: push: branches: [ "next" ] paths: - .github/workflows/coolify-testing-host.yml - docker/testing-host/Dockerfile permissions: contents: read packages: write env: GITHUB_REGISTRY: ghcr.io DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-testing-host" jobs: build-push: strategy: matrix: include: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - arch: aarch64 platform: linux/aarch64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v5 with: persist-credentials: false - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and Push Image (${{ matrix.arch }}) uses: docker/build-push-action@v6 with: context: . file: docker/testing-host/Dockerfile platforms: ${{ matrix.platform }} push: true tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-${{ matrix.arch }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-${{ matrix.arch }} labels: | coolify.managed=true merge-manifest: runs-on: ubuntu-24.04 needs: build-push steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: docker/setup-buildx-action@v3 - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: registry: ${{ env.DOCKER_REGISTRY }} username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64 \ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 \ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} run: | docker buildx imagetools create \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64 \ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 \ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} ================================================ FILE: .github/workflows/generate-changelog.yml ================================================ name: Generate Changelog on: push: branches: [ v4.x ] paths-ignore: - .github/workflows/coolify-helper.yml - .github/workflows/coolify-helper-next.yml - .github/workflows/coolify-realtime.yml - .github/workflows/coolify-realtime-next.yml - .github/workflows/pr-quality.yaml workflow_dispatch: permissions: contents: write jobs: changelog: name: Generate changelog runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Generate changelog uses: orhun/git-cliff-action@v4 with: config: cliff.toml args: --verbose env: OUTPUT: CHANGELOG.md GITHUB_REPO: ${{ github.repository }} - name: Commit run: | git config user.name 'github-actions[bot]' git config user.email 'github-actions[bot]@users.noreply.github.com' git add CHANGELOG.md git commit -m "docs: update changelog" git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git v4.x ================================================ FILE: .github/workflows/pr-quality.yaml ================================================ name: PR Quality permissions: contents: read issues: read pull-requests: write on: pull_request_target: types: [opened, reopened] jobs: pr-quality: runs-on: ubuntu-latest steps: - uses: peakoss/anti-slop@v0 with: # General Settings max-failures: 4 # PR Branch Checks allowed-target-branches: "next" blocked-target-branches: "" allowed-source-branches: "" blocked-source-branches: | main master v4.x # PR Quality Checks max-negative-reactions: 0 require-maintainer-can-modify: true # PR Title Checks require-conventional-title: true # PR Description Checks require-description: true max-description-length: 2500 max-emoji-count: 2 max-code-references: 5 require-linked-issue: false blocked-terms: "STRAWBERRY" blocked-issue-numbers: 8154 # PR Template Checks require-pr-template: true strict-pr-template-sections: "Contributor Agreement" optional-pr-template-sections: "Issues,Preview" max-additional-pr-template-sections: 2 # Commit Message Checks max-commit-message-length: 500 require-conventional-commits: false require-commit-author-match: true blocked-commit-authors: "" # File Checks allowed-file-extensions: "" allowed-paths: "" blocked-paths: | README.md SECURITY.md LICENSE CODE_OF_CONDUCT.md templates/service-templates-latest.json templates/service-templates.json require-final-newline: true max-added-comments: 10 # User Checks detect-spam-usernames: true min-account-age: 30 max-daily-forks: 7 min-profile-completeness: 4 # Merge Checks min-repo-merged-prs: 0 min-repo-merge-ratio: 0 min-global-merge-ratio: 30 global-merge-ratio-exclude-own: false # Exemptions exempt-draft-prs: false exempt-bots: | actions-user dependabot[bot] renovate[bot] github-actions[bot] exempt-users: "" exempt-author-association: "OWNER,MEMBER,COLLABORATOR" exempt-label: "quality/exempt" exempt-pr-label: "" exempt-all-milestones: false exempt-all-pr-milestones: false exempt-milestones: "" exempt-pr-milestones: "" # PR Success Actions success-add-pr-labels: "quality/verified" # PR Failure Actions failure-remove-pr-labels: "" failure-remove-all-pr-labels: true failure-add-pr-labels: "quality/rejected" failure-pr-message: "This PR did not pass quality checks so it will be closed. If you believe this is a mistake please let us know." close-pr: true lock-pr: false ================================================ FILE: .mcp.json ================================================ { "mcpServers": { "laravel-boost": { "command": "php", "args": [ "artisan", "boost:mcp" ] } } } ================================================ FILE: .phpactor.json ================================================ { "$schema": "/phpactor.schema.json", "language_server_phpstan.enabled": true } ================================================ FILE: AGENTS.md ================================================ === foundation rules === # Laravel Boost Guidelines The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to ensure the best experience when building Laravel applications. ## Foundational Context This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions. - php - 8.4.1 - laravel/fortify (FORTIFY) - v1 - laravel/framework (LARAVEL) - v12 - laravel/horizon (HORIZON) - v5 - laravel/prompts (PROMPTS) - v0 - laravel/sanctum (SANCTUM) - v4 - laravel/socialite (SOCIALITE) - v5 - livewire/livewire (LIVEWIRE) - v3 - laravel/dusk (DUSK) - v8 - laravel/mcp (MCP) - v0 - laravel/pint (PINT) - v1 - laravel/telescope (TELESCOPE) - v5 - pestphp/pest (PEST) - v4 - phpunit/phpunit (PHPUNIT) - v12 - rector/rector (RECTOR) - v2 - laravel-echo (ECHO) - v2 - tailwindcss (TAILWINDCSS) - v4 - vue (VUE) - v3 ## Skills Activation This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. - `livewire-development` — Develops reactive Livewire 3 components. Activates when creating, updating, or modifying Livewire components; working with wire:model, wire:click, wire:loading, or any wire: directives; adding real-time updates, loading states, or reactivity; debugging component behavior; writing Livewire tests; or when the user mentions Livewire, component, counter, or reactive UI. - `pest-testing` — Tests applications using the Pest 4 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, browser testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. - `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. - `developing-with-fortify` — Laravel Fortify headless authentication backend development. Activate when implementing authentication features including login, registration, password reset, email verification, two-factor authentication (2FA/TOTP), profile updates, headless auth, authentication scaffolding, or auth guards in Laravel applications. - `debugging-output-and-previewing-html-using-ray` — Use when user says "send to Ray," "show in Ray," "debug in Ray," "log to Ray," "display in Ray," or wants to visualize data, debug output, or show diagrams in the Ray desktop application. ## Conventions - You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, and naming. - Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`. - Check for existing components to reuse before writing a new one. ## Verification Scripts - Do not create verification scripts or tinker when tests cover that functionality and prove they work. Unit and feature tests are more important. ## Application Structure & Architecture - Stick to existing directory structure; don't create new base folders without approval. - Do not change the application's dependencies without approval. ## Frontend Bundling - If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them. ## Documentation Files - You must only create documentation files if explicitly requested by the user. ## Replies - Be concise in your explanations - focus on what's important rather than explaining obvious details. === boost rules === # Laravel Boost - Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them. ## Artisan - Use the `list-artisan-commands` tool when you need to call an Artisan command to double-check the available parameters. ## URLs - Whenever you share a project URL with the user, you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain/IP, and port. ## Tinker / Debugging - You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly. - Use the `database-query` tool when you only need to read from the database. ## Reading Browser Logs With the `browser-logs` Tool - You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost. - Only recent browser logs will be useful - ignore old logs. ## Searching Documentation (Critically Important) - Boost comes with a powerful `search-docs` tool you should use before trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. - Search the documentation before making code changes to ensure we are taking the correct approach. - Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. - Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. ### Available Search Syntax 1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'. 2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit". 3. Quoted Phrases (Exact Position) - query="infinite scroll" - words must be adjacent and in that order. 4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit". 5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms. === php rules === # PHP - Always use curly braces for control structures, even for single-line bodies. ## Constructors - Use PHP 8 constructor property promotion in `__construct()`. - public function __construct(public GitHub $github) { } - Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. ## Type Declarations - Always use explicit return type declarations for methods and functions. - Use appropriate PHP type hints for method parameters. protected function isAccessible(User $user, ?string $path = null): bool { ... } ## Enums - Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. ## Comments - Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. ## PHPDoc Blocks - Add useful array shape type definitions when appropriate. === tests rules === # Test Enforcement - Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass. - Run the minimum number of tests needed to ensure code quality and speed. Use `php artisan test --compact` with a specific filename or filter. === laravel/core rules === # Do Things the Laravel Way - Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool. - If you're creating a generic PHP class, use `php artisan make:class`. - Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior. ## Database - Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins. - Use Eloquent models and relationships before suggesting raw database queries. - Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them. - Generate code that prevents N+1 query problems by using eager loading. - Use Laravel's query builder for very complex database operations. ### Model Creation - When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `php artisan make:model`. ### APIs & Eloquent Resources - For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention. ## Controllers & Validation - Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages. - Check sibling Form Requests to see if the application uses array or string based validation rules. ## Authentication & Authorization - Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.). ## URL Generation - When generating links to other pages, prefer named routes and the `route()` function. ## Queues - Use queued jobs for time-consuming operations with the `ShouldQueue` interface. ## Configuration - Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`. ## Testing - When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model. - Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`. - When creating tests, make use of `php artisan make:test [options] {name}` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests. ## Vite Error - If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`. === laravel/v12 rules === # Laravel 12 - CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. - This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. - This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. ## Laravel 10 Structure - Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. - There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: - Middleware registration happens in `app/Http/Kernel.php` - Exception handling is in `app/Exceptions/Handler.php` - Console commands and schedule register in `app/Console/Kernel.php` - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` ## Database - When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost. - Laravel 12 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`. ### Models - Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models. === livewire/core rules === # Livewire - Livewire allows you to build dynamic, reactive interfaces using only PHP — no JavaScript required. - Instead of writing frontend code in JavaScript frameworks, you use Alpine.js to build the UI when client-side interactions are required. - State lives on the server; the UI reflects it. Validate and authorize in actions (they're like HTTP requests). - IMPORTANT: Activate `livewire-development` every time you're working with Livewire-related tasks. === pint/core rules === # Laravel Pint Code Formatter - You must run `vendor/bin/pint --dirty --format agent` before finalizing changes to ensure your code matches the project's expected style. - Do not run `vendor/bin/pint --test --format agent`, simply run `vendor/bin/pint --format agent` to fix any formatting issues. === pest/core rules === ## Pest - This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. - Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. - Do NOT delete tests without approval. - CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. - IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. === tailwindcss/core rules === # Tailwind CSS - Always use existing Tailwind conventions; check project patterns before adding new ones. - IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. - IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. === laravel/fortify rules === # Laravel Fortify - Fortify is a headless authentication backend that provides authentication routes and controllers for Laravel applications. - IMPORTANT: Always use the `search-docs` tool for detailed Laravel Fortify patterns and documentation. - IMPORTANT: Activate `developing-with-fortify` skill when working with Fortify authentication features. ================================================ FILE: CLAUDE.md ================================================ # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Coolify is an open-source, self-hostable PaaS (alternative to Heroku/Netlify/Vercel). It manages servers, applications, databases, and services via SSH. Built with Laravel 12 (using Laravel 10 file structure), Livewire 3, and Tailwind CSS v4. ## Development Environment Docker Compose-based dev setup with services: coolify (app), postgres, redis, soketi (WebSockets), vite, testing-host, mailpit, minio. ```bash # Start dev environment (uses docker-compose.dev.yml) spin up # or: docker compose -f docker-compose.dev.yml up -d spin down # stop services ``` The app runs at `localhost:8000` by default. Vite dev server on port 5173. ## Common Commands ```bash # Tests (Pest 4) php artisan test --compact # all tests php artisan test --compact --filter=testName # single test php artisan test --compact tests/Feature/SomeTest.php # specific file # Code formatting (Pint, Laravel preset) vendor/bin/pint --dirty --format agent # format changed files # Frontend npm run dev # vite dev server npm run build # production build ``` ## Architecture ### Backend Structure (app/) - **Actions/** — Domain actions organized by area (Application, Database, Docker, Proxy, Server, Service, Shared, Stripe, User). Uses `lorisleiva/laravel-actions`. - **Livewire/** — All UI components (Livewire 3). Pages organized by domain: Server, Project, Settings, Notifications, etc. This is the primary UI layer — no traditional Blade controllers. - **Jobs/** — Queue jobs for deployments (`ApplicationDeploymentJob`), backups, Docker cleanup, server management, proxy configuration. - **Models/** — Eloquent models. Key models: `Server`, `Application`, `Service`, `Project`, `Environment`, `Team`, plus standalone database models (`StandalonePostgresql`, `StandaloneMysql`, etc.). - **Services/** — Business logic services. - **Helpers/** — Global helper functions loaded via `bootstrap/includeHelpers.php`. - **Data/** — Spatie Laravel Data DTOs. - **Enums/** — PHP enums (TitleCase keys). ### Key Domain Concepts - **Server** — A managed host connected via SSH. Has settings, proxy config, and destinations. - **Application** — A deployed app (from Git or Docker image) with environment variables, previews, deployment queue. - **Service** — A pre-configured service stack from templates (`templates/service-templates-latest.json`). - **Standalone Databases** — Individual database instances (Postgres, MySQL, MariaDB, MongoDB, Redis, Clickhouse, KeyDB, Dragonfly). - **Project/Environment** — Organizational hierarchy: Team → Project → Environment → Resources. - **Proxy** — Traefik reverse proxy managed per server. ### Frontend - Livewire 3 components with Alpine.js for client-side interactivity - Blade templates in `resources/views/livewire/` - Tailwind CSS v4 with `@tailwindcss/forms` and `@tailwindcss/typography` - Vite for asset bundling ### Laravel 10 Structure (NOT Laravel 11+ slim structure) - Middleware in `app/Http/Middleware/` - Kernels: `app/Http/Kernel.php`, `app/Console/Kernel.php` - Exception handler: `app/Exceptions/Handler.php` - Service providers in `app/Providers/` ## Key Conventions - Use `php artisan make:*` commands with `--no-interaction` to create files - Use Eloquent relationships, avoid `DB::` facade — prefer `Model::query()` - PHP 8.4: constructor property promotion, explicit return types, type hints - Always create Form Request classes for validation - Run `vendor/bin/pint --dirty --format agent` before finalizing changes - Every change must have tests — write or update tests, then run them - Check sibling files for conventions before creating new files ## Git Workflow - Main branch: `v4.x` - Development branch: `next` - PRs should target `v4.x` === foundation rules === # Laravel Boost Guidelines The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to ensure the best experience when building Laravel applications. ## Foundational Context This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions. - php - 8.4.1 - laravel/fortify (FORTIFY) - v1 - laravel/framework (LARAVEL) - v12 - laravel/horizon (HORIZON) - v5 - laravel/prompts (PROMPTS) - v0 - laravel/sanctum (SANCTUM) - v4 - laravel/socialite (SOCIALITE) - v5 - livewire/livewire (LIVEWIRE) - v3 - laravel/dusk (DUSK) - v8 - laravel/mcp (MCP) - v0 - laravel/pint (PINT) - v1 - laravel/telescope (TELESCOPE) - v5 - pestphp/pest (PEST) - v4 - phpunit/phpunit (PHPUNIT) - v12 - rector/rector (RECTOR) - v2 - laravel-echo (ECHO) - v2 - tailwindcss (TAILWINDCSS) - v4 - vue (VUE) - v3 ## Skills Activation This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. - `livewire-development` — Develops reactive Livewire 3 components. Activates when creating, updating, or modifying Livewire components; working with wire:model, wire:click, wire:loading, or any wire: directives; adding real-time updates, loading states, or reactivity; debugging component behavior; writing Livewire tests; or when the user mentions Livewire, component, counter, or reactive UI. - `pest-testing` — Tests applications using the Pest 4 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, browser testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works. - `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes. - `developing-with-fortify` — Laravel Fortify headless authentication backend development. Activate when implementing authentication features including login, registration, password reset, email verification, two-factor authentication (2FA/TOTP), profile updates, headless auth, authentication scaffolding, or auth guards in Laravel applications. - `debugging-output-and-previewing-html-using-ray` — Use when user says "send to Ray," "show in Ray," "debug in Ray," "log to Ray," "display in Ray," or wants to visualize data, debug output, or show diagrams in the Ray desktop application. ## Conventions - You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, and naming. - Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`. - Check for existing components to reuse before writing a new one. ## Verification Scripts - Do not create verification scripts or tinker when tests cover that functionality and prove they work. Unit and feature tests are more important. ## Application Structure & Architecture - Stick to existing directory structure; don't create new base folders without approval. - Do not change the application's dependencies without approval. ## Frontend Bundling - If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them. ## Documentation Files - You must only create documentation files if explicitly requested by the user. ## Replies - Be concise in your explanations - focus on what's important rather than explaining obvious details. === boost rules === # Laravel Boost - Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them. ## Artisan - Use the `list-artisan-commands` tool when you need to call an Artisan command to double-check the available parameters. ## URLs - Whenever you share a project URL with the user, you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain/IP, and port. ## Tinker / Debugging - You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly. - Use the `database-query` tool when you only need to read from the database. ## Reading Browser Logs With the `browser-logs` Tool - You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost. - Only recent browser logs will be useful - ignore old logs. ## Searching Documentation (Critically Important) - Boost comes with a powerful `search-docs` tool you should use before trying other approaches when working with Laravel or Laravel ecosystem packages. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. - Search the documentation before making code changes to ensure we are taking the correct approach. - Use multiple, broad, simple, topic-based queries at once. For example: `['rate limiting', 'routing rate limiting', 'routing']`. The most relevant results will be returned first. - Do not add package names to queries; package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. ### Available Search Syntax 1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'. 2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit". 3. Quoted Phrases (Exact Position) - query="infinite scroll" - words must be adjacent and in that order. 4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit". 5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms. === php rules === # PHP - Always use curly braces for control structures, even for single-line bodies. ## Constructors - Use PHP 8 constructor property promotion in `__construct()`. - public function __construct(public GitHub $github) { } - Do not allow empty `__construct()` methods with zero parameters unless the constructor is private. ## Type Declarations - Always use explicit return type declarations for methods and functions. - Use appropriate PHP type hints for method parameters. protected function isAccessible(User $user, ?string $path = null): bool { ... } ## Enums - Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. ## Comments - Prefer PHPDoc blocks over inline comments. Never use comments within the code itself unless the logic is exceptionally complex. ## PHPDoc Blocks - Add useful array shape type definitions when appropriate. === tests rules === # Test Enforcement - Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass. - Run the minimum number of tests needed to ensure code quality and speed. Use `php artisan test --compact` with a specific filename or filter. === laravel/core rules === # Do Things the Laravel Way - Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool. - If you're creating a generic PHP class, use `php artisan make:class`. - Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior. ## Database - Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins. - Use Eloquent models and relationships before suggesting raw database queries. - Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them. - Generate code that prevents N+1 query problems by using eager loading. - Use Laravel's query builder for very complex database operations. ### Model Creation - When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `php artisan make:model`. ### APIs & Eloquent Resources - For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention. ## Controllers & Validation - Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages. - Check sibling Form Requests to see if the application uses array or string based validation rules. ## Authentication & Authorization - Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.). ## URL Generation - When generating links to other pages, prefer named routes and the `route()` function. ## Queues - Use queued jobs for time-consuming operations with the `ShouldQueue` interface. ## Configuration - Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`. ## Testing - When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model. - Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`. - When creating tests, make use of `php artisan make:test [options] {name}` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests. ## Vite Error - If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`. === laravel/v12 rules === # Laravel 12 - CRITICAL: ALWAYS use `search-docs` tool for version-specific Laravel documentation and updated code examples. - This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. - This is perfectly fine and recommended by Laravel. Follow the existing structure from Laravel 10. We do not need to migrate to the new Laravel structure unless the user explicitly requests it. ## Laravel 10 Structure - Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. - There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: - Middleware registration happens in `app/Http/Kernel.php` - Exception handling is in `app/Exceptions/Handler.php` - Console commands and schedule register in `app/Console/Kernel.php` - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` ## Database - When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost. - Laravel 12 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`. ### Models - Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models. === livewire/core rules === # Livewire - Livewire allows you to build dynamic, reactive interfaces using only PHP — no JavaScript required. - Instead of writing frontend code in JavaScript frameworks, you use Alpine.js to build the UI when client-side interactions are required. - State lives on the server; the UI reflects it. Validate and authorize in actions (they're like HTTP requests). - IMPORTANT: Activate `livewire-development` every time you're working with Livewire-related tasks. === pint/core rules === # Laravel Pint Code Formatter - You must run `vendor/bin/pint --dirty --format agent` before finalizing changes to ensure your code matches the project's expected style. - Do not run `vendor/bin/pint --test --format agent`, simply run `vendor/bin/pint --format agent` to fix any formatting issues. === pest/core rules === ## Pest - This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`. - Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`. - Do NOT delete tests without approval. - CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples. - IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task. === tailwindcss/core rules === # Tailwind CSS - Always use existing Tailwind conventions; check project patterns before adding new ones. - IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data. - IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task. === laravel/fortify rules === # Laravel Fortify - Fortify is a headless authentication backend that provides authentication routes and controllers for Laravel applications. - IMPORTANT: Always use the `search-docs` tool for detailed Laravel Fortify patterns and documentation. - IMPORTANT: Activate `developing-with-fortify` skill when working with Fortify authentication features. ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Citizen Code of Conduct ## 1. Purpose A primary goal of Coolify is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. We invite all those who participate in Coolify to help us create safe and positive experiences for everyone. ## 2. Open [Source/Culture/Tech] Citizenship A supplemental goal of this Code of Conduct is to increase open [source/culture/tech] citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community. Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know. ## 3. Expected Behavior The following behaviors are expected and requested of all community members: * Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community. * Exercise consideration and respect in your speech and actions. * Attempt collaboration before conflict. * Refrain from demeaning, discriminatory, or harassing behavior and speech. * Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. * Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations. ## 4. Unacceptable Behavior The following behaviors are considered harassment and are unacceptable within our community: * Violence, threats of violence or violent language directed against another person. * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. * Posting or displaying sexually explicit or violent material. * Posting or threatening to post other people's personally identifying information ("doxing"). * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. * Inappropriate photography or recording. * Inappropriate physical contact. You should have someone's consent before touching them. * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. * Deliberate intimidation, stalking or following (online or in person). * Advocating for, or encouraging, any of the above behavior. * Sustained disruption of community events, including talks and presentations. ## 5. Weapons Policy No weapons will be allowed at Coolify events, community spaces, or in other spaces covered by the scope of this Code of Conduct. Weapons include but are not limited to guns, explosives (including fireworks), and large knives such as those used for hunting or display, as well as any other item used for the purpose of causing injury or harm to others. Anyone seen in possession of one of these items will be asked to leave immediately, and will only be allowed to return without the weapon. Community members are further expected to comply with all state and local laws on this matter. ## 6. Consequences of Unacceptable Behavior Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated. Anyone asked to stop unacceptable behavior is expected to comply immediately. If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event). ## 7. Reporting Guidelines If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. hi@coollabs.io. Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress. ## 8. Addressing Grievances If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify coollabsio with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies. ## 9. Scope We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues--online and in-person--as well as in all one-on-one communications pertaining to community business. This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members. ## 10. Contact info hi@coollabs.io ## 11. License and attribution The Citizen Code of Conduct is distributed by [Stumptown Syndicate](http://stumptownsyndicate.org) under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy). _Revision 2.3. Posted 6 March 2017._ _Revision 2.2. Posted 4 February 2016._ _Revision 2.1. Posted 23 June 2014._ _Revision 2.0, adopted by the [Stumptown Syndicate](http://stumptownsyndicate.org) board on 10 January 2013. Posted 17 March 2013._ ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to Coolify > "First, thanks for considering contributing to my project. It really means a lot!" - [@andrasbacsai](https://github.com/andrasbacsai) You can ask for guidance anytime on our [Discord server](https://coollabs.io/discord) in the `#contribute` channel. To understand the tech stack, please refer to the [Tech Stack](TECH_STACK.md) document. ## Table of Contents 1. [Setup Development Environment](#1-setup-development-environment) 2. [Verify Installation](#2-verify-installation-optional) 3. [Fork and Setup Local Repository](#3-fork-and-setup-local-repository) 4. [Set up Environment Variables](#4-set-up-environment-variables) 5. [Start Coolify](#5-start-coolify) 6. [Start Development](#6-start-development) 7. [Create a Pull Request](#7-create-a-pull-request) 8. [Development Notes](#development-notes) 9. [Resetting Development Environment](#resetting-development-environment) 10. [Additional Contribution Guidelines](#additional-contribution-guidelines) ## 1. Setup Development Environment Follow the steps below for your operating system:
Windows 1. Install `docker-ce`, Docker Desktop (or similar): - Docker CE (recommended): - Install Windows Subsystem for Linux v2 (WSL2) by following this guide: [Install WSL](https://learn.microsoft.com/en-us/windows/wsl/install?ref=coolify) - After installing WSL2, install Docker CE for your Linux distribution by following this guide: [Install Docker Engine](https://docs.docker.com/engine/install/?ref=coolify) - Make sure to choose the appropriate Linux distribution (e.g., Ubuntu) when following the Docker installation guide - Install Docker Desktop (easier): - Download and install [Docker Desktop for Windows](https://docs.docker.com/desktop/install/windows-install/?ref=coolify) - Ensure WSL2 backend is enabled in Docker Desktop settings 2. Install Spin: - Follow the instructions to install Spin on Windows from the [Spin documentation](https://serversideup.net/open-source/spin/docs/installation/install-windows#download-and-install-spin-into-wsl2?ref=coolify)
MacOS 1. Install Orbstack, Docker Desktop (or similar): - Orbstack (recommended, as it is a faster and lighter alternative to Docker Desktop): - Download and install [Orbstack](https://docs.orbstack.dev/quick-start#installation?ref=coolify) - Docker Desktop: - Download and install [Docker Desktop for Mac](https://docs.docker.com/desktop/install/mac-install/?ref=coolify) 2. Install Spin: - Follow the instructions to install Spin on MacOS from the [Spin documentation](https://serversideup.net/open-source/spin/docs/installation/install-macos/#download-and-install-spin?ref=coolify)
Linux 1. Install Docker Engine, Docker Desktop (or similar): - Docker Engine (recommended, as there is no VM overhead): - Follow the official [Docker Engine installation guide](https://docs.docker.com/engine/install/?ref=coolify) for your Linux distribution - Docker Desktop: - If you want a GUI, you can use [Docker Desktop for Linux](https://docs.docker.com/desktop/install/linux-install/?ref=coolify) 2. Install Spin: - Follow the instructions to install Spin on Linux from the [Spin documentation](https://serversideup.net/open-source/spin/docs/installation/install-linux#configure-docker-permissions?ref=coolify)
## 2. Verify Installation (Optional) After installing Docker (or Orbstack) and Spin, verify the installation: 1. Open a terminal or command prompt 2. Run the following commands: ```bash docker --version spin --version ``` You should see version information for both Docker and Spin. ## 3. Fork and Setup Local Repository 1. Fork the [Coolify](https://github.com/coollabsio/coolify) repository to your GitHub account. 2. Install a code editor on your machine (choose one): | Editor | Platform | Download Link | |--------|----------|---------------| | Visual Studio Code (recommended free) | Windows/macOS/Linux | [Download](https://code.visualstudio.com/download?ref=coolify) | | Cursor (recommended but paid) | Windows/macOS/Linux | [Download](https://www.cursor.com/?ref=coolify) | | Zed (very fast) | macOS/Linux | [Download](https://zed.dev/download?ref=coolify) | 3. Clone the Coolify Repository from your fork to your local machine - Use `git clone` in the command line, or - Use GitHub Desktop (recommended): - Download and install from [https://desktop.github.com/](https://desktop.github.com/?ref=coolify) - Open GitHub Desktop and login with your GitHub account - Click on `File` -> `Clone Repository` select `github.com` as the repository location, then select your forked Coolify repository, choose the local path and then click `Clone` 4. Open the cloned Coolify Repository in your chosen code editor. ## 4. Set up Environment Variables 1. In the Code Editor, locate the `.env.development.example` file in the root directory of your local Coolify repository. 2. Duplicate the `.env.development.example` file and rename the copy to `.env`. 3. Open the new `.env` file and review its contents. Adjust any environment variables as needed for your development setup. 4. If you encounter errors during database migrations, update the database connection settings in your `.env` file. Use the IP address or hostname of your PostgreSQL database container. You can find this information by running `docker ps` after executing `spin up`. 5. Save the changes to your `.env` file. ## 5. Start Coolify 1. Open a terminal in the local Coolify directory. 2. Run the following command in the terminal (leave that terminal open): ```bash spin up ``` > [!NOTE] > You may see some errors, but don't worry; this is expected. 3. If you encounter permission errors, especially on macOS, use: ```bash sudo spin up ``` > [!NOTE] > If you change environment variables afterwards or anything seems broken, press Ctrl + C to stop the process and run `spin up` again. ## 6. Start Development 1. Access your Coolify instance: - URL: `http://localhost:8000` - Login: `test@example.com` - Password: `password` 2. Additional development tools: | Tool | URL | Note | |------|-----|------| | Laravel Horizon (scheduler) | `http://localhost:8000/horizon` | Only accessible when logged in as root user | | Mailpit (email catcher) | `http://localhost:8025` | | | Telescope (debugging tool) | `http://localhost:8000/telescope` | Disabled by default | > [!NOTE] > To enable Telescope, add the following to your `.env` file: > ```env > TELESCOPE_ENABLED=true > ``` ## 7. Create a Pull Request > [!IMPORTANT] > Please read the [Pull Request Guidelines](#pull-request-guidelines) carefully before creating your PR. 1. After making changes or adding a new service: - Commit your changes to your forked repository. - Push the changes to your GitHub account. 2. Creating the Pull Request (PR): - Navigate to the main Coolify repository on GitHub. - Click the "Pull requests" tab. - Click the green "New pull request" button. - Choose your fork and `next` branch as the compare branch. - Click "Create pull request". 3. Filling out the PR details: - Give your PR a descriptive title. - Use the Pull Request Template provided and fill in the details. > [!IMPORTANT] > Always set the base branch for your PR to the `next` branch of the Coolify repository, not the `v4.x` branch. 4. Submit your PR: - Review your changes one last time. - Click "Create pull request" to submit. > [!NOTE] > Make sure your PR is out of draft mode as soon as it's ready for review. PRs that are in draft mode for a long time may be closed by maintainers. After submission, maintainers will review your PR and may request changes or provide feedback. #### Pull Request Guidelines To maintain high-quality contributions and efficient review process: - **Target Branch**: Always target the `next` branch, never `v4.x` or any other branch. PRs targeting incorrect branches will be closed without review. - **Descriptive Titles**: Use clear, concise PR titles that describe the change (e.g., "fix: one click postgresql database stuck in restart loop" instead of "Fix database"). - **PR Descriptions**: Provide detailed, meaningful descriptions. Avoid generic or AI-generated fluff. Include: - What the change does - Why it's needed - How to test it - Any breaking changes - Screenshot or video recording of your changes working without any issues - Links to related issues - **Link to Issues**: All PRs must link to an existing GitHub issue. If no issue exists, create one first. Unrelated PRs may be closed. - **Single Responsibility**: Each PR should address one issue or feature. Do not bundle unrelated changes. - **Draft Mode**: Use draft PRs for work-in-progress. Convert to ready-for-review only when complete and tested. - **Review Readiness**: Ensure your PR is ready for review within a reasonable timeframe (max 7 days in draft). Stale drafts may be closed. - **Current Focus**: We are currently prioritizing stability and bug fixes over new features. PRs adding new features may not be reviewed, or may be closed without review to maintain focus. - **Language Translations**: Coolify currently supports only English. Pull requests for new language translations will not be accepted. Multi-language support may be considered in the next major version (v5). - **AI Usage Policy**: We are not against AI tools—we use them ourselves. However, AI discourse is mandatory: You must fully understand the changes in your PR and be able to explain them clearly. Many PRs using AI lack this understanding, leading to untested or incorrect submissions. If you use AI, ensure you can articulate what the code does, why it was changed, and how it was tested. #### Review Process - **Response Time**: Maintainers will review PRs promptly, but complex changes may take time. Be patient and responsive to feedback. - **Revisions**: Address all review comments. Unresolved feedback may lead to PR closure. - **Merge Criteria**: PRs are merged only after: - All tests pass (including CI) - Code review approval - **Closing PRs**: PRs may be closed for: - Inactivity (>7 days without response) - Failure to meet guidelines - Duplicate or superseded work - Security or quality concerns #### Code Quality, Testing, and Bounty Submissions All contributions must adhere to the highest standards of code quality and testing: - **Testing Required**: Every PR must include steps to test your changes. Untested code will not be reviewed or merged. - **Local Verification**: Ensure your changes work in the development environment. Test all affected features thoroughly. - **Code Standards**: Follow the existing code style, conventions, and patterns in the codebase. - **No AI-Generated Code**: Do not submit code generated by AI tools without fully understanding and verifying it. AI-generated submissions that are untested or incorrect will be rejected immediately. **For PRs that claim bounties:** - **Eligibility**: Bounty PRs must strictly follow all guidelines above. Untested, poorly described, or non-compliant PRs will not qualify for bounty rewards. - **Original Work**: Bounties are for genuine contributions. Submitting AI-generated or copied code solely for bounty claims will result in disqualification and potential removal from contributing. - **Quality Standards**: Bounty submissions are held to even higher standards. Ensure comprehensive testing, clear documentation, and alignment with project goals. When maintainers review the changes, they should work as expected (the things mentioned in the PR description plus what the bounty issuer needs). - **Claim Process**: Only successfully merged PRs that pass all reviews (core maintainers + bounty issuer) and meet bounty criteria will be awarded. Follow the issue's bounty guidelines precisely. - **Prioritization**: Contributor PRs are prioritized over first-time or new contributors. - **Developer Experience**: We highly advise beginners to avoid participating in bug bounties for our codebase. Most of the time, they don't know what they are changing, how it affects other parts of the system, or if their changes are even correct. - **Review Comments**: When maintainers ask questions, you should be able to respond properly without generic or AI-generated fluff. ## Development Notes When working on Coolify, keep the following in mind: 1. **Database Migrations**: After switching branches or making changes to the database structure, always run migrations: ```bash docker exec -it coolify php artisan migrate ``` 2. **Resetting Development Setup**: To reset your development setup to a clean database with default values: ```bash docker exec -it coolify php artisan migrate:fresh --seed ``` 3. **Troubleshooting**: If you encounter unexpected behavior, ensure your database is up-to-date with the latest migrations and if possible reset the development setup to eliminate any environment-specific issues. > [!IMPORTANT] > Forgetting to migrate the database can cause problems, so make it a habit to run migrations after pulling changes or switching branches. ## Resetting Development Environment If you encounter issues or break your database or something else, follow these steps to start from a clean slate (works since `v4.0.0-beta.342`): 1. Stop all running containers `ctrl + c`. 2. Remove all Coolify containers: ```bash docker rm coolify coolify-db coolify-redis coolify-realtime coolify-testing-host coolify-minio coolify-vite-1 coolify-mail ``` 3. Remove Coolify volumes (it is possible that the volumes have no `coolify` prefix on your machine, in that case remove the prefix from the command): ```bash docker volume rm coolify_dev_backups_data coolify_dev_postgres_data coolify_dev_redis_data coolify_dev_coolify_data coolify_dev_minio_data ``` 4. Remove unused images: ```bash docker image prune -a ``` 5. Start Coolify again: ```bash spin up ``` 6. Run database migrations and seeders: ```bash docker exec -it coolify php artisan migrate:fresh --seed ``` After completing these steps, you'll have a fresh development setup. > [!IMPORTANT] > Always run database migrations and seeders after switching branches or pulling updates to ensure your local database structure matches the current codebase and includes necessary seed data. ## Additional Contribution Guidelines ### Contributing a New Service To add a new service to Coolify, please refer to our documentation: [Adding a New Service](https://coolify.io/docs/get-started/contribute/service) ### Contributing to Documentation To contribute to the Coolify documentation, please refer to this guide: [Contributing to the Coolify Documentation](https://github.com/coollabsio/documentation-coolify/blob/main/readme.md) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [2025] [Andras Bacsai] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================
# Coolify An open-source & self-hostable Heroku / Netlify / Vercel alternative. ![Latest Release Version](https://img.shields.io/badge/dynamic/json?labelColor=grey&color=6366f1&label=Latest%20released%20version&url=https%3A%2F%2Fcdn.coollabs.io%2Fcoolify%2Fversions.json&query=coolify.v4.version&style=for-the-badge ) [![Bounty Issues](https://img.shields.io/static/v1?labelColor=grey&color=6366f1&label=Algora&message=%F0%9F%92%8E+Bounty+issues&style=for-the-badge)](https://console.algora.io/org/coollabsio/bounties/new)
## About the Project Coolify is an open-source & self-hostable alternative to Heroku / Netlify / Vercel / etc. It helps you manage your servers, applications, and databases on your own hardware; you only need an SSH connection. You can manage VPS, Bare Metal, Raspberry PIs, and anything else. Imagine having the ease of a cloud but with your own servers. That is **Coolify**. No vendor lock-in, which means that all the configurations for your applications/databases/etc are saved to your server. So, if you decide to stop using Coolify (oh nooo), you could still manage your running resources. You lose the automations and all the magic. 🪄️ For more information, take a look at our landing page at [coolify.io](https://coolify.io). ## Installation ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` You can find the installation script source [here](./scripts/install.sh). > [!NOTE] > Please refer to the [docs](https://coolify.io/docs/installation) for more information about the installation. ## Support Contact us at [coolify.io/docs/contact](https://coolify.io/docs/contact). ## Cloud If you do not want to self-host Coolify, there is a paid cloud version available: [app.coolify.io](https://app.coolify.io) For more information & pricing, take a look at our landing page [coolify.io](https://coolify.io). ## Why should I use the Cloud version? The recommended way to use Coolify is to have one server for Coolify and one (or more) for the resources you are deploying. A server is around 4-5$/month. By subscribing to the cloud version, you get the Coolify server for the same price, but with: - High-availability - Free email notifications - Better support - Less maintenance for you ## Donations To stay completely free and open-source, with no feature behind the paywall and evolve the project, we need your help. If you like Coolify, please consider donating to help us fund the project's future development. [coolify.io/sponsorships](https://coolify.io/sponsorships) Thank you so much! ### Huge Sponsors * [MVPS](https://www.mvps.net?ref=coolify.io) - Cheap VPS servers at the highest possible quality * [SerpAPI](https://serpapi.com?ref=coolify.io) - Google Search API — Scrape Google and other search engines from our fast, easy, and complete API * ### Big Sponsors * [23M](https://23m.com?ref=coolify.io) - Your experts for high-availability hosting solutions! * [Algora](https://algora.io?ref=coolify.io) - Open source contribution platform * [American Cloud](https://americancloud.com?ref=coolify.io) - US-based cloud infrastructure services * [Arcjet](https://arcjet.com?ref=coolify.io) - Advanced web security and performance solutions * [BC Direct](https://bc.direct?ref=coolify.io) - Your trusted technology consulting partner * [Blacksmith](https://blacksmith.sh?ref=coolify.io) - Infrastructure automation platform * [Brand.dev](https://brand.dev?ref=coolify.io) - API to personalize your product with logos, colors, and company info from any domain * [ByteBase](https://www.bytebase.com?ref=coolify.io) - Database CI/CD and Security at Scale * [CodeRabbit](https://coderabbit.ai?ref=coolify.io) - Cut Code Review Time & Bugs in Half * [COMIT](https://comit.international?ref=coolify.io) - New York Times award–winning contractor * [CompAI](https://www.trycomp.ai?ref=coolify.io) - Open source compliance automation platform * [Convex](https://convex.link/coolify.io) - Open-source reactive database for web app developers * [CubePath](https://cubepath.com/?ref=coolify.io) - Dedicated Servers & Instant Deploy * [Darweb](https://darweb.nl/?ref=coolify.io) - 3D CPQ solutions for ecommerce design * [Formbricks](https://formbricks.com?ref=coolify.io) - The open source feedback platform * [GoldenVM](https://billing.goldenvm.com?ref=coolify.io) - Premium virtual machine hosting solutions * [Greptile](https://www.greptile.com?ref=coolify.io) - The AI Code Reviewer * [Hetzner](http://htznr.li/CoolifyXHetzner) - Server, cloud, hosting, and data center solutions * [Hostinger](https://www.hostinger.com/vps/coolify-hosting?ref=coolify.io) - Web hosting and VPS solutions * [JobsCollider](https://jobscollider.com/remote-jobs?ref=coolify.io) - 30,000+ remote jobs for developers * [Juxtdigital](https://juxtdigital.com?ref=coolify.io) - Digital PR & AI Authority Building Agency * [LiquidWeb](https://liquidweb.com?ref=coolify.io) - Premium managed hosting solutions * [Logto](https://logto.io?ref=coolify.io) - The better identity infrastructure for developers * [Macarne](https://macarne.com?ref=coolify.io) - Best IP Transit & Carrier Ethernet Solutions for Simplified Network Connectivity * [Mobb](https://vibe.mobb.ai/?ref=coolify.io) - Secure Your AI-Generated Code to Unlock Dev Productivity * [PFGLabs](https://pfglabs.com?ref=coolify.io) - Build Real Projects with Golang * [Ramnode](https://ramnode.com/?ref=coolify.io) - High Performance Cloud VPS Hosting * [SaasyKit](https://saasykit.com?ref=coolify.io) - Complete SaaS starter kit for developers * [SupaGuide](https://supa.guide?ref=coolify.io) - Your comprehensive guide to Supabase * [Supadata AI](https://supadata.ai/?ref=coolify.io) - Scrape YouTube, web, and files. Get AI-ready, clean data * [Syntax.fm](https://syntax.fm?ref=coolify.io) - Podcast for web developers * [Tigris](https://www.tigrisdata.com?ref=coolify.io) - Modern developer data platform * [Tolgee](https://tolgee.io?ref=coolify.io) - The open source localization platform * [Ubicloud](https://www.ubicloud.com?ref=coolify.io) - Open source cloud infrastructure platform * [VPSDime](https://vpsdime.com?ref=coolify.io) - Affordable high-performance VPS hosting solutions ### Small Sponsors OpenElements XamanApp UXWizz Evercam Imre Ujlaki jyc.dev TheRealJP 360Creators NiftyCo Dry Software Lightspeed.run LinkDr Gravity Wiz BitLaunch Best for Android Ilias Ism Formbricks Server Searcher Reshot Cirun Typebot Creating Coding Careers Internet Garden Web3 Jobs Codext Michael Mazurczak Fider Flint Paweł Pierścionek RunPod DartNode Tyler Whitesides Aquarela Crypto Jobs List Alfred Nutile Startup Fame Younes Barrad Jonas Jaeger Pixel Infinito Corentin Clichy Thompson Edolo Devhuset Arvensis Systems Niklas Lausch Cap-go InterviewPal Transcript LOL ...and many more at [GitHub Sponsors](https://github.com/sponsors/coollabsio) ## Recognitions

Featured on Hacker News

Coolify - An open-source & self-hostable Heroku, Netlify alternative | Product Hunt coollabsio%2Fcoolify | Trendshift ## Core Maintainers | Andras Bacsai | 🏔️ Peak | |------------|------------| | Andras Bacsai | peaklabs-dev | | | | ## Repo Activity ![Alt](https://repobeats.axiom.co/api/embed/eab1c8066f9c59d0ad37b76c23ebb5ccac4278ae.svg "Repobeats analytics image") ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=coollabsio/coolify&type=Date)](https://star-history.com/#coollabsio/coolify&Date) ================================================ FILE: RELEASE.md ================================================ # Coolify Release Guide This guide outlines the release process for Coolify, intended for developers and those interested in understanding how Coolify releases are managed and deployed. ## Table of Contents - [Release Process](#release-process) - [Version Types](#version-types) - [Stable](#stable) - [Nightly](#nightly) - [Beta](#beta) - [Version Availability](#version-availability) - [Self-Hosted](#self-hosted) - [Cloud](#cloud) - [Manually Update to Specific Versions](#manually-update-to-specific-versions) ## Release Process 1. **Development on `next` or Feature Branches** - Improvements, fixes, and new features are developed on the `next` branch or separate feature branches. 2. **Merging to `main`** - Once ready, changes are merged from the `next` branch into the `main` branch (via a pull request). 3. **Building the Release** - After merging to `main`, GitHub Actions automatically builds release images for all architectures and pushes them to the GitHub Container Registry and Docker Hub with the specific version tag and the `latest` tag. 4. **Creating a GitHub Release** - A new GitHub release is manually created with details of the changes made in the version. 5. **Updating the CDN** - To make a new version publicly available, the version information on the CDN needs to be updated manually. After that the new version number will be available at [https://cdn.coollabs.io/coolify/versions.json](https://cdn.coollabs.io/coolify/versions.json). > [!NOTE] > The CDN update may not occur immediately after the GitHub release. It can take hours or even days due to additional testing, stability checks, or potential hotfixes. **The update becomes available only after the CDN is updated. After the CDN is updated, a discord announcement will be made in the Production Release channel.** ## Version Types
Stable (coming soon) - **Stable** - The production version suitable for stable, production environments (recommended). - **Update Frequency:** Every 2 to 4 weeks, with more frequent possible fixes. - **Release Size:** Larger but less frequent releases. Multiple nightly versions are consolidated into a single stable release. - **Versioning Scheme:** Follows semantic versioning (e.g., `v4.0.0`, `4.1.0`, etc.). - **Installation Command:** ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ```
Nightly - **Nightly** - The latest development version, suitable for testing the latest changes and experimenting with new features. - **Update Frequency:** Daily or bi-weekly updates. - **Release Size:** Smaller, more frequent releases. - **Versioning Scheme:** Follows semantic versioning (e.g., `4.1.0-nightly.1`, `4.1.0-nightly.2`, etc.). - **Installation Command:** ```bash curl -fsSL https://cdn.coollabs.io/coolify-nightly/install.sh | bash -s next ```
Beta - **Beta** - Test releases for the upcoming stable version. - **Purpose:** Allows users to test and provide feedback on new features and changes before they become stable. - **Update Frequency:** Available if we think beta testing is necessary. - **Release Size:** Same size as stable release as it will become the next stabe release after some time. - **Versioning Scheme:** Follows semantic versioning (e.g., `4.1.0-beta.1`, `4.1.0-beta.2`, etc.). - **Installation Command:** ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ```
> [!WARNING] > Do not use nightly/beta builds in production as there is no guarantee of stability. ## Version Availability When a new version is released and a new GitHub release is created, it doesn't immediately become available for your instance. Here's how version availability works for different instance types. ### Self-Hosted - **Update Frequency:** More frequent updates, especially on the nightly release channel. - **Update Availability:** New versions are available once the CDN has been updated. - **Update Methods:** 1. **Manual Update in Instance Settings:** - Go to `Settings > Update Check Frequency` and click the `Check Manually` button. - If an update is available, an upgrade button will appear on the sidebar. 2. **Automatic Update:** - If enabled, the instance will update automatically at the time set in the settings. 3. **Re-run Installation Script:** - Run the installation script again to upgrade to the latest version available on the CDN: ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash ``` > [!IMPORTANT] > If a new release is available on GitHub but your instance hasn't updated yet or no upgrade button is shown in the UI, the CDN might not have been updated yet. This intentional delay ensures stability and allows for hotfixes before official release. ### Cloud - **Update Frequency:** Less frequent as it's a managed service. - **Update Availability:** New versions are available once Andras has updated the cloud version manually. - **Update Method:** - Updates are managed by Andras, who ensures each cloud version is thoroughly tested and stable before releasing it. > [!IMPORTANT] > The cloud version of Coolify may be several versions behind the latest GitHub releases even if the CDN is updated. This is intentional to ensure stability and reliability for cloud users and Andras will manully update the cloud version when the update is ready. ## Manually Update/ Downgrade to Specific Versions > [!CAUTION] > Updating to unreleased versions is not recommended and can cause issues. > [!IMPORTANT] > Downgrading is supported but not recommended and can cause issues because of database migrations and other changes. To update your Coolify instance to a specific version, use the following command: ```bash curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash -s ``` Replace `` with the version you want to update to (for example `4.0.0-beta.332`). ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Supported Versions Currently supported, maintained and updated versions: | Version | Supported | Support Status | | ------- | ------------------ | -------------- | | 4.x | :white_check_mark: | Active Development & Security Updates | | < 4.0 | :x: | End of Life (no security updates) | ## Security Updates We take security seriously. Security updates are released as soon as possible after a vulnerability is discovered and verified. ## Reporting a Vulnerability If you discover a security vulnerability, please follow these steps: 1. **DO NOT** disclose the vulnerability publicly. 2. Send a detailed report to: `security@coollabs.io`. 3. Include in your report: - A description of the vulnerability - Steps to reproduce the issue - Potential impact ================================================ FILE: TECH_STACK.md ================================================ # Coolify Technology Stack ## Frontend - Livewire and Alpine.js - Blade (PHP templating engine) - Tailwind CSS - Monaco Editor (Code editor component) - XTerm.js (Terminal component) ## Backend - Laravel 11 (PHP Framework) - PostgreSQL 15 (Database) - Redis 7 (Caching & Real-time features) - Soketi (WebSocket Server) ## DevOps & Infrastructure - Docker & Docker Compose - Nginx (Web Server) - S6 Overlay (Process Supervisor) - GitHub Actions (CI/CD) ## Languages - PHP 8.4 - JavaScript - Shell/Bash scripts ================================================ FILE: app/Actions/Application/CleanupPreviewDeployment.php ================================================ 0, 'killed_containers' => 0, 'status' => 'success', ]; $server = $application->destination->server; if (! $server->isFunctional()) { return [ ...$result, 'status' => 'failed', 'message' => 'Server is not functional', ]; } // Step 1: Cancel all active deployments for this PR and kill helper containers $result['cancelled_deployments'] = $this->cancelActiveDeployments( $application, $pull_request_id, $server ); // Step 2: Stop and remove all running PR containers $result['killed_containers'] = $this->stopRunningContainers( $application, $pull_request_id, $server ); // Step 3: Find or use provided preview, then dispatch cleanup job for thorough cleanup if (! $preview) { $preview = ApplicationPreview::where('application_id', $application->id) ->where('pull_request_id', $pull_request_id) ->first(); } if ($preview) { DeleteResourceJob::dispatch($preview); } return $result; } /** * Cancel all active (QUEUED/IN_PROGRESS) deployments for this PR. */ private function cancelActiveDeployments( Application $application, int $pull_request_id, $server ): int { $activeDeployments = ApplicationDeploymentQueue::where('application_id', $application->id) ->where('pull_request_id', $pull_request_id) ->whereIn('status', [ ApplicationDeploymentStatus::QUEUED->value, ApplicationDeploymentStatus::IN_PROGRESS->value, ]) ->get(); $cancelled = 0; foreach ($activeDeployments as $deployment) { try { // Mark deployment as cancelled $deployment->update([ 'status' => ApplicationDeploymentStatus::CANCELLED_BY_USER->value, ]); // Add cancellation log entry $deployment->addLogEntry('Deployment cancelled: Pull request closed.', 'stderr'); // Try to kill helper container if it exists $this->killHelperContainer($deployment->deployment_uuid, $server); $cancelled++; } catch (\Throwable $e) { \Log::warning("Failed to cancel deployment {$deployment->id}: {$e->getMessage()}"); } } return $cancelled; } /** * Kill the helper container used during deployment. */ private function killHelperContainer(string $deployment_uuid, $server): void { try { $escapedUuid = escapeshellarg($deployment_uuid); $checkCommand = "docker ps -a --filter name={$escapedUuid} --format '{{.Names}}'"; $containerExists = instant_remote_process([$checkCommand], $server); if ($containerExists && str($containerExists)->trim()->isNotEmpty()) { instant_remote_process(["docker rm -f {$escapedUuid}"], $server); } } catch (\Throwable $e) { // Silently handle - container may already be gone } } /** * Stop and remove all running containers for this PR. */ private function stopRunningContainers( Application $application, int $pull_request_id, $server ): int { $killed = 0; try { if ($server->isSwarm()) { $escapedStackName = escapeshellarg("{$application->uuid}-{$pull_request_id}"); instant_remote_process(["docker stack rm {$escapedStackName}"], $server); $killed++; } else { $containers = getCurrentApplicationContainerStatus( $server, $application->id, $pull_request_id ); if ($containers->isNotEmpty()) { foreach ($containers as $container) { $containerName = data_get($container, 'Names'); if ($containerName) { $escapedContainerName = escapeshellarg($containerName); instant_remote_process( ["docker rm -f {$escapedContainerName}"], $server ); $killed++; } } } } } catch (\Throwable $e) { \Log::warning("Error stopping containers for PR #{$pull_request_id}: {$e->getMessage()}"); } return $killed; } } ================================================ FILE: app/Actions/Application/GenerateConfig.php ================================================ generateConfig(is_json: $is_json); } } ================================================ FILE: app/Actions/Application/IsHorizonQueueEmpty.php ================================================ getRecent(); if ($recent) { $running = $recent->filter(function ($job) use ($hostname) { $payload = json_decode($job->payload); $tags = data_get($payload, 'tags'); return $job->status != 'completed' && $job->status != 'failed' && isset($tags) && is_array($tags) && in_array('server:'.$hostname, $tags); }); if ($running->count() > 0) { echo 'false'; return false; } } echo 'true'; return true; } } ================================================ FILE: app/Actions/Application/LoadComposeFile.php ================================================ loadComposeFile(); } } ================================================ FILE: app/Actions/Application/StopApplication.php ================================================ destination->server]); if ($application?->additional_servers?->count() > 0) { $servers = $servers->merge($application->additional_servers); } foreach ($servers as $server) { try { if (! $server->isFunctional()) { return 'Server is not functional'; } if ($server->isSwarm()) { instant_remote_process(["docker stack rm {$application->uuid}"], $server); return; } $containers = $previewDeployments ? getCurrentApplicationContainerStatus($server, $application->id, includePullrequests: true) : getCurrentApplicationContainerStatus($server, $application->id, 0); $containersToStop = $containers->pluck('Names')->toArray(); foreach ($containersToStop as $containerName) { instant_remote_process(command: [ "docker stop -t 30 $containerName", "docker rm -f $containerName", ], server: $server, throwError: false); } if ($application->build_pack === 'dockercompose') { $application->deleteConnectedNetworks(); } if ($dockerCleanup) { CleanupDocker::dispatch($server, false, false); } } catch (\Exception $e) { return $e->getMessage(); } } // Reset restart tracking when application is manually stopped $application->update([ 'restart_count' => 0, 'last_restart_at' => null, 'last_restart_type' => null, ]); ServiceStatusChanged::dispatch($application->environment->project->team->id); } } ================================================ FILE: app/Actions/Application/StopApplicationOneServer.php ================================================ destination->server->isSwarm()) { return; } if (! $server->isFunctional()) { return 'Server is not functional'; } try { $containers = getCurrentApplicationContainerStatus($server, $application->id, 0); if ($containers->count() > 0) { foreach ($containers as $container) { $containerName = data_get($container, 'Names'); if ($containerName) { instant_remote_process( [ "docker stop -t 30 $containerName", "docker rm -f $containerName", ], $server ); } } } } catch (\Exception $e) { return $e->getMessage(); } } } ================================================ FILE: app/Actions/CoolifyTask/PrepareCoolifyTask.php ================================================ remoteProcessArgs = $remoteProcessArgs; if ($remoteProcessArgs->model) { $properties = $remoteProcessArgs->toArray(); unset($properties['model']); $this->activity = activity() ->withProperties($properties) ->performedOn($remoteProcessArgs->model) ->event($remoteProcessArgs->type) ->log('[]'); } else { $this->activity = activity() ->withProperties($remoteProcessArgs->toArray()) ->event($remoteProcessArgs->type) ->log('[]'); } } public function __invoke(): Activity { $job = new CoolifyTask( activity: $this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors, call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish, call_event_data: $this->remoteProcessArgs->call_event_data, ); dispatch($job); $this->activity->refresh(); return $this->activity; } } ================================================ FILE: app/Actions/CoolifyTask/RunRemoteProcess.php ================================================ getExtraProperty('type') !== ActivityTypes::INLINE->value && $activity->getExtraProperty('type') !== ActivityTypes::COMMAND->value) { throw new \RuntimeException('Incompatible Activity to run a remote command.'); } $this->activity = $activity; $this->hide_from_output = $hide_from_output; $this->ignore_errors = $ignore_errors; $this->call_event_on_finish = $call_event_on_finish; $this->call_event_data = $call_event_data; } public static function decodeOutput(?Activity $activity = null): string { if (is_null($activity)) { return ''; } try { $decoded = json_decode( data_get($activity, 'description'), associative: true, flags: JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE ); } catch (\JsonException $exception) { return ''; } return collect($decoded) ->sortBy(fn ($i) => $i['order']) ->map(fn ($i) => $i['output']) ->implode(''); } public function __invoke(): ProcessResult { $this->time_start = hrtime(true); $status = ProcessStatus::IN_PROGRESS; $timeout = config('constants.ssh.command_timeout'); $process = Process::timeout($timeout)->start($this->getCommand(), $this->handleOutput(...)); $this->activity->properties = $this->activity->properties->merge([ 'process_id' => $process->id(), ]); $processResult = $process->wait(); if ($this->activity->properties->get('status') === ProcessStatus::ERROR->value) { $status = ProcessStatus::ERROR; } else { if ($processResult->exitCode() == 0) { $status = ProcessStatus::FINISHED; } else { $status = ProcessStatus::ERROR; } } $this->activity->properties = $this->activity->properties->merge([ 'exitCode' => $processResult->exitCode(), 'stdout' => $processResult->output(), 'stderr' => $processResult->errorOutput(), 'status' => $status->value, ]); $this->activity->save(); if ($this->call_event_on_finish) { try { $eventClass = "App\\Events\\$this->call_event_on_finish"; if (! is_null($this->call_event_data)) { event(new $eventClass($this->call_event_data)); } else { event(new $eventClass($this->activity->causer_id)); } } catch (\Throwable $e) { Log::error('Error calling event: '.$e->getMessage()); } } if ($processResult->exitCode() != 0 && ! $this->ignore_errors) { throw new \RuntimeException($processResult->errorOutput(), $processResult->exitCode()); } return $processResult; } protected function getCommand(): string { $server_uuid = $this->activity->getExtraProperty('server_uuid'); $command = $this->activity->getExtraProperty('command'); $server = Server::whereUuid($server_uuid)->firstOrFail(); return SshMultiplexingHelper::generateSshCommand($server, $command); } protected function handleOutput(string $type, string $output) { if ($this->hide_from_output) { return; } $this->current_time = $this->elapsedTime(); $this->activity->description = $this->encodeOutput($type, $output); if ($this->isAfterLastThrottle()) { // Let's write to database. DB::transaction(function () { $this->activity->save(); $this->last_write_at = $this->current_time; }); } } protected function elapsedTime(): int { $timeMs = (hrtime(true) - $this->time_start) / 1_000_000; return intval($timeMs); } public function encodeOutput($type, $output) { $outputStack = json_decode($this->activity->description, associative: true, flags: JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE); $outputStack[] = [ 'type' => $type, 'output' => $output, 'timestamp' => hrtime(true), 'batch' => ApplicationDeploymentJob::$batch_counter, 'order' => $this->getLatestCounter(), ]; return json_encode($outputStack, flags: JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE); } protected function getLatestCounter(): int { $description = json_decode($this->activity->description, associative: true, flags: JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE); if ($description === null || count($description) === 0) { return 1; } return end($description)['order'] + 1; } /** * Determines if it's time to write again to database. * * @return bool */ protected function isAfterLastThrottle() { // If DB was never written, then we immediately decide we have to write. if ($this->last_write_at === 0) { return true; } return ($this->current_time - $this->throttle_interval_ms) > $this->last_write_at; } } ================================================ FILE: app/Actions/Database/RestartDatabase.php ================================================ destination->server; if (! $server->isFunctional()) { return 'Server is not functional'; } StopDatabase::run($database, dockerCleanup: false); return StartDatabase::run($database); } } ================================================ FILE: app/Actions/Database/StartClickhouse.php ================================================ database = $database; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ "echo 'Starting database.'", "mkdir -p $this->configuration_dir", ]; $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'ulimits' => [ 'nofile' => [ 'soft' => 262144, 'hard' => 262144, ], ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => "clickhouse-client --user {$this->database->clickhouse_admin_user} --password {$this->database->clickhouse_admin_password} --query 'SELECT 1'", 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (! is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = $persistent_storages; } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray(); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_USER'))->isEmpty()) { $environment_variables->push("CLICKHOUSE_USER={$this->database->clickhouse_admin_user}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_PASSWORD'))->isEmpty()) { $environment_variables->push("CLICKHOUSE_PASSWORD={$this->database->clickhouse_admin_password}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_DB'))->isEmpty()) { $environment_variables->push("CLICKHOUSE_DB={$this->database->clickhouse_db}"); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } } ================================================ FILE: app/Actions/Database/StartDatabase.php ================================================ destination->server; if (! $server->isFunctional()) { return 'Server is not functional'; } switch ($database->getMorphClass()) { case \App\Models\StandalonePostgresql::class: $activity = StartPostgresql::run($database); break; case \App\Models\StandaloneRedis::class: $activity = StartRedis::run($database); break; case \App\Models\StandaloneMongodb::class: $activity = StartMongodb::run($database); break; case \App\Models\StandaloneMysql::class: $activity = StartMysql::run($database); break; case \App\Models\StandaloneMariadb::class: $activity = StartMariadb::run($database); break; case \App\Models\StandaloneKeydb::class: $activity = StartKeydb::run($database); break; case \App\Models\StandaloneDragonfly::class: $activity = StartDragonfly::run($database); break; case \App\Models\StandaloneClickhouse::class: $activity = StartClickhouse::run($database); break; } if ($database->is_public && $database->public_port) { StartDatabaseProxy::dispatch($database); } return $activity; } } ================================================ FILE: app/Actions/Database/StartDatabaseProxy.php ================================================ database_type; $network = data_get($database, 'destination.network'); $server = data_get($database, 'destination.server'); $containerName = data_get($database, 'uuid'); $proxyContainerName = "{$database->uuid}-proxy"; $isSSLEnabled = $database->enable_ssl ?? false; if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) { $databaseType = $database->databaseType(); $network = $database->service->uuid; $server = data_get($database, 'service.destination.server'); $containerName = "{$database->name}-{$database->service->uuid}"; } $internalPort = match ($databaseType) { 'standalone-mariadb', 'standalone-mysql' => 3306, 'standalone-postgresql', 'standalone-supabase/postgres' => 5432, 'standalone-redis', 'standalone-keydb', 'standalone-dragonfly' => 6379, 'standalone-clickhouse' => 9000, 'standalone-mongodb' => 27017, default => throw new \Exception("Unsupported database type: $databaseType"), }; if ($isSSLEnabled) { $internalPort = match ($databaseType) { 'standalone-redis', 'standalone-keydb', 'standalone-dragonfly' => 6380, default => $internalPort, }; } $configuration_dir = database_proxy_dir($database->uuid); $host_configuration_dir = $configuration_dir; if (isDev()) { $host_configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy'; } $timeoutConfig = $this->buildProxyTimeoutConfig($database->public_port_timeout); $nginxconf = <<public_port; proxy_pass $containerName:$internalPort; $timeoutConfig } } EOF; $docker_compose = [ 'services' => [ $proxyContainerName => [ 'image' => 'nginx:stable-alpine', 'container_name' => $proxyContainerName, 'restart' => RESTART_MODE, 'ports' => [ "$database->public_port:$database->public_port", ], 'networks' => [ $network, ], 'volumes' => [ [ 'type' => 'bind', 'source' => "$host_configuration_dir/nginx.conf", 'target' => '/etc/nginx/nginx.conf', ], ], 'healthcheck' => [ 'test' => [ 'CMD-SHELL', 'stat /etc/nginx/nginx.conf || exit 1', ], 'interval' => '5s', 'timeout' => '5s', 'retries' => 3, 'start_period' => '1s', ], ], ], 'networks' => [ $network => [ 'external' => true, 'name' => $network, 'attachable' => true, ], ], ]; $dockercompose_base64 = base64_encode(Yaml::dump($docker_compose, 4, 2)); $nginxconf_base64 = base64_encode($nginxconf); instant_remote_process(["docker rm -f $proxyContainerName"], $server, false); try { instant_remote_process([ "mkdir -p $configuration_dir", "echo '{$nginxconf_base64}' | base64 -d | tee $configuration_dir/nginx.conf > /dev/null", "echo '{$dockercompose_base64}' | base64 -d | tee $configuration_dir/docker-compose.yaml > /dev/null", "docker compose --project-directory {$configuration_dir} pull", "docker compose --project-directory {$configuration_dir} up -d", ], $server); } catch (\RuntimeException $e) { if ($this->isNonTransientError($e->getMessage())) { $database->update(['is_public' => false]); $team = data_get($database, 'environment.project.team') ?? data_get($database, 'service.environment.project.team'); $team?->notify( new \App\Notifications\Container\ContainerRestarted( "TCP Proxy for {$database->name} database has been disabled due to error: {$e->getMessage()}", $server, ) ); ray("Database proxy for {$database->name} disabled due to non-transient error: {$e->getMessage()}"); return; } throw $e; } } private function isNonTransientError(string $message): bool { $nonTransientPatterns = [ 'port is already allocated', 'address already in use', 'Bind for', ]; foreach ($nonTransientPatterns as $pattern) { if (str_contains($message, $pattern)) { return true; } } return false; } private function buildProxyTimeoutConfig(?int $timeout): string { if ($timeout === null || $timeout < 1) { $timeout = 3600; } return "proxy_timeout {$timeout}s;"; } } ================================================ FILE: app/Actions/Database/StartDragonfly.php ================================================ database = $database; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ "echo 'Starting database.'", "echo 'Creating directories.'", "mkdir -p $this->configuration_dir", "echo 'Directories created successfully.'", ]; if (! $this->database->enable_ssl) { $this->commands[] = "rm -rf $this->configuration_dir/ssl"; $this->database->sslCertificates()->delete(); $this->database->fileStorages() ->where('resource_type', $this->database->getMorphClass()) ->where('resource_id', $this->database->id) ->get() ->filter(function ($storage) { return in_array($storage->mount_path, [ '/etc/dragonfly/certs/server.crt', '/etc/dragonfly/certs/server.key', ]); }) ->each(function ($storage) { $storage->delete(); }); } else { $this->commands[] = "echo 'Setting up SSL for this database.'"; $this->commands[] = "mkdir -p $this->configuration_dir/ssl"; $server = $this->database->destination->server; $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { $this->commands[] = "echo 'No SSL certificate found, generating new SSL certificate for this database.'"; $this->ssl_certificate = SslHelper::generateSslCertificate( commonName: $this->database->uuid, resourceType: $this->database->getMorphClass(), resourceId: $this->database->id, serverId: $server->id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $this->configuration_dir, mountPath: '/etc/dragonfly/certs', ); } } $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $startCommand = $this->buildStartCommand(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'command' => $startCommand, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => "redis-cli -a {$this->database->dragonfly_password} ping", 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (! is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } $docker_compose['services'][$container_name]['volumes'] ??= []; if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_storages ); } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray() ); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => '/data/coolify/ssl/coolify-ca.crt', 'target' => '/etc/dragonfly/certs/coolify-ca.crt', 'read_only' => true, ], ] ); } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; if ($this->database->enable_ssl) { $this->commands[] = "chown -R 999:999 $this->configuration_dir/ssl/server.key $this->configuration_dir/ssl/server.crt"; } $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function buildStartCommand(): string { $command = "dragonfly --requirepass {$this->database->dragonfly_password}"; if ($this->database->enable_ssl) { $sslArgs = [ '--tls', '--tls_cert_file /etc/dragonfly/certs/server.crt', '--tls_key_file /etc/dragonfly/certs/server.key', '--tls_ca_cert_file /etc/dragonfly/certs/coolify-ca.crt', ]; $command .= ' '.implode(' ', $sslArgs); } return $command; } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) { $environment_variables->push("REDIS_PASSWORD={$this->database->dragonfly_password}"); } return $environment_variables->all(); } } ================================================ FILE: app/Actions/Database/StartKeydb.php ================================================ database = $database; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ "echo 'Starting database.'", "echo 'Creating directories.'", "mkdir -p $this->configuration_dir", "echo 'Directories created successfully.'", ]; if (! $this->database->enable_ssl) { $this->commands[] = "rm -rf $this->configuration_dir/ssl"; $this->database->sslCertificates()->delete(); $this->database->fileStorages() ->where('resource_type', $this->database->getMorphClass()) ->where('resource_id', $this->database->id) ->get() ->filter(function ($storage) { return in_array($storage->mount_path, [ '/etc/keydb/certs/server.crt', '/etc/keydb/certs/server.key', ]); }) ->each(function ($storage) { $storage->delete(); }); } else { $this->commands[] = "echo 'Setting up SSL for this database.'"; $this->commands[] = "mkdir -p $this->configuration_dir/ssl"; $server = $this->database->destination->server; $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { $this->commands[] = "echo 'No SSL certificate found, generating new SSL certificate for this database.'"; $this->ssl_certificate = SslHelper::generateSslCertificate( commonName: $this->database->uuid, resourceType: $this->database->getMorphClass(), resourceId: $this->database->id, serverId: $server->id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $this->configuration_dir, mountPath: '/etc/keydb/certs', ); } } $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->add_custom_keydb(); $startCommand = $this->buildStartCommand(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'command' => $startCommand, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => "keydb-cli --pass {$this->database->keydb_password} ping", 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (! is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } $docker_compose['services'][$container_name]['volumes'] ??= []; if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], $persistent_storages ); } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray() ); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } if (! is_null($this->database->keydb_conf) || ! empty($this->database->keydb_conf)) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => $this->configuration_dir.'/keydb.conf', 'target' => '/etc/keydb/keydb.conf', 'read_only' => true, ], ] ); } if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => '/data/coolify/ssl/coolify-ca.crt', 'target' => '/etc/keydb/certs/coolify-ca.crt', 'read_only' => true, ], ] ); } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; if ($this->database->enable_ssl) { $this->commands[] = "chown -R 999:999 $this->configuration_dir/ssl/server.key $this->configuration_dir/ssl/server.crt"; } if (! is_null($this->database->keydb_conf) && ! empty($this->database->keydb_conf)) { $this->commands[] = "chown 999:999 $this->configuration_dir/keydb.conf"; } $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) { $environment_variables->push("REDIS_PASSWORD={$this->database->keydb_password}"); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } private function add_custom_keydb() { if (is_null($this->database->keydb_conf) || empty($this->database->keydb_conf)) { return; } $filename = 'keydb.conf'; $content = $this->database->keydb_conf; $content_base64 = base64_encode($content); $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null"; } private function buildStartCommand(): string { $hasKeydbConf = ! is_null($this->database->keydb_conf) && ! empty($this->database->keydb_conf); $keydbConfPath = '/etc/keydb/keydb.conf'; if ($hasKeydbConf) { $confContent = $this->database->keydb_conf; $hasRequirePass = str_contains($confContent, 'requirepass'); if ($hasRequirePass) { $command = "keydb-server $keydbConfPath"; } else { $command = "keydb-server $keydbConfPath --requirepass {$this->database->keydb_password}"; } } else { $command = "keydb-server --requirepass {$this->database->keydb_password} --appendonly yes"; } if ($this->database->enable_ssl) { $sslArgs = [ '--tls-port 6380', '--tls-cert-file /etc/keydb/certs/server.crt', '--tls-key-file /etc/keydb/certs/server.key', '--tls-ca-cert-file /etc/keydb/certs/coolify-ca.crt', '--tls-auth-clients optional', ]; $command .= ' '.implode(' ', $sslArgs); } return $command; } } ================================================ FILE: app/Actions/Database/StartMariadb.php ================================================ database = $database; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ "echo 'Starting database.'", "echo 'Creating directories.'", "mkdir -p $this->configuration_dir", "echo 'Directories created successfully.'", ]; if (! $this->database->enable_ssl) { $this->commands[] = "rm -rf $this->configuration_dir/ssl"; $this->database->sslCertificates()->delete(); $this->database->fileStorages() ->where('resource_type', $this->database->getMorphClass()) ->where('resource_id', $this->database->id) ->get() ->filter(function ($storage) { return in_array($storage->mount_path, [ '/etc/mysql/certs/server.crt', '/etc/mysql/certs/server.key', ]); }) ->each(function ($storage) { $storage->delete(); }); } else { $this->commands[] = "echo 'Setting up SSL for this database.'"; $this->commands[] = "mkdir -p $this->configuration_dir/ssl"; $server = $this->database->destination->server; $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { $this->commands[] = "echo 'No SSL certificate found, generating new SSL certificate for this database.'"; $this->ssl_certificate = SslHelper::generateSslCertificate( commonName: $this->database->uuid, resourceType: $this->database->getMorphClass(), resourceId: $this->database->id, serverId: $server->id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $this->configuration_dir, mountPath: '/etc/mysql/certs', ); } } $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->add_custom_mysql(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => ['CMD', 'healthcheck.sh', '--connect', '--innodb_initialized'], 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (! is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } $docker_compose['services'][$container_name]['volumes'] ??= []; if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_storages ); } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray() ); } if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => '/data/coolify/ssl/coolify-ca.crt', 'target' => '/etc/mysql/certs/coolify-ca.crt', 'read_only' => true, ], ] ); } if (! is_null($this->database->mariadb_conf) || ! empty($this->database->mariadb_conf)) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], [ [ 'type' => 'bind', 'source' => $this->configuration_dir.'/custom-config.cnf', 'target' => '/etc/mysql/conf.d/custom-config.cnf', 'read_only' => true, ], ] ); } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['command'] = [ 'mariadbd', '--ssl-cert=/etc/mysql/certs/server.crt', '--ssl-key=/etc/mysql/certs/server.key', '--ssl-ca=/etc/mysql/certs/coolify-ca.crt', '--require-secure-transport=1', ]; } $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; if ($this->database->enable_ssl) { $this->commands[] = executeInDocker($this->database->uuid, 'chown mysql:mysql /etc/mysql/certs/server.crt /etc/mysql/certs/server.key'); } return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_ROOT_PASSWORD'))->isEmpty()) { $environment_variables->push("MARIADB_ROOT_PASSWORD={$this->database->mariadb_root_password}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_DATABASE'))->isEmpty()) { $environment_variables->push("MARIADB_DATABASE={$this->database->mariadb_database}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_USER'))->isEmpty()) { $environment_variables->push("MARIADB_USER={$this->database->mariadb_user}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_PASSWORD'))->isEmpty()) { $environment_variables->push("MARIADB_PASSWORD={$this->database->mariadb_password}"); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } private function add_custom_mysql() { if (is_null($this->database->mariadb_conf) || empty($this->database->mariadb_conf)) { return; } $filename = 'custom-config.cnf'; $content = $this->database->mariadb_conf; $content_base64 = base64_encode($content); $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null"; } } ================================================ FILE: app/Actions/Database/StartMongodb.php ================================================ database = $database; $startCommand = 'mongod'; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; if (isDev()) { $this->configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$container_name; } $this->commands = [ "echo 'Starting database.'", "echo 'Creating directories.'", "mkdir -p $this->configuration_dir", "echo 'Directories created successfully.'", ]; if (! $this->database->enable_ssl) { $this->commands[] = "rm -rf $this->configuration_dir/ssl"; $this->database->sslCertificates()->delete(); $this->database->fileStorages() ->where('resource_type', $this->database->getMorphClass()) ->where('resource_id', $this->database->id) ->get() ->filter(function ($storage) { return in_array($storage->mount_path, [ '/etc/mongo/certs/server.pem', ]); }) ->each(function ($storage) { $storage->delete(); }); } else { $this->commands[] = "echo 'Setting up SSL for this database.'"; $this->commands[] = "mkdir -p $this->configuration_dir/ssl"; $server = $this->database->destination->server; $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { $this->commands[] = "echo 'No SSL certificate found, generating new SSL certificate for this database.'"; $this->ssl_certificate = SslHelper::generateSslCertificate( commonName: $this->database->uuid, resourceType: $this->database->getMorphClass(), resourceId: $this->database->id, serverId: $server->id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $this->configuration_dir, mountPath: '/etc/mongo/certs', isPemKeyFileRequired: true, ); } } $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->add_custom_mongo_conf(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'command' => $startCommand, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => [ 'CMD', 'echo', 'ok', ], 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (! is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } $docker_compose['services'][$container_name]['volumes'] ??= []; if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], $persistent_storages ); } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray() ); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } if (! empty($this->database->mongo_conf)) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [[ 'type' => 'bind', 'source' => $this->configuration_dir.'/mongod.conf', 'target' => '/etc/mongo/mongod.conf', 'read_only' => true, ]] ); $docker_compose['services'][$container_name]['command'] = ['mongod', '--config', '/etc/mongo/mongod.conf']; } $this->add_default_database(); $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [[ 'type' => 'bind', 'source' => $this->configuration_dir.'/docker-entrypoint-initdb.d', 'target' => '/docker-entrypoint-initdb.d', 'read_only' => true, ]] ); if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => '/data/coolify/ssl/coolify-ca.crt', 'target' => '/etc/mongo/certs/ca.pem', 'read_only' => true, ], ] ); } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); if ($this->database->enable_ssl) { $commandParts = ['mongod']; if (! empty($this->database->mongo_conf)) { $commandParts = ['mongod', '--config', '/etc/mongo/mongod.conf']; } $sslConfig = match ($this->database->ssl_mode) { 'allow' => [ '--tlsMode=allowTLS', '--tlsAllowConnectionsWithoutCertificates', '--tlsAllowInvalidHostnames', ], 'prefer' => [ '--tlsMode=preferTLS', '--tlsAllowConnectionsWithoutCertificates', '--tlsAllowInvalidHostnames', ], 'require' => [ '--tlsMode=requireTLS', '--tlsAllowConnectionsWithoutCertificates', '--tlsAllowInvalidHostnames', ], 'verify-full' => [ '--tlsMode=requireTLS', '--tlsAllowInvalidHostnames', ], default => [], }; $commandParts = [...$commandParts, ...$sslConfig]; $commandParts[] = '--tlsCAFile'; $commandParts[] = '/etc/mongo/certs/ca.pem'; $commandParts[] = '--tlsCertificateKeyFile'; $commandParts[] = '/etc/mongo/certs/server.pem'; $docker_compose['services'][$container_name]['command'] = $commandParts; } $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; if ($this->database->enable_ssl) { $this->commands[] = executeInDocker($this->database->uuid, 'chown mongodb:mongodb /etc/mongo/certs/server.pem'); } $this->commands[] = "echo 'Database started.'"; return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MONGO_INITDB_ROOT_USERNAME'))->isEmpty()) { $environment_variables->push("MONGO_INITDB_ROOT_USERNAME={$this->database->mongo_initdb_root_username}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MONGO_INITDB_ROOT_PASSWORD'))->isEmpty()) { $environment_variables->push("MONGO_INITDB_ROOT_PASSWORD={$this->database->mongo_initdb_root_password}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MONGO_INITDB_DATABASE'))->isEmpty()) { $environment_variables->push("MONGO_INITDB_DATABASE={$this->database->mongo_initdb_database}"); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } private function add_custom_mongo_conf() { if (is_null($this->database->mongo_conf) || empty($this->database->mongo_conf)) { return; } $filename = 'mongod.conf'; $content = $this->database->mongo_conf; $content_base64 = base64_encode($content); $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null"; } private function add_default_database() { $content = "db = db.getSiblingDB(\"{$this->database->mongo_initdb_database}\");db.createCollection('init_collection');db.createUser({user: \"{$this->database->mongo_initdb_root_username}\", pwd: \"{$this->database->mongo_initdb_root_password}\",roles: [{role:\"readWrite\",db:\"{$this->database->mongo_initdb_database}\"}]});"; $content_base64 = base64_encode($content); $this->commands[] = "mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d"; $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/docker-entrypoint-initdb.d/01-default-database.js > /dev/null"; } } ================================================ FILE: app/Actions/Database/StartMysql.php ================================================ database = $database; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ "echo 'Starting database.'", "echo 'Creating directories.'", "mkdir -p $this->configuration_dir", "echo 'Directories created successfully.'", ]; if (! $this->database->enable_ssl) { $this->commands[] = "rm -rf $this->configuration_dir/ssl"; $this->database->sslCertificates()->delete(); $this->database->fileStorages() ->where('resource_type', $this->database->getMorphClass()) ->where('resource_id', $this->database->id) ->get() ->filter(function ($storage) { return in_array($storage->mount_path, [ '/etc/mysql/certs/server.crt', '/etc/mysql/certs/server.key', ]); }) ->each(function ($storage) { $storage->delete(); }); } else { $this->commands[] = "echo 'Setting up SSL for this database.'"; $this->commands[] = "mkdir -p $this->configuration_dir/ssl"; $server = $this->database->destination->server; $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { $this->commands[] = "echo 'No SSL certificate found, generating new SSL certificate for this database.'"; $this->ssl_certificate = SslHelper::generateSslCertificate( commonName: $this->database->uuid, resourceType: $this->database->getMorphClass(), resourceId: $this->database->id, serverId: $server->id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $this->configuration_dir, mountPath: '/etc/mysql/certs', ); } } $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->add_custom_mysql(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => ['CMD', 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', "-p{$this->database->mysql_root_password}"], 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (! is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } $docker_compose['services'][$container_name]['volumes'] ??= []; if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], $persistent_storages ); } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray() ); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => '/data/coolify/ssl/coolify-ca.crt', 'target' => '/etc/mysql/certs/coolify-ca.crt', 'read_only' => true, ], ] ); } if (! is_null($this->database->mysql_conf) || ! empty($this->database->mysql_conf)) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => $this->configuration_dir.'/custom-config.cnf', 'target' => '/etc/mysql/conf.d/custom-config.cnf', 'read_only' => true, ], ] ); } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['command'] = [ 'mysqld', '--ssl-cert=/etc/mysql/certs/server.crt', '--ssl-key=/etc/mysql/certs/server.key', '--ssl-ca=/etc/mysql/certs/coolify-ca.crt', '--require-secure-transport=1', ]; } $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; if ($this->database->enable_ssl) { $this->commands[] = executeInDocker($this->database->uuid, "chown {$this->database->mysql_user}:{$this->database->mysql_user} /etc/mysql/certs/server.crt /etc/mysql/certs/server.key"); } $this->commands[] = "echo 'Database started.'"; return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_ROOT_PASSWORD'))->isEmpty()) { $environment_variables->push("MYSQL_ROOT_PASSWORD={$this->database->mysql_root_password}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_DATABASE'))->isEmpty()) { $environment_variables->push("MYSQL_DATABASE={$this->database->mysql_database}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_USER'))->isEmpty()) { $environment_variables->push("MYSQL_USER={$this->database->mysql_user}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_PASSWORD'))->isEmpty()) { $environment_variables->push("MYSQL_PASSWORD={$this->database->mysql_password}"); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } private function add_custom_mysql() { if (is_null($this->database->mysql_conf) || empty($this->database->mysql_conf)) { return; } $filename = 'custom-config.cnf'; $content = $this->database->mysql_conf; $content_base64 = base64_encode($content); $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null"; } } ================================================ FILE: app/Actions/Database/StartPostgresql.php ================================================ database = $database; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; if (isDev()) { $this->configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$container_name; } $this->commands = [ "echo 'Starting database.'", "echo 'Creating directories.'", "mkdir -p $this->configuration_dir", "mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d/", "echo 'Directories created successfully.'", ]; if (! $this->database->enable_ssl) { $this->commands[] = "rm -rf $this->configuration_dir/ssl"; $this->database->sslCertificates()->delete(); $this->database->fileStorages() ->where('resource_type', $this->database->getMorphClass()) ->where('resource_id', $this->database->id) ->get() ->filter(function ($storage) { return in_array($storage->mount_path, [ '/var/lib/postgresql/certs/server.crt', '/var/lib/postgresql/certs/server.key', ]); }) ->each(function ($storage) { $storage->delete(); }); } else { $this->commands[] = "echo 'Setting up SSL for this database.'"; $this->commands[] = "mkdir -p $this->configuration_dir/ssl"; $server = $this->database->destination->server; $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { $this->commands[] = "echo 'No SSL certificate found, generating new SSL certificate for this database.'"; $this->ssl_certificate = SslHelper::generateSslCertificate( commonName: $this->database->uuid, resourceType: $this->database->getMorphClass(), resourceId: $this->database->id, serverId: $server->id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $this->configuration_dir, mountPath: '/var/lib/postgresql/certs', ); } } $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->generate_init_scripts(); $this->add_custom_conf(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => [ 'CMD-SHELL', "psql -U {$this->database->postgres_user} -d {$this->database->postgres_db} -c 'SELECT 1' || exit 1", ], 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (filled($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } $docker_compose['services'][$container_name]['volumes'] ??= []; if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_storages ); } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray() ); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } if (count($this->init_scripts) > 0) { foreach ($this->init_scripts as $init_script) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], [[ 'type' => 'bind', 'source' => $init_script, 'target' => '/docker-entrypoint-initdb.d/'.basename($init_script), 'read_only' => true, ]] ); } } $command = ['postgres']; if (filled($this->database->postgres_conf)) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], [[ 'type' => 'bind', 'source' => $this->configuration_dir.'/custom-postgres.conf', 'target' => '/etc/postgresql/postgresql.conf', 'read_only' => true, ]] ); $command = array_merge($command, ['-c', 'config_file=/etc/postgresql/postgresql.conf']); } if ($this->database->enable_ssl) { $command = array_merge($command, [ '-c', 'ssl=on', '-c', 'ssl_cert_file=/var/lib/postgresql/certs/server.crt', '-c', 'ssl_key_file=/var/lib/postgresql/certs/server.key', ]); } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); if (count($command) > 1) { $docker_compose['services'][$container_name]['command'] = $command; } $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; if ($this->database->enable_ssl) { $this->commands[] = executeInDocker($this->database->uuid, "chown {$this->database->postgres_user}:{$this->database->postgres_user} /var/lib/postgresql/certs/server.key /var/lib/postgresql/certs/server.crt"); } $this->commands[] = "echo 'Database started.'"; return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('POSTGRES_USER'))->isEmpty()) { $environment_variables->push("POSTGRES_USER={$this->database->postgres_user}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('PGUSER'))->isEmpty()) { $environment_variables->push("PGUSER={$this->database->postgres_user}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('POSTGRES_PASSWORD'))->isEmpty()) { $environment_variables->push("POSTGRES_PASSWORD={$this->database->postgres_password}"); } if ($environment_variables->filter(fn ($env) => str($env)->contains('POSTGRES_DB'))->isEmpty()) { $environment_variables->push("POSTGRES_DB={$this->database->postgres_db}"); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } private function generate_init_scripts() { $this->commands[] = "rm -rf $this->configuration_dir/docker-entrypoint-initdb.d/*"; if (blank($this->database->init_scripts) || count($this->database->init_scripts) === 0) { return; } foreach ($this->database->init_scripts as $init_script) { $filename = data_get($init_script, 'filename'); $content = data_get($init_script, 'content'); $content_base64 = base64_encode($content); $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/docker-entrypoint-initdb.d/{$filename} > /dev/null"; $this->init_scripts[] = "$this->configuration_dir/docker-entrypoint-initdb.d/{$filename}"; } } private function add_custom_conf() { $filename = 'custom-postgres.conf'; $config_file_path = "$this->configuration_dir/$filename"; if (blank($this->database->postgres_conf)) { $this->commands[] = "rm -f $config_file_path"; return; } $content = $this->database->postgres_conf; if (! str($content)->contains('listen_addresses')) { $content .= "\nlisten_addresses = '*'"; $this->database->postgres_conf = $content; $this->database->save(); } $content_base64 = base64_encode($content); $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $config_file_path > /dev/null"; } } ================================================ FILE: app/Actions/Database/StartRedis.php ================================================ database = $database; $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ "echo 'Starting database.'", "echo 'Creating directories.'", "mkdir -p $this->configuration_dir", "echo 'Directories created successfully.'", ]; if (! $this->database->enable_ssl) { $this->commands[] = "rm -rf $this->configuration_dir/ssl"; $this->database->sslCertificates()->delete(); $this->database->fileStorages() ->where('resource_type', $this->database->getMorphClass()) ->where('resource_id', $this->database->id) ->get() ->filter(function ($storage) { return in_array($storage->mount_path, [ '/etc/redis/certs/server.crt', '/etc/redis/certs/server.key', ]); }) ->each(function ($storage) { $storage->delete(); }); } else { $this->commands[] = "echo 'Setting up SSL for this database.'"; $this->commands[] = "mkdir -p $this->configuration_dir/ssl"; $server = $this->database->destination->server; $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } $this->ssl_certificate = $this->database->sslCertificates()->first(); if (! $this->ssl_certificate) { $this->commands[] = "echo 'No SSL certificate found, generating new SSL certificate for this database.'"; $this->ssl_certificate = SslHelper::generateSslCertificate( commonName: $this->database->uuid, resourceType: $this->database->getMorphClass(), resourceId: $this->database->id, serverId: $server->id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $this->configuration_dir, mountPath: '/etc/redis/certs', ); } } $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->add_custom_redis(); $startCommand = $this->buildStartCommand(); $docker_compose = [ 'services' => [ $container_name => [ 'image' => $this->database->image, 'command' => $startCommand, 'container_name' => $container_name, 'environment' => $environment_variables, 'restart' => RESTART_MODE, 'networks' => [ $this->database->destination->network, ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ 'test' => [ 'CMD-SHELL', 'redis-cli', 'ping', ], 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, 'start_period' => '5s', ], 'mem_limit' => $this->database->limits_memory, 'memswap_limit' => $this->database->limits_memory_swap, 'mem_swappiness' => $this->database->limits_memory_swappiness, 'mem_reservation' => $this->database->limits_memory_reservation, 'cpus' => (float) $this->database->limits_cpus, 'cpu_shares' => $this->database->limits_cpu_shares, ], ], 'networks' => [ $this->database->destination->network => [ 'external' => true, 'name' => $this->database->destination->network, 'attachable' => true, ], ], ]; if (! is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; } $docker_compose['services'][$container_name]['volumes'] ??= []; if (count($persistent_storages) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_storages ); } if (count($persistent_file_volumes) > 0) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray() ); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } if ($this->database->enable_ssl) { $docker_compose['services'][$container_name]['volumes'] = array_merge( $docker_compose['services'][$container_name]['volumes'] ?? [], [ [ 'type' => 'bind', 'source' => '/data/coolify/ssl/coolify-ca.crt', 'target' => '/etc/redis/certs/coolify-ca.crt', 'read_only' => true, ], ] ); } if (! is_null($this->database->redis_conf) || ! empty($this->database->redis_conf)) { $docker_compose['services'][$container_name]['volumes'][] = [ 'type' => 'bind', 'source' => $this->configuration_dir.'/redis.conf', 'target' => '/usr/local/etc/redis/redis.conf', 'read_only' => true, ]; } // Add custom docker run options $docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options); $docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; $readme = generate_readme_file($this->database->name, now()); $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; $this->commands[] = "echo 'Pulling {$database->image} image.'"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; if ($this->database->enable_ssl) { $this->commands[] = "chown -R 999:999 $this->configuration_dir/ssl/server.key $this->configuration_dir/ssl/server.crt"; } if (! is_null($this->database->redis_conf) && ! empty($this->database->redis_conf)) { $this->commands[] = "chown 999:999 $this->configuration_dir/redis.conf"; } $this->commands[] = "docker stop -t 10 $container_name 2>/dev/null || true"; $this->commands[] = "docker rm -f $container_name 2>/dev/null || true"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "echo 'Database started.'"; return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $local_persistent_volumes[] = $persistentStorage->host_path.':'.$persistentStorage->mount_path; } else { $volume_name = $persistentStorage->name; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->database->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_environment_variables() { $environment_variables = collect(); foreach ($this->database->runtime_environment_variables as $env) { if ($env->is_shared) { $environment_variables->push("$env->key=$env->real_value"); if ($env->key === 'REDIS_PASSWORD') { $this->database->update(['redis_password' => $env->real_value]); } if ($env->key === 'REDIS_USERNAME') { $this->database->update(['redis_username' => $env->real_value]); } } else { if ($env->key === 'REDIS_PASSWORD') { $env->update(['value' => $this->database->redis_password]); } elseif ($env->key === 'REDIS_USERNAME') { $env->update(['value' => $this->database->redis_username]); } $environment_variables->push("$env->key=$env->real_value"); } } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } private function buildStartCommand(): string { $hasRedisConf = ! is_null($this->database->redis_conf) && ! empty($this->database->redis_conf); $redisConfPath = '/usr/local/etc/redis/redis.conf'; if ($hasRedisConf) { $confContent = $this->database->redis_conf; $hasRequirePass = str_contains($confContent, 'requirepass'); if ($hasRequirePass) { $command = "redis-server $redisConfPath"; } else { $command = "redis-server $redisConfPath --requirepass {$this->database->redis_password}"; } } else { $command = "redis-server --requirepass {$this->database->redis_password} --appendonly yes"; } if ($this->database->enable_ssl) { $sslArgs = [ '--tls-port 6380', '--tls-cert-file /etc/redis/certs/server.crt', '--tls-key-file /etc/redis/certs/server.key', '--tls-ca-cert-file /etc/redis/certs/coolify-ca.crt', '--tls-auth-clients optional', ]; } if (! empty($sslArgs)) { $command .= ' '.implode(' ', $sslArgs); } return $command; } private function add_custom_redis() { if (is_null($this->database->redis_conf) || empty($this->database->redis_conf)) { return; } $filename = 'redis.conf'; $content = $this->database->redis_conf; $content_base64 = base64_encode($content); $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null"; } } ================================================ FILE: app/Actions/Database/StopDatabase.php ================================================ destination->server; if (! $server->isFunctional()) { return 'Server is not functional'; } $this->stopContainer($database, $database->uuid, 30); // Reset restart tracking when database is manually stopped $database->update([ 'restart_count' => 0, 'last_restart_at' => null, 'last_restart_type' => null, ]); if ($dockerCleanup) { CleanupDocker::dispatch($server, false, false); } if ($database->is_public) { StopDatabaseProxy::run($database); } return 'Database stopped successfully'; } catch (\Exception $e) { return 'Database stop failed: '.$e->getMessage(); } finally { ServiceStatusChanged::dispatch($database->environment->project->team->id); } } private function stopContainer($database, string $containerName, int $timeout = 30): void { $server = $database->destination->server; instant_remote_process(command: [ "docker stop -t $timeout $containerName", "docker rm -f $containerName", ], server: $server, throwError: false); } } ================================================ FILE: app/Actions/Database/StopDatabaseProxy.php ================================================ uuid; if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) { $server = data_get($database, 'service.server'); } instant_remote_process(["docker rm -f {$uuid}-proxy"], $server); $database->save(); DatabaseProxyStopped::dispatch(); } } ================================================ FILE: app/Actions/Docker/GetContainersStatus.php ================================================ containers = $containers; $this->containerReplicates = $containerReplicates; $this->server = $server; if (! $this->server->isFunctional()) { return 'Server is not functional.'; } $this->applications = $this->server->applications(); $skip_these_applications = collect([]); foreach ($this->applications as $application) { if ($application->additional_servers->count() > 0) { $skip_these_applications->push($application); ComplexStatusCheck::run($application); $this->applications = $this->applications->filter(function ($value, $key) use ($application) { return $value->id !== $application->id; }); } } $this->applications = $this->applications->filter(function ($value, $key) use ($skip_these_applications) { return ! $skip_these_applications->pluck('id')->contains($value->id); }); if ($this->containers === null) { ['containers' => $this->containers, 'containerReplicates' => $this->containerReplicates] = $this->server->getContainers(); } if (is_null($this->containers)) { return; } if ($this->containerReplicates) { foreach ($this->containerReplicates as $containerReplica) { $name = data_get($containerReplica, 'Name'); $this->containers = $this->containers->map(function ($container) use ($name, $containerReplica) { if (data_get($container, 'Spec.Name') === $name) { $replicas = data_get($containerReplica, 'Replicas'); $running = str($replicas)->explode('/')[0]; $total = str($replicas)->explode('/')[1]; if ($running === $total) { data_set($container, 'State.Status', 'running'); data_set($container, 'State.Health.Status', 'healthy'); } else { data_set($container, 'State.Status', 'starting'); data_set($container, 'State.Health.Status', 'unhealthy'); } } return $container; }); } } $databases = $this->server->databases(); $services = $this->server->services()->get(); $previews = $this->server->previews(); $foundApplications = []; $foundApplicationPreviews = []; $foundDatabases = []; $foundServices = []; foreach ($this->containers as $container) { if ($this->server->isSwarm()) { $labels = data_get($container, 'Spec.Labels'); $uuid = data_get($labels, 'coolify.name'); } else { $labels = data_get($container, 'Config.Labels'); } $containerStatus = data_get($container, 'State.Status'); $containerHealth = data_get($container, 'State.Health.Status'); if ($containerStatus === 'restarting') { $healthSuffix = $containerHealth ?? 'unknown'; $containerStatus = "restarting:$healthSuffix"; } elseif ($containerStatus === 'exited') { // Keep as-is, no health suffix for exited containers } else { $healthSuffix = $containerHealth ?? 'unknown'; $containerStatus = "$containerStatus:$healthSuffix"; } $labels = Arr::undot(format_docker_labels_to_json($labels)); $applicationId = data_get($labels, 'coolify.applicationId'); if ($applicationId) { $pullRequestId = data_get($labels, 'coolify.pullRequestId'); if ($pullRequestId) { if (str($applicationId)->contains('-')) { $applicationId = str($applicationId)->before('-'); } $preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first(); if ($preview) { $foundApplicationPreviews[] = $preview->id; $statusFromDb = $preview->status; if ($statusFromDb !== $containerStatus) { $preview->update(['status' => $containerStatus]); } else { $preview->update(['last_online_at' => now()]); } } else { // Notify user that this container should not be there. } } else { $application = $this->applications->where('id', $applicationId)->first(); if ($application) { $foundApplications[] = $application->id; // Store container status for aggregation if (! isset($this->applicationContainerStatuses)) { $this->applicationContainerStatuses = collect(); } if (! $this->applicationContainerStatuses->has($applicationId)) { $this->applicationContainerStatuses->put($applicationId, collect()); } $containerName = data_get($labels, 'com.docker.compose.service'); // Fallback for Docker Swarm which uses different labels if (! $containerName && $this->server->isSwarm()) { $containerName = data_get($labels, 'coolify.serviceName') ?? data_get($labels, 'coolify.name') ?? data_get($labels, 'com.docker.stack.namespace'); } if ($containerName) { $this->applicationContainerStatuses->get($applicationId)->put($containerName, $containerStatus); } // Track restart counts for applications $restartCount = data_get($container, 'RestartCount', 0); if (! isset($this->applicationContainerRestartCounts)) { $this->applicationContainerRestartCounts = collect(); } if (! $this->applicationContainerRestartCounts->has($applicationId)) { $this->applicationContainerRestartCounts->put($applicationId, collect()); } if ($containerName) { $this->applicationContainerRestartCounts->get($applicationId)->put($containerName, $restartCount); } } else { // Notify user that this container should not be there. } } } else { $uuid = data_get($labels, 'com.docker.compose.service'); $type = data_get($labels, 'coolify.type'); if ($uuid) { if ($type === 'service') { $database_id = data_get($labels, 'coolify.service.subId'); if ($database_id) { $service_db = ServiceDatabase::where('id', $database_id)->first(); if ($service_db) { $proxyUuid = $service_db->uuid; $isPublic = data_get($service_db, 'is_public'); if ($isPublic) { $foundTcpProxy = $this->containers->filter(function ($value, $key) use ($proxyUuid) { if ($this->server->isSwarm()) { return data_get($value, 'Spec.Name') === "coolify-proxy_$proxyUuid"; } else { return data_get($value, 'Name') === "/$proxyUuid-proxy"; } })->first(); if (! $foundTcpProxy) { StartDatabaseProxy::run($service_db); } } else { // Clean up orphaned proxy when is_public=false $orphanedProxy = $this->containers->filter(function ($value, $key) use ($proxyUuid) { if ($this->server->isSwarm()) { return data_get($value, 'Spec.Name') === "coolify-proxy_$proxyUuid"; } else { return data_get($value, 'Name') === "/$proxyUuid-proxy"; } })->first(); if ($orphanedProxy) { StopDatabaseProxy::run($service_db); } } } } } else { $database = $databases->where('uuid', $uuid)->first(); if ($database) { $isPublic = data_get($database, 'is_public'); $foundDatabases[] = $database->id; $statusFromDb = $database->status; // Track restart count for databases (single-container) $restartCount = data_get($container, 'RestartCount', 0); $previousRestartCount = $database->restart_count ?? 0; if ($statusFromDb !== $containerStatus) { $updateData = ['status' => $containerStatus]; } else { $updateData = ['last_online_at' => now()]; } // Update restart tracking if restart count increased if ($restartCount > $previousRestartCount) { $updateData['restart_count'] = $restartCount; $updateData['last_restart_at'] = now(); $updateData['last_restart_type'] = 'crash'; } $database->update($updateData); if ($isPublic) { $foundTcpProxy = $this->containers->filter(function ($value, $key) use ($uuid) { if ($this->server->isSwarm()) { return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid"; } else { return data_get($value, 'Name') === "/$uuid-proxy"; } })->first(); if (! $foundTcpProxy) { StartDatabaseProxy::run($database); } } else { // Clean up orphaned proxy when is_public=false $orphanedProxy = $this->containers->filter(function ($value, $key) use ($uuid) { if ($this->server->isSwarm()) { return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid"; } else { return data_get($value, 'Name') === "/$uuid-proxy"; } })->first(); if ($orphanedProxy) { StopDatabaseProxy::run($database); } } } else { // Notify user that this container should not be there. } } } if (data_get($container, 'Name') === '/coolify-db') { $foundDatabases[] = 0; } } $serviceLabelId = data_get($labels, 'coolify.serviceId'); if ($serviceLabelId) { $subType = data_get($labels, 'coolify.service.subType'); $subId = data_get($labels, 'coolify.service.subId'); $parentService = $services->where('id', $serviceLabelId)->first(); if (! $parentService) { continue; } // Store container status for aggregation if (! isset($this->serviceContainerStatuses)) { $this->serviceContainerStatuses = collect(); } $key = $serviceLabelId.':'.$subType.':'.$subId; if (! $this->serviceContainerStatuses->has($key)) { $this->serviceContainerStatuses->put($key, collect()); } $containerName = data_get($labels, 'com.docker.compose.service'); if ($containerName) { $this->serviceContainerStatuses->get($key)->put($containerName, $containerStatus); } // Mark service as found if ($subType === 'application') { $service = $parentService->applications()->where('id', $subId)->first(); } else { $service = $parentService->databases()->where('id', $subId)->first(); } if ($service) { $foundServices[] = "$service->id-$service->name"; } } } $exitedServices = collect([]); foreach ($services as $service) { $apps = $service->applications()->get(); $dbs = $service->databases()->get(); foreach ($apps as $app) { if (in_array("$app->id-$app->name", $foundServices)) { continue; } else { $exitedServices->push($app); } } foreach ($dbs as $db) { if (in_array("$db->id-$db->name", $foundServices)) { continue; } else { $exitedServices->push($db); } } } $exitedServices = $exitedServices->unique('uuid'); foreach ($exitedServices as $exitedService) { if (str($exitedService->status)->startsWith('exited')) { continue; } // Only protection: If no containers at all, Docker query might have failed if ($this->containers->isEmpty()) { continue; } $name = data_get($exitedService, 'name'); $fqdn = data_get($exitedService, 'fqdn'); if ($name) { if ($fqdn) { $containerName = "$name, available at $fqdn"; } else { $containerName = $name; } } else { if ($fqdn) { $containerName = $fqdn; } else { $containerName = null; } } $projectUuid = data_get($service, 'environment.project.uuid'); $serviceUuid = data_get($service, 'uuid'); $environmentName = data_get($service, 'environment.name'); if ($projectUuid && $serviceUuid && $environmentName) { $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/service/'.$serviceUuid; } else { $url = null; } // $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url)); $exitedService->update(['status' => 'exited']); } $notRunningApplications = $this->applications->pluck('id')->diff($foundApplications); foreach ($notRunningApplications as $applicationId) { $application = $this->applications->where('id', $applicationId)->first(); if (str($application->status)->startsWith('exited')) { continue; } // Only protection: If no containers at all, Docker query might have failed if ($this->containers->isEmpty()) { continue; } // If container was recently restarting (crash loop), keep it as degraded for a grace period // This prevents false "exited" status during the brief moment between container removal and recreation $recentlyRestarted = $application->restart_count > 0 && $application->last_restart_at && $application->last_restart_at->greaterThan(now()->subSeconds(30)); if ($recentlyRestarted) { // Keep it as degraded if it was recently in a crash loop $application->update(['status' => 'degraded:unhealthy']); } else { // Reset restart count when application exits completely $application->update([ 'status' => 'exited', 'restart_count' => 0, 'last_restart_at' => null, 'last_restart_type' => null, ]); } } $notRunningApplicationPreviews = $previews->pluck('id')->diff($foundApplicationPreviews); foreach ($notRunningApplicationPreviews as $previewId) { $preview = $previews->where('id', $previewId)->first(); if (str($preview->status)->startsWith('exited')) { continue; } // Only protection: If no containers at all, Docker query might have failed if ($this->containers->isEmpty()) { continue; } $preview->update(['status' => 'exited']); } $notRunningDatabases = $databases->pluck('id')->diff($foundDatabases); foreach ($notRunningDatabases as $database) { $database = $databases->where('id', $database)->first(); if (str($database->status)->startsWith('exited')) { continue; } // Only protection: If no containers at all, Docker query might have failed if ($this->containers->isEmpty()) { continue; } // Reset restart tracking when database exits completely $database->update([ 'status' => 'exited', 'restart_count' => 0, 'last_restart_at' => null, 'last_restart_type' => null, ]); // Stop proxy if database was public if ($database->is_public) { StopDatabaseProxy::run($database); } $name = data_get($database, 'name'); $fqdn = data_get($database, 'fqdn'); $containerName = $name; $projectUuid = data_get($database, 'environment.project.uuid'); $environmentName = data_get($database, 'environment.name'); $databaseUuid = data_get($database, 'uuid'); if ($projectUuid && $databaseUuid && $environmentName) { $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/database/'.$databaseUuid; } else { $url = null; } // $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url)); } // Aggregate multi-container application statuses if (isset($this->applicationContainerStatuses) && $this->applicationContainerStatuses->isNotEmpty()) { foreach ($this->applicationContainerStatuses as $applicationId => $containerStatuses) { $application = $this->applications->where('id', $applicationId)->first(); if (! $application) { continue; } // Track restart counts first $maxRestartCount = 0; if (isset($this->applicationContainerRestartCounts) && $this->applicationContainerRestartCounts->has($applicationId)) { $containerRestartCounts = $this->applicationContainerRestartCounts->get($applicationId); $maxRestartCount = $containerRestartCounts->max() ?? 0; } // Wrap all database updates in a transaction to ensure consistency DB::transaction(function () use ($application, $maxRestartCount, $containerStatuses) { $previousRestartCount = $application->restart_count ?? 0; if ($maxRestartCount > $previousRestartCount) { // Restart count increased - this is a crash restart $application->update([ 'restart_count' => $maxRestartCount, 'last_restart_at' => now(), 'last_restart_type' => 'crash', ]); // Send notification $containerName = $application->name; $projectUuid = data_get($application, 'environment.project.uuid'); $environmentName = data_get($application, 'environment.name'); $applicationUuid = data_get($application, 'uuid'); if ($projectUuid && $applicationUuid && $environmentName) { $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/application/'.$applicationUuid; } else { $url = null; } } // Aggregate status after tracking restart counts $aggregatedStatus = $this->aggregateApplicationStatus($application, $containerStatuses, $maxRestartCount); if ($aggregatedStatus) { $statusFromDb = $application->status; if ($statusFromDb !== $aggregatedStatus) { $application->update(['status' => $aggregatedStatus]); } else { $application->update(['last_online_at' => now()]); } } }); } } // Aggregate multi-container service statuses $this->aggregateServiceContainerStatuses($services); ServiceChecked::dispatch($this->server->team->id); } private function aggregateApplicationStatus($application, Collection $containerStatuses, int $maxRestartCount = 0): ?string { // Parse docker compose to check for excluded containers $dockerComposeRaw = data_get($application, 'docker_compose_raw'); $excludedContainers = $this->getExcludedContainersFromDockerCompose($dockerComposeRaw); // Filter out excluded containers $relevantStatuses = $containerStatuses->filter(function ($status, $containerName) use ($excludedContainers) { return ! $excludedContainers->contains($containerName); }); // If all containers are excluded, calculate status from excluded containers if ($relevantStatuses->isEmpty()) { return $this->calculateExcludedStatusFromStrings($containerStatuses); } // Use ContainerStatusAggregator service for state machine logic // Use preserveRestarting: true so applications show "Restarting" instead of "Degraded" $aggregator = new ContainerStatusAggregator; return $aggregator->aggregateFromStrings($relevantStatuses, $maxRestartCount, preserveRestarting: true); } private function aggregateServiceContainerStatuses($services) { if (! isset($this->serviceContainerStatuses) || $this->serviceContainerStatuses->isEmpty()) { return; } foreach ($this->serviceContainerStatuses as $key => $containerStatuses) { // Parse key: serviceId:subType:subId [$serviceId, $subType, $subId] = explode(':', $key); $service = $services->where('id', $serviceId)->first(); if (! $service) { continue; } // Get the service sub-resource (ServiceApplication or ServiceDatabase) $subResource = null; if ($subType === 'application') { $subResource = $service->applications()->where('id', $subId)->first(); } elseif ($subType === 'database') { $subResource = $service->databases()->where('id', $subId)->first(); } if (! $subResource) { continue; } // Parse docker compose from service to check for excluded containers $dockerComposeRaw = data_get($service, 'docker_compose_raw'); $excludedContainers = $this->getExcludedContainersFromDockerCompose($dockerComposeRaw); // Filter out excluded containers $relevantStatuses = $containerStatuses->filter(function ($status, $containerName) use ($excludedContainers) { return ! $excludedContainers->contains($containerName); }); // If all containers are excluded, calculate status from excluded containers if ($relevantStatuses->isEmpty()) { $aggregatedStatus = $this->calculateExcludedStatusFromStrings($containerStatuses); if ($aggregatedStatus) { $statusFromDb = $subResource->status; if ($statusFromDb !== $aggregatedStatus) { $subResource->update(['status' => $aggregatedStatus]); } else { $subResource->update(['last_online_at' => now()]); } } continue; } // Use ContainerStatusAggregator service for state machine logic // Use preserveRestarting: true so individual sub-resources show "Restarting" instead of "Degraded" $aggregator = new ContainerStatusAggregator; $aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, preserveRestarting: true); // Update service sub-resource status with aggregated result if ($aggregatedStatus) { $statusFromDb = $subResource->status; if ($statusFromDb !== $aggregatedStatus) { $subResource->update(['status' => $aggregatedStatus]); } else { $subResource->update(['last_online_at' => now()]); } } } } } ================================================ FILE: app/Actions/Fortify/CreateNewUser.php ================================================ $input */ public function create(array $input): User { $settings = instanceSettings(); if (! $settings->is_registration_enabled) { abort(403); } Validator::make($input, [ 'name' => ['required', 'string', 'max:255'], 'email' => [ 'required', 'string', 'email', 'max:255', Rule::unique(User::class), ], 'password' => ['required', Password::defaults(), 'confirmed'], ])->validate(); if (User::count() == 0) { // If this is the first user, make them the root user // Team is already created in the database/seeders/ProductionSeeder.php $user = User::create([ 'id' => 0, 'name' => $input['name'], 'email' => $input['email'], 'password' => Hash::make($input['password']), ]); $team = $user->teams()->first(); // Disable registration after first user is created $settings = instanceSettings(); $settings->is_registration_enabled = false; $settings->save(); } else { $user = User::create([ 'name' => $input['name'], 'email' => $input['email'], 'password' => Hash::make($input['password']), ]); $team = $user->teams()->first(); if (isCloud()) { $user->sendVerificationEmail(); } else { $user->markEmailAsVerified(); } } // Set session variable session(['currentTeam' => $user->currentTeam = $team]); return $user; } } ================================================ FILE: app/Actions/Fortify/ResetUserPassword.php ================================================ $input */ public function reset(User $user, array $input): void { Validator::make($input, [ 'password' => ['required', Password::defaults(), 'confirmed'], ])->validate(); $user->forceFill([ 'password' => Hash::make($input['password']), ])->save(); $user->deleteAllSessions(); } } ================================================ FILE: app/Actions/Fortify/UpdateUserPassword.php ================================================ $input */ public function update(User $user, array $input): void { Validator::make($input, [ 'current_password' => ['required', 'string', 'current_password:web'], 'password' => ['required', Password::defaults(), 'confirmed'], ], [ 'current_password.current_password' => __('The provided password does not match your current password.'), ])->validateWithBag('updatePassword'); $user->forceFill([ 'password' => Hash::make($input['password']), ])->save(); } } ================================================ FILE: app/Actions/Fortify/UpdateUserProfileInformation.php ================================================ $input */ public function update(User $user, array $input): void { Validator::make($input, [ 'name' => ['required', 'string', 'max:255'], 'email' => [ 'required', 'string', 'email', 'max:255', Rule::unique('users')->ignore($user->id), ], ])->validateWithBag('updateProfileInformation'); if ( $input['email'] !== $user->email && $user instanceof MustVerifyEmail ) { $this->updateVerifiedUser($user, $input); } else { $user->forceFill([ 'name' => $input['name'], 'email' => $input['email'], ])->save(); } } /** * Update the given verified user's profile information. * * @param array $input */ protected function updateVerifiedUser(User $user, array $input): void { $user->forceFill([ 'name' => $input['name'], 'email' => $input['email'], 'email_verified_at' => null, ])->save(); $user->sendEmailVerificationNotification(); } } ================================================ FILE: app/Actions/Proxy/CheckProxy.php ================================================ isFunctional()) { return false; } if ($server->isBuildServer()) { if ($server->proxy) { $server->proxy = null; $server->save(); } return false; } $proxyType = $server->proxyType(); if ((is_null($proxyType) || $proxyType === 'NONE' || $server->proxy->force_stop) && ! $fromUI) { return false; } if (! $server->isProxyShouldRun()) { if ($fromUI) { throw new \Exception('Proxy should not run. You selected the Custom Proxy.'); } else { return false; } } // Determine proxy container name based on environment $proxyContainerName = $server->isSwarm() ? 'coolify-proxy_traefik' : 'coolify-proxy'; if ($server->isSwarm()) { $status = getContainerStatus($server, $proxyContainerName); $server->proxy->set('status', $status); $server->save(); if ($status === 'running') { return false; } return true; } else { $status = getContainerStatus($server, $proxyContainerName); if ($status === 'running') { $server->proxy->set('status', 'running'); $server->save(); return false; } if ($server->settings->is_cloudflare_tunnel) { return false; } $ip = $server->ip; if ($server->id === 0) { $ip = 'host.docker.internal'; } $portsToCheck = []; try { if ($server->proxyType() !== ProxyTypes::NONE->value) { $proxyCompose = GetProxyConfiguration::run($server); if (isset($proxyCompose)) { $yaml = Yaml::parse($proxyCompose); $configPorts = []; if ($server->proxyType() === ProxyTypes::TRAEFIK->value) { $ports = data_get($yaml, 'services.traefik.ports'); } elseif ($server->proxyType() === ProxyTypes::CADDY->value) { $ports = data_get($yaml, 'services.caddy.ports'); } if (isset($ports)) { foreach ($ports as $port) { $configPorts[] = str($port)->before(':')->value(); } } // Combine default ports with config ports $portsToCheck = array_merge($portsToCheck, $configPorts); } } else { $portsToCheck = []; } } catch (\Exception $e) { Log::error('Error checking proxy: '.$e->getMessage()); } if (count($portsToCheck) === 0) { return false; } $portsToCheck = array_values(array_unique($portsToCheck)); // Check port conflicts in parallel $conflicts = $this->checkPortConflictsInParallel($server, $portsToCheck, $proxyContainerName); foreach ($conflicts as $port => $conflict) { if ($conflict) { if ($fromUI) { throw new \Exception("Port $port is in use.
You must stop the process using this port.

Docs: https://coolify.io/docs
Discord: https://coolify.io/discord"); } else { return false; } } } return true; } } /** * Check multiple ports for conflicts in parallel * Returns an array with port => conflict_status mapping */ private function checkPortConflictsInParallel(Server $server, array $ports, string $proxyContainerName): array { if (empty($ports)) { return []; } try { // Build concurrent port check commands $results = Process::concurrently(function ($pool) use ($server, $ports, $proxyContainerName) { foreach ($ports as $port) { $commands = $this->buildPortCheckCommands($server, $port, $proxyContainerName); $pool->command($commands['ssh_command'])->timeout(10); } }); // Process results $conflicts = []; foreach ($ports as $index => $port) { $result = $results[$index] ?? null; if ($result) { $conflicts[$port] = $this->parsePortCheckResult($result, $port, $proxyContainerName); } else { // If process failed, assume no conflict to avoid false positives $conflicts[$port] = false; } } return $conflicts; } catch (\Throwable $e) { Log::warning('Parallel port checking failed: '.$e->getMessage().'. Falling back to sequential checking.'); // Fallback to sequential checking if parallel fails $conflicts = []; foreach ($ports as $port) { $conflicts[$port] = $this->isPortConflict($server, $port, $proxyContainerName); } return $conflicts; } } /** * Build the SSH command for checking a specific port */ private function buildPortCheckCommands(Server $server, string $port, string $proxyContainerName): array { // First check if our own proxy is using this port (which is fine) $getProxyContainerId = "docker ps -a --filter name=$proxyContainerName --format '{{.ID}}'"; $checkProxyPortScript = " CONTAINER_ID=\$($getProxyContainerId); if [ ! -z \"\$CONTAINER_ID\" ]; then if docker inspect \$CONTAINER_ID --format '{{json .NetworkSettings.Ports}}' | grep -q '\"$port/tcp\"'; then echo 'proxy_using_port'; exit 0; fi; fi; "; // Command sets for different ways to check ports, ordered by preference $portCheckScript = " $checkProxyPortScript # Try ss command first if command -v ss >/dev/null 2>&1; then ss_output=\$(ss -Htuln state listening sport = :$port 2>/dev/null); if [ -z \"\$ss_output\" ]; then echo 'port_free'; exit 0; fi; count=\$(echo \"\$ss_output\" | grep -c ':$port '); if [ \$count -eq 0 ]; then echo 'port_free'; exit 0; fi; # Check for dual-stack or docker processes if [ \$count -le 2 ] && (echo \"\$ss_output\" | grep -q 'docker\\|coolify'); then echo 'port_free'; exit 0; fi; echo \"port_conflict|\$ss_output\"; exit 0; fi; # Try netstat as fallback if command -v netstat >/dev/null 2>&1; then netstat_output=\$(netstat -tuln 2>/dev/null | grep ':$port '); if [ -z \"\$netstat_output\" ]; then echo 'port_free'; exit 0; fi; count=\$(echo \"\$netstat_output\" | grep -c 'LISTEN'); if [ \$count -eq 0 ]; then echo 'port_free'; exit 0; fi; if [ \$count -le 2 ] && (echo \"\$netstat_output\" | grep -q 'docker\\|coolify'); then echo 'port_free'; exit 0; fi; echo \"port_conflict|\$netstat_output\"; exit 0; fi; # Final fallback using nc if nc -z -w1 127.0.0.1 $port >/dev/null 2>&1; then echo 'port_conflict|nc_detected'; else echo 'port_free'; fi; "; $sshCommand = \App\Helpers\SshMultiplexingHelper::generateSshCommand($server, $portCheckScript); return [ 'ssh_command' => $sshCommand, 'script' => $portCheckScript, ]; } /** * Parse the result from port check command */ private function parsePortCheckResult($processResult, string $port, string $proxyContainerName): bool { $exitCode = $processResult->exitCode(); $output = trim($processResult->output()); $errorOutput = trim($processResult->errorOutput()); if ($exitCode !== 0) { return false; } if ($output === 'proxy_using_port' || $output === 'port_free') { return false; // No conflict } if (str_starts_with($output, 'port_conflict|')) { $details = substr($output, strlen('port_conflict|')); // Additional logic to detect dual-stack scenarios if ($details !== 'nc_detected') { // Check for dual-stack scenario - typically 1-2 listeners (IPv4+IPv6) $lines = explode("\n", $details); if (count($lines) <= 2) { // Look for IPv4 and IPv6 in the listing if ((strpos($details, '0.0.0.0:'.$port) !== false && strpos($details, ':::'.$port) !== false) || (strpos($details, '*:'.$port) !== false && preg_match('/\*:'.$port.'.*IPv[46]/', $details))) { return false; // This is just a normal dual-stack setup } } } return true; // Real port conflict } return false; } /** * Smart port checker that handles dual-stack configurations * Returns true only if there's a real port conflict (not just dual-stack) */ private function isPortConflict(Server $server, string $port, string $proxyContainerName): bool { // First check if our own proxy is using this port (which is fine) try { $getProxyContainerId = "docker ps -a --filter name=$proxyContainerName --format '{{.ID}}'"; $containerId = trim(instant_remote_process([$getProxyContainerId], $server)); if (! empty($containerId)) { $checkProxyPort = "docker inspect $containerId --format '{{json .NetworkSettings.Ports}}' | grep '\"$port/tcp\"'"; try { instant_remote_process([$checkProxyPort], $server); // Our proxy is using the port, which is fine return false; } catch (\Throwable $e) { // Our container exists but not using this port } } } catch (\Throwable $e) { // Container not found or error checking, continue with regular checks } // Command sets for different ways to check ports, ordered by preference $commandSets = [ // Set 1: Use ss to check listener counts by protocol stack [ 'available' => 'command -v ss >/dev/null 2>&1', 'check' => [ // Get listening process details "ss_output=\$(ss -Htuln state listening sport = :$port 2>/dev/null) && echo \"\$ss_output\"", // Count IPv4 listeners "echo \"\$ss_output\" | grep -c ':$port '", ], ], // Set 2: Use netstat as alternative to ss [ 'available' => 'command -v netstat >/dev/null 2>&1', 'check' => [ // Get listening process details "netstat_output=\$(netstat -tuln 2>/dev/null) && echo \"\$netstat_output\" | grep ':$port '", // Count listeners "echo \"\$netstat_output\" | grep ':$port ' | grep -c 'LISTEN'", ], ], // Set 3: Use lsof as last resort [ 'available' => 'command -v lsof >/dev/null 2>&1', 'check' => [ // Get process using the port "lsof -i :$port -P -n | grep 'LISTEN'", // Count listeners "lsof -i :$port -P -n | grep 'LISTEN' | wc -l", ], ], ]; // Try each command set until we find one available foreach ($commandSets as $set) { try { // Check if the command is available instant_remote_process([$set['available']], $server); // Run the actual check commands $output = instant_remote_process($set['check'], $server, true); // Parse the output lines $lines = explode("\n", trim($output)); // Get the detailed output and listener count $details = trim(implode("\n", array_slice($lines, 0, -1))); $count = intval(trim($lines[count($lines) - 1] ?? '0')); // If no listeners or empty result, port is free if ($count == 0 || empty($details)) { return false; } // Try to detect if this is our coolify-proxy if (strpos($details, 'docker') !== false || strpos($details, $proxyContainerName) !== false) { // It's likely our docker or proxy, which is fine return false; } // Check for dual-stack scenario - typically 1-2 listeners (IPv4+IPv6) // If exactly 2 listeners and both have same port, likely dual-stack if ($count <= 2) { // Check if it looks like a standard dual-stack setup $isDualStack = false; // Look for IPv4 and IPv6 in the listing (ss output format) if (preg_match('/LISTEN.*:'.$port.'\s/', $details) && (preg_match('/\*:'.$port.'\s/', $details) || preg_match('/:::'.$port.'\s/', $details))) { $isDualStack = true; } // For netstat format if (strpos($details, '0.0.0.0:'.$port) !== false && strpos($details, ':::'.$port) !== false) { $isDualStack = true; } // For lsof format (IPv4 and IPv6) if (strpos($details, '*:'.$port) !== false && preg_match('/\*:'.$port.'.*IPv4/', $details) && preg_match('/\*:'.$port.'.*IPv6/', $details)) { $isDualStack = true; } if ($isDualStack) { return false; // This is just a normal dual-stack setup } } // If we get here, it's likely a real port conflict return true; } catch (\Throwable $e) { // This command set failed, try the next one continue; } } // Fallback to simpler check if all above methods fail try { // Just try to bind to the port directly to see if it's available $checkCommand = "nc -z -w1 127.0.0.1 $port >/dev/null 2>&1 && echo 'in-use' || echo 'free'"; $result = instant_remote_process([$checkCommand], $server, true); return trim($result) === 'in-use'; } catch (\Throwable $e) { // If everything fails, assume the port is free to avoid false positives return false; } } } ================================================ FILE: app/Actions/Proxy/GetProxyConfiguration.php ================================================ proxyType(); if ($proxyType === 'NONE') { return 'OK'; } $proxy_configuration = null; if (! $forceRegenerate) { // Primary source: database $proxy_configuration = $server->proxy->get('last_saved_proxy_configuration'); // Backfill: existing servers may not have DB config yet — read from disk once if (empty(trim($proxy_configuration ?? ''))) { $proxy_configuration = $this->backfillFromDisk($server); } } // Generate default configuration as last resort if ($forceRegenerate || empty(trim($proxy_configuration ?? ''))) { $custom_commands = []; if (! empty(trim($proxy_configuration ?? ''))) { $custom_commands = extractCustomProxyCommands($server, $proxy_configuration); } Log::warning('Proxy configuration regenerated to defaults', [ 'server_id' => $server->id, 'server_name' => $server->name, 'reason' => $forceRegenerate ? 'force_regenerate' : 'config_not_found', ]); $proxy_configuration = str(generateDefaultProxyConfiguration($server, $custom_commands))->trim()->value(); } if (empty($proxy_configuration)) { throw new \Exception('Could not get or generate proxy configuration'); } ProxyDashboardCacheService::isTraefikDashboardAvailableFromConfiguration($server, $proxy_configuration); return $proxy_configuration; } /** * Backfill: read config from disk for servers that predate DB storage. * Stores the result in the database so future reads skip SSH entirely. */ private function backfillFromDisk(Server $server): ?string { $proxy_path = $server->proxyPath(); $result = instant_remote_process([ "mkdir -p $proxy_path", "cat $proxy_path/docker-compose.yml 2>/dev/null", ], $server, false); if (! empty(trim($result ?? ''))) { $server->proxy->last_saved_proxy_configuration = $result; $server->save(); Log::info('Proxy config backfilled to database from disk', [ 'server_id' => $server->id, ]); return $result; } return null; } } ================================================ FILE: app/Actions/Proxy/SaveProxyConfiguration.php ================================================ proxyPath(); $docker_compose_yml_base64 = base64_encode($configuration); $new_hash = str($docker_compose_yml_base64)->pipe('md5')->value; // Only create a backup if the configuration actually changed $old_hash = $server->proxy->get('last_saved_settings'); $config_changed = $old_hash && $old_hash !== $new_hash; // Update the saved settings hash and store full config as database backup $server->proxy->last_saved_settings = $new_hash; $server->proxy->last_saved_proxy_configuration = $configuration; $server->save(); $backup_path = "$proxy_path/backups"; // Transfer the configuration file to the server, with backup if changed $commands = ["mkdir -p $proxy_path"]; if ($config_changed) { $short_hash = substr($old_hash, 0, 8); $timestamp = now()->format('Y-m-d_H-i-s'); $backup_file = "docker-compose.{$timestamp}.{$short_hash}.yml"; $commands[] = "mkdir -p $backup_path"; // Skip backup if a file with the same hash already exists (identical content) $commands[] = "ls $backup_path/docker-compose.*.$short_hash.yml 1>/dev/null 2>&1 || cp -f $proxy_path/docker-compose.yml $backup_path/$backup_file 2>/dev/null || true"; // Prune old backups, keep only the most recent ones $commands[] = 'cd '.$backup_path.' && ls -1t docker-compose.*.yml 2>/dev/null | tail -n +'.((int) self::MAX_BACKUPS + 1).' | xargs rm -f 2>/dev/null || true'; } $commands[] = "echo '$docker_compose_yml_base64' | base64 -d | tee $proxy_path/docker-compose.yml > /dev/null"; instant_remote_process($commands, $server); } } ================================================ FILE: app/Actions/Proxy/StartProxy.php ================================================ proxyType(); if ((is_null($proxyType) || $proxyType === 'NONE' || $server->proxy->force_stop || $server->isBuildServer()) && $force === false) { return 'OK'; } $server->proxy->set('status', 'starting'); $server->save(); $server->refresh(); if (! $restarting) { ProxyStatusChangedUI::dispatch($server->team_id); } $commands = collect([]); $proxy_path = $server->proxyPath(); $configuration = GetProxyConfiguration::run($server); if (! $configuration) { throw new \Exception('Configuration is not synced'); } SaveProxyConfiguration::run($server, $configuration); $docker_compose_yml_base64 = base64_encode($configuration); $server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value(); $server->save(); if ($server->isSwarmManager()) { $commands = $commands->merge([ "mkdir -p $proxy_path/dynamic", "cd $proxy_path", "echo 'Creating required Docker Compose file.'", "echo 'Starting coolify-proxy.'", 'docker stack deploy --detach=true -c docker-compose.yml coolify-proxy', "echo 'Successfully started coolify-proxy.'", ]); } else { if (isDev()) { if ($proxyType === ProxyTypes::CADDY->value) { $proxy_path = '/data/coolify/proxy/caddy'; } } $caddyfile = 'import /dynamic/*.caddy'; $commands = $commands->merge([ "mkdir -p $proxy_path/dynamic", "cd $proxy_path", "echo '$caddyfile' > $proxy_path/dynamic/Caddyfile", "echo 'Creating required Docker Compose file.'", "echo 'Pulling docker image.'", 'docker compose pull', 'if docker ps -a --format "{{.Names}}" | grep -q "^coolify-proxy$"; then', " echo 'Stopping and removing existing coolify-proxy.'", ' docker stop coolify-proxy 2>/dev/null || true', ' docker rm -f coolify-proxy 2>/dev/null || true', ' # Wait for container to be fully removed', ' for i in {1..10}; do', ' if ! docker ps -a --format "{{.Names}}" | grep -q "^coolify-proxy$"; then', ' break', ' fi', ' echo "Waiting for coolify-proxy to be removed... ($i/10)"', ' sleep 1', ' done', " echo 'Successfully stopped and removed existing coolify-proxy.'", 'fi', ]); // Ensure required networks exist BEFORE docker compose up (networks are declared as external) $commands = $commands->merge(ensureProxyNetworksExist($server)); $commands = $commands->merge([ "echo 'Starting coolify-proxy.'", 'docker compose up -d --wait --remove-orphans', "echo 'Successfully started coolify-proxy.'", ]); $commands = $commands->merge(connectProxyToNetworks($server)); } if ($async) { return remote_process($commands, $server, callEventOnFinish: 'ProxyStatusChanged', callEventData: $server->id); } else { instant_remote_process($commands, $server); $server->proxy->set('type', $proxyType); $server->save(); ProxyStatusChanged::dispatch($server->id); return 'OK'; } } } ================================================ FILE: app/Actions/Proxy/StopProxy.php ================================================ isSwarm() ? 'coolify-proxy_traefik' : 'coolify-proxy'; $server->proxy->status = 'stopping'; $server->save(); if (! $restarting) { ProxyStatusChangedUI::dispatch($server->team_id); } instant_remote_process(command: [ "docker stop -t=$timeout $containerName 2>/dev/null || true", "docker rm -f $containerName 2>/dev/null || true", '# Wait for container to be fully removed', 'for i in {1..10}; do', " if ! docker ps -a --format \"{{.Names}}\" | grep -q \"^$containerName$\"; then", ' break', ' fi', ' sleep 1', 'done', ], server: $server, throwError: false); $server->proxy->force_stop = $forceStop; $server->proxy->status = 'exited'; $server->save(); } catch (\Throwable $e) { return handleError($e); } finally { ProxyDashboardCacheService::clearCache($server); if (! $restarting) { ProxyStatusChanged::dispatch($server->id); } } } } ================================================ FILE: app/Actions/Server/CheckUpdates.php ================================================ serverStatus() === false) { return [ 'error' => 'Server is not reachable or not ready.', ]; } // Try first method - using instant_remote_process $output = instant_remote_process(['cat /etc/os-release'], $server); // Parse os-release into an associative array $osInfo = []; foreach (explode("\n", $output) as $line) { if (empty($line)) { continue; } if (strpos($line, '=') === false) { continue; } [$key, $value] = explode('=', $line, 2); $osInfo[$key] = trim($value, '"'); } // Get the main OS identifier $osId = $osInfo['ID'] ?? ''; // $osIdLike = $osInfo['ID_LIKE'] ?? ''; // $versionId = $osInfo['VERSION_ID'] ?? ''; // Normalize OS types based on install.sh logic switch ($osId) { case 'manjaro': case 'manjaro-arm': case 'endeavouros': $osType = 'arch'; break; case 'pop': case 'linuxmint': case 'zorin': $osType = 'ubuntu'; break; case 'fedora-asahi-remix': $osType = 'fedora'; break; default: $osType = $osId; } // Determine package manager based on OS type $packageManager = match ($osType) { 'arch' => 'pacman', 'alpine' => 'apk', 'ubuntu', 'debian', 'raspbian' => 'apt', 'centos', 'fedora', 'rhel', 'ol', 'rocky', 'almalinux', 'amzn' => 'dnf', 'sles', 'opensuse-leap', 'opensuse-tumbleweed' => 'zypper', default => null }; switch ($packageManager) { case 'zypper': $output = instant_remote_process(['LANG=C zypper -tx list-updates'], $server); $out = $this->parseZypperOutput($output); $out['osId'] = $osId; $out['package_manager'] = $packageManager; return $out; case 'dnf': $output = instant_remote_process(['LANG=C dnf list -q --updates --refresh'], $server); $out = $this->parseDnfOutput($output); $out['osId'] = $osId; $out['package_manager'] = $packageManager; return $out; case 'apt': instant_remote_process(['apt-get update -qq'], $server); $output = instant_remote_process(['LANG=C apt list --upgradable 2>/dev/null'], $server); $out = $this->parseAptOutput($output); $out['osId'] = $osId; $out['package_manager'] = $packageManager; return $out; case 'pacman': // Sync database first, then check for updates // Using -Sy to refresh package database before querying available updates instant_remote_process(['pacman -Sy'], $server); $output = instant_remote_process(['pacman -Qu 2>/dev/null'], $server); $out = $this->parsePacmanOutput($output); $out['osId'] = $osId; $out['package_manager'] = $packageManager; return $out; default: return [ 'osId' => $osId, 'error' => 'Unsupported package manager', 'package_manager' => $packageManager, ]; } } catch (\Throwable $e) { return [ 'osId' => $osId, 'package_manager' => $packageManager, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]; } } private function parseZypperOutput(string $output): array { $updates = []; try { $xml = simplexml_load_string($output); if ($xml === false) { return [ 'total_updates' => 0, 'updates' => [], 'error' => 'Failed to parse XML output', ]; } // Navigate to the update-list node $updateList = $xml->xpath('//update-list/update'); foreach ($updateList as $update) { $updates[] = [ 'package' => (string) $update['name'], 'new_version' => (string) $update['edition'], 'current_version' => (string) $update['edition-old'], 'architecture' => (string) $update['arch'], 'repository' => (string) $update->source['alias'], 'summary' => (string) $update->summary, 'description' => (string) $update->description, ]; } return [ 'total_updates' => count($updates), 'updates' => $updates, ]; } catch (\Throwable $e) { return [ 'total_updates' => 0, 'updates' => [], 'error' => 'Error parsing zypper output: '.$e->getMessage(), ]; } } private function parseDnfOutput(string $output): array { $updates = []; $lines = explode("\n", $output); foreach ($lines as $line) { if (empty($line)) { continue; } // Split by multiple spaces/tabs and filter out empty elements $parts = array_values(array_filter(preg_split('/\s+/', $line))); if (count($parts) >= 3) { $package = $parts[0]; $new_version = $parts[1]; $repository = $parts[2]; // Extract architecture from package name (e.g., "cloud-init.noarch" -> "noarch") $architecture = str_contains($package, '.') ? explode('.', $package)[1] : 'noarch'; $updates[] = [ 'package' => $package, 'new_version' => $new_version, 'repository' => $repository, 'architecture' => $architecture, 'current_version' => 'unknown', // DNF doesn't show current version in check-update output ]; } } return [ 'total_updates' => count($updates), 'updates' => $updates, ]; } private function parseAptOutput(string $output): array { $updates = []; $lines = explode("\n", $output); foreach ($lines as $line) { // Skip the "Listing... Done" line and empty lines if (empty($line) || str_contains($line, 'Listing...')) { continue; } // Example line: package/stable 2.0-1 amd64 [upgradable from: 1.0-1] if (preg_match('/^(.+?)\/(\S+)\s+(\S+)\s+(\S+)\s+\[upgradable from: (.+?)\]/', $line, $matches)) { $updates[] = [ 'package' => $matches[1], 'repository' => $matches[2], 'new_version' => $matches[3], 'architecture' => $matches[4], 'current_version' => $matches[5], ]; } } return [ 'total_updates' => count($updates), 'updates' => $updates, ]; } private function parsePacmanOutput(string $output): array { $updates = []; $unparsedLines = []; $lines = explode("\n", $output); foreach ($lines as $line) { if (empty($line)) { continue; } // Format: package current_version -> new_version if (preg_match('/^(\S+)\s+(\S+)\s+->\s+(\S+)$/', $line, $matches)) { $updates[] = [ 'package' => $matches[1], 'current_version' => $matches[2], 'new_version' => $matches[3], 'architecture' => 'unknown', 'repository' => 'unknown', ]; } else { // Log unmatched lines for debugging purposes $unparsedLines[] = $line; } } $result = [ 'total_updates' => count($updates), 'updates' => $updates, ]; // Include unparsed lines in the result for debugging if any exist if (! empty($unparsedLines)) { $result['unparsed_lines'] = $unparsedLines; \Illuminate\Support\Facades\Log::debug('Pacman output contained unparsed lines', [ 'unparsed_lines' => $unparsedLines, ]); } return $result; } } ================================================ FILE: app/Actions/Server/CleanupDocker.php ================================================ applications(); $applicationImageRepos = collect($applications)->map(function ($app) { return $app->docker_registry_image_name ?? $app->uuid; })->unique()->values(); // Clean up old application images while preserving N most recent for rollback $applicationCleanupLog = $this->cleanupApplicationImages($server, $applications); $cleanupLog = array_merge($cleanupLog, $applicationCleanupLog); // Build image prune command that excludes application images and current Coolify infrastructure images // This ensures we clean up non-Coolify images while preserving rollback images and current helper/realtime images // Note: Only the current version is protected; old versions will be cleaned up by explicit commands below // We pass the version strings so all registry variants are protected (ghcr.io, docker.io, no prefix) $imagePruneCmd = $this->buildImagePruneCommand( $applicationImageRepos, $helperImageVersion, $realtimeImageVersion ); $commands = [ 'docker container prune -f --filter "label=coolify.managed=true" --filter "label!=coolify.proxy=true"', $imagePruneCmd, 'docker builder prune -af', "docker images --filter before=$helperImageWithVersion --filter reference=$helperImage | grep $helperImage | awk '{print $3}' | xargs -r docker rmi -f", "docker images --filter before=$realtimeImageWithVersion --filter reference=$realtimeImage | grep $realtimeImage | awk '{print $3}' | xargs -r docker rmi -f", "docker images --filter before=$helperImageWithoutPrefixVersion --filter reference=$helperImageWithoutPrefix | grep $helperImageWithoutPrefix | awk '{print $3}' | xargs -r docker rmi -f", "docker images --filter before=$realtimeImageWithoutPrefixVersion --filter reference=$realtimeImageWithoutPrefix | grep $realtimeImageWithoutPrefix | awk '{print $3}' | xargs -r docker rmi -f", ]; if ($deleteUnusedVolumes) { $commands[] = 'docker volume prune -af'; } if ($deleteUnusedNetworks) { $commands[] = 'docker network prune -f'; } foreach ($commands as $command) { $commandOutput = instant_remote_process([$command], $server, false); if ($commandOutput !== null) { $cleanupLog[] = [ 'command' => $command, 'output' => $commandOutput, ]; } } return $cleanupLog; } /** * Build a docker image prune command that excludes application image repositories. * * Since docker image prune doesn't support excluding by repository name directly, * we use a shell script approach to delete unused images while preserving application images. */ private function buildImagePruneCommand( $applicationImageRepos, string $helperImageVersion, string $realtimeImageVersion ): string { // Step 1: Always prune dangling images (untagged) $commands = ['docker image prune -f']; // Build grep pattern to exclude application image repositories (matches repo:tag and repo_service:tag) $appExcludePatterns = $applicationImageRepos->map(function ($repo) { // Escape special characters for grep extended regex (ERE) // ERE special chars: . \ + * ? [ ^ ] $ ( ) { } | return preg_replace('/([.\\\\+*?\[\]^$(){}|])/', '\\\\$1', $repo); })->implode('|'); // Build grep pattern to exclude Coolify infrastructure images (current version only) // This pattern matches the image name regardless of registry prefix: // - ghcr.io/coollabsio/coolify-helper:1.0.12 // - docker.io/coollabsio/coolify-helper:1.0.12 // - coollabsio/coolify-helper:1.0.12 // Pattern: (^|/)coollabsio/coolify-(helper|realtime):VERSION$ $escapedHelperVersion = preg_replace('/([.\\\\+*?\[\]^$(){}|])/', '\\\\$1', $helperImageVersion); $escapedRealtimeVersion = preg_replace('/([.\\\\+*?\[\]^$(){}|])/', '\\\\$1', $realtimeImageVersion); $infraExcludePattern = "(^|/)coollabsio/coolify-helper:{$escapedHelperVersion}$|(^|/)coollabsio/coolify-realtime:{$escapedRealtimeVersion}$"; // Delete unused images that: // - Are not application images (don't match app repos) // - Are not current Coolify infrastructure images (any registry) // - Don't have coolify.managed=true label // Images in use by containers will fail silently with docker rmi // Pattern matches both uuid:tag and uuid_servicename:tag (Docker Compose with build) $grepCommands = "grep -v ''"; // Add application repo exclusion if there are applications if ($applicationImageRepos->isNotEmpty()) { $grepCommands .= " | grep -v -E '^({$appExcludePatterns})[_:].+'"; } // Add infrastructure image exclusion (matches any registry prefix) $grepCommands .= " | grep -v -E '{$infraExcludePattern}'"; $commands[] = "docker images --format '{{.Repository}}:{{.Tag}}' | ". $grepCommands.' | '. "xargs -r -I {} sh -c 'docker inspect --format \"{{{{index .Config.Labels \\\"coolify.managed\\\"}}}}\" \"{}\" 2>/dev/null | grep -q true || docker rmi \"{}\" 2>/dev/null' || true"; return implode(' && ', $commands); } private function cleanupApplicationImages(Server $server, $applications = null): array { $cleanupLog = []; if ($applications === null) { $applications = $server->applications(); } $disableRetention = $server->settings->disable_application_image_retention ?? false; foreach ($applications as $application) { $imagesToKeep = $disableRetention ? 0 : ($application->settings->docker_images_to_keep ?? 2); $imageRepository = $application->docker_registry_image_name ?? $application->uuid; // Get the currently running image tag $currentTagCommand = "docker inspect --format='{{.Config.Image}}' {$application->uuid} 2>/dev/null | grep -oP '(?<=:)[^:]+$' || true"; $currentTag = instant_remote_process([$currentTagCommand], $server, false); $currentTag = trim($currentTag ?? ''); // List all images for this application with their creation timestamps // Use wildcard to match both uuid:tag and uuid_servicename:tag (Docker Compose with build) $listCommand = "docker images --format '{{.Repository}}:{{.Tag}}#{{.CreatedAt}}' --filter reference='{$imageRepository}*' 2>/dev/null || true"; $output = instant_remote_process([$listCommand], $server, false); if (empty($output)) { continue; } $images = collect(explode("\n", trim($output))) ->filter() ->map(function ($line) { $parts = explode('#', $line); $imageRef = $parts[0] ?? ''; $tagParts = explode(':', $imageRef); return [ 'repository' => $tagParts[0] ?? '', 'tag' => $tagParts[1] ?? '', 'created_at' => $parts[1] ?? '', 'image_ref' => $imageRef, ]; }) ->filter(fn ($image) => ! empty($image['tag'])); // Separate images into categories // PR images (pr-*) are always deleted // Build images (*-build) are cleaned up to match retained regular images $prImages = $images->filter(fn ($image) => str_starts_with($image['tag'], 'pr-')); $buildImages = $images->filter(fn ($image) => ! str_starts_with($image['tag'], 'pr-') && str_ends_with($image['tag'], '-build')); $regularImages = $images->filter(fn ($image) => ! str_starts_with($image['tag'], 'pr-') && ! str_ends_with($image['tag'], '-build')); // Always delete all PR images foreach ($prImages as $image) { $deleteCommand = "docker rmi {$image['image_ref']} 2>/dev/null || true"; $deleteOutput = instant_remote_process([$deleteCommand], $server, false); $cleanupLog[] = [ 'command' => $deleteCommand, 'output' => $deleteOutput ?? 'PR image removed or was in use', ]; } // Filter out current running image from regular images and sort by creation date $sortedRegularImages = $regularImages ->filter(fn ($image) => $image['tag'] !== $currentTag) ->sortByDesc('created_at') ->values(); // Keep only N images (imagesToKeep), delete the rest $imagesToDelete = $sortedRegularImages->skip($imagesToKeep); foreach ($imagesToDelete as $image) { $deleteCommand = "docker rmi {$image['image_ref']} 2>/dev/null || true"; $deleteOutput = instant_remote_process([$deleteCommand], $server, false); $cleanupLog[] = [ 'command' => $deleteCommand, 'output' => $deleteOutput ?? 'Image removed or was in use', ]; } // Clean up build images (-build suffix) that don't correspond to retained regular images // Build images are intermediate artifacts (e.g. Nixpacks) not used by running containers. // If a build is in progress, docker rmi will fail silently since the image is in use. $keptTags = $sortedRegularImages->take($imagesToKeep)->pluck('tag'); if (! empty($currentTag)) { $keptTags = $keptTags->push($currentTag); } foreach ($buildImages as $image) { $baseTag = preg_replace('/-build$/', '', $image['tag']); if (! $keptTags->contains($baseTag)) { $deleteCommand = "docker rmi {$image['image_ref']} 2>/dev/null || true"; $deleteOutput = instant_remote_process([$deleteCommand], $server, false); $cleanupLog[] = [ 'command' => $deleteCommand, 'output' => $deleteOutput ?? 'Build image removed or was in use', ]; } } } return $cleanupLog; } } ================================================ FILE: app/Actions/Server/ConfigureCloudflared.php ================================================ [ 'coolify-cloudflared' => [ 'container_name' => 'coolify-cloudflared', 'image' => 'cloudflare/cloudflared:latest', 'restart' => RESTART_MODE, 'network_mode' => 'host', 'command' => 'tunnel run', 'environment' => [ "TUNNEL_TOKEN={$cloudflare_token}", 'TUNNEL_METRICS=127.0.0.1:60123', ], 'healthcheck' => [ 'test' => ['CMD', 'cloudflared', 'tunnel', '--metrics', '127.0.0.1:60123', 'ready'], 'interval' => '5s', 'timeout' => '30s', 'retries' => 5, ], ], ], ]; $config = Yaml::dump($config, 12, 2); $docker_compose_yml_base64 = base64_encode($config); $commands = collect([ 'mkdir -p /tmp/cloudflared', 'cd /tmp/cloudflared', "echo '$docker_compose_yml_base64' | base64 -d | tee docker-compose.yml > /dev/null", 'echo Pulling latest Cloudflare Tunnel image.', 'docker compose pull', 'echo Stopping existing Cloudflare Tunnel container.', 'docker rm -f coolify-cloudflared || true', 'echo Starting new Cloudflare Tunnel container.', 'docker compose up --wait --wait-timeout 15 --remove-orphans || docker logs coolify-cloudflared', ]); return remote_process($commands, $server, callEventOnFinish: 'CloudflareTunnelChanged', callEventData: [ 'server_id' => $server->id, 'ssh_domain' => $ssh_domain, ]); } catch (\Throwable $e) { throw $e; } } } ================================================ FILE: app/Actions/Server/DeleteServer.php ================================================ find($serverId); // Delete from Hetzner even if server is already gone from Coolify if ($deleteFromHetzner && ($hetznerServerId || ($server && $server->hetzner_server_id))) { $this->deleteFromHetznerById( $hetznerServerId ?? $server->hetzner_server_id, $cloudProviderTokenId ?? $server->cloud_provider_token_id, $teamId ?? $server->team_id ); } ray($server ? 'Deleting server from Coolify' : 'Server already deleted from Coolify, skipping Coolify deletion'); // If server is already deleted from Coolify, skip this part if (! $server) { return; // Server already force deleted from Coolify } ray('force deleting server from Coolify', ['server_id' => $server->id]); try { $server->forceDelete(); } catch (\Throwable $e) { ray('Failed to force delete server from Coolify', [ 'error' => $e->getMessage(), 'server_id' => $server->id, ]); logger()->error('Failed to force delete server from Coolify', [ 'error' => $e->getMessage(), 'server_id' => $server->id, ]); } } private function deleteFromHetznerById(int $hetznerServerId, ?int $cloudProviderTokenId, int $teamId): void { try { // Use the provided token, or fallback to first available team token $token = null; if ($cloudProviderTokenId) { $token = CloudProviderToken::find($cloudProviderTokenId); } if (! $token) { $token = CloudProviderToken::where('team_id', $teamId) ->where('provider', 'hetzner') ->first(); } if (! $token) { ray('No Hetzner token found for team, skipping Hetzner deletion', [ 'team_id' => $teamId, 'hetzner_server_id' => $hetznerServerId, ]); return; } $hetznerService = new HetznerService($token->token); $hetznerService->deleteServer($hetznerServerId); ray('Deleted server from Hetzner', [ 'hetzner_server_id' => $hetznerServerId, 'team_id' => $teamId, ]); } catch (\Throwable $e) { ray('Failed to delete server from Hetzner', [ 'error' => $e->getMessage(), 'hetzner_server_id' => $hetznerServerId, 'team_id' => $teamId, ]); // Log the error but don't prevent the server from being deleted from Coolify logger()->error('Failed to delete server from Hetzner', [ 'error' => $e->getMessage(), 'hetzner_server_id' => $hetznerServerId, 'team_id' => $teamId, ]); // Notify the team about the failure $team = Team::find($teamId); $team?->notify(new HetznerDeletionFailed($hetznerServerId, $teamId, $e->getMessage())); } } } ================================================ FILE: app/Actions/Server/InstallDocker.php ================================================ dockerVersion = config('constants.docker.minimum_required_version'); $supported_os_type = $server->validateOS(); if (! $supported_os_type) { throw new \Exception('Server OS type is not supported for automated installation. Please install Docker manually before continuing: documentation.'); } if (! $server->sslCertificates()->where('is_ca_certificate', true)->exists()) { $serverCert = SslHelper::generateSslCertificate( commonName: 'Coolify CA Certificate', serverId: $server->id, isCaCertificate: true, validityDays: 10 * 365 ); $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; $base64Cert = base64_encode($serverCert->ssl_certificate); $commands = collect([ "mkdir -p $caCertPath", "chown -R 9999:root $caCertPath", "chmod -R 700 $caCertPath", "rm -rf $caCertPath/coolify-ca.crt", "echo '{$base64Cert}' | base64 -d | tee $caCertPath/coolify-ca.crt > /dev/null", "chmod 644 $caCertPath/coolify-ca.crt", ]); remote_process($commands, $server); } $config = base64_encode('{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }'); $found = StandaloneDocker::where('server_id', $server->id); if ($found->count() == 0 && $server->id) { StandaloneDocker::create([ 'name' => 'coolify', 'network' => 'coolify', 'server_id' => $server->id, ]); } $command = collect([]); if (isDev() && $server->id === 0) { $command = $command->merge([ "echo 'Installing Docker Engine...'", "echo 'Configuring Docker Engine (merging existing configuration with the required)...'", 'sleep 4', "echo 'Restarting Docker Engine...'", 'ls -l /tmp', ]); return remote_process($command, $server); } else { $command = $command->merge([ "echo 'Installing Docker Engine...'", ]); if ($supported_os_type->contains('debian')) { $command = $command->merge([$this->getDebianDockerInstallCommand()]); } elseif ($supported_os_type->contains('rhel')) { $command = $command->merge([$this->getRhelDockerInstallCommand()]); } elseif ($supported_os_type->contains('sles')) { $command = $command->merge([$this->getSuseDockerInstallCommand()]); } elseif ($supported_os_type->contains('arch')) { $command = $command->merge([$this->getArchDockerInstallCommand()]); } else { $command = $command->merge([$this->getGenericDockerInstallCommand()]); } $command = $command->merge([ "echo 'Configuring Docker Engine (merging existing configuration with the required)...'", 'test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json "/etc/docker/daemon.json.original-$(date +"%Y%m%d-%H%M%S")"', "test ! -s /etc/docker/daemon.json && echo '{$config}' | base64 -d | tee /etc/docker/daemon.json > /dev/null", "echo '{$config}' | base64 -d | tee /etc/docker/daemon.json.coolify > /dev/null", 'jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null', 'mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify', "jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null", 'mv /etc/docker/daemon.json.appended /etc/docker/daemon.json', "echo 'Restarting Docker Engine...'", 'systemctl enable docker >/dev/null 2>&1 || true', 'systemctl restart docker', ]); if ($server->isSwarm()) { $command = $command->merge([ 'docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true', ]); } else { $command = $command->merge([ 'docker network create --attachable coolify >/dev/null 2>&1 || true', ]); $command = $command->merge([ "echo 'Done!'", ]); } return remote_process($command, $server); } } private function getDebianDockerInstallCommand(): string { return "curl --max-time 300 --retry 3 https://releases.rancher.com/install-docker/{$this->dockerVersion}.sh | sh || curl --max-time 300 --retry 3 https://get.docker.com | sh -s -- --version {$this->dockerVersion} || (". '. /etc/os-release && '. 'install -m 0755 -d /etc/apt/keyrings && '. 'curl -fsSL https://download.docker.com/linux/${ID}/gpg -o /etc/apt/keyrings/docker.asc && '. 'chmod a+r /etc/apt/keyrings/docker.asc && '. 'echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" > /etc/apt/sources.list.d/docker.list && '. 'apt-get update && '. 'apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin'. ')'; } private function getRhelDockerInstallCommand(): string { return "curl https://releases.rancher.com/install-docker/{$this->dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$this->dockerVersion} || (". 'dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && '. 'dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && '. 'systemctl start docker && '. 'systemctl enable docker'. ')'; } private function getSuseDockerInstallCommand(): string { return "curl https://releases.rancher.com/install-docker/{$this->dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$this->dockerVersion} || (". 'zypper addrepo https://download.docker.com/linux/sles/docker-ce.repo && '. 'zypper refresh && '. 'zypper install -y --no-confirm docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && '. 'systemctl start docker && '. 'systemctl enable docker'. ')'; } private function getArchDockerInstallCommand(): string { // Use -Syu to perform full system upgrade before installing Docker // Partial upgrades (-Sy without -u) are discouraged on Arch Linux // as they can lead to broken dependencies and system instability // Use --needed to skip reinstalling packages that are already up-to-date (idempotent) return 'pacman -Syu --noconfirm --needed docker docker-compose && '. 'systemctl enable docker.service && '. 'systemctl start docker.service'; } private function getGenericDockerInstallCommand(): string { return "curl --max-time 300 --retry 3 https://releases.rancher.com/install-docker/{$this->dockerVersion}.sh | sh || curl --max-time 300 --retry 3 https://get.docker.com | sh -s -- --version {$this->dockerVersion}"; } } ================================================ FILE: app/Actions/Server/InstallPrerequisites.php ================================================ validateOS(); if (! $supported_os_type) { throw new \Exception('Server OS type is not supported for automated installation. Please install prerequisites manually.'); } $command = collect([]); if ($supported_os_type->contains('debian')) { $command = $command->merge([ "echo 'Installing Prerequisites...'", 'apt-get update -y', 'command -v curl >/dev/null || apt install -y curl', 'command -v wget >/dev/null || apt install -y wget', 'command -v git >/dev/null || apt install -y git', 'command -v jq >/dev/null || apt install -y jq', ]); } elseif ($supported_os_type->contains('rhel')) { $command = $command->merge([ "echo 'Installing Prerequisites...'", 'command -v curl >/dev/null || dnf install -y curl', 'command -v wget >/dev/null || dnf install -y wget', 'command -v git >/dev/null || dnf install -y git', 'command -v jq >/dev/null || dnf install -y jq', ]); } elseif ($supported_os_type->contains('sles')) { $command = $command->merge([ "echo 'Installing Prerequisites...'", 'zypper update -y', 'command -v curl >/dev/null || zypper install -y curl', 'command -v wget >/dev/null || zypper install -y wget', 'command -v git >/dev/null || zypper install -y git', 'command -v jq >/dev/null || zypper install -y jq', ]); } elseif ($supported_os_type->contains('arch')) { // Use -Syu for full system upgrade to avoid partial upgrade issues on Arch Linux // --needed flag skips packages that are already installed and up-to-date $command = $command->merge([ "echo 'Installing Prerequisites for Arch Linux...'", 'pacman -Syu --noconfirm --needed curl wget git jq', ]); } else { throw new \Exception('Unsupported OS type for prerequisites installation'); } $command->push("echo 'Prerequisites installed successfully.'"); return remote_process($command, $server); } } ================================================ FILE: app/Actions/Server/ResourcesCheck.php ================================================ subSeconds($seconds))->update(['status' => 'exited']); ServiceApplication::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); ServiceDatabase::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandalonePostgresql::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandaloneRedis::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandaloneMongodb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandaloneMysql::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandaloneMariadb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandaloneKeydb::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandaloneDragonfly::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); StandaloneClickhouse::where('last_online_at', '<', now()->subSeconds($seconds))->update(['status' => 'exited']); } catch (\Throwable $e) { return handleError($e); } } } ================================================ FILE: app/Actions/Server/RestartContainer.php ================================================ restartContainer($containerName); } } ================================================ FILE: app/Actions/Server/RunCommand.php ================================================ value); } } ================================================ FILE: app/Actions/Server/StartLogDrain.php ================================================ settings->is_logdrain_newrelic_enabled) { $type = 'newrelic'; } elseif ($server->settings->is_logdrain_highlight_enabled) { $type = 'highlight'; } elseif ($server->settings->is_logdrain_axiom_enabled) { $type = 'axiom'; } elseif ($server->settings->is_logdrain_custom_enabled) { $type = 'custom'; } else { $type = 'none'; } if ($type !== 'none') { StopLogDrain::run($server); } try { if ($type === 'none') { return 'No log drain is enabled.'; } elseif ($type === 'newrelic') { if (! $server->settings->is_logdrain_newrelic_enabled) { throw new \Exception('New Relic log drain is not enabled.'); } $config = base64_encode(" [SERVICE] Flush 5 Daemon off Tag container_logs Log_Level debug Parsers_File parsers.conf [INPUT] Name forward Buffer_Chunk_Size 1M Buffer_Max_Size 6M [FILTER] Name grep Match * Exclude log 127.0.0.1 [FILTER] Name modify Match * Set coolify.server_name {$server->name} Rename COOLIFY_APP_NAME coolify.app_name Rename COOLIFY_PROJECT_NAME coolify.project_name Rename COOLIFY_SERVER_IP coolify.server_ip Rename COOLIFY_ENVIRONMENT_NAME coolify.environment_name [OUTPUT] Name nrlogs Match * license_key \${LICENSE_KEY} # https://log-api.eu.newrelic.com/log/v1 - EU # https://log-api.newrelic.com/log/v1 - US base_uri \${BASE_URI} "); } elseif ($type === 'highlight') { if (! $server->settings->is_logdrain_highlight_enabled) { throw new \Exception('Highlight log drain is not enabled.'); } $config = base64_encode(' [SERVICE] Flush 5 Daemon off Log_Level debug Parsers_File parsers.conf [INPUT] Name forward tag ${HIGHLIGHT_PROJECT_ID} Buffer_Chunk_Size 1M Buffer_Max_Size 6M [OUTPUT] Name forward Match * Host otel.highlight.io Port 24224 '); } elseif ($type === 'axiom') { if (! $server->settings->is_logdrain_axiom_enabled) { throw new \Exception('Axiom log drain is not enabled.'); } $config = base64_encode(" [SERVICE] Flush 5 Daemon off Log_Level debug Parsers_File parsers.conf [INPUT] Name forward Buffer_Chunk_Size 1M Buffer_Max_Size 6M [FILTER] Name grep Match * Exclude log 127.0.0.1 [FILTER] Name modify Match * Set coolify.server_name {$server->name} Rename COOLIFY_APP_NAME coolify.app_name Rename COOLIFY_PROJECT_NAME coolify.project_name Rename COOLIFY_SERVER_IP coolify.server_ip Rename COOLIFY_ENVIRONMENT_NAME coolify.environment_name [OUTPUT] Name http Match * Host api.axiom.co Port 443 URI /v1/datasets/\${AXIOM_DATASET_NAME}/ingest # Authorization Bearer should be an API token Header Authorization Bearer \${AXIOM_API_KEY} compress gzip format json json_date_key _time json_date_format iso8601 tls On "); } elseif ($type === 'custom') { if (! $server->settings->is_logdrain_custom_enabled) { throw new \Exception('Custom log drain is not enabled.'); } $config = base64_encode($server->settings->logdrain_custom_config); $parsers = base64_encode($server->settings->logdrain_custom_config_parser); } else { throw new \Exception('Unknown log drain type.'); } if ($type !== 'custom') { $parsers = base64_encode(" [PARSER] Name empty_line_skipper Format regex Regex /^(?!\s*$).+/ "); } $compose = base64_encode(' services: coolify-log-drain: image: cr.fluentbit.io/fluent/fluent-bit:2.0 container_name: coolify-log-drain command: -c /fluent-bit.conf env_file: - .env volumes: - ./fluent-bit.conf:/fluent-bit.conf - ./parsers.conf:/parsers.conf ports: - 127.0.0.1:24224:24224 labels: - coolify.managed=true restart: unless-stopped '); $readme = base64_encode('# New Relic Log Drain This log drain is based on [Fluent Bit](https://fluentbit.io/) and New Relic Log Forwarder. Files: - `fluent-bit.conf` - configuration file for Fluent Bit - `docker-compose.yml` - docker-compose file to run Fluent Bit - `.env` - environment variables for Fluent Bit '); $license_key = $server->settings->logdrain_newrelic_license_key; $base_uri = $server->settings->logdrain_newrelic_base_uri; $base_path = config('constants.coolify.base_config_path'); $config_path = $base_path.'/log-drains'; $fluent_bit_config = $config_path.'/fluent-bit.conf'; $parsers_config = $config_path.'/parsers.conf'; $compose_path = $config_path.'/docker-compose.yml'; $readme_path = $config_path.'/README.md'; if ($type === 'newrelic') { $envContent = "LICENSE_KEY={$license_key}\nBASE_URI={$base_uri}\n"; } elseif ($type === 'highlight') { $envContent = "HIGHLIGHT_PROJECT_ID={$server->settings->logdrain_highlight_project_id}\n"; } elseif ($type === 'axiom') { $envContent = "AXIOM_DATASET_NAME={$server->settings->logdrain_axiom_dataset_name}\nAXIOM_API_KEY={$server->settings->logdrain_axiom_api_key}\n"; } elseif ($type === 'custom') { $envContent = ''; } else { throw new \Exception('Unknown log drain type.'); } $envEncoded = base64_encode($envContent); $command = [ "echo 'Saving configuration'", "mkdir -p $config_path", "echo '{$parsers}' | base64 -d | tee $parsers_config > /dev/null", "echo '{$config}' | base64 -d | tee $fluent_bit_config > /dev/null", "echo '{$compose}' | base64 -d | tee $compose_path > /dev/null", "echo '{$readme}' | base64 -d | tee $readme_path > /dev/null", "echo '{$envEncoded}' | base64 -d | tee $config_path/.env > /dev/null", "echo 'Starting Fluent Bit'", "cd $config_path && docker compose up -d", ]; return instant_remote_process($command, $server); } catch (\Throwable $e) { return handleError($e); } } } ================================================ FILE: app/Actions/Server/StartSentinel.php ================================================ isSwarm() || $server->isBuildServer()) { return; } if ($restart) { StopSentinel::run($server); } $version = $latestVersion ?? get_latest_sentinel_version(); $metricsHistory = data_get($server, 'settings.sentinel_metrics_history_days'); $refreshRate = data_get($server, 'settings.sentinel_metrics_refresh_rate_seconds'); $pushInterval = data_get($server, 'settings.sentinel_push_interval_seconds'); $token = data_get($server, 'settings.sentinel_token'); if (! ServerSetting::isValidSentinelToken($token)) { throw new \RuntimeException('Invalid sentinel token format. Token must contain only alphanumeric characters, dots, hyphens, and underscores.'); } $endpoint = data_get($server, 'settings.sentinel_custom_url'); $debug = data_get($server, 'settings.is_sentinel_debug_enabled'); $mountDir = '/data/coolify/sentinel'; $image = config('constants.coolify.registry_url').'/coollabsio/sentinel:'.$version; if (! $endpoint) { throw new \RuntimeException('You should set FQDN in Instance Settings.'); } $environments = [ 'TOKEN' => $token, 'DEBUG' => $debug ? 'true' : 'false', 'PUSH_ENDPOINT' => $endpoint, 'PUSH_INTERVAL_SECONDS' => $pushInterval, 'COLLECTOR_ENABLED' => $server->isMetricsEnabled() ? 'true' : 'false', 'COLLECTOR_REFRESH_RATE_SECONDS' => $refreshRate, 'COLLECTOR_RETENTION_PERIOD_DAYS' => $metricsHistory, ]; $labels = [ 'coolify.managed' => 'true', ]; if (isDev()) { // data_set($environments, 'DEBUG', 'true'); if ($customImage && ! empty($customImage)) { $image = $customImage; } $mountDir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/sentinel'; } $dockerEnvironments = implode(' ', array_map(fn ($key, $value) => '-e '.escapeshellarg("$key=$value"), array_keys($environments), $environments)); $dockerLabels = implode(' ', array_map(fn ($key, $value) => "$key=$value", array_keys($labels), $labels)); $dockerCommand = "docker run -d $dockerEnvironments --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v $mountDir:/app/db --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 --add-host=host.docker.internal:host-gateway --label $dockerLabels $image"; instant_remote_process([ 'docker rm -f coolify-sentinel || true', "mkdir -p $mountDir", $dockerCommand, "chown -R 9999:root $mountDir", "chmod -R 700 $mountDir", ], $server); $server->settings->is_sentinel_enabled = true; $server->settings->save(); $server->sentinelHeartbeat(); // Dispatch event to notify UI components SentinelRestarted::dispatch($server, $version); } } ================================================ FILE: app/Actions/Server/StopLogDrain.php ================================================ sentinelHeartbeat(isReset: true); } } ================================================ FILE: app/Actions/Server/UpdateCoolify.php ================================================ seconds(); return; } $settings = instanceSettings(); $this->server = Server::find(0); if (! $this->server) { return; } // Fetch fresh version from CDN instead of using cache try { $response = Http::retry(3, 1000)->timeout(10) ->get(config('constants.coolify.versions_url')); if ($response->successful()) { $versions = $response->json(); $this->latestVersion = data_get($versions, 'coolify.v4.version'); } else { // Fallback to cache if CDN unavailable $cacheVersion = get_latest_version_of_coolify(); // Validate cache version against current running version if ($cacheVersion && version_compare($cacheVersion, config('constants.coolify.version'), '<')) { Log::error('Failed to fetch fresh version from CDN and cache is corrupted/outdated', [ 'cached_version' => $cacheVersion, 'current_version' => config('constants.coolify.version'), ]); throw new \Exception( 'Cannot determine latest version: CDN unavailable and cache version '. "({$cacheVersion}) is older than running version (".config('constants.coolify.version').')' ); } $this->latestVersion = $cacheVersion; Log::warning('Failed to fetch fresh version from CDN (unsuccessful response), using validated cache', [ 'version' => $cacheVersion, ]); } } catch (\Throwable $e) { $cacheVersion = get_latest_version_of_coolify(); // Validate cache version against current running version if ($cacheVersion && version_compare($cacheVersion, config('constants.coolify.version'), '<')) { Log::error('Failed to fetch fresh version from CDN and cache is corrupted/outdated', [ 'error' => $e->getMessage(), 'cached_version' => $cacheVersion, 'current_version' => config('constants.coolify.version'), ]); throw new \Exception( 'Cannot determine latest version: CDN unavailable and cache version '. "({$cacheVersion}) is older than running version (".config('constants.coolify.version').')' ); } $this->latestVersion = $cacheVersion; Log::warning('Failed to fetch fresh version from CDN, using validated cache', [ 'error' => $e->getMessage(), 'version' => $cacheVersion, ]); } $this->currentVersion = config('constants.coolify.version'); if (! $manual_update) { if (! $settings->is_auto_update_enabled) { return; } if ($this->latestVersion === $this->currentVersion) { return; } if (version_compare($this->latestVersion, $this->currentVersion, '<')) { return; } } // ALWAYS check for downgrades (even for manual updates) if (version_compare($this->latestVersion, $this->currentVersion, '<')) { Log::error('Downgrade prevented', [ 'target_version' => $this->latestVersion, 'current_version' => $this->currentVersion, 'manual_update' => $manual_update, ]); throw new \Exception( "Cannot downgrade from {$this->currentVersion} to {$this->latestVersion}. ". 'If you need to downgrade, please do so manually via Docker commands.' ); } $this->update(); $settings->new_version_available = false; $settings->save(); } private function update() { $latestHelperImageVersion = getHelperVersion(); $upgradeScriptUrl = config('constants.coolify.upgrade_script_url'); remote_process([ "curl -fsSL {$upgradeScriptUrl} -o /data/coolify/source/upgrade.sh", "bash /data/coolify/source/upgrade.sh $this->latestVersion $latestHelperImageVersion", ], $this->server); } } ================================================ FILE: app/Actions/Server/UpdatePackage.php ================================================ serverStatus() === false) { return [ 'error' => 'Server is not reachable or not ready.', ]; } // Validate that package name is provided when not updating all packages if (! $all && ($package === null || $package === '')) { return [ 'error' => "Package name required when 'all' is false.", ]; } // Sanitize package name to prevent command injection // Only allow alphanumeric characters, hyphens, underscores, periods, plus signs, and colons // These are valid characters in package names across most package managers $sanitizedPackage = ''; if ($package !== null && ! $all) { if (! preg_match('/^[a-zA-Z0-9._+:-]+$/', $package)) { return [ 'error' => 'Invalid package name. Package names can only contain alphanumeric characters, hyphens, underscores, periods, plus signs, and colons.', ]; } $sanitizedPackage = escapeshellarg($package); } switch ($packageManager) { case 'zypper': $commandAll = 'zypper update -y'; $commandInstall = 'zypper install -y '.$sanitizedPackage; break; case 'dnf': $commandAll = 'dnf update -y'; $commandInstall = 'dnf update -y '.$sanitizedPackage; break; case 'apt': $commandAll = 'apt update && apt upgrade -y'; $commandInstall = 'apt install -y '.$sanitizedPackage; break; case 'pacman': $commandAll = 'pacman -Syu --noconfirm'; $commandInstall = 'pacman -S --noconfirm '.$sanitizedPackage; break; default: return [ 'error' => 'OS not supported', ]; } if ($all) { return remote_process([$commandAll], $server); } return remote_process([$commandInstall], $server); } catch (\Exception $e) { return [ 'error' => $e->getMessage(), ]; } } } ================================================ FILE: app/Actions/Server/ValidatePrerequisites.php ================================================ , found: array} */ public function handle(Server $server): array { $requiredCommands = ['git', 'curl', 'jq']; $missing = []; $found = []; foreach ($requiredCommands as $cmd) { $result = instant_remote_process(["command -v {$cmd}"], $server, false); if (! $result) { $missing[] = $cmd; } else { $found[] = $cmd; } } return [ 'success' => empty($missing), 'missing' => $missing, 'found' => $found, ]; } } ================================================ FILE: app/Actions/Server/ValidateServer.php ================================================ update([ 'validation_logs' => null, ]); ['uptime' => $this->uptime, 'error' => $error] = $server->validateConnection(); if (! $this->uptime) { $this->error = 'Server is not reachable. Please validate your configuration and connection.
Check this documentation for further help.

Error: '.$error.'
'; $server->update([ 'validation_logs' => $this->error, ]); throw new \Exception($this->error); } $this->supported_os_type = $server->validateOS(); if (! $this->supported_os_type) { $this->error = 'Server OS type is not supported. Please install Docker manually before continuing: documentation.'; $server->update([ 'validation_logs' => $this->error, ]); throw new \Exception($this->error); } $validationResult = $server->validatePrerequisites(); if (! $validationResult['success']) { $missingCommands = implode(', ', $validationResult['missing']); $this->error = "Prerequisites ({$missingCommands}) are not installed. Please install them before continuing or use the validation with installation endpoint."; $server->update([ 'validation_logs' => $this->error, ]); throw new \Exception($this->error); } $this->docker_installed = $server->validateDockerEngine(); $this->docker_compose_installed = $server->validateDockerCompose(); if (! $this->docker_installed || ! $this->docker_compose_installed) { $this->error = 'Docker Engine is not installed. Please install Docker manually before continuing: documentation.'; $server->update([ 'validation_logs' => $this->error, ]); throw new \Exception($this->error); } $this->docker_version = $server->validateDockerEngineVersion(); if ($this->docker_version) { return 'OK'; } else { $this->error = 'Docker Engine is not installed. Please install Docker manually before continuing: documentation.'; $server->update([ 'validation_logs' => $this->error, ]); throw new \Exception($this->error); } } } ================================================ FILE: app/Actions/Service/DeleteService.php ================================================ isFunctional()) { $storagesToDelete = collect([]); $service->environment_variables()->delete(); $commands = []; foreach ($service->applications()->get() as $application) { $storages = $application->persistentStorages()->get(); foreach ($storages as $storage) { $storagesToDelete->push($storage); } } foreach ($service->databases()->get() as $database) { $storages = $database->persistentStorages()->get(); foreach ($storages as $storage) { $storagesToDelete->push($storage); } } foreach ($storagesToDelete as $storage) { $commands[] = "docker volume rm -f $storage->name"; } // Execute volume deletion first, this must be done first otherwise volumes will not be deleted. if (! empty($commands)) { foreach ($commands as $command) { $result = instant_remote_process([$command], $server, false); if ($result !== null && $result !== 0) { Log::error('Error deleting volumes: '.$result); } } } } if ($deleteConnectedNetworks) { $service->deleteConnectedNetworks(); } instant_remote_process(["docker rm -f $service->uuid"], $server, throwError: false); } catch (\Exception $e) { throw new \RuntimeException($e->getMessage()); } finally { if ($deleteConfigurations) { $service->deleteConfigurations(); } foreach ($service->applications()->get() as $application) { $application->forceDelete(); } foreach ($service->databases()->get() as $database) { $database->forceDelete(); } foreach ($service->scheduled_tasks as $task) { $task->delete(); } $service->tags()->detach(); $service->forceDelete(); if ($dockerCleanup) { CleanupDocker::dispatch($server, false, false); } } } } ================================================ FILE: app/Actions/Service/RestartService.php ================================================ parse(); if ($stopBeforeStart) { StopService::run(service: $service, dockerCleanup: false); } $service->saveComposeConfigs(); $service->isConfigurationChanged(save: true); $workdir = $service->workdir(); // $commands[] = "cd {$workdir}"; $commands[] = "echo 'Saved configuration files to {$workdir}.'"; // Ensure .env exists in the correct directory before docker compose tries to load it // This is defensive programming - saveComposeConfigs() already creates it, // but we guarantee it here in case of any edge cases or manual deployments $commands[] = "touch {$workdir}/.env"; if ($pullLatestImages) { $commands[] = "echo 'Pulling images.'"; $commands[] = "docker compose --project-directory {$workdir} pull"; } if ($service->networks()->count() > 0) { $commands[] = "echo 'Creating Docker network.'"; $commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid"; } $commands[] = 'echo Starting service.'; $commands[] = "docker compose --project-directory {$workdir} -f {$workdir}/docker-compose.yml --project-name {$service->uuid} up -d --remove-orphans --force-recreate --build"; $commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true"; if (data_get($service, 'connect_to_docker_network')) { $compose = data_get($service, 'docker_compose', []); $network = $service->destination->network; $serviceNames = data_get(Yaml::parse($compose), 'services', []); foreach ($serviceNames as $serviceName => $serviceConfig) { $commands[] = "docker network connect --alias {$serviceName}-{$service->uuid} $network {$serviceName}-{$service->uuid} >/dev/null 2>&1 || true"; } } return remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged'); } } ================================================ FILE: app/Actions/Service/StopService.php ================================================ type_uuid', $service->uuid) ->where(function ($q) { $q->where('properties->status', ProcessStatus::IN_PROGRESS->value) ->orWhere('properties->status', ProcessStatus::QUEUED->value); }) ->each(function ($activity) { $activity->properties = $activity->properties->put('status', ProcessStatus::CANCELLED->value); $activity->save(); }); $server = $service->destination->server; if (! $server->isFunctional()) { return 'Server is not functional'; } $containersToStop = []; $applications = $service->applications()->get(); foreach ($applications as $application) { $containersToStop[] = "{$application->name}-{$service->uuid}"; } $dbs = $service->databases()->get(); foreach ($dbs as $db) { $containersToStop[] = "{$db->name}-{$service->uuid}"; } if (! empty($containersToStop)) { $this->stopContainersInParallel($containersToStop, $server); } if ($deleteConnectedNetworks) { $service->deleteConnectedNetworks(); } if ($dockerCleanup) { CleanupDocker::dispatch($server, false, false); } } catch (\Exception $e) { return $e->getMessage(); } finally { ServiceStatusChanged::dispatch($service->environment->project->team->id); } } private function stopContainersInParallel(array $containersToStop, Server $server): void { $timeout = count($containersToStop) > 5 ? 10 : 30; $commands = []; $containerList = implode(' ', $containersToStop); $commands[] = "docker stop -t $timeout $containerList"; $commands[] = "docker rm -f $containerList"; instant_remote_process( command: $commands, server: $server, throwError: false ); } } ================================================ FILE: app/Actions/Shared/ComplexStatusCheck.php ================================================ additional_servers; $servers->push($application->destination->server); foreach ($servers as $server) { $is_main_server = $application->destination->server->id === $server->id; if (! $server->isFunctional()) { if ($is_main_server) { $application->update(['status' => 'exited']); continue; } else { $application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited']); continue; } } $containers = instant_remote_process(["docker container inspect $(docker container ls -q --filter 'label=coolify.applicationId={$application->id}' --filter 'label=coolify.pullRequestId=0') --format '{{json .}}'"], $server, false); $containers = format_docker_command_output_to_json($containers); if ($containers->count() > 0) { $statusToSet = $this->aggregateContainerStatuses($application, $containers); if ($is_main_server) { $statusFromDb = $application->status; if ($statusFromDb !== $statusToSet) { $application->update(['status' => $statusToSet]); } } else { $additional_server = $application->additional_servers()->wherePivot('server_id', $server->id); $statusFromDb = $additional_server->first()->pivot->status; if ($statusFromDb !== $statusToSet) { $additional_server->updateExistingPivot($server->id, ['status' => $statusToSet]); } } } else { if ($is_main_server) { $application->update(['status' => 'exited']); continue; } else { $application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited']); continue; } } } } private function aggregateContainerStatuses($application, $containers) { $dockerComposeRaw = data_get($application, 'docker_compose_raw'); $excludedContainers = $this->getExcludedContainersFromDockerCompose($dockerComposeRaw); // Filter non-excluded containers $relevantContainers = collect($containers)->filter(function ($container) use ($excludedContainers) { $labels = data_get($container, 'Config.Labels', []); $serviceName = data_get($labels, 'com.docker.compose.service'); return ! ($serviceName && $excludedContainers->contains($serviceName)); }); // If all containers are excluded, calculate status from excluded containers // but mark it with :excluded to indicate monitoring is disabled if ($relevantContainers->isEmpty()) { return $this->calculateExcludedStatus($containers, $excludedContainers); } // Use ContainerStatusAggregator service for state machine logic $aggregator = new ContainerStatusAggregator; return $aggregator->aggregateFromContainers($relevantContainers); } } ================================================ FILE: app/Actions/Stripe/CancelSubscription.php ================================================ user = $user; $this->isDryRun = $isDryRun; if (! $isDryRun && isCloud()) { $this->stripe = new StripeClient(config('subscription.stripe_api_key')); } } public function getSubscriptionsPreview(): Collection { $subscriptions = collect(); // Get all teams the user belongs to $teams = $this->user->teams()->get(); foreach ($teams as $team) { // Only include subscriptions from teams where user is owner $userRole = $team->pivot->role; if ($userRole === 'owner' && $team->subscription) { $subscription = $team->subscription; // Only include active subscriptions if ($subscription->stripe_subscription_id && $subscription->stripe_invoice_paid) { $subscriptions->push($subscription); } } } return $subscriptions; } /** * Verify subscriptions exist and are active in Stripe API * * @return array ['verified' => Collection, 'not_found' => Collection, 'errors' => array] */ public function verifySubscriptionsInStripe(): array { if (! isCloud()) { return [ 'verified' => collect(), 'not_found' => collect(), 'errors' => [], ]; } $stripe = new StripeClient(config('subscription.stripe_api_key')); $subscriptions = $this->getSubscriptionsPreview(); $verified = collect(); $notFound = collect(); $errors = []; foreach ($subscriptions as $subscription) { try { $stripeSubscription = $stripe->subscriptions->retrieve($subscription->stripe_subscription_id); // Check if subscription is actually active in Stripe if (in_array($stripeSubscription->status, ['active', 'trialing', 'past_due'])) { $verified->push([ 'subscription' => $subscription, 'stripe_status' => $stripeSubscription->status, 'current_period_end' => $stripeSubscription->current_period_end, ]); } else { $notFound->push([ 'subscription' => $subscription, 'reason' => "Status in Stripe: {$stripeSubscription->status}", ]); } } catch (\Stripe\Exception\InvalidRequestException $e) { // Subscription doesn't exist in Stripe $notFound->push([ 'subscription' => $subscription, 'reason' => 'Not found in Stripe', ]); } catch (\Exception $e) { $errors[] = "Error verifying subscription {$subscription->stripe_subscription_id}: ".$e->getMessage(); \Log::error("Error verifying subscription {$subscription->stripe_subscription_id}: ".$e->getMessage()); } } return [ 'verified' => $verified, 'not_found' => $notFound, 'errors' => $errors, ]; } public function execute(): array { if ($this->isDryRun) { return [ 'cancelled' => 0, 'failed' => 0, 'errors' => [], ]; } $cancelledCount = 0; $failedCount = 0; $errors = []; $subscriptions = $this->getSubscriptionsPreview(); foreach ($subscriptions as $subscription) { try { $this->cancelSingleSubscription($subscription); $cancelledCount++; } catch (\Exception $e) { $failedCount++; $errorMessage = "Failed to cancel subscription {$subscription->stripe_subscription_id}: ".$e->getMessage(); $errors[] = $errorMessage; \Log::error($errorMessage); } } return [ 'cancelled' => $cancelledCount, 'failed' => $failedCount, 'errors' => $errors, ]; } private function cancelSingleSubscription(Subscription $subscription): void { if (! $this->stripe) { throw new \Exception('Stripe client not initialized'); } $subscriptionId = $subscription->stripe_subscription_id; // Cancel the subscription immediately (not at period end) $this->stripe->subscriptions->cancel($subscriptionId, []); // Update local database $subscription->update([ 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, 'stripe_trial_already_ended' => false, 'stripe_past_due' => false, 'stripe_feedback' => 'User account deleted', 'stripe_comment' => 'Subscription cancelled due to user account deletion at '.now()->toDateTimeString(), ]); // Call the team's subscription ended method to handle cleanup if ($subscription->team) { $subscription->team->subscriptionEnded(); } \Log::info("Cancelled Stripe subscription: {$subscriptionId} for team: {$subscription->team->name}"); } /** * Cancel a single subscription by ID (helper method for external use) */ public static function cancelById(string $subscriptionId): bool { try { if (! isCloud()) { return false; } $stripe = new StripeClient(config('subscription.stripe_api_key')); $stripe->subscriptions->cancel($subscriptionId, []); // Update local record if exists $subscription = Subscription::where('stripe_subscription_id', $subscriptionId)->first(); if ($subscription) { $subscription->update([ 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, 'stripe_trial_already_ended' => false, 'stripe_past_due' => false, ]); if ($subscription->team) { $subscription->team->subscriptionEnded(); } } return true; } catch (\Exception $e) { \Log::error("Failed to cancel subscription {$subscriptionId}: ".$e->getMessage()); return false; } } } ================================================ FILE: app/Actions/Stripe/CancelSubscriptionAtPeriodEnd.php ================================================ stripe = $stripe ?? new StripeClient(config('subscription.stripe_api_key')); } /** * Cancel the team's subscription at the end of the current billing period. * * @return array{success: bool, error: string|null} */ public function execute(Team $team): array { $subscription = $team->subscription; if (! $subscription?->stripe_subscription_id) { return ['success' => false, 'error' => 'No active subscription found.']; } if (! $subscription->stripe_invoice_paid) { return ['success' => false, 'error' => 'Subscription is not active.']; } if ($subscription->stripe_cancel_at_period_end) { return ['success' => false, 'error' => 'Subscription is already set to cancel at the end of the billing period.']; } try { $this->stripe->subscriptions->update($subscription->stripe_subscription_id, [ 'cancel_at_period_end' => true, ]); $subscription->update([ 'stripe_cancel_at_period_end' => true, ]); \Log::info("Subscription {$subscription->stripe_subscription_id} set to cancel at period end for team {$team->name}"); return ['success' => true, 'error' => null]; } catch (\Stripe\Exception\InvalidRequestException $e) { \Log::error("Stripe cancel at period end error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'Stripe error: '.$e->getMessage()]; } catch (\Exception $e) { \Log::error("Cancel at period end error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'An unexpected error occurred. Please contact support.']; } } } ================================================ FILE: app/Actions/Stripe/RefundSubscription.php ================================================ stripe = $stripe ?? new StripeClient(config('subscription.stripe_api_key')); } /** * Check if the team's subscription is eligible for a refund. * * @return array{eligible: bool, days_remaining: int, reason: string} */ public function checkEligibility(Team $team): array { $subscription = $team->subscription; if ($subscription?->stripe_refunded_at) { return $this->ineligible('A refund has already been processed for this team.'); } if (! $subscription?->stripe_subscription_id) { return $this->ineligible('No active subscription found.'); } if (! $subscription->stripe_invoice_paid) { return $this->ineligible('Subscription invoice is not paid.'); } try { $stripeSubscription = $this->stripe->subscriptions->retrieve($subscription->stripe_subscription_id); } catch (\Stripe\Exception\InvalidRequestException $e) { return $this->ineligible('Subscription not found in Stripe.'); } if (! in_array($stripeSubscription->status, ['active', 'trialing'])) { return $this->ineligible("Subscription status is '{$stripeSubscription->status}'."); } $startDate = \Carbon\Carbon::createFromTimestamp($stripeSubscription->start_date); $daysSinceStart = (int) $startDate->diffInDays(now()); $daysRemaining = self::REFUND_WINDOW_DAYS - $daysSinceStart; if ($daysRemaining <= 0) { return $this->ineligible('The 30-day refund window has expired.'); } return [ 'eligible' => true, 'days_remaining' => $daysRemaining, 'reason' => 'Eligible for refund.', ]; } /** * Process a full refund and cancel the subscription. * * @return array{success: bool, error: string|null} */ public function execute(Team $team): array { $eligibility = $this->checkEligibility($team); if (! $eligibility['eligible']) { return ['success' => false, 'error' => $eligibility['reason']]; } $subscription = $team->subscription; try { $invoices = $this->stripe->invoices->all([ 'subscription' => $subscription->stripe_subscription_id, 'status' => 'paid', 'limit' => 1, ]); if (empty($invoices->data)) { return ['success' => false, 'error' => 'No paid invoice found to refund.']; } $invoice = $invoices->data[0]; $paymentIntentId = $invoice->payment_intent; if (! $paymentIntentId) { return ['success' => false, 'error' => 'No payment intent found on the invoice.']; } $this->stripe->refunds->create([ 'payment_intent' => $paymentIntentId, ]); $this->stripe->subscriptions->cancel($subscription->stripe_subscription_id); $subscription->update([ 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, 'stripe_trial_already_ended' => false, 'stripe_past_due' => false, 'stripe_feedback' => 'Refund requested by user', 'stripe_comment' => 'Full refund processed within 30-day window at '.now()->toDateTimeString(), 'stripe_refunded_at' => now(), ]); $team->subscriptionEnded(); \Log::info("Refunded and cancelled subscription {$subscription->stripe_subscription_id} for team {$team->name}"); return ['success' => true, 'error' => null]; } catch (\Stripe\Exception\InvalidRequestException $e) { \Log::error("Stripe refund error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'Stripe error: '.$e->getMessage()]; } catch (\Exception $e) { \Log::error("Refund error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'An unexpected error occurred. Please contact support.']; } } /** * @return array{eligible: bool, days_remaining: int, reason: string} */ private function ineligible(string $reason): array { return [ 'eligible' => false, 'days_remaining' => 0, 'reason' => $reason, ]; } } ================================================ FILE: app/Actions/Stripe/ResumeSubscription.php ================================================ stripe = $stripe ?? new StripeClient(config('subscription.stripe_api_key')); } /** * Resume a subscription that was set to cancel at the end of the billing period. * * @return array{success: bool, error: string|null} */ public function execute(Team $team): array { $subscription = $team->subscription; if (! $subscription?->stripe_subscription_id) { return ['success' => false, 'error' => 'No active subscription found.']; } if (! $subscription->stripe_cancel_at_period_end) { return ['success' => false, 'error' => 'Subscription is not set to cancel.']; } try { $this->stripe->subscriptions->update($subscription->stripe_subscription_id, [ 'cancel_at_period_end' => false, ]); $subscription->update([ 'stripe_cancel_at_period_end' => false, ]); \Log::info("Subscription {$subscription->stripe_subscription_id} resumed for team {$team->name}"); return ['success' => true, 'error' => null]; } catch (\Stripe\Exception\InvalidRequestException $e) { \Log::error("Stripe resume subscription error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'Stripe error: '.$e->getMessage()]; } catch (\Exception $e) { \Log::error("Resume subscription error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'An unexpected error occurred. Please contact support.']; } } } ================================================ FILE: app/Actions/Stripe/UpdateSubscriptionQuantity.php ================================================ stripe = $stripe ?? new StripeClient(config('subscription.stripe_api_key')); } /** * Fetch a full price preview for a quantity change from Stripe. * Returns both the prorated amount due now and the recurring cost for the next billing cycle. * * @return array{success: bool, error: string|null, preview: array{due_now: int, recurring_subtotal: int, recurring_tax: int, recurring_total: int, unit_price: int, tax_description: string|null, quantity: int, currency: string}|null} */ public function fetchPricePreview(Team $team, int $quantity): array { $subscription = $team->subscription; if (! $subscription?->stripe_subscription_id || ! $subscription->stripe_invoice_paid) { return ['success' => false, 'error' => 'No active subscription found.', 'preview' => null]; } try { $stripeSubscription = $this->stripe->subscriptions->retrieve($subscription->stripe_subscription_id); $item = $stripeSubscription->items->data[0] ?? null; if (! $item) { return ['success' => false, 'error' => 'Could not retrieve subscription details.', 'preview' => null]; } $currency = strtoupper($item->price->currency ?? 'usd'); // Upcoming invoice gives us the prorated amount due now $upcomingInvoice = $this->stripe->invoices->upcoming([ 'customer' => $subscription->stripe_customer_id, 'subscription' => $subscription->stripe_subscription_id, 'subscription_items' => [ ['id' => $item->id, 'quantity' => $quantity], ], 'subscription_proration_behavior' => 'create_prorations', ]); // Extract tax percentage — try total_tax_amounts first, fall back to invoice tax/subtotal $taxPercentage = 0.0; $taxDescription = null; if (! empty($upcomingInvoice->total_tax_amounts)) { $taxAmount = $upcomingInvoice->total_tax_amounts[0] ?? null; if ($taxAmount?->tax_rate) { $taxRate = $this->stripe->taxRates->retrieve($taxAmount->tax_rate); $taxPercentage = (float) ($taxRate->percentage ?? 0); $taxDescription = $taxRate->display_name.' ('.$taxRate->jurisdiction.') '.$taxRate->percentage.'%'; } } // Fallback tax percentage from invoice totals - use tax_rate details when available for accuracy if ($taxPercentage === 0.0 && ($upcomingInvoice->tax ?? 0) > 0 && ($upcomingInvoice->subtotal ?? 0) > 0) { $taxPercentage = round(($upcomingInvoice->tax / $upcomingInvoice->subtotal) * 100, 2); } // Recurring cost for next cycle — read from non-proration invoice lines $recurringSubtotal = 0; foreach ($upcomingInvoice->lines->data as $line) { if (! $line->proration) { $recurringSubtotal += $line->amount; } } $unitPrice = $quantity > 0 ? (int) round($recurringSubtotal / $quantity) : 0; $recurringTax = $taxPercentage > 0 ? (int) round($recurringSubtotal * $taxPercentage / 100) : 0; $recurringTotal = $recurringSubtotal + $recurringTax; // Due now = amount_due (accounts for customer balance/credits) minus recurring $amountDue = $upcomingInvoice->amount_due ?? $upcomingInvoice->total ?? 0; $dueNow = $amountDue - $recurringTotal; return [ 'success' => true, 'error' => null, 'preview' => [ 'due_now' => $dueNow, 'recurring_subtotal' => $recurringSubtotal, 'recurring_tax' => $recurringTax, 'recurring_total' => $recurringTotal, 'unit_price' => $unitPrice, 'tax_description' => $taxDescription, 'quantity' => $quantity, 'currency' => $currency, ], ]; } catch (\Exception $e) { \Log::warning("Stripe fetch price preview error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'Could not load price preview.', 'preview' => null]; } } /** * Update the subscription quantity (server limit) for a team. * * @return array{success: bool, error: string|null} */ public function execute(Team $team, int $quantity): array { if ($quantity < self::MIN_SERVER_LIMIT) { return ['success' => false, 'error' => 'Minimum server limit is '.self::MIN_SERVER_LIMIT.'.']; } $subscription = $team->subscription; if (! $subscription?->stripe_subscription_id) { return ['success' => false, 'error' => 'No active subscription found.']; } if (! $subscription->stripe_invoice_paid) { return ['success' => false, 'error' => 'Subscription is not active.']; } try { $stripeSubscription = $this->stripe->subscriptions->retrieve($subscription->stripe_subscription_id); $item = $stripeSubscription->items->data[0] ?? null; if (! $item?->id) { return ['success' => false, 'error' => 'Could not find subscription item.']; } $previousQuantity = $item->quantity ?? $team->custom_server_limit; $updatedSubscription = $this->stripe->subscriptions->update($subscription->stripe_subscription_id, [ 'items' => [ ['id' => $item->id, 'quantity' => $quantity], ], 'proration_behavior' => 'always_invoice', 'expand' => ['latest_invoice'], ]); // Check if the proration invoice was paid $latestInvoice = $updatedSubscription->latest_invoice; if ($latestInvoice && $latestInvoice->status !== 'paid') { \Log::warning("Subscription {$subscription->stripe_subscription_id} quantity updated but invoice not paid (status: {$latestInvoice->status}) for team {$team->name}. Reverting to {$previousQuantity}."); // Revert subscription quantity on Stripe $this->stripe->subscriptions->update($subscription->stripe_subscription_id, [ 'items' => [ ['id' => $item->id, 'quantity' => $previousQuantity], ], 'proration_behavior' => 'none', ]); // Void the unpaid invoice if ($latestInvoice->id) { $this->stripe->invoices->voidInvoice($latestInvoice->id); } return ['success' => false, 'error' => 'Payment failed. Your server limit was not changed. Please check your payment method and try again.']; } $team->update([ 'custom_server_limit' => $quantity, ]); ServerLimitCheckJob::dispatch($team); \Log::info("Subscription {$subscription->stripe_subscription_id} quantity updated to {$quantity} for team {$team->name}"); return ['success' => true, 'error' => null]; } catch (\Stripe\Exception\InvalidRequestException $e) { \Log::error("Stripe update quantity error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'Stripe error: '.$e->getMessage()]; } catch (\Exception $e) { \Log::error("Update subscription quantity error for team {$team->id}: ".$e->getMessage()); return ['success' => false, 'error' => 'An unexpected error occurred. Please contact support.']; } } private function formatAmount(int $cents, string $currency): string { return strtoupper($currency) === 'USD' ? '$'.number_format($cents / 100, 2) : number_format($cents / 100, 2).' '.$currency; } } ================================================ FILE: app/Actions/User/DeleteUserResources.php ================================================ user = $user; $this->isDryRun = $isDryRun; } public function getResourcesPreview(): array { $applications = collect(); $databases = collect(); $services = collect(); // Get all teams the user belongs to $teams = $this->user->teams()->get(); foreach ($teams as $team) { // Only delete resources from teams that will be FULLY DELETED // This means: user is the ONLY member of the team // // DO NOT delete resources if: // - User is just a member (not owner) // - Team has other members (ownership will be transferred or user just removed) $userRole = $team->pivot->role; $memberCount = $team->members->count(); // Skip if user is not owner if ($userRole !== 'owner') { continue; } // Skip if team has other members (will be transferred/user removed, not deleted) if ($memberCount > 1) { continue; } // Only delete resources from teams where user is the ONLY member // These teams will be fully deleted // Get all servers for this team $servers = $team->servers()->get(); foreach ($servers as $server) { // Get applications (custom method returns Collection) $serverApplications = $server->applications(); $applications = $applications->merge($serverApplications); // Get databases (custom method returns Collection) $serverDatabases = $server->databases(); $databases = $databases->merge($serverDatabases); // Get services (relationship needs ->get()) $serverServices = $server->services()->get(); $services = $services->merge($serverServices); } } return [ 'applications' => $applications->unique('id'), 'databases' => $databases->unique('id'), 'services' => $services->unique('id'), ]; } public function execute(): array { if ($this->isDryRun) { return [ 'applications' => 0, 'databases' => 0, 'services' => 0, ]; } $deletedCounts = [ 'applications' => 0, 'databases' => 0, 'services' => 0, ]; $resources = $this->getResourcesPreview(); // Delete applications foreach ($resources['applications'] as $application) { try { $application->forceDelete(); $deletedCounts['applications']++; } catch (\Exception $e) { \Log::error("Failed to delete application {$application->id}: ".$e->getMessage()); throw $e; // Re-throw to trigger rollback } } // Delete databases foreach ($resources['databases'] as $database) { try { $database->forceDelete(); $deletedCounts['databases']++; } catch (\Exception $e) { \Log::error("Failed to delete database {$database->id}: ".$e->getMessage()); throw $e; // Re-throw to trigger rollback } } // Delete services foreach ($resources['services'] as $service) { try { $service->forceDelete(); $deletedCounts['services']++; } catch (\Exception $e) { \Log::error("Failed to delete service {$service->id}: ".$e->getMessage()); throw $e; // Re-throw to trigger rollback } } return $deletedCounts; } } ================================================ FILE: app/Actions/User/DeleteUserServers.php ================================================ user = $user; $this->isDryRun = $isDryRun; } public function getServersPreview(): Collection { $servers = collect(); // Get all teams the user belongs to $teams = $this->user->teams()->get(); foreach ($teams as $team) { // Only include servers from teams where user is owner or admin $userRole = $team->pivot->role; if ($userRole === 'owner' || $userRole === 'admin') { $teamServers = $team->servers()->get(); $servers = $servers->merge($teamServers); } } // Return unique servers (in case same server is in multiple teams) return $servers->unique('id'); } public function execute(): array { if ($this->isDryRun) { return [ 'servers' => 0, ]; } $deletedCount = 0; $servers = $this->getServersPreview(); foreach ($servers as $server) { try { // Skip the default server (ID 0) which is the Coolify host if ($server->id === 0) { \Log::info('Skipping deletion of Coolify host server (ID: 0)'); continue; } // The Server model's forceDeleting event will handle cleanup of: // - destinations // - settings $server->forceDelete(); $deletedCount++; } catch (\Exception $e) { \Log::error("Failed to delete server {$server->id}: ".$e->getMessage()); throw $e; // Re-throw to trigger rollback } } return [ 'servers' => $deletedCount, ]; } } ================================================ FILE: app/Actions/User/DeleteUserTeams.php ================================================ user = $user; $this->isDryRun = $isDryRun; } public function getTeamsPreview(): array { $teamsToDelete = collect(); $teamsToTransfer = collect(); $teamsToLeave = collect(); $edgeCases = collect(); $teams = $this->user->teams; foreach ($teams as $team) { // Skip root team (ID 0) if ($team->id === 0) { continue; } $userRole = $team->pivot->role; $memberCount = $team->members->count(); if ($memberCount === 1) { // User is alone in the team - delete it $teamsToDelete->push($team); } elseif ($userRole === 'owner') { // Check if there are other owners $otherOwners = $team->members ->where('id', '!=', $this->user->id) ->filter(function ($member) { return $member->pivot->role === 'owner'; }); if ($otherOwners->isNotEmpty()) { // There are other owners, but check if this user is paying for the subscription if ($this->isUserPayingForTeamSubscription($team)) { // User is paying for the subscription - this is an edge case $edgeCases->push([ 'team' => $team, 'reason' => 'User is paying for the team\'s Stripe subscription but there are other owners. The subscription needs to be cancelled or transferred to another owner\'s payment method.', ]); } else { // There are other owners and user is not paying, just remove this user $teamsToLeave->push($team); } } else { // User is the only owner, check for replacement $newOwner = $this->findNewOwner($team); if ($newOwner) { $teamsToTransfer->push([ 'team' => $team, 'new_owner' => $newOwner, ]); } else { // No suitable replacement found - this is an edge case $edgeCases->push([ 'team' => $team, 'reason' => 'No suitable owner replacement found. Team has only regular members without admin privileges.', ]); } } } else { // User is just a member - remove them from the team $teamsToLeave->push($team); } } return [ 'to_delete' => $teamsToDelete, 'to_transfer' => $teamsToTransfer, 'to_leave' => $teamsToLeave, 'edge_cases' => $edgeCases, ]; } public function execute(): array { if ($this->isDryRun) { return [ 'deleted' => 0, 'transferred' => 0, 'left' => 0, ]; } $counts = [ 'deleted' => 0, 'transferred' => 0, 'left' => 0, ]; $preview = $this->getTeamsPreview(); // Check for edge cases - should not happen here as we check earlier, but be safe if ($preview['edge_cases']->isNotEmpty()) { throw new \Exception('Edge cases detected during execution. This should not happen.'); } // Delete teams where user is alone foreach ($preview['to_delete'] as $team) { try { // The Team model's deleting event will handle cleanup of: // - private keys // - sources // - tags // - environment variables // - s3 storages // - notification settings $team->delete(); $counts['deleted']++; } catch (\Exception $e) { \Log::error("Failed to delete team {$team->id}: ".$e->getMessage()); throw $e; // Re-throw to trigger rollback } } // Transfer ownership for teams where user is owner but not alone foreach ($preview['to_transfer'] as $item) { try { $team = $item['team']; $newOwner = $item['new_owner']; // Update the new owner's role to owner $team->members()->updateExistingPivot($newOwner->id, ['role' => 'owner']); // Remove the current user from the team $team->members()->detach($this->user->id); $counts['transferred']++; } catch (\Exception $e) { \Log::error("Failed to transfer ownership of team {$item['team']->id}: ".$e->getMessage()); throw $e; // Re-throw to trigger rollback } } // Remove user from teams where they're just a member foreach ($preview['to_leave'] as $team) { try { $team->members()->detach($this->user->id); $counts['left']++; } catch (\Exception $e) { \Log::error("Failed to remove user from team {$team->id}: ".$e->getMessage()); throw $e; // Re-throw to trigger rollback } } return $counts; } private function findNewOwner(Team $team): ?User { // Only look for admins as potential new owners // We don't promote regular members automatically $otherAdmin = $team->members ->where('id', '!=', $this->user->id) ->filter(function ($member) { return $member->pivot->role === 'admin'; }) ->first(); return $otherAdmin; } private function isUserPayingForTeamSubscription(Team $team): bool { if (! $team->subscription || ! $team->subscription->stripe_customer_id) { return false; } // In Stripe, we need to check if the customer email matches the user's email // This would require a Stripe API call to get customer details // For now, we'll check if the subscription was created by this user // Alternative approach: Check if user is the one who initiated the subscription // We could store this information when the subscription is created // For safety, we'll assume if there's an active subscription and multiple owners, // we should treat it as an edge case that needs manual review if ($team->subscription->stripe_subscription_id && $team->subscription->stripe_invoice_paid) { // Active subscription exists - we should be cautious return true; } return false; } } ================================================ FILE: app/Console/Commands/AdminDeleteUser.php ================================================ false, 'phase_2_resources' => false, 'phase_3_servers' => false, 'phase_4_teams' => false, 'phase_5_user_profile' => false, 'phase_6_stripe' => false, 'db_committed' => false, ]; public function handle() { // Register signal handlers for graceful shutdown (Ctrl+C handling) $this->registerSignalHandlers(); $email = $this->argument('email'); $this->isDryRun = $this->option('dry-run'); $this->skipStripe = $this->option('skip-stripe'); $this->skipResources = $this->option('skip-resources'); $force = $this->option('force'); if ($force) { $this->warn('⚠️ FORCE MODE - Lock check will be bypassed'); $this->warn(' Use this flag only if you are certain no other deletion is running'); $this->newLine(); } if ($this->isDryRun) { $this->info('🔍 DRY RUN MODE - No data will be deleted'); $this->newLine(); } if ($this->output->isVerbose()) { $this->info('📊 VERBOSE MODE - Full stack traces will be shown on errors'); $this->newLine(); } else { $this->comment('💡 Tip: Use -v flag for detailed error stack traces'); $this->newLine(); } if (! $this->isDryRun && ! $this->option('auto-confirm')) { $this->info('🔄 INTERACTIVE MODE - You will be asked to confirm after each phase'); $this->comment(' Use --auto-confirm to skip phase confirmations'); $this->newLine(); } // Notify about instance type and Stripe if (isCloud()) { $this->comment('☁️ Cloud instance - Stripe subscriptions will be handled'); } else { $this->comment('🏠 Self-hosted instance - Stripe operations will be skipped'); } $this->newLine(); try { $this->user = User::whereEmail($email)->firstOrFail(); } catch (\Exception $e) { $this->error("User with email '{$email}' not found."); return 1; } // Implement file lock to prevent concurrent deletions of the same user $lockKey = "user_deletion_{$this->user->id}"; $this->lock = Cache::lock($lockKey, 600); // 10 minute lock if (! $force) { if (! $this->lock->get()) { $this->error('Another deletion process is already running for this user.'); $this->error('Use --force to bypass this lock (use with extreme caution).'); $this->logAction("Deletion blocked for user {$email}: Another process is already running"); return 1; } } else { // In force mode, try to get lock but continue even if it fails if (! $this->lock->get()) { $this->warn('⚠️ Lock exists but proceeding due to --force flag'); $this->warn(' There may be another deletion process running!'); $this->newLine(); } } try { $this->logAction("Starting user deletion process for: {$email}"); // Phase 1: Show User Overview (outside transaction) if (! $this->showUserOverview()) { $this->info('User deletion cancelled by operator.'); return 0; } $this->deletionState['phase_1_overview'] = true; // If not dry run, wrap DB operations in a transaction // NOTE: Stripe cancellations happen AFTER commit to avoid inconsistent state if (! $this->isDryRun) { try { DB::beginTransaction(); // Phase 2: Delete Resources // WARNING: This triggers Docker container deletion via SSH which CANNOT be rolled back if (! $this->skipResources) { if (! $this->deleteResources()) { DB::rollBack(); $this->displayErrorState('Phase 2: Resource Deletion'); $this->error('❌ User deletion failed at resource deletion phase.'); $this->warn('⚠️ Some Docker containers may have been deleted on remote servers and cannot be restored.'); $this->displayRecoverySteps(); return 1; } } $this->deletionState['phase_2_resources'] = true; // Confirmation to continue after Phase 2 if (! $this->skipResources && ! $this->option('auto-confirm')) { $this->newLine(); if (! $this->confirm('Phase 2 completed. Continue to Phase 3 (Delete Servers)?', true)) { DB::rollBack(); $this->info('User deletion cancelled by operator after Phase 2.'); $this->info('Database changes have been rolled back.'); return 0; } } // Phase 3: Delete Servers // WARNING: This may trigger cleanup operations on remote servers which CANNOT be rolled back if (! $this->deleteServers()) { DB::rollBack(); $this->displayErrorState('Phase 3: Server Deletion'); $this->error('❌ User deletion failed at server deletion phase.'); $this->warn('⚠️ Some server cleanup operations may have been performed and cannot be restored.'); $this->displayRecoverySteps(); return 1; } $this->deletionState['phase_3_servers'] = true; // Confirmation to continue after Phase 3 if (! $this->option('auto-confirm')) { $this->newLine(); if (! $this->confirm('Phase 3 completed. Continue to Phase 4 (Handle Teams)?', true)) { DB::rollBack(); $this->info('User deletion cancelled by operator after Phase 3.'); $this->info('Database changes have been rolled back.'); return 0; } } // Phase 4: Handle Teams if (! $this->handleTeams()) { DB::rollBack(); $this->displayErrorState('Phase 4: Team Handling'); $this->error('❌ User deletion failed at team handling phase.'); $this->displayRecoverySteps(); return 1; } $this->deletionState['phase_4_teams'] = true; // Confirmation to continue after Phase 4 if (! $this->option('auto-confirm')) { $this->newLine(); if (! $this->confirm('Phase 4 completed. Continue to Phase 5 (Delete User Profile)?', true)) { DB::rollBack(); $this->info('User deletion cancelled by operator after Phase 4.'); $this->info('Database changes have been rolled back.'); return 0; } } // Phase 5: Delete User Profile if (! $this->deleteUserProfile()) { DB::rollBack(); $this->displayErrorState('Phase 5: User Profile Deletion'); $this->error('❌ User deletion failed at user profile deletion phase.'); $this->displayRecoverySteps(); return 1; } $this->deletionState['phase_5_user_profile'] = true; // CRITICAL CONFIRMATION: Database commit is next (PERMANENT) if (! $this->option('auto-confirm')) { $this->newLine(); $this->warn('⚠️ CRITICAL DECISION POINT'); $this->warn('Next step: COMMIT database changes (PERMANENT and IRREVERSIBLE)'); $this->warn('All resources, servers, teams, and user profile will be permanently deleted'); $this->newLine(); if (! $this->confirm('Phase 5 completed. Commit database changes? (THIS IS PERMANENT)', false)) { DB::rollBack(); $this->info('User deletion cancelled by operator before commit.'); $this->info('Database changes have been rolled back.'); $this->warn('⚠️ Note: Some Docker containers may have been deleted on remote servers.'); return 0; } } // Commit the database transaction DB::commit(); $this->deletionState['db_committed'] = true; $this->newLine(); $this->info('✅ Database operations completed successfully!'); $this->info('✅ Transaction committed - database changes are now PERMANENT.'); $this->logAction("Database deletion completed for: {$email}"); // Confirmation to continue to Stripe (after commit) if (! $this->skipStripe && isCloud() && ! $this->option('auto-confirm')) { $this->newLine(); $this->warn('⚠️ Database changes are committed (permanent)'); $this->info('Next: Cancel Stripe subscriptions'); if (! $this->confirm('Continue to Phase 6 (Cancel Stripe Subscriptions)?', true)) { $this->warn('User deletion stopped after database commit.'); $this->error('⚠️ IMPORTANT: User deleted from database but Stripe subscriptions remain active!'); $this->error('You must cancel subscriptions manually in Stripe Dashboard.'); $this->error('Go to: https://dashboard.stripe.com/'); $this->error('Search for: '.$email); return 1; } } // Phase 6: Cancel Stripe Subscriptions (AFTER DB commit) // This is done AFTER commit because Stripe API calls cannot be rolled back // If this fails, DB changes are already committed but subscriptions remain active if (! $this->skipStripe && isCloud()) { if (! $this->cancelStripeSubscriptions()) { $this->newLine(); $this->error('═══════════════════════════════════════'); $this->error('⚠️ CRITICAL: INCONSISTENT STATE DETECTED'); $this->error('═══════════════════════════════════════'); $this->error('✓ User data DELETED from database (committed)'); $this->error('✗ Stripe subscription cancellation FAILED'); $this->newLine(); $this->displayErrorState('Phase 6: Stripe Cancellation (Post-Commit)'); $this->newLine(); $this->error('MANUAL ACTION REQUIRED:'); $this->error('1. Go to Stripe Dashboard: https://dashboard.stripe.com/'); $this->error('2. Search for customer email: '.$email); $this->error('3. Cancel all active subscriptions'); $this->error('4. Check storage/logs/user-deletions.log for subscription IDs'); $this->newLine(); $this->logAction("INCONSISTENT STATE: User {$email} deleted but Stripe cancellation failed"); return 1; } } $this->deletionState['phase_6_stripe'] = true; $this->newLine(); $this->info('✅ User deletion completed successfully!'); $this->logAction("User deletion completed for: {$email}"); } catch (\Exception $e) { DB::rollBack(); $this->newLine(); $this->error('═══════════════════════════════════════'); $this->error('❌ EXCEPTION DURING USER DELETION'); $this->error('═══════════════════════════════════════'); $this->error('Exception: '.get_class($e)); $this->error('Message: '.$e->getMessage()); $this->error('File: '.$e->getFile().':'.$e->getLine()); $this->newLine(); if ($this->output->isVerbose()) { $this->error('Stack Trace:'); $this->error($e->getTraceAsString()); $this->newLine(); } else { $this->info('Run with -v for full stack trace'); $this->newLine(); } $this->displayErrorState('Exception during execution'); $this->displayRecoverySteps(); $this->logAction("User deletion failed for {$email}: {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}"); return 1; } } else { // Dry run mode - just run through the phases without transaction // Phase 2: Delete Resources if (! $this->skipResources) { if (! $this->deleteResources()) { $this->info('User deletion would be cancelled at resource deletion phase.'); return 0; } } // Phase 3: Delete Servers if (! $this->deleteServers()) { $this->info('User deletion would be cancelled at server deletion phase.'); return 0; } // Phase 4: Handle Teams if (! $this->handleTeams()) { $this->info('User deletion would be cancelled at team handling phase.'); return 0; } // Phase 5: Delete User Profile if (! $this->deleteUserProfile()) { $this->info('User deletion would be cancelled at user profile deletion phase.'); return 0; } // Phase 6: Cancel Stripe Subscriptions (shown after DB operations in dry run too) if (! $this->skipStripe && isCloud()) { if (! $this->cancelStripeSubscriptions()) { $this->info('User deletion would be cancelled at Stripe cancellation phase.'); return 0; } } $this->newLine(); $this->info('✅ DRY RUN completed successfully! No data was deleted.'); } return 0; } finally { // Ensure lock is always released $this->releaseLock(); } } private function showUserOverview(): bool { $this->info('═══════════════════════════════════════'); $this->info('PHASE 1: USER OVERVIEW'); $this->info('═══════════════════════════════════════'); $this->newLine(); $teams = $this->user->teams()->get(); $ownedTeams = $teams->filter(fn ($team) => $team->pivot->role === 'owner'); $memberTeams = $teams->filter(fn ($team) => $team->pivot->role !== 'owner'); // Collect servers and resources ONLY from teams that will be FULLY DELETED // This means: user is owner AND is the ONLY member // // Resources from these teams will NOT be deleted: // - Teams where user is just a member // - Teams where user is owner but has other members (will be transferred/user removed) $allServers = collect(); $allApplications = collect(); $allDatabases = collect(); $allServices = collect(); $activeSubscriptions = collect(); foreach ($teams as $team) { $userRole = $team->pivot->role; $memberCount = $team->members->count(); // Only show resources from teams where user is the ONLY member // These are the teams that will be fully deleted if ($userRole !== 'owner' || $memberCount > 1) { continue; } $servers = $team->servers()->get(); $allServers = $allServers->merge($servers); foreach ($servers as $server) { $resources = $server->definedResources(); foreach ($resources as $resource) { if ($resource instanceof \App\Models\Application) { $allApplications->push($resource); } elseif ($resource instanceof \App\Models\Service) { $allServices->push($resource); } else { $allDatabases->push($resource); } } } // Only collect subscriptions on cloud instances if (isCloud() && $team->subscription && $team->subscription->stripe_subscription_id) { $activeSubscriptions->push($team->subscription); } } // Build table data $tableData = [ ['User', $this->user->email], ['User ID', $this->user->id], ['Created', $this->user->created_at->format('Y-m-d H:i:s')], ['Last Login', $this->user->updated_at->format('Y-m-d H:i:s')], ['Teams (Total)', $teams->count()], ['Teams (Owner)', $ownedTeams->count()], ['Teams (Member)', $memberTeams->count()], ['Servers', $allServers->unique('id')->count()], ['Applications', $allApplications->count()], ['Databases', $allDatabases->count()], ['Services', $allServices->count()], ]; // Only show Stripe subscriptions on cloud instances if (isCloud()) { $tableData[] = ['Active Stripe Subscriptions', $activeSubscriptions->count()]; } $this->table(['Property', 'Value'], $tableData); $this->newLine(); $this->warn('⚠️ WARNING: This will permanently delete the user and all associated data!'); $this->newLine(); if (! $this->confirm('Do you want to continue with the deletion process?', false)) { return false; } return true; } private function deleteResources(): bool { $this->newLine(); $this->info('═══════════════════════════════════════'); $this->info('PHASE 2: DELETE RESOURCES'); $this->info('═══════════════════════════════════════'); $this->newLine(); $action = new DeleteUserResources($this->user, $this->isDryRun); $resources = $action->getResourcesPreview(); if ($resources['applications']->isEmpty() && $resources['databases']->isEmpty() && $resources['services']->isEmpty()) { $this->info('No resources to delete.'); return true; } $this->info('Resources to be deleted:'); $this->newLine(); if ($resources['applications']->isNotEmpty()) { $this->warn("Applications to be deleted ({$resources['applications']->count()}):"); $this->table( ['Name', 'UUID', 'Server', 'Status'], $resources['applications']->map(function ($app) { return [ $app->name, $app->uuid, $app->destination->server->name, $app->status ?? 'unknown', ]; })->toArray() ); $this->newLine(); } if ($resources['databases']->isNotEmpty()) { $this->warn("Databases to be deleted ({$resources['databases']->count()}):"); $this->table( ['Name', 'Type', 'UUID', 'Server'], $resources['databases']->map(function ($db) { return [ $db->name, class_basename($db), $db->uuid, $db->destination->server->name, ]; })->toArray() ); $this->newLine(); } if ($resources['services']->isNotEmpty()) { $this->warn("Services to be deleted ({$resources['services']->count()}):"); $this->table( ['Name', 'UUID', 'Server'], $resources['services']->map(function ($service) { return [ $service->name, $service->uuid, $service->server->name, ]; })->toArray() ); $this->newLine(); } $this->error('⚠️ THIS ACTION CANNOT BE UNDONE!'); if (! $this->confirm('Are you sure you want to delete all these resources?', false)) { return false; } if (! $this->isDryRun) { $this->info('Deleting resources...'); try { $result = $action->execute(); $this->info("✓ Deleted: {$result['applications']} applications, {$result['databases']} databases, {$result['services']} services"); $this->logAction("Deleted resources for user {$this->user->email}: {$result['applications']} apps, {$result['databases']} databases, {$result['services']} services"); } catch (\Exception $e) { $this->error('Failed to delete resources:'); $this->error('Exception: '.get_class($e)); $this->error('Message: '.$e->getMessage()); $this->error('File: '.$e->getFile().':'.$e->getLine()); if ($this->output->isVerbose()) { $this->error('Stack Trace:'); $this->error($e->getTraceAsString()); } throw $e; // Re-throw to trigger rollback } } return true; } private function deleteServers(): bool { $this->newLine(); $this->info('═══════════════════════════════════════'); $this->info('PHASE 3: DELETE SERVERS'); $this->info('═══════════════════════════════════════'); $this->newLine(); $action = new DeleteUserServers($this->user, $this->isDryRun); $servers = $action->getServersPreview(); if ($servers->isEmpty()) { $this->info('No servers to delete.'); return true; } $this->warn("Servers to be deleted ({$servers->count()}):"); $this->table( ['ID', 'Name', 'IP', 'Description', 'Resources Count'], $servers->map(function ($server) { $resourceCount = $server->definedResources()->count(); return [ $server->id, $server->name, $server->ip, $server->description ?? '-', $resourceCount, ]; })->toArray() ); $this->newLine(); $this->error('⚠️ WARNING: Deleting servers will remove all server configurations!'); if (! $this->confirm('Are you sure you want to delete all these servers?', false)) { return false; } if (! $this->isDryRun) { $this->info('Deleting servers...'); try { $result = $action->execute(); $this->info("✓ Deleted {$result['servers']} servers"); $this->logAction("Deleted {$result['servers']} servers for user {$this->user->email}"); } catch (\Exception $e) { $this->error('Failed to delete servers:'); $this->error('Exception: '.get_class($e)); $this->error('Message: '.$e->getMessage()); $this->error('File: '.$e->getFile().':'.$e->getLine()); if ($this->output->isVerbose()) { $this->error('Stack Trace:'); $this->error($e->getTraceAsString()); } throw $e; // Re-throw to trigger rollback } } return true; } private function handleTeams(): bool { $this->newLine(); $this->info('═══════════════════════════════════════'); $this->info('PHASE 4: HANDLE TEAMS'); $this->info('═══════════════════════════════════════'); $this->newLine(); $action = new DeleteUserTeams($this->user, $this->isDryRun); $preview = $action->getTeamsPreview(); // Check for edge cases first - EXIT IMMEDIATELY if found if ($preview['edge_cases']->isNotEmpty()) { $this->error('═══════════════════════════════════════'); $this->error('⚠️ EDGE CASES DETECTED - CANNOT PROCEED'); $this->error('═══════════════════════════════════════'); $this->newLine(); foreach ($preview['edge_cases'] as $edgeCase) { $team = $edgeCase['team']; $reason = $edgeCase['reason']; $this->error("Team: {$team->name} (ID: {$team->id})"); $this->error("Issue: {$reason}"); // Show team members for context $this->info('Current members:'); foreach ($team->members as $member) { $role = $member->pivot->role; $this->line(" - {$member->name} ({$member->email}) - Role: {$role}"); } // Check for active resources $resourceCount = 0; foreach ($team->servers()->get() as $server) { $resources = $server->definedResources(); $resourceCount += $resources->count(); } if ($resourceCount > 0) { $this->warn(" ⚠️ This team has {$resourceCount} active resources!"); } // Show subscription details if relevant if ($team->subscription && $team->subscription->stripe_subscription_id) { $this->warn(' ⚠️ Active Stripe subscription details:'); $this->warn(" Subscription ID: {$team->subscription->stripe_subscription_id}"); $this->warn(" Customer ID: {$team->subscription->stripe_customer_id}"); // Show other owners who could potentially take over $otherOwners = $team->members ->where('id', '!=', $this->user->id) ->filter(function ($member) { return $member->pivot->role === 'owner'; }); if ($otherOwners->isNotEmpty()) { $this->info(' Other owners who could take over billing:'); foreach ($otherOwners as $owner) { $this->line(" - {$owner->name} ({$owner->email})"); } } } $this->newLine(); } $this->error('Please resolve these issues manually before retrying:'); // Check if any edge case involves subscription payment issues $hasSubscriptionIssue = $preview['edge_cases']->contains(function ($edgeCase) { return str_contains($edgeCase['reason'], 'Stripe subscription'); }); if ($hasSubscriptionIssue) { $this->info('For teams with subscription payment issues:'); $this->info('1. Cancel the subscription through Stripe dashboard, OR'); $this->info('2. Transfer the subscription to another owner\'s payment method, OR'); $this->info('3. Have the other owner create a new subscription after cancelling this one'); $this->newLine(); } $hasNoOwnerReplacement = $preview['edge_cases']->contains(function ($edgeCase) { return str_contains($edgeCase['reason'], 'No suitable owner replacement'); }); if ($hasNoOwnerReplacement) { $this->info('For teams with no suitable owner replacement:'); $this->info('1. Assign an admin role to a trusted member, OR'); $this->info('2. Transfer team resources to another team, OR'); $this->info('3. Delete the team manually if no longer needed'); $this->newLine(); } $this->error('USER DELETION ABORTED DUE TO EDGE CASES'); $this->logAction("User deletion aborted for {$this->user->email}: Edge cases in team handling"); // Return false to trigger proper cleanup and lock release return false; } if ($preview['to_delete']->isEmpty() && $preview['to_transfer']->isEmpty() && $preview['to_leave']->isEmpty()) { $this->info('No team changes needed.'); return true; } if ($preview['to_delete']->isNotEmpty()) { $this->warn('Teams to be DELETED (user is the only member):'); $this->table( ['ID', 'Name', 'Resources', 'Subscription'], $preview['to_delete']->map(function ($team) { $resourceCount = 0; foreach ($team->servers()->get() as $server) { $resourceCount += $server->definedResources()->count(); } $hasSubscription = $team->subscription && $team->subscription->stripe_subscription_id ? '⚠️ YES - '.$team->subscription->stripe_subscription_id : 'No'; return [ $team->id, $team->name, $resourceCount, $hasSubscription, ]; })->toArray() ); $this->newLine(); } if ($preview['to_transfer']->isNotEmpty()) { $this->warn('Teams where ownership will be TRANSFERRED:'); $this->table( ['Team ID', 'Team Name', 'New Owner', 'New Owner Email'], $preview['to_transfer']->map(function ($item) { return [ $item['team']->id, $item['team']->name, $item['new_owner']->name, $item['new_owner']->email, ]; })->toArray() ); $this->newLine(); } if ($preview['to_leave']->isNotEmpty()) { $this->warn('Teams where user will be REMOVED (other owners/admins exist):'); $userId = $this->user->id; $this->table( ['ID', 'Name', 'User Role', 'Other Members'], $preview['to_leave']->map(function ($team) use ($userId) { $userRole = $team->members->where('id', $userId)->first()->pivot->role; $otherMembers = $team->members->count() - 1; return [ $team->id, $team->name, $userRole, $otherMembers, ]; })->toArray() ); $this->newLine(); } $this->error('⚠️ WARNING: Team changes affect access control and ownership!'); if (! $this->confirm('Are you sure you want to proceed with these team changes?', false)) { return false; } if (! $this->isDryRun) { $this->info('Processing team changes...'); try { $result = $action->execute(); $this->info("✓ Teams deleted: {$result['deleted']}, ownership transferred: {$result['transferred']}, left: {$result['left']}"); $this->logAction("Team changes for user {$this->user->email}: deleted {$result['deleted']}, transferred {$result['transferred']}, left {$result['left']}"); } catch (\Exception $e) { $this->error('Failed to process team changes:'); $this->error('Exception: '.get_class($e)); $this->error('Message: '.$e->getMessage()); $this->error('File: '.$e->getFile().':'.$e->getLine()); if ($this->output->isVerbose()) { $this->error('Stack Trace:'); $this->error($e->getTraceAsString()); } throw $e; // Re-throw to trigger rollback } } return true; } private function cancelStripeSubscriptions(): bool { $this->newLine(); $this->info('═══════════════════════════════════════'); $this->info('PHASE 6: CANCEL STRIPE SUBSCRIPTIONS'); $this->info('═══════════════════════════════════════'); $this->newLine(); $action = new CancelSubscription($this->user, $this->isDryRun); $subscriptions = $action->getSubscriptionsPreview(); if ($subscriptions->isEmpty()) { $this->info('No Stripe subscriptions to cancel.'); return true; } // Verify subscriptions in Stripe before showing details $this->info('Verifying subscriptions in Stripe...'); $verification = $action->verifySubscriptionsInStripe(); if (! empty($verification['errors'])) { $this->warn('⚠️ Errors occurred during verification:'); foreach ($verification['errors'] as $error) { $this->warn(" - {$error}"); } $this->newLine(); } if ($verification['not_found']->isNotEmpty()) { $this->warn('⚠️ Subscriptions not found or inactive in Stripe:'); foreach ($verification['not_found'] as $item) { $subscription = $item['subscription']; $reason = $item['reason']; $this->line(" - {$subscription->stripe_subscription_id} (Team: {$subscription->team->name}) - {$reason}"); } $this->newLine(); } if ($verification['verified']->isEmpty()) { $this->info('No active subscriptions found in Stripe to cancel.'); return true; } $this->info('Active Stripe subscriptions to cancel:'); $this->newLine(); $totalMonthlyValue = 0; foreach ($verification['verified'] as $item) { $subscription = $item['subscription']; $stripeStatus = $item['stripe_status']; $team = $subscription->team; $planId = $subscription->stripe_plan_id; // Try to get the price from config $monthlyValue = $this->getSubscriptionMonthlyValue($planId); $totalMonthlyValue += $monthlyValue; $this->line(" - {$subscription->stripe_subscription_id} (Team: {$team->name})"); $this->line(" Stripe Status: {$stripeStatus}"); if ($monthlyValue > 0) { $this->line(" Monthly value: \${$monthlyValue}"); } if ($subscription->stripe_cancel_at_period_end) { $this->line(' ⚠️ Already set to cancel at period end'); } } if ($totalMonthlyValue > 0) { $this->newLine(); $this->warn("Total monthly value: \${$totalMonthlyValue}"); } $this->newLine(); $this->error('⚠️ WARNING: Subscriptions will be cancelled IMMEDIATELY (not at period end)!'); $this->warn('⚠️ NOTE: This operation happens AFTER database commit and cannot be rolled back!'); if (! $this->confirm('Are you sure you want to cancel all these subscriptions immediately?', false)) { return false; } if (! $this->isDryRun) { $this->info('Cancelling subscriptions...'); $result = $action->execute(); $this->info("Cancelled {$result['cancelled']} subscriptions, {$result['failed']} failed"); if ($result['failed'] > 0 && ! empty($result['errors'])) { $this->error('Failed subscriptions:'); foreach ($result['errors'] as $error) { $this->error(" - {$error}"); } return false; } $this->logAction("Cancelled {$result['cancelled']} Stripe subscriptions for user {$this->user->email}"); } return true; } private function deleteUserProfile(): bool { $this->newLine(); $this->info('═══════════════════════════════════════'); $this->info('PHASE 5: DELETE USER PROFILE'); $this->info('═══════════════════════════════════════'); $this->newLine(); $this->warn('⚠️ FINAL STEP - This action is IRREVERSIBLE!'); $this->newLine(); $this->info('User profile to be deleted:'); $this->table( ['Property', 'Value'], [ ['Email', $this->user->email], ['Name', $this->user->name], ['User ID', $this->user->id], ['Created', $this->user->created_at->format('Y-m-d H:i:s')], ['Email Verified', $this->user->email_verified_at ? 'Yes' : 'No'], ['2FA Enabled', $this->user->two_factor_confirmed_at ? 'Yes' : 'No'], ] ); $this->newLine(); $this->warn("Type 'DELETE {$this->user->email}' to confirm final deletion:"); $confirmation = $this->ask('Confirmation'); if ($confirmation !== "DELETE {$this->user->email}") { $this->error('Confirmation text does not match. Deletion cancelled.'); return false; } if (! $this->isDryRun) { $this->info('Deleting user profile...'); try { $this->user->delete(); $this->info('✓ User profile deleted successfully.'); $this->logAction("User profile deleted: {$this->user->email}"); } catch (\Exception $e) { $this->error('Failed to delete user profile:'); $this->error('Exception: '.get_class($e)); $this->error('Message: '.$e->getMessage()); $this->error('File: '.$e->getFile().':'.$e->getLine()); if ($this->output->isVerbose()) { $this->error('Stack Trace:'); $this->error($e->getTraceAsString()); } $this->logAction("Failed to delete user profile {$this->user->email}: {$e->getMessage()}"); throw $e; // Re-throw to trigger rollback } } return true; } private function getSubscriptionMonthlyValue(string $planId): int { // Try to get pricing from subscription metadata or config // Since we're using dynamic pricing, return 0 for now // This could be enhanced by fetching the actual price from Stripe API // Check if this is a dynamic pricing plan $dynamicMonthlyPlanId = config('subscription.stripe_price_id_dynamic_monthly'); $dynamicYearlyPlanId = config('subscription.stripe_price_id_dynamic_yearly'); if ($planId === $dynamicMonthlyPlanId || $planId === $dynamicYearlyPlanId) { // For dynamic pricing, we can't determine the exact amount without calling Stripe API // Return 0 to indicate dynamic/usage-based pricing return 0; } // For any other plans, return 0 as we don't have hardcoded prices return 0; } private function logAction(string $message): void { $logMessage = "[CloudDeleteUser] {$message}"; if ($this->isDryRun) { $logMessage = "[DRY RUN] {$logMessage}"; } Log::channel('single')->info($logMessage); // Also log to a dedicated user deletion log file $logFile = storage_path('logs/user-deletions.log'); // Ensure the logs directory exists $logDir = dirname($logFile); if (! is_dir($logDir)) { mkdir($logDir, 0755, true); } $timestamp = now()->format('Y-m-d H:i:s'); file_put_contents($logFile, "[{$timestamp}] {$logMessage}\n", FILE_APPEND | LOCK_EX); } private function displayErrorState(string $failedAt): void { $this->newLine(); $this->error('═══════════════════════════════════════'); $this->error('DELETION STATE AT FAILURE'); $this->error('═══════════════════════════════════════'); $this->error("Failed at: {$failedAt}"); $this->newLine(); $stateTable = []; foreach ($this->deletionState as $phase => $completed) { $phaseLabel = str_replace('_', ' ', ucwords($phase, '_')); $status = $completed ? '✓ Completed' : '✗ Not completed'; $stateTable[] = [$phaseLabel, $status]; } $this->table(['Phase', 'Status'], $stateTable); $this->newLine(); // Show what was rolled back vs what remains if ($this->deletionState['db_committed']) { $this->error('⚠️ DATABASE COMMITTED - Changes CANNOT be rolled back!'); } else { $this->info('✓ Database changes were ROLLED BACK'); } $this->newLine(); $this->error('User email: '.$this->user->email); $this->error('User ID: '.$this->user->id); $this->error('Timestamp: '.now()->format('Y-m-d H:i:s')); $this->newLine(); } private function displayRecoverySteps(): void { $this->error('═══════════════════════════════════════'); $this->error('RECOVERY STEPS'); $this->error('═══════════════════════════════════════'); if (! $this->deletionState['db_committed']) { $this->info('✓ Database was rolled back - no recovery needed for database'); $this->newLine(); if ($this->deletionState['phase_2_resources'] || $this->deletionState['phase_3_servers']) { $this->warn('However, some remote operations may have occurred:'); $this->newLine(); if ($this->deletionState['phase_2_resources']) { $this->warn('Phase 2 (Resources) was attempted:'); $this->warn('- Check remote servers for orphaned Docker containers'); $this->warn('- Use: docker ps -a | grep coolify'); $this->warn('- Manually remove if needed: docker rm -f '); $this->newLine(); } if ($this->deletionState['phase_3_servers']) { $this->warn('Phase 3 (Servers) was attempted:'); $this->warn('- Check for orphaned server configurations'); $this->warn('- Verify SSH access to servers listed for this user'); $this->newLine(); } } } else { $this->error('⚠️ DATABASE WAS COMMITTED - Manual recovery required!'); $this->newLine(); $this->error('The following data has been PERMANENTLY deleted:'); if ($this->deletionState['phase_5_user_profile']) { $this->error('- User profile (email: '.$this->user->email.')'); } if ($this->deletionState['phase_4_teams']) { $this->error('- Team memberships and owned teams'); } if ($this->deletionState['phase_3_servers']) { $this->error('- Server records and configurations'); } if ($this->deletionState['phase_2_resources']) { $this->error('- Applications, databases, and services'); } $this->newLine(); if (! $this->deletionState['phase_6_stripe']) { $this->error('Stripe subscriptions were NOT cancelled:'); $this->error('1. Go to Stripe Dashboard: https://dashboard.stripe.com/'); $this->error('2. Search for: '.$this->user->email); $this->error('3. Cancel all active subscriptions manually'); $this->newLine(); } } $this->error('Log file: storage/logs/user-deletions.log'); $this->error('Check logs for detailed error information'); $this->newLine(); } /** * Register signal handlers for graceful shutdown on Ctrl+C (SIGINT) and SIGTERM */ private function registerSignalHandlers(): void { if (! function_exists('pcntl_signal')) { // pcntl extension not available, skip signal handling return; } // Handle Ctrl+C (SIGINT) pcntl_signal(SIGINT, function () { $this->newLine(); $this->warn('═══════════════════════════════════════'); $this->warn('⚠️ PROCESS INTERRUPTED (Ctrl+C)'); $this->warn('═══════════════════════════════════════'); $this->info('Cleaning up and releasing lock...'); $this->releaseLock(); $this->info('Lock released. Exiting gracefully.'); exit(130); // Standard exit code for SIGINT }); // Handle SIGTERM pcntl_signal(SIGTERM, function () { $this->newLine(); $this->warn('═══════════════════════════════════════'); $this->warn('⚠️ PROCESS TERMINATED (SIGTERM)'); $this->warn('═══════════════════════════════════════'); $this->info('Cleaning up and releasing lock...'); $this->releaseLock(); $this->info('Lock released. Exiting gracefully.'); exit(143); // Standard exit code for SIGTERM }); // Enable async signal handling pcntl_async_signals(true); } /** * Release the lock if it exists */ private function releaseLock(): void { if ($this->lock) { try { $this->lock->release(); } catch (\Exception $e) { // Silently ignore lock release errors // Lock will expire after 10 minutes anyway } } } } ================================================ FILE: app/Console/Commands/CheckApplicationDeploymentQueue.php ================================================ option('seconds'); $deployments = ApplicationDeploymentQueue::whereIn('status', [ ApplicationDeploymentStatus::IN_PROGRESS, ApplicationDeploymentStatus::QUEUED, ])->where('created_at', '<=', now()->subSeconds($seconds))->get(); if ($deployments->isEmpty()) { $this->info('No deployments found in the last '.$seconds.' seconds.'); return; } $this->info('Found '.$deployments->count().' deployments created in the last '.$seconds.' seconds.'); foreach ($deployments as $deployment) { if ($this->option('force')) { $this->info('Deployment '.$deployment->id.' created at '.$deployment->created_at.' is older than '.$seconds.' seconds. Setting status to failed.'); $this->cancelDeployment($deployment); } else { $this->info('Deployment '.$deployment->id.' created at '.$deployment->created_at.' is older than '.$seconds.' seconds. Setting status to failed.'); if ($this->confirm('Do you want to cancel this deployment?', true)) { $this->cancelDeployment($deployment); } } } } private function cancelDeployment(ApplicationDeploymentQueue $deployment) { $deployment->update(['status' => ApplicationDeploymentStatus::FAILED]); if ($deployment->server?->isFunctional()) { remote_process(['docker rm -f '.$deployment->deployment_uuid], $deployment->server, false); } } } ================================================ FILE: app/Console/Commands/CheckTraefikVersionCommand.php ================================================ info('Checking Traefik versions on all servers...'); try { CheckTraefikVersionJob::dispatch(); $this->info('Traefik version check job dispatched successfully.'); $this->info('Notifications will be sent to teams with outdated Traefik versions.'); return Command::SUCCESS; } catch (\Exception $e) { $this->error('Failed to dispatch Traefik version check job: '.$e->getMessage()); return Command::FAILURE; } } } ================================================ FILE: app/Console/Commands/CleanupApplicationDeploymentQueue.php ================================================ option('team-id'); $servers = \App\Models\Server::where('team_id', $team_id)->get(); foreach ($servers as $server) { $deployments = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->where('server_id', $server->id)->get(); foreach ($deployments as $deployment) { $deployment->update(['status' => 'failed']); instant_remote_process(['docker rm -f '.$deployment->deployment_uuid], $server, false); } } } } ================================================ FILE: app/Console/Commands/CleanupDatabase.php ================================================ option('yes')) { echo "Running database cleanup...\n"; } else { echo "Running database cleanup in dry-run mode...\n"; } if (isCloud()) { // Later on we can increase this to 180 days or dynamically set $keep_days = $this->option('keep-days') ?? 60; } else { $keep_days = $this->option('keep-days') ?? 60; } echo "Keep days: $keep_days\n"; // Cleanup failed jobs table $failed_jobs = DB::table('failed_jobs')->where('failed_at', '<', now()->subDays(1)); $count = $failed_jobs->count(); echo "Delete $count entries from failed_jobs.\n"; if ($this->option('yes')) { $failed_jobs->delete(); } // Cleanup sessions table $sessions = DB::table('sessions')->where('last_activity', '<', now()->subDays($keep_days)->timestamp); $count = $sessions->count(); echo "Delete $count entries from sessions.\n"; if ($this->option('yes')) { $sessions->delete(); } // Cleanup activity_log table $activity_log = DB::table('activity_log')->where('created_at', '<', now()->subDays($keep_days))->orderBy('created_at', 'desc')->skip(10); $count = $activity_log->count(); echo "Delete $count entries from activity_log.\n"; if ($this->option('yes')) { $activity_log->delete(); } // Cleanup application_deployment_queues table $application_deployment_queues = DB::table('application_deployment_queues')->where('created_at', '<', now()->subDays($keep_days))->orderBy('created_at', 'desc')->skip(10); $count = $application_deployment_queues->count(); echo "Delete $count entries from application_deployment_queues.\n"; if ($this->option('yes')) { $application_deployment_queues->delete(); } // Cleanup scheduled_task_executions table $scheduled_task_executions = DB::table('scheduled_task_executions')->where('created_at', '<', now()->subDays($keep_days))->orderBy('created_at', 'desc'); $count = $scheduled_task_executions->count(); echo "Delete $count entries from scheduled_task_executions.\n"; if ($this->option('yes')) { $scheduled_task_executions->delete(); } } } ================================================ FILE: app/Console/Commands/CleanupNames.php ================================================ Project::class, 'Environment' => Environment::class, 'Application' => Application::class, 'Service' => Service::class, 'Server' => Server::class, 'Team' => Team::class, 'StandalonePostgresql' => StandalonePostgresql::class, 'StandaloneMysql' => StandaloneMysql::class, 'StandaloneRedis' => StandaloneRedis::class, 'StandaloneMongodb' => StandaloneMongodb::class, 'StandaloneMariadb' => StandaloneMariadb::class, 'StandaloneKeydb' => StandaloneKeydb::class, 'StandaloneDragonfly' => StandaloneDragonfly::class, 'StandaloneClickhouse' => StandaloneClickhouse::class, 'S3Storage' => S3Storage::class, 'Tag' => Tag::class, 'PrivateKey' => PrivateKey::class, 'ScheduledTask' => ScheduledTask::class, ]; protected array $changes = []; protected int $totalProcessed = 0; protected int $totalCleaned = 0; public function handle(): int { if ($this->option('backup') && ! $this->option('dry-run')) { $this->createBackup(); } $modelFilter = $this->option('model'); $modelsToProcess = $modelFilter ? [$modelFilter => $this->modelsToClean[$modelFilter] ?? null] : $this->modelsToClean; if ($modelFilter && ! isset($this->modelsToClean[$modelFilter])) { $this->error("Unknown model: {$modelFilter}"); $this->info('Available models: '.implode(', ', array_keys($this->modelsToClean))); return self::FAILURE; } foreach ($modelsToProcess as $modelName => $modelClass) { if (! $modelClass) { continue; } $this->processModel($modelName, $modelClass); } if (! $this->option('dry-run') && $this->totalCleaned > 0) { $this->logChanges(); } if ($this->option('dry-run')) { $this->info("Name cleanup: would sanitize {$this->totalCleaned} records"); } else { $this->info("Name cleanup: sanitized {$this->totalCleaned} records"); } return self::SUCCESS; } protected function processModel(string $modelName, string $modelClass): void { try { $records = $modelClass::all(['id', 'name']); $cleaned = 0; foreach ($records as $record) { $this->totalProcessed++; $originalName = $record->name; $sanitizedName = $this->sanitizeName($originalName); if ($sanitizedName !== $originalName) { $this->changes[] = [ 'model' => $modelName, 'id' => $record->id, 'original' => $originalName, 'sanitized' => $sanitizedName, 'timestamp' => now(), ]; if (! $this->option('dry-run')) { // Update without triggering events/mutators to avoid conflicts $modelClass::where('id', $record->id)->update(['name' => $sanitizedName]); } $cleaned++; $this->totalCleaned++; // Only log in dry-run mode to preview changes if ($this->option('dry-run')) { $this->warn(" 🧹 {$modelName} #{$record->id}:"); $this->line(' From: '.$this->truncate($originalName, 80)); $this->line(' To: '.$this->truncate($sanitizedName, 80)); } } } } catch (\Exception $e) { $this->error("Error processing {$modelName}: ".$e->getMessage()); } } protected function sanitizeName(string $name): string { // Remove all characters that don't match the allowed pattern // Use the shared ValidationPatterns to ensure consistency $allowedPattern = str_replace(['/', '^', '$'], '', ValidationPatterns::NAME_PATTERN); $sanitized = preg_replace('/[^'.$allowedPattern.']+/', '', $name); // Clean up excessive whitespace but preserve other allowed characters $sanitized = preg_replace('/\s+/', ' ', $sanitized); $sanitized = trim($sanitized); // If result is empty, provide a default name if (empty($sanitized)) { $sanitized = 'sanitized-item'; } return $sanitized; } protected function logChanges(): void { $logFile = storage_path('logs/name-cleanup.log'); $logData = [ 'timestamp' => now()->toISOString(), 'total_processed' => $this->totalProcessed, 'total_cleaned' => $this->totalCleaned, 'changes' => $this->changes, ]; file_put_contents($logFile, json_encode($logData, JSON_PRETTY_PRINT)."\n", FILE_APPEND); Log::info('Name Sanitization completed', [ 'total_processed' => $this->totalProcessed, 'total_sanitized' => $this->totalCleaned, 'changes_count' => count($this->changes), ]); } protected function createBackup(): void { try { $backupFile = storage_path('backups/name-cleanup-backup-'.now()->format('Y-m-d-H-i-s').'.sql'); // Ensure backup directory exists if (! file_exists(dirname($backupFile))) { mkdir(dirname($backupFile), 0755, true); } $dbConfig = config('database.connections.'.config('database.default')); $command = sprintf( 'pg_dump -h %s -p %s -U %s -d %s > %s', $dbConfig['host'], $dbConfig['port'], $dbConfig['username'], $dbConfig['database'], $backupFile ); exec($command, $output, $returnCode); } catch (\Exception $e) { // Log failure but continue - backup is optional safeguard Log::warning('Name cleanup backup failed', ['error' => $e->getMessage()]); } } protected function truncate(string $text, int $length): string { return strlen($text) > $length ? substr($text, 0, $length).'...' : $text; } } ================================================ FILE: app/Console/Commands/CleanupRedis.php ================================================ option('dry-run'); $skipOverlapping = $this->option('skip-overlapping'); $deletedCount = 0; $totalKeys = 0; // Get all keys with the horizon prefix $keys = $redis->keys('*'); $totalKeys = count($keys); foreach ($keys as $key) { $keyWithoutPrefix = str_replace($prefix, '', $key); $type = $redis->command('type', [$keyWithoutPrefix]); // Handle hash-type keys (individual jobs) if ($type === 5) { if ($this->shouldDeleteHashKey($redis, $keyWithoutPrefix, $dryRun)) { $deletedCount++; } } // Handle other key types (metrics, lists, etc.) else { if ($this->shouldDeleteOtherKey($redis, $keyWithoutPrefix, $key, $dryRun)) { $deletedCount++; } } } // Clean up overlapping queues if not skipped if (! $skipOverlapping) { $overlappingCleaned = $this->cleanupOverlappingQueues($redis, $prefix, $dryRun); $deletedCount += $overlappingCleaned; } // Clean up stale cache locks (WithoutOverlapping middleware) if ($this->option('clear-locks')) { $locksCleaned = $this->cleanupCacheLocks($dryRun); $deletedCount += $locksCleaned; } // Clean up stuck jobs (restart mode = aggressive, runtime mode = conservative) $isRestart = $this->option('restart'); if ($isRestart || $this->option('clear-locks')) { $jobsCleaned = $this->cleanupStuckJobs($redis, $prefix, $dryRun, $isRestart); $deletedCount += $jobsCleaned; } if ($dryRun) { $this->info("Redis cleanup: would delete {$deletedCount} items"); } else { $this->info("Redis cleanup: deleted {$deletedCount} items"); } } private function shouldDeleteHashKey($redis, $keyWithoutPrefix, $dryRun) { $data = $redis->command('hgetall', [$keyWithoutPrefix]); $status = data_get($data, 'status'); // Delete completed and failed jobs if (in_array($status, ['completed', 'failed'])) { if (! $dryRun) { $redis->command('del', [$keyWithoutPrefix]); } return true; } return false; } private function shouldDeleteOtherKey($redis, $keyWithoutPrefix, $fullKey, $dryRun) { // Clean up various Horizon data structures $patterns = [ 'recent_jobs' => 'Recent jobs list', 'failed_jobs' => 'Failed jobs list', 'completed_jobs' => 'Completed jobs list', 'job_classes' => 'Job classes metrics', 'queues' => 'Queue metrics', 'processes' => 'Process metrics', 'supervisors' => 'Supervisor data', 'metrics' => 'General metrics', 'workload' => 'Workload data', ]; foreach ($patterns as $pattern => $description) { if (str_contains($keyWithoutPrefix, $pattern)) { if (! $dryRun) { $redis->command('del', [$keyWithoutPrefix]); } return true; } } // Clean up old timestamped data (older than 7 days) if (preg_match('/(\d{10})/', $keyWithoutPrefix, $matches)) { $timestamp = (int) $matches[1]; $weekAgo = now()->subDays(7)->timestamp; if ($timestamp < $weekAgo) { if (! $dryRun) { $redis->command('del', [$keyWithoutPrefix]); } return true; } } return false; } private function cleanupOverlappingQueues($redis, $prefix, $dryRun) { $cleanedCount = 0; $queueKeys = []; // Find all queue-related keys $allKeys = $redis->keys('*'); foreach ($allKeys as $key) { $keyWithoutPrefix = str_replace($prefix, '', $key); if (str_contains($keyWithoutPrefix, 'queue:') || preg_match('/queues?[:\-]/', $keyWithoutPrefix)) { $queueKeys[] = $keyWithoutPrefix; } } // Group queues by name pattern to find duplicates $queueGroups = []; foreach ($queueKeys as $queueKey) { // Extract queue name (remove timestamps, suffixes) $baseName = preg_replace('/[:\-]\d+$/', '', $queueKey); $baseName = preg_replace('/[:\-](pending|reserved|delayed|processing)$/', '', $baseName); if (! isset($queueGroups[$baseName])) { $queueGroups[$baseName] = []; } $queueGroups[$baseName][] = $queueKey; } // Process each group for overlaps foreach ($queueGroups as $baseName => $keys) { if (count($keys) > 1) { $cleanedCount += $this->deduplicateQueueGroup($redis, $baseName, $keys, $dryRun); } // Also check for duplicate jobs within individual queues foreach ($keys as $queueKey) { $cleanedCount += $this->deduplicateQueueContents($redis, $queueKey, $dryRun); } } return $cleanedCount; } private function deduplicateQueueGroup($redis, $baseName, $keys, $dryRun) { $cleanedCount = 0; // Sort keys to keep the most recent one usort($keys, function ($a, $b) { // Prefer keys without timestamps (they're usually the main queue) $aHasTimestamp = preg_match('/\d{10}/', $a); $bHasTimestamp = preg_match('/\d{10}/', $b); if ($aHasTimestamp && ! $bHasTimestamp) { return 1; } if (! $aHasTimestamp && $bHasTimestamp) { return -1; } // If both have timestamps, prefer the newer one if ($aHasTimestamp && $bHasTimestamp) { preg_match('/(\d{10})/', $a, $aMatches); preg_match('/(\d{10})/', $b, $bMatches); return ($bMatches[1] ?? 0) <=> ($aMatches[1] ?? 0); } return strcmp($a, $b); }); // Keep the first (preferred) key, remove others that are empty or redundant $keepKey = array_shift($keys); foreach ($keys as $redundantKey) { $type = $redis->command('type', [$redundantKey]); $shouldDelete = false; if ($type === 1) { // LIST type $length = $redis->command('llen', [$redundantKey]); if ($length == 0) { $shouldDelete = true; } } elseif ($type === 3) { // SET type $count = $redis->command('scard', [$redundantKey]); if ($count == 0) { $shouldDelete = true; } } elseif ($type === 4) { // ZSET type $count = $redis->command('zcard', [$redundantKey]); if ($count == 0) { $shouldDelete = true; } } if ($shouldDelete) { if (! $dryRun) { $redis->command('del', [$redundantKey]); } $cleanedCount++; } } return $cleanedCount; } private function deduplicateQueueContents($redis, $queueKey, $dryRun) { $cleanedCount = 0; $type = $redis->command('type', [$queueKey]); if ($type === 1) { // LIST type - common for job queues $length = $redis->command('llen', [$queueKey]); if ($length > 1) { $items = $redis->command('lrange', [$queueKey, 0, -1]); $uniqueItems = array_unique($items); if (count($uniqueItems) < count($items)) { $duplicates = count($items) - count($uniqueItems); if (! $dryRun) { // Rebuild the list with unique items $redis->command('del', [$queueKey]); foreach (array_reverse($uniqueItems) as $item) { $redis->command('lpush', [$queueKey, $item]); } } $cleanedCount += $duplicates; } } } return $cleanedCount; } private function cleanupCacheLocks(bool $dryRun): int { $cleanedCount = 0; // Use the default Redis connection (database 0) where cache locks are stored $redis = Redis::connection('default'); // Get all keys matching WithoutOverlapping lock pattern $allKeys = $redis->keys('*'); $lockKeys = []; foreach ($allKeys as $key) { // Match cache lock keys: they contain 'laravel-queue-overlap' if (preg_match('/overlap/i', $key)) { $lockKeys[] = $key; } } if (empty($lockKeys)) { return 0; } foreach ($lockKeys as $lockKey) { // Check TTL to identify stale locks $ttl = $redis->ttl($lockKey); // TTL = -1 means no expiration (stale lock!) // TTL = -2 means key doesn't exist // TTL > 0 means lock is valid and will expire if ($ttl === -1) { if ($dryRun) { $this->warn(" Would delete STALE lock (no expiration): {$lockKey}"); } else { $redis->del($lockKey); } $cleanedCount++; } } return $cleanedCount; } /** * Clean up stuck jobs based on mode (restart vs runtime). * * @param mixed $redis Redis connection * @param string $prefix Horizon prefix * @param bool $dryRun Dry run mode * @param bool $isRestart Restart mode (aggressive) vs runtime mode (conservative) * @return int Number of jobs cleaned */ private function cleanupStuckJobs($redis, string $prefix, bool $dryRun, bool $isRestart): int { $cleanedCount = 0; $now = time(); // Get all keys with the horizon prefix $cursor = 0; $keys = []; do { $result = $redis->scan($cursor, ['match' => '*', 'count' => 100]); // Guard against scan() returning false if ($result === false) { $this->error('Redis scan failed, stopping key retrieval'); break; } $cursor = $result[0]; $keys = array_merge($keys, $result[1]); } while ($cursor !== 0); foreach ($keys as $key) { $keyWithoutPrefix = str_replace($prefix, '', $key); $type = $redis->command('type', [$keyWithoutPrefix]); // Only process hash-type keys (individual jobs) if ($type !== 5) { continue; } $data = $redis->command('hgetall', [$keyWithoutPrefix]); $status = data_get($data, 'status'); $payload = data_get($data, 'payload'); // Only process jobs in "processing" or "reserved" state if (! in_array($status, ['processing', 'reserved'])) { continue; } // Parse job payload to get job class and started time $payloadData = json_decode($payload, true); // Check for JSON decode errors if ($payloadData === null || json_last_error() !== JSON_ERROR_NONE) { $errorMsg = json_last_error_msg(); $truncatedPayload = is_string($payload) ? substr($payload, 0, 200) : 'non-string payload'; $this->error("Failed to decode job payload for {$keyWithoutPrefix}: {$errorMsg}. Payload: {$truncatedPayload}"); continue; } $jobClass = data_get($payloadData, 'displayName', 'Unknown'); // Prefer reserved_at (when job started processing), fallback to created_at $reservedAt = (int) data_get($data, 'reserved_at', 0); $createdAt = (int) data_get($data, 'created_at', 0); $startTime = $reservedAt ?: $createdAt; // If we can't determine when the job started, skip it if (! $startTime) { continue; } // Calculate how long the job has been processing $processingTime = $now - $startTime; $shouldFail = false; $reason = ''; if ($isRestart) { // RESTART MODE: Mark ALL processing/reserved jobs as failed // Safe because all workers are dead on restart $shouldFail = true; $reason = 'System restart - all workers terminated'; } else { // RUNTIME MODE: Only mark truly stuck jobs as failed // Be conservative to avoid killing legitimate long-running jobs // Skip ApplicationDeploymentJob entirely (has dynamic_timeout, can run 2+ hours) if (str_contains($jobClass, 'ApplicationDeploymentJob')) { continue; } // Skip DatabaseBackupJob (large backups can take hours) if (str_contains($jobClass, 'DatabaseBackupJob')) { continue; } // For other jobs, only fail if processing > 12 hours if ($processingTime > 43200) { // 12 hours $shouldFail = true; $reason = 'Processing for more than 12 hours'; } } if ($shouldFail) { if ($dryRun) { $this->warn(" Would mark as FAILED: {$jobClass} (processing for ".round($processingTime / 60, 1)." min) - {$reason}"); } else { // Mark job as failed $redis->command('hset', [$keyWithoutPrefix, 'status', 'failed']); $redis->command('hset', [$keyWithoutPrefix, 'failed_at', $now]); $redis->command('hset', [$keyWithoutPrefix, 'exception', "Job cleaned up by cleanup:redis - {$reason}"]); } $cleanedCount++; } } return $cleanedCount; } } ================================================ FILE: app/Console/Commands/CleanupStuckedResources.php ================================================ cleanup_stucked_resources(); } private function cleanup_stucked_resources() { try { $teams = Team::all()->filter(function ($team) { return $team->members()->count() === 0 && $team->servers()->count() === 0; }); foreach ($teams as $team) { $team->delete(); } $servers = Server::all()->filter(function ($server) { return $server->isFunctional(); }); if (isCloud()) { $servers = $servers->filter(function ($server) { return data_get($server->team->subscription, 'stripe_invoice_paid', false) === true; }); } foreach ($servers as $server) { CleanupHelperContainersJob::dispatch($server); } } catch (\Throwable $e) { echo "Error in cleaning stucked resources: {$e->getMessage()}\n"; } try { $servers = Server::onlyTrashed()->get(); foreach ($servers as $server) { echo "Force deleting stuck server: {$server->name}\n"; $server->forceDelete(); } } catch (\Throwable $e) { echo "Error in cleaning stuck servers: {$e->getMessage()}\n"; } try { $applicationsDeploymentQueue = ApplicationDeploymentQueue::get(); foreach ($applicationsDeploymentQueue as $applicationDeploymentQueue) { if (is_null($applicationDeploymentQueue->application)) { echo "Deleting stuck application deployment queue: {$applicationDeploymentQueue->id}\n"; $applicationDeploymentQueue->delete(); } } } catch (\Throwable $e) { echo "Error in cleaning stuck application deployment queue: {$e->getMessage()}\n"; } try { $applications = Application::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($applications as $application) { echo "Deleting stuck application: {$application->name}\n"; DeleteResourceJob::dispatch($application); } } catch (\Throwable $e) { echo "Error in cleaning stuck application: {$e->getMessage()}\n"; } try { $applicationsPreviews = ApplicationPreview::get(); foreach ($applicationsPreviews as $applicationPreview) { if (! data_get($applicationPreview, 'application')) { echo "Deleting stuck application preview: {$applicationPreview->uuid}\n"; DeleteResourceJob::dispatch($applicationPreview); } } } catch (\Throwable $e) { echo "Error in cleaning stuck application: {$e->getMessage()}\n"; } try { $applicationsPreviews = ApplicationPreview::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($applicationsPreviews as $applicationPreview) { echo "Deleting stuck application preview: {$applicationPreview->fqdn}\n"; DeleteResourceJob::dispatch($applicationPreview); } } catch (\Throwable $e) { echo "Error in cleaning stuck application: {$e->getMessage()}\n"; } try { $postgresqls = StandalonePostgresql::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($postgresqls as $postgresql) { echo "Deleting stuck postgresql: {$postgresql->name}\n"; DeleteResourceJob::dispatch($postgresql); } } catch (\Throwable $e) { echo "Error in cleaning stuck postgresql: {$e->getMessage()}\n"; } try { $rediss = StandaloneRedis::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($rediss as $redis) { echo "Deleting stuck redis: {$redis->name}\n"; DeleteResourceJob::dispatch($redis); } } catch (\Throwable $e) { echo "Error in cleaning stuck redis: {$e->getMessage()}\n"; } try { $keydbs = StandaloneKeydb::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($keydbs as $keydb) { echo "Deleting stuck keydb: {$keydb->name}\n"; DeleteResourceJob::dispatch($keydb); } } catch (\Throwable $e) { echo "Error in cleaning stuck keydb: {$e->getMessage()}\n"; } try { $dragonflies = StandaloneDragonfly::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($dragonflies as $dragonfly) { echo "Deleting stuck dragonfly: {$dragonfly->name}\n"; DeleteResourceJob::dispatch($dragonfly); } } catch (\Throwable $e) { echo "Error in cleaning stuck dragonfly: {$e->getMessage()}\n"; } try { $clickhouses = StandaloneClickhouse::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($clickhouses as $clickhouse) { echo "Deleting stuck clickhouse: {$clickhouse->name}\n"; DeleteResourceJob::dispatch($clickhouse); } } catch (\Throwable $e) { echo "Error in cleaning stuck clickhouse: {$e->getMessage()}\n"; } try { $mongodbs = StandaloneMongodb::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($mongodbs as $mongodb) { echo "Deleting stuck mongodb: {$mongodb->name}\n"; DeleteResourceJob::dispatch($mongodb); } } catch (\Throwable $e) { echo "Error in cleaning stuck mongodb: {$e->getMessage()}\n"; } try { $mysqls = StandaloneMysql::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($mysqls as $mysql) { echo "Deleting stuck mysql: {$mysql->name}\n"; DeleteResourceJob::dispatch($mysql); } } catch (\Throwable $e) { echo "Error in cleaning stuck mysql: {$e->getMessage()}\n"; } try { $mariadbs = StandaloneMariadb::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($mariadbs as $mariadb) { echo "Deleting stuck mariadb: {$mariadb->name}\n"; DeleteResourceJob::dispatch($mariadb); } } catch (\Throwable $e) { echo "Error in cleaning stuck mariadb: {$e->getMessage()}\n"; } try { $services = Service::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($services as $service) { echo "Deleting stuck service: {$service->name}\n"; DeleteResourceJob::dispatch($service); } } catch (\Throwable $e) { echo "Error in cleaning stuck service: {$e->getMessage()}\n"; } try { $serviceApps = ServiceApplication::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($serviceApps as $serviceApp) { echo "Deleting stuck serviceapp: {$serviceApp->name}\n"; $serviceApp->forceDelete(); } } catch (\Throwable $e) { echo "Error in cleaning stuck serviceapp: {$e->getMessage()}\n"; } try { $serviceDbs = ServiceDatabase::withTrashed()->whereNotNull('deleted_at')->get(); foreach ($serviceDbs as $serviceDb) { echo "Deleting stuck serviceapp: {$serviceDb->name}\n"; $serviceDb->forceDelete(); } } catch (\Throwable $e) { echo "Error in cleaning stuck serviceapp: {$e->getMessage()}\n"; } try { $scheduled_tasks = ScheduledTask::all(); foreach ($scheduled_tasks as $scheduled_task) { if (! $scheduled_task->service && ! $scheduled_task->application) { echo "Deleting stuck scheduledtask: {$scheduled_task->name}\n"; $scheduled_task->delete(); } } } catch (\Throwable $e) { echo "Error in cleaning stuck scheduledtasks: {$e->getMessage()}\n"; } try { $scheduled_backups = ScheduledDatabaseBackup::all(); foreach ($scheduled_backups as $scheduled_backup) { try { $server = $scheduled_backup->server(); if (! $server) { echo "Deleting stuck scheduledbackup: {$scheduled_backup->name}\n"; $scheduled_backup->delete(); } } catch (\Throwable $e) { echo "Error checking server for scheduledbackup {$scheduled_backup->id}: {$e->getMessage()}\n"; } } } catch (\Throwable $e) { echo "Error in cleaning stuck scheduledbackups: {$e->getMessage()}\n"; } // Cleanup any resources that are not attached to any environment or destination or server try { $applications = Application::all(); foreach ($applications as $application) { if (! data_get($application, 'environment')) { echo 'Application without environment: '.$application->name.'\n'; DeleteResourceJob::dispatch($application); continue; } if (! $application->destination()) { echo 'Application without destination: '.$application->name.'\n'; DeleteResourceJob::dispatch($application); continue; } if (! data_get($application, 'destination.server')) { echo 'Application without server: '.$application->name.'\n'; DeleteResourceJob::dispatch($application); continue; } } } catch (\Throwable $e) { echo "Error in application: {$e->getMessage()}\n"; } try { $postgresqls = StandalonePostgresql::all()->where('id', '!=', 0); foreach ($postgresqls as $postgresql) { if (! data_get($postgresql, 'environment')) { echo 'Postgresql without environment: '.$postgresql->name.'\n'; DeleteResourceJob::dispatch($postgresql); continue; } if (! $postgresql->destination()) { echo 'Postgresql without destination: '.$postgresql->name.'\n'; DeleteResourceJob::dispatch($postgresql); continue; } if (! data_get($postgresql, 'destination.server')) { echo 'Postgresql without server: '.$postgresql->name.'\n'; DeleteResourceJob::dispatch($postgresql); continue; } } } catch (\Throwable $e) { echo "Error in postgresql: {$e->getMessage()}\n"; } try { $redis = StandaloneRedis::all(); foreach ($redis as $redis) { if (! data_get($redis, 'environment')) { echo 'Redis without environment: '.$redis->name.'\n'; DeleteResourceJob::dispatch($redis); continue; } if (! $redis->destination()) { echo 'Redis without destination: '.$redis->name.'\n'; DeleteResourceJob::dispatch($redis); continue; } if (! data_get($redis, 'destination.server')) { echo 'Redis without server: '.$redis->name.'\n'; DeleteResourceJob::dispatch($redis); continue; } } } catch (\Throwable $e) { echo "Error in redis: {$e->getMessage()}\n"; } try { $mongodbs = StandaloneMongodb::all(); foreach ($mongodbs as $mongodb) { if (! data_get($mongodb, 'environment')) { echo 'Mongodb without environment: '.$mongodb->name.'\n'; DeleteResourceJob::dispatch($mongodb); continue; } if (! $mongodb->destination()) { echo 'Mongodb without destination: '.$mongodb->name.'\n'; DeleteResourceJob::dispatch($mongodb); continue; } if (! data_get($mongodb, 'destination.server')) { echo 'Mongodb without server: '.$mongodb->name.'\n'; DeleteResourceJob::dispatch($mongodb); continue; } } } catch (\Throwable $e) { echo "Error in mongodb: {$e->getMessage()}\n"; } try { $mysqls = StandaloneMysql::all(); foreach ($mysqls as $mysql) { if (! data_get($mysql, 'environment')) { echo 'Mysql without environment: '.$mysql->name.'\n'; DeleteResourceJob::dispatch($mysql); continue; } if (! $mysql->destination()) { echo 'Mysql without destination: '.$mysql->name.'\n'; DeleteResourceJob::dispatch($mysql); continue; } if (! data_get($mysql, 'destination.server')) { echo 'Mysql without server: '.$mysql->name.'\n'; DeleteResourceJob::dispatch($mysql); continue; } } } catch (\Throwable $e) { echo "Error in mysql: {$e->getMessage()}\n"; } try { $mariadbs = StandaloneMariadb::all(); foreach ($mariadbs as $mariadb) { if (! data_get($mariadb, 'environment')) { echo 'Mariadb without environment: '.$mariadb->name.'\n'; DeleteResourceJob::dispatch($mariadb); continue; } if (! $mariadb->destination()) { echo 'Mariadb without destination: '.$mariadb->name.'\n'; DeleteResourceJob::dispatch($mariadb); continue; } if (! data_get($mariadb, 'destination.server')) { echo 'Mariadb without server: '.$mariadb->name.'\n'; DeleteResourceJob::dispatch($mariadb); continue; } } } catch (\Throwable $e) { echo "Error in mariadb: {$e->getMessage()}\n"; } try { $services = Service::all(); foreach ($services as $service) { if (! data_get($service, 'environment')) { echo 'Service without environment: '.$service->name.'\n'; DeleteResourceJob::dispatch($service); continue; } if (! $service->destination()) { echo 'Service without destination: '.$service->name.'\n'; DeleteResourceJob::dispatch($service); continue; } if (! data_get($service, 'server')) { echo 'Service without server: '.$service->name.'\n'; DeleteResourceJob::dispatch($service); continue; } } } catch (\Throwable $e) { echo "Error in service: {$e->getMessage()}\n"; } try { $serviceApplications = ServiceApplication::all(); foreach ($serviceApplications as $service) { if (! data_get($service, 'service')) { echo 'ServiceApplication without service: '.$service->name.'\n'; $service->forceDelete(); continue; } } } catch (\Throwable $e) { echo "Error in serviceApplications: {$e->getMessage()}\n"; } try { $serviceDatabases = ServiceDatabase::all(); foreach ($serviceDatabases as $service) { if (! data_get($service, 'service')) { echo 'ServiceDatabase without service: '.$service->name.'\n'; $service->forceDelete(); continue; } } } catch (\Throwable $e) { echo "Error in ServiceDatabases: {$e->getMessage()}\n"; } try { $orphanedCerts = SslCertificate::whereNotIn('server_id', function ($query) { $query->select('id')->from('servers'); })->get(); foreach ($orphanedCerts as $cert) { echo "Deleting orphaned SSL certificate: {$cert->id} (server_id: {$cert->server_id})\n"; $cert->delete(); } } catch (\Throwable $e) { echo "Error in cleaning orphaned SSL certificates: {$e->getMessage()}\n"; } } } ================================================ FILE: app/Console/Commands/CleanupUnreachableServers.php ================================================ =', 3)->where('unreachable_notification_sent', true)->where('updated_at', '<', now()->subDays(7))->get(); if ($servers->count() > 0) { foreach ($servers as $server) { echo "Cleanup unreachable server ($server->id) with name $server->name"; $server->update([ 'ip' => '1.2.3.4', ]); } } } } ================================================ FILE: app/Console/Commands/ClearGlobalSearchCache.php ================================================ option('all')) { return $this->clearAllTeamsCache(); } if ($teamId = $this->option('team')) { return $this->clearTeamCache($teamId); } // If no options provided, clear cache for current user's team if (! auth()->check()) { $this->error('No authenticated user found. Use --team=ID or --all option.'); return Command::FAILURE; } $teamId = auth()->user()->currentTeam()->id; return $this->clearTeamCache($teamId); } private function clearTeamCache(int $teamId): int { $team = Team::find($teamId); if (! $team) { $this->error("Team with ID {$teamId} not found."); return Command::FAILURE; } GlobalSearch::clearTeamCache($teamId); $this->info("✓ Cleared global search cache for team: {$team->name} (ID: {$teamId})"); return Command::SUCCESS; } private function clearAllTeamsCache(): int { $teams = Team::all(); if ($teams->isEmpty()) { $this->warn('No teams found.'); return Command::SUCCESS; } $count = 0; foreach ($teams as $team) { GlobalSearch::clearTeamCache($team->id); $count++; } $this->info("✓ Cleared global search cache for {$count} team(s)"); return Command::SUCCESS; } } ================================================ FILE: app/Console/Commands/Cloud/CloudFixSubscription.php ================================================ option('verify-all')) { return $this->verifyAllActiveSubscriptions($stripe); } if ($this->option('fix-canceled-subs') || $this->option('dry-run')) { return $this->fixCanceledSubscriptions($stripe); } $activeSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', true)->get(); $out = fopen('php://output', 'w'); // CSV header fputcsv($out, [ 'team_id', 'invoice_status', 'stripe_customer_url', 'stripe_subscription_id', 'subscription_status', 'subscription_url', 'note', ]); foreach ($activeSubscribers as $team) { $stripeSubscriptionId = $team->subscription->stripe_subscription_id; $stripeInvoicePaid = $team->subscription->stripe_invoice_paid; $stripeCustomerId = $team->subscription->stripe_customer_id; if (! $stripeSubscriptionId && str($stripeInvoicePaid)->lower() != 'past_due') { fputcsv($out, [ $team->id, $stripeInvoicePaid, $stripeCustomerId ? "https://dashboard.stripe.com/customers/{$stripeCustomerId}" : null, null, null, null, 'Missing subscription ID while invoice not past_due', ]); continue; } if (! $stripeSubscriptionId) { // No subscription ID and invoice is past_due, still record for visibility fputcsv($out, [ $team->id, $stripeInvoicePaid, $stripeCustomerId ? "https://dashboard.stripe.com/customers/{$stripeCustomerId}" : null, null, null, null, 'Missing subscription ID', ]); continue; } $subscription = $stripe->subscriptions->retrieve($stripeSubscriptionId); if ($subscription->status === 'active') { continue; } fputcsv($out, [ $team->id, $stripeInvoicePaid, $stripeCustomerId ? "https://dashboard.stripe.com/customers/{$stripeCustomerId}" : null, $stripeSubscriptionId, $subscription->status, "https://dashboard.stripe.com/subscriptions/{$stripeSubscriptionId}", 'Subscription not active', ]); } fclose($out); } /** * Fix canceled subscriptions in the database */ private function fixCanceledSubscriptions(\Stripe\StripeClient $stripe) { $isDryRun = $this->option('dry-run'); $checkOne = $this->option('one'); if ($isDryRun) { $this->info('DRY RUN MODE - No changes will be made'); if ($checkOne) { $this->info('Checking only the first canceled subscription...'); } else { $this->info('Checking for canceled subscriptions...'); } } else { if ($checkOne) { $this->info('Checking and fixing only the first canceled subscription...'); } else { $this->info('Checking and fixing canceled subscriptions...'); } } $teamsWithSubscriptions = Team::whereRelation('subscription', 'stripe_invoice_paid', true)->get(); $toFixCount = 0; $fixedCount = 0; $errors = []; $canceledSubscriptions = []; foreach ($teamsWithSubscriptions as $team) { $subscription = $team->subscription; if (! $subscription->stripe_subscription_id) { continue; } try { $stripeSubscription = $stripe->subscriptions->retrieve( $subscription->stripe_subscription_id ); if ($stripeSubscription->status === 'canceled') { $toFixCount++; // Get team members' emails $memberEmails = $team->members->pluck('email')->toArray(); $canceledSubscriptions[] = [ 'team_id' => $team->id, 'team_name' => $team->name, 'customer_id' => $subscription->stripe_customer_id, 'subscription_id' => $subscription->stripe_subscription_id, 'status' => 'canceled', 'member_emails' => $memberEmails, 'subscription_model' => $subscription->toArray(), ]; if ($isDryRun) { $this->warn('Would fix canceled subscription:'); $this->line(" Team ID: {$team->id}"); $this->line(" Team Name: {$team->name}"); $this->line(' Team Members: '.implode(', ', $memberEmails)); $this->line(" Customer URL: https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}"); $this->line(" Subscription URL: https://dashboard.stripe.com/subscriptions/{$subscription->stripe_subscription_id}"); $this->line(' Current Subscription Data:'); foreach ($subscription->getAttributes() as $key => $value) { if (is_null($value)) { $this->line(" - {$key}: null"); } elseif (is_bool($value)) { $this->line(" - {$key}: ".($value ? 'true' : 'false')); } else { $this->line(" - {$key}: {$value}"); } } $this->newLine(); } else { $this->warn("Found canceled subscription for Team ID: {$team->id}"); // Send internal notification with all details before fixing $notificationMessage = "Fixing canceled subscription:\n"; $notificationMessage .= "Team ID: {$team->id}\n"; $notificationMessage .= "Team Name: {$team->name}\n"; $notificationMessage .= 'Team Members: '.implode(', ', $memberEmails)."\n"; $notificationMessage .= "Customer URL: https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}\n"; $notificationMessage .= "Subscription URL: https://dashboard.stripe.com/subscriptions/{$subscription->stripe_subscription_id}\n"; $notificationMessage .= "Subscription Data:\n"; foreach ($subscription->getAttributes() as $key => $value) { if (is_null($value)) { $notificationMessage .= " - {$key}: null\n"; } elseif (is_bool($value)) { $notificationMessage .= " - {$key}: ".($value ? 'true' : 'false')."\n"; } else { $notificationMessage .= " - {$key}: {$value}\n"; } } send_internal_notification($notificationMessage); // Apply the same logic as customer.subscription.deleted webhook $team->subscriptionEnded(); $fixedCount++; $this->info(" ✓ Fixed subscription for Team ID: {$team->id}"); $this->line(' Team Members: '.implode(', ', $memberEmails)); $this->line(" Customer URL: https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}"); $this->line(" Subscription URL: https://dashboard.stripe.com/subscriptions/{$subscription->stripe_subscription_id}"); } // Break if --one flag is set if ($checkOne) { break; } } } catch (\Stripe\Exception\InvalidRequestException $e) { if ($e->getStripeCode() === 'resource_missing') { $toFixCount++; // Get team members' emails $memberEmails = $team->members->pluck('email')->toArray(); $canceledSubscriptions[] = [ 'team_id' => $team->id, 'team_name' => $team->name, 'customer_id' => $subscription->stripe_customer_id, 'subscription_id' => $subscription->stripe_subscription_id, 'status' => 'missing', 'member_emails' => $memberEmails, 'subscription_model' => $subscription->toArray(), ]; if ($isDryRun) { $this->error('Would fix missing subscription (not found in Stripe):'); $this->line(" Team ID: {$team->id}"); $this->line(" Team Name: {$team->name}"); $this->line(' Team Members: '.implode(', ', $memberEmails)); $this->line(" Customer URL: https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}"); $this->line(" Subscription ID (missing): {$subscription->stripe_subscription_id}"); $this->line(' Current Subscription Data:'); foreach ($subscription->getAttributes() as $key => $value) { if (is_null($value)) { $this->line(" - {$key}: null"); } elseif (is_bool($value)) { $this->line(" - {$key}: ".($value ? 'true' : 'false')); } else { $this->line(" - {$key}: {$value}"); } } $this->newLine(); } else { $this->error("Subscription not found in Stripe for Team ID: {$team->id}"); // Send internal notification with all details before fixing $notificationMessage = "Fixing missing subscription (not found in Stripe):\n"; $notificationMessage .= "Team ID: {$team->id}\n"; $notificationMessage .= "Team Name: {$team->name}\n"; $notificationMessage .= 'Team Members: '.implode(', ', $memberEmails)."\n"; $notificationMessage .= "Customer URL: https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}\n"; $notificationMessage .= "Subscription ID (missing): {$subscription->stripe_subscription_id}\n"; $notificationMessage .= "Subscription Data:\n"; foreach ($subscription->getAttributes() as $key => $value) { if (is_null($value)) { $notificationMessage .= " - {$key}: null\n"; } elseif (is_bool($value)) { $notificationMessage .= " - {$key}: ".($value ? 'true' : 'false')."\n"; } else { $notificationMessage .= " - {$key}: {$value}\n"; } } send_internal_notification($notificationMessage); // Apply the same logic as customer.subscription.deleted webhook $team->subscriptionEnded(); $fixedCount++; $this->info(" ✓ Fixed missing subscription for Team ID: {$team->id}"); $this->line(' Team Members: '.implode(', ', $memberEmails)); $this->line(" Customer URL: https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}"); } // Break if --one flag is set if ($checkOne) { break; } } else { $errors[] = "Team ID {$team->id}: ".$e->getMessage(); } } catch (\Exception $e) { $errors[] = "Team ID {$team->id}: ".$e->getMessage(); } } $this->newLine(); $this->info('Summary:'); if ($isDryRun) { $this->info(" - Found {$toFixCount} canceled/missing subscriptions that would be fixed"); if ($toFixCount > 0) { $this->newLine(); $this->comment('Run with --fix-canceled-subs to apply these changes'); } } else { $this->info(" - Fixed {$fixedCount} canceled/missing subscriptions"); } if (! empty($errors)) { $this->newLine(); $this->error('Errors encountered:'); foreach ($errors as $error) { $this->error(" - {$error}"); } } return 0; } /** * Verify all active subscriptions against Stripe API */ private function verifyAllActiveSubscriptions(\Stripe\StripeClient $stripe) { $isDryRun = $this->option('dry-run'); $shouldFix = $this->option('fix-verified'); $this->info('Verifying all active subscriptions against Stripe...'); if ($isDryRun) { $this->info('DRY RUN MODE - No changes will be made'); } if ($shouldFix && ! $isDryRun) { $this->warn('FIX MODE - Discrepancies will be corrected'); } // Get all teams with active subscriptions $teamsWithActiveSubscriptions = Team::whereRelation('subscription', 'stripe_invoice_paid', true)->get(); $totalCount = $teamsWithActiveSubscriptions->count(); $this->info("Found {$totalCount} teams with active subscriptions in database"); $this->newLine(); $out = fopen('php://output', 'w'); // CSV header fputcsv($out, [ 'team_id', 'team_name', 'customer_id', 'subscription_id', 'db_status', 'stripe_status', 'action', 'member_emails', 'customer_url', 'subscription_url', ]); $stats = [ 'total' => $totalCount, 'valid_active' => 0, 'valid_past_due' => 0, 'canceled' => 0, 'missing' => 0, 'invalid' => 0, 'fixed' => 0, 'errors' => 0, ]; $processedCount = 0; foreach ($teamsWithActiveSubscriptions as $team) { $subscription = $team->subscription; $memberEmails = $team->members->pluck('email')->toArray(); // Database state $dbStatus = 'active'; if ($subscription->stripe_past_due) { $dbStatus = 'past_due'; } $stripeStatus = null; $action = 'none'; if (! $subscription->stripe_subscription_id) { $this->line("Team {$team->id}: Missing subscription ID, searching in Stripe..."); $foundResult = null; $searchMethod = null; // Search by customer ID if ($subscription->stripe_customer_id) { $this->line(" → Searching by customer ID: {$subscription->stripe_customer_id}"); $foundResult = $this->searchSubscriptionsByCustomer($stripe, $subscription->stripe_customer_id); if ($foundResult) { $searchMethod = $foundResult['method']; } } else { $this->line(' → No customer ID available'); } // Search by emails if not found if (! $foundResult && count($memberEmails) > 0) { $foundResult = $this->searchSubscriptionsByEmails($stripe, $memberEmails); if ($foundResult) { $searchMethod = $foundResult['method']; // Update customer ID if different if (isset($foundResult['customer_id']) && $subscription->stripe_customer_id !== $foundResult['customer_id']) { if ($isDryRun) { $this->warn(" ⚠ Would update customer ID from {$subscription->stripe_customer_id} to {$foundResult['customer_id']}"); } elseif ($shouldFix) { $subscription->update(['stripe_customer_id' => $foundResult['customer_id']]); $this->info(" ✓ Updated customer ID to {$foundResult['customer_id']}"); } } } } if ($foundResult && isset($foundResult['subscription'])) { // Check if it's an active/past_due subscription if (in_array($foundResult['status'], ['active', 'past_due'])) { // Found an active subscription, handle update $result = $this->handleFoundSubscription( $team, $subscription, $foundResult['subscription'], $searchMethod, $isDryRun, $shouldFix, $stats ); fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, $result['id'], $dbStatus, $result['status'], $result['action'], implode(', ', $memberEmails), $subscription->stripe_customer_id ? "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}" : 'N/A', $result['url'], ]); } else { // Found subscription but it's canceled/expired - needs to be deactivated $this->warn(" → Found {$foundResult['status']} subscription {$foundResult['subscription']->id} - needs deactivation"); $result = $this->handleMissingSubscription($team, $subscription, $foundResult['status'], $isDryRun, $shouldFix, $stats); fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, $foundResult['subscription']->id, $dbStatus, $foundResult['status'], 'needs_fix', implode(', ', $memberEmails), $subscription->stripe_customer_id ? "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}" : 'N/A', "https://dashboard.stripe.com/subscriptions/{$foundResult['subscription']->id}", ]); } } else { // No subscription found at all $this->line(' → No subscription found'); $stripeStatus = 'not_found'; $result = $this->handleMissingSubscription($team, $subscription, $stripeStatus, $isDryRun, $shouldFix, $stats); fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, 'N/A', $dbStatus, $result['status'], $result['action'], implode(', ', $memberEmails), $subscription->stripe_customer_id ? "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}" : 'N/A', 'N/A', ]); } } else { // First validate the subscription ID format if (! str_starts_with($subscription->stripe_subscription_id, 'sub_')) { $this->warn(" ⚠ Invalid subscription ID format (doesn't start with 'sub_')"); } try { $stripeSubscription = $stripe->subscriptions->retrieve( $subscription->stripe_subscription_id ); $stripeStatus = $stripeSubscription->status; // Determine if action is needed switch ($stripeStatus) { case 'active': $stats['valid_active']++; $action = 'valid'; break; case 'past_due': $stats['valid_past_due']++; $action = 'valid'; // Ensure past_due flag is set if (! $subscription->stripe_past_due) { if ($isDryRun) { $this->info("Would set stripe_past_due=true for Team {$team->id}"); } elseif ($shouldFix) { $subscription->update(['stripe_past_due' => true]); } } break; case 'canceled': case 'incomplete_expired': case 'unpaid': case 'incomplete': $stats['canceled']++; $action = 'needs_fix'; // Only output problematic subscriptions fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, $subscription->stripe_subscription_id, $dbStatus, $stripeStatus, $action, implode(', ', $memberEmails), "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}", "https://dashboard.stripe.com/subscriptions/{$subscription->stripe_subscription_id}", ]); if ($isDryRun) { $this->info("Would deactivate subscription for Team {$team->id} - status: {$stripeStatus}"); } elseif ($shouldFix) { $this->fixSubscription($team, $subscription, $stripeStatus); $stats['fixed']++; } break; default: $stats['invalid']++; $action = 'unknown'; // Only output problematic subscriptions fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, $subscription->stripe_subscription_id, $dbStatus, $stripeStatus, $action, implode(', ', $memberEmails), "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}", "https://dashboard.stripe.com/subscriptions/{$subscription->stripe_subscription_id}", ]); break; } } catch (\Stripe\Exception\InvalidRequestException $e) { $this->error(' → Error: '.$e->getMessage()); if ($e->getStripeCode() === 'resource_missing' || $e->getHttpStatus() === 404) { // Subscription doesn't exist, try to find by customer ID $this->warn(" → Subscription not found, checking customer's subscriptions..."); $foundResult = null; if ($subscription->stripe_customer_id) { $foundResult = $this->searchSubscriptionsByCustomer($stripe, $subscription->stripe_customer_id); } if ($foundResult && isset($foundResult['subscription']) && in_array($foundResult['status'], ['active', 'past_due'])) { // Found an active subscription with different ID $this->warn(" → ID mismatch! DB: {$subscription->stripe_subscription_id}, Stripe: {$foundResult['subscription']->id}"); fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, "WRONG ID: {$subscription->stripe_subscription_id} → {$foundResult['subscription']->id}", $dbStatus, $foundResult['status'], 'id_mismatch', implode(', ', $memberEmails), "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}", "https://dashboard.stripe.com/subscriptions/{$foundResult['subscription']->id}", ]); if ($isDryRun) { $this->warn(" → Would update subscription ID to {$foundResult['subscription']->id}"); } elseif ($shouldFix) { $subscription->update([ 'stripe_subscription_id' => $foundResult['subscription']->id, 'stripe_invoice_paid' => true, 'stripe_past_due' => $foundResult['status'] === 'past_due', ]); $stats['fixed']++; $this->info(' → Updated subscription ID'); } $stats[$foundResult['status'] === 'active' ? 'valid_active' : 'valid_past_due']++; } else { // No active subscription found $stripeStatus = $foundResult ? $foundResult['status'] : 'not_found'; $result = $this->handleMissingSubscription($team, $subscription, $stripeStatus, $isDryRun, $shouldFix, $stats); fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, $subscription->stripe_subscription_id, $dbStatus, $result['status'], $result['action'], implode(', ', $memberEmails), $subscription->stripe_customer_id ? "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}" : 'N/A', $foundResult && isset($foundResult['subscription']) ? "https://dashboard.stripe.com/subscriptions/{$foundResult['subscription']->id}" : 'N/A', ]); } } else { // Other API error $stats['errors']++; $this->error(' → API Error - not marking as deleted'); fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, $subscription->stripe_subscription_id, $dbStatus, 'error: '.$e->getStripeCode(), 'error', implode(', ', $memberEmails), $subscription->stripe_customer_id ? "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}" : 'N/A', $subscription->stripe_subscription_id ? "https://dashboard.stripe.com/subscriptions/{$subscription->stripe_subscription_id}" : 'N/A', ]); } } catch (\Exception $e) { $this->error(' → Unexpected error: '.$e->getMessage()); $stats['errors']++; fputcsv($out, [ $team->id, $team->name, $subscription->stripe_customer_id, $subscription->stripe_subscription_id, $dbStatus, 'error', 'error', implode(', ', $memberEmails), $subscription->stripe_customer_id ? "https://dashboard.stripe.com/customers/{$subscription->stripe_customer_id}" : 'N/A', $subscription->stripe_subscription_id ? "https://dashboard.stripe.com/subscriptions/{$subscription->stripe_subscription_id}" : 'N/A', ]); } } $processedCount++; if ($processedCount % 100 === 0) { $this->info("Processed {$processedCount}/{$totalCount} subscriptions..."); } } fclose($out); // Print summary $this->newLine(2); $this->info('=== Verification Summary ==='); $this->info("Total subscriptions checked: {$stats['total']}"); $this->newLine(); $this->info('Valid subscriptions in Stripe:'); $this->line(" - Active: {$stats['valid_active']}"); $this->line(" - Past Due: {$stats['valid_past_due']}"); $validTotal = $stats['valid_active'] + $stats['valid_past_due']; $this->info(" Total valid: {$validTotal}"); $this->newLine(); $this->warn('Invalid subscriptions:'); $this->line(" - Canceled/Expired: {$stats['canceled']}"); $this->line(" - Missing/Not Found: {$stats['missing']}"); $this->line(" - Unknown status: {$stats['invalid']}"); $invalidTotal = $stats['canceled'] + $stats['missing'] + $stats['invalid']; $this->warn(" Total invalid: {$invalidTotal}"); if ($stats['errors'] > 0) { $this->newLine(); $this->error("Errors encountered: {$stats['errors']}"); } if ($shouldFix && ! $isDryRun) { $this->newLine(); $this->info("Fixed subscriptions: {$stats['fixed']}"); } elseif ($invalidTotal > 0 && ! $shouldFix) { $this->newLine(); $this->comment('Run with --fix-verified to fix the discrepancies'); } return 0; } /** * Fix a subscription based on its status */ private function fixSubscription($team, $subscription, $status) { $message = "Fixing subscription for Team ID: {$team->id} (Status: {$status})\n"; $message .= "Team Name: {$team->name}\n"; $message .= "Customer ID: {$subscription->stripe_customer_id}\n"; $message .= "Subscription ID: {$subscription->stripe_subscription_id}\n"; send_internal_notification($message); // Call the team's subscription ended method which properly cleans up $team->subscriptionEnded(); } /** * Search for subscriptions by customer ID */ private function searchSubscriptionsByCustomer(\Stripe\StripeClient $stripe, $customerId, $requireActive = false) { try { $subscriptions = $stripe->subscriptions->all([ 'customer' => $customerId, 'limit' => 10, 'status' => 'all', ]); $this->line(' → Found '.count($subscriptions->data).' subscription(s) for customer'); // Look for active/past_due first foreach ($subscriptions->data as $sub) { $this->line(" - Subscription {$sub->id}: status={$sub->status}"); if (in_array($sub->status, ['active', 'past_due'])) { $this->info(" ✓ Found active/past_due subscription: {$sub->id}"); return ['subscription' => $sub, 'status' => $sub->status, 'method' => 'customer_id']; } } // If not requiring active and there are subscriptions, return first one if (! $requireActive && count($subscriptions->data) > 0) { $sub = $subscriptions->data[0]; $this->warn(" ⚠ Only found {$sub->status} subscription: {$sub->id}"); return ['subscription' => $sub, 'status' => $sub->status, 'method' => 'customer_id_first']; } return null; } catch (\Exception $e) { $this->error(' → Error searching by customer ID: '.$e->getMessage()); return null; } } /** * Search for subscriptions by team member emails */ private function searchSubscriptionsByEmails(\Stripe\StripeClient $stripe, $emails) { $this->line(' → Searching by team member emails...'); foreach ($emails as $email) { $this->line(" → Checking email: {$email}"); try { $customers = $stripe->customers->all([ 'email' => $email, 'limit' => 5, ]); if (count($customers->data) === 0) { $this->line(' - No customers found'); continue; } $this->line(' - Found '.count($customers->data).' customer(s)'); foreach ($customers->data as $customer) { $this->line(" - Checking customer {$customer->id}"); $result = $this->searchSubscriptionsByCustomer($stripe, $customer->id, true); if ($result) { $result['method'] = "email:{$email}"; $result['customer_id'] = $customer->id; return $result; } } } catch (\Exception $e) { $this->error(" - Error searching for email {$email}: ".$e->getMessage()); } } return null; } /** * Handle found subscription update (only for active/past_due subscriptions) */ private function handleFoundSubscription($team, $subscription, $foundSub, $searchMethod, $isDryRun, $shouldFix, &$stats) { $stripeStatus = $foundSub->status; $this->info(" ✓ FOUND active/past_due subscription {$foundSub->id} (status: {$stripeStatus})"); // Only update if it's active or past_due if (! in_array($stripeStatus, ['active', 'past_due'])) { $this->error(" ERROR: handleFoundSubscription called with {$stripeStatus} subscription!"); return [ 'id' => $foundSub->id, 'status' => $stripeStatus, 'action' => 'error', 'url' => "https://dashboard.stripe.com/subscriptions/{$foundSub->id}", ]; } if ($isDryRun) { $this->warn(" → Would update subscription ID to {$foundSub->id} (status: {$stripeStatus})"); } elseif ($shouldFix) { $subscription->update([ 'stripe_subscription_id' => $foundSub->id, 'stripe_invoice_paid' => true, 'stripe_past_due' => $stripeStatus === 'past_due', ]); $stats['fixed']++; $this->info(" → Updated subscription ID to {$foundSub->id}"); } // Update stats $stats[$stripeStatus === 'active' ? 'valid_active' : 'valid_past_due']++; return [ 'id' => "FOUND: {$foundSub->id}", 'status' => $stripeStatus, 'action' => "will_update (via {$searchMethod})", 'url' => "https://dashboard.stripe.com/subscriptions/{$foundSub->id}", ]; } /** * Handle missing subscription */ private function handleMissingSubscription($team, $subscription, $status, $isDryRun, $shouldFix, &$stats) { $stats['missing']++; if ($isDryRun) { $statusMsg = $status !== 'not_found' ? "status: {$status}" : 'no subscription found in Stripe'; $this->warn(" → Would deactivate subscription - {$statusMsg}"); } elseif ($shouldFix) { $this->fixSubscription($team, $subscription, $status); $stats['fixed']++; $this->info(' → Deactivated subscription'); } return [ 'id' => 'N/A', 'status' => $status, 'action' => 'needs_fix', 'url' => 'N/A', ]; } } ================================================ FILE: app/Console/Commands/Cloud/RestoreDatabase.php ================================================ debug = $this->option('debug'); if (! $this->isDevelopment()) { $this->error('This command can only be run in development mode.'); return 1; } $filePath = $this->argument('file'); if (! file_exists($filePath)) { $this->error("File not found: {$filePath}"); return 1; } if (! is_readable($filePath)) { $this->error("File is not readable: {$filePath}"); return 1; } try { $this->info('Starting database restoration...'); $database = config('database.connections.pgsql.database'); $host = config('database.connections.pgsql.host'); $port = config('database.connections.pgsql.port'); $username = config('database.connections.pgsql.username'); $password = config('database.connections.pgsql.password'); if (! $database || ! $username) { $this->error('Database configuration is incomplete.'); return 1; } $this->info("Restoring to database: {$database}"); // Drop all tables if (! $this->dropAllTables($database, $host, $port, $username, $password)) { return 1; } // Restore the database dump if (! $this->restoreDatabaseDump($filePath, $database, $host, $port, $username, $password)) { return 1; } $this->info('Database restoration completed successfully!'); return 0; } catch (\Exception $e) { $this->error("An error occurred: {$e->getMessage()}"); return 1; } } private function dropAllTables(string $database, string $host, string $port, string $username, string $password): bool { $this->info('Dropping all tables...'); // SQL to drop all tables $dropTablesSQL = <<<'SQL' DO $$ DECLARE r RECORD; BEGIN FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public') LOOP EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; END LOOP; END $$; SQL; // Build the psql command to drop all tables $command = sprintf( 'PGPASSWORD=%s psql -h %s -p %s -U %s -d %s -c %s', escapeshellarg($password), escapeshellarg($host), escapeshellarg($port), escapeshellarg($username), escapeshellarg($database), escapeshellarg($dropTablesSQL) ); if ($this->debug) { $this->line('Executing drop command:'); $this->line($command); } $output = shell_exec($command.' 2>&1'); if ($this->debug) { $this->line("Output: {$output}"); } $this->info('All tables dropped successfully.'); return true; } private function restoreDatabaseDump(string $filePath, string $database, string $host, string $port, string $username, string $password): bool { $this->info('Restoring database from dump file...'); // Handle gzipped files by decompressing first $actualFile = $filePath; if (str_ends_with($filePath, '.gz')) { $actualFile = rtrim($filePath, '.gz'); $this->info('Decompressing gzipped dump file...'); $decompressCommand = sprintf( 'gunzip -c %s > %s', escapeshellarg($filePath), escapeshellarg($actualFile) ); if ($this->debug) { $this->line('Executing decompress command:'); $this->line($decompressCommand); } $decompressOutput = shell_exec($decompressCommand.' 2>&1'); if ($this->debug && $decompressOutput) { $this->line("Decompress output: {$decompressOutput}"); } } // Use pg_restore for custom format dumps $command = sprintf( 'PGPASSWORD=%s pg_restore -h %s -p %s -U %s -d %s -v %s', escapeshellarg($password), escapeshellarg($host), escapeshellarg($port), escapeshellarg($username), escapeshellarg($database), escapeshellarg($actualFile) ); if ($this->debug) { $this->line('Executing restore command:'); $this->line($command); } // Execute the restore command $process = proc_open( $command, [ 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ], $pipes ); if (! is_resource($process)) { $this->error('Failed to start restoration process.'); return false; } $output = stream_get_contents($pipes[1]); $error = stream_get_contents($pipes[2]); $exitCode = proc_close($process); // Clean up decompressed file if we created one if ($actualFile !== $filePath && file_exists($actualFile)) { unlink($actualFile); } if ($this->debug) { if ($output) { $this->line('Output:'); $this->line($output); } if ($error) { $this->line('Error output:'); $this->line($error); } $this->line("Exit code: {$exitCode}"); } if ($exitCode !== 0) { $this->error("Restoration failed with exit code: {$exitCode}"); if ($error) { $this->error('Error details:'); $this->error($error); } return false; } if ($output && ! $this->debug) { $this->line($output); } return true; } private function isDevelopment(): bool { return app()->environment(['local', 'development', 'dev']); } } ================================================ FILE: app/Console/Commands/Cloud/SyncStripeSubscriptions.php ================================================ error('This command can only be run on Coolify Cloud.'); return 1; } if (! isStripe()) { $this->error('Stripe is not configured.'); return 1; } $fix = $this->option('fix'); if ($fix) { $this->warn('Running with --fix: discrepancies will be corrected.'); } else { $this->info('Running in check mode (no changes will be made). Use --fix to apply corrections.'); } $this->newLine(); $job = new SyncStripeSubscriptionsJob($fix); $fetched = 0; $result = $job->handle(function (int $count) use (&$fetched): void { $fetched = $count; $this->output->write("\r Fetching subscriptions from Stripe... {$fetched}"); }); if ($fetched > 0) { $this->output->write("\r".str_repeat(' ', 60)."\r"); } if (isset($result['error'])) { $this->error($result['error']); return 1; } $this->info("Total subscriptions checked: {$result['total_checked']}"); $this->newLine(); if (count($result['discrepancies']) > 0) { $this->warn('Discrepancies found: '.count($result['discrepancies'])); $this->newLine(); foreach ($result['discrepancies'] as $discrepancy) { $this->line(" - Subscription ID: {$discrepancy['subscription_id']}"); $this->line(" Team ID: {$discrepancy['team_id']}"); $this->line(" Stripe ID: {$discrepancy['stripe_subscription_id']}"); $this->line(" Stripe Status: {$discrepancy['stripe_status']}"); $this->newLine(); } if ($fix) { $this->info('All discrepancies have been fixed.'); } else { $this->comment('Run with --fix to correct these discrepancies.'); } } else { $this->info('No discrepancies found. All subscriptions are in sync.'); } if (count($result['resubscribed']) > 0) { $this->newLine(); $this->warn('Resubscribed users (same email, different customer): '.count($result['resubscribed'])); $this->newLine(); foreach ($result['resubscribed'] as $resub) { $this->line(" - Team ID: {$resub['team_id']} | Email: {$resub['email']}"); $this->line(" Old: {$resub['old_stripe_subscription_id']} (cus: {$resub['old_stripe_customer_id']})"); $this->line(" New: {$resub['new_stripe_subscription_id']} (cus: {$resub['new_stripe_customer_id']}) [{$resub['new_status']}]"); $this->newLine(); } } if (count($result['errors']) > 0) { $this->newLine(); $this->error('Errors encountered: '.count($result['errors'])); foreach ($result['errors'] as $error) { $this->line(" - Subscription {$error['subscription_id']}: {$error['error']}"); } } return 0; } } ================================================ FILE: app/Console/Commands/Dev.php ================================================ option('init')) { $this->init(); return; } } public function init() { // Generate APP_KEY if not exists if (empty(config('app.key'))) { echo "Generating APP_KEY.\n"; Artisan::call('key:generate'); } // Generate STORAGE link if not exists if (! file_exists(public_path('storage'))) { echo "Generating STORAGE link.\n"; Artisan::call('storage:link'); } // Seed database if it's empty $settings = InstanceSettings::find(0); if (! $settings) { echo "Initializing instance, seeding database.\n"; Artisan::call('migrate --seed'); } else { echo "Instance already initialized.\n"; } // Clean up stuck jobs and stale locks on development startup try { echo "Cleaning up Redis (stuck jobs and stale locks)...\n"; Artisan::call('cleanup:redis', ['--restart' => true, '--clear-locks' => true]); echo "Redis cleanup completed.\n"; } catch (\Throwable $e) { echo "Error in cleanup:redis: {$e->getMessage()}\n"; } try { $updatedTaskCount = ScheduledTaskExecution::where('status', 'running')->update([ 'status' => 'failed', 'message' => 'Marked as failed during Coolify startup - job was interrupted', 'finished_at' => Carbon::now(), ]); if ($updatedTaskCount > 0) { echo "Marked {$updatedTaskCount} stuck scheduled task executions as failed\n"; } } catch (\Throwable $e) { echo "Could not cleanup stuck scheduled task executions: {$e->getMessage()}\n"; } try { $updatedBackupCount = ScheduledDatabaseBackupExecution::where('status', 'running')->update([ 'status' => 'failed', 'message' => 'Marked as failed during Coolify startup - job was interrupted', 'finished_at' => Carbon::now(), ]); if ($updatedBackupCount > 0) { echo "Marked {$updatedBackupCount} stuck database backup executions as failed\n"; } } catch (\Throwable $e) { echo "Could not cleanup stuck database backup executions: {$e->getMessage()}\n"; } CheckHelperImageJob::dispatch(); } } ================================================ FILE: app/Console/Commands/Emails.php ================================================ 'Send Update Email to all users', 'emails-test' => 'Test', 'database-backup-statuses-daily' => 'Database - Backup Statuses (Daily)', 'application-deployment-success-daily' => 'Application - Deployment Success (Daily)', 'application-deployment-success' => 'Application - Deployment Success', 'application-deployment-failed' => 'Application - Deployment Failed', 'application-status-changed' => 'Application - Status Changed', 'backup-success' => 'Database - Backup Success', 'backup-failed' => 'Database - Backup Failed', // 'invitation-link' => 'Invitation Link', 'realusers-before-trial' => 'REAL - Registered Users Before Trial without Subscription', 'realusers-server-lost-connection' => 'REAL - Server Lost Connection', ], ); $emailsGathered = ['realusers-before-trial', 'realusers-server-lost-connection']; if (isDev()) { $this->email = 'test@example.com'; } else { if (! in_array($type, $emailsGathered)) { $this->email = text('Email Address to send to:'); } } set_transanctional_email_settings(); $this->mail = new MailMessage; $this->mail->subject('Test Email'); switch ($type) { case 'updates': $teams = Team::all(); if (! $teams || $teams->isEmpty()) { echo 'No teams found.'.PHP_EOL; return; } $emails = []; foreach ($teams as $team) { foreach ($team->members as $member) { if ($member->email && $member->marketing_emails) { $emails[] = $member->email; } } } $emails = array_unique($emails); $this->info('Sending to '.count($emails).' emails.'); foreach ($emails as $email) { $this->info($email); } $confirmed = confirm('Are you sure?'); if ($confirmed) { foreach ($emails as $email) { $this->mail = new MailMessage; $this->mail->subject('One-click Services, Docker Compose support'); $unsubscribeUrl = route('unsubscribe.marketing.emails', [ 'token' => encrypt($email), ]); $this->mail->view('emails.updates', ['unsubscribeUrl' => $unsubscribeUrl]); $this->sendEmail($email); } } break; case 'emails-test': $this->mail = (new Test)->toMail(); $this->sendEmail(); break; case 'application-deployment-success-daily': $applications = Application::all(); foreach ($applications as $application) { $deployments = $application->get_last_days_deployments(); if ($deployments->isEmpty()) { continue; } $this->mail = (new DeploymentSuccess($application, 'test'))->toMail(); $this->sendEmail(); } break; case 'application-deployment-success': $application = Application::all()->first(); $this->mail = (new DeploymentSuccess($application, 'test'))->toMail(); $this->sendEmail(); break; case 'application-deployment-failed': $application = Application::all()->first(); $preview = ApplicationPreview::all()->first(); if (! $preview) { $preview = ApplicationPreview::create([ 'application_id' => $application->id, 'pull_request_id' => 1, 'pull_request_html_url' => 'http://example.com', 'fqdn' => $application->fqdn, ]); } $this->mail = (new DeploymentFailed($application, 'test'))->toMail(); $this->sendEmail(); $this->mail = (new DeploymentFailed($application, 'test', $preview))->toMail(); $this->sendEmail(); break; case 'application-status-changed': $application = Application::all()->first(); $this->mail = (new StatusChanged($application))->toMail(); $this->sendEmail(); break; case 'backup-failed': $backup = ScheduledDatabaseBackup::all()->first(); $db = StandalonePostgresql::all()->first(); if (! $backup) { $backup = ScheduledDatabaseBackup::create([ 'enabled' => true, 'frequency' => 'daily', 'save_s3' => false, 'database_id' => $db->id, 'database_type' => $db->getMorphClass(), 'team_id' => 0, ]); } $output = 'Because of an error, the backup of the database '.$db->name.' failed.'; $this->mail = (new BackupFailed($backup, $db, $output, $backup->database_name ?? 'unknown'))->toMail(); $this->sendEmail(); break; case 'backup-success': $backup = ScheduledDatabaseBackup::all()->first(); $db = StandalonePostgresql::all()->first(); if (! $backup) { $backup = ScheduledDatabaseBackup::create([ 'enabled' => true, 'frequency' => 'daily', 'save_s3' => false, 'database_id' => $db->id, 'database_type' => $db->getMorphClass(), 'team_id' => 0, ]); } // $this->mail = (new BackupSuccess($backup->frequency, $db->name))->toMail(); $this->sendEmail(); break; // case 'invitation-link': // $user = User::all()->first(); // $invitation = TeamInvitation::whereEmail($user->email)->first(); // if (!$invitation) { // $invitation = TeamInvitation::create([ // 'uuid' => Str::uuid(), // 'email' => $user->email, // 'team_id' => 1, // 'link' => 'http://example.com', // ]); // } // $this->mail = (new InvitationLink($user))->toMail(); // $this->sendEmail(); // break; case 'realusers-before-trial': $this->mail = new MailMessage; $this->mail->view('emails.before-trial-conversion'); $this->mail->subject('Trial period has been added for all subscription plans.'); $teams = Team::doesntHave('subscription')->where('id', '!=', 0)->get(); if (! $teams || $teams->isEmpty()) { echo 'No teams found.'.PHP_EOL; return; } $emails = []; foreach ($teams as $team) { foreach ($team->members as $member) { if ($member->email) { $emails[] = $member->email; } } } $emails = array_unique($emails); $this->info('Sending to '.count($emails).' emails.'); foreach ($emails as $email) { $this->info($email); } $confirmed = confirm('Are you sure?'); if ($confirmed) { foreach ($emails as $email) { $this->sendEmail($email); } } break; case 'realusers-server-lost-connection': $serverId = text('Server Id'); $server = Server::find($serverId); if (! $server) { throw new Exception('Server not found'); } $admins = []; $members = $server->team->members; foreach ($members as $member) { if ($member->isAdmin()) { $admins[] = $member->email; } } $this->info('Sending to '.count($admins).' admins.'); foreach ($admins as $admin) { $this->info($admin); } $this->mail = new MailMessage; $this->mail->view('emails.server-lost-connection', [ 'name' => $server->name, ]); $this->mail->subject('Action required: Server '.$server->name.' lost connection.'); foreach ($admins as $email) { $this->sendEmail($email); } break; } } private function sendEmail(?string $email = null) { if ($email) { $this->email = $email; } Mail::send( [], [], fn (Message $message) => $message ->to($this->email) ->subject($this->mail->subject) ->html((string) $this->mail->render()) ); $this->info("Email sent to $this->email successfully. 📧"); } } ================================================ FILE: app/Console/Commands/Generate/OpenApi.php ================================================ errorOutput(); $error = preg_replace('/^.*an object literal,.*$/m', '', $error); $error = preg_replace('/^\h*\v+/m', '', $error); echo $error; echo $process->output(); $yaml = file_get_contents('openapi.yaml'); $json = json_encode(Yaml::parse($yaml), JSON_PRETTY_PRINT)."\n"; file_put_contents('openapi.json', $json); echo "Converted OpenAPI YAML to JSON.\n"; } } ================================================ FILE: app/Console/Commands/Generate/Services.php ================================================ mapWithKeys(function ($file): array { $file = basename($file); $parsed = $this->processFile($file); return $parsed === false ? [] : [ Arr::pull($parsed, 'name') => $parsed, ]; })->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); file_put_contents(base_path('templates/'.config('constants.services.file_name')), $serviceTemplatesJson.PHP_EOL); // Generate service-templates.json with SERVICE_URL changed to SERVICE_FQDN $this->generateServiceTemplatesWithFqdn(); return self::SUCCESS; } private function processFile(string $file): false|array { $content = file_get_contents(base_path("templates/compose/$file")); $data = collect(explode(PHP_EOL, $content))->mapWithKeys(function ($line): array { preg_match('/^#(?.*):(?.*)$/U', $line, $m); return $m ? [trim($m['key']) => trim($m['value'])] : []; }); if (str($data->get('ignore'))->toBoolean()) { $this->info("Ignoring $file"); return false; } $this->info("Processing $file"); $documentation = $data->get('documentation'); $documentation = $documentation ? $documentation.'?utm_source=coolify.io' : 'https://coolify.io/docs'; $json = Yaml::parse($content); $compose = base64_encode(Yaml::dump($json, 10, 2)); $tags = str($data->get('tags'))->lower()->explode(',')->map(fn ($tag) => trim($tag))->filter(); $tags = $tags->isEmpty() ? null : $tags->all(); $payload = [ 'name' => pathinfo($file, PATHINFO_FILENAME), 'documentation' => $documentation, 'slogan' => $data->get('slogan', str($file)->headline()), 'compose' => $compose, 'tags' => $tags, 'category' => $data->get('category'), 'logo' => $data->get('logo', 'svgs/default.webp'), 'minversion' => $data->get('minversion', '0.0.0'), ]; if ($port = $data->get('port')) { $payload['port'] = $port; } if ($envFile = $data->get('env_file')) { $envFileContent = file_get_contents(base_path("templates/compose/$envFile")); $payload['envs'] = base64_encode($envFileContent); } return $payload; } private function generateServiceTemplatesWithFqdn(): void { $serviceTemplatesWithFqdn = collect(array_merge( glob(base_path('templates/compose/*.yaml')), glob(base_path('templates/compose/*.yml')) )) ->mapWithKeys(function ($file): array { $file = basename($file); $parsed = $this->processFileWithFqdn($file); return $parsed === false ? [] : [ Arr::pull($parsed, 'name') => $parsed, ]; })->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); file_put_contents(base_path('templates/service-templates.json'), $serviceTemplatesWithFqdn.PHP_EOL); // Generate service-templates-raw.json with non-base64 encoded compose content // $this->generateServiceTemplatesRaw(); } private function processFileWithFqdn(string $file): false|array { $content = file_get_contents(base_path("templates/compose/$file")); $data = collect(explode(PHP_EOL, $content))->mapWithKeys(function ($line): array { preg_match('/^#(?.*):(?.*)$/U', $line, $m); return $m ? [trim($m['key']) => trim($m['value'])] : []; }); if (str($data->get('ignore'))->toBoolean()) { return false; } $documentation = $data->get('documentation'); $documentation = $documentation ? $documentation.'?utm_source=coolify.io' : 'https://coolify.io/docs'; // Replace SERVICE_URL with SERVICE_FQDN in the content $modifiedContent = str_replace('SERVICE_URL', 'SERVICE_FQDN', $content); $json = Yaml::parse($modifiedContent); $compose = base64_encode(Yaml::dump($json, 10, 2)); $tags = str($data->get('tags'))->lower()->explode(',')->map(fn ($tag) => trim($tag))->filter(); $tags = $tags->isEmpty() ? null : $tags->all(); $payload = [ 'name' => pathinfo($file, PATHINFO_FILENAME), 'documentation' => $documentation, 'slogan' => $data->get('slogan', str($file)->headline()), 'compose' => $compose, 'tags' => $tags, 'category' => $data->get('category'), 'logo' => $data->get('logo', 'svgs/default.webp'), 'minversion' => $data->get('minversion', '0.0.0'), ]; if ($port = $data->get('port')) { $payload['port'] = $port; } if ($envFile = $data->get('env_file')) { $envFileContent = file_get_contents(base_path("templates/compose/$envFile")); // Also replace SERVICE_URL with SERVICE_FQDN in env file content $modifiedEnvContent = str_replace('SERVICE_URL', 'SERVICE_FQDN', $envFileContent); $payload['envs'] = base64_encode($modifiedEnvContent); } return $payload; } private function generateServiceTemplatesRaw(): void { $serviceTemplatesRaw = collect(array_merge( glob(base_path('templates/compose/*.yaml')), glob(base_path('templates/compose/*.yml')) )) ->mapWithKeys(function ($file): array { $file = basename($file); $parsed = $this->processFileWithFqdnRaw($file); return $parsed === false ? [] : [ Arr::pull($parsed, 'name') => $parsed, ]; })->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); file_put_contents(base_path('templates/service-templates-raw.json'), $serviceTemplatesRaw.PHP_EOL); } private function processFileWithFqdnRaw(string $file): false|array { $content = file_get_contents(base_path("templates/compose/$file")); $data = collect(explode(PHP_EOL, $content))->mapWithKeys(function ($line): array { preg_match('/^#(?.*):(?.*)$/U', $line, $m); return $m ? [trim($m['key']) => trim($m['value'])] : []; }); if (str($data->get('ignore'))->toBoolean()) { return false; } $documentation = $data->get('documentation'); $documentation = $documentation ? $documentation.'?utm_source=coolify.io' : 'https://coolify.io/docs'; // Replace SERVICE_URL with SERVICE_FQDN in the content $modifiedContent = str_replace('SERVICE_URL', 'SERVICE_FQDN', $content); $json = Yaml::parse($modifiedContent); $compose = Yaml::dump($json, 10, 2); // Not base64 encoded $tags = str($data->get('tags'))->lower()->explode(',')->map(fn ($tag) => trim($tag))->filter(); $tags = $tags->isEmpty() ? null : $tags->all(); $payload = [ 'name' => pathinfo($file, PATHINFO_FILENAME), 'documentation' => $documentation, 'slogan' => $data->get('slogan', str($file)->headline()), 'compose' => $compose, 'tags' => $tags, 'category' => $data->get('category'), 'logo' => $data->get('logo', 'svgs/default.webp'), 'minversion' => $data->get('minversion', '0.0.0'), ]; if ($port = $data->get('port')) { $payload['port'] = $port; } if ($envFile = $data->get('env_file')) { $envFileContent = file_get_contents(base_path("templates/compose/$envFile")); // Also replace SERVICE_URL with SERVICE_FQDN in env file content (not base64 encoded) $modifiedEnvContent = str_replace('SERVICE_URL', 'SERVICE_FQDN', $envFileContent); $payload['envs'] = $modifiedEnvContent; } return $payload; } } ================================================ FILE: app/Console/Commands/GenerateTestingSchema.php ================================================ 'INTEGER', '/\binteger\b/' => 'INTEGER', '/\bsmallint\b/' => 'INTEGER', '/\bboolean\b/' => 'INTEGER', '/character varying\(\d+\)/' => 'TEXT', '/timestamp\(\d+\) without time zone/' => 'TEXT', '/timestamp\(\d+\) with time zone/' => 'TEXT', '/\bjsonb\b/' => 'TEXT', '/\bjson\b/' => 'TEXT', '/\buuid\b/' => 'TEXT', '/double precision/' => 'REAL', '/numeric\(\d+,\d+\)/' => 'REAL', '/\bdate\b/' => 'TEXT', ]; private array $castRemovals = [ '::character varying', '::text', '::integer', '::boolean', '::timestamp without time zone', '::timestamp with time zone', '::numeric', ]; public function handle(): int { $connection = $this->option('connection'); if (DB::connection($connection)->getDriverName() !== 'pgsql') { $this->error("Connection '{$connection}' is not PostgreSQL."); return self::FAILURE; } $this->info('Reading schema from PostgreSQL...'); $tables = $this->getTables($connection); $lastMigration = DB::connection($connection) ->table('migrations') ->orderByDesc('id') ->value('migration'); $output = []; $output[] = '-- Generated by: php artisan schema:generate-testing'; $output[] = '-- Date: '.now()->format('Y-m-d H:i:s'); $output[] = '-- Last migration: '.($lastMigration ?? 'none'); $output[] = ''; foreach ($tables as $table) { $columns = $this->getColumns($connection, $table); $output[] = $this->generateCreateTable($table, $columns); } $indexes = $this->getIndexes($connection, $tables); foreach ($indexes as $index) { $output[] = $index; } $output[] = ''; $output[] = '-- Migration records'; $migrations = DB::connection($connection)->table('migrations')->orderBy('id')->get(); foreach ($migrations as $m) { $migration = str_replace("'", "''", $m->migration); $output[] = "INSERT INTO \"migrations\" (\"id\", \"migration\", \"batch\") VALUES ({$m->id}, '{$migration}', {$m->batch});"; } $path = database_path('schema/testing-schema.sql'); if (! is_dir(dirname($path))) { mkdir(dirname($path), 0755, true); } file_put_contents($path, implode("\n", $output)."\n"); $this->info("Schema written to {$path}"); $this->info(count($tables).' tables, '.count($migrations).' migration records.'); return self::SUCCESS; } private function getTables(string $connection): array { return collect(DB::connection($connection)->select( "SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename" ))->pluck('tablename')->toArray(); } private function getColumns(string $connection, string $table): array { return DB::connection($connection)->select( "SELECT column_name, data_type, character_maximum_length, column_default, is_nullable, udt_name, numeric_precision, numeric_scale, datetime_precision FROM information_schema.columns WHERE table_schema = 'public' AND table_name = ? ORDER BY ordinal_position", [$table] ); } private function generateCreateTable(string $table, array $columns): string { $lines = []; foreach ($columns as $col) { $lines[] = ' '.$this->generateColumnDef($table, $col); } return "CREATE TABLE IF NOT EXISTS \"{$table}\" (\n".implode(",\n", $lines)."\n);\n"; } private function generateColumnDef(string $table, object $col): string { $name = $col->column_name; $sqliteType = $this->convertType($col); // Auto-increment primary key for id columns if ($name === 'id' && $sqliteType === 'INTEGER' && $col->is_nullable === 'NO' && str_contains((string) $col->column_default, 'nextval')) { return "\"{$name}\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"; } $parts = ["\"{$name}\"", $sqliteType]; // Default value $default = $col->column_default; if ($default !== null && ! str_contains($default, 'nextval')) { $default = $this->cleanDefault($default); $parts[] = "DEFAULT {$default}"; } // NOT NULL if ($col->is_nullable === 'NO') { $parts[] = 'NOT NULL'; } return implode(' ', $parts); } private function convertType(object $col): string { $pgType = $col->data_type; return match (true) { in_array($pgType, ['bigint', 'integer', 'smallint']) => 'INTEGER', $pgType === 'boolean' => 'INTEGER', in_array($pgType, ['character varying', 'text', 'USER-DEFINED']) => 'TEXT', str_contains($pgType, 'timestamp') => 'TEXT', in_array($pgType, ['json', 'jsonb']) => 'TEXT', $pgType === 'uuid' => 'TEXT', $pgType === 'double precision' => 'REAL', $pgType === 'numeric' => 'REAL', $pgType === 'date' => 'TEXT', default => 'TEXT', }; } private function cleanDefault(string $default): string { foreach ($this->castRemovals as $cast) { $default = str_replace($cast, '', $default); } // Remove array type casts like ::text[] $default = preg_replace('/::[\w\s]+(\[\])?/', '', $default); return $default; } private function getIndexes(string $connection, array $tables): array { $results = []; $indexes = DB::connection($connection)->select( "SELECT indexname, tablename, indexdef FROM pg_indexes WHERE schemaname = 'public' ORDER BY tablename, indexname" ); foreach ($indexes as $idx) { $def = $idx->indexdef; // Skip primary key indexes if (str_contains($def, '_pkey')) { continue; } // Skip PG-specific indexes (GIN, GIST, expression indexes) if (preg_match('/USING (gin|gist)/i', $def)) { continue; } if (str_contains($def, '->>') || str_contains($def, '::')) { continue; } // Convert to SQLite-compatible CREATE INDEX $unique = str_contains($def, 'UNIQUE') ? 'UNIQUE ' : ''; // Extract columns from the index definition if (preg_match('/\((.+)\)$/', $def, $m)) { $cols = $m[1]; $results[] = "CREATE {$unique}INDEX IF NOT EXISTS \"{$idx->indexname}\" ON \"{$idx->tablename}\" ({$cols});"; } } return $results; } } ================================================ FILE: app/Console/Commands/Horizon.php ================================================ info('Horizon is enabled on this server.'); $this->call('horizon'); exit(0); } else { exit(0); } } } ================================================ FILE: app/Console/Commands/HorizonManage.php ================================================ option('can-i-restart-this-worker')) { return $this->isThereAJobInProgress(); } if ($this->option('job-status')) { return $this->getJobStatus($this->option('job-status')); } $action = select( label: 'What to do?', options: [ 'pending' => 'Pending Jobs', 'running' => 'Running Jobs', 'can-i-restart-this-worker' => 'Can I restart this worker?', 'job-status' => 'Job Status', 'workers' => 'Workers', 'failed' => 'Failed Jobs', 'failed-delete' => 'Failed Jobs - Delete', 'purge-queues' => 'Purge Queues', ] ); if ($action === 'can-i-restart-this-worker') { $this->isThereAJobInProgress(); } if ($action === 'job-status') { $jobId = text('Which job to check?'); $jobStatus = $this->getJobStatus($jobId); $this->info('Job Status: '.$jobStatus); } if ($action === 'pending') { $pendingJobs = app(JobRepository::class)->getPending(); $pendingJobsTable = []; if (count($pendingJobs) === 0) { $this->info('No pending jobs found.'); return; } foreach ($pendingJobs as $pendingJob) { $pendingJobsTable[] = [ 'id' => $pendingJob->id, 'name' => $pendingJob->name, 'status' => $pendingJob->status, 'reserved_at' => $pendingJob->reserved_at ? now()->parse($pendingJob->reserved_at)->format('Y-m-d H:i:s') : null, ]; } table($pendingJobsTable); } if ($action === 'failed') { $failedJobs = app(JobRepository::class)->getFailed(); $failedJobsTable = []; if (count($failedJobs) === 0) { $this->info('No failed jobs found.'); return; } foreach ($failedJobs as $failedJob) { $failedJobsTable[] = [ 'id' => $failedJob->id, 'name' => $failedJob->name, 'failed_at' => $failedJob->failed_at ? now()->parse($failedJob->failed_at)->format('Y-m-d H:i:s') : null, ]; } table($failedJobsTable); } if ($action === 'failed-delete') { $failedJobs = app(JobRepository::class)->getFailed(); $failedJobsTable = []; foreach ($failedJobs as $failedJob) { $failedJobsTable[] = [ 'id' => $failedJob->id, 'name' => $failedJob->name, 'failed_at' => $failedJob->failed_at ? now()->parse($failedJob->failed_at)->format('Y-m-d H:i:s') : null, ]; } app(MetricsRepository::class)->clear(); if (count($failedJobsTable) === 0) { $this->info('No failed jobs found.'); return; } $jobIds = multiselect( label: 'Which job to delete?', options: collect($failedJobsTable)->mapWithKeys(fn ($job) => [$job['id'] => $job['id'].' - '.$job['name']])->toArray(), ); foreach ($jobIds as $jobId) { Artisan::queue('horizon:forget', ['id' => $jobId]); } } if ($action === 'running') { $redisJobRepository = app(CustomJobRepository::class); $runningJobs = $redisJobRepository->getReservedJobs(); $runningJobsTable = []; if (count($runningJobs) === 0) { $this->info('No running jobs found.'); return; } foreach ($runningJobs as $runningJob) { $runningJobsTable[] = [ 'id' => $runningJob->id, 'name' => $runningJob->name, 'reserved_at' => $runningJob->reserved_at ? now()->parse($runningJob->reserved_at)->format('Y-m-d H:i:s') : null, ]; } table($runningJobsTable); } if ($action === 'workers') { $redisJobRepository = app(CustomJobRepository::class); $workers = $redisJobRepository->getHorizonWorkers(); $workersTable = []; foreach ($workers as $worker) { $workersTable[] = [ 'name' => $worker->name, ]; } table($workersTable); } if ($action === 'purge-queues') { $getQueues = app(CustomJobRepository::class)->getQueues(); $queueName = select( label: 'Which queue to purge?', options: $getQueues, ); $redisJobRepository = app(RedisJobRepository::class); $redisJobRepository->purge($queueName); } } public function isThereAJobInProgress() { $runningJobs = ApplicationDeploymentQueue::where('horizon_job_worker', gethostname())->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value)->get(); $count = $runningJobs->count(); if ($count === 0) { return false; } return true; } public function getJobStatus(string $jobId) { return getJobStatus($jobId); } } ================================================ FILE: app/Console/Commands/Init.php ================================================ pullTemplatesFromCDN(); } catch (\Throwable $e) { echo "Could not pull templates from CDN: {$e->getMessage()}\n"; } try { $this->pullChangelogFromGitHub(); } catch (\Throwable $e) { echo "Could not changelogs from github: {$e->getMessage()}\n"; } try { $this->pullHelperImage(); } catch (\Throwable $e) { echo "Error in pullHelperImage command: {$e->getMessage()}\n"; } if (isCloud()) { return; } $this->settings = instanceSettings(); $this->servers = Server::all(); $do_not_track = data_get($this->settings, 'do_not_track', true); if ($do_not_track == false) { $this->sendAliveSignal(); } get_public_ips(); // Backward compatibility $this->replaceSlashInEnvironmentName(); $this->restoreCoolifyDbBackup(); $this->updateUserEmails(); // $this->updateTraefikLabels(); $this->cleanupUnusedNetworkFromCoolifyProxy(); try { $this->call('cleanup:redis', ['--restart' => true, '--clear-locks' => true]); } catch (\Throwable $e) { echo "Error in cleanup:redis command: {$e->getMessage()}\n"; } try { $this->call('cleanup:names'); } catch (\Throwable $e) { echo "Error in cleanup:names command: {$e->getMessage()}\n"; } try { $this->call('cleanup:stucked-resources'); } catch (\Throwable $e) { echo "Error in cleanup:stucked-resources command: {$e->getMessage()}\n"; echo "Continuing with initialization - cleanup errors will not prevent Coolify from starting\n"; } try { $updatedCount = ApplicationDeploymentQueue::whereIn('status', [ ApplicationDeploymentStatus::IN_PROGRESS->value, ApplicationDeploymentStatus::QUEUED->value, ])->update([ 'status' => ApplicationDeploymentStatus::FAILED->value, ]); if ($updatedCount > 0) { echo "Marked {$updatedCount} stuck deployments as failed\n"; } } catch (\Throwable $e) { echo "Could not cleanup inprogress deployments: {$e->getMessage()}\n"; } try { $updatedTaskCount = ScheduledTaskExecution::where('status', 'running')->update([ 'status' => 'failed', 'message' => 'Marked as failed during Coolify startup - job was interrupted', 'finished_at' => Carbon::now(), ]); if ($updatedTaskCount > 0) { echo "Marked {$updatedTaskCount} stuck scheduled task executions as failed\n"; } } catch (\Throwable $e) { echo "Could not cleanup stuck scheduled task executions: {$e->getMessage()}\n"; } try { $updatedBackupCount = ScheduledDatabaseBackupExecution::where('status', 'running')->update([ 'status' => 'failed', 'message' => 'Marked as failed during Coolify startup - job was interrupted', 'finished_at' => Carbon::now(), ]); if ($updatedBackupCount > 0) { echo "Marked {$updatedBackupCount} stuck database backup executions as failed\n"; } } catch (\Throwable $e) { echo "Could not cleanup stuck database backup executions: {$e->getMessage()}\n"; } try { $localhost = $this->servers->where('id', 0)->first(); if ($localhost) { $localhost->setupDynamicProxyConfiguration(); } } catch (\Throwable $e) { echo "Could not setup dynamic configuration: {$e->getMessage()}\n"; } if (! is_null(config('constants.coolify.autoupdate', null))) { if (config('constants.coolify.autoupdate') == true) { echo "Enabling auto-update\n"; $this->settings->update(['is_auto_update_enabled' => true]); } else { echo "Disabling auto-update\n"; $this->settings->update(['is_auto_update_enabled' => false]); } } } private function pullHelperImage() { CheckHelperImageJob::dispatch(); } private function pullTemplatesFromCDN() { $response = Http::retry(3, 1000)->get(config('constants.services.official')); if ($response->successful()) { $services = $response->json(); File::put(base_path('templates/'.config('constants.services.file_name')), json_encode($services)); } } private function pullChangelogFromGitHub() { try { PullChangelog::dispatch(); echo "Changelog fetch initiated\n"; } catch (\Throwable $e) { echo "Could not fetch changelog from GitHub: {$e->getMessage()}\n"; } } private function updateUserEmails() { try { User::whereRaw('email ~ \'[A-Z]\'')->get()->each(function (User $user) { $user->update(['email' => $user->email]); }); } catch (\Throwable $e) { echo "Error in updating user emails: {$e->getMessage()}\n"; } } private function updateTraefikLabels() { try { Server::where('proxy->type', 'TRAEFIK_V2')->update(['proxy->type' => 'TRAEFIK']); } catch (\Throwable $e) { echo "Error in updating traefik labels: {$e->getMessage()}\n"; } } private function cleanupUnusedNetworkFromCoolifyProxy() { foreach ($this->servers as $server) { if (! $server->isFunctional()) { continue; } if (! $server->isProxyShouldRun()) { continue; } try { ['networks' => $networks, 'allNetworks' => $allNetworks] = collectDockerNetworksByServer($server); $removeNetworks = $allNetworks->diff($networks); $commands = collect(); foreach ($removeNetworks as $network) { $out = instant_remote_process(["docker network inspect -f json $network | jq '.[].Containers | if . == {} then null else . end'"], $server, false); if (empty($out)) { $commands->push("docker network disconnect $network coolify-proxy >/dev/null 2>&1 || true"); $commands->push("docker network rm $network >/dev/null 2>&1 || true"); } else { $data = collect(json_decode($out, true)); if ($data->count() === 1) { // If only coolify-proxy itself is connected to that network (it should not be possible, but who knows) $isCoolifyProxyItself = data_get($data->first(), 'Name') === 'coolify-proxy'; if ($isCoolifyProxyItself) { $commands->push("docker network disconnect $network coolify-proxy >/dev/null 2>&1 || true"); $commands->push("docker network rm $network >/dev/null 2>&1 || true"); } } } } if ($commands->isNotEmpty()) { remote_process(command: $commands, type: ActivityTypes::INLINE->value, server: $server, ignore_errors: false); } } catch (\Throwable $e) { echo "Error in cleaning up unused networks from coolify proxy: {$e->getMessage()}\n"; } } } private function restoreCoolifyDbBackup() { if (version_compare('4.0.0-beta.179', config('constants.coolify.version'), '<=')) { try { $database = StandalonePostgresql::withTrashed()->find(0); if ($database && $database->trashed()) { $database->restore(); $scheduledBackup = ScheduledDatabaseBackup::find(0); if (! $scheduledBackup) { ScheduledDatabaseBackup::create([ 'id' => 0, 'enabled' => true, 'save_s3' => false, 'frequency' => '0 0 * * *', 'database_id' => $database->id, 'database_type' => \App\Models\StandalonePostgresql::class, 'team_id' => 0, ]); } } } catch (\Throwable $e) { echo "Error in restoring coolify db backup: {$e->getMessage()}\n"; } } } private function sendAliveSignal() { $id = config('app.id'); $version = config('constants.coolify.version'); try { Http::get("https://undead.coolify.io/v4/alive?appId=$id&version=$version"); } catch (\Throwable $e) { echo "Error in sending live signal: {$e->getMessage()}\n"; } } private function replaceSlashInEnvironmentName() { if (version_compare('4.0.0-beta.298', config('constants.coolify.version'), '<=')) { $environments = Environment::all(); foreach ($environments as $environment) { if (str_contains($environment->name, '/')) { $environment->name = str_replace('/', '-', $environment->name); $environment->save(); } } } } } ================================================ FILE: app/Console/Commands/Migration.php ================================================ info('Migration is enabled on this server.'); $this->call('migrate', ['--force' => true, '--isolated' => true]); exit(0); } else { $this->info('Migration is disabled on this server.'); exit(0); } } } ================================================ FILE: app/Console/Commands/NotifyDemo.php ================================================ argument('channel'); if (blank($channel)) { $this->showHelp(); return; } } private function showHelp() { style('coolify')->color('#9333EA'); style('title-box')->apply('mt-1 px-2 py-1 bg-coolify'); render( <<<'HTML'
Coolify

Demo Notify => Send a demo notification to a given channel.

php artisan app:demo-notify {channel}

Channels:
  • email
  • discord
  • telegram
  • slack
  • pushover
HTML ); ask(<<<'HTML'
In which manner you wish a coolified notification?
HTML, ['email', 'discord', 'telegram', 'slack', 'pushover']); } } ================================================ FILE: app/Console/Commands/RootChangeEmail.php ================================================ info('You are about to change the root user\'s email.'); $email = $this->ask('Give me a new email for root user'); $this->info('Updating root email...'); try { User::find(0)->update(['email' => $email]); $this->info('Root user\'s email updated successfully.'); } catch (\Exception $e) { $this->error('Failed to update root user\'s email.'); return; } } } ================================================ FILE: app/Console/Commands/RootResetPassword.php ================================================ info('You are about to reset the root password.'); $password = password('Give me a new password for root user: '); $passwordAgain = password('Again'); if ($password != $passwordAgain) { $this->error('Passwords do not match.'); return; } $this->info('Updating root password...'); try { $user = User::find(0); if (! $user) { $this->error('Root user not found.'); return; } $user->update(['password' => Hash::make($password)]); $this->info('Root password updated successfully.'); } catch (\Exception $e) { $this->error('Failed to update root password.'); return; } } } ================================================ FILE: app/Console/Commands/RunScheduledJobsManually.php ================================================ option('type'); $frequency = $this->option('frequency'); $chunkSize = (int) $this->option('chunk'); $delay = (int) $this->option('delay'); $maxJobs = $this->option('max') ? (int) $this->option('max') : null; $dryRun = $this->option('dry-run'); $this->info('Starting manual execution of scheduled jobs...'.($dryRun ? ' (DRY RUN)' : '')); $this->info("Type: {$type}".($frequency ? ", Frequency: {$frequency}" : '').", Chunk size: {$chunkSize}, Delay: {$delay}s".($maxJobs ? ", Max jobs: {$maxJobs}" : '').($dryRun ? ', Dry run: enabled' : '')); if ($dryRun) { $this->warn('DRY RUN MODE: No jobs will actually be dispatched'); } if ($type === 'all' || $type === 'backups') { $this->runScheduledBackups($chunkSize, $delay, $maxJobs, $dryRun, $frequency); } if ($type === 'all' || $type === 'tasks') { $this->runScheduledTasks($chunkSize, $delay, $maxJobs, $dryRun, $frequency); } $this->info('Completed manual execution of scheduled jobs.'.($dryRun ? ' (DRY RUN)' : '')); } private function runScheduledBackups(int $chunkSize, int $delay, ?int $maxJobs = null, bool $dryRun = false, ?string $frequency = null): void { $this->info('Processing scheduled database backups...'); $query = ScheduledDatabaseBackup::where('enabled', true); if ($frequency) { $query->where(function ($q) use ($frequency) { // Handle human-readable frequency strings if (in_array($frequency, ['daily', 'hourly', 'weekly', 'monthly', 'yearly', 'every_minute'])) { $q->where('frequency', $frequency); } else { // Handle cron expressions $q->where('frequency', $frequency); } }); } $scheduled_backups = $query->get(); if ($scheduled_backups->isEmpty()) { $this->info('No enabled scheduled backups found'.($frequency ? " with frequency '{$frequency}'" : '').'.'); return; } $finalScheduledBackups = collect(); foreach ($scheduled_backups as $scheduled_backup) { if (blank(data_get($scheduled_backup, 'database'))) { $this->warn("Deleting backup {$scheduled_backup->id} - missing database"); $scheduled_backup->delete(); continue; } $server = $scheduled_backup->server(); if (blank($server)) { $this->warn("Deleting backup {$scheduled_backup->id} - missing server"); $scheduled_backup->delete(); continue; } if ($server->isFunctional() === false) { $this->warn("Skipping backup {$scheduled_backup->id} - server not functional"); continue; } if (isCloud() && data_get($server->team->subscription, 'stripe_invoice_paid', false) === false && $server->team->id !== 0) { $this->warn("Skipping backup {$scheduled_backup->id} - subscription not paid"); continue; } $finalScheduledBackups->push($scheduled_backup); } if ($maxJobs && $finalScheduledBackups->count() > $maxJobs) { $finalScheduledBackups = $finalScheduledBackups->take($maxJobs); $this->info("Limited to {$maxJobs} scheduled backups for testing"); } $this->info("Found {$finalScheduledBackups->count()} valid scheduled backups to process".($frequency ? " with frequency '{$frequency}'" : '')); $chunks = $finalScheduledBackups->chunk($chunkSize); foreach ($chunks as $index => $chunk) { $this->info('Processing backup batch '.($index + 1).' of '.$chunks->count()." ({$chunk->count()} items)"); foreach ($chunk as $scheduled_backup) { try { if ($dryRun) { $this->info("🔍 Would dispatch backup job for: {$scheduled_backup->name} (ID: {$scheduled_backup->id}, Frequency: {$scheduled_backup->frequency})"); } else { DatabaseBackupJob::dispatch($scheduled_backup); $this->info("✓ Dispatched backup job for: {$scheduled_backup->name} (ID: {$scheduled_backup->id}, Frequency: {$scheduled_backup->frequency})"); } } catch (\Exception $e) { $this->error("✗ Failed to dispatch backup job for {$scheduled_backup->id}: ".$e->getMessage()); Log::error('Error dispatching backup job: '.$e->getMessage()); } } if ($index < $chunks->count() - 1 && ! $dryRun) { $this->info("Waiting {$delay} seconds before next batch..."); sleep($delay); } } } private function runScheduledTasks(int $chunkSize, int $delay, ?int $maxJobs = null, bool $dryRun = false, ?string $frequency = null): void { $this->info('Processing scheduled tasks...'); $query = ScheduledTask::where('enabled', true); if ($frequency) { $query->where(function ($q) use ($frequency) { // Handle human-readable frequency strings if (in_array($frequency, ['daily', 'hourly', 'weekly', 'monthly', 'yearly', 'every_minute'])) { $q->where('frequency', $frequency); } else { // Handle cron expressions $q->where('frequency', $frequency); } }); } $scheduled_tasks = $query->get(); if ($scheduled_tasks->isEmpty()) { $this->info('No enabled scheduled tasks found'.($frequency ? " with frequency '{$frequency}'" : '').'.'); return; } $finalScheduledTasks = collect(); foreach ($scheduled_tasks as $scheduled_task) { $service = $scheduled_task->service; $application = $scheduled_task->application; $server = $scheduled_task->server(); if (blank($server)) { $this->warn("Deleting task {$scheduled_task->id} - missing server"); $scheduled_task->delete(); continue; } if ($server->isFunctional() === false) { $this->warn("Skipping task {$scheduled_task->id} - server not functional"); continue; } if (isCloud() && data_get($server->team->subscription, 'stripe_invoice_paid', false) === false && $server->team->id !== 0) { $this->warn("Skipping task {$scheduled_task->id} - subscription not paid"); continue; } if (! $service && ! $application) { $this->warn("Deleting task {$scheduled_task->id} - missing service and application"); $scheduled_task->delete(); continue; } if ($application && str($application->status)->contains('running') === false) { $this->warn("Skipping task {$scheduled_task->id} - application not running"); continue; } if ($service && str($service->status)->contains('running') === false) { $this->warn("Skipping task {$scheduled_task->id} - service not running"); continue; } $finalScheduledTasks->push($scheduled_task); } if ($maxJobs && $finalScheduledTasks->count() > $maxJobs) { $finalScheduledTasks = $finalScheduledTasks->take($maxJobs); $this->info("Limited to {$maxJobs} scheduled tasks for testing"); } $this->info("Found {$finalScheduledTasks->count()} valid scheduled tasks to process".($frequency ? " with frequency '{$frequency}'" : '')); $chunks = $finalScheduledTasks->chunk($chunkSize); foreach ($chunks as $index => $chunk) { $this->info('Processing task batch '.($index + 1).' of '.$chunks->count()." ({$chunk->count()} items)"); foreach ($chunk as $scheduled_task) { try { if ($dryRun) { $this->info("🔍 Would dispatch task job for: {$scheduled_task->name} (ID: {$scheduled_task->id}, Frequency: {$scheduled_task->frequency})"); } else { ScheduledTaskJob::dispatch($scheduled_task); $this->info("✓ Dispatched task job for: {$scheduled_task->name} (ID: {$scheduled_task->id}, Frequency: {$scheduled_task->frequency})"); } } catch (\Exception $e) { $this->error("✗ Failed to dispatch task job for {$scheduled_task->id}: ".$e->getMessage()); Log::error('Error dispatching task job: '.$e->getMessage()); } } if ($index < $chunks->count() - 1 && ! $dryRun) { $this->info("Waiting {$delay} seconds before next batch..."); sleep($delay); } } } } ================================================ FILE: app/Console/Commands/Scheduler.php ================================================ info('Scheduler is enabled on this server.'); $this->call('schedule:work'); exit(0); } else { exit(0); } } } ================================================ FILE: app/Console/Commands/Seeder.php ================================================ info('Seeder is enabled on this server.'); $this->call('db:seed', ['--class' => 'ProductionSeeder', '--force' => true]); exit(0); } else { $this->info('Seeder is disabled on this server.'); exit(0); } } } ================================================ FILE: app/Console/Commands/ServicesDelete.php ================================================ deleteApplication(); } elseif ($resource === 'Database') { $this->deleteDatabase(); } elseif ($resource === 'Service') { $this->deleteService(); } elseif ($resource === 'Server') { $this->deleteServer(); } } private function deleteServer() { $servers = Server::all(); if ($servers->count() === 0) { $this->error('There are no applications to delete.'); return; } $serversToDelete = multiselect( label: 'What server do you want to delete?', options: $servers->pluck('name', 'id')->sortKeys(), ); foreach ($serversToDelete as $server) { $toDelete = $servers->where('id', $server)->first(); if ($toDelete) { $this->info($toDelete); $confirmed = confirm('Are you sure you want to delete all selected resources?'); if (! $confirmed) { break; } $toDelete->delete(); } } } private function deleteApplication() { $applications = Application::all(); if ($applications->count() === 0) { $this->error('There are no applications to delete.'); return; } $applicationsToDelete = multiselect( 'What application do you want to delete?', $applications->pluck('name', 'id')->sortKeys(), ); foreach ($applicationsToDelete as $application) { $toDelete = $applications->where('id', $application)->first(); if ($toDelete) { $this->info($toDelete); $confirmed = confirm('Are you sure you want to delete all selected resources? '); if (! $confirmed) { break; } DeleteResourceJob::dispatch($toDelete); } } } private function deleteDatabase() { // Collect all databases from all types with unique identifiers $allDatabases = collect(); $databaseOptions = collect(); // Add PostgreSQL databases foreach (StandalonePostgresql::all() as $db) { $key = "postgresql_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (PostgreSQL)"); } // Add MySQL databases foreach (StandaloneMysql::all() as $db) { $key = "mysql_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (MySQL)"); } // Add MariaDB databases foreach (StandaloneMariadb::all() as $db) { $key = "mariadb_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (MariaDB)"); } // Add MongoDB databases foreach (StandaloneMongodb::all() as $db) { $key = "mongodb_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (MongoDB)"); } // Add Redis databases foreach (StandaloneRedis::all() as $db) { $key = "redis_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (Redis)"); } // Add KeyDB databases foreach (StandaloneKeydb::all() as $db) { $key = "keydb_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (KeyDB)"); } // Add Dragonfly databases foreach (StandaloneDragonfly::all() as $db) { $key = "dragonfly_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (Dragonfly)"); } // Add ClickHouse databases foreach (StandaloneClickhouse::all() as $db) { $key = "clickhouse_{$db->id}"; $allDatabases->put($key, $db); $databaseOptions->put($key, "{$db->name} (ClickHouse)"); } if ($allDatabases->count() === 0) { $this->error('There are no databases to delete.'); return; } $databasesToDelete = multiselect( 'What database do you want to delete?', $databaseOptions->sortKeys(), ); foreach ($databasesToDelete as $databaseKey) { $toDelete = $allDatabases->get($databaseKey); if ($toDelete) { $this->info($toDelete); $confirmed = confirm('Are you sure you want to delete all selected resources?'); if (! $confirmed) { return; } DeleteResourceJob::dispatch($toDelete); } } } private function deleteService() { $services = Service::all(); if ($services->count() === 0) { $this->error('There are no services to delete.'); return; } $servicesToDelete = multiselect( 'What service do you want to delete?', $services->pluck('name', 'id')->sortKeys(), ); foreach ($servicesToDelete as $service) { $toDelete = $services->where('id', $service)->first(); if ($toDelete) { $this->info($toDelete); $confirmed = confirm('Are you sure you want to delete all selected resources?'); if (! $confirmed) { return; } DeleteResourceJob::dispatch($toDelete); } } } } ================================================ FILE: app/Console/Commands/SyncBunny.php ================================================ info('Fetching releases from GitHub...'); try { $response = Http::timeout(30) ->get('https://api.github.com/repos/coollabsio/coolify/releases', [ 'per_page' => 30, // Fetch more releases for better changelog ]); if (! $response->successful()) { $this->error('Failed to fetch releases from GitHub: '.$response->status()); return false; } $releases = $response->json(); $timestamp = time(); $tmpDir = sys_get_temp_dir().'/coolify-cdn-'.$timestamp; $branchName = 'update-releases-'.$timestamp; // Clone the repository $this->info('Cloning coolify-cdn repository...'); $output = []; exec('gh repo clone coollabsio/coolify-cdn '.escapeshellarg($tmpDir).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to clone repository: '.implode("\n", $output)); return false; } // Create feature branch $this->info('Creating feature branch...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git checkout -b '.escapeshellarg($branchName).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to create branch: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Write releases.json $this->info('Writing releases.json...'); $releasesPath = "$tmpDir/json/releases.json"; $releasesDir = dirname($releasesPath); // Ensure directory exists if (! is_dir($releasesDir)) { $this->info("Creating directory: $releasesDir"); if (! mkdir($releasesDir, 0755, true)) { $this->error("Failed to create directory: $releasesDir"); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } } $jsonContent = json_encode($releases, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); $bytesWritten = file_put_contents($releasesPath, $jsonContent); if ($bytesWritten === false) { $this->error("Failed to write releases.json to: $releasesPath"); $this->error('Possible reasons: permission denied or disk full.'); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Stage and commit $this->info('Committing changes...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git add json/releases.json 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to stage changes: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } $this->info('Checking for changes...'); $statusOutput = []; exec('cd '.escapeshellarg($tmpDir).' && git status --porcelain json/releases.json 2>&1', $statusOutput, $returnCode); if ($returnCode !== 0) { $this->error('Failed to check repository status: '.implode("\n", $statusOutput)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } if (empty(array_filter($statusOutput))) { $this->info('Releases are already up to date. No changes to commit.'); exec('rm -rf '.escapeshellarg($tmpDir)); return true; } $commitMessage = 'Update releases.json with latest releases - '.date('Y-m-d H:i:s'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git commit -m '.escapeshellarg($commitMessage).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to commit changes: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Push to remote $this->info('Pushing branch to remote...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git push origin '.escapeshellarg($branchName).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to push branch: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Create pull request $this->info('Creating pull request...'); $prTitle = 'Update releases.json - '.date('Y-m-d H:i:s'); $prBody = 'Automated update of releases.json with latest '.count($releases).' releases from GitHub API'; $prCommand = 'gh pr create --repo coollabsio/coolify-cdn --title '.escapeshellarg($prTitle).' --body '.escapeshellarg($prBody).' --base main --head '.escapeshellarg($branchName).' 2>&1'; $output = []; exec($prCommand, $output, $returnCode); // Clean up exec('rm -rf '.escapeshellarg($tmpDir)); if ($returnCode !== 0) { $this->error('Failed to create PR: '.implode("\n", $output)); return false; } $this->info('Pull request created successfully!'); if (! empty($output)) { $this->info('PR Output: '.implode("\n", $output)); } $this->info('Total releases synced: '.count($releases)); return true; } catch (\Throwable $e) { $this->error('Error syncing releases: '.$e->getMessage()); return false; } } /** * Sync both releases.json and versions.json to GitHub repository in one PR */ private function syncReleasesAndVersionsToGitHubRepo(string $versionsLocation, bool $nightly = false): bool { $this->info('Syncing releases.json and versions.json to GitHub repository...'); try { // 1. Fetch releases from GitHub API $this->info('Fetching releases from GitHub API...'); $response = Http::timeout(30) ->get('https://api.github.com/repos/coollabsio/coolify/releases', [ 'per_page' => 30, ]); if (! $response->successful()) { $this->error('Failed to fetch releases from GitHub: '.$response->status()); return false; } $releases = $response->json(); // 2. Read versions.json if (! file_exists($versionsLocation)) { $this->error("versions.json not found at: $versionsLocation"); return false; } $file = file_get_contents($versionsLocation); $versionsJson = json_decode($file, true); $actualVersion = data_get($versionsJson, 'coolify.v4.version'); $timestamp = time(); $tmpDir = sys_get_temp_dir().'/coolify-cdn-combined-'.$timestamp; $branchName = 'update-releases-and-versions-'.$timestamp; $versionsTargetPath = $nightly ? 'json/versions-nightly.json' : 'json/versions.json'; // 3. Clone the repository $this->info('Cloning coolify-cdn repository...'); $output = []; exec('gh repo clone coollabsio/coolify-cdn '.escapeshellarg($tmpDir).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to clone repository: '.implode("\n", $output)); return false; } // 4. Create feature branch $this->info('Creating feature branch...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git checkout -b '.escapeshellarg($branchName).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to create branch: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // 5. Write releases.json $this->info('Writing releases.json...'); $releasesPath = "$tmpDir/json/releases.json"; $releasesDir = dirname($releasesPath); if (! is_dir($releasesDir)) { if (! mkdir($releasesDir, 0755, true)) { $this->error("Failed to create directory: $releasesDir"); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } } $releasesJsonContent = json_encode($releases, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); if (file_put_contents($releasesPath, $releasesJsonContent) === false) { $this->error("Failed to write releases.json to: $releasesPath"); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // 6. Write versions.json $this->info('Writing versions.json...'); $versionsPath = "$tmpDir/$versionsTargetPath"; $versionsDir = dirname($versionsPath); if (! is_dir($versionsDir)) { if (! mkdir($versionsDir, 0755, true)) { $this->error("Failed to create directory: $versionsDir"); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } } $versionsJsonContent = json_encode($versionsJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); if (file_put_contents($versionsPath, $versionsJsonContent) === false) { $this->error("Failed to write versions.json to: $versionsPath"); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // 7. Stage both files $this->info('Staging changes...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git add json/releases.json '.escapeshellarg($versionsTargetPath).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to stage changes: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // 8. Check for changes $this->info('Checking for changes...'); $statusOutput = []; exec('cd '.escapeshellarg($tmpDir).' && git status --porcelain 2>&1', $statusOutput, $returnCode); if ($returnCode !== 0) { $this->error('Failed to check repository status: '.implode("\n", $statusOutput)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } if (empty(array_filter($statusOutput))) { $this->info('Both files are already up to date. No changes to commit.'); exec('rm -rf '.escapeshellarg($tmpDir)); return true; } // 9. Commit changes $envLabel = $nightly ? 'NIGHTLY' : 'PRODUCTION'; $commitMessage = "Update releases.json and $envLabel versions.json to $actualVersion - ".date('Y-m-d H:i:s'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git commit -m '.escapeshellarg($commitMessage).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to commit changes: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // 10. Push to remote $this->info('Pushing branch to remote...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git push origin '.escapeshellarg($branchName).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to push branch: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // 11. Create pull request $this->info('Creating pull request...'); $prTitle = "Update releases.json and $envLabel versions.json to $actualVersion - ".date('Y-m-d H:i:s'); $prBody = "Automated update:\n- releases.json with latest ".count($releases)." releases from GitHub API\n- $envLabel versions.json to version $actualVersion"; $prCommand = 'gh pr create --repo coollabsio/coolify-cdn --title '.escapeshellarg($prTitle).' --body '.escapeshellarg($prBody).' --base main --head '.escapeshellarg($branchName).' 2>&1'; $output = []; exec($prCommand, $output, $returnCode); // 12. Clean up exec('rm -rf '.escapeshellarg($tmpDir)); if ($returnCode !== 0) { $this->error('Failed to create PR: '.implode("\n", $output)); return false; } $this->info('Pull request created successfully!'); if (! empty($output)) { $this->info('PR URL: '.implode("\n", $output)); } $this->info("Version synced: $actualVersion"); $this->info('Total releases synced: '.count($releases)); return true; } catch (\Throwable $e) { $this->error('Error syncing to GitHub: '.$e->getMessage()); return false; } } /** * Sync versions.json to GitHub repository via PR */ private function syncVersionsToGitHubRepo(string $versionsLocation, bool $nightly = false): bool { $this->info('Syncing versions.json to GitHub repository...'); try { if (! file_exists($versionsLocation)) { $this->error("versions.json not found at: $versionsLocation"); return false; } $file = file_get_contents($versionsLocation); $json = json_decode($file, true); $actualVersion = data_get($json, 'coolify.v4.version'); $timestamp = time(); $tmpDir = sys_get_temp_dir().'/coolify-cdn-versions-'.$timestamp; $branchName = 'update-versions-'.$timestamp; $targetPath = $nightly ? 'json/versions-nightly.json' : 'json/versions.json'; // Clone the repository $this->info('Cloning coolify-cdn repository...'); exec('gh repo clone coollabsio/coolify-cdn '.escapeshellarg($tmpDir).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to clone repository: '.implode("\n", $output)); return false; } // Create feature branch $this->info('Creating feature branch...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git checkout -b '.escapeshellarg($branchName).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to create branch: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Write versions.json $this->info('Writing versions.json...'); $versionsPath = "$tmpDir/$targetPath"; $versionsDir = dirname($versionsPath); // Ensure directory exists if (! is_dir($versionsDir)) { $this->info("Creating directory: $versionsDir"); if (! mkdir($versionsDir, 0755, true)) { $this->error("Failed to create directory: $versionsDir"); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } } $jsonContent = json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); $bytesWritten = file_put_contents($versionsPath, $jsonContent); if ($bytesWritten === false) { $this->error("Failed to write versions.json to: $versionsPath"); $this->error('Possible reasons: permission denied or disk full.'); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Stage and commit $this->info('Committing changes...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git add '.escapeshellarg($targetPath).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to stage changes: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } $this->info('Checking for changes...'); $statusOutput = []; exec('cd '.escapeshellarg($tmpDir).' && git status --porcelain '.escapeshellarg($targetPath).' 2>&1', $statusOutput, $returnCode); if ($returnCode !== 0) { $this->error('Failed to check repository status: '.implode("\n", $statusOutput)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } if (empty(array_filter($statusOutput))) { $this->info('versions.json is already up to date. No changes to commit.'); exec('rm -rf '.escapeshellarg($tmpDir)); return true; } $envLabel = $nightly ? 'NIGHTLY' : 'PRODUCTION'; $commitMessage = "Update $envLabel versions.json to $actualVersion - ".date('Y-m-d H:i:s'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git commit -m '.escapeshellarg($commitMessage).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to commit changes: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Push to remote $this->info('Pushing branch to remote...'); $output = []; exec('cd '.escapeshellarg($tmpDir).' && git push origin '.escapeshellarg($branchName).' 2>&1', $output, $returnCode); if ($returnCode !== 0) { $this->error('Failed to push branch: '.implode("\n", $output)); exec('rm -rf '.escapeshellarg($tmpDir)); return false; } // Create pull request $this->info('Creating pull request...'); $prTitle = "Update $envLabel versions.json to $actualVersion - ".date('Y-m-d H:i:s'); $prBody = "Automated update of $envLabel versions.json to version $actualVersion"; $output = []; $prCommand = 'gh pr create --repo coollabsio/coolify-cdn --title '.escapeshellarg($prTitle).' --body '.escapeshellarg($prBody).' --base main --head '.escapeshellarg($branchName).' 2>&1'; exec($prCommand, $output, $returnCode); // Clean up exec('rm -rf '.escapeshellarg($tmpDir)); if ($returnCode !== 0) { $this->error('Failed to create PR: '.implode("\n", $output)); return false; } $this->info('Pull request created successfully!'); if (! empty($output)) { $this->info('PR URL: '.implode("\n", $output)); } $this->info("Version synced: $actualVersion"); return true; } catch (\Throwable $e) { $this->error('Error syncing versions.json: '.$e->getMessage()); return false; } } /** * Execute the console command. */ public function handle() { $that = $this; $only_template = $this->option('templates'); $only_version = $this->option('release'); $only_github_releases = $this->option('github-releases'); $only_github_versions = $this->option('github-versions'); $nightly = $this->option('nightly'); $bunny_cdn = 'https://cdn.coollabs.io'; $bunny_cdn_path = 'coolify'; $bunny_cdn_storage_name = 'coolcdn'; $parent_dir = realpath(dirname(__FILE__).'/../../..'); $compose_file = 'docker-compose.yml'; $compose_file_prod = 'docker-compose.prod.yml'; $install_script = 'install.sh'; $upgrade_script = 'upgrade.sh'; $production_env = '.env.production'; $service_template = config('constants.services.file_name'); $versions = 'versions.json'; $compose_file_location = "$parent_dir/$compose_file"; $compose_file_prod_location = "$parent_dir/$compose_file_prod"; $install_script_location = "$parent_dir/scripts/install.sh"; $upgrade_script_location = "$parent_dir/scripts/upgrade.sh"; $production_env_location = "$parent_dir/.env.production"; $versions_location = "$parent_dir/$versions"; PendingRequest::macro('storage', function ($fileName) use ($that) { $headers = [ 'AccessKey' => config('constants.bunny.storage_api_key'), 'Accept' => 'application/json', 'Content-Type' => 'application/octet-stream', ]; $fileStream = fopen($fileName, 'r'); $file = fread($fileStream, filesize($fileName)); $that->info('Uploading: '.$fileName); return PendingRequest::baseUrl('https://storage.bunnycdn.com')->withHeaders($headers)->withBody($file)->throw(); }); PendingRequest::macro('purge', function ($url) use ($that) { $headers = [ 'AccessKey' => config('constants.bunny.api_key'), 'Accept' => 'application/json', ]; $that->info('Purging: '.$url); return PendingRequest::withHeaders($headers)->get('https://api.bunny.net/purge', [ 'url' => $url, 'async' => false, ]); }); try { if ($nightly) { $bunny_cdn_path = 'coolify-nightly'; $compose_file_location = "$parent_dir/other/nightly/$compose_file"; $compose_file_prod_location = "$parent_dir/other/nightly/$compose_file_prod"; $production_env_location = "$parent_dir/other/nightly/$production_env"; $upgrade_script_location = "$parent_dir/other/nightly/$upgrade_script"; $install_script_location = "$parent_dir/other/nightly/$install_script"; $versions_location = "$parent_dir/other/nightly/$versions"; } if (! $only_template && ! $only_version && ! $only_github_releases && ! $only_github_versions) { if ($nightly) { $this->info('About to sync files NIGHTLY (docker-compose.prod.yaml, upgrade.sh, install.sh, etc) to BunnyCDN.'); } else { $this->info('About to sync files PRODUCTION (docker-compose.yml, docker-compose.prod.yml, upgrade.sh, install.sh, etc) to BunnyCDN.'); } $confirmed = confirm('Are you sure you want to sync?'); if (! $confirmed) { return; } } if ($only_template) { $this->info('About to sync '.config('constants.services.file_name').' to BunnyCDN.'); $confirmed = confirm('Are you sure you want to sync?'); if (! $confirmed) { return; } Http::pool(fn (Pool $pool) => [ $pool->storage(fileName: "$parent_dir/templates/$service_template")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$service_template"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$service_template"), ]); $this->info('Service template uploaded & purged...'); return; } elseif ($only_version) { if ($nightly) { $this->info('About to sync NIGHTLY versions.json to BunnyCDN and create GitHub PR.'); } else { $this->info('About to sync PRODUCTION versions.json to BunnyCDN and create GitHub PR.'); } $file = file_get_contents($versions_location); $json = json_decode($file, true); $actual_version = data_get($json, 'coolify.v4.version'); $this->info("Version: {$actual_version}"); $this->info('This will:'); $this->info(' 1. Sync versions.json to BunnyCDN (deprecated but still supported)'); $this->info(' 2. Create ONE GitHub PR with both releases.json and versions.json'); $this->newLine(); $confirmed = confirm('Are you sure you want to proceed?'); if (! $confirmed) { return; } // 1. Sync versions.json to BunnyCDN (deprecated but still needed) $this->info('Step 1/2: Syncing versions.json to BunnyCDN...'); Http::pool(fn (Pool $pool) => [ $pool->storage(fileName: $versions_location)->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$versions"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"), ]); $this->info('✓ versions.json uploaded & purged to BunnyCDN'); $this->newLine(); // 2. Create GitHub PR with both releases.json and versions.json $this->info('Step 2/2: Creating GitHub PR with releases.json and versions.json...'); $githubSuccess = $this->syncReleasesAndVersionsToGitHubRepo($versions_location, $nightly); if ($githubSuccess) { $this->info('✓ GitHub PR created successfully with both files'); } else { $this->error('✗ Failed to create GitHub PR'); } $this->newLine(); $this->info('=== Summary ==='); $this->info('BunnyCDN sync: ✓ Complete'); $this->info('GitHub PR: '.($githubSuccess ? '✓ Created (releases.json + versions.json)' : '✗ Failed')); return; } elseif ($only_github_releases) { $this->info('About to sync GitHub releases to GitHub repository.'); $confirmed = confirm('Are you sure you want to sync GitHub releases?'); if (! $confirmed) { return; } // Sync releases to GitHub repository $this->syncReleasesToGitHubRepo(); return; } elseif ($only_github_versions) { $envLabel = $nightly ? 'NIGHTLY' : 'PRODUCTION'; $file = file_get_contents($versions_location); $json = json_decode($file, true); $actual_version = data_get($json, 'coolify.v4.version'); $this->info("About to sync $envLabel versions.json ($actual_version) to GitHub repository."); $confirmed = confirm('Are you sure you want to sync versions.json via GitHub PR?'); if (! $confirmed) { return; } // Sync versions.json to GitHub repository $this->syncVersionsToGitHubRepo($versions_location, $nightly); return; } Http::pool(fn (Pool $pool) => [ $pool->storage(fileName: "$compose_file_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file"), $pool->storage(fileName: "$compose_file_prod_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file_prod"), $pool->storage(fileName: "$production_env_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$production_env"), $pool->storage(fileName: "$upgrade_script_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$upgrade_script"), $pool->storage(fileName: "$install_script_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$install_script"), ]); Http::pool(fn (Pool $pool) => [ $pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file_prod"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$production_env"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$upgrade_script"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$install_script"), ]); $this->info('All files uploaded & purged...'); } catch (\Throwable $e) { $this->error('Error: '.$e->getMessage()); } } } ================================================ FILE: app/Console/Commands/UpdateServiceVersions.php ================================================ 0, 'updated' => 0, 'failed' => 0, 'skipped' => 0, ]; protected array $registryCache = []; protected array $majorVersionUpdates = []; public function handle(): int { $this->info('Starting service version update...'); $templateFiles = $this->getTemplateFiles(); $this->stats['total'] = count($templateFiles); foreach ($templateFiles as $file) { $this->processTemplate($file); } $this->newLine(); $this->displayStats(); return self::SUCCESS; } protected function getTemplateFiles(): array { $pattern = base_path('templates/compose/*.yaml'); $files = glob($pattern); if ($service = $this->option('service')) { $files = array_filter($files, fn ($file) => basename($file) === "$service.yaml"); } return $files; } protected function processTemplate(string $filePath): void { $filename = basename($filePath); $this->info("Processing: {$filename}"); try { $content = file_get_contents($filePath); $yaml = Yaml::parse($content); if (! isset($yaml['services'])) { $this->warn(" No services found in {$filename}"); $this->stats['skipped']++; return; } $updated = false; $updatedYaml = $yaml; foreach ($yaml['services'] as $serviceName => $serviceConfig) { if (! isset($serviceConfig['image'])) { continue; } $currentImage = $serviceConfig['image']; // Check if using 'latest' tag and log for manual review if (str_contains($currentImage, ':latest')) { $registryUrl = $this->getRegistryUrl($currentImage); $this->warn(" {$serviceName}: {$currentImage} (using 'latest' tag)"); if ($registryUrl) { $this->line(" → Manual review: {$registryUrl}"); } } $latestVersion = $this->getLatestVersion($currentImage); if ($latestVersion && $latestVersion !== $currentImage) { $this->line(" {$serviceName}: {$currentImage} → {$latestVersion}"); $updatedYaml['services'][$serviceName]['image'] = $latestVersion; $updated = true; } else { $this->line(" {$serviceName}: {$currentImage} (up to date)"); } } if ($updated) { if (! $this->option('dry-run')) { $this->updateYamlFile($filePath, $content, $updatedYaml); $this->stats['updated']++; } else { $this->warn(' [DRY RUN] Would update this file'); $this->stats['updated']++; } } else { $this->stats['skipped']++; } } catch (\Throwable $e) { $this->error(" Failed: {$e->getMessage()}"); $this->stats['failed']++; } $this->newLine(); } protected function getLatestVersion(string $image): ?string { // Parse the image string [$repository, $currentTag] = $this->parseImage($image); // Determine registry and fetch latest version $result = null; if (str_starts_with($repository, 'ghcr.io/')) { $result = $this->getGhcrLatestVersion($repository, $currentTag); } elseif (str_starts_with($repository, 'quay.io/')) { $result = $this->getQuayLatestVersion($repository, $currentTag); } elseif (str_starts_with($repository, 'codeberg.org/')) { $result = $this->getCodebergLatestVersion($repository, $currentTag); } elseif (str_starts_with($repository, 'lscr.io/')) { $result = $this->getDockerHubLatestVersion($repository, $currentTag); } elseif ($this->isCustomRegistry($repository)) { // Custom registries - skip for now, log warning $this->warn(" Skipping custom registry: {$repository}"); $result = null; } else { // DockerHub (default registry - no prefix or docker.io/index.docker.io) $result = $this->getDockerHubLatestVersion($repository, $currentTag); } return $result; } protected function isCustomRegistry(string $repository): bool { // List of custom/private registries that we can't query $customRegistries = [ 'docker.elastic.co/', 'docker.n8n.io/', 'docker.flipt.io/', 'docker.getoutline.com/', 'cr.weaviate.io/', 'downloads.unstructured.io/', 'budibase.docker.scarf.sh/', 'calcom.docker.scarf.sh/', 'code.forgejo.org/', 'registry.supertokens.io/', 'registry.rocket.chat/', 'nabo.codimd.dev/', 'gcr.io/', ]; foreach ($customRegistries as $registry) { if (str_starts_with($repository, $registry)) { return true; } } return false; } protected function getRegistryUrl(string $image): ?string { [$repository] = $this->parseImage($image); // GitHub Container Registry if (str_starts_with($repository, 'ghcr.io/')) { $parts = explode('/', str_replace('ghcr.io/', '', $repository)); if (count($parts) >= 2) { return "https://github.com/{$parts[0]}/{$parts[1]}/pkgs/container/{$parts[1]}"; } } // Quay.io if (str_starts_with($repository, 'quay.io/')) { $repo = str_replace('quay.io/', '', $repository); return "https://quay.io/repository/{$repo}?tab=tags"; } // Codeberg if (str_starts_with($repository, 'codeberg.org/')) { $parts = explode('/', str_replace('codeberg.org/', '', $repository)); if (count($parts) >= 2) { return "https://codeberg.org/{$parts[0]}/-/packages/container/{$parts[1]}"; } } // Docker Hub $cleanRepo = str_replace(['index.docker.io/', 'docker.io/', 'lscr.io/'], '', $repository); if (! str_contains($cleanRepo, '/')) { // Official image return "https://hub.docker.com/_/{$cleanRepo}/tags"; } else { // User/org image return "https://hub.docker.com/r/{$cleanRepo}/tags"; } } protected function parseImage(string $image): array { if (str_contains($image, ':')) { [$repo, $tag] = explode(':', $image, 2); } else { $repo = $image; $tag = 'latest'; } // Handle variables in tags if (str_contains($tag, '$')) { $tag = 'latest'; // Default to latest for variable tags } return [$repo, $tag]; } protected function getDockerHubLatestVersion(string $repository, string $currentTag): ?string { try { // Check if we've already fetched tags for this repository if (! isset($this->registryCache[$repository.'_tags'])) { // Remove various registry prefixes $cleanRepo = $repository; $cleanRepo = str_replace('index.docker.io/', '', $cleanRepo); $cleanRepo = str_replace('docker.io/', '', $cleanRepo); $cleanRepo = str_replace('lscr.io/', '', $cleanRepo); // For official images (no /) add library prefix if (! str_contains($cleanRepo, '/')) { $cleanRepo = "library/{$cleanRepo}"; } $url = "https://hub.docker.com/v2/repositories/{$cleanRepo}/tags"; $response = Http::timeout(10)->get($url, [ 'page_size' => 100, 'ordering' => 'last_updated', ]); if (! $response->successful()) { return null; } $data = $response->json(); $tags = $data['results'] ?? []; // Cache the tags for this repository $this->registryCache[$repository.'_tags'] = $tags; } else { $this->line(" [cached] Using cached tags for {$repository}"); $tags = $this->registryCache[$repository.'_tags']; } // Find the best matching tag return $this->findBestTag($tags, $currentTag, $repository); } catch (\Throwable $e) { $this->warn(" DockerHub API error for {$repository}: {$e->getMessage()}"); return null; } } protected function findLatestTagDigest(array $tags, string $targetTag = 'latest'): ?string { // Find the digest/sha for the target tag (usually 'latest') foreach ($tags as $tag) { if ($tag['name'] === $targetTag) { return $tag['digest'] ?? $tag['images'][0]['digest'] ?? null; } } return null; } protected function findVersionTagsForDigest(array $tags, string $digest): array { // Find all semantic version tags that share the same digest $versionTags = []; foreach ($tags as $tag) { $tagDigest = $tag['digest'] ?? $tag['images'][0]['digest'] ?? null; if ($tagDigest === $digest) { $tagName = $tag['name']; // Only include semantic version tags if (preg_match('/^\d+\.\d+(\.\d+)?$/', $tagName)) { $versionTags[] = $tagName; } } } return $versionTags; } protected function getGhcrLatestVersion(string $repository, string $currentTag): ?string { try { // GHCR doesn't have a public API for listing tags without auth // We'll try to fetch the package metadata via GitHub API $parts = explode('/', str_replace('ghcr.io/', '', $repository)); if (count($parts) < 2) { return null; } $owner = $parts[0]; $package = $parts[1]; // Try GitHub Container Registry API $url = "https://api.github.com/users/{$owner}/packages/container/{$package}/versions"; $response = Http::timeout(10) ->withHeaders([ 'Accept' => 'application/vnd.github.v3+json', ]) ->get($url, ['per_page' => 100]); if (! $response->successful()) { // Most GHCR packages require authentication if ($currentTag === 'latest') { $this->warn(' ⚠ GHCR requires authentication - manual review needed'); } return null; } $versions = $response->json(); $tags = []; // Build tags array with digest information foreach ($versions as $version) { $digest = $version['name'] ?? null; // This is the SHA digest if (isset($version['metadata']['container']['tags'])) { foreach ($version['metadata']['container']['tags'] as $tag) { $tags[] = [ 'name' => $tag, 'digest' => $digest, ]; } } } return $this->findBestTag($tags, $currentTag, $repository); } catch (\Throwable $e) { $this->warn(" GHCR API error for {$repository}: {$e->getMessage()}"); return null; } } protected function getQuayLatestVersion(string $repository, string $currentTag): ?string { try { // Check if we've already fetched tags for this repository if (! isset($this->registryCache[$repository.'_tags'])) { $cleanRepo = str_replace('quay.io/', '', $repository); $url = "https://quay.io/api/v1/repository/{$cleanRepo}/tag/"; $response = Http::timeout(10)->get($url, ['limit' => 100]); if (! $response->successful()) { return null; } $data = $response->json(); $tags = array_map(fn ($tag) => ['name' => $tag['name']], $data['tags'] ?? []); // Cache the tags for this repository $this->registryCache[$repository.'_tags'] = $tags; } else { $this->line(" [cached] Using cached tags for {$repository}"); $tags = $this->registryCache[$repository.'_tags']; } return $this->findBestTag($tags, $currentTag, $repository); } catch (\Throwable $e) { $this->warn(" Quay API error for {$repository}: {$e->getMessage()}"); return null; } } protected function getCodebergLatestVersion(string $repository, string $currentTag): ?string { try { // Check if we've already fetched tags for this repository if (! isset($this->registryCache[$repository.'_tags'])) { // Codeberg uses Forgejo/Gitea, which has a container registry API $cleanRepo = str_replace('codeberg.org/', '', $repository); $parts = explode('/', $cleanRepo); if (count($parts) < 2) { return null; } $owner = $parts[0]; $package = $parts[1]; // Codeberg API endpoint for packages $url = "https://codeberg.org/api/packages/{$owner}/container/{$package}"; $response = Http::timeout(10)->get($url); if (! $response->successful()) { return null; } $data = $response->json(); $tags = []; if (isset($data['versions'])) { foreach ($data['versions'] as $version) { if (isset($version['name'])) { $tags[] = ['name' => $version['name']]; } } } // Cache the tags for this repository $this->registryCache[$repository.'_tags'] = $tags; } else { $this->line(" [cached] Using cached tags for {$repository}"); $tags = $this->registryCache[$repository.'_tags']; } return $this->findBestTag($tags, $currentTag, $repository); } catch (\Throwable $e) { $this->warn(" Codeberg API error for {$repository}: {$e->getMessage()}"); return null; } } protected function findBestTag(array $tags, string $currentTag, string $repository): ?string { if (empty($tags)) { return null; } // If current tag is 'latest', find what version it actually points to if ($currentTag === 'latest') { // First, try to find the digest for 'latest' tag $latestDigest = $this->findLatestTagDigest($tags, 'latest'); if ($latestDigest) { // Find all semantic version tags that share the same digest $versionTags = $this->findVersionTagsForDigest($tags, $latestDigest); if (! empty($versionTags)) { // Prefer shorter version tags (1.8 over 1.8.1) $bestVersion = $this->preferShorterVersion($versionTags); $this->info(" ✓ Found 'latest' points to: {$bestVersion}"); return $repository.':'.$bestVersion; } } // Fallback: get the latest semantic version available (prefer shorter) $semverTags = $this->filterSemanticVersionTags($tags); if (! empty($semverTags)) { $bestVersion = $this->preferShorterVersion($semverTags); return $repository.':'.$bestVersion; } // If no semantic versions found, keep 'latest' return null; } // Check for major version updates for reporting $this->checkForMajorVersionUpdate($tags, $currentTag, $repository); // If current tag is a major version (e.g., "8", "5", "16") if (preg_match('/^\d+$/', $currentTag)) { $majorVersion = (int) $currentTag; $matchingTags = array_filter($tags, function ($tag) use ($majorVersion) { $name = $tag['name']; // Match tags that start with the major version return preg_match("/^{$majorVersion}(\.\d+)?(\.\d+)?$/", $name); }); if (! empty($matchingTags)) { $versions = array_column($matchingTags, 'name'); $bestVersion = $this->preferShorterVersion($versions); if ($bestVersion !== $currentTag) { return $repository.':'.$bestVersion; } } } // If current tag is date-based version (e.g., "2025.06.02-sha-xxx") if (preg_match('/^\d{4}\.\d{2}\.\d{2}/', $currentTag)) { // Get all date-based tags $dateTags = array_filter($tags, function ($tag) { return preg_match('/^\d{4}\.\d{2}\.\d{2}/', $tag['name']); }); if (! empty($dateTags)) { $versions = array_column($dateTags, 'name'); $sorted = $this->sortSemanticVersions($versions); $latestDate = $sorted[0]; // Compare dates if ($latestDate !== $currentTag) { return $repository.':'.$latestDate; } } return null; } // If current tag is semantic version (e.g., "1.7.4", "8.0") if (preg_match('/^\d+\.\d+(\.\d+)?$/', $currentTag)) { $parts = explode('.', $currentTag); $majorMinor = $parts[0].'.'.$parts[1]; $matchingTags = array_filter($tags, function ($tag) use ($majorMinor) { $name = $tag['name']; return str_starts_with($name, $majorMinor); }); if (! empty($matchingTags)) { $versions = array_column($matchingTags, 'name'); $bestVersion = $this->preferShorterVersion($versions); if (version_compare($bestVersion, $currentTag, '>') || version_compare($bestVersion, $currentTag, '=')) { // Only update if it's newer or if we can simplify (1.8.1 -> 1.8) if ($bestVersion !== $currentTag) { return $repository.':'.$bestVersion; } } } } // If current tag is a named version (e.g., "stable") if (in_array($currentTag, ['stable', 'lts', 'edge'])) { // Check if the same tag exists in the list (it's up to date) $exists = array_filter($tags, fn ($tag) => $tag['name'] === $currentTag); if (! empty($exists)) { return null; // Tag exists and is current } } return null; } protected function filterSemanticVersionTags(array $tags): array { $semverTags = array_filter($tags, function ($tag) { $name = $tag['name']; // Accept semantic versions (1.2.3, v1.2.3) if (preg_match('/^v?\d+\.\d+(\.\d+)?(\.\d+)?$/', $name)) { // Exclude versions with suffixes like -rc, -beta, -alpha if (preg_match('/-(rc|beta|alpha|dev|test|pre|snapshot)/i', $name)) { return false; } return true; } // Accept date-based versions (2025.06.02, 2025.10.0, 2025.06.02-sha-xxx, RELEASE.2025-10-15T17-29-55Z) if (preg_match('/^\d{4}\.\d{2}\.(\d{2}|\d)/', $name) || preg_match('/^RELEASE\.\d{4}-\d{2}-\d{2}/', $name)) { return true; } return false; }); return $this->sortSemanticVersions(array_column($semverTags, 'name')); } protected function sortSemanticVersions(array $versions): array { usort($versions, function ($a, $b) { // Check if these are date-based versions (YYYY.MM.DD or YYYY.MM.D format) $isDateA = preg_match('/^(\d{4})\.(\d{2})\.(\d{1,2})/', $a, $matchesA); $isDateB = preg_match('/^(\d{4})\.(\d{2})\.(\d{1,2})/', $b, $matchesB); if ($isDateA && $isDateB) { // Both are date-based (YYYY.MM.DD), compare as dates $dateA = $matchesA[1].$matchesA[2].str_pad($matchesA[3], 2, '0', STR_PAD_LEFT); // YYYYMMDD $dateB = $matchesB[1].$matchesB[2].str_pad($matchesB[3], 2, '0', STR_PAD_LEFT); // YYYYMMDD return strcmp($dateB, $dateA); // Descending order (newest first) } // Check if these are RELEASE date versions (RELEASE.YYYY-MM-DDTHH-MM-SSZ) $isReleaseA = preg_match('/^RELEASE\.(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})Z/', $a, $matchesA); $isReleaseB = preg_match('/^RELEASE\.(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})Z/', $b, $matchesB); if ($isReleaseA && $isReleaseB) { // Both are RELEASE format, compare as datetime $dateTimeA = $matchesA[1].$matchesA[2].$matchesA[3].$matchesA[4].$matchesA[5].$matchesA[6]; // YYYYMMDDHHMMSS $dateTimeB = $matchesB[1].$matchesB[2].$matchesB[3].$matchesB[4].$matchesB[5].$matchesB[6]; // YYYYMMDDHHMMSS return strcmp($dateTimeB, $dateTimeA); // Descending order (newest first) } // Strip 'v' prefix for version comparison $cleanA = ltrim($a, 'v'); $cleanB = ltrim($b, 'v'); // Fall back to semantic version comparison return version_compare($cleanB, $cleanA); // Descending order }); return $versions; } protected function preferShorterVersion(array $versions): string { if (empty($versions)) { return ''; } // Sort by version (highest first) $sorted = $this->sortSemanticVersions($versions); $highest = $sorted[0]; // Parse the highest version $parts = explode('.', $highest); // Look for shorter versions that match // Priority: major (8) > major.minor (8.0) > major.minor.patch (8.0.39) // Try to find just major.minor (e.g., 1.8 instead of 1.8.1) if (count($parts) === 3) { $majorMinor = $parts[0].'.'.$parts[1]; if (in_array($majorMinor, $versions)) { return $majorMinor; } } // Try to find just major (e.g., 8 instead of 8.0.39) if (count($parts) >= 2) { $major = $parts[0]; if (in_array($major, $versions)) { return $major; } } // Return the highest version we found return $highest; } protected function updateYamlFile(string $filePath, string $originalContent, array $updatedYaml): void { // Preserve comments and formatting by updating the YAML content $lines = explode("\n", $originalContent); $updatedLines = []; $inServices = false; $currentService = null; foreach ($lines as $line) { // Detect if we're in the services section if (preg_match('/^services:/', $line)) { $inServices = true; $updatedLines[] = $line; continue; } // Detect service name (allow hyphens and underscores) if ($inServices && preg_match('/^ ([\w-]+):/', $line, $matches)) { $currentService = $matches[1]; $updatedLines[] = $line; continue; } // Update image line if ($currentService && preg_match('/^(\s+)image:\s*(.+)$/', $line, $matches)) { $indent = $matches[1]; $newImage = $updatedYaml['services'][$currentService]['image'] ?? $matches[2]; $updatedLines[] = "{$indent}image: {$newImage}"; continue; } // If we hit a non-indented line, we're out of services if ($inServices && preg_match('/^\S/', $line) && ! preg_match('/^services:/', $line)) { $inServices = false; $currentService = null; } $updatedLines[] = $line; } file_put_contents($filePath, implode("\n", $updatedLines)); } protected function checkForMajorVersionUpdate(array $tags, string $currentTag, string $repository): void { // Only check semantic versions if (! preg_match('/^v?(\d+)\./', $currentTag, $currentMatches)) { return; } $currentMajor = (int) $currentMatches[1]; // Get all semantic version tags $semverTags = $this->filterSemanticVersionTags($tags); // Find the highest major version available $highestMajor = $currentMajor; foreach ($semverTags as $version) { if (preg_match('/^v?(\d+)\./', $version, $matches)) { $major = (int) $matches[1]; if ($major > $highestMajor) { $highestMajor = $major; } } } // If there's a higher major version available, record it if ($highestMajor > $currentMajor) { $this->majorVersionUpdates[] = [ 'repository' => $repository, 'current' => $currentTag, 'current_major' => $currentMajor, 'available_major' => $highestMajor, 'registry_url' => $this->getRegistryUrl($repository.':'.$currentTag), ]; } } protected function displayStats(): void { $this->info('Summary:'); $this->table( ['Metric', 'Count'], [ ['Total Templates', $this->stats['total']], ['Updated', $this->stats['updated']], ['Skipped (up to date)', $this->stats['skipped']], ['Failed', $this->stats['failed']], ] ); // Display major version updates if any if (! empty($this->majorVersionUpdates)) { $this->newLine(); $this->warn('⚠ Services with available MAJOR version updates:'); $this->newLine(); $tableData = []; foreach ($this->majorVersionUpdates as $update) { $tableData[] = [ $update['repository'], "v{$update['current_major']}.x", "v{$update['available_major']}.x", $update['registry_url'], ]; } $this->table( ['Repository', 'Current', 'Available', 'Registry URL'], $tableData ); $this->newLine(); $this->comment('💡 Major version updates may include breaking changes. Review before upgrading.'); } } } ================================================ FILE: app/Console/Commands/ViewScheduledLogs.php ================================================ option('date') ?: now()->format('Y-m-d'); $logPaths = $this->getLogPaths($date); if (empty($logPaths)) { $this->showAvailableLogFiles($date); return; } $lines = $this->option('lines'); $follow = $this->option('follow'); // Build grep filters $filters = $this->buildFilters(); $filterDescription = $this->getFilterDescription(); $logTypeDescription = $this->getLogTypeDescription(); if ($follow) { $this->info("Following {$logTypeDescription} logs for {$date}{$filterDescription} (Press Ctrl+C to stop)..."); $this->line(''); if (count($logPaths) === 1) { $logPath = $logPaths[0]; if ($filters) { passthru("tail -f {$logPath} | grep -E '{$filters}'"); } else { passthru("tail -f {$logPath}"); } } else { // Multiple files - use multitail or tail with process substitution $logPathsStr = implode(' ', $logPaths); if ($filters) { passthru("tail -f {$logPathsStr} | grep -E '{$filters}'"); } else { passthru("tail -f {$logPathsStr}"); } } } else { $this->info("Showing last {$lines} lines of {$logTypeDescription} logs for {$date}{$filterDescription}:"); $this->line(''); if (count($logPaths) === 1) { $logPath = $logPaths[0]; if ($filters) { passthru("tail -n {$lines} {$logPath} | grep -E '{$filters}'"); } else { passthru("tail -n {$lines} {$logPath}"); } } else { // Multiple files - concatenate and sort by timestamp $logPathsStr = implode(' ', $logPaths); if ($filters) { passthru("tail -n {$lines} {$logPathsStr} | sort | grep -E '{$filters}'"); } else { passthru("tail -n {$lines} {$logPathsStr} | sort"); } } } } private function getLogPaths(string $date): array { $paths = []; if ($this->option('errors')) { // Error logs only $errorPath = storage_path("logs/scheduled-errors-{$date}.log"); if (File::exists($errorPath)) { $paths[] = $errorPath; } } elseif ($this->option('all')) { // Both normal and error logs $normalPath = storage_path("logs/scheduled-{$date}.log"); $errorPath = storage_path("logs/scheduled-errors-{$date}.log"); if (File::exists($normalPath)) { $paths[] = $normalPath; } if (File::exists($errorPath)) { $paths[] = $errorPath; } } else { // Normal logs only (default) $normalPath = storage_path("logs/scheduled-{$date}.log"); if (File::exists($normalPath)) { $paths[] = $normalPath; } } return $paths; } private function showAvailableLogFiles(string $date): void { $logType = $this->getLogTypeDescription(); $this->warn("No {$logType} logs found for date {$date}"); // Show available log files $normalFiles = File::glob(storage_path('logs/scheduled-*.log')); $errorFiles = File::glob(storage_path('logs/scheduled-errors-*.log')); if (! empty($normalFiles) || ! empty($errorFiles)) { $this->info('Available scheduled log files:'); if (! empty($normalFiles)) { $this->line(' Normal logs:'); foreach ($normalFiles as $file) { $basename = basename($file); $this->line(" - {$basename}"); } } if (! empty($errorFiles)) { $this->line(' Error logs:'); foreach ($errorFiles as $file) { $basename = basename($file); $this->line(" - {$basename}"); } } } } private function getLogTypeDescription(): string { if ($this->option('errors')) { return 'error'; } elseif ($this->option('all')) { return 'all'; } else { return 'normal'; } } private function buildFilters(): ?string { $filters = []; if ($taskName = $this->option('task-name')) { $filters[] = '"task_name":"[^"]*'.preg_quote($taskName, '/').'[^"]*"'; } if ($taskId = $this->option('task-id')) { $filters[] = '"task_id":'.preg_quote($taskId, '/'); } if ($backupName = $this->option('backup-name')) { $filters[] = '"backup_name":"[^"]*'.preg_quote($backupName, '/').'[^"]*"'; } if ($backupId = $this->option('backup-id')) { $filters[] = '"backup_id":'.preg_quote($backupId, '/'); } // Frequency filters if ($this->option('hourly')) { $filters[] = $this->getFrequencyPattern('hourly'); } if ($this->option('daily')) { $filters[] = $this->getFrequencyPattern('daily'); } if ($this->option('weekly')) { $filters[] = $this->getFrequencyPattern('weekly'); } if ($this->option('monthly')) { $filters[] = $this->getFrequencyPattern('monthly'); } if ($frequency = $this->option('frequency')) { $filters[] = '"frequency":"'.preg_quote($frequency, '/').'"'; } return empty($filters) ? null : implode('|', $filters); } private function getFrequencyPattern(string $type): string { $patterns = [ 'hourly' => [ '0 \* \* \* \*', // 0 * * * * '@hourly', // @hourly ], 'daily' => [ '0 0 \* \* \*', // 0 0 * * * '@daily', // @daily '@midnight', // @midnight ], 'weekly' => [ '0 0 \* \* [0-6]', // 0 0 * * 0-6 (any day of week) '@weekly', // @weekly ], 'monthly' => [ '0 0 1 \* \*', // 0 0 1 * * (first of month) '@monthly', // @monthly ], ]; $typePatterns = $patterns[$type] ?? []; // For grep, we need to match the frequency field in JSON return '"frequency":"('.implode('|', $typePatterns).')"'; } private function getFilterDescription(): string { $descriptions = []; if ($taskName = $this->option('task-name')) { $descriptions[] = "task name: {$taskName}"; } if ($taskId = $this->option('task-id')) { $descriptions[] = "task ID: {$taskId}"; } if ($backupName = $this->option('backup-name')) { $descriptions[] = "backup name: {$backupName}"; } if ($backupId = $this->option('backup-id')) { $descriptions[] = "backup ID: {$backupId}"; } // Frequency filters if ($this->option('hourly')) { $descriptions[] = 'hourly jobs'; } if ($this->option('daily')) { $descriptions[] = 'daily jobs'; } if ($this->option('weekly')) { $descriptions[] = 'weekly jobs'; } if ($this->option('monthly')) { $descriptions[] = 'monthly jobs'; } if ($frequency = $this->option('frequency')) { $descriptions[] = "frequency: {$frequency}"; } return empty($descriptions) ? '' : ' (filtered by '.implode(', ', $descriptions).')'; } } ================================================ FILE: app/Console/Kernel.php ================================================ scheduleInstance = $schedule; $this->settings = instanceSettings(); $this->updateCheckFrequency = $this->settings->update_check_frequency ?: '0 * * * *'; $this->instanceTimezone = $this->settings->instance_timezone ?: config('app.timezone'); if (validate_timezone($this->instanceTimezone) === false) { $this->instanceTimezone = config('app.timezone'); } // $this->scheduleInstance->job(new CleanupStaleMultiplexedConnections)->hourly(); $this->scheduleInstance->command('cleanup:redis --clear-locks')->daily(); if (isDev()) { // Instance Jobs $this->scheduleInstance->command('horizon:snapshot')->everyMinute(); $this->scheduleInstance->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer(); $this->scheduleInstance->job(new CheckHelperImageJob)->everyTenMinutes()->onOneServer(); // Server Jobs $this->scheduleInstance->job(new ServerManagerJob)->everyMinute()->onOneServer(); // Scheduled Jobs (Backups & Tasks) $this->scheduleInstance->job(new ScheduledJobManager)->everyMinute()->onOneServer(); $this->scheduleInstance->command('uploads:clear')->everyTwoMinutes(); } else { // Instance Jobs $this->scheduleInstance->command('horizon:snapshot')->everyFiveMinutes(); $this->scheduleInstance->command('cleanup:unreachable-servers')->daily()->onOneServer(); $this->scheduleInstance->job(new PullTemplatesFromCDN)->cron($this->updateCheckFrequency)->timezone($this->instanceTimezone)->onOneServer(); $this->scheduleInstance->job(new PullChangelog)->cron($this->updateCheckFrequency)->timezone($this->instanceTimezone)->onOneServer(); $this->scheduleInstance->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer(); $this->scheduleUpdates(); // Server Jobs $this->scheduleInstance->job(new ServerManagerJob)->everyMinute()->onOneServer(); $this->pullImages(); // Scheduled Jobs (Backups & Tasks) $this->scheduleInstance->job(new ScheduledJobManager)->everyMinute()->onOneServer(); $this->scheduleInstance->job(new RegenerateSslCertJob)->twiceDaily(); $this->scheduleInstance->job(new CheckTraefikVersionJob)->weekly()->sundays()->at('00:00')->timezone($this->instanceTimezone)->onOneServer(); $this->scheduleInstance->command('cleanup:database --yes')->daily(); $this->scheduleInstance->command('uploads:clear')->everyTwoMinutes(); // Cleanup orphaned PR preview containers daily $this->scheduleInstance->job(new CleanupOrphanedPreviewContainersJob)->daily()->onOneServer(); } } private function pullImages(): void { $this->scheduleInstance->job(new CheckHelperImageJob) ->cron($this->updateCheckFrequency) ->timezone($this->instanceTimezone) ->onOneServer(); } private function scheduleUpdates(): void { $this->scheduleInstance->job(new CheckForUpdatesJob) ->cron($this->updateCheckFrequency) ->timezone($this->instanceTimezone) ->onOneServer(); if ($this->settings->is_auto_update_enabled) { $autoUpdateFrequency = $this->settings->auto_update_frequency; $this->scheduleInstance->job(new UpdateCoolifyJob) ->cron($autoUpdateFrequency) ->timezone($this->instanceTimezone) ->onOneServer(); } } protected function commands(): void { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); } } ================================================ FILE: app/Contracts/CustomJobRepositoryInterface.php ================================================ status = ProcessStatus::QUEUED->value; } } } ================================================ FILE: app/Data/ServerMetadata.php ================================================ 1, self::ADMIN => 2, self::OWNER => 3, }; } public function lt(Role|string $role): bool { if (is_string($role)) { $role = Role::from($role); } return $this->rank() < $role->rank(); } public function gt(Role|string $role): bool { if (is_string($role)) { $role = Role::from($role); } return $this->rank() > $role->rank(); } } ================================================ FILE: app/Enums/StaticImageTypes.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/ApplicationStatusChanged.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/BackupCreated.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/CloudflareTunnelChanged.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/DatabaseProxyStopped.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/DatabaseStatusChanged.php ================================================ userId = $userId; } public function broadcastOn(): ?array { if (is_null($this->userId)) { return []; } return [ new PrivateChannel("user.{$this->userId}"), ]; } } ================================================ FILE: app/Events/DockerCleanupDone.php ================================================ execution->server->team->id), ]; } } ================================================ FILE: app/Events/FileStorageChanged.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/ProxyStatusChanged.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; $this->activityId = $activityId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/RestoreJobFinished.php ================================================ /dev/null || true'"; } if (isSafeTmpPath($tmpPath)) { $commands[] = 'docker exec '.escapeshellarg($container)." sh -c 'rm ".escapeshellarg($tmpPath)." 2>/dev/null || true'"; } if (! empty($commands)) { $server = Server::find($serverId); if ($server) { instant_remote_process($commands, $server, throwError: false); } } } } } ================================================ FILE: app/Events/S3RestoreJobFinished.php ================================================ /dev/null || true'; } // Clean up server temp file if still exists (should already be cleaned) if (isSafeTmpPath($serverTmpPath)) { $commands[] = 'rm -f '.escapeshellarg($serverTmpPath).' 2>/dev/null || true'; } // Clean up any remaining files in database container (may already be cleaned) if (filled($container)) { if (isSafeTmpPath($containerTmpPath)) { $commands[] = 'docker exec '.escapeshellarg($container).' rm -f '.escapeshellarg($containerTmpPath).' 2>/dev/null || true'; } if (isSafeTmpPath($scriptPath)) { $commands[] = 'docker exec '.escapeshellarg($container).' rm -f '.escapeshellarg($scriptPath).' 2>/dev/null || true'; } } if (! empty($commands)) { $server = Server::find($serverId); if ($server) { instant_remote_process($commands, $server, throwError: false); } } } } } ================================================ FILE: app/Events/ScheduledTaskDone.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/SentinelRestarted.php ================================================ teamId = $server->team_id; $this->serverUuid = $server->uuid; $this->version = $version; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/ServerPackageUpdated.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/ServerReachabilityChanged.php ================================================ server->isReachableChanged(); } } ================================================ FILE: app/Events/ServerValidated.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; $this->serverUuid = $serverUuid; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } public function broadcastAs(): string { return 'ServerValidated'; } public function broadcastWith(): array { return [ 'teamId' => $this->teamId, 'serverUuid' => $this->serverUuid, ]; } } ================================================ FILE: app/Events/ServiceChecked.php ================================================ check() && auth()->user()->currentTeam()) { $teamId = auth()->user()->currentTeam()->id; } $this->teamId = $teamId; } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/ServiceStatusChanged.php ================================================ teamId) && Auth::check() && Auth::user()->currentTeam()) { $this->teamId = Auth::user()->currentTeam()->id; } } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Events/TestEvent.php ================================================ check() && auth()->user()->currentTeam()) { $this->teamId = auth()->user()->currentTeam()->id; } } public function broadcastOn(): array { if (is_null($this->teamId)) { return []; } return [ new PrivateChannel("team.{$this->teamId}"), ]; } } ================================================ FILE: app/Exceptions/DeploymentException.php ================================================ getMessage(), $exception->getCode(), $exception); } } ================================================ FILE: app/Exceptions/Handler.php ================================================ , \Psr\Log\LogLevel::*> */ protected $levels = [ // ]; /** * A list of the exception types that are not reported. * * @var array> */ protected $dontReport = [ ProcessException::class, NonReportableException::class, DeploymentException::class, ]; /** * A list of the inputs that are never flashed to the session on validation exceptions. * * @var array */ protected $dontFlash = [ 'current_password', 'password', 'password_confirmation', ]; private InstanceSettings $settings; protected function unauthenticated($request, AuthenticationException $exception) { if ($request->is('api/*') || $request->expectsJson() || $this->shouldReturnJson($request, $exception)) { return response()->json(['message' => $exception->getMessage()], 401); } return redirect()->guest($exception->redirectTo($request) ?? route('login')); } /** * Render an exception into an HTTP response. */ public function render($request, Throwable $e) { // Handle authorization exceptions for API routes if ($e instanceof \Illuminate\Auth\Access\AuthorizationException) { if ($request->is('api/*') || $request->expectsJson()) { // Get the custom message from the policy if available $message = $e->getMessage(); // Clean up the message for API responses (remove HTML tags if present) $message = strip_tags(str_replace('
', ' ', $message)); // If no custom message, use a default one if (empty($message) || $message === 'This action is unauthorized.') { $message = 'You are not authorized to perform this action.'; } return response()->json([ 'message' => $message, 'error' => 'Unauthorized', ], 403); } } return parent::render($request, $e); } /** * Register the exception handling callbacks for the application. */ public function register(): void { $this->reportable(function (Throwable $e) { if (isDev()) { return; } if ($e instanceof RuntimeException) { return; } $this->settings = instanceSettings(); if ($this->settings->do_not_track) { return; } app('sentry')->configureScope( function (Scope $scope) { $email = auth()?->user() ? auth()->user()->email : 'guest'; $instanceAdmin = User::find(0)->email ?? 'admin@localhost'; $scope->setUser( [ 'email' => $email, 'instanceAdmin' => $instanceAdmin, ] ); } ); // Check for errors that should not be reported to Sentry if (str($e->getMessage())->contains('No space left on device')) { // Log locally but don't send to Sentry logger()->warning('Disk space error: '.$e->getMessage()); return; } Integration::captureUnhandledException($e); }); } } ================================================ FILE: app/Exceptions/NonReportableException.php ================================================ getMessage(), $exception->getCode(), $exception); } } ================================================ FILE: app/Exceptions/ProcessException.php ================================================ private_key_id); $sshKeyLocation = $privateKey->getKeyLocation(); $muxFilename = '/var/www/html/storage/app/ssh/mux/mux_'.$server->uuid; return [ 'sshKeyLocation' => $sshKeyLocation, 'muxFilename' => $muxFilename, ]; } public static function ensureMultiplexedConnection(Server $server): bool { if (! self::isMultiplexingEnabled()) { return false; } $sshConfig = self::serverSshConfiguration($server); $muxSocket = $sshConfig['muxFilename']; // Check if connection exists $checkCommand = "ssh -O check -o ControlPath=$muxSocket "; if (data_get($server, 'settings.is_cloudflare_tunnel')) { $checkCommand .= '-o ProxyCommand="cloudflared access ssh --hostname %h" '; } $checkCommand .= self::escapedUserAtHost($server); $process = Process::run($checkCommand); if ($process->exitCode() !== 0) { return self::establishNewMultiplexedConnection($server); } // Connection exists, ensure we have metadata for age tracking if (self::getConnectionAge($server) === null) { // Existing connection but no metadata, store current time as fallback self::storeConnectionMetadata($server); } // Connection exists, check if it needs refresh due to age if (self::isConnectionExpired($server)) { return self::refreshMultiplexedConnection($server); } // Perform health check if enabled if (config('constants.ssh.mux_health_check_enabled')) { if (! self::isConnectionHealthy($server)) { return self::refreshMultiplexedConnection($server); } } return true; } public static function establishNewMultiplexedConnection(Server $server): bool { $sshConfig = self::serverSshConfiguration($server); $sshKeyLocation = $sshConfig['sshKeyLocation']; $muxSocket = $sshConfig['muxFilename']; $connectionTimeout = config('constants.ssh.connection_timeout'); $serverInterval = config('constants.ssh.server_interval'); $muxPersistTime = config('constants.ssh.mux_persist_time'); $establishCommand = "ssh -fNM -o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} "; if (data_get($server, 'settings.is_cloudflare_tunnel')) { $establishCommand .= ' -o ProxyCommand="cloudflared access ssh --hostname %h" '; } $establishCommand .= self::getCommonSshOptions($server, $sshKeyLocation, $connectionTimeout, $serverInterval); $establishCommand .= self::escapedUserAtHost($server); $establishProcess = Process::run($establishCommand); if ($establishProcess->exitCode() !== 0) { return false; } // Store connection metadata for tracking self::storeConnectionMetadata($server); return true; } public static function removeMuxFile(Server $server) { $sshConfig = self::serverSshConfiguration($server); $muxSocket = $sshConfig['muxFilename']; $closeCommand = "ssh -O exit -o ControlPath=$muxSocket "; if (data_get($server, 'settings.is_cloudflare_tunnel')) { $closeCommand .= '-o ProxyCommand="cloudflared access ssh --hostname %h" '; } $closeCommand .= self::escapedUserAtHost($server); Process::run($closeCommand); // Clear connection metadata from cache self::clearConnectionMetadata($server); } public static function generateScpCommand(Server $server, string $source, string $dest) { $sshConfig = self::serverSshConfiguration($server); $sshKeyLocation = $sshConfig['sshKeyLocation']; $muxSocket = $sshConfig['muxFilename']; $timeout = config('constants.ssh.command_timeout'); $muxPersistTime = config('constants.ssh.mux_persist_time'); $scp_command = "timeout $timeout scp "; if ($server->isIpv6()) { $scp_command .= '-6 '; } if (self::isMultiplexingEnabled()) { try { if (self::ensureMultiplexedConnection($server)) { $scp_command .= "-o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} "; } } catch (\Exception $e) { Log::warning('SSH multiplexing failed for SCP, falling back to non-multiplexed connection', [ 'server' => $server->name ?? $server->ip, 'error' => $e->getMessage(), ]); // Continue without multiplexing } } if (data_get($server, 'settings.is_cloudflare_tunnel')) { $scp_command .= '-o ProxyCommand="cloudflared access ssh --hostname %h" '; } $scp_command .= self::getCommonSshOptions($server, $sshKeyLocation, config('constants.ssh.connection_timeout'), config('constants.ssh.server_interval'), isScp: true); if ($server->isIpv6()) { $scp_command .= "{$source} ".escapeshellarg($server->user).'@['.escapeshellarg($server->ip)."]:{$dest}"; } else { $scp_command .= "{$source} ".self::escapedUserAtHost($server).":{$dest}"; } return $scp_command; } public static function generateSshCommand(Server $server, string $command, bool $disableMultiplexing = false) { if ($server->settings->force_disabled) { throw new \RuntimeException('Server is disabled.'); } $sshConfig = self::serverSshConfiguration($server); $sshKeyLocation = $sshConfig['sshKeyLocation']; self::validateSshKey($server->privateKey); $muxSocket = $sshConfig['muxFilename']; $timeout = config('constants.ssh.command_timeout'); $muxPersistTime = config('constants.ssh.mux_persist_time'); $ssh_command = "timeout $timeout ssh "; $multiplexingSuccessful = false; if (! $disableMultiplexing && self::isMultiplexingEnabled()) { try { $multiplexingSuccessful = self::ensureMultiplexedConnection($server); if ($multiplexingSuccessful) { $ssh_command .= "-o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} "; } } catch (\Exception $e) { // Continue without multiplexing } } if (data_get($server, 'settings.is_cloudflare_tunnel')) { $ssh_command .= "-o ProxyCommand='cloudflared access ssh --hostname %h' "; } $ssh_command .= self::getCommonSshOptions($server, $sshKeyLocation, config('constants.ssh.connection_timeout'), config('constants.ssh.server_interval')); $delimiter = Hash::make($command); $delimiter = base64_encode($delimiter); $command = str_replace($delimiter, '', $command); $ssh_command .= self::escapedUserAtHost($server)." 'bash -se' << \\$delimiter".PHP_EOL .$command.PHP_EOL .$delimiter; return $ssh_command; } private static function escapedUserAtHost(Server $server): string { return escapeshellarg($server->user).'@'.escapeshellarg($server->ip); } private static function isMultiplexingEnabled(): bool { return config('constants.ssh.mux_enabled') && ! config('constants.coolify.is_windows_docker_desktop'); } private static function validateSshKey(PrivateKey $privateKey): void { $keyLocation = $privateKey->getKeyLocation(); $checkKeyCommand = "ls $keyLocation 2>/dev/null"; $keyCheckProcess = Process::run($checkKeyCommand); if ($keyCheckProcess->exitCode() !== 0) { $privateKey->storeInFileSystem(); } } private static function getCommonSshOptions(Server $server, string $sshKeyLocation, int $connectionTimeout, int $serverInterval, bool $isScp = false): string { $options = "-i {$sshKeyLocation} " .'-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ' .'-o PasswordAuthentication=no ' ."-o ConnectTimeout=$connectionTimeout " ."-o ServerAliveInterval=$serverInterval " .'-o RequestTTY=no ' .'-o LogLevel=ERROR '; // Bruh if ($isScp) { $options .= '-P '.escapeshellarg((string) $server->port).' '; } else { $options .= '-p '.escapeshellarg((string) $server->port).' '; } return $options; } /** * Check if the multiplexed connection is healthy by running a test command */ public static function isConnectionHealthy(Server $server): bool { $sshConfig = self::serverSshConfiguration($server); $muxSocket = $sshConfig['muxFilename']; $healthCheckTimeout = config('constants.ssh.mux_health_check_timeout'); $healthCommand = "timeout $healthCheckTimeout ssh -o ControlMaster=auto -o ControlPath=$muxSocket "; if (data_get($server, 'settings.is_cloudflare_tunnel')) { $healthCommand .= '-o ProxyCommand="cloudflared access ssh --hostname %h" '; } $healthCommand .= self::escapedUserAtHost($server)." 'echo \"health_check_ok\"'"; $process = Process::run($healthCommand); $isHealthy = $process->exitCode() === 0 && str_contains($process->output(), 'health_check_ok'); return $isHealthy; } /** * Check if the connection has exceeded its maximum age */ public static function isConnectionExpired(Server $server): bool { $connectionAge = self::getConnectionAge($server); $maxAge = config('constants.ssh.mux_max_age'); return $connectionAge !== null && $connectionAge > $maxAge; } /** * Get the age of the current connection in seconds */ public static function getConnectionAge(Server $server): ?int { $cacheKey = "ssh_mux_connection_time_{$server->uuid}"; $connectionTime = Cache::get($cacheKey); if ($connectionTime === null) { return null; } return time() - $connectionTime; } /** * Refresh a multiplexed connection by closing and re-establishing it */ public static function refreshMultiplexedConnection(Server $server): bool { // Close existing connection self::removeMuxFile($server); // Establish new connection return self::establishNewMultiplexedConnection($server); } /** * Store connection metadata when a new connection is established */ private static function storeConnectionMetadata(Server $server): void { $cacheKey = "ssh_mux_connection_time_{$server->uuid}"; Cache::put($cacheKey, time(), config('constants.ssh.mux_persist_time') + 300); // Cache slightly longer than persist time } /** * Clear connection metadata from cache */ private static function clearConnectionMetadata(Server $server): void { $cacheKey = "ssh_mux_connection_time_{$server->uuid}"; Cache::forget($cacheKey); } } ================================================ FILE: app/Helpers/SshRetryHandler.php ================================================ executeWithSshRetry($callback, $context, $throwError); } } ================================================ FILE: app/Helpers/SslHelper.php ================================================ OPENSSL_KEYTYPE_EC, 'curve_name' => 'secp521r1', ]); if ($privateKey === false) { throw new \RuntimeException('Failed to generate private key: '.openssl_error_string()); } if (! openssl_pkey_export($privateKey, $privateKeyStr)) { throw new \RuntimeException('Failed to export private key: '.openssl_error_string()); } if (! is_null($serverId) && ! $isCaCertificate) { $server = Server::find($serverId); if ($server) { $ip = $server->getIp; if ($ip) { $type = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) ? 'IP' : 'DNS'; $subjectAlternativeNames = array_unique( array_merge($subjectAlternativeNames, ["$type:$ip"]) ); } } } $basicConstraints = $isCaCertificate ? 'critical, CA:TRUE, pathlen:0' : 'critical, CA:FALSE'; $keyUsage = $isCaCertificate ? 'critical, keyCertSign, cRLSign' : 'critical, digitalSignature, keyAgreement'; $subjectAltNameSection = ''; $extendedKeyUsageSection = ''; if (! $isCaCertificate) { $extendedKeyUsageSection = "\nextendedKeyUsage = serverAuth, clientAuth"; $subjectAlternativeNames = array_values( array_unique( array_merge(["DNS:$commonName"], $subjectAlternativeNames) ) ); $formattedSubjectAltNames = array_map( function ($index, $san) { [$type, $value] = explode(':', $san, 2); return "{$type}.".($index + 1)." = $value"; }, array_keys($subjectAlternativeNames), $subjectAlternativeNames ); $subjectAltNameSection = "subjectAltName = @subject_alt_names\n\n[ subject_alt_names ]\n" .implode("\n", $formattedSubjectAltNames); } $config = << $commonName, 'organizationName' => $organizationName, 'countryName' => $countryName, 'stateOrProvinceName' => $stateName, ], $privateKey, [ 'digest_alg' => 'sha512', 'config' => $tempConfigPath, 'req_extensions' => 'req_ext', ]); if ($csr === false) { throw new \RuntimeException('Failed to generate CSR: '.openssl_error_string()); } $certificate = openssl_csr_sign( $csr, $caCert ?? null, $caKey ?? $privateKey, $validityDays, [ 'digest_alg' => 'sha512', 'config' => $tempConfigPath, 'x509_extensions' => 'v3_req', ], random_int(1, PHP_INT_MAX) ); if ($certificate === false) { throw new \RuntimeException('Failed to sign certificate: '.openssl_error_string()); } if (! openssl_x509_export($certificate, $certificateStr)) { throw new \RuntimeException('Failed to export certificate: '.openssl_error_string()); } SslCertificate::query() ->where('resource_type', $resourceType) ->where('resource_id', $resourceId) ->where('server_id', $serverId) ->delete(); $sslCertificate = SslCertificate::create([ 'ssl_certificate' => $certificateStr, 'ssl_private_key' => $privateKeyStr, 'resource_type' => $resourceType, 'resource_id' => $resourceId, 'server_id' => $serverId, 'configuration_dir' => $configurationDir, 'mount_path' => $mountPath, 'valid_until' => CarbonImmutable::now()->addDays($validityDays), 'is_ca_certificate' => $isCaCertificate, 'common_name' => $commonName, 'subject_alternative_names' => $subjectAlternativeNames, ]); if ($configurationDir && $mountPath && $resourceType && $resourceId) { $model = app($resourceType)->find($resourceId); $model->fileStorages() ->where('resource_type', $model->getMorphClass()) ->where('resource_id', $model->id) ->get() ->filter(function ($storage) use ($mountPath) { return in_array($storage->mount_path, [ $mountPath.'/server.crt', $mountPath.'/server.key', $mountPath.'/server.pem', ]); }) ->each(function ($storage) { $storage->delete(); }); if ($isPemKeyFileRequired) { $model->fileStorages()->create([ 'fs_path' => $configurationDir.'/ssl/server.pem', 'mount_path' => $mountPath.'/server.pem', 'content' => $certificateStr."\n".$privateKeyStr, 'is_directory' => false, 'chmod' => '600', 'resource_type' => $resourceType, 'resource_id' => $resourceId, ]); } else { $model->fileStorages()->create([ 'fs_path' => $configurationDir.'/ssl/server.crt', 'mount_path' => $mountPath.'/server.crt', 'content' => $certificateStr, 'is_directory' => false, 'chmod' => '644', 'resource_type' => $resourceType, 'resource_id' => $resourceId, ]); $model->fileStorages()->create([ 'fs_path' => $configurationDir.'/ssl/server.key', 'mount_path' => $mountPath.'/server.key', 'content' => $privateKeyStr, 'is_directory' => false, 'chmod' => '600', 'resource_type' => $resourceType, 'resource_id' => $resourceId, ]); } } return $sslCertificate; } catch (\Throwable $e) { throw new \RuntimeException('SSL Certificate generation failed: '.$e->getMessage(), 0, $e); } finally { fclose($tempConfig); } } } ================================================ FILE: app/Http/Controllers/Api/ApplicationsController.php ================================================ makeHidden([ 'id', 'resourceable', 'resourceable_id', 'resourceable_type', ]); if (request()->attributes->get('can_read_sensitive', false) === false) { $application->makeHidden([ 'custom_labels', 'dockerfile', 'docker_compose', 'docker_compose_raw', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'private_key_id', 'value', 'real_value', 'http_basic_auth_password', ]); } return serializeApiResponse($application); } #[OA\Get( summary: 'List', description: 'List all applications.', path: '/applications', operationId: 'list-applications', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'tag', in: 'query', description: 'Filter applications by tag name.', required: false, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get all applications.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/Application') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function applications(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $tagName = $request->query('tag'); $applications = Application::ownedByCurrentTeamAPI($teamId) ->when($tagName, function ($query, $tagName) { $query->whereHas('tags', function ($query) use ($tagName) { $query->where('name', $tagName); }); }) ->get() ->map(function ($application) { return $this->removeSensitiveData($application); }); return response()->json($applications); } #[OA\Post( summary: 'Create (Public)', description: 'Create new application based on a public git repository.', path: '/applications/public', operationId: 'create-public-application', security: [ ['bearerAuth' => []], ], tags: ['Applications'], requestBody: new OA\RequestBody( description: 'Application object that needs to be created.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['project_uuid', 'server_uuid', 'environment_name', 'environment_uuid', 'git_repository', 'git_branch', 'build_pack', 'ports_exposes'], properties: [ 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.'], 'git_repository' => ['type' => 'string', 'description' => 'The git repository URL.'], 'git_branch' => ['type' => 'string', 'description' => 'The git branch.'], 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose'], 'description' => 'The build pack type.'], 'ports_exposes' => ['type' => 'string', 'description' => 'The ports to expose.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'description' => ['type' => 'string', 'description' => 'The application description.'], 'domains' => ['type' => 'string', 'description' => 'The application URLs in a comma-separated list.'], 'git_commit_sha' => ['type' => 'string', 'description' => 'The git commit SHA.'], 'docker_registry_image_name' => ['type' => 'string', 'description' => 'The docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'description' => 'The docker registry image tag.'], 'is_static' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is static.'], 'is_spa' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.'], 'is_auto_deploy_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.'], 'is_force_https_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if HTTPS is forced. Defaults to true.'], 'static_image' => ['type' => 'string', 'enum' => ['nginx:alpine'], 'description' => 'The static image.'], 'install_command' => ['type' => 'string', 'description' => 'The install command.'], 'build_command' => ['type' => 'string', 'description' => 'The build command.'], 'start_command' => ['type' => 'string', 'description' => 'The start command.'], 'ports_mappings' => ['type' => 'string', 'description' => 'The ports mappings.'], 'base_directory' => ['type' => 'string', 'description' => 'The base directory for all commands.'], 'publish_directory' => ['type' => 'string', 'description' => 'The publish directory.'], 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Health check enabled.'], 'health_check_path' => ['type' => 'string', 'description' => 'Health check path.'], 'health_check_port' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check port.'], 'health_check_host' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check host.'], 'health_check_method' => ['type' => 'string', 'description' => 'Health check method.'], 'health_check_return_code' => ['type' => 'integer', 'description' => 'Health check return code.'], 'health_check_scheme' => ['type' => 'string', 'description' => 'Health check scheme.'], 'health_check_response_text' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check response text.'], 'health_check_interval' => ['type' => 'integer', 'description' => 'Health check interval in seconds.'], 'health_check_timeout' => ['type' => 'integer', 'description' => 'Health check timeout in seconds.'], 'health_check_retries' => ['type' => 'integer', 'description' => 'Health check retries count.'], 'health_check_start_period' => ['type' => 'integer', 'description' => 'Health check start period in seconds.'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit.'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit.'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness.'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation.'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit.'], 'limits_cpuset' => ['type' => 'string', 'nullable' => true, 'description' => 'CPU set.'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares.'], 'custom_labels' => ['type' => 'string', 'description' => 'Custom labels.'], 'custom_docker_run_options' => ['type' => 'string', 'description' => 'Custom docker run options.'], 'post_deployment_command' => ['type' => 'string', 'description' => 'Post deployment command.'], 'post_deployment_command_container' => ['type' => 'string', 'description' => 'Post deployment command container.'], 'pre_deployment_command' => ['type' => 'string', 'description' => 'Pre deployment command.'], 'pre_deployment_command_container' => ['type' => 'string', 'description' => 'Pre deployment command container.'], 'manual_webhook_secret_github' => ['type' => 'string', 'description' => 'Manual webhook secret for Github.'], 'manual_webhook_secret_gitlab' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitlab.'], 'manual_webhook_secret_bitbucket' => ['type' => 'string', 'description' => 'Manual webhook secret for Bitbucket.'], 'manual_webhook_secret_gitea' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitea.'], 'redirect' => ['type' => 'string', 'nullable' => true, 'description' => 'How to set redirect with Traefik / Caddy. www<->non-www.', 'enum' => ['www', 'non-www', 'both']], // 'github_app_uuid' => ['type' => 'string', 'description' => 'The Github App UUID.'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'dockerfile' => ['type' => 'string', 'description' => 'The Dockerfile content.'], 'dockerfile_location' => ['type' => 'string', 'description' => 'The Dockerfile location in the repository.'], 'docker_compose_location' => ['type' => 'string', 'description' => 'The Docker Compose location.'], 'docker_compose_custom_start_command' => ['type' => 'string', 'description' => 'The Docker Compose custom start command.'], 'docker_compose_custom_build_command' => ['type' => 'string', 'description' => 'The Docker Compose custom build command.'], 'docker_compose_domains' => [ 'type' => 'array', 'description' => 'Array of URLs to be applied to containers of a dockercompose application.', 'items' => new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The service name as defined in docker-compose.'], 'domain' => ['type' => 'string', 'description' => 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")'], ], ), ], 'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'autogenerate_domain' => ['type' => 'boolean', 'default' => true, 'description' => 'If true and domains is empty, auto-generate a domain using the server\'s wildcard domain or sslip.io fallback. Default: true.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], ], ) ), ] ), responses: [ new OA\Response( response: 201, description: 'Application created successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ) ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), ] )] public function create_public_application(Request $request) { return $this->create_application($request, 'public'); } #[OA\Post( summary: 'Create (Private - GH App)', description: 'Create new application based on a private repository through a Github App.', path: '/applications/private-github-app', operationId: 'create-private-github-app-application', security: [ ['bearerAuth' => []], ], tags: ['Applications'], requestBody: new OA\RequestBody( description: 'Application object that needs to be created.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['project_uuid', 'server_uuid', 'environment_name', 'environment_uuid', 'github_app_uuid', 'git_repository', 'git_branch', 'build_pack', 'ports_exposes'], properties: [ 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.'], 'github_app_uuid' => ['type' => 'string', 'description' => 'The Github App UUID.'], 'git_repository' => ['type' => 'string', 'description' => 'The git repository URL.'], 'git_branch' => ['type' => 'string', 'description' => 'The git branch.'], 'ports_exposes' => ['type' => 'string', 'description' => 'The ports to expose.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID.'], 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose'], 'description' => 'The build pack type.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'description' => ['type' => 'string', 'description' => 'The application description.'], 'domains' => ['type' => 'string', 'description' => 'The application URLs in a comma-separated list.'], 'git_commit_sha' => ['type' => 'string', 'description' => 'The git commit SHA.'], 'docker_registry_image_name' => ['type' => 'string', 'description' => 'The docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'description' => 'The docker registry image tag.'], 'is_static' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is static.'], 'is_spa' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.'], 'is_auto_deploy_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.'], 'is_force_https_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if HTTPS is forced. Defaults to true.'], 'static_image' => ['type' => 'string', 'enum' => ['nginx:alpine'], 'description' => 'The static image.'], 'install_command' => ['type' => 'string', 'description' => 'The install command.'], 'build_command' => ['type' => 'string', 'description' => 'The build command.'], 'start_command' => ['type' => 'string', 'description' => 'The start command.'], 'ports_mappings' => ['type' => 'string', 'description' => 'The ports mappings.'], 'base_directory' => ['type' => 'string', 'description' => 'The base directory for all commands.'], 'publish_directory' => ['type' => 'string', 'description' => 'The publish directory.'], 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Health check enabled.'], 'health_check_path' => ['type' => 'string', 'description' => 'Health check path.'], 'health_check_port' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check port.'], 'health_check_host' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check host.'], 'health_check_method' => ['type' => 'string', 'description' => 'Health check method.'], 'health_check_return_code' => ['type' => 'integer', 'description' => 'Health check return code.'], 'health_check_scheme' => ['type' => 'string', 'description' => 'Health check scheme.'], 'health_check_response_text' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check response text.'], 'health_check_interval' => ['type' => 'integer', 'description' => 'Health check interval in seconds.'], 'health_check_timeout' => ['type' => 'integer', 'description' => 'Health check timeout in seconds.'], 'health_check_retries' => ['type' => 'integer', 'description' => 'Health check retries count.'], 'health_check_start_period' => ['type' => 'integer', 'description' => 'Health check start period in seconds.'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit.'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit.'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness.'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation.'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit.'], 'limits_cpuset' => ['type' => 'string', 'nullable' => true, 'description' => 'CPU set.'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares.'], 'custom_labels' => ['type' => 'string', 'description' => 'Custom labels.'], 'custom_docker_run_options' => ['type' => 'string', 'description' => 'Custom docker run options.'], 'post_deployment_command' => ['type' => 'string', 'description' => 'Post deployment command.'], 'post_deployment_command_container' => ['type' => 'string', 'description' => 'Post deployment command container.'], 'pre_deployment_command' => ['type' => 'string', 'description' => 'Pre deployment command.'], 'pre_deployment_command_container' => ['type' => 'string', 'description' => 'Pre deployment command container.'], 'manual_webhook_secret_github' => ['type' => 'string', 'description' => 'Manual webhook secret for Github.'], 'manual_webhook_secret_gitlab' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitlab.'], 'manual_webhook_secret_bitbucket' => ['type' => 'string', 'description' => 'Manual webhook secret for Bitbucket.'], 'manual_webhook_secret_gitea' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitea.'], 'redirect' => ['type' => 'string', 'nullable' => true, 'description' => 'How to set redirect with Traefik / Caddy. www<->non-www.', 'enum' => ['www', 'non-www', 'both']], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'dockerfile' => ['type' => 'string', 'description' => 'The Dockerfile content.'], 'dockerfile_location' => ['type' => 'string', 'description' => 'The Dockerfile location in the repository'], 'docker_compose_location' => ['type' => 'string', 'description' => 'The Docker Compose location.'], 'docker_compose_custom_start_command' => ['type' => 'string', 'description' => 'The Docker Compose custom start command.'], 'docker_compose_custom_build_command' => ['type' => 'string', 'description' => 'The Docker Compose custom build command.'], 'docker_compose_domains' => [ 'type' => 'array', 'description' => 'Array of URLs to be applied to containers of a dockercompose application.', 'items' => new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The service name as defined in docker-compose.'], 'domain' => ['type' => 'string', 'description' => 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")'], ], ), ], 'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'autogenerate_domain' => ['type' => 'boolean', 'default' => true, 'description' => 'If true and domains is empty, auto-generate a domain using the server\'s wildcard domain or sslip.io fallback. Default: true.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], ], ) ), ] ), responses: [ new OA\Response( response: 201, description: 'Application created successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ) ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), ] )] public function create_private_gh_app_application(Request $request) { return $this->create_application($request, 'private-gh-app'); } #[OA\Post( summary: 'Create (Private - Deploy Key)', description: 'Create new application based on a private repository through a Deploy Key.', path: '/applications/private-deploy-key', operationId: 'create-private-deploy-key-application', security: [ ['bearerAuth' => []], ], tags: ['Applications'], requestBody: new OA\RequestBody( description: 'Application object that needs to be created.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['project_uuid', 'server_uuid', 'environment_name', 'environment_uuid', 'private_key_uuid', 'git_repository', 'git_branch', 'build_pack', 'ports_exposes'], properties: [ 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.'], 'private_key_uuid' => ['type' => 'string', 'description' => 'The private key UUID.'], 'git_repository' => ['type' => 'string', 'description' => 'The git repository URL.'], 'git_branch' => ['type' => 'string', 'description' => 'The git branch.'], 'ports_exposes' => ['type' => 'string', 'description' => 'The ports to expose.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID.'], 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose'], 'description' => 'The build pack type.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'description' => ['type' => 'string', 'description' => 'The application description.'], 'domains' => ['type' => 'string', 'description' => 'The application URLs in a comma-separated list.'], 'git_commit_sha' => ['type' => 'string', 'description' => 'The git commit SHA.'], 'docker_registry_image_name' => ['type' => 'string', 'description' => 'The docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'description' => 'The docker registry image tag.'], 'is_static' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is static.'], 'is_spa' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.'], 'is_auto_deploy_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.'], 'is_force_https_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if HTTPS is forced. Defaults to true.'], 'static_image' => ['type' => 'string', 'enum' => ['nginx:alpine'], 'description' => 'The static image.'], 'install_command' => ['type' => 'string', 'description' => 'The install command.'], 'build_command' => ['type' => 'string', 'description' => 'The build command.'], 'start_command' => ['type' => 'string', 'description' => 'The start command.'], 'ports_mappings' => ['type' => 'string', 'description' => 'The ports mappings.'], 'base_directory' => ['type' => 'string', 'description' => 'The base directory for all commands.'], 'publish_directory' => ['type' => 'string', 'description' => 'The publish directory.'], 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Health check enabled.'], 'health_check_path' => ['type' => 'string', 'description' => 'Health check path.'], 'health_check_port' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check port.'], 'health_check_host' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check host.'], 'health_check_method' => ['type' => 'string', 'description' => 'Health check method.'], 'health_check_return_code' => ['type' => 'integer', 'description' => 'Health check return code.'], 'health_check_scheme' => ['type' => 'string', 'description' => 'Health check scheme.'], 'health_check_response_text' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check response text.'], 'health_check_interval' => ['type' => 'integer', 'description' => 'Health check interval in seconds.'], 'health_check_timeout' => ['type' => 'integer', 'description' => 'Health check timeout in seconds.'], 'health_check_retries' => ['type' => 'integer', 'description' => 'Health check retries count.'], 'health_check_start_period' => ['type' => 'integer', 'description' => 'Health check start period in seconds.'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit.'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit.'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness.'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation.'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit.'], 'limits_cpuset' => ['type' => 'string', 'nullable' => true, 'description' => 'CPU set.'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares.'], 'custom_labels' => ['type' => 'string', 'description' => 'Custom labels.'], 'custom_docker_run_options' => ['type' => 'string', 'description' => 'Custom docker run options.'], 'post_deployment_command' => ['type' => 'string', 'description' => 'Post deployment command.'], 'post_deployment_command_container' => ['type' => 'string', 'description' => 'Post deployment command container.'], 'pre_deployment_command' => ['type' => 'string', 'description' => 'Pre deployment command.'], 'pre_deployment_command_container' => ['type' => 'string', 'description' => 'Pre deployment command container.'], 'manual_webhook_secret_github' => ['type' => 'string', 'description' => 'Manual webhook secret for Github.'], 'manual_webhook_secret_gitlab' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitlab.'], 'manual_webhook_secret_bitbucket' => ['type' => 'string', 'description' => 'Manual webhook secret for Bitbucket.'], 'manual_webhook_secret_gitea' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitea.'], 'redirect' => ['type' => 'string', 'nullable' => true, 'description' => 'How to set redirect with Traefik / Caddy. www<->non-www.', 'enum' => ['www', 'non-www', 'both']], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'dockerfile' => ['type' => 'string', 'description' => 'The Dockerfile content.'], 'dockerfile_location' => ['type' => 'string', 'description' => 'The Dockerfile location in the repository.'], 'docker_compose_location' => ['type' => 'string', 'description' => 'The Docker Compose location.'], 'docker_compose_custom_start_command' => ['type' => 'string', 'description' => 'The Docker Compose custom start command.'], 'docker_compose_custom_build_command' => ['type' => 'string', 'description' => 'The Docker Compose custom build command.'], 'docker_compose_domains' => [ 'type' => 'array', 'description' => 'Array of URLs to be applied to containers of a dockercompose application.', 'items' => new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The service name as defined in docker-compose.'], 'domain' => ['type' => 'string', 'description' => 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")'], ], ), ], 'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'autogenerate_domain' => ['type' => 'boolean', 'default' => true, 'description' => 'If true and domains is empty, auto-generate a domain using the server\'s wildcard domain or sslip.io fallback. Default: true.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], ], ) ), ] ), responses: [ new OA\Response( response: 201, description: 'Application created successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ) ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), ] )] public function create_private_deploy_key_application(Request $request) { return $this->create_application($request, 'private-deploy-key'); } #[OA\Post( summary: 'Create (Dockerfile without git)', description: 'Create new application based on a simple Dockerfile (without git).', path: '/applications/dockerfile', operationId: 'create-dockerfile-application', security: [ ['bearerAuth' => []], ], tags: ['Applications'], requestBody: new OA\RequestBody( description: 'Application object that needs to be created.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['project_uuid', 'server_uuid', 'environment_name', 'environment_uuid', 'dockerfile'], properties: [ 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.'], 'dockerfile' => ['type' => 'string', 'description' => 'The Dockerfile content.'], 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose'], 'description' => 'The build pack type.'], 'ports_exposes' => ['type' => 'string', 'description' => 'The ports to expose.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'description' => ['type' => 'string', 'description' => 'The application description.'], 'domains' => ['type' => 'string', 'description' => 'The application URLs in a comma-separated list.'], 'docker_registry_image_name' => ['type' => 'string', 'description' => 'The docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'description' => 'The docker registry image tag.'], 'ports_mappings' => ['type' => 'string', 'description' => 'The ports mappings.'], 'base_directory' => ['type' => 'string', 'description' => 'The base directory for all commands.'], 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Health check enabled.'], 'health_check_path' => ['type' => 'string', 'description' => 'Health check path.'], 'health_check_port' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check port.'], 'health_check_host' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check host.'], 'health_check_method' => ['type' => 'string', 'description' => 'Health check method.'], 'health_check_return_code' => ['type' => 'integer', 'description' => 'Health check return code.'], 'health_check_scheme' => ['type' => 'string', 'description' => 'Health check scheme.'], 'health_check_response_text' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check response text.'], 'health_check_interval' => ['type' => 'integer', 'description' => 'Health check interval in seconds.'], 'health_check_timeout' => ['type' => 'integer', 'description' => 'Health check timeout in seconds.'], 'health_check_retries' => ['type' => 'integer', 'description' => 'Health check retries count.'], 'health_check_start_period' => ['type' => 'integer', 'description' => 'Health check start period in seconds.'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit.'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit.'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness.'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation.'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit.'], 'limits_cpuset' => ['type' => 'string', 'nullable' => true, 'description' => 'CPU set.'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares.'], 'custom_labels' => ['type' => 'string', 'description' => 'Custom labels.'], 'custom_docker_run_options' => ['type' => 'string', 'description' => 'Custom docker run options.'], 'post_deployment_command' => ['type' => 'string', 'description' => 'Post deployment command.'], 'post_deployment_command_container' => ['type' => 'string', 'description' => 'Post deployment command container.'], 'pre_deployment_command' => ['type' => 'string', 'description' => 'Pre deployment command.'], 'pre_deployment_command_container' => ['type' => 'string', 'description' => 'Pre deployment command container.'], 'manual_webhook_secret_github' => ['type' => 'string', 'description' => 'Manual webhook secret for Github.'], 'manual_webhook_secret_gitlab' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitlab.'], 'manual_webhook_secret_bitbucket' => ['type' => 'string', 'description' => 'Manual webhook secret for Bitbucket.'], 'manual_webhook_secret_gitea' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitea.'], 'redirect' => ['type' => 'string', 'nullable' => true, 'description' => 'How to set redirect with Traefik / Caddy. www<->non-www.', 'enum' => ['www', 'non-www', 'both']], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'is_force_https_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if HTTPS is forced. Defaults to true.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'autogenerate_domain' => ['type' => 'boolean', 'default' => true, 'description' => 'If true and domains is empty, auto-generate a domain using the server\'s wildcard domain or sslip.io fallback. Default: true.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], ], ) ), ] ), responses: [ new OA\Response( response: 201, description: 'Application created successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ) ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), ] )] public function create_dockerfile_application(Request $request) { return $this->create_application($request, 'dockerfile'); } #[OA\Post( summary: 'Create (Docker Image without git)', description: 'Create new application based on a prebuilt docker image (without git).', path: '/applications/dockerimage', operationId: 'create-dockerimage-application', security: [ ['bearerAuth' => []], ], tags: ['Applications'], requestBody: new OA\RequestBody( description: 'Application object that needs to be created.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['project_uuid', 'server_uuid', 'environment_name', 'environment_uuid', 'docker_registry_image_name', 'ports_exposes'], properties: [ 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.'], 'docker_registry_image_name' => ['type' => 'string', 'description' => 'The docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'description' => 'The docker registry image tag.'], 'ports_exposes' => ['type' => 'string', 'description' => 'The ports to expose.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'description' => ['type' => 'string', 'description' => 'The application description.'], 'domains' => ['type' => 'string', 'description' => 'The application URLs in a comma-separated list.'], 'ports_mappings' => ['type' => 'string', 'description' => 'The ports mappings.'], 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Health check enabled.'], 'health_check_path' => ['type' => 'string', 'description' => 'Health check path.'], 'health_check_port' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check port.'], 'health_check_host' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check host.'], 'health_check_method' => ['type' => 'string', 'description' => 'Health check method.'], 'health_check_return_code' => ['type' => 'integer', 'description' => 'Health check return code.'], 'health_check_scheme' => ['type' => 'string', 'description' => 'Health check scheme.'], 'health_check_response_text' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check response text.'], 'health_check_interval' => ['type' => 'integer', 'description' => 'Health check interval in seconds.'], 'health_check_timeout' => ['type' => 'integer', 'description' => 'Health check timeout in seconds.'], 'health_check_retries' => ['type' => 'integer', 'description' => 'Health check retries count.'], 'health_check_start_period' => ['type' => 'integer', 'description' => 'Health check start period in seconds.'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit.'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit.'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness.'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation.'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit.'], 'limits_cpuset' => ['type' => 'string', 'nullable' => true, 'description' => 'CPU set.'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares.'], 'custom_labels' => ['type' => 'string', 'description' => 'Custom labels.'], 'custom_docker_run_options' => ['type' => 'string', 'description' => 'Custom docker run options.'], 'post_deployment_command' => ['type' => 'string', 'description' => 'Post deployment command.'], 'post_deployment_command_container' => ['type' => 'string', 'description' => 'Post deployment command container.'], 'pre_deployment_command' => ['type' => 'string', 'description' => 'Pre deployment command.'], 'pre_deployment_command_container' => ['type' => 'string', 'description' => 'Pre deployment command container.'], 'manual_webhook_secret_github' => ['type' => 'string', 'description' => 'Manual webhook secret for Github.'], 'manual_webhook_secret_gitlab' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitlab.'], 'manual_webhook_secret_bitbucket' => ['type' => 'string', 'description' => 'Manual webhook secret for Bitbucket.'], 'manual_webhook_secret_gitea' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitea.'], 'redirect' => ['type' => 'string', 'nullable' => true, 'description' => 'How to set redirect with Traefik / Caddy. www<->non-www.', 'enum' => ['www', 'non-www', 'both']], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'is_force_https_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if HTTPS is forced. Defaults to true.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'autogenerate_domain' => ['type' => 'boolean', 'default' => true, 'description' => 'If true and domains is empty, auto-generate a domain using the server\'s wildcard domain or sslip.io fallback. Default: true.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], ], ) ), ] ), responses: [ new OA\Response( response: 201, description: 'Application created successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ) ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), ] )] public function create_dockerimage_application(Request $request) { return $this->create_application($request, 'dockerimage'); } /** * @deprecated Use POST /api/v1/services instead. This endpoint creates a Service, not an Application and is an unstable duplicate of POST /api/v1/services. */ #[OA\Post( summary: 'Create (Docker Compose)', description: 'Deprecated: Use POST /api/v1/services instead.', path: '/applications/dockercompose', operationId: 'create-dockercompose-application', deprecated: true, security: [ ['bearerAuth' => []], ], tags: ['Applications'], requestBody: new OA\RequestBody( description: 'Application object that needs to be created.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['project_uuid', 'server_uuid', 'environment_name', 'environment_uuid', 'docker_compose_raw'], properties: [ 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.'], 'docker_compose_raw' => ['type' => 'string', 'description' => 'The Docker Compose raw content.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID if the server has more than one destinations.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'description' => ['type' => 'string', 'description' => 'The application description.'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], ], ) ), ] ), responses: [ new OA\Response( response: 201, description: 'Application created successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ) ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), ] )] public function create_dockercompose_application(Request $request) { return $this->create_application($request, 'dockercompose'); } private function create_application(Request $request, $type) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $this->authorize('create', Application::class); $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'is_spa', 'is_auto_deploy_enabled', 'is_force_https_enabled', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'private_key_uuid', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'custom_network_aliases', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_type', 'health_check_command', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy', 'dockerfile', 'dockerfile_location', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'watch_paths', 'use_build_server', 'static_image', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network', 'force_domain_override', 'autogenerate_domain', 'is_container_label_escape_enabled']; $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', 'description' => 'string|nullable', 'project_uuid' => 'string|required', 'environment_name' => 'string|nullable', 'environment_uuid' => 'string|nullable', 'server_uuid' => 'string|required', 'destination_uuid' => 'string', 'is_http_basic_auth_enabled' => 'boolean', 'http_basic_auth_username' => 'string|nullable', 'http_basic_auth_password' => 'string|nullable', 'autogenerate_domain' => 'boolean', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $environmentUuid = $request->environment_uuid; $environmentName = $request->environment_name; if (blank($environmentUuid) && blank($environmentName)) { return response()->json(['message' => 'You need to provide at least one of environment_name or environment_uuid.'], 422); } $serverUuid = $request->server_uuid; $fqdn = $request->domains; $autogenerateDomain = $request->boolean('autogenerate_domain', true); $instantDeploy = $request->instant_deploy; $githubAppUuid = $request->github_app_uuid; $useBuildServer = $request->use_build_server; $isStatic = $request->is_static; $isSpa = $request->is_spa; $isAutoDeployEnabled = $request->is_auto_deploy_enabled; $isForceHttpsEnabled = $request->is_force_https_enabled; $connectToDockerNetwork = $request->connect_to_docker_network; $customNginxConfiguration = $request->custom_nginx_configuration; $isContainerLabelEscapeEnabled = $request->boolean('is_container_label_escape_enabled', true); if (! is_null($customNginxConfiguration)) { if (! isBase64Encoded($customNginxConfiguration)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.', ], ], 422); } $customNginxConfiguration = base64_decode($customNginxConfiguration); if (mb_detect_encoding($customNginxConfiguration, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.', ], ], 422); } } $project = Project::whereTeamId($teamId)->whereUuid($request->project_uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $environment = $project->environments()->where('name', $environmentName)->first(); if (! $environment) { $environment = $project->environments()->where('uuid', $environmentUuid)->first(); } if (! $environment) { return response()->json(['message' => 'Environment not found.'], 404); } $server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first(); if (! $server) { return response()->json(['message' => 'Server not found.'], 404); } $destinations = $server->destinations(); if ($destinations->count() == 0) { return response()->json(['message' => 'Server has no destinations.'], 400); } if ($destinations->count() > 1 && ! $request->has('destination_uuid')) { return response()->json(['message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400); } $destination = $destinations->first(); if ($destinations->count() > 1 && $request->has('destination_uuid')) { $destination = $destinations->where('uuid', $request->destination_uuid)->first(); if (! $destination) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'destination_uuid' => 'Provided destination_uuid does not belong to the specified server.', ], ], 422); } } if ($type === 'public') { $validationRules = [ 'git_repository' => ['string', 'required', new ValidGitRepositoryUrl], 'git_branch' => ['string', 'required', new ValidGitBranch], 'build_pack' => ['required', Rule::enum(BuildPackTypes::class)], 'ports_exposes' => 'string|regex:/^(\d+)(,\d+)*$/|required', 'docker_compose_domains' => 'array|nullable', 'docker_compose_domains.*' => 'array:name,domain', 'docker_compose_domains.*.name' => 'string|required', 'docker_compose_domains.*.domain' => 'string|nullable', ]; // ports_exposes is not required for dockercompose if ($request->build_pack === 'dockercompose') { $validationRules['ports_exposes'] = 'string'; $request->offsetSet('ports_exposes', '80'); } $validationRules = array_merge(sharedDataApplications(), $validationRules); $validationMessages = [ 'docker_compose_domains.*.array' => 'An item in the docker_compose_domains array has invalid fields. Only a name and domain field are supported.', ]; $validator = Validator::make($request->all(), $validationRules, $validationMessages); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } // For dockercompose applications, domains (fqdn) field should not be used // Only docker_compose_domains should be used to set domains for individual services if ($request->build_pack === 'dockercompose' && $request->has('domains')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'domains' => 'The domains field cannot be used for dockercompose applications. Use docker_compose_domains instead to set domains for individual services.', ], ], 422); } if (! $request->has('name')) { $request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch)); } $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $application = new Application; removeUnnecessaryFieldsFromRequest($request); $application->fill($request->all()); $dockerComposeDomainsJson = collect(); if ($request->has('docker_compose_domains')) { $dockerComposeDomains = collect($request->docker_compose_domains); // Collect all URLs from all docker_compose_domains items $urls = $dockerComposeDomains->flatMap(function ($item) { $domainValue = data_get($item, 'domain'); if (blank($domainValue)) { return []; } return str($domainValue)->replaceStart(',', '')->replaceEnd(',', '')->trim()->explode(',')->map(fn ($url) => trim($url))->filter(); }); $errors = []; $urls = $urls->map(function ($url) use (&$errors) { if (! filter_var($url, FILTER_VALIDATE_URL)) { $errors[] = "Invalid URL: {$url}"; return $url; } $scheme = parse_url($url, PHP_URL_SCHEME) ?? ''; if (! in_array(strtolower($scheme), ['http', 'https'])) { $errors[] = "Invalid URL scheme: {$scheme} for URL: {$url}. Only http and https are supported."; } return $url; }); $duplicates = $urls->duplicates()->unique()->values(); if ($duplicates->isNotEmpty() && ! $request->boolean('force_domain_override')) { $errors[] = 'The current request contains conflicting URLs: '.implode(', ', $duplicates->toArray()).' Use force_domain_override=true to proceed.'; } if (count($errors) > 0) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $errors], ], 422); } // Check for domain conflicts if ($urls->isNotEmpty()) { $result = checkIfDomainIsAlreadyUsedViaAPI($urls, $teamId); if (isset($result['error'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $result['error']], ], 422); } if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], 'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.', ], 409); } } $dockerComposeDomains->each(function ($domain) use ($dockerComposeDomainsJson) { $dockerComposeDomainsJson->put(data_get($domain, 'name'), ['domain' => data_get($domain, 'domain')]); }); $request->offsetUnset('docker_compose_domains'); } if ($dockerComposeDomainsJson->count() > 0) { $application->docker_compose_domains = $dockerComposeDomainsJson; } $repository_url_parsed = Url::fromString($request->git_repository); $git_host = $repository_url_parsed->getHost(); if ($git_host === 'github.com') { $application->source_type = GithubApp::class; $application->source_id = GithubApp::find(0)->id; } $application->git_repository = str($repository_url_parsed->getSegment(1).'/'.$repository_url_parsed->getSegment(2))->trim()->toString(); $application->fqdn = $fqdn; $application->destination_id = $destination->id; $application->destination_type = $destination->getMorphClass(); $application->environment_id = $environment->id; $application->save(); if (isset($isStatic)) { $application->settings->is_static = $isStatic; $application->settings->save(); } if (isset($isSpa)) { $application->settings->is_spa = $isSpa; $application->settings->save(); } if (isset($isAutoDeployEnabled)) { $application->settings->is_auto_deploy_enabled = $isAutoDeployEnabled; $application->settings->save(); } if (isset($isForceHttpsEnabled)) { $application->settings->is_force_https_enabled = $isForceHttpsEnabled; $application->settings->save(); } if (isset($connectToDockerNetwork)) { $application->settings->connect_to_docker_network = $connectToDockerNetwork; $application->settings->save(); } if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); } if (isset($isContainerLabelEscapeEnabled)) { $application->settings->is_container_label_escape_enabled = $isContainerLabelEscapeEnabled; $application->settings->save(); } $application->refresh(); // Auto-generate domain if requested and no custom domain provided if ($autogenerateDomain && blank($fqdn)) { $application->fqdn = generateUrl(server: $server, random: $application->uuid); $application->save(); } if ($application->settings->is_container_label_readonly_enabled) { $application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n"); $application->save(); } $application->isConfigurationChanged(true); if ($instantDeploy) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, no_questions_asked: true, is_api: true, ); if ($result['status'] === 'skipped') { return response()->json([ 'message' => $result['message'], ], 200); } } else { if ($application->build_pack === 'dockercompose') { LoadComposeFile::dispatch($application); } } return response()->json(serializeApiResponse([ 'uuid' => data_get($application, 'uuid'), 'domains' => data_get($application, 'fqdn'), ]))->setStatusCode(201); } elseif ($type === 'private-gh-app') { $validationRules = [ 'git_repository' => 'string|required', 'git_branch' => ['string', 'required', new ValidGitBranch], 'build_pack' => ['required', Rule::enum(BuildPackTypes::class)], 'ports_exposes' => 'string|regex:/^(\d+)(,\d+)*$/|required', 'github_app_uuid' => 'string|required', 'watch_paths' => 'string|nullable', 'docker_compose_domains' => 'array|nullable', 'docker_compose_domains.*' => 'array:name,domain', 'docker_compose_domains.*.name' => 'string|required', 'docker_compose_domains.*.domain' => 'string|nullable', ]; $validationRules = array_merge(sharedDataApplications(), $validationRules); $validationMessages = [ 'docker_compose_domains.*.array' => 'An item in the docker_compose_domains array has invalid fields. Only a name and domain field are supported.', ]; $validator = Validator::make($request->all(), $validationRules, $validationMessages); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } // For dockercompose applications, domains (fqdn) field should not be used // Only docker_compose_domains should be used to set domains for individual services if ($request->build_pack === 'dockercompose' && $request->has('domains')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'domains' => 'The domains field cannot be used for dockercompose applications. Use docker_compose_domains instead to set domains for individual services.', ], ], 422); } if (! $request->has('name')) { $request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch)); } if ($request->build_pack === 'dockercompose') { $request->offsetSet('ports_exposes', '80'); } $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $githubApp = GithubApp::whereTeamId($teamId)->where('uuid', $githubAppUuid)->first(); if (! $githubApp) { return response()->json(['message' => 'Github App not found.'], 404); } $token = generateGithubInstallationToken($githubApp); if (! $token) { return response()->json(['message' => 'Failed to generate Github App token.'], 400); } $gitRepository = $request->git_repository; if (str($gitRepository)->startsWith('http') || str($gitRepository)->contains('github.com')) { $gitRepository = str($gitRepository)->replace('https://', '')->replace('http://', '')->replace('github.com/', ''); } $gitRepository = str($gitRepository)->trim('/')->replaceEnd('.git', '')->toString(); // Use direct API call to verify repository access instead of loading all repositories // This is much faster and avoids timeouts for GitHub Apps with many repositories $response = Http::GitHub($githubApp->api_url, $token) ->timeout(20) ->retry(3, 200, throw: false) ->get("/repos/{$gitRepository}"); if ($response->status() === 404 || $response->status() === 403) { return response()->json(['message' => 'Repository not found or not accessible by the GitHub App.'], 404); } if (! $response->successful()) { return response()->json(['message' => 'Failed to verify repository access: '.($response->json()['message'] ?? 'Unknown error')], 400); } $gitRepositoryFound = $response->json(); $repository_project_id = data_get($gitRepositoryFound, 'id'); $application = new Application; removeUnnecessaryFieldsFromRequest($request); $application->fill($request->all()); $dockerComposeDomainsJson = collect(); if ($request->has('docker_compose_domains')) { $dockerComposeDomains = collect($request->docker_compose_domains); // Collect all URLs from all docker_compose_domains items $urls = $dockerComposeDomains->flatMap(function ($item) { $domainValue = data_get($item, 'domain'); if (blank($domainValue)) { return []; } return str($domainValue)->replaceStart(',', '')->replaceEnd(',', '')->trim()->explode(',')->map(fn ($url) => trim($url))->filter(); }); $errors = []; $urls = $urls->map(function ($url) use (&$errors) { if (! filter_var($url, FILTER_VALIDATE_URL)) { $errors[] = "Invalid URL: {$url}"; return $url; } $scheme = parse_url($url, PHP_URL_SCHEME) ?? ''; if (! in_array(strtolower($scheme), ['http', 'https'])) { $errors[] = "Invalid URL scheme: {$scheme} for URL: {$url}. Only http and https are supported."; } return $url; }); $duplicates = $urls->duplicates()->unique()->values(); if ($duplicates->isNotEmpty() && ! $request->boolean('force_domain_override')) { $errors[] = 'The current request contains conflicting URLs: '.implode(', ', $duplicates->toArray()).' Use force_domain_override=true to proceed. '; } if (count($errors) > 0) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $errors], ], 422); } // Check for domain conflicts if ($urls->isNotEmpty()) { $result = checkIfDomainIsAlreadyUsedViaAPI($urls, $teamId); if (isset($result['error'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $result['error']], ], 422); } if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], 'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.', ], 409); } } $dockerComposeDomains->each(function ($domain) use ($dockerComposeDomainsJson) { $dockerComposeDomainsJson->put(data_get($domain, 'name'), ['domain' => data_get($domain, 'domain')]); }); $request->offsetUnset('docker_compose_domains'); } if ($dockerComposeDomainsJson->count() > 0) { $application->docker_compose_domains = $dockerComposeDomainsJson; } $application->fqdn = $fqdn; $application->git_repository = str($gitRepository)->trim()->toString(); $application->destination_id = $destination->id; $application->destination_type = $destination->getMorphClass(); $application->environment_id = $environment->id; $application->source_type = $githubApp->getMorphClass(); $application->source_id = $githubApp->id; $application->repository_project_id = $repository_project_id; $application->save(); $application->refresh(); // Auto-generate domain if requested and no custom domain provided if ($autogenerateDomain && blank($fqdn)) { $application->fqdn = generateUrl(server: $server, random: $application->uuid); $application->save(); } if (isset($isStatic)) { $application->settings->is_static = $isStatic; $application->settings->save(); } if (isset($isSpa)) { $application->settings->is_spa = $isSpa; $application->settings->save(); } if (isset($isAutoDeployEnabled)) { $application->settings->is_auto_deploy_enabled = $isAutoDeployEnabled; $application->settings->save(); } if (isset($isForceHttpsEnabled)) { $application->settings->is_force_https_enabled = $isForceHttpsEnabled; $application->settings->save(); } if (isset($connectToDockerNetwork)) { $application->settings->connect_to_docker_network = $connectToDockerNetwork; $application->settings->save(); } if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); } if (isset($isContainerLabelEscapeEnabled)) { $application->settings->is_container_label_escape_enabled = $isContainerLabelEscapeEnabled; $application->settings->save(); } if ($application->settings->is_container_label_readonly_enabled) { $application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n"); $application->save(); } $application->isConfigurationChanged(true); if ($instantDeploy) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, no_questions_asked: true, is_api: true, ); if ($result['status'] === 'skipped') { return response()->json([ 'message' => $result['message'], ], 200); } } else { if ($application->build_pack === 'dockercompose') { LoadComposeFile::dispatch($application); } } return response()->json(serializeApiResponse([ 'uuid' => data_get($application, 'uuid'), 'domains' => data_get($application, 'fqdn'), ]))->setStatusCode(201); } elseif ($type === 'private-deploy-key') { $validationRules = [ 'git_repository' => ['string', 'required', new ValidGitRepositoryUrl], 'git_branch' => ['string', 'required', new ValidGitBranch], 'build_pack' => ['required', Rule::enum(BuildPackTypes::class)], 'ports_exposes' => 'string|regex:/^(\d+)(,\d+)*$/|required', 'private_key_uuid' => 'string|required', 'watch_paths' => 'string|nullable', 'docker_compose_domains' => 'array|nullable', 'docker_compose_domains.*' => 'array:name,domain', 'docker_compose_domains.*.name' => 'string|required', 'docker_compose_domains.*.domain' => 'string|nullable', ]; $validationRules = array_merge(sharedDataApplications(), $validationRules); $validationMessages = [ 'docker_compose_domains.*.array' => 'An item in the docker_compose_domains array has invalid fields. Only a name and domain field are supported.', ]; $validator = Validator::make($request->all(), $validationRules, $validationMessages); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } // For dockercompose applications, domains (fqdn) field should not be used // Only docker_compose_domains should be used to set domains for individual services if ($request->build_pack === 'dockercompose' && $request->has('domains')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'domains' => 'The domains field cannot be used for dockercompose applications. Use docker_compose_domains instead to set domains for individual services.', ], ], 422); } if (! $request->has('name')) { $request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch)); } if ($request->build_pack === 'dockercompose') { $request->offsetSet('ports_exposes', '80'); } $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $privateKey = PrivateKey::whereTeamId($teamId)->where('uuid', $request->private_key_uuid)->first(); if (! $privateKey) { return response()->json(['message' => 'Private Key not found.'], 404); } $application = new Application; removeUnnecessaryFieldsFromRequest($request); $application->fill($request->all()); $dockerComposeDomainsJson = collect(); if ($request->has('docker_compose_domains')) { $dockerComposeDomains = collect($request->docker_compose_domains); // Collect all URLs from all docker_compose_domains items $urls = $dockerComposeDomains->flatMap(function ($item) { $domainValue = data_get($item, 'domain'); if (blank($domainValue)) { return []; } return str($domainValue)->replaceStart(',', '')->replaceEnd(',', '')->trim()->explode(',')->map(fn ($url) => trim($url))->filter(); }); $errors = []; $urls = $urls->map(function ($url) use (&$errors) { if (! filter_var($url, FILTER_VALIDATE_URL)) { $errors[] = "Invalid URL: {$url}"; return $url; } $scheme = parse_url($url, PHP_URL_SCHEME) ?? ''; if (! in_array(strtolower($scheme), ['http', 'https'])) { $errors[] = "Invalid URL scheme: {$scheme} for URL: {$url}. Only http and https are supported."; } return $url; }); $duplicates = $urls->duplicates()->unique()->values(); if ($duplicates->isNotEmpty() && ! $request->boolean('force_domain_override')) { $errors[] = 'The current request contains conflicting URLs: '.implode(', ', $duplicates->toArray()).' Use force_domain_override=true to proceed.'; } if (count($errors) > 0) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $errors], ], 422); } // Check for domain conflicts if ($urls->isNotEmpty()) { $result = checkIfDomainIsAlreadyUsedViaAPI($urls, $teamId); if (isset($result['error'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $result['error']], ], 422); } if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], 'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.', ], 409); } } $dockerComposeDomains->each(function ($domain) use ($dockerComposeDomainsJson) { $dockerComposeDomainsJson->put(data_get($domain, 'name'), ['domain' => data_get($domain, 'domain')]); }); $request->offsetUnset('docker_compose_domains'); } if ($dockerComposeDomainsJson->count() > 0) { $application->docker_compose_domains = $dockerComposeDomainsJson; } $application->fqdn = $fqdn; $application->private_key_id = $privateKey->id; $application->destination_id = $destination->id; $application->destination_type = $destination->getMorphClass(); $application->environment_id = $environment->id; $application->save(); $application->refresh(); // Auto-generate domain if requested and no custom domain provided if ($autogenerateDomain && blank($fqdn)) { $application->fqdn = generateUrl(server: $server, random: $application->uuid); $application->save(); } if (isset($isStatic)) { $application->settings->is_static = $isStatic; $application->settings->save(); } if (isset($isSpa)) { $application->settings->is_spa = $isSpa; $application->settings->save(); } if (isset($isAutoDeployEnabled)) { $application->settings->is_auto_deploy_enabled = $isAutoDeployEnabled; $application->settings->save(); } if (isset($isForceHttpsEnabled)) { $application->settings->is_force_https_enabled = $isForceHttpsEnabled; $application->settings->save(); } if (isset($connectToDockerNetwork)) { $application->settings->connect_to_docker_network = $connectToDockerNetwork; $application->settings->save(); } if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); } if (isset($isContainerLabelEscapeEnabled)) { $application->settings->is_container_label_escape_enabled = $isContainerLabelEscapeEnabled; $application->settings->save(); } if ($application->settings->is_container_label_readonly_enabled) { $application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n"); $application->save(); } $application->isConfigurationChanged(true); if ($instantDeploy) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, no_questions_asked: true, is_api: true, ); if ($result['status'] === 'skipped') { return response()->json([ 'message' => $result['message'], ], 200); } } else { if ($application->build_pack === 'dockercompose') { LoadComposeFile::dispatch($application); } } return response()->json(serializeApiResponse([ 'uuid' => data_get($application, 'uuid'), 'domains' => data_get($application, 'fqdn'), ]))->setStatusCode(201); } elseif ($type === 'dockerfile') { $validationRules = [ 'dockerfile' => 'string|required', ]; $validationRules = array_merge(sharedDataApplications(), $validationRules); $validator = customApiValidator($request->all(), $validationRules); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } if (! $request->has('name')) { $request->offsetSet('name', 'dockerfile-'.new Cuid2); } $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } if (! isBase64Encoded($request->dockerfile)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'dockerfile' => 'The dockerfile should be base64 encoded.', ], ], 422); } $dockerFile = base64_decode($request->dockerfile); if (mb_detect_encoding($dockerFile, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'dockerfile' => 'The dockerfile should be base64 encoded.', ], ], 422); } $dockerFile = base64_decode($request->dockerfile); removeUnnecessaryFieldsFromRequest($request); $port = get_port_from_dockerfile($request->dockerfile); if (! $port) { $port = 80; } $application = new Application; $application->fill($request->all()); $application->fqdn = $fqdn; $application->ports_exposes = $port; $application->build_pack = 'dockerfile'; $application->dockerfile = $dockerFile; $application->destination_id = $destination->id; $application->destination_type = $destination->getMorphClass(); $application->environment_id = $environment->id; $application->git_repository = 'coollabsio/coolify'; $application->git_branch = 'main'; $application->save(); $application->refresh(); // Auto-generate domain if requested and no custom domain provided if ($autogenerateDomain && blank($fqdn)) { $application->fqdn = generateUrl(server: $server, random: $application->uuid); $application->save(); } if (isset($isForceHttpsEnabled)) { $application->settings->is_force_https_enabled = $isForceHttpsEnabled; $application->settings->save(); } if (isset($connectToDockerNetwork)) { $application->settings->connect_to_docker_network = $connectToDockerNetwork; $application->settings->save(); } if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); } if (isset($isContainerLabelEscapeEnabled)) { $application->settings->is_container_label_escape_enabled = $isContainerLabelEscapeEnabled; $application->settings->save(); } if ($application->settings->is_container_label_readonly_enabled) { $application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n"); $application->save(); } $application->isConfigurationChanged(true); if ($instantDeploy) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, no_questions_asked: true, is_api: true, ); if ($result['status'] === 'skipped') { return response()->json([ 'message' => $result['message'], ], 200); } } return response()->json(serializeApiResponse([ 'uuid' => data_get($application, 'uuid'), 'domains' => data_get($application, 'fqdn'), ]))->setStatusCode(201); } elseif ($type === 'dockerimage') { $validationRules = [ 'docker_registry_image_name' => 'string|required', 'docker_registry_image_tag' => 'string', 'ports_exposes' => 'string|regex:/^(\d+)(,\d+)*$/|required', ]; $validationRules = array_merge(sharedDataApplications(), $validationRules); $validator = customApiValidator($request->all(), $validationRules); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } if (! $request->has('name')) { $request->offsetSet('name', 'docker-image-'.new Cuid2); } $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } // Process docker image name and tag using DockerImageParser $dockerImageName = $request->docker_registry_image_name; $dockerImageTag = $request->docker_registry_image_tag; // Build the full Docker image string for parsing if ($dockerImageTag) { $dockerImageString = $dockerImageName.':'.$dockerImageTag; } else { $dockerImageString = $dockerImageName; } // Parse using DockerImageParser to normalize the image reference $parser = new DockerImageParser; $parser->parse($dockerImageString); // Get normalized image name and tag $normalizedImageName = $parser->getFullImageNameWithoutTag(); // Append @sha256 to image name if using digest if ($parser->isImageHash() && ! str_ends_with($normalizedImageName, '@sha256')) { $normalizedImageName .= '@sha256'; } // Set processed values back to request $request->offsetSet('docker_registry_image_name', $normalizedImageName); $request->offsetSet('docker_registry_image_tag', $parser->getTag()); $application = new Application; removeUnnecessaryFieldsFromRequest($request); $application->fill($request->all()); $application->fqdn = $fqdn; $application->build_pack = 'dockerimage'; $application->destination_id = $destination->id; $application->destination_type = $destination->getMorphClass(); $application->environment_id = $environment->id; $application->git_repository = 'coollabsio/coolify'; $application->git_branch = 'main'; $application->save(); $application->refresh(); // Auto-generate domain if requested and no custom domain provided if ($autogenerateDomain && blank($fqdn)) { $application->fqdn = generateUrl(server: $server, random: $application->uuid); $application->save(); } if (isset($isForceHttpsEnabled)) { $application->settings->is_force_https_enabled = $isForceHttpsEnabled; $application->settings->save(); } if (isset($connectToDockerNetwork)) { $application->settings->connect_to_docker_network = $connectToDockerNetwork; $application->settings->save(); } if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); } if (isset($isContainerLabelEscapeEnabled)) { $application->settings->is_container_label_escape_enabled = $isContainerLabelEscapeEnabled; $application->settings->save(); } if ($application->settings->is_container_label_readonly_enabled) { $application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n"); $application->save(); } $application->isConfigurationChanged(true); if ($instantDeploy) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, no_questions_asked: true, is_api: true, ); if ($result['status'] === 'skipped') { return response()->json([ 'message' => $result['message'], ], 200); } } return response()->json(serializeApiResponse([ 'uuid' => data_get($application, 'uuid'), 'domains' => data_get($application, 'fqdn'), ]))->setStatusCode(201); } elseif ($type === 'dockercompose') { $allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'instant_deploy', 'docker_compose_raw', 'force_domain_override', 'is_container_label_escape_enabled']; $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if (! $request->has('name')) { $request->offsetSet('name', 'service'.new Cuid2); } $validationRules = [ 'docker_compose_raw' => 'string|required', ]; $validationRules = array_merge(sharedDataApplications(), $validationRules); $validator = customApiValidator($request->all(), $validationRules); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } if (! isBase64Encoded($request->docker_compose_raw)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', ], ], 422); } $dockerComposeRaw = base64_decode($request->docker_compose_raw); if (mb_detect_encoding($dockerComposeRaw, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', ], ], 422); } $dockerCompose = base64_decode($request->docker_compose_raw); $dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $service = new Service; removeUnnecessaryFieldsFromRequest($request); $service->fill($request->all()); $service->docker_compose_raw = $dockerComposeRaw; $service->environment_id = $environment->id; $service->server_id = $server->id; $service->destination_id = $destination->id; $service->destination_type = $destination->getMorphClass(); if (isset($isContainerLabelEscapeEnabled)) { $service->is_container_label_escape_enabled = $isContainerLabelEscapeEnabled; } $service->save(); $service->parse(isNew: true); // Apply service-specific application prerequisites applyServiceApplicationPrerequisites($service); if ($instantDeploy) { StartService::dispatch($service); } return response()->json(serializeApiResponse([ 'uuid' => data_get($service, 'uuid'), 'domains' => data_get($service, 'domains'), ]))->setStatusCode(201); } return response()->json(['message' => 'Invalid type.'], 400); } #[OA\Get( summary: 'Get', description: 'Get application by UUID.', path: '/applications/{uuid}', operationId: 'get-application-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get application by UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( ref: '#/components/schemas/Application' ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function application_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } $this->authorize('view', $application); return response()->json($this->removeSensitiveData($application)); } #[OA\Get( summary: 'Get application logs.', description: 'Get application logs by UUID.', path: '/applications/{uuid}/logs', operationId: 'get-application-logs-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'lines', in: 'query', description: 'Number of lines to show from the end of the logs.', required: false, schema: new OA\Schema( type: 'integer', format: 'int32', default: 100, ) ), ], responses: [ new OA\Response( response: 200, description: 'Get application logs by UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'logs' => ['type' => 'string'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function logs_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } $containers = getCurrentApplicationContainerStatus($application->destination->server, $application->id); if ($containers->count() == 0) { return response()->json([ 'message' => 'Application is not running.', ], 400); } $container = $containers->first(); $status = getContainerStatus($application->destination->server, $container['Names']); if ($status !== 'running') { return response()->json([ 'message' => 'Application is not running.', ], 400); } $lines = $request->query->get('lines', 100) ?: 100; $logs = getContainerLogs($application->destination->server, $container['ID'], $lines); return response()->json([ 'logs' => $logs, ]); } #[OA\Delete( summary: 'Delete', description: 'Delete application by UUID.', path: '/applications/{uuid}', operationId: 'delete-application-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter(name: 'delete_configurations', in: 'query', required: false, description: 'Delete configurations.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'delete_volumes', in: 'query', required: false, description: 'Delete volumes.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'docker_cleanup', in: 'query', required: false, description: 'Run docker cleanup.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'delete_connected_networks', in: 'query', required: false, description: 'Delete connected networks.', schema: new OA\Schema(type: 'boolean', default: true)), ], responses: [ new OA\Response( response: 200, description: 'Application deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Application deleted.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function delete_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json([ 'message' => 'Application not found', ], 404); } $this->authorize('delete', $application); DeleteResourceJob::dispatch( resource: $application, deleteVolumes: $request->boolean('delete_volumes', true), deleteConnectedNetworks: $request->boolean('delete_connected_networks', true), deleteConfigurations: $request->boolean('delete_configurations', true), dockerCleanup: $request->boolean('docker_cleanup', true) ); return response()->json([ 'message' => 'Application deletion request queued.', ]); } #[OA\Patch( summary: 'Update', description: 'Update application by UUID.', path: '/applications/{uuid}', operationId: 'update-application-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Application updated.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name.'], 'github_app_uuid' => ['type' => 'string', 'description' => 'The Github App UUID.'], 'git_repository' => ['type' => 'string', 'description' => 'The git repository URL.'], 'git_branch' => ['type' => 'string', 'description' => 'The git branch.'], 'ports_exposes' => ['type' => 'string', 'description' => 'The ports to expose.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID.'], 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose'], 'description' => 'The build pack type.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'description' => ['type' => 'string', 'description' => 'The application description.'], 'domains' => ['type' => 'string', 'description' => 'The application URLs in a comma-separated list.'], 'git_commit_sha' => ['type' => 'string', 'description' => 'The git commit SHA.'], 'docker_registry_image_name' => ['type' => 'string', 'description' => 'The docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'description' => 'The docker registry image tag.'], 'is_static' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is static.'], 'is_spa' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.'], 'is_auto_deploy_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.'], 'is_force_https_enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if HTTPS is forced. Defaults to true.'], 'install_command' => ['type' => 'string', 'description' => 'The install command.'], 'build_command' => ['type' => 'string', 'description' => 'The build command.'], 'start_command' => ['type' => 'string', 'description' => 'The start command.'], 'ports_mappings' => ['type' => 'string', 'description' => 'The ports mappings.'], 'base_directory' => ['type' => 'string', 'description' => 'The base directory for all commands.'], 'publish_directory' => ['type' => 'string', 'description' => 'The publish directory.'], 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Health check enabled.'], 'health_check_path' => ['type' => 'string', 'description' => 'Health check path.'], 'health_check_port' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check port.'], 'health_check_host' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check host.'], 'health_check_method' => ['type' => 'string', 'description' => 'Health check method.'], 'health_check_return_code' => ['type' => 'integer', 'description' => 'Health check return code.'], 'health_check_scheme' => ['type' => 'string', 'description' => 'Health check scheme.'], 'health_check_response_text' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check response text.'], 'health_check_interval' => ['type' => 'integer', 'description' => 'Health check interval in seconds.'], 'health_check_timeout' => ['type' => 'integer', 'description' => 'Health check timeout in seconds.'], 'health_check_retries' => ['type' => 'integer', 'description' => 'Health check retries count.'], 'health_check_start_period' => ['type' => 'integer', 'description' => 'Health check start period in seconds.'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit.'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit.'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness.'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation.'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit.'], 'limits_cpuset' => ['type' => 'string', 'nullable' => true, 'description' => 'CPU set.'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares.'], 'custom_labels' => ['type' => 'string', 'description' => 'Custom labels.'], 'custom_docker_run_options' => ['type' => 'string', 'description' => 'Custom docker run options.'], 'post_deployment_command' => ['type' => 'string', 'description' => 'Post deployment command.'], 'post_deployment_command_container' => ['type' => 'string', 'description' => 'Post deployment command container.'], 'pre_deployment_command' => ['type' => 'string', 'description' => 'Pre deployment command.'], 'pre_deployment_command_container' => ['type' => 'string', 'description' => 'Pre deployment command container.'], 'manual_webhook_secret_github' => ['type' => 'string', 'description' => 'Manual webhook secret for Github.'], 'manual_webhook_secret_gitlab' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitlab.'], 'manual_webhook_secret_bitbucket' => ['type' => 'string', 'description' => 'Manual webhook secret for Bitbucket.'], 'manual_webhook_secret_gitea' => ['type' => 'string', 'description' => 'Manual webhook secret for Gitea.'], 'redirect' => ['type' => 'string', 'nullable' => true, 'description' => 'How to set redirect with Traefik / Caddy. www<->non-www.', 'enum' => ['www', 'non-www', 'both']], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'], 'dockerfile' => ['type' => 'string', 'description' => 'The Dockerfile content.'], 'dockerfile_location' => ['type' => 'string', 'description' => 'The Dockerfile location in the repository.'], 'docker_compose_location' => ['type' => 'string', 'description' => 'The Docker Compose location.'], 'docker_compose_custom_start_command' => ['type' => 'string', 'description' => 'The Docker Compose custom start command.'], 'docker_compose_custom_build_command' => ['type' => 'string', 'description' => 'The Docker Compose custom build command.'], 'docker_compose_domains' => [ 'type' => 'array', 'description' => 'Array of URLs to be applied to containers of a dockercompose application.', 'items' => new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The service name as defined in docker-compose.'], 'domain' => ['type' => 'string', 'description' => 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")'], ], ), ], 'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'], 'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], ], ) ), ] ), responses: [ new OA\Response( response: 200, description: 'Application updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), ] )] public function update_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json([ 'message' => 'Application not found', ], 404); } $this->authorize('update', $application); $server = $application->destination->server; $allowedFields = ['name', 'description', 'is_static', 'is_spa', 'is_auto_deploy_enabled', 'is_force_https_enabled', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'custom_network_aliases', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_type', 'health_check_command', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'dockerfile_location', 'docker_compose_location', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network', 'force_domain_override', 'is_container_label_escape_enabled']; $validationRules = [ 'name' => 'string|max:255', 'description' => 'string|nullable', 'static_image' => 'string', 'watch_paths' => 'string|nullable', 'docker_compose_domains' => 'array|nullable', 'docker_compose_domains.*' => 'array:name,domain', 'docker_compose_domains.*.name' => 'string|required', 'docker_compose_domains.*.domain' => 'string|nullable', 'docker_compose_custom_start_command' => 'string|nullable', 'docker_compose_custom_build_command' => 'string|nullable', 'custom_nginx_configuration' => 'string|nullable', 'is_http_basic_auth_enabled' => 'boolean|nullable', 'http_basic_auth_username' => 'string', 'http_basic_auth_password' => 'string', ]; $validationRules = array_merge(sharedDataApplications(), $validationRules); $validationMessages = [ 'docker_compose_domains.*.array' => 'An item in the docker_compose_domains array has invalid fields. Only a name and domain field are supported.', ]; $validator = Validator::make($request->all(), $validationRules, $validationMessages); // Validate ports_exposes if ($request->has('ports_exposes')) { $ports = explode(',', $request->ports_exposes); foreach ($ports as $port) { if (! is_numeric($port)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'ports_exposes' => 'The ports_exposes should be a comma separated list of numbers.', ], ], 422); } } } if ($request->has('custom_nginx_configuration')) { if (! isBase64Encoded($request->custom_nginx_configuration)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.', ], ], 422); } $customNginxConfiguration = base64_decode($request->custom_nginx_configuration); if (mb_detect_encoding($customNginxConfiguration, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'custom_nginx_configuration' => 'The custom_nginx_configuration should be base64 encoded.', ], ], 422); } } $return = $this->validateDataApplications($request, $server); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if ($request->has('is_http_basic_auth_enabled') && $request->is_http_basic_auth_enabled === true) { if (blank($application->http_basic_auth_username) || blank($application->http_basic_auth_password)) { $validationErrors = []; if (blank($request->http_basic_auth_username)) { $validationErrors['http_basic_auth_username'] = 'The http_basic_auth_username is required.'; } if (blank($request->http_basic_auth_password)) { $validationErrors['http_basic_auth_password'] = 'The http_basic_auth_password is required.'; } if (count($validationErrors) > 0) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validationErrors, ], 422); } } } if ($request->has('is_http_basic_auth_enabled') && $application->is_container_label_readonly_enabled === false) { $application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n"); $application->save(); } // For dockercompose applications, domains (fqdn) field should not be used // Only docker_compose_domains should be used to set domains for individual services if ($application->build_pack === 'dockercompose' && $request->has('domains')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'domains' => 'The domains field cannot be used for dockercompose applications. Use docker_compose_domains instead to set domains for individual services.', ], ], 422); } $domains = $request->domains; $requestHasDomains = $request->has('domains'); if ($requestHasDomains && $server->isProxyShouldRun()) { $uuid = $request->uuid; $urls = $request->domains; $urls = str($urls)->replaceStart(',', '')->replaceEnd(',', '')->trim(); $errors = []; $urls = str($urls)->trim()->explode(',')->map(function ($url) use (&$errors) { $url = trim($url); // If "domains" is empty clear all URLs from the fqdn column if (blank($url)) { return null; } if (! filter_var($url, FILTER_VALIDATE_URL)) { $errors[] = 'Invalid URL: '.$url; return $url; } $scheme = parse_url($url, PHP_URL_SCHEME) ?? ''; if (! in_array(strtolower($scheme), ['http', 'https'])) { $errors[] = "Invalid URL scheme: {$scheme} for URL: {$url}. Only http and https are supported."; } return str($url)->lower(); }); if (count($errors) > 0) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } // Check for domain conflicts $result = checkIfDomainIsAlreadyUsedViaAPI($urls, $teamId, $uuid); if (isset($result['error'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['domains' => $result['error']], ], 422); } // If there are conflicts and force is not enabled, return warning if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], 'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.', ], 409); } } $dockerComposeDomainsJson = collect(); if ($request->has('docker_compose_domains')) { if (empty($application->docker_compose_raw)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_domains' => 'Cannot set docker_compose_domains without docker_compose_raw. Reload the compose file from the git repository first.', ], ], 422); } $dockerComposeDomains = collect($request->docker_compose_domains); // Collect all URLs from all docker_compose_domains items $urls = $dockerComposeDomains->flatMap(function ($item) { $domainValue = data_get($item, 'domain'); if (blank($domainValue)) { return []; } return str($domainValue)->replaceStart(',', '')->replaceEnd(',', '')->trim()->explode(',')->map(fn ($url) => trim($url))->filter(); }); $errors = []; $urls = $urls->map(function ($url) use (&$errors) { if (! filter_var($url, FILTER_VALIDATE_URL)) { $errors[] = "Invalid URL: {$url}"; return $url; } $scheme = parse_url($url, PHP_URL_SCHEME) ?? ''; if (! in_array(strtolower($scheme), ['http', 'https'])) { $errors[] = "Invalid URL scheme: {$scheme} for URL: {$url}. Only http and https are supported."; } return $url; }); $duplicates = $urls->duplicates()->unique()->values(); if ($duplicates->isNotEmpty() && ! $request->boolean('force_domain_override')) { $errors[] = 'The current request contains conflicting URLs: '.implode(', ', $duplicates->toArray()).' Use force_domain_override=true to proceed.'; } if (count($errors) > 0) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $errors], ], 422); } // Check for domain conflicts if ($urls->isNotEmpty()) { $result = checkIfDomainIsAlreadyUsedViaAPI($urls, $teamId, $request->uuid); if (isset($result['error'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['docker_compose_domains' => $result['error']], ], 422); } if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], 'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.', ], 409); } } $yaml = Yaml::parse($application->docker_compose_raw); $services = data_get($yaml, 'services', []); $dockerComposeDomains->each(function ($domain) use ($services, $dockerComposeDomainsJson) { $name = data_get($domain, 'name'); if ($name && is_array($services) && isset($services[$name])) { $dockerComposeDomainsJson->put($name, ['domain' => data_get($domain, 'domain')]); } }); $request->offsetUnset('docker_compose_domains'); } $instantDeploy = $request->instant_deploy; $isStatic = $request->is_static; $isSpa = $request->is_spa; $isAutoDeployEnabled = $request->is_auto_deploy_enabled; $isForceHttpsEnabled = $request->is_force_https_enabled; $connectToDockerNetwork = $request->connect_to_docker_network; $useBuildServer = $request->use_build_server; $isContainerLabelEscapeEnabled = $request->boolean('is_container_label_escape_enabled'); if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); } if (isset($isStatic)) { $application->settings->is_static = $isStatic; $application->settings->save(); } if (isset($isSpa)) { $application->settings->is_spa = $isSpa; $application->settings->save(); } if (isset($isAutoDeployEnabled)) { $application->settings->is_auto_deploy_enabled = $isAutoDeployEnabled; $application->settings->save(); } if (isset($isForceHttpsEnabled)) { $application->settings->is_force_https_enabled = $isForceHttpsEnabled; $application->settings->save(); } if (isset($connectToDockerNetwork)) { $application->settings->connect_to_docker_network = $connectToDockerNetwork; $application->settings->save(); } if ($request->has('is_container_label_escape_enabled')) { $application->settings->is_container_label_escape_enabled = $isContainerLabelEscapeEnabled; $application->settings->save(); } removeUnnecessaryFieldsFromRequest($request); $data = $request->all(); if ($requestHasDomains && $server->isProxyShouldRun()) { data_set($data, 'fqdn', $domains); } if ($dockerComposeDomainsJson->count() > 0) { data_set($data, 'docker_compose_domains', json_encode($dockerComposeDomainsJson)); } $application->fill($data); if ($application->settings->is_container_label_readonly_enabled && $requestHasDomains && $server->isProxyShouldRun()) { $application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n"); } $application->save(); if ($instantDeploy) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, is_api: true, ); if ($result['status'] === 'skipped') { return response()->json([ 'message' => $result['message'], ], 200); } } return response()->json([ 'uuid' => $application->uuid, ]); } #[OA\Get( summary: 'List Envs', description: 'List all envs by application UUID.', path: '/applications/{uuid}/envs', operationId: 'list-envs-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'All environment variables by application UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/EnvironmentVariable') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function envs(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json([ 'message' => 'Application not found', ], 404); } $this->authorize('view', $application); $envs = $application->environment_variables->sortBy('id')->merge($application->environment_variables_preview->sortBy('id')); $envs = $envs->map(function ($env) { $env->makeHidden([ 'service_id', 'standalone_clickhouse_id', 'standalone_dragonfly_id', 'standalone_keydb_id', 'standalone_mariadb_id', 'standalone_mongodb_id', 'standalone_mysql_id', 'standalone_postgresql_id', 'standalone_redis_id', ]); return $this->removeSensitiveData($env); }); return response()->json($envs); } #[OA\Patch( summary: 'Update Env', description: 'Update env by application UUID.', path: '/applications/{uuid}/envs', operationId: 'update-env-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Env updated.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['key', 'value'], properties: [ 'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'], 'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'], 'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'], 'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'], 'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'], 'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'], ], ), ), ], ), responses: [ new OA\Response( response: 201, description: 'Environment variable updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( ref: '#/components/schemas/EnvironmentVariable' ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function update_env_by_uuid(Request $request) { $allowedFields = ['key', 'value', 'is_preview', 'is_literal', 'is_multiline', 'is_shown_once', 'is_runtime', 'is_buildtime', 'comment']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json([ 'message' => 'Application not found', ], 404); } $this->authorize('manageEnvironment', $application); $validator = customApiValidator($request->all(), [ 'key' => 'string|required', 'value' => 'string|nullable', 'is_preview' => 'boolean', 'is_literal' => 'boolean', 'is_multiline' => 'boolean', 'is_shown_once' => 'boolean', 'is_runtime' => 'boolean', 'is_buildtime' => 'boolean', 'comment' => 'string|nullable|max:256', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $is_preview = $request->is_preview ?? false; $is_literal = $request->is_literal ?? false; $key = str($request->key)->trim()->replace(' ', '_')->value; if ($is_preview) { $env = $application->environment_variables_preview->where('key', $key)->first(); if ($env) { $env->value = $request->value; if ($env->is_literal != $is_literal) { $env->is_literal = $is_literal; } if ($env->is_preview != $is_preview) { $env->is_preview = $is_preview; } if ($env->is_multiline != $request->is_multiline) { $env->is_multiline = $request->is_multiline; } if ($env->is_shown_once != $request->is_shown_once) { $env->is_shown_once = $request->is_shown_once; } if ($request->has('is_runtime') && $env->is_runtime != $request->is_runtime) { $env->is_runtime = $request->is_runtime; } if ($request->has('is_buildtime') && $env->is_buildtime != $request->is_buildtime) { $env->is_buildtime = $request->is_buildtime; } if ($request->has('comment') && $env->comment != $request->comment) { $env->comment = $request->comment; } $env->save(); return response()->json($this->removeSensitiveData($env))->setStatusCode(201); } else { return response()->json([ 'message' => 'Environment variable not found.', ], 404); } } else { $env = $application->environment_variables->where('key', $key)->first(); if ($env) { $env->value = $request->value; if ($env->is_literal != $is_literal) { $env->is_literal = $is_literal; } if ($env->is_preview != $is_preview) { $env->is_preview = $is_preview; } if ($env->is_multiline != $request->is_multiline) { $env->is_multiline = $request->is_multiline; } if ($env->is_shown_once != $request->is_shown_once) { $env->is_shown_once = $request->is_shown_once; } if ($request->has('is_runtime') && $env->is_runtime != $request->is_runtime) { $env->is_runtime = $request->is_runtime; } if ($request->has('is_buildtime') && $env->is_buildtime != $request->is_buildtime) { $env->is_buildtime = $request->is_buildtime; } if ($request->has('comment') && $env->comment != $request->comment) { $env->comment = $request->comment; } $env->save(); return response()->json($this->removeSensitiveData($env))->setStatusCode(201); } else { return response()->json([ 'message' => 'Environment variable not found.', ], 404); } } return response()->json([ 'message' => 'Something is not okay. Are you okay?', ], 500); } #[OA\Patch( summary: 'Update Envs (Bulk)', description: 'Update multiple envs by application UUID.', path: '/applications/{uuid}/envs/bulk', operationId: 'update-envs-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Bulk envs updated.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['data'], properties: [ 'data' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'], 'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'], 'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'], 'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'], 'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'], 'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'], ], ), ], ], ), ), ], ), responses: [ new OA\Response( response: 201, description: 'Environment variables updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/EnvironmentVariable') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function create_bulk_envs(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json([ 'message' => 'Application not found', ], 404); } $this->authorize('manageEnvironment', $application); $bulk_data = $request->get('data'); if (! $bulk_data) { return response()->json([ 'message' => 'Bulk data is required.', ], 400); } $bulk_data = collect($bulk_data)->map(function ($item) { return collect($item)->only(['key', 'value', 'is_preview', 'is_literal', 'is_multiline', 'is_shown_once', 'is_runtime', 'is_buildtime']); }); $returnedEnvs = collect(); foreach ($bulk_data as $item) { $validator = customApiValidator($item, [ 'key' => 'string|required', 'value' => 'string|nullable', 'is_preview' => 'boolean', 'is_literal' => 'boolean', 'is_multiline' => 'boolean', 'is_shown_once' => 'boolean', 'is_runtime' => 'boolean', 'is_buildtime' => 'boolean', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $is_preview = $item->get('is_preview') ?? false; $is_literal = $item->get('is_literal') ?? false; $is_multi_line = $item->get('is_multiline') ?? false; $is_shown_once = $item->get('is_shown_once') ?? false; $key = str($item->get('key'))->trim()->replace(' ', '_')->value; if ($is_preview) { $env = $application->environment_variables_preview->where('key', $key)->first(); if ($env) { $env->value = $item->get('value'); if ($env->is_literal != $is_literal) { $env->is_literal = $is_literal; } if ($env->is_multiline != $item->get('is_multiline')) { $env->is_multiline = $item->get('is_multiline'); } if ($env->is_shown_once != $item->get('is_shown_once')) { $env->is_shown_once = $item->get('is_shown_once'); } if ($item->has('is_runtime') && $env->is_runtime != $item->get('is_runtime')) { $env->is_runtime = $item->get('is_runtime'); } if ($item->has('is_buildtime') && $env->is_buildtime != $item->get('is_buildtime')) { $env->is_buildtime = $item->get('is_buildtime'); } $env->save(); } else { $env = $application->environment_variables()->create([ 'key' => $item->get('key'), 'value' => $item->get('value'), 'is_preview' => $is_preview, 'is_literal' => $is_literal, 'is_multiline' => $is_multi_line, 'is_shown_once' => $is_shown_once, 'is_runtime' => $item->get('is_runtime', true), 'is_buildtime' => $item->get('is_buildtime', true), 'resourceable_type' => get_class($application), 'resourceable_id' => $application->id, ]); } } else { $env = $application->environment_variables->where('key', $key)->first(); if ($env) { $env->value = $item->get('value'); if ($env->is_literal != $is_literal) { $env->is_literal = $is_literal; } if ($env->is_multiline != $item->get('is_multiline')) { $env->is_multiline = $item->get('is_multiline'); } if ($env->is_shown_once != $item->get('is_shown_once')) { $env->is_shown_once = $item->get('is_shown_once'); } if ($item->has('is_runtime') && $env->is_runtime != $item->get('is_runtime')) { $env->is_runtime = $item->get('is_runtime'); } if ($item->has('is_buildtime') && $env->is_buildtime != $item->get('is_buildtime')) { $env->is_buildtime = $item->get('is_buildtime'); } $env->save(); } else { $env = $application->environment_variables()->create([ 'key' => $item->get('key'), 'value' => $item->get('value'), 'is_preview' => $is_preview, 'is_literal' => $is_literal, 'is_multiline' => $is_multi_line, 'is_shown_once' => $is_shown_once, 'is_runtime' => $item->get('is_runtime', true), 'is_buildtime' => $item->get('is_buildtime', true), 'resourceable_type' => get_class($application), 'resourceable_id' => $application->id, ]); } } $returnedEnvs->push($this->removeSensitiveData($env)); } return response()->json($returnedEnvs)->setStatusCode(201); } #[OA\Post( summary: 'Create Env', description: 'Create env by application UUID.', path: '/applications/{uuid}/envs', operationId: 'create-env-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( required: true, description: 'Env created.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'], 'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'], 'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'], 'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'], 'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'], 'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Environment variable created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'nc0k04gk8g0cgsk440g0koko'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function create_env(Request $request) { $allowedFields = ['key', 'value', 'is_preview', 'is_literal', 'is_multiline', 'is_shown_once', 'is_runtime', 'is_buildtime', 'comment']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json([ 'message' => 'Application not found', ], 404); } $this->authorize('manageEnvironment', $application); $validator = customApiValidator($request->all(), [ 'key' => 'string|required', 'value' => 'string|nullable', 'is_preview' => 'boolean', 'is_literal' => 'boolean', 'is_multiline' => 'boolean', 'is_shown_once' => 'boolean', 'is_runtime' => 'boolean', 'is_buildtime' => 'boolean', 'comment' => 'string|nullable|max:256', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $is_preview = $request->is_preview ?? false; $key = str($request->key)->trim()->replace(' ', '_')->value; if ($is_preview) { $env = $application->environment_variables_preview->where('key', $key)->first(); if ($env) { return response()->json([ 'message' => 'Environment variable already exists. Use PATCH request to update it.', ], 409); } else { $env = $application->environment_variables()->create([ 'key' => $request->key, 'value' => $request->value, 'is_preview' => $request->is_preview ?? false, 'is_literal' => $request->is_literal ?? false, 'is_multiline' => $request->is_multiline ?? false, 'is_shown_once' => $request->is_shown_once ?? false, 'is_runtime' => $request->is_runtime ?? true, 'is_buildtime' => $request->is_buildtime ?? true, 'comment' => $request->comment ?? null, 'resourceable_type' => get_class($application), 'resourceable_id' => $application->id, ]); return response()->json([ 'uuid' => $env->uuid, ])->setStatusCode(201); } } else { $env = $application->environment_variables->where('key', $key)->first(); if ($env) { return response()->json([ 'message' => 'Environment variable already exists. Use PATCH request to update it.', ], 409); } else { $env = $application->environment_variables()->create([ 'key' => $request->key, 'value' => $request->value, 'is_preview' => $request->is_preview ?? false, 'is_literal' => $request->is_literal ?? false, 'is_multiline' => $request->is_multiline ?? false, 'is_shown_once' => $request->is_shown_once ?? false, 'is_runtime' => $request->is_runtime ?? true, 'is_buildtime' => $request->is_buildtime ?? true, 'comment' => $request->comment ?? null, 'resourceable_type' => get_class($application), 'resourceable_id' => $application->id, ]); return response()->json([ 'uuid' => $env->uuid, ])->setStatusCode(201); } } } #[OA\Delete( summary: 'Delete Env', description: 'Delete env by UUID.', path: '/applications/{uuid}/envs/{env_uuid}', operationId: 'delete-env-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'env_uuid', in: 'path', description: 'UUID of the environment variable.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Environment variable deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Environment variable deleted.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function delete_env_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json([ 'message' => 'Application not found.', ], 404); } $this->authorize('manageEnvironment', $application); $found_env = EnvironmentVariable::where('uuid', $request->env_uuid) ->where('resourceable_type', Application::class) ->where('resourceable_id', $application->id) ->first(); if (! $found_env) { return response()->json([ 'message' => 'Environment variable not found.', ], 404); } $found_env->forceDelete(); return response()->json([ 'message' => 'Environment variable deleted.', ]); } #[OA\Get( summary: 'Start', description: 'Start application. `Post` request is also accepted.', path: '/applications/{uuid}/start', operationId: 'start-application-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'force', in: 'query', description: 'Force rebuild.', schema: new OA\Schema( type: 'boolean', default: false, ) ), new OA\Parameter( name: 'instant_deploy', in: 'query', description: 'Instant deploy (skip queuing).', schema: new OA\Schema( type: 'boolean', default: false, ) ), ], responses: [ new OA\Response( response: 200, description: 'Start application.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Deployment request queued.', 'description' => 'Message.'], 'deployment_uuid' => ['type' => 'string', 'example' => 'doogksw', 'description' => 'UUID of the deployment.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_deploy(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $force = $request->boolean('force', false); $instant_deploy = $request->boolean('instant_deploy', false); $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } $this->authorize('deploy', $application); $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, force_rebuild: $force, is_api: true, no_questions_asked: $instant_deploy ); if ($result['status'] === 'skipped') { return response()->json( [ 'message' => $result['message'], ], 200 ); } return response()->json( [ 'message' => 'Deployment request queued.', 'deployment_uuid' => $deployment_uuid->toString(), ], 200 ); } #[OA\Get( summary: 'Stop', description: 'Stop application. `Post` request is also accepted.', path: '/applications/{uuid}/stop', operationId: 'stop-application-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'docker_cleanup', in: 'query', description: 'Perform docker cleanup (prune networks, volumes, etc.).', schema: new OA\Schema( type: 'boolean', default: true, ) ), ], responses: [ new OA\Response( response: 200, description: 'Stop application.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Application stopping request queued.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_stop(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } $this->authorize('deploy', $application); $dockerCleanup = $request->boolean('docker_cleanup', true); StopApplication::dispatch($application, false, $dockerCleanup); return response()->json( [ 'message' => 'Application stopping request queued.', ], ); } #[OA\Get( summary: 'Restart', description: 'Restart application. `Post` request is also accepted.', path: '/applications/{uuid}/restart', operationId: 'restart-application-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Applications'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Restart application.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Restart request queued.'], 'deployment_uuid' => ['type' => 'string', 'example' => 'doogksw', 'description' => 'UUID of the deployment.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_restart(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } $this->authorize('deploy', $application); $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, restart_only: true, is_api: true, ); if ($result['status'] === 'skipped') { return response()->json([ 'message' => $result['message'], ], 200); } return response()->json( [ 'message' => 'Restart request queued.', 'deployment_uuid' => $deployment_uuid->toString(), ], ); } private function validateDataApplications(Request $request, Server $server) { $teamId = getTeamIdFromToken(); // Validate ports_mappings if ($request->has('ports_mappings')) { $ports = []; foreach (explode(',', $request->ports_mappings) as $portMapping) { $port = explode(':', $portMapping); if (in_array($port[0], $ports)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'ports_mappings' => 'The first number before : should be unique between mappings.', ], ], 422); } $ports[] = $port[0]; } } // Validate custom_labels if ($request->has('custom_labels')) { if (! isBase64Encoded($request->custom_labels)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'custom_labels' => 'The custom_labels should be base64 encoded.', ], ], 422); } $customLabels = base64_decode($request->custom_labels); if (mb_detect_encoding($customLabels, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'custom_labels' => 'The custom_labels should be base64 encoded.', ], ], 422); } } if ($request->has('domains') && $server->isProxyShouldRun()) { $uuid = $request->uuid; $urls = $request->domains; $urls = str($urls)->replaceEnd(',', '')->trim(); $urls = str($urls)->replaceStart(',', '')->trim(); $errors = []; $urls = str($urls)->trim()->explode(',')->map(function ($url) use (&$errors) { $url = trim($url); // If "domains" is empty clear all URLs from the fqdn column if (blank($url)) { return null; } if (! filter_var($url, FILTER_VALIDATE_URL)) { $errors[] = 'Invalid URL: '.$url; return str($url)->lower(); } $scheme = parse_url($url, PHP_URL_SCHEME) ?? ''; if (! in_array(strtolower($scheme), ['http', 'https'])) { $errors[] = "Invalid URL scheme: {$scheme} for URL: {$url}. Only http and https are supported."; } return str($url)->lower(); }); if (count($errors) > 0) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } // Check for domain conflicts $result = checkIfDomainIsAlreadyUsedViaAPI($urls, $teamId, $uuid); if (isset($result['error'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['domains' => $result['error']], ], 422); } // If there are conflicts and force is not enabled, return warning if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $result['conflicts'], 'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.', ], 409); } } } } ================================================ FILE: app/Http/Controllers/Api/CloudProviderTokensController.php ================================================ makeHidden([ 'id', 'token', ]); return serializeApiResponse($token); } /** * Validate a provider token against the provider's API. * * @return array{valid: bool, error: string|null} */ private function validateProviderToken(string $provider, string $token): array { try { $response = match ($provider) { 'hetzner' => Http::withHeaders([ 'Authorization' => 'Bearer '.$token, ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'), 'digitalocean' => Http::withHeaders([ 'Authorization' => 'Bearer '.$token, ])->timeout(10)->get('https://api.digitalocean.com/v2/account'), default => null, }; if ($response === null) { return ['valid' => false, 'error' => 'Unsupported provider.']; } if ($response->successful()) { return ['valid' => true, 'error' => null]; } return ['valid' => false, 'error' => "Invalid {$provider} token. Please check your API token."]; } catch (\Throwable $e) { Log::error('Failed to validate cloud provider token', [ 'provider' => $provider, 'exception' => $e->getMessage(), ]); return ['valid' => false, 'error' => 'Failed to validate token with provider API.']; } } #[OA\Get( summary: 'List Cloud Provider Tokens', description: 'List all cloud provider tokens for the authenticated team.', path: '/cloud-tokens', operationId: 'list-cloud-tokens', security: [ ['bearerAuth' => []], ], tags: ['Cloud Tokens'], responses: [ new OA\Response( response: 200, description: 'Get all cloud provider tokens.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'provider' => ['type' => 'string', 'enum' => ['hetzner', 'digitalocean']], 'team_id' => ['type' => 'integer'], 'servers_count' => ['type' => 'integer'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], ] ) ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function index(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $tokens = CloudProviderToken::whereTeamId($teamId) ->withCount('servers') ->get() ->map(function ($token) { return $this->removeSensitiveData($token); }); return response()->json($tokens); } #[OA\Get( summary: 'Get Cloud Provider Token', description: 'Get cloud provider token by UUID.', path: '/cloud-tokens/{uuid}', operationId: 'get-cloud-token-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Cloud Tokens'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Token UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Get cloud provider token by UUID', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'provider' => ['type' => 'string'], 'team_id' => ['type' => 'integer'], 'servers_count' => ['type' => 'integer'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function show(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $token = CloudProviderToken::whereTeamId($teamId) ->whereUuid($request->uuid) ->withCount('servers') ->first(); if (is_null($token)) { return response()->json(['message' => 'Cloud provider token not found.'], 404); } return response()->json($this->removeSensitiveData($token)); } #[OA\Post( summary: 'Create Cloud Provider Token', description: 'Create a new cloud provider token. The token will be validated before being stored.', path: '/cloud-tokens', operationId: 'create-cloud-token', security: [ ['bearerAuth' => []], ], tags: ['Cloud Tokens'], requestBody: new OA\RequestBody( required: true, description: 'Cloud provider token details', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['provider', 'token', 'name'], properties: [ 'provider' => ['type' => 'string', 'enum' => ['hetzner', 'digitalocean'], 'example' => 'hetzner', 'description' => 'The cloud provider.'], 'token' => ['type' => 'string', 'example' => 'your-api-token-here', 'description' => 'The API token for the cloud provider.'], 'name' => ['type' => 'string', 'example' => 'My Hetzner Token', 'description' => 'A friendly name for the token.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Cloud provider token created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'og888os', 'description' => 'The UUID of the token.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function store(Request $request) { $allowedFields = ['provider', 'token', 'name']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } // Use request body only (excludes any route parameters) $body = $request->json()->all(); $validator = customApiValidator($body, [ 'provider' => 'required|string|in:hetzner,digitalocean', 'token' => 'required|string', 'name' => 'required|string|max:255', ]); $extraFields = array_diff(array_keys($body), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } // Validate token with the provider's API $validation = $this->validateProviderToken($body['provider'], $body['token']); if (! $validation['valid']) { return response()->json(['message' => $validation['error']], 400); } $cloudProviderToken = CloudProviderToken::create([ 'team_id' => $teamId, 'provider' => $body['provider'], 'token' => $body['token'], 'name' => $body['name'], ]); return response()->json([ 'uuid' => $cloudProviderToken->uuid, ])->setStatusCode(201); } #[OA\Patch( summary: 'Update Cloud Provider Token', description: 'Update cloud provider token name.', path: '/cloud-tokens/{uuid}', operationId: 'update-cloud-token-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Cloud Tokens'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Token UUID', schema: new OA\Schema(type: 'string')), ], requestBody: new OA\RequestBody( required: true, description: 'Cloud provider token updated.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The friendly name for the token.'], ], ), ), ), responses: [ new OA\Response( response: 200, description: 'Cloud provider token updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update(Request $request) { $allowedFields = ['name']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } // Use request body only (excludes route parameters like uuid) $body = $request->json()->all(); $validator = customApiValidator($body, [ 'name' => 'required|string|max:255', ]); $extraFields = array_diff(array_keys($body), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } // Use route parameter for UUID lookup $token = CloudProviderToken::whereTeamId($teamId)->whereUuid($request->route('uuid'))->first(); if (! $token) { return response()->json(['message' => 'Cloud provider token not found.'], 404); } $token->update(array_intersect_key($body, array_flip($allowedFields))); return response()->json([ 'uuid' => $token->uuid, ]); } #[OA\Delete( summary: 'Delete Cloud Provider Token', description: 'Delete cloud provider token by UUID. Cannot delete if token is used by any servers.', path: '/cloud-tokens/{uuid}', operationId: 'delete-cloud-token-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Cloud Tokens'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the cloud provider token.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Cloud provider token deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Cloud provider token deleted.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function destroy(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 422); } $token = CloudProviderToken::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $token) { return response()->json(['message' => 'Cloud provider token not found.'], 404); } if ($token->hasServers()) { return response()->json(['message' => 'Cannot delete token that is used by servers.'], 400); } $token->delete(); return response()->json(['message' => 'Cloud provider token deleted.']); } #[OA\Post( summary: 'Validate Cloud Provider Token', description: 'Validate a cloud provider token against the provider API.', path: '/cloud-tokens/{uuid}/validate', operationId: 'validate-cloud-token-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Cloud Tokens'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Token UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Token validation result.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'valid' => ['type' => 'boolean', 'example' => true], 'message' => ['type' => 'string', 'example' => 'Token is valid.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function validateToken(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $cloudToken = CloudProviderToken::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $cloudToken) { return response()->json(['message' => 'Cloud provider token not found.'], 404); } $validation = $this->validateProviderToken($cloudToken->provider, $cloudToken->token); return response()->json([ 'valid' => $validation['valid'], 'message' => $validation['valid'] ? 'Token is valid.' : $validation['error'], ]); } } ================================================ FILE: app/Http/Controllers/Api/DatabasesController.php ================================================ makeHidden([ 'id', 'laravel_through_key', ]); if (request()->attributes->get('can_read_sensitive', false) === false) { $database->makeHidden([ 'internal_db_url', 'external_db_url', 'postgres_password', 'dragonfly_password', 'redis_password', 'mongo_initdb_root_password', 'keydb_password', 'clickhouse_admin_password', ]); } return serializeApiResponse($database); } #[OA\Get( summary: 'List', description: 'List all databases.', path: '/databases', operationId: 'list-databases', security: [ ['bearerAuth' => []], ], tags: ['Databases'], responses: [ new OA\Response( response: 200, description: 'Get all databases', content: new OA\JsonContent( type: 'string', example: 'Content is very complex. Will be implemented later.', ), ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function databases(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $projects = Project::where('team_id', $teamId)->get(); $databases = collect(); foreach ($projects as $project) { $databases = $databases->merge($project->databases()); } $databaseIds = $databases->pluck('id')->toArray(); $backupConfigs = ScheduledDatabaseBackup::ownedByCurrentTeamAPI($teamId)->with('latest_log') ->whereIn('database_id', $databaseIds) ->get() ->groupBy('database_id'); $databases = $databases->map(function ($database) use ($backupConfigs) { $database->backup_configs = $backupConfigs->get($database->id, collect())->values(); return $this->removeSensitiveData($database); }); return response()->json($databases); } #[OA\Get( summary: 'Get', description: 'Get backups details by database UUID.', path: '/databases/{uuid}/backups', operationId: 'get-database-backups-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get all backups for a database', content: new OA\JsonContent( type: 'string', example: 'Content is very complex. Will be implemented later.', ), ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function database_backup_details_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('view', $database); $backupConfig = ScheduledDatabaseBackup::ownedByCurrentTeamAPI($teamId)->with('executions')->where('database_id', $database->id)->get(); return response()->json($backupConfig); } #[OA\Get( summary: 'Get', description: 'Get database by UUID.', path: '/databases/{uuid}', operationId: 'get-database-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get all databases', content: new OA\JsonContent( type: 'string', example: 'Content is very complex. Will be implemented later.', ), ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function database_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('view', $database); return response()->json($this->removeSensitiveData($database)); } #[OA\Patch( summary: 'Update', description: 'Update database by UUID.', path: '/databases/{uuid}', operationId: 'update-database-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'postgres_user' => ['type' => 'string', 'description' => 'PostgreSQL user'], 'postgres_password' => ['type' => 'string', 'description' => 'PostgreSQL password'], 'postgres_db' => ['type' => 'string', 'description' => 'PostgreSQL database'], 'postgres_initdb_args' => ['type' => 'string', 'description' => 'PostgreSQL initdb args'], 'postgres_host_auth_method' => ['type' => 'string', 'description' => 'PostgreSQL host auth method'], 'postgres_conf' => ['type' => 'string', 'description' => 'PostgreSQL conf'], 'clickhouse_admin_user' => ['type' => 'string', 'description' => 'Clickhouse admin user'], 'clickhouse_admin_password' => ['type' => 'string', 'description' => 'Clickhouse admin password'], 'dragonfly_password' => ['type' => 'string', 'description' => 'DragonFly password'], 'redis_password' => ['type' => 'string', 'description' => 'Redis password'], 'redis_conf' => ['type' => 'string', 'description' => 'Redis conf'], 'keydb_password' => ['type' => 'string', 'description' => 'KeyDB password'], 'keydb_conf' => ['type' => 'string', 'description' => 'KeyDB conf'], 'mariadb_conf' => ['type' => 'string', 'description' => 'MariaDB conf'], 'mariadb_root_password' => ['type' => 'string', 'description' => 'MariaDB root password'], 'mariadb_user' => ['type' => 'string', 'description' => 'MariaDB user'], 'mariadb_password' => ['type' => 'string', 'description' => 'MariaDB password'], 'mariadb_database' => ['type' => 'string', 'description' => 'MariaDB database'], 'mongo_conf' => ['type' => 'string', 'description' => 'Mongo conf'], 'mongo_initdb_root_username' => ['type' => 'string', 'description' => 'Mongo initdb root username'], 'mongo_initdb_root_password' => ['type' => 'string', 'description' => 'Mongo initdb root password'], 'mongo_initdb_database' => ['type' => 'string', 'description' => 'Mongo initdb init database'], 'mysql_root_password' => ['type' => 'string', 'description' => 'MySQL root password'], 'mysql_password' => ['type' => 'string', 'description' => 'MySQL password'], 'mysql_user' => ['type' => 'string', 'description' => 'MySQL user'], 'mysql_database' => ['type' => 'string', 'description' => 'MySQL database'], 'mysql_conf' => ['type' => 'string', 'description' => 'MySQL conf'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_by_uuid(Request $request) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_database', 'mysql_root_password', 'mysql_password', 'mysql_user', 'mysql_database', 'mysql_conf']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // this check if the request is a valid json $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', 'description' => 'string|nullable', 'image' => 'string', 'is_public' => 'boolean', 'public_port' => 'numeric|nullable', 'limits_memory' => 'string', 'limits_memory_swap' => 'string', 'limits_memory_swappiness' => 'numeric', 'limits_memory_reservation' => 'string', 'limits_cpus' => 'string', 'limits_cpuset' => 'string|nullable', 'limits_cpu_shares' => 'numeric', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $uuid = $request->uuid; removeUnnecessaryFieldsFromRequest($request); $database = queryDatabaseByUuidWithinTeam($uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('update', $database); if ($request->is_public && $request->public_port) { if (isPublicPortAlreadyUsed($database->destination->server, $request->public_port, $database->id)) { return response()->json(['message' => 'Public port already used by another database.'], 400); } } switch ($database->type()) { case 'standalone-postgresql': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf']; $validator = customApiValidator($request->all(), [ 'postgres_user' => 'string', 'postgres_password' => 'string', 'postgres_db' => 'string', 'postgres_initdb_args' => 'string', 'postgres_host_auth_method' => 'string', 'postgres_conf' => 'string', ]); if ($request->has('postgres_conf')) { if (! isBase64Encoded($request->postgres_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'postgres_conf' => 'The postgres_conf should be base64 encoded.', ], ], 422); } $postgresConf = base64_decode($request->postgres_conf); if (mb_detect_encoding($postgresConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'postgres_conf' => 'The postgres_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('postgres_conf', $postgresConf); } break; case 'standalone-clickhouse': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'clickhouse_admin_user', 'clickhouse_admin_password']; $validator = customApiValidator($request->all(), [ 'clickhouse_admin_user' => 'string', 'clickhouse_admin_password' => 'string', ]); break; case 'standalone-dragonfly': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'dragonfly_password']; $validator = customApiValidator($request->all(), [ 'dragonfly_password' => 'string', ]); break; case 'standalone-redis': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'redis_password', 'redis_conf']; $validator = customApiValidator($request->all(), [ 'redis_password' => 'string', 'redis_conf' => 'string', ]); if ($request->has('redis_conf')) { if (! isBase64Encoded($request->redis_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'redis_conf' => 'The redis_conf should be base64 encoded.', ], ], 422); } $redisConf = base64_decode($request->redis_conf); if (mb_detect_encoding($redisConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'redis_conf' => 'The redis_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('redis_conf', $redisConf); } break; case 'standalone-keydb': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'keydb_password', 'keydb_conf']; $validator = customApiValidator($request->all(), [ 'keydb_password' => 'string', 'keydb_conf' => 'string', ]); if ($request->has('keydb_conf')) { if (! isBase64Encoded($request->keydb_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'keydb_conf' => 'The keydb_conf should be base64 encoded.', ], ], 422); } $keydbConf = base64_decode($request->keydb_conf); if (mb_detect_encoding($keydbConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'keydb_conf' => 'The keydb_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('keydb_conf', $keydbConf); } break; case 'standalone-mariadb': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database']; $validator = customApiValidator($request->all(), [ 'mariadb_conf' => 'string', 'mariadb_root_password' => 'string', 'mariadb_user' => 'string', 'mariadb_password' => 'string', 'mariadb_database' => 'string', ]); if ($request->has('mariadb_conf')) { if (! isBase64Encoded($request->mariadb_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mariadb_conf' => 'The mariadb_conf should be base64 encoded.', ], ], 422); } $mariadbConf = base64_decode($request->mariadb_conf); if (mb_detect_encoding($mariadbConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mariadb_conf' => 'The mariadb_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('mariadb_conf', $mariadbConf); } break; case 'standalone-mongodb': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_database']; $validator = customApiValidator($request->all(), [ 'mongo_conf' => 'string', 'mongo_initdb_root_username' => 'string', 'mongo_initdb_root_password' => 'string', 'mongo_initdb_database' => 'string', ]); if ($request->has('mongo_conf')) { if (! isBase64Encoded($request->mongo_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mongo_conf' => 'The mongo_conf should be base64 encoded.', ], ], 422); } $mongoConf = base64_decode($request->mongo_conf); if (mb_detect_encoding($mongoConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mongo_conf' => 'The mongo_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('mongo_conf', $mongoConf); } break; case 'standalone-mysql': $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mysql_root_password', 'mysql_password', 'mysql_user', 'mysql_database', 'mysql_conf']; $validator = customApiValidator($request->all(), [ 'mysql_root_password' => 'string', 'mysql_password' => 'string', 'mysql_user' => 'string', 'mysql_database' => 'string', 'mysql_conf' => 'string', ]); if ($request->has('mysql_conf')) { if (! isBase64Encoded($request->mysql_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mysql_conf' => 'The mysql_conf should be base64 encoded.', ], ], 422); } $mysqlConf = base64_decode($request->mysql_conf); if (mb_detect_encoding($mysqlConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mysql_conf' => 'The mysql_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('mysql_conf', $mysqlConf); } break; } $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $whatToDoWithDatabaseProxy = null; if ($request->is_public === false && $database->is_public === true) { $whatToDoWithDatabaseProxy = 'stop'; } if ($request->is_public === true && $request->public_port && $database->is_public === false) { $whatToDoWithDatabaseProxy = 'start'; } // Only update database fields, not backup configuration $database->update($request->only($allowedFields)); if ($whatToDoWithDatabaseProxy === 'start') { StartDatabaseProxy::dispatch($database); } elseif ($whatToDoWithDatabaseProxy === 'stop') { StopDatabaseProxy::dispatch($database); } return response()->json([ 'message' => 'Database updated.', ]); } #[OA\Post( summary: 'Create Backup', description: 'Create a new scheduled backup configuration for a database', path: '/databases/{uuid}/backups', operationId: 'create-database-backup', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Backup configuration data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['frequency'], properties: [ 'frequency' => ['type' => 'string', 'description' => 'Backup frequency (cron expression or: every_minute, hourly, daily, weekly, monthly, yearly)'], 'enabled' => ['type' => 'boolean', 'description' => 'Whether the backup is enabled', 'default' => true], 'save_s3' => ['type' => 'boolean', 'description' => 'Whether to save backups to S3', 'default' => false], 's3_storage_uuid' => ['type' => 'string', 'description' => 'S3 storage UUID (required if save_s3 is true)'], 'databases_to_backup' => ['type' => 'string', 'description' => 'Comma separated list of databases to backup'], 'dump_all' => ['type' => 'boolean', 'description' => 'Whether to dump all databases', 'default' => false], 'backup_now' => ['type' => 'boolean', 'description' => 'Whether to trigger backup immediately after creation'], 'database_backup_retention_amount_locally' => ['type' => 'integer', 'description' => 'Number of backups to retain locally'], 'database_backup_retention_days_locally' => ['type' => 'integer', 'description' => 'Number of days to retain backups locally'], 'database_backup_retention_max_storage_locally' => ['type' => 'integer', 'description' => 'Max storage (MB) for local backups'], 'database_backup_retention_amount_s3' => ['type' => 'integer', 'description' => 'Number of backups to retain in S3'], 'database_backup_retention_days_s3' => ['type' => 'integer', 'description' => 'Number of days to retain backups in S3'], 'database_backup_retention_max_storage_s3' => ['type' => 'integer', 'description' => 'Max storage (MB) for S3 backups'], ], ), ) ), responses: [ new OA\Response( response: 201, description: 'Backup configuration created successfully', content: new OA\JsonContent( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'format' => 'uuid', 'example' => '550e8400-e29b-41d4-a716-446655440000'], 'message' => ['type' => 'string', 'example' => 'Backup configuration created successfully.'], ] ) ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_backup(Request $request) { $backupConfigFields = ['save_s3', 'enabled', 'dump_all', 'frequency', 'databases_to_backup', 'database_backup_retention_amount_locally', 'database_backup_retention_days_locally', 'database_backup_retention_max_storage_locally', 'database_backup_retention_amount_s3', 'database_backup_retention_days_s3', 'database_backup_retention_max_storage_s3', 's3_storage_uuid']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // Validate incoming request is valid JSON $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'frequency' => 'required|string', 'enabled' => 'boolean', 'save_s3' => 'boolean', 'dump_all' => 'boolean', 'backup_now' => 'boolean|nullable', 's3_storage_uuid' => 'string|exists:s3_storages,uuid|nullable', 'databases_to_backup' => 'string|nullable', 'database_backup_retention_amount_locally' => 'integer|min:0', 'database_backup_retention_days_locally' => 'integer|min:0', 'database_backup_retention_max_storage_locally' => 'integer|min:0', 'database_backup_retention_amount_s3' => 'integer|min:0', 'database_backup_retention_days_s3' => 'integer|min:0', 'database_backup_retention_max_storage_s3' => 'integer|min:0', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } $uuid = $request->uuid; $database = queryDatabaseByUuidWithinTeam($uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('manageBackups', $database); // Validate frequency is a valid cron expression $isValid = validate_cron_expression($request->frequency); if (! $isValid) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['frequency' => ['Invalid cron expression or frequency format.']], ], 422); } // Validate S3 storage if save_s3 is true if ($request->boolean('save_s3') && ! $request->filled('s3_storage_uuid')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['s3_storage_uuid' => ['The s3_storage_uuid field is required when save_s3 is true.']], ], 422); } if ($request->filled('s3_storage_uuid')) { $existsInTeam = S3Storage::ownedByCurrentTeam()->where('uuid', $request->s3_storage_uuid)->exists(); if (! $existsInTeam) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['s3_storage_uuid' => ['The selected S3 storage is invalid for this team.']], ], 422); } } // Check for extra fields $extraFields = array_diff(array_keys($request->all()), $backupConfigFields, ['backup_now']); if (! empty($extraFields)) { $errors = $validator->errors(); foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $backupData = $request->only($backupConfigFields); // Convert s3_storage_uuid to s3_storage_id if (isset($backupData['s3_storage_uuid'])) { $s3Storage = S3Storage::ownedByCurrentTeam()->where('uuid', $backupData['s3_storage_uuid'])->first(); if ($s3Storage) { $backupData['s3_storage_id'] = $s3Storage->id; } elseif ($request->boolean('save_s3')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['s3_storage_uuid' => ['The selected S3 storage is invalid for this team.']], ], 422); } unset($backupData['s3_storage_uuid']); } // Set default databases_to_backup based on database type if not provided if (! isset($backupData['databases_to_backup']) || empty($backupData['databases_to_backup'])) { if ($database->type() === 'standalone-postgresql') { $backupData['databases_to_backup'] = $database->postgres_db; } elseif ($database->type() === 'standalone-mysql') { $backupData['databases_to_backup'] = $database->mysql_database; } elseif ($database->type() === 'standalone-mariadb') { $backupData['databases_to_backup'] = $database->mariadb_database; } } // Add required fields $backupData['database_id'] = $database->id; $backupData['database_type'] = $database->getMorphClass(); $backupData['team_id'] = $teamId; // Set defaults if (! isset($backupData['enabled'])) { $backupData['enabled'] = true; } $backupConfig = ScheduledDatabaseBackup::create($backupData); // Trigger immediate backup if requested if ($request->backup_now) { dispatch(new DatabaseBackupJob($backupConfig)); } return response()->json([ 'uuid' => $backupConfig->uuid, 'message' => 'Backup configuration created successfully.', ], 201); } #[OA\Patch( summary: 'Update', description: 'Update a specific backup configuration for a given database, identified by its UUID and the backup ID', path: '/databases/{uuid}/backups/{scheduled_backup_uuid}', operationId: 'update-database-backup', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'scheduled_backup_uuid', in: 'path', description: 'UUID of the backup configuration.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Database backup configuration data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'save_s3' => ['type' => 'boolean', 'description' => 'Whether data is saved in s3 or not'], 's3_storage_uuid' => ['type' => 'string', 'description' => 'S3 storage UUID'], 'backup_now' => ['type' => 'boolean', 'description' => 'Whether to take a backup now or not'], 'enabled' => ['type' => 'boolean', 'description' => 'Whether the backup is enabled or not'], 'databases_to_backup' => ['type' => 'string', 'description' => 'Comma separated list of databases to backup'], 'dump_all' => ['type' => 'boolean', 'description' => 'Whether all databases are dumped or not'], 'frequency' => ['type' => 'string', 'description' => 'Frequency of the backup'], 'database_backup_retention_amount_locally' => ['type' => 'integer', 'description' => 'Retention amount of the backup locally'], 'database_backup_retention_days_locally' => ['type' => 'integer', 'description' => 'Retention days of the backup locally'], 'database_backup_retention_max_storage_locally' => ['type' => 'integer', 'description' => 'Max storage of the backup locally'], 'database_backup_retention_amount_s3' => ['type' => 'integer', 'description' => 'Retention amount of the backup in s3'], 'database_backup_retention_days_s3' => ['type' => 'integer', 'description' => 'Retention days of the backup in s3'], 'database_backup_retention_max_storage_s3' => ['type' => 'integer', 'description' => 'Max storage of the backup in S3'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database backup configuration updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_backup(Request $request) { $backupConfigFields = ['save_s3', 'enabled', 'dump_all', 'frequency', 'databases_to_backup', 'database_backup_retention_amount_locally', 'database_backup_retention_days_locally', 'database_backup_retention_max_storage_locally', 'database_backup_retention_amount_s3', 'database_backup_retention_days_s3', 'database_backup_retention_max_storage_s3', 's3_storage_uuid']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // this check if the request is a valid json $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'save_s3' => 'boolean', 'backup_now' => 'boolean|nullable', 'enabled' => 'boolean', 'dump_all' => 'boolean', 's3_storage_uuid' => 'string|exists:s3_storages,uuid|nullable', 'databases_to_backup' => 'string|nullable', 'frequency' => 'string|in:every_minute,hourly,daily,weekly,monthly,yearly', 'database_backup_retention_amount_locally' => 'integer|min:0', 'database_backup_retention_days_locally' => 'integer|min:0', 'database_backup_retention_max_storage_locally' => 'integer|min:0', 'database_backup_retention_amount_s3' => 'integer|min:0', 'database_backup_retention_days_s3' => 'integer|min:0', 'database_backup_retention_max_storage_s3' => 'integer|min:0', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } // Validate scheduled_backup_uuid is provided if (! $request->scheduled_backup_uuid) { return response()->json(['message' => 'Scheduled backup UUID is required.'], 400); } $uuid = $request->uuid; removeUnnecessaryFieldsFromRequest($request); $database = queryDatabaseByUuidWithinTeam($uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('update', $database); if ($request->boolean('save_s3') && ! $request->filled('s3_storage_uuid')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['s3_storage_uuid' => ['The s3_storage_uuid field is required when save_s3 is true.']], ], 422); } if ($request->filled('s3_storage_uuid')) { $existsInTeam = S3Storage::ownedByCurrentTeam()->where('uuid', $request->s3_storage_uuid)->exists(); if (! $existsInTeam) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['s3_storage_uuid' => ['The selected S3 storage is invalid for this team.']], ], 422); } } $backupConfig = ScheduledDatabaseBackup::ownedByCurrentTeamAPI($teamId)->where('database_id', $database->id) ->where('uuid', $request->scheduled_backup_uuid) ->first(); if (! $backupConfig) { return response()->json(['message' => 'Backup config not found.'], 404); } $extraFields = array_diff(array_keys($request->all()), $backupConfigFields, ['backup_now']); if (! empty($extraFields)) { $errors = $validator->errors(); foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $backupData = $request->only($backupConfigFields); // Convert s3_storage_uuid to s3_storage_id if (isset($backupData['s3_storage_uuid'])) { $s3Storage = S3Storage::ownedByCurrentTeam()->where('uuid', $backupData['s3_storage_uuid'])->first(); if ($s3Storage) { $backupData['s3_storage_id'] = $s3Storage->id; } elseif ($request->boolean('save_s3')) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['s3_storage_uuid' => ['The selected S3 storage is invalid for this team.']], ], 422); } unset($backupData['s3_storage_uuid']); } $backupConfig->update($backupData); if ($request->backup_now) { dispatch(new DatabaseBackupJob($backupConfig)); } return response()->json([ 'message' => 'Database backup configuration updated', ]); } #[OA\Post( summary: 'Create (PostgreSQL)', description: 'Create a new PostgreSQL database.', path: '/databases/postgresql', operationId: 'create-database-postgresql', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'postgres_user' => ['type' => 'string', 'description' => 'PostgreSQL user'], 'postgres_password' => ['type' => 'string', 'description' => 'PostgreSQL password'], 'postgres_db' => ['type' => 'string', 'description' => 'PostgreSQL database'], 'postgres_initdb_args' => ['type' => 'string', 'description' => 'PostgreSQL initdb args'], 'postgres_host_auth_method' => ['type' => 'string', 'description' => 'PostgreSQL host auth method'], 'postgres_conf' => ['type' => 'string', 'description' => 'PostgreSQL conf'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_postgresql(Request $request) { return $this->create_database($request, NewDatabaseTypes::POSTGRESQL); } #[OA\Post( summary: 'Create (Clickhouse)', description: 'Create a new Clickhouse database.', path: '/databases/clickhouse', operationId: 'create-database-clickhouse', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'clickhouse_admin_user' => ['type' => 'string', 'description' => 'Clickhouse admin user'], 'clickhouse_admin_password' => ['type' => 'string', 'description' => 'Clickhouse admin password'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_clickhouse(Request $request) { return $this->create_database($request, NewDatabaseTypes::CLICKHOUSE); } #[OA\Post( summary: 'Create (DragonFly)', description: 'Create a new DragonFly database.', path: '/databases/dragonfly', operationId: 'create-database-dragonfly', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'dragonfly_password' => ['type' => 'string', 'description' => 'DragonFly password'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_dragonfly(Request $request) { return $this->create_database($request, NewDatabaseTypes::DRAGONFLY); } #[OA\Post( summary: 'Create (Redis)', description: 'Create a new Redis database.', path: '/databases/redis', operationId: 'create-database-redis', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'redis_password' => ['type' => 'string', 'description' => 'Redis password'], 'redis_conf' => ['type' => 'string', 'description' => 'Redis conf'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_redis(Request $request) { return $this->create_database($request, NewDatabaseTypes::REDIS); } #[OA\Post( summary: 'Create (KeyDB)', description: 'Create a new KeyDB database.', path: '/databases/keydb', operationId: 'create-database-keydb', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'keydb_password' => ['type' => 'string', 'description' => 'KeyDB password'], 'keydb_conf' => ['type' => 'string', 'description' => 'KeyDB conf'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_keydb(Request $request) { return $this->create_database($request, NewDatabaseTypes::KEYDB); } #[OA\Post( summary: 'Create (MariaDB)', description: 'Create a new MariaDB database.', path: '/databases/mariadb', operationId: 'create-database-mariadb', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'mariadb_conf' => ['type' => 'string', 'description' => 'MariaDB conf'], 'mariadb_root_password' => ['type' => 'string', 'description' => 'MariaDB root password'], 'mariadb_user' => ['type' => 'string', 'description' => 'MariaDB user'], 'mariadb_password' => ['type' => 'string', 'description' => 'MariaDB password'], 'mariadb_database' => ['type' => 'string', 'description' => 'MariaDB database'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_mariadb(Request $request) { return $this->create_database($request, NewDatabaseTypes::MARIADB); } #[OA\Post( summary: 'Create (MySQL)', description: 'Create a new MySQL database.', path: '/databases/mysql', operationId: 'create-database-mysql', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'mysql_root_password' => ['type' => 'string', 'description' => 'MySQL root password'], 'mysql_password' => ['type' => 'string', 'description' => 'MySQL password'], 'mysql_user' => ['type' => 'string', 'description' => 'MySQL user'], 'mysql_database' => ['type' => 'string', 'description' => 'MySQL database'], 'mysql_conf' => ['type' => 'string', 'description' => 'MySQL conf'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_mysql(Request $request) { return $this->create_database($request, NewDatabaseTypes::MYSQL); } #[OA\Post( summary: 'Create (MongoDB)', description: 'Create a new MongoDB database.', path: '/databases/mongodb', operationId: 'create-database-mongodb', security: [ ['bearerAuth' => []], ], tags: ['Databases'], requestBody: new OA\RequestBody( description: 'Database data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'server_uuid' => ['type' => 'string', 'description' => 'UUID of the server'], 'project_uuid' => ['type' => 'string', 'description' => 'UUID of the project'], 'environment_name' => ['type' => 'string', 'description' => 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.'], 'destination_uuid' => ['type' => 'string', 'description' => 'UUID of the destination if the server has multiple destinations'], 'mongo_conf' => ['type' => 'string', 'description' => 'MongoDB conf'], 'mongo_initdb_root_username' => ['type' => 'string', 'description' => 'MongoDB initdb root username'], 'name' => ['type' => 'string', 'description' => 'Name of the database'], 'description' => ['type' => 'string', 'description' => 'Description of the database'], 'image' => ['type' => 'string', 'description' => 'Docker Image of the database'], 'is_public' => ['type' => 'boolean', 'description' => 'Is the database public?'], 'public_port' => ['type' => 'integer', 'description' => 'Public port of the database'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit of the database'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit of the database'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness of the database'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation of the database'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit of the database'], 'limits_cpuset' => ['type' => 'string', 'description' => 'CPU set of the database'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares of the database'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'Instant deploy the database'], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Database updated', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_database_mongodb(Request $request) { return $this->create_database($request, NewDatabaseTypes::MONGODB); } public function create_database(Request $request, NewDatabaseTypes $type) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_database', 'mysql_root_password', 'mysql_password', 'mysql_user', 'mysql_database', 'mysql_conf']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // Use a generic authorization for database creation - using PostgreSQL as representative model $this->authorize('create', StandalonePostgresql::class); $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $extraFields = array_diff(array_keys($request->all()), $allowedFields); if (! empty($extraFields)) { $errors = collect([]); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $environmentUuid = $request->environment_uuid; $environmentName = $request->environment_name; if (blank($environmentUuid) && blank($environmentName)) { return response()->json(['message' => 'You need to provide at least one of environment_name or environment_uuid.'], 422); } $serverUuid = $request->server_uuid; $instantDeploy = $request->instant_deploy ?? false; if ($request->is_public && ! $request->public_port) { $request->offsetSet('is_public', false); } $project = Project::whereTeamId($teamId)->whereUuid($request->project_uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $environment = $project->environments()->where('name', $environmentName)->first(); if (! $environment) { $environment = $project->environments()->where('uuid', $environmentUuid)->first(); } if (! $environment) { return response()->json(['message' => 'You need to provide a valid environment_name or environment_uuid.'], 422); } $server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first(); if (! $server) { return response()->json(['message' => 'Server not found.'], 404); } $destinations = $server->destinations(); if ($destinations->count() == 0) { return response()->json(['message' => 'Server has no destinations.'], 400); } if ($destinations->count() > 1 && ! $request->has('destination_uuid')) { return response()->json(['message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400); } $destination = $destinations->first(); if ($destinations->count() > 1 && $request->has('destination_uuid')) { $destination = $destinations->where('uuid', $request->destination_uuid)->first(); if (! $destination) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'destination_uuid' => 'Provided destination_uuid does not belong to the specified server.', ], ], 422); } } if ($request->has('public_port') && $request->is_public) { if (isPublicPortAlreadyUsed($server, $request->public_port)) { return response()->json(['message' => 'Public port already used by another database.'], 400); } } $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', 'description' => 'string|nullable', 'image' => 'string', 'project_uuid' => 'string|required', 'environment_name' => 'string|nullable', 'environment_uuid' => 'string|nullable', 'server_uuid' => 'string|required', 'destination_uuid' => 'string', 'is_public' => 'boolean', 'public_port' => 'numeric|nullable', 'limits_memory' => 'string', 'limits_memory_swap' => 'string', 'limits_memory_swappiness' => 'numeric', 'limits_memory_reservation' => 'string', 'limits_cpus' => 'string', 'limits_cpuset' => 'string|nullable', 'limits_cpu_shares' => 'numeric', 'instant_deploy' => 'boolean', ]); if ($validator->failed()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } if ($request->public_port) { if ($request->public_port < 1024 || $request->public_port > 65535) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'public_port' => 'The public port should be between 1024 and 65535.', ], ], 422); } } if ($type === NewDatabaseTypes::POSTGRESQL) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf']; $validator = customApiValidator($request->all(), [ 'postgres_user' => 'string', 'postgres_password' => 'string', 'postgres_db' => 'string', 'postgres_initdb_args' => 'string', 'postgres_host_auth_method' => 'string', 'postgres_conf' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); if ($request->has('postgres_conf')) { if (! isBase64Encoded($request->postgres_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'postgres_conf' => 'The postgres_conf should be base64 encoded.', ], ], 422); } $postgresConf = base64_decode($request->postgres_conf); if (mb_detect_encoding($postgresConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'postgres_conf' => 'The postgres_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('postgres_conf', $postgresConf); } $database = create_standalone_postgresql($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } $database->refresh(); $payload = [ 'uuid' => $database->uuid, 'internal_db_url' => $database->internal_db_url, ]; if ($database->is_public && $database->public_port) { $payload['external_db_url'] = $database->external_db_url; } return response()->json(serializeApiResponse($payload))->setStatusCode(201); } elseif ($type === NewDatabaseTypes::MARIADB) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database']; $validator = customApiValidator($request->all(), [ 'clickhouse_admin_user' => 'string', 'clickhouse_admin_password' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); if ($request->has('mariadb_conf')) { if (! isBase64Encoded($request->mariadb_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mariadb_conf' => 'The mariadb_conf should be base64 encoded.', ], ], 422); } $mariadbConf = base64_decode($request->mariadb_conf); if (mb_detect_encoding($mariadbConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mariadb_conf' => 'The mariadb_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('mariadb_conf', $mariadbConf); } $database = create_standalone_mariadb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } $database->refresh(); $payload = [ 'uuid' => $database->uuid, 'internal_db_url' => $database->internal_db_url, ]; if ($database->is_public && $database->public_port) { $payload['external_db_url'] = $database->external_db_url; } return response()->json(serializeApiResponse($payload))->setStatusCode(201); } elseif ($type === NewDatabaseTypes::MYSQL) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mysql_root_password', 'mysql_password', 'mysql_user', 'mysql_database', 'mysql_conf']; $validator = customApiValidator($request->all(), [ 'mysql_root_password' => 'string', 'mysql_password' => 'string', 'mysql_user' => 'string', 'mysql_database' => 'string', 'mysql_conf' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); if ($request->has('mysql_conf')) { if (! isBase64Encoded($request->mysql_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mysql_conf' => 'The mysql_conf should be base64 encoded.', ], ], 422); } $mysqlConf = base64_decode($request->mysql_conf); if (mb_detect_encoding($mysqlConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mysql_conf' => 'The mysql_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('mysql_conf', $mysqlConf); } $database = create_standalone_mysql($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } $database->refresh(); $payload = [ 'uuid' => $database->uuid, 'internal_db_url' => $database->internal_db_url, ]; if ($database->is_public && $database->public_port) { $payload['external_db_url'] = $database->external_db_url; } return response()->json(serializeApiResponse($payload))->setStatusCode(201); } elseif ($type === NewDatabaseTypes::REDIS) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'redis_password', 'redis_conf']; $validator = customApiValidator($request->all(), [ 'redis_password' => 'string', 'redis_conf' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); if ($request->has('redis_conf')) { if (! isBase64Encoded($request->redis_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'redis_conf' => 'The redis_conf should be base64 encoded.', ], ], 422); } $redisConf = base64_decode($request->redis_conf); if (mb_detect_encoding($redisConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'redis_conf' => 'The redis_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('redis_conf', $redisConf); } $database = create_standalone_redis($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } $database->refresh(); $payload = [ 'uuid' => $database->uuid, 'internal_db_url' => $database->internal_db_url, ]; if ($database->is_public && $database->public_port) { $payload['external_db_url'] = $database->external_db_url; } return response()->json(serializeApiResponse($payload))->setStatusCode(201); } elseif ($type === NewDatabaseTypes::DRAGONFLY) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'dragonfly_password']; $validator = customApiValidator($request->all(), [ 'dragonfly_password' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); $database = create_standalone_dragonfly($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } return response()->json(serializeApiResponse([ 'uuid' => $database->uuid, ]))->setStatusCode(201); } elseif ($type === NewDatabaseTypes::KEYDB) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'keydb_password', 'keydb_conf']; $validator = customApiValidator($request->all(), [ 'keydb_password' => 'string', 'keydb_conf' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); if ($request->has('keydb_conf')) { if (! isBase64Encoded($request->keydb_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'keydb_conf' => 'The keydb_conf should be base64 encoded.', ], ], 422); } $keydbConf = base64_decode($request->keydb_conf); if (mb_detect_encoding($keydbConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'keydb_conf' => 'The keydb_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('keydb_conf', $keydbConf); } $database = create_standalone_keydb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } $database->refresh(); $payload = [ 'uuid' => $database->uuid, 'internal_db_url' => $database->internal_db_url, ]; if ($database->is_public && $database->public_port) { $payload['external_db_url'] = $database->external_db_url; } return response()->json(serializeApiResponse($payload))->setStatusCode(201); } elseif ($type === NewDatabaseTypes::CLICKHOUSE) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'clickhouse_admin_user', 'clickhouse_admin_password']; $validator = customApiValidator($request->all(), [ 'clickhouse_admin_user' => 'string', 'clickhouse_admin_password' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); $database = create_standalone_clickhouse($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } $database->refresh(); $payload = [ 'uuid' => $database->uuid, 'internal_db_url' => $database->internal_db_url, ]; if ($database->is_public && $database->public_port) { $payload['external_db_url'] = $database->external_db_url; } return response()->json(serializeApiResponse($payload))->setStatusCode(201); } elseif ($type === NewDatabaseTypes::MONGODB) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_database']; $validator = customApiValidator($request->all(), [ 'mongo_conf' => 'string', 'mongo_initdb_root_username' => 'string', 'mongo_initdb_root_password' => 'string', 'mongo_initdb_database' => 'string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } removeUnnecessaryFieldsFromRequest($request); if ($request->has('mongo_conf')) { if (! isBase64Encoded($request->mongo_conf)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mongo_conf' => 'The mongo_conf should be base64 encoded.', ], ], 422); } $mongoConf = base64_decode($request->mongo_conf); if (mb_detect_encoding($mongoConf, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'mongo_conf' => 'The mongo_conf should be base64 encoded.', ], ], 422); } $request->offsetSet('mongo_conf', $mongoConf); } $database = create_standalone_mongodb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); } $database->refresh(); $payload = [ 'uuid' => $database->uuid, 'internal_db_url' => $database->internal_db_url, ]; if ($database->is_public && $database->public_port) { $payload['external_db_url'] = $database->external_db_url; } return response()->json(serializeApiResponse($payload))->setStatusCode(201); } return response()->json(['message' => 'Invalid database type requested.'], 400); } #[OA\Delete( summary: 'Delete', description: 'Delete database by UUID.', path: '/databases/{uuid}', operationId: 'delete-database-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter(name: 'delete_configurations', in: 'query', required: false, description: 'Delete configurations.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'delete_volumes', in: 'query', required: false, description: 'Delete volumes.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'docker_cleanup', in: 'query', required: false, description: 'Run docker cleanup.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'delete_connected_networks', in: 'query', required: false, description: 'Delete connected networks.', schema: new OA\Schema(type: 'boolean', default: true)), ], responses: [ new OA\Response( response: 200, description: 'Database deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Database deleted.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function delete_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('delete', $database); DeleteResourceJob::dispatch( resource: $database, deleteVolumes: $request->boolean('delete_volumes', true), deleteConnectedNetworks: $request->boolean('delete_connected_networks', true), deleteConfigurations: $request->boolean('delete_configurations', true), dockerCleanup: $request->boolean('docker_cleanup', true) ); return response()->json([ 'message' => 'Database deletion request queued.', ]); } #[OA\Delete( summary: 'Delete backup configuration', description: 'Deletes a backup configuration and all its executions.', path: '/databases/{uuid}/backups/{scheduled_backup_uuid}', operationId: 'delete-backup-configuration-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', required: true, description: 'UUID of the database', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'scheduled_backup_uuid', in: 'path', required: true, description: 'UUID of the backup configuration to delete', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'delete_s3', in: 'query', required: false, description: 'Whether to delete all backup files from S3', schema: new OA\Schema(type: 'boolean', default: false) ), ], responses: [ new OA\Response( response: 200, description: 'Backup configuration deleted.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'Backup configuration and all executions deleted.'), ] ) ), new OA\Response( response: 404, description: 'Backup configuration not found.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'Backup configuration not found.'), ] ) ), ] )] public function delete_backup_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // Validate scheduled_backup_uuid is provided if (! $request->scheduled_backup_uuid) { return response()->json(['message' => 'Scheduled backup UUID is required.'], 400); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('update', $database); // Find the backup configuration by its UUID $backup = ScheduledDatabaseBackup::ownedByCurrentTeamAPI($teamId)->where('database_id', $database->id) ->where('uuid', $request->scheduled_backup_uuid) ->first(); if (! $backup) { return response()->json(['message' => 'Backup configuration not found.'], 404); } $deleteS3 = $request->boolean('delete_s3', false); try { DB::beginTransaction(); // Get all executions for this backup configuration $executions = $backup->executions()->get(); // Delete all execution files (locally and optionally from S3) foreach ($executions as $execution) { if ($execution->filename) { deleteBackupsLocally($execution->filename, $database->destination->server); if ($deleteS3 && $backup->s3) { deleteBackupsS3($execution->filename, $backup->s3); } } $execution->delete(); } // Delete the backup configuration itself $backup->delete(); DB::commit(); return response()->json([ 'message' => 'Backup configuration and all executions deleted.', ]); } catch (\Exception $e) { DB::rollBack(); return response()->json(['message' => 'Failed to delete backup: '.$e->getMessage()], 500); } } #[OA\Delete( summary: 'Delete backup execution', description: 'Deletes a specific backup execution.', path: '/databases/{uuid}/backups/{scheduled_backup_uuid}/executions/{execution_uuid}', operationId: 'delete-backup-execution-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', required: true, description: 'UUID of the database', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'scheduled_backup_uuid', in: 'path', required: true, description: 'UUID of the backup configuration', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'execution_uuid', in: 'path', required: true, description: 'UUID of the backup execution to delete', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'delete_s3', in: 'query', required: false, description: 'Whether to delete the backup from S3', schema: new OA\Schema(type: 'boolean', default: false) ), ], responses: [ new OA\Response( response: 200, description: 'Backup execution deleted.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'Backup execution deleted.'), ] ) ), new OA\Response( response: 404, description: 'Backup execution not found.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'Backup execution not found.'), ] ) ), ] )] public function delete_execution_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // Validate parameters if (! $request->scheduled_backup_uuid) { return response()->json(['message' => 'Scheduled backup UUID is required.'], 400); } if (! $request->execution_uuid) { return response()->json(['message' => 'Execution UUID is required.'], 400); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('update', $database); // Find the backup configuration by its UUID $backup = ScheduledDatabaseBackup::ownedByCurrentTeamAPI($teamId)->where('database_id', $database->id) ->where('uuid', $request->scheduled_backup_uuid) ->first(); if (! $backup) { return response()->json(['message' => 'Backup configuration not found.'], 404); } // Find the specific execution $execution = $backup->executions()->where('uuid', $request->execution_uuid)->first(); if (! $execution) { return response()->json(['message' => 'Backup execution not found.'], 404); } $deleteS3 = $request->boolean('delete_s3', false); try { if ($execution->filename) { deleteBackupsLocally($execution->filename, $database->destination->server); if ($deleteS3 && $backup->s3) { deleteBackupsS3($execution->filename, $backup->s3); } } $execution->delete(); return response()->json([ 'message' => 'Backup execution deleted.', ]); } catch (\Exception $e) { return response()->json(['message' => 'Failed to delete backup execution: '.$e->getMessage()], 500); } } #[OA\Get( summary: 'List backup executions', description: 'Get all executions for a specific backup configuration.', path: '/databases/{uuid}/backups/{scheduled_backup_uuid}/executions', operationId: 'list-backup-executions', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', required: true, description: 'UUID of the database', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'scheduled_backup_uuid', in: 'path', required: true, description: 'UUID of the backup configuration', schema: new OA\Schema(type: 'string') ), ], responses: [ new OA\Response( response: 200, description: 'List of backup executions', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property( property: 'executions', type: 'array', items: new OA\Items( type: 'object', properties: [ new OA\Property(property: 'uuid', type: 'string'), new OA\Property(property: 'filename', type: 'string'), new OA\Property(property: 'size', type: 'integer'), new OA\Property(property: 'created_at', type: 'string'), new OA\Property(property: 'message', type: 'string'), new OA\Property(property: 'status', type: 'string'), ] ) ), ] ) ), new OA\Response( response: 404, description: 'Backup configuration not found.', ), ] )] public function list_backup_executions(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // Validate scheduled_backup_uuid is provided if (! $request->scheduled_backup_uuid) { return response()->json(['message' => 'Scheduled backup UUID is required.'], 400); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } // Find the backup configuration by its UUID $backup = ScheduledDatabaseBackup::ownedByCurrentTeamAPI($teamId)->where('database_id', $database->id) ->where('uuid', $request->scheduled_backup_uuid) ->first(); if (! $backup) { return response()->json(['message' => 'Backup configuration not found.'], 404); } // Get all executions for this backup configuration $executions = $backup->executions() ->orderBy('created_at', 'desc') ->get() ->map(function ($execution) { return [ 'uuid' => $execution->uuid, 'filename' => $execution->filename, 'size' => $execution->size, 'created_at' => $execution->created_at->toIso8601String(), 'message' => $execution->message, 'status' => $execution->status, ]; }); return response()->json([ 'executions' => $executions, ]); } #[OA\Get( summary: 'Start', description: 'Start database. `Post` request is also accepted.', path: '/databases/{uuid}/start', operationId: 'start-database-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Start database.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Database starting request queued.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_deploy(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('manage', $database); if (str($database->status)->contains('running')) { return response()->json(['message' => 'Database is already running.'], 400); } StartDatabase::dispatch($database); return response()->json( [ 'message' => 'Database starting request queued.', ], 200 ); } #[OA\Get( summary: 'Stop', description: 'Stop database. `Post` request is also accepted.', path: '/databases/{uuid}/stop', operationId: 'stop-database-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'docker_cleanup', in: 'query', description: 'Perform docker cleanup (prune networks, volumes, etc.).', schema: new OA\Schema( type: 'boolean', default: true, ) ), ], responses: [ new OA\Response( response: 200, description: 'Stop database.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Database stopping request queued.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_stop(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('manage', $database); if (str($database->status)->contains('stopped') || str($database->status)->contains('exited')) { return response()->json(['message' => 'Database is already stopped.'], 400); } $dockerCleanup = $request->boolean('docker_cleanup', true); StopDatabase::dispatch($database, $dockerCleanup); return response()->json( [ 'message' => 'Database stopping request queued.', ], 200 ); } #[OA\Get( summary: 'Restart', description: 'Restart database. `Post` request is also accepted.', path: '/databases/{uuid}/restart', operationId: 'restart-database-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Databases'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the database.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Restart database.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Database restaring request queued.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_restart(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $database = queryDatabaseByUuidWithinTeam($request->uuid, $teamId); if (! $database) { return response()->json(['message' => 'Database not found.'], 404); } $this->authorize('manage', $database); RestartDatabase::dispatch($database); return response()->json( [ 'message' => 'Database restarting request queued.', ], 200 ); } } ================================================ FILE: app/Http/Controllers/Api/DeployController.php ================================================ attributes->get('can_read_sensitive', false) === false) { $deployment->makeHidden([ 'logs', ]); } return serializeApiResponse($deployment); } #[OA\Get( summary: 'List', description: 'List currently running deployments', path: '/deployments', operationId: 'list-deployments', security: [ ['bearerAuth' => []], ], tags: ['Deployments'], responses: [ new OA\Response( response: 200, description: 'Get all currently running deployments.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/ApplicationDeploymentQueue'), ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function deployments(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $servers = Server::whereTeamId($teamId)->get(); $deployments_per_server = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->whereIn('server_id', $servers->pluck('id'))->get()->sortBy('id'); $deployments_per_server = $deployments_per_server->map(function ($deployment) { return $this->removeSensitiveData($deployment); }); return response()->json($deployments_per_server); } #[OA\Get( summary: 'Get', description: 'Get deployment by UUID.', path: '/deployments/{uuid}', operationId: 'get-deployment-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Deployments'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Deployment UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Get deployment by UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( ref: '#/components/schemas/ApplicationDeploymentQueue', ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function deployment_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $deployment = ApplicationDeploymentQueue::where('deployment_uuid', $uuid)->first(); if (! $deployment) { return response()->json(['message' => 'Deployment not found.'], 404); } $application = $deployment->application; if (! $application || data_get($application->team(), 'id') !== (int) $teamId) { return response()->json(['message' => 'Deployment not found.'], 404); } return response()->json($this->removeSensitiveData($deployment)); } #[OA\Post( summary: 'Cancel', description: 'Cancel a deployment by UUID.', path: '/deployments/{uuid}/cancel', operationId: 'cancel-deployment-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Deployments'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Deployment UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Deployment cancelled successfully.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Deployment cancelled successfully.'], 'deployment_uuid' => ['type' => 'string', 'example' => 'cm37r6cqj000008jm0veg5tkm'], 'status' => ['type' => 'string', 'example' => 'cancelled-by-user'], ] ) ), ]), new OA\Response( response: 400, description: 'Deployment cannot be cancelled (already finished/failed/cancelled).', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Deployment cannot be cancelled. Current status: finished'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 403, description: 'User doesn\'t have permission to cancel this deployment.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'You do not have permission to cancel this deployment.'], ] ) ), ]), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function cancel_deployment(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } // Find the deployment by UUID $deployment = ApplicationDeploymentQueue::where('deployment_uuid', $uuid)->first(); if (! $deployment) { return response()->json(['message' => 'Deployment not found.'], 404); } // Check if the deployment belongs to the user's team $servers = Server::whereTeamId($teamId)->pluck('id'); if (! $servers->contains($deployment->server_id)) { return response()->json(['message' => 'You do not have permission to cancel this deployment.'], 403); } // Check if deployment can be cancelled (must be queued or in_progress) $cancellableStatuses = [ \App\Enums\ApplicationDeploymentStatus::QUEUED->value, \App\Enums\ApplicationDeploymentStatus::IN_PROGRESS->value, ]; if (! in_array($deployment->status, $cancellableStatuses)) { return response()->json([ 'message' => "Deployment cannot be cancelled. Current status: {$deployment->status}", ], 400); } // Perform the cancellation try { $deployment_uuid = $deployment->deployment_uuid; $kill_command = "docker rm -f {$deployment_uuid}"; $build_server_id = $deployment->build_server_id ?? $deployment->server_id; // Mark deployment as cancelled $deployment->update([ 'status' => \App\Enums\ApplicationDeploymentStatus::CANCELLED_BY_USER->value, ]); // Get the server $server = Server::find($build_server_id); if ($server) { // Add cancellation log entry $deployment->addLogEntry('Deployment cancelled by user via API.', 'stderr'); // Check if container exists and kill it $checkCommand = "docker ps -a --filter name={$deployment_uuid} --format '{{.Names}}'"; $containerExists = instant_remote_process([$checkCommand], $server); if ($containerExists && str($containerExists)->trim()->isNotEmpty()) { instant_remote_process([$kill_command], $server); $deployment->addLogEntry('Deployment container stopped.'); } else { $deployment->addLogEntry('Deployment container not yet started. Will be cancelled when job checks status.'); } // Kill running process if process ID exists if ($deployment->current_process_id) { try { $processKillCommand = "kill -9 {$deployment->current_process_id}"; instant_remote_process([$processKillCommand], $server); } catch (\Throwable $e) { // Process might already be gone } } } return response()->json([ 'message' => 'Deployment cancelled successfully.', 'deployment_uuid' => $deployment->deployment_uuid, 'status' => $deployment->status, ]); } catch (\Throwable $e) { return response()->json([ 'message' => 'Failed to cancel deployment: '.$e->getMessage(), ], 500); } } #[OA\Get( summary: 'Deploy', description: 'Deploy by tag or uuid. `Post` request also accepted with `uuid` and `tag` json body.', path: '/deploy', operationId: 'deploy-by-tag-or-uuid', security: [ ['bearerAuth' => []], ], tags: ['Deployments'], parameters: [ new OA\Parameter(name: 'tag', in: 'query', description: 'Tag name(s). Comma separated list is also accepted.', schema: new OA\Schema(type: 'string')), new OA\Parameter(name: 'uuid', in: 'query', description: 'Resource UUID(s). Comma separated list is also accepted.', schema: new OA\Schema(type: 'string')), new OA\Parameter(name: 'force', in: 'query', description: 'Force rebuild (without cache)', schema: new OA\Schema(type: 'boolean')), new OA\Parameter(name: 'pr', in: 'query', description: 'Pull Request Id for deploying specific PR builds. Cannot be used with tag parameter.', schema: new OA\Schema(type: 'integer')), ], responses: [ new OA\Response( response: 200, description: 'Get deployment(s) UUID\'s', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'deployments' => new OA\Property( property: 'deployments', type: 'array', items: new OA\Items( type: 'object', properties: [ 'message' => ['type' => 'string'], 'resource_uuid' => ['type' => 'string'], 'deployment_uuid' => ['type' => 'string'], ] ), ), ], ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function deploy(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuids = $request->input('uuid'); $tags = $request->input('tag'); $force = $request->input('force') ?? false; $pr = $request->input('pr') ? max((int) $request->input('pr'), 0) : 0; if ($uuids && $tags) { return response()->json(['message' => 'You can only use uuid or tag, not both.'], 400); } if ($tags && $pr) { return response()->json(['message' => 'You can only use tag or pr, not both.'], 400); } if ($tags) { return $this->by_tags($tags, $teamId, $force); } elseif ($uuids) { return $this->by_uuids($uuids, $teamId, $force, $pr); } return response()->json(['message' => 'You must provide uuid or tag.'], 400); } private function by_uuids(string $uuid, int $teamId, bool $force = false, int $pr = 0) { $uuids = explode(',', $uuid); $uuids = collect(array_filter($uuids)); if (count($uuids) === 0) { return response()->json(['message' => 'No UUIDs provided.'], 400); } $deployments = collect(); $payload = collect(); foreach ($uuids as $uuid) { $resource = getResourceByUuid($uuid, $teamId); if ($resource) { if ($pr !== 0) { $preview = $resource->previews()->where('pull_request_id', $pr)->first(); if (! $preview) { $deployments->push(['message' => "Pull request {$pr} not found for this resource.", 'resource_uuid' => $uuid]); continue; } } $result = $this->deploy_resource($resource, $force, $pr); if (isset($result['status']) && $result['status'] === 429) { return response()->json(['message' => $result['message']], 429)->header('Retry-After', 60); } ['message' => $return_message, 'deployment_uuid' => $deployment_uuid] = $result; if ($deployment_uuid) { $deployments->push(['message' => $return_message, 'resource_uuid' => $uuid, 'deployment_uuid' => $deployment_uuid->toString()]); } else { $deployments->push(['message' => $return_message, 'resource_uuid' => $uuid]); } } } if ($deployments->count() > 0) { $payload->put('deployments', $deployments->toArray()); return response()->json(serializeApiResponse($payload->toArray())); } return response()->json(['message' => 'No resources found.'], 404); } public function by_tags(string $tags, int $team_id, bool $force = false) { $tags = explode(',', $tags); $tags = collect(array_filter($tags)); if (count($tags) === 0) { return response()->json(['message' => 'No TAGs provided.'], 400); } $message = collect([]); $deployments = collect(); $payload = collect(); foreach ($tags as $tag) { $found_tag = Tag::where(['name' => $tag, 'team_id' => $team_id])->first(); if (! $found_tag) { // $message->push("Tag {$tag} not found."); continue; } $applications = $found_tag->applications()->get(); $services = $found_tag->services()->get(); if ($applications->count() === 0 && $services->count() === 0) { $message->push("No resources found for tag {$tag}."); continue; } foreach ($applications as $resource) { $result = $this->deploy_resource($resource, $force); if (isset($result['status']) && $result['status'] === 429) { return response()->json(['message' => $result['message']], 429)->header('Retry-After', 60); } ['message' => $return_message, 'deployment_uuid' => $deployment_uuid] = $result; if ($deployment_uuid) { $deployments->push(['resource_uuid' => $resource->uuid, 'deployment_uuid' => $deployment_uuid->toString()]); } $message = $message->merge($return_message); } foreach ($services as $resource) { ['message' => $return_message] = $this->deploy_resource($resource, $force); $message = $message->merge($return_message); } } if ($message->count() > 0) { $payload->put('message', $message->toArray()); if ($deployments->count() > 0) { $payload->put('details', $deployments->toArray()); } return response()->json(serializeApiResponse($payload->toArray())); } return response()->json(['message' => 'No resources found with this tag.'], 404); } public function deploy_resource($resource, bool $force = false, int $pr = 0): array { $message = null; $deployment_uuid = null; if (gettype($resource) !== 'object') { return ['message' => "Resource ($resource) not found.", 'deployment_uuid' => $deployment_uuid]; } switch ($resource?->getMorphClass()) { case Application::class: // Check authorization for application deployment try { $this->authorize('deploy', $resource); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { return ['message' => 'Unauthorized to deploy this application.', 'deployment_uuid' => null]; } $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $resource, deployment_uuid: $deployment_uuid, force_rebuild: $force, pull_request_id: $pr, is_api: true, ); if ($result['status'] === 'queue_full') { return ['message' => $result['message'], 'deployment_uuid' => null, 'status' => 429]; } elseif ($result['status'] === 'skipped') { $message = $result['message']; } else { $message = "Application {$resource->name} deployment queued."; } break; case Service::class: // Check authorization for service deployment try { $this->authorize('deploy', $resource); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { return ['message' => 'Unauthorized to deploy this service.', 'deployment_uuid' => null]; } StartService::run($resource); $message = "Service {$resource->name} started. It could take a while, be patient."; break; default: // Database resource - check authorization try { $this->authorize('manage', $resource); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { return ['message' => 'Unauthorized to start this database.', 'deployment_uuid' => null]; } StartDatabase::dispatch($resource); $resource->started_at ??= now(); $resource->save(); $message = "Database {$resource->name} started."; break; } return ['message' => $message, 'deployment_uuid' => $deployment_uuid]; } #[OA\Get( summary: 'List application deployments', description: 'List application deployments by using the app uuid', path: '/deployments/applications/{uuid}', operationId: 'list-deployments-by-app-uuid', security: [ ['bearerAuth' => []], ], tags: ['Deployments'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'skip', in: 'query', description: 'Number of records to skip.', required: false, schema: new OA\Schema( type: 'integer', minimum: 0, default: 0, ) ), new OA\Parameter( name: 'take', in: 'query', description: 'Number of records to take.', required: false, schema: new OA\Schema( type: 'integer', minimum: 1, default: 10, ) ), ], responses: [ new OA\Response( response: 200, description: 'List application deployments by using the app uuid.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/Application'), ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function get_application_deployments(Request $request) { $request->validate([ 'skip' => ['nullable', 'integer', 'min:0'], 'take' => ['nullable', 'integer', 'min:1'], ]); $app_uuid = $request->route('uuid', null); $skip = $request->get('skip', 0); $take = $request->get('take', 10); $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $servers = Server::whereTeamId($teamId)->get(); if (is_null($app_uuid)) { return response()->json(['message' => 'Application uuid is required'], 400); } $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $app_uuid)->first(); if (is_null($application)) { return response()->json(['message' => 'Application not found'], 404); } // Check authorization to view application deployments $this->authorize('view', $application); $deployments = $application->deployments($skip, $take); return response()->json($deployments); } } ================================================ FILE: app/Http/Controllers/Api/GithubController.php ================================================ makeHidden([ 'client_secret', 'webhook_secret', ]); return serializeApiResponse($githubApp); } #[OA\Get( summary: 'List', description: 'List all GitHub apps.', path: '/github-apps', operationId: 'list-github-apps', security: [ ['bearerAuth' => []], ], tags: ['GitHub Apps'], responses: [ new OA\Response( response: 200, description: 'List of GitHub apps.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'id' => ['type' => 'integer'], 'uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'organization' => ['type' => 'string', 'nullable' => true], 'api_url' => ['type' => 'string'], 'html_url' => ['type' => 'string'], 'custom_user' => ['type' => 'string'], 'custom_port' => ['type' => 'integer'], 'app_id' => ['type' => 'integer'], 'installation_id' => ['type' => 'integer'], 'client_id' => ['type' => 'string'], 'private_key_id' => ['type' => 'integer'], 'is_system_wide' => ['type' => 'boolean'], 'is_public' => ['type' => 'boolean'], 'team_id' => ['type' => 'integer'], 'type' => ['type' => 'string'], ] ) ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function list_github_apps(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $githubApps = GithubApp::where(function ($query) use ($teamId) { $query->where('team_id', $teamId) ->orWhere('is_system_wide', true); })->get(); $githubApps = $githubApps->map(function ($app) { return $this->removeSensitiveData($app); }); return response()->json($githubApps); } #[OA\Post( summary: 'Create GitHub App', description: 'Create a new GitHub app.', path: '/github-apps', operationId: 'create-github-app', security: [ ['bearerAuth' => []], ], tags: ['GitHub Apps'], requestBody: new OA\RequestBody( description: 'GitHub app creation payload.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'Name of the GitHub app.'], 'organization' => ['type' => 'string', 'nullable' => true, 'description' => 'Organization to associate the app with.'], 'api_url' => ['type' => 'string', 'description' => 'API URL for the GitHub app (e.g., https://api.github.com).'], 'html_url' => ['type' => 'string', 'description' => 'HTML URL for the GitHub app (e.g., https://github.com).'], 'custom_user' => ['type' => 'string', 'description' => 'Custom user for SSH access (default: git).'], 'custom_port' => ['type' => 'integer', 'description' => 'Custom port for SSH access (default: 22).'], 'app_id' => ['type' => 'integer', 'description' => 'GitHub App ID from GitHub.'], 'installation_id' => ['type' => 'integer', 'description' => 'GitHub Installation ID.'], 'client_id' => ['type' => 'string', 'description' => 'GitHub OAuth App Client ID.'], 'client_secret' => ['type' => 'string', 'description' => 'GitHub OAuth App Client Secret.'], 'webhook_secret' => ['type' => 'string', 'description' => 'Webhook secret for GitHub webhooks.'], 'private_key_uuid' => ['type' => 'string', 'description' => 'UUID of an existing private key for GitHub App authentication.'], 'is_system_wide' => ['type' => 'boolean', 'description' => 'Is this app system-wide (cloud only).'], ], required: ['name', 'api_url', 'html_url', 'app_id', 'installation_id', 'client_id', 'client_secret', 'private_key_uuid'], ), ), ], ), responses: [ new OA\Response( response: 201, description: 'GitHub app created successfully.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'id' => ['type' => 'integer'], 'uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'organization' => ['type' => 'string', 'nullable' => true], 'api_url' => ['type' => 'string'], 'html_url' => ['type' => 'string'], 'custom_user' => ['type' => 'string'], 'custom_port' => ['type' => 'integer'], 'app_id' => ['type' => 'integer'], 'installation_id' => ['type' => 'integer'], 'client_id' => ['type' => 'string'], 'private_key_id' => ['type' => 'integer'], 'is_system_wide' => ['type' => 'boolean'], 'team_id' => ['type' => 'integer'], ] ) ), ] ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_github_app(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $allowedFields = [ 'name', 'organization', 'api_url', 'html_url', 'custom_user', 'custom_port', 'app_id', 'installation_id', 'client_id', 'client_secret', 'webhook_secret', 'private_key_uuid', 'is_system_wide', ]; $validator = customApiValidator($request->all(), [ 'name' => 'required|string|max:255', 'organization' => 'nullable|string|max:255', 'api_url' => 'required|string|url', 'html_url' => 'required|string|url', 'custom_user' => 'nullable|string|max:255', 'custom_port' => 'nullable|integer|min:1|max:65535', 'app_id' => 'required|integer', 'installation_id' => 'required|integer', 'client_id' => 'required|string|max:255', 'client_secret' => 'required|string', 'webhook_secret' => 'required|string', 'private_key_uuid' => 'required|string', 'is_system_wide' => 'boolean', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } try { // Verify the private key belongs to the team $privateKey = PrivateKey::where('uuid', $request->input('private_key_uuid')) ->where('team_id', $teamId) ->first(); if (! $privateKey) { return response()->json([ 'message' => 'Private key not found or does not belong to your team.', ], 404); } $payload = [ 'uuid' => Str::uuid(), 'name' => $request->input('name'), 'organization' => $request->input('organization'), 'api_url' => $request->input('api_url'), 'html_url' => $request->input('html_url'), 'custom_user' => $request->input('custom_user', 'git'), 'custom_port' => $request->input('custom_port', 22), 'app_id' => $request->input('app_id'), 'installation_id' => $request->input('installation_id'), 'client_id' => $request->input('client_id'), 'client_secret' => $request->input('client_secret'), 'webhook_secret' => $request->input('webhook_secret'), 'private_key_id' => $privateKey->id, 'is_public' => false, 'team_id' => $teamId, ]; if (! isCloud()) { $payload['is_system_wide'] = $request->input('is_system_wide', false); } $githubApp = GithubApp::create($payload); return response()->json($githubApp, 201); } catch (\Throwable $e) { return handleError($e); } } #[OA\Get( path: '/github-apps/{github_app_id}/repositories', summary: 'Load Repositories for a GitHub App', description: 'Fetch repositories from GitHub for a given GitHub app.', operationId: 'load-repositories', tags: ['GitHub Apps'], security: [ ['bearerAuth' => []], ], parameters: [ new OA\Parameter( name: 'github_app_id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'), description: 'GitHub App ID' ), ], responses: [ new OA\Response( response: 200, description: 'Repositories loaded successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ new OA\Property( property: 'repositories', type: 'array', items: new OA\Items(type: 'object') ), ] ) ) ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function load_repositories($github_app_id) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } try { $githubApp = GithubApp::where('id', $github_app_id) ->where('team_id', $teamId) ->firstOrFail(); $token = generateGithubInstallationToken($githubApp); $repositories = collect(); $page = 1; $maxPages = 100; // Safety limit: max 10,000 repositories while ($page <= $maxPages) { $response = Http::GitHub($githubApp->api_url, $token) ->timeout(20) ->retry(3, 200, throw: false) ->get('/installation/repositories', [ 'per_page' => 100, 'page' => $page, ]); if ($response->status() !== 200) { return response()->json([ 'message' => $response->json()['message'] ?? 'Failed to load repositories', ], $response->status()); } $json = $response->json(); $repos = $json['repositories'] ?? []; if (empty($repos)) { break; // No more repositories to load } $repositories = $repositories->concat($repos); $page++; } return response()->json([ 'repositories' => $repositories->sortBy('name')->values(), ]); } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { return response()->json(['message' => 'GitHub app not found'], 404); } catch (\Throwable $e) { return handleError($e); } } #[OA\Get( path: '/github-apps/{github_app_id}/repositories/{owner}/{repo}/branches', summary: 'Load Branches for a GitHub Repository', description: 'Fetch branches from GitHub for a given repository.', operationId: 'load-branches', tags: ['GitHub Apps'], security: [ ['bearerAuth' => []], ], parameters: [ new OA\Parameter( name: 'github_app_id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'), description: 'GitHub App ID' ), new OA\Parameter( name: 'owner', in: 'path', required: true, schema: new OA\Schema(type: 'string'), description: 'Repository owner' ), new OA\Parameter( name: 'repo', in: 'path', required: true, schema: new OA\Schema(type: 'string'), description: 'Repository name' ), ], responses: [ new OA\Response( response: 200, description: 'Branches loaded successfully.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ new OA\Property( property: 'branches', type: 'array', items: new OA\Items(type: 'object') ), ] ) ) ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function load_branches($github_app_id, $owner, $repo) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } try { $githubApp = GithubApp::where('id', $github_app_id) ->where('team_id', $teamId) ->firstOrFail(); $token = generateGithubInstallationToken($githubApp); $response = Http::GitHub($githubApp->api_url, $token) ->timeout(20) ->retry(3, 200, throw: false) ->get("/repos/{$owner}/{$repo}/branches"); if ($response->status() !== 200) { return response()->json([ 'message' => 'Error loading branches from GitHub.', 'error' => $response->json('message'), ], $response->status()); } $branches = $response->json(); return response()->json([ 'branches' => $branches, ]); } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { return response()->json(['message' => 'GitHub app not found'], 404); } catch (\Throwable $e) { return handleError($e); } } /** * Update a GitHub app. */ #[OA\Patch( path: '/github-apps/{github_app_id}', operationId: 'updateGithubApp', security: [ ['bearerAuth' => []], ], tags: ['GitHub Apps'], summary: 'Update GitHub App', description: 'Update an existing GitHub app.', parameters: [ new OA\Parameter( name: 'github_app_id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'), description: 'GitHub App ID' ), ], requestBody: new OA\RequestBody( required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'GitHub App name'], 'organization' => ['type' => 'string', 'nullable' => true, 'description' => 'GitHub organization'], 'api_url' => ['type' => 'string', 'description' => 'GitHub API URL'], 'html_url' => ['type' => 'string', 'description' => 'GitHub HTML URL'], 'custom_user' => ['type' => 'string', 'description' => 'Custom user for SSH'], 'custom_port' => ['type' => 'integer', 'description' => 'Custom port for SSH'], 'app_id' => ['type' => 'integer', 'description' => 'GitHub App ID'], 'installation_id' => ['type' => 'integer', 'description' => 'GitHub Installation ID'], 'client_id' => ['type' => 'string', 'description' => 'GitHub Client ID'], 'client_secret' => ['type' => 'string', 'description' => 'GitHub Client Secret'], 'webhook_secret' => ['type' => 'string', 'description' => 'GitHub Webhook Secret'], 'private_key_uuid' => ['type' => 'string', 'description' => 'Private key UUID'], 'is_system_wide' => ['type' => 'boolean', 'description' => 'Is system wide (non-cloud instances only)'], ] ) ) ), responses: [ new OA\Response( response: 200, description: 'GitHub app updated successfully', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'GitHub app updated successfully'], 'data' => ['type' => 'object', 'description' => 'Updated GitHub app data'], ] ) ) ), new OA\Response(response: 401, description: 'Unauthorized'), new OA\Response(response: 404, description: 'GitHub app not found'), new OA\Response(response: 422, ref: '#/components/responses/422'), ] )] public function update_github_app(Request $request, $github_app_id) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } try { $githubApp = GithubApp::where('id', $github_app_id) ->where('team_id', $teamId) ->firstOrFail(); // Define allowed fields for update $allowedFields = [ 'name', 'organization', 'api_url', 'html_url', 'custom_user', 'custom_port', 'app_id', 'installation_id', 'client_id', 'client_secret', 'webhook_secret', 'private_key_uuid', ]; if (! isCloud()) { $allowedFields[] = 'is_system_wide'; } $payload = $request->only($allowedFields); // Validate the request $rules = []; if (isset($payload['name'])) { $rules['name'] = 'string'; } if (isset($payload['organization'])) { $rules['organization'] = 'nullable|string'; } if (isset($payload['api_url'])) { $rules['api_url'] = 'url'; } if (isset($payload['html_url'])) { $rules['html_url'] = 'url'; } if (isset($payload['custom_user'])) { $rules['custom_user'] = 'string'; } if (isset($payload['custom_port'])) { $rules['custom_port'] = 'integer|min:1|max:65535'; } if (isset($payload['app_id'])) { $rules['app_id'] = 'integer'; } if (isset($payload['installation_id'])) { $rules['installation_id'] = 'integer'; } if (isset($payload['client_id'])) { $rules['client_id'] = 'string'; } if (isset($payload['client_secret'])) { $rules['client_secret'] = 'string'; } if (isset($payload['webhook_secret'])) { $rules['webhook_secret'] = 'string'; } if (isset($payload['private_key_uuid'])) { $rules['private_key_uuid'] = 'string|uuid'; } if (! isCloud() && isset($payload['is_system_wide'])) { $rules['is_system_wide'] = 'boolean'; } $validator = customApiValidator($payload, $rules); if ($validator->fails()) { return response()->json([ 'message' => 'Validation error', 'errors' => $validator->errors(), ], 422); } // Handle private_key_uuid -> private_key_id conversion if (isset($payload['private_key_uuid'])) { $privateKey = PrivateKey::where('team_id', $teamId) ->where('uuid', $payload['private_key_uuid']) ->first(); if (! $privateKey) { return response()->json([ 'message' => 'Private key not found or does not belong to your team', ], 404); } unset($payload['private_key_uuid']); $payload['private_key_id'] = $privateKey->id; } // Update the GitHub app $githubApp->update($payload); return response()->json([ 'message' => 'GitHub app updated successfully', 'data' => $githubApp, ]); } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { return response()->json([ 'message' => 'GitHub app not found', ], 404); } } /** * Delete a GitHub app. */ #[OA\Delete( path: '/github-apps/{github_app_id}', operationId: 'deleteGithubApp', security: [ ['bearerAuth' => []], ], tags: ['GitHub Apps'], summary: 'Delete GitHub App', description: 'Delete a GitHub app if it\'s not being used by any applications.', parameters: [ new OA\Parameter( name: 'github_app_id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'), description: 'GitHub App ID' ), ], responses: [ new OA\Response( response: 200, description: 'GitHub app deleted successfully', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'GitHub app deleted successfully'], ] ) ) ), new OA\Response(response: 401, description: 'Unauthorized'), new OA\Response(response: 404, description: 'GitHub app not found'), new OA\Response( response: 409, description: 'Conflict - GitHub app is in use', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'This GitHub app is being used by 5 application(s). Please delete all applications first.'], ] ) ) ), ] )] public function delete_github_app($github_app_id) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } try { $githubApp = GithubApp::where('id', $github_app_id) ->where('team_id', $teamId) ->firstOrFail(); // Check if the GitHub app is being used by any applications if ($githubApp->applications->isNotEmpty()) { $count = $githubApp->applications->count(); return response()->json([ 'message' => "This GitHub app is being used by {$count} application(s). Please delete all applications first.", ], 409); } $githubApp->delete(); return response()->json([ 'message' => 'GitHub app deleted successfully', ]); } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) { return response()->json([ 'message' => 'GitHub app not found', ], 404); } } } ================================================ FILE: app/Http/Controllers/Api/HetznerController.php ================================================ cloud_provider_token_uuid ?? $request->cloud_provider_token_id; } #[OA\Get( summary: 'Get Hetzner Locations', description: 'Get all available Hetzner datacenter locations.', path: '/hetzner/locations', operationId: 'get-hetzner-locations', security: [ ['bearerAuth' => []], ], tags: ['Hetzner'], parameters: [ new OA\Parameter( name: 'cloud_provider_token_uuid', in: 'query', required: false, description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'cloud_provider_token_id', in: 'query', required: false, deprecated: true, description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.', schema: new OA\Schema(type: 'string') ), ], responses: [ new OA\Response( response: 200, description: 'List of Hetzner locations.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'country' => ['type' => 'string'], 'city' => ['type' => 'string'], 'latitude' => ['type' => 'number'], 'longitude' => ['type' => 'number'], ] ) ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function locations(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $validator = customApiValidator($request->all(), [ 'cloud_provider_token_uuid' => 'required_without:cloud_provider_token_id|string', 'cloud_provider_token_id' => 'required_without:cloud_provider_token_uuid|string', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $tokenUuid = $this->getCloudProviderTokenUuid($request); $token = CloudProviderToken::whereTeamId($teamId) ->whereUuid($tokenUuid) ->where('provider', 'hetzner') ->first(); if (! $token) { return response()->json(['message' => 'Hetzner cloud provider token not found.'], 404); } try { $hetznerService = new HetznerService($token->token); $locations = $hetznerService->getLocations(); return response()->json($locations); } catch (\Throwable $e) { return response()->json(['message' => 'Failed to fetch locations: '.$e->getMessage()], 500); } } #[OA\Get( summary: 'Get Hetzner Server Types', description: 'Get all available Hetzner server types (instance sizes).', path: '/hetzner/server-types', operationId: 'get-hetzner-server-types', security: [ ['bearerAuth' => []], ], tags: ['Hetzner'], parameters: [ new OA\Parameter( name: 'cloud_provider_token_uuid', in: 'query', required: false, description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'cloud_provider_token_id', in: 'query', required: false, deprecated: true, description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.', schema: new OA\Schema(type: 'string') ), ], responses: [ new OA\Response( response: 200, description: 'List of Hetzner server types.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'cores' => ['type' => 'integer'], 'memory' => ['type' => 'number'], 'disk' => ['type' => 'integer'], 'prices' => [ 'type' => 'array', 'items' => [ 'type' => 'object', 'properties' => [ 'location' => ['type' => 'string', 'description' => 'Datacenter location name'], 'price_hourly' => [ 'type' => 'object', 'properties' => [ 'net' => ['type' => 'string'], 'gross' => ['type' => 'string'], ], ], 'price_monthly' => [ 'type' => 'object', 'properties' => [ 'net' => ['type' => 'string'], 'gross' => ['type' => 'string'], ], ], ], ], ], ] ) ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function serverTypes(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $validator = customApiValidator($request->all(), [ 'cloud_provider_token_uuid' => 'required_without:cloud_provider_token_id|string', 'cloud_provider_token_id' => 'required_without:cloud_provider_token_uuid|string', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $tokenUuid = $this->getCloudProviderTokenUuid($request); $token = CloudProviderToken::whereTeamId($teamId) ->whereUuid($tokenUuid) ->where('provider', 'hetzner') ->first(); if (! $token) { return response()->json(['message' => 'Hetzner cloud provider token not found.'], 404); } try { $hetznerService = new HetznerService($token->token); $serverTypes = $hetznerService->getServerTypes(); return response()->json($serverTypes); } catch (\Throwable $e) { return response()->json(['message' => 'Failed to fetch server types: '.$e->getMessage()], 500); } } #[OA\Get( summary: 'Get Hetzner Images', description: 'Get all available Hetzner system images (operating systems).', path: '/hetzner/images', operationId: 'get-hetzner-images', security: [ ['bearerAuth' => []], ], tags: ['Hetzner'], parameters: [ new OA\Parameter( name: 'cloud_provider_token_uuid', in: 'query', required: false, description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'cloud_provider_token_id', in: 'query', required: false, deprecated: true, description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.', schema: new OA\Schema(type: 'string') ), ], responses: [ new OA\Response( response: 200, description: 'List of Hetzner images.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'type' => ['type' => 'string'], 'os_flavor' => ['type' => 'string'], 'os_version' => ['type' => 'string'], 'architecture' => ['type' => 'string'], ] ) ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function images(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $validator = customApiValidator($request->all(), [ 'cloud_provider_token_uuid' => 'required_without:cloud_provider_token_id|string', 'cloud_provider_token_id' => 'required_without:cloud_provider_token_uuid|string', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $tokenUuid = $this->getCloudProviderTokenUuid($request); $token = CloudProviderToken::whereTeamId($teamId) ->whereUuid($tokenUuid) ->where('provider', 'hetzner') ->first(); if (! $token) { return response()->json(['message' => 'Hetzner cloud provider token not found.'], 404); } try { $hetznerService = new HetznerService($token->token); $images = $hetznerService->getImages(); // Filter out deprecated images (same as UI) $filtered = array_filter($images, function ($image) { if (isset($image['type']) && $image['type'] !== 'system') { return false; } if (isset($image['deprecated']) && $image['deprecated'] === true) { return false; } return true; }); return response()->json(array_values($filtered)); } catch (\Throwable $e) { return response()->json(['message' => 'Failed to fetch images: '.$e->getMessage()], 500); } } #[OA\Get( summary: 'Get Hetzner SSH Keys', description: 'Get all SSH keys stored in the Hetzner account.', path: '/hetzner/ssh-keys', operationId: 'get-hetzner-ssh-keys', security: [ ['bearerAuth' => []], ], tags: ['Hetzner'], parameters: [ new OA\Parameter( name: 'cloud_provider_token_uuid', in: 'query', required: false, description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.', schema: new OA\Schema(type: 'string') ), new OA\Parameter( name: 'cloud_provider_token_id', in: 'query', required: false, deprecated: true, description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.', schema: new OA\Schema(type: 'string') ), ], responses: [ new OA\Response( response: 200, description: 'List of Hetzner SSH keys.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'fingerprint' => ['type' => 'string'], 'public_key' => ['type' => 'string'], ] ) ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function sshKeys(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $validator = customApiValidator($request->all(), [ 'cloud_provider_token_uuid' => 'required_without:cloud_provider_token_id|string', 'cloud_provider_token_id' => 'required_without:cloud_provider_token_uuid|string', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $tokenUuid = $this->getCloudProviderTokenUuid($request); $token = CloudProviderToken::whereTeamId($teamId) ->whereUuid($tokenUuid) ->where('provider', 'hetzner') ->first(); if (! $token) { return response()->json(['message' => 'Hetzner cloud provider token not found.'], 404); } try { $hetznerService = new HetznerService($token->token); $sshKeys = $hetznerService->getSshKeys(); return response()->json($sshKeys); } catch (\Throwable $e) { return response()->json(['message' => 'Failed to fetch SSH keys: '.$e->getMessage()], 500); } } #[OA\Post( summary: 'Create Hetzner Server', description: 'Create a new server on Hetzner and register it in Coolify.', path: '/servers/hetzner', operationId: 'create-hetzner-server', security: [ ['bearerAuth' => []], ], tags: ['Hetzner'], requestBody: new OA\RequestBody( required: true, description: 'Hetzner server creation parameters', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['location', 'server_type', 'image', 'private_key_uuid'], properties: [ 'cloud_provider_token_uuid' => ['type' => 'string', 'example' => 'abc123', 'description' => 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.'], 'cloud_provider_token_id' => ['type' => 'string', 'example' => 'abc123', 'description' => 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.', 'deprecated' => true], 'location' => ['type' => 'string', 'example' => 'nbg1', 'description' => 'Hetzner location name'], 'server_type' => ['type' => 'string', 'example' => 'cx11', 'description' => 'Hetzner server type name'], 'image' => ['type' => 'integer', 'example' => 15512617, 'description' => 'Hetzner image ID'], 'name' => ['type' => 'string', 'example' => 'my-server', 'description' => 'Server name (auto-generated if not provided)'], 'private_key_uuid' => ['type' => 'string', 'example' => 'xyz789', 'description' => 'Private key UUID'], 'enable_ipv4' => ['type' => 'boolean', 'example' => true, 'description' => 'Enable IPv4 (default: true)'], 'enable_ipv6' => ['type' => 'boolean', 'example' => true, 'description' => 'Enable IPv6 (default: true)'], 'hetzner_ssh_key_ids' => ['type' => 'array', 'items' => ['type' => 'integer'], 'description' => 'Additional Hetzner SSH key IDs'], 'cloud_init_script' => ['type' => 'string', 'description' => 'Cloud-init YAML script (optional)'], 'instant_validate' => ['type' => 'boolean', 'example' => false, 'description' => 'Validate server immediately after creation'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Hetzner server created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'og888os', 'description' => 'The UUID of the server.'], 'hetzner_server_id' => ['type' => 'integer', 'description' => 'The Hetzner server ID.'], 'ip' => ['type' => 'string', 'description' => 'The server IP address.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), new OA\Response( response: 429, ref: '#/components/responses/429', ), ] )] public function createServer(Request $request) { $allowedFields = [ 'cloud_provider_token_uuid', 'cloud_provider_token_id', 'location', 'server_type', 'image', 'name', 'private_key_uuid', 'enable_ipv4', 'enable_ipv6', 'hetzner_ssh_key_ids', 'cloud_init_script', 'instant_validate', ]; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'cloud_provider_token_uuid' => 'required_without:cloud_provider_token_id|string', 'cloud_provider_token_id' => 'required_without:cloud_provider_token_uuid|string', 'location' => 'required|string', 'server_type' => 'required|string', 'image' => 'required|integer', 'name' => ['nullable', 'string', 'max:253', new ValidHostname], 'private_key_uuid' => 'required|string', 'enable_ipv4' => 'nullable|boolean', 'enable_ipv6' => 'nullable|boolean', 'hetzner_ssh_key_ids' => 'nullable|array', 'hetzner_ssh_key_ids.*' => 'integer', 'cloud_init_script' => ['nullable', 'string', new ValidCloudInitYaml], 'instant_validate' => 'nullable|boolean', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } // Check server limit if (Team::serverLimitReached()) { return response()->json(['message' => 'Server limit reached for your subscription.'], 400); } // Set defaults if (! $request->name) { $request->offsetSet('name', generate_random_name()); } if (is_null($request->enable_ipv4)) { $request->offsetSet('enable_ipv4', true); } if (is_null($request->enable_ipv6)) { $request->offsetSet('enable_ipv6', true); } if (is_null($request->hetzner_ssh_key_ids)) { $request->offsetSet('hetzner_ssh_key_ids', []); } if (is_null($request->instant_validate)) { $request->offsetSet('instant_validate', false); } // Validate cloud provider token $tokenUuid = $this->getCloudProviderTokenUuid($request); $token = CloudProviderToken::whereTeamId($teamId) ->whereUuid($tokenUuid) ->where('provider', 'hetzner') ->first(); if (! $token) { return response()->json(['message' => 'Hetzner cloud provider token not found.'], 404); } // Validate private key $privateKey = PrivateKey::whereTeamId($teamId)->whereUuid($request->private_key_uuid)->first(); if (! $privateKey) { return response()->json(['message' => 'Private key not found.'], 404); } try { $hetznerService = new HetznerService($token->token); // Get public key and MD5 fingerprint $publicKey = $privateKey->getPublicKey(); $md5Fingerprint = PrivateKey::generateMd5Fingerprint($privateKey->private_key); // Check if SSH key already exists on Hetzner $existingSshKeys = $hetznerService->getSshKeys(); $existingKey = null; foreach ($existingSshKeys as $key) { if ($key['fingerprint'] === $md5Fingerprint) { $existingKey = $key; break; } } // Upload SSH key if it doesn't exist if ($existingKey) { $sshKeyId = $existingKey['id']; } else { $sshKeyName = $privateKey->name; $uploadedKey = $hetznerService->uploadSshKey($sshKeyName, $publicKey); $sshKeyId = $uploadedKey['id']; } // Normalize server name to lowercase for RFC 1123 compliance $normalizedServerName = strtolower(trim($request->name)); // Prepare SSH keys array: Coolify key + user-selected Hetzner keys $sshKeys = array_merge( [$sshKeyId], $request->hetzner_ssh_key_ids ); // Remove duplicates $sshKeys = array_unique($sshKeys); $sshKeys = array_values($sshKeys); // Prepare server creation parameters $params = [ 'name' => $normalizedServerName, 'server_type' => $request->server_type, 'image' => $request->image, 'location' => $request->location, 'start_after_create' => true, 'ssh_keys' => $sshKeys, 'public_net' => [ 'enable_ipv4' => $request->enable_ipv4, 'enable_ipv6' => $request->enable_ipv6, ], ]; // Add cloud-init script if provided if (! empty($request->cloud_init_script)) { $params['user_data'] = $request->cloud_init_script; } // Create server on Hetzner $hetznerServer = $hetznerService->createServer($params); // Determine IP address to use (prefer IPv4, fallback to IPv6) $ipAddress = null; if ($request->enable_ipv4 && isset($hetznerServer['public_net']['ipv4']['ip'])) { $ipAddress = $hetznerServer['public_net']['ipv4']['ip']; } elseif ($request->enable_ipv6 && isset($hetznerServer['public_net']['ipv6']['ip'])) { $ipAddress = $hetznerServer['public_net']['ipv6']['ip']; } if (! $ipAddress) { throw new \Exception('No public IP address available. Enable at least one of IPv4 or IPv6.'); } // Create server in Coolify database $server = Server::create([ 'name' => $normalizedServerName, 'ip' => $ipAddress, 'user' => 'root', 'port' => 22, 'team_id' => $teamId, 'private_key_id' => $privateKey->id, 'cloud_provider_token_id' => $token->id, 'hetzner_server_id' => $hetznerServer['id'], ]); $server->proxy->set('status', 'exited'); $server->proxy->set('type', ProxyTypes::TRAEFIK->value); $server->save(); // Validate server if requested if ($request->instant_validate) { \App\Actions\Server\ValidateServer::dispatch($server); } return response()->json([ 'uuid' => $server->uuid, 'hetzner_server_id' => $hetznerServer['id'], 'ip' => $ipAddress, ])->setStatusCode(201); } catch (RateLimitException $e) { $response = response()->json(['message' => $e->getMessage()], 429); if ($e->retryAfter !== null) { $response->header('Retry-After', $e->retryAfter); } return $response; } catch (\Throwable $e) { return response()->json(['message' => 'Failed to create server: '.$e->getMessage()], 500); } } } ================================================ FILE: app/Http/Controllers/Api/OpenApi.php ================================================ ['The name field is required.'], 'api_url' => ['The api url field is required.', 'The api url format is invalid.'], ] ), ] )), new OA\Response( response: 429, description: 'Rate limit exceeded.', headers: [ new OA\Header( header: 'Retry-After', description: 'Number of seconds to wait before retrying.', schema: new OA\Schema(type: 'integer', example: 60) ), ], content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'Rate limit exceeded. Please try again later.'), ] )), ], )] class OpenApi { // This class is used to generate OpenAPI documentation // for the Coolify API. It is not a controller and does // not contain any routes. It is used to define the // OpenAPI metadata and security scheme for the API. } ================================================ FILE: app/Http/Controllers/Api/OtherController.php ================================================ []], ], responses: [ new OA\Response( response: 200, description: 'Returns the version of the application', content: new OA\MediaType( mediaType: 'text/html', schema: new OA\Schema(type: 'string'), example: 'v4.0.0', )), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function version(Request $request) { return response(config('constants.coolify.version')); } #[OA\Get( summary: 'Enable API', description: 'Enable API (only with root permissions).', path: '/enable', operationId: 'enable-api', security: [ ['bearerAuth' => []], ], responses: [ new OA\Response( response: 200, description: 'Enable API.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'API enabled.'), ] )), new OA\Response( response: 403, description: 'You are not allowed to enable the API.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'You are not allowed to enable the API.'), ] )), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function enable_api(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if ($teamId !== '0') { return response()->json(['message' => 'You are not allowed to enable the API.'], 403); } $settings = instanceSettings(); $settings->update(['is_api_enabled' => true]); return response()->json(['message' => 'API enabled.'], 200); } #[OA\Get( summary: 'Disable API', description: 'Disable API (only with root permissions).', path: '/disable', operationId: 'disable-api', security: [ ['bearerAuth' => []], ], responses: [ new OA\Response( response: 200, description: 'Disable API.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'API disabled.'), ] )), new OA\Response( response: 403, description: 'You are not allowed to disable the API.', content: new OA\JsonContent( type: 'object', properties: [ new OA\Property(property: 'message', type: 'string', example: 'You are not allowed to disable the API.'), ] )), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function disable_api(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if ($teamId !== '0') { return response()->json(['message' => 'You are not allowed to disable the API.'], 403); } $settings = instanceSettings(); $settings->update(['is_api_enabled' => false]); return response()->json(['message' => 'API disabled.'], 200); } public function feedback(Request $request) { $content = $request->input('content'); $webhook_url = config('constants.webhooks.feedback_discord_webhook'); if ($webhook_url) { Http::post($webhook_url, [ 'content' => $content, ]); } return response()->json(['message' => 'Feedback sent.'], 200); } #[OA\Get( summary: 'Healthcheck', description: 'Healthcheck endpoint.', path: '/health', operationId: 'healthcheck', responses: [ new OA\Response( response: 200, description: 'Healthcheck endpoint.', content: new OA\MediaType( mediaType: 'text/html', schema: new OA\Schema(type: 'string'), example: 'OK', )), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function healthcheck(Request $request) { return 'OK'; } } ================================================ FILE: app/Http/Controllers/Api/ProjectController.php ================================================ []], ], tags: ['Projects'], responses: [ new OA\Response( response: 200, description: 'Get all projects.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/Project') ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function projects(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $projects = Project::whereTeamId($teamId)->select('id', 'name', 'description', 'uuid')->get(); return response()->json(serializeApiResponse($projects), ); } #[OA\Get( summary: 'Get', description: 'Get project by UUID.', path: '/projects/{uuid}', operationId: 'get-project-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Projects'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Project details', content: new OA\JsonContent(ref: '#/components/schemas/Project')), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, description: 'Project not found.', ), ] )] public function project_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $project = Project::whereTeamId($teamId)->whereUuid(request()->uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $project->load(['environments']); return response()->json( serializeApiResponse($project), ); } #[OA\Get( summary: 'Environment', description: 'Get environment by name or UUID.', path: '/projects/{uuid}/{environment_name_or_uuid}', operationId: 'get-environment-by-name-or-uuid', security: [ ['bearerAuth' => []], ], tags: ['Projects'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'string')), new OA\Parameter(name: 'environment_name_or_uuid', in: 'path', required: true, description: 'Environment name or UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Environment details', content: new OA\JsonContent(ref: '#/components/schemas/Environment')), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function environment_details(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 422); } if (! $request->environment_name_or_uuid) { return response()->json(['message' => 'Environment name or UUID is required.'], 422); } $project = Project::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $environment = $project->environments()->whereName($request->environment_name_or_uuid)->first(); if (! $environment) { $environment = $project->environments()->whereUuid($request->environment_name_or_uuid)->first(); } if (! $environment) { return response()->json(['message' => 'Environment not found.'], 404); } $environment = $environment->load(['applications', 'postgresqls', 'redis', 'mongodbs', 'mysqls', 'mariadbs', 'services']); return response()->json(serializeApiResponse($environment)); } #[OA\Post( summary: 'Create', description: 'Create Project.', path: '/projects', operationId: 'create-project', security: [ ['bearerAuth' => []], ], tags: ['Projects'], requestBody: new OA\RequestBody( required: true, description: 'Project created.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the project.'], 'description' => ['type' => 'string', 'description' => 'The description of the project.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Project created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'og888os', 'description' => 'The UUID of the project.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_project(Request $request) { $allowedFields = ['name', 'description']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = Validator::make($request->all(), [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), ], ValidationPatterns::combinedMessages()); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $project = Project::create([ 'name' => $request->name, 'description' => $request->description, 'team_id' => $teamId, ]); return response()->json([ 'uuid' => $project->uuid, ])->setStatusCode(201); } #[OA\Patch( summary: 'Update', description: 'Update Project.', path: '/projects/{uuid}', operationId: 'update-project-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Projects'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the project.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( required: true, description: 'Project updated.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the project.'], 'description' => ['type' => 'string', 'description' => 'The description of the project.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Project updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'og888os'], 'name' => ['type' => 'string', 'example' => 'Project Name'], 'description' => ['type' => 'string', 'example' => 'Project Description'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_project(Request $request) { $allowedFields = ['name', 'description']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = Validator::make($request->all(), [ 'name' => ValidationPatterns::nameRules(required: false), 'description' => ValidationPatterns::descriptionRules(), ], ValidationPatterns::combinedMessages()); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $uuid = $request->uuid; if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 422); } $project = Project::whereTeamId($teamId)->whereUuid($uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $project->update($request->only($allowedFields)); return response()->json([ 'uuid' => $project->uuid, 'name' => $project->name, 'description' => $project->description, ])->setStatusCode(201); } #[OA\Delete( summary: 'Delete', description: 'Delete project by UUID.', path: '/projects/{uuid}', operationId: 'delete-project-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Projects'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Project deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Project deleted.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function delete_project(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 422); } $project = Project::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } if (! $project->isEmpty()) { return response()->json(['message' => 'Project has resources, so it cannot be deleted.'], 400); } $project->delete(); return response()->json(['message' => 'Project deleted.']); } #[OA\Get( summary: 'List Environments', description: 'List all environments in a project.', path: '/projects/{uuid}/environments', operationId: 'get-environments', security: [ ['bearerAuth' => []], ], tags: ['Projects'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'List of environments', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/Environment') ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, description: 'Project not found.', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function get_environments(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'Project UUID is required.'], 422); } $project = Project::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $environments = $project->environments()->select('id', 'name', 'uuid')->get(); return response()->json(serializeApiResponse($environments)); } #[OA\Post( summary: 'Create Environment', description: 'Create environment in project.', path: '/projects/{uuid}/environments', operationId: 'create-environment', security: [ ['bearerAuth' => []], ], tags: ['Projects'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'string')), ], requestBody: new OA\RequestBody( required: true, description: 'Environment created.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the environment.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Environment created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'env123', 'description' => 'The UUID of the environment.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, description: 'Project not found.', ), new OA\Response( response: 409, description: 'Environment with this name already exists.', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_environment(Request $request) { $allowedFields = ['name']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = Validator::make($request->all(), [ 'name' => ValidationPatterns::nameRules(), ], ValidationPatterns::nameMessages()); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if (! $request->uuid) { return response()->json(['message' => 'Project UUID is required.'], 422); } $project = Project::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $existingEnvironment = $project->environments()->where('name', $request->name)->first(); if ($existingEnvironment) { return response()->json(['message' => 'Environment with this name already exists.'], 409); } $environment = $project->environments()->create([ 'name' => $request->name, ]); return response()->json([ 'uuid' => $environment->uuid, ])->setStatusCode(201); } #[OA\Delete( summary: 'Delete Environment', description: 'Delete environment by name or UUID. Environment must be empty.', path: '/projects/{uuid}/environments/{environment_name_or_uuid}', operationId: 'delete-environment', security: [ ['bearerAuth' => []], ], tags: ['Projects'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Project UUID', schema: new OA\Schema(type: 'string')), new OA\Parameter(name: 'environment_name_or_uuid', in: 'path', required: true, description: 'Environment name or UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Environment deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Environment deleted.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, description: 'Environment has resources, so it cannot be deleted.', ), new OA\Response( response: 404, description: 'Project or environment not found.', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function delete_environment(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'Project UUID is required.'], 422); } if (! $request->environment_name_or_uuid) { return response()->json(['message' => 'Environment name or UUID is required.'], 422); } $project = Project::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $environment = $project->environments()->whereName($request->environment_name_or_uuid)->first(); if (! $environment) { $environment = $project->environments()->whereUuid($request->environment_name_or_uuid)->first(); } if (! $environment) { return response()->json(['message' => 'Environment not found.'], 404); } if (! $environment->isEmpty()) { return response()->json(['message' => 'Environment has resources, so it cannot be deleted.'], 400); } $environment->delete(); return response()->json(['message' => 'Environment deleted.']); } } ================================================ FILE: app/Http/Controllers/Api/ResourcesController.php ================================================ []], ], tags: ['Resources'], responses: [ new OA\Response( response: 200, description: 'Get all resources', content: new OA\JsonContent( type: 'string', example: 'Content is very complex. Will be implemented later.', ), ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function resources(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } // General authorization check for viewing resources - using Project as base resource type $this->authorize('viewAny', Project::class); $projects = Project::where('team_id', $teamId)->get(); $resources = collect(); $resources->push($projects->pluck('applications')->flatten()); $resources->push($projects->pluck('services')->flatten()); foreach (collect(DATABASE_TYPES) as $db) { $resources->push($projects->pluck(str($db)->plural(2))->flatten()); } $resources = $resources->flatten(); $resources = $resources->map(function ($resource) { $payload = $resource->toArray(); $payload['status'] = $resource->status; $payload['type'] = $resource->type(); return $payload; }); return response()->json(serializeApiResponse($resources)); } } ================================================ FILE: app/Http/Controllers/Api/ScheduledTasksController.php ================================================ makeHidden([ 'id', 'team_id', 'application_id', 'service_id', ]); return serializeApiResponse($task); } private function resolveApplication(Request $request, int $teamId): ?Application { return Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first(); } private function resolveService(Request $request, int $teamId): ?Service { return Service::whereRelation('environment.project.team', 'id', $teamId)->where('uuid', $request->uuid)->first(); } private function listTasks(Application|Service $resource): \Illuminate\Http\JsonResponse { $this->authorize('view', $resource); $tasks = $resource->scheduled_tasks->map(function ($task) { return $this->removeSensitiveData($task); }); return response()->json($tasks); } private function createTask(Request $request, Application|Service $resource): \Illuminate\Http\JsonResponse { $this->authorize('update', $resource); $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $allowedFields = ['name', 'command', 'frequency', 'container', 'timeout', 'enabled']; $validator = customApiValidator($request->all(), [ 'name' => 'required|string|max:255', 'command' => 'required|string', 'frequency' => 'required|string', 'container' => 'string|nullable', 'timeout' => 'integer|min:1', 'enabled' => 'boolean', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if (! validate_cron_expression($request->frequency)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['frequency' => ['Invalid cron expression or frequency format.']], ], 422); } $teamId = getTeamIdFromToken(); $task = new ScheduledTask; $task->name = $request->name; $task->command = $request->command; $task->frequency = $request->frequency; $task->container = $request->container; $task->timeout = $request->has('timeout') ? $request->timeout : 300; $task->enabled = $request->has('enabled') ? $request->enabled : true; $task->team_id = $teamId; if ($resource instanceof Application) { $task->application_id = $resource->id; } elseif ($resource instanceof Service) { $task->service_id = $resource->id; } $task->save(); return response()->json($this->removeSensitiveData($task), 201); } private function updateTask(Request $request, Application|Service $resource): \Illuminate\Http\JsonResponse { $this->authorize('update', $resource); $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } if ($request->all() === []) { return response()->json(['message' => 'At least one field must be provided.'], 422); } $allowedFields = ['name', 'command', 'frequency', 'container', 'timeout', 'enabled']; $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', 'command' => 'string', 'frequency' => 'string', 'container' => 'string|nullable', 'timeout' => 'integer|min:1', 'enabled' => 'boolean', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if ($request->has('frequency') && ! validate_cron_expression($request->frequency)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => ['frequency' => ['Invalid cron expression or frequency format.']], ], 422); } $task = $resource->scheduled_tasks()->where('uuid', $request->task_uuid)->first(); if (! $task) { return response()->json(['message' => 'Scheduled task not found.'], 404); } $task->update($request->only($allowedFields)); return response()->json($this->removeSensitiveData($task), 200); } private function deleteTask(Request $request, Application|Service $resource): \Illuminate\Http\JsonResponse { $this->authorize('update', $resource); $deleted = $resource->scheduled_tasks()->where('uuid', $request->task_uuid)->delete(); if (! $deleted) { return response()->json(['message' => 'Scheduled task not found.'], 404); } return response()->json(['message' => 'Scheduled task deleted.']); } private function getExecutions(Request $request, Application|Service $resource): \Illuminate\Http\JsonResponse { $this->authorize('view', $resource); $task = $resource->scheduled_tasks()->where('uuid', $request->task_uuid)->first(); if (! $task) { return response()->json(['message' => 'Scheduled task not found.'], 404); } $executions = $task->executions()->get()->map(function ($execution) { $execution->makeHidden(['id', 'scheduled_task_id']); return serializeApiResponse($execution); }); return response()->json($executions); } #[OA\Get( summary: 'List Tasks', description: 'List all scheduled tasks for an application.', path: '/applications/{uuid}/scheduled-tasks', operationId: 'list-scheduled-tasks-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get all scheduled tasks for an application.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/ScheduledTask') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function scheduled_tasks_by_application_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = $this->resolveApplication($request, $teamId); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } return $this->listTasks($application); } #[OA\Post( summary: 'Create Task', description: 'Create a new scheduled task for an application.', path: '/applications/{uuid}/scheduled-tasks', operationId: 'create-scheduled-task-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Scheduled task data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['name', 'command', 'frequency'], properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the scheduled task.'], 'command' => ['type' => 'string', 'description' => 'The command to execute.'], 'frequency' => ['type' => 'string', 'description' => 'The frequency of the scheduled task.'], 'container' => ['type' => 'string', 'nullable' => true, 'description' => 'The container where the command should be executed.'], 'timeout' => ['type' => 'integer', 'description' => 'The timeout of the scheduled task in seconds.', 'default' => 300], 'enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if the scheduled task is enabled.', 'default' => true], ], ), ) ), responses: [ new OA\Response( response: 201, description: 'Scheduled task created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema(ref: '#/components/schemas/ScheduledTask') ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_scheduled_task_by_application_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = $this->resolveApplication($request, $teamId); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } return $this->createTask($request, $application); } #[OA\Patch( summary: 'Update Task', description: 'Update a scheduled task for an application.', path: '/applications/{uuid}/scheduled-tasks/{task_uuid}', operationId: 'update-scheduled-task-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'task_uuid', in: 'path', description: 'UUID of the scheduled task.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Scheduled task data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the scheduled task.'], 'command' => ['type' => 'string', 'description' => 'The command to execute.'], 'frequency' => ['type' => 'string', 'description' => 'The frequency of the scheduled task.'], 'container' => ['type' => 'string', 'nullable' => true, 'description' => 'The container where the command should be executed.'], 'timeout' => ['type' => 'integer', 'description' => 'The timeout of the scheduled task in seconds.', 'default' => 300], 'enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if the scheduled task is enabled.', 'default' => true], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Scheduled task updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema(ref: '#/components/schemas/ScheduledTask') ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_scheduled_task_by_application_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = $this->resolveApplication($request, $teamId); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } return $this->updateTask($request, $application); } #[OA\Delete( summary: 'Delete Task', description: 'Delete a scheduled task for an application.', path: '/applications/{uuid}/scheduled-tasks/{task_uuid}', operationId: 'delete-scheduled-task-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'task_uuid', in: 'path', description: 'UUID of the scheduled task.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Scheduled task deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Scheduled task deleted.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function delete_scheduled_task_by_application_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = $this->resolveApplication($request, $teamId); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } return $this->deleteTask($request, $application); } #[OA\Get( summary: 'List Executions', description: 'List all executions for a scheduled task on an application.', path: '/applications/{uuid}/scheduled-tasks/{task_uuid}/executions', operationId: 'list-scheduled-task-executions-by-application-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the application.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'task_uuid', in: 'path', description: 'UUID of the scheduled task.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get all executions for a scheduled task.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/ScheduledTaskExecution') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function executions_by_application_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $application = $this->resolveApplication($request, $teamId); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } return $this->getExecutions($request, $application); } #[OA\Get( summary: 'List Tasks', description: 'List all scheduled tasks for a service.', path: '/services/{uuid}/scheduled-tasks', operationId: 'list-scheduled-tasks-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get all scheduled tasks for a service.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/ScheduledTask') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function scheduled_tasks_by_service_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = $this->resolveService($request, $teamId); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } return $this->listTasks($service); } #[OA\Post( summary: 'Create Task', description: 'Create a new scheduled task for a service.', path: '/services/{uuid}/scheduled-tasks', operationId: 'create-scheduled-task-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Scheduled task data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['name', 'command', 'frequency'], properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the scheduled task.'], 'command' => ['type' => 'string', 'description' => 'The command to execute.'], 'frequency' => ['type' => 'string', 'description' => 'The frequency of the scheduled task.'], 'container' => ['type' => 'string', 'nullable' => true, 'description' => 'The container where the command should be executed.'], 'timeout' => ['type' => 'integer', 'description' => 'The timeout of the scheduled task in seconds.', 'default' => 300], 'enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if the scheduled task is enabled.', 'default' => true], ], ), ) ), responses: [ new OA\Response( response: 201, description: 'Scheduled task created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema(ref: '#/components/schemas/ScheduledTask') ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_scheduled_task_by_service_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = $this->resolveService($request, $teamId); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } return $this->createTask($request, $service); } #[OA\Patch( summary: 'Update Task', description: 'Update a scheduled task for a service.', path: '/services/{uuid}/scheduled-tasks/{task_uuid}', operationId: 'update-scheduled-task-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'task_uuid', in: 'path', description: 'UUID of the scheduled task.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Scheduled task data', required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the scheduled task.'], 'command' => ['type' => 'string', 'description' => 'The command to execute.'], 'frequency' => ['type' => 'string', 'description' => 'The frequency of the scheduled task.'], 'container' => ['type' => 'string', 'nullable' => true, 'description' => 'The container where the command should be executed.'], 'timeout' => ['type' => 'integer', 'description' => 'The timeout of the scheduled task in seconds.', 'default' => 300], 'enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if the scheduled task is enabled.', 'default' => true], ], ), ) ), responses: [ new OA\Response( response: 200, description: 'Scheduled task updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema(ref: '#/components/schemas/ScheduledTask') ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_scheduled_task_by_service_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = $this->resolveService($request, $teamId); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } return $this->updateTask($request, $service); } #[OA\Delete( summary: 'Delete Task', description: 'Delete a scheduled task for a service.', path: '/services/{uuid}/scheduled-tasks/{task_uuid}', operationId: 'delete-scheduled-task-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'task_uuid', in: 'path', description: 'UUID of the scheduled task.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Scheduled task deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Scheduled task deleted.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function delete_scheduled_task_by_service_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = $this->resolveService($request, $teamId); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } return $this->deleteTask($request, $service); } #[OA\Get( summary: 'List Executions', description: 'List all executions for a scheduled task on a service.', path: '/services/{uuid}/scheduled-tasks/{task_uuid}/executions', operationId: 'list-scheduled-task-executions-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Scheduled Tasks'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'task_uuid', in: 'path', description: 'UUID of the scheduled task.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Get all executions for a scheduled task.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/ScheduledTaskExecution') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function executions_by_service_uuid(Request $request): \Illuminate\Http\JsonResponse { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = $this->resolveService($request, $teamId); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } return $this->getExecutions($request, $service); } } ================================================ FILE: app/Http/Controllers/Api/SecurityController.php ================================================ attributes->get('can_read_sensitive', false) === false) { $team->makeHidden([ 'private_key', ]); } return serializeApiResponse($team); } #[OA\Get( summary: 'List', description: 'List all private keys.', path: '/security/keys', operationId: 'list-private-keys', security: [ ['bearerAuth' => []], ], tags: ['Private Keys'], responses: [ new OA\Response( response: 200, description: 'Get all private keys.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/PrivateKey') ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function keys(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $keys = PrivateKey::where('team_id', $teamId)->get(); return response()->json($this->removeSensitiveData($keys)); } #[OA\Get( summary: 'Get', description: 'Get key by UUID.', path: '/security/keys/{uuid}', operationId: 'get-private-key-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Private Keys'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Get all private keys.', content: new OA\JsonContent(ref: '#/components/schemas/PrivateKey') ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, description: 'Private Key not found.', ), ] )] public function key_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $key = PrivateKey::where('team_id', $teamId)->where('uuid', $request->uuid)->first(); if (is_null($key)) { return response()->json([ 'message' => 'Private Key not found.', ], 404); } return response()->json($this->removeSensitiveData($key)); } #[OA\Post( summary: 'Create', description: 'Create a new private key.', path: '/security/keys', operationId: 'create-private-key', security: [ ['bearerAuth' => []], ], tags: ['Private Keys'], requestBody: new OA\RequestBody( required: true, content: [ 'application/json' => new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['private_key'], properties: [ 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'private_key' => ['type' => 'string'], ], additionalProperties: false, ) ), ] ), responses: [ new OA\Response( response: 201, description: 'The created private key\'s UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_key(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', 'description' => 'string|max:255', 'private_key' => 'required|string', ]); if ($validator->fails()) { $errors = $validator->errors(); return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if (! $request->name) { $request->offsetSet('name', generate_random_name()); } if (! $request->description) { $request->offsetSet('description', 'Created by Coolify via API'); } $isPrivateKeyString = str_starts_with($request->private_key, '-----BEGIN'); if (! $isPrivateKeyString) { try { $base64PrivateKey = base64_decode($request->private_key); $request->offsetSet('private_key', $base64PrivateKey); } catch (\Exception $e) { return response()->json([ 'message' => 'Invalid private key.', ], 422); } } $isPrivateKeyValid = PrivateKey::validatePrivateKey($request->private_key); if (! $isPrivateKeyValid) { return response()->json([ 'message' => 'Invalid private key.', ], 422); } $fingerPrint = PrivateKey::generateFingerprint($request->private_key); $isFingerPrintExists = PrivateKey::fingerprintExists($fingerPrint); if ($isFingerPrintExists) { return response()->json([ 'message' => 'Private key already exists.', ], 422); } $key = PrivateKey::create([ 'team_id' => $teamId, 'name' => $request->name, 'description' => $request->description, 'private_key' => $request->private_key, ]); return response()->json(serializeApiResponse([ 'uuid' => $key->uuid, ]))->setStatusCode(201); } #[OA\Patch( summary: 'Update', description: 'Update a private key.', path: '/security/keys', operationId: 'update-private-key', security: [ ['bearerAuth' => []], ], tags: ['Private Keys'], requestBody: new OA\RequestBody( required: true, content: [ 'application/json' => new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['private_key'], properties: [ 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'private_key' => ['type' => 'string'], ], additionalProperties: false, ) ), ] ), responses: [ new OA\Response( response: 201, description: 'The updated private key\'s UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_key(Request $request) { $allowedFields = ['name', 'description', 'private_key']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', 'description' => 'string|max:255', 'private_key' => 'required|string', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $foundKey = PrivateKey::where('team_id', $teamId)->where('uuid', $request->uuid)->first(); if (is_null($foundKey)) { return response()->json([ 'message' => 'Private Key not found.', ], 404); } $foundKey->update($request->all()); return response()->json(serializeApiResponse([ 'uuid' => $foundKey->uuid, ]))->setStatusCode(201); } #[OA\Delete( summary: 'Delete', description: 'Delete a private key.', path: '/security/keys/{uuid}', operationId: 'delete-private-key-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Private Keys'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Private Key deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Private Key deleted.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, description: 'Private Key not found.', ), new OA\Response( response: 422, description: 'Private Key is in use and cannot be deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Private Key is in use and cannot be deleted.'], ] ) ), ]), ] )] public function delete_key(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 422); } $key = PrivateKey::where('team_id', $teamId)->where('uuid', $request->uuid)->first(); if (is_null($key)) { return response()->json(['message' => 'Private Key not found.'], 404); } if ($key->isInUse()) { return response()->json([ 'message' => 'Private Key is in use and cannot be deleted.', 'details' => 'This private key is currently being used by servers, applications, or Git integrations.', ], 422); } $key->forceDelete(); return response()->json([ 'message' => 'Private Key deleted.', ]); } } ================================================ FILE: app/Http/Controllers/Api/ServersController.php ================================================ attributes->get('can_read_sensitive', false) === false) { $settings = $settings->makeHidden([ 'sentinel_token', ]); } return serializeApiResponse($settings); } private function removeSensitiveData($server) { $server->makeHidden([ 'id', ]); if (request()->attributes->get('can_read_sensitive', false) === false) { // Do nothing } return serializeApiResponse($server); } #[OA\Get( summary: 'List', description: 'List all servers.', path: '/servers', operationId: 'list-servers', security: [ ['bearerAuth' => []], ], tags: ['Servers'], responses: [ new OA\Response( response: 200, description: 'Get all servers.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/Server') ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function servers(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $servers = ModelsServer::whereTeamId($teamId)->select('id', 'name', 'uuid', 'ip', 'user', 'port', 'description')->get()->load(['settings'])->map(function ($server) { $server['is_reachable'] = $server->settings->is_reachable; $server['is_usable'] = $server->settings->is_usable; return $server; }); $servers = $servers->map(function ($server) { $settings = $this->removeSensitiveDataFromSettings($server->settings); $server = $this->removeSensitiveData($server); data_set($server, 'settings', $settings); return $server; }); return response()->json($servers); } #[OA\Get( summary: 'Get', description: 'Get server by UUID.', path: '/servers/{uuid}', operationId: 'get-server-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Servers'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Get server by UUID', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( ref: '#/components/schemas/Server' ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function server_by_uuid(Request $request) { $with_resources = $request->query('resources'); $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $server = ModelsServer::whereTeamId($teamId)->whereUuid(request()->uuid)->first(); if (is_null($server)) { return response()->json(['message' => 'Server not found.'], 404); } if ($with_resources) { $server['resources'] = $server->definedResources()->map(function ($resource) { $payload = [ 'id' => $resource->id, 'uuid' => $resource->uuid, 'name' => $resource->name, 'type' => $resource->type(), 'created_at' => $resource->created_at, 'updated_at' => $resource->updated_at, ]; $payload['status'] = $resource->status; return $payload; }); } else { $server->load(['settings']); } $settings = $this->removeSensitiveDataFromSettings($server->settings); $server = $this->removeSensitiveData($server); data_set($server, 'settings', $settings); return response()->json(serializeApiResponse($server)); } #[OA\Get( summary: 'Resources', description: 'Get resources by server.', path: '/servers/{uuid}/resources', operationId: 'get-resources-by-server-uuid', security: [ ['bearerAuth' => []], ], tags: ['Servers'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Get resources by server', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'id' => ['type' => 'integer'], 'uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'type' => ['type' => 'string'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], 'status' => ['type' => 'string'], ] ) )), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function resources_by_server(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $server = ModelsServer::whereTeamId($teamId)->whereUuid(request()->uuid)->first(); if (is_null($server)) { return response()->json(['message' => 'Server not found.'], 404); } $server['resources'] = $server->definedResources()->map(function ($resource) { $payload = [ 'id' => $resource->id, 'uuid' => $resource->uuid, 'name' => $resource->name, 'type' => $resource->type(), 'created_at' => $resource->created_at, 'updated_at' => $resource->updated_at, ]; $payload['status'] = $resource->status; return $payload; }); $server = $this->removeSensitiveData($server); return response()->json(serializeApiResponse(data_get($server, 'resources'))); } #[OA\Get( summary: 'Domains', description: 'Get domains by server.', path: '/servers/{uuid}/domains', operationId: 'get-domains-by-server-uuid', security: [ ['bearerAuth' => []], ], tags: ['Servers'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Get domains by server', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items( type: 'object', properties: [ 'ip' => ['type' => 'string'], 'domains' => ['type' => 'array', 'items' => ['type' => 'string']], ] ) )), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function domains_by_server(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->get('uuid'); if ($uuid) { $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $uuid)->first(); if (! $application) { return response()->json(['message' => 'Application not found.'], 404); } return response()->json(serializeApiResponse($application->fqdns)); } $projects = Project::where('team_id', $teamId)->get(); $domains = collect(); $applications = $projects->pluck('applications')->flatten(); $settings = instanceSettings(); if ($applications->count() > 0) { foreach ($applications as $application) { $ip = $application->destination->server->ip; $fqdn = str($application->fqdn)->explode(',')->map(function ($fqdn) { $f = str($fqdn)->replace('http://', '')->replace('https://', '')->explode('/'); return str(str($f[0])->explode(':')[0]); })->filter(function (Stringable $fqdn) { return $fqdn->isNotEmpty(); }); if ($ip === 'host.docker.internal') { if ($settings->public_ipv4) { $domains->push([ 'domain' => $fqdn, 'ip' => $settings->public_ipv4, ]); } if ($settings->public_ipv6) { $domains->push([ 'domain' => $fqdn, 'ip' => $settings->public_ipv6, ]); } if (! $settings->public_ipv4 && ! $settings->public_ipv6) { $domains->push([ 'domain' => $fqdn, 'ip' => $ip, ]); } } else { $domains->push([ 'domain' => $fqdn, 'ip' => $ip, ]); } } } $services = $projects->pluck('services')->flatten(); if ($services->count() > 0) { foreach ($services as $service) { $service_applications = $service->applications; if ($service_applications->count() > 0) { foreach ($service_applications as $application) { $fqdn = str($application->fqdn)->explode(',')->map(function ($fqdn) { $f = str($fqdn)->replace('http://', '')->replace('https://', '')->explode('/'); return str(str($f[0])->explode(':')[0]); })->filter(function (Stringable $fqdn) { return $fqdn->isNotEmpty(); }); if ($ip === 'host.docker.internal') { if ($settings->public_ipv4) { $domains->push([ 'domain' => $fqdn, 'ip' => $settings->public_ipv4, ]); } if ($settings->public_ipv6) { $domains->push([ 'domain' => $fqdn, 'ip' => $settings->public_ipv6, ]); } if (! $settings->public_ipv4 && ! $settings->public_ipv6) { $domains->push([ 'domain' => $fqdn, 'ip' => $ip, ]); } } else { $domains->push([ 'domain' => $fqdn, 'ip' => $ip, ]); } } } } } $domains = $domains->groupBy('ip')->map(function ($domain) { return $domain->pluck('domain')->flatten(); })->map(function ($domain, $ip) { return [ 'ip' => $ip, 'domains' => $domain, ]; })->values(); return response()->json(serializeApiResponse($domains)); } #[OA\Post( summary: 'Create', description: 'Create Server.', path: '/servers', operationId: 'create-server', security: [ ['bearerAuth' => []], ], tags: ['Servers'], requestBody: new OA\RequestBody( required: true, description: 'Server created.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'example' => 'My Server', 'description' => 'The name of the server.'], 'description' => ['type' => 'string', 'example' => 'My Server Description', 'description' => 'The description of the server.'], 'ip' => ['type' => 'string', 'example' => '127.0.0.1', 'description' => 'The IP of the server.'], 'port' => ['type' => 'integer', 'example' => 22, 'description' => 'The port of the server.'], 'user' => ['type' => 'string', 'example' => 'root', 'description' => 'The user of the server.'], 'private_key_uuid' => ['type' => 'string', 'example' => 'og888os', 'description' => 'The UUID of the private key.'], 'is_build_server' => ['type' => 'boolean', 'example' => false, 'description' => 'Is build server.'], 'instant_validate' => ['type' => 'boolean', 'example' => false, 'description' => 'Instant validate.'], 'proxy_type' => ['type' => 'string', 'enum' => ['traefik', 'caddy', 'none'], 'example' => 'traefik', 'description' => 'The proxy type.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Server created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'og888os', 'description' => 'The UUID of the server.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_server(Request $request) { $allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate', 'proxy_type']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255', 'description' => 'string|nullable', 'ip' => ['string', 'required', new ValidServerIp], 'port' => 'integer|nullable|between:1,65535', 'private_key_uuid' => 'string|required', 'user' => ['string', 'nullable', 'regex:/^[a-zA-Z0-9_-]+$/'], 'is_build_server' => 'boolean|nullable', 'instant_validate' => 'boolean|nullable', 'proxy_type' => 'string|nullable', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if (! $request->name) { $request->offsetSet('name', generate_random_name()); } if (! $request->user) { $request->offsetSet('user', 'root'); } if (is_null($request->port)) { $request->offsetSet('port', 22); } if (is_null($request->is_build_server)) { $request->offsetSet('is_build_server', false); } if (is_null($request->instant_validate)) { $request->offsetSet('instant_validate', false); } if ($request->proxy_type) { $validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) { return str($proxyType->value)->lower(); }); if (! $validProxyTypes->contains(str($request->proxy_type)->lower())) { return response()->json(['message' => 'Invalid proxy type.'], 422); } } $privateKey = PrivateKey::whereTeamId($teamId)->whereUuid($request->private_key_uuid)->first(); if (! $privateKey) { return response()->json(['message' => 'Private key not found.'], 404); } $foundServer = ModelsServer::whereIp($request->ip)->first(); if ($foundServer) { if ($foundServer->team_id === $teamId) { return response()->json(['message' => 'A server with this IP/Domain already exists in your team.'], 400); } return response()->json(['message' => 'A server with this IP/Domain is already in use by another team.'], 400); } $proxyType = $request->proxy_type ? str($request->proxy_type)->upper() : ProxyTypes::TRAEFIK->value; $server = ModelsServer::create([ 'name' => $request->name, 'description' => $request->description, 'ip' => $request->ip, 'port' => $request->port, 'user' => $request->user, 'private_key_id' => $privateKey->id, 'team_id' => $teamId, ]); $server->proxy->set('type', $proxyType); $server->proxy->set('status', ProxyStatus::EXITED->value); $server->save(); $server->settings()->update([ 'is_build_server' => $request->is_build_server, ]); if ($request->instant_validate) { ValidateServer::dispatch($server); } return response()->json([ 'uuid' => $server->uuid, ])->setStatusCode(201); } #[OA\Patch( summary: 'Update', description: 'Update Server.', path: '/servers/{uuid}', operationId: 'update-server-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Servers'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server UUID', schema: new OA\Schema(type: 'string')), ], requestBody: new OA\RequestBody( required: true, description: 'Server updated.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The name of the server.'], 'description' => ['type' => 'string', 'description' => 'The description of the server.'], 'ip' => ['type' => 'string', 'description' => 'The IP of the server.'], 'port' => ['type' => 'integer', 'description' => 'The port of the server.'], 'user' => ['type' => 'string', 'description' => 'The user of the server.'], 'private_key_uuid' => ['type' => 'string', 'description' => 'The UUID of the private key.'], 'is_build_server' => ['type' => 'boolean', 'description' => 'Is build server.'], 'instant_validate' => ['type' => 'boolean', 'description' => 'Instant validate.'], 'proxy_type' => ['type' => 'string', 'enum' => ['traefik', 'caddy', 'none'], 'description' => 'The proxy type.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Server updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( ref: '#/components/schemas/Server' ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_server(Request $request) { $allowedFields = ['name', 'description', 'ip', 'port', 'user', 'private_key_uuid', 'is_build_server', 'instant_validate', 'proxy_type']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validator = customApiValidator($request->all(), [ 'name' => 'string|max:255|nullable', 'description' => 'string|nullable', 'ip' => ['string', 'nullable', new ValidServerIp], 'port' => 'integer|nullable|between:1,65535', 'private_key_uuid' => 'string|nullable', 'user' => ['string', 'nullable', 'regex:/^[a-zA-Z0-9_-]+$/'], 'is_build_server' => 'boolean|nullable', 'instant_validate' => 'boolean|nullable', 'proxy_type' => 'string|nullable', ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $server = ModelsServer::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $server) { return response()->json(['message' => 'Server not found.'], 404); } if ($request->proxy_type) { $validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) { return str($proxyType->value)->lower(); }); if ($validProxyTypes->contains(str($request->proxy_type)->lower())) { $server->changeProxy($request->proxy_type, async: true); } else { return response()->json(['message' => 'Invalid proxy type.'], 422); } } $server->update($request->only(['name', 'description', 'ip', 'port', 'user'])); if ($request->is_build_server) { $server->settings()->update([ 'is_build_server' => $request->is_build_server, ]); } if ($request->instant_validate) { ValidateServer::dispatch($server); } return response()->json([ 'uuid' => $server->uuid, ])->setStatusCode(201); } #[OA\Delete( summary: 'Delete', description: 'Delete server by UUID.', path: '/servers/{uuid}', operationId: 'delete-server-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Servers'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the server.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Server deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Server deleted.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function delete_server(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'Uuid is required.'], 422); } $server = ModelsServer::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $server) { return response()->json(['message' => 'Server not found.'], 404); } if ($server->definedResources()->count() > 0) { return response()->json(['message' => 'Server has resources, so you need to delete them before.'], 400); } if ($server->isLocalhost()) { return response()->json(['message' => 'Local server cannot be deleted.'], 400); } $server->delete(); DeleteServer::dispatch( $server->id, false, // Don't delete from Hetzner via API $server->hetzner_server_id, $server->cloud_provider_token_id, $server->team_id ); return response()->json(['message' => 'Server deleted.']); } #[OA\Get( summary: 'Validate', description: 'Validate server by UUID.', path: '/servers/{uuid}/validate', operationId: 'validate-server-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Servers'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 201, description: 'Server validation started.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Validation started.'], ] ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function validate_server(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'Uuid is required.'], 422); } $server = ModelsServer::whereTeamId($teamId)->whereUuid($request->uuid)->first(); if (! $server) { return response()->json(['message' => 'Server not found.'], 404); } ValidateServer::dispatch($server); return response()->json(['message' => 'Validation started.'], 201); } } ================================================ FILE: app/Http/Controllers/Api/ServicesController.php ================================================ makeHidden([ 'id', 'resourceable', 'resourceable_id', 'resourceable_type', ]); if (request()->attributes->get('can_read_sensitive', false) === false) { $service->makeHidden([ 'docker_compose_raw', 'docker_compose', 'value', 'real_value', ]); } return serializeApiResponse($service); } private function applyServiceUrls(Service $service, array $urlsArray, string $teamId, bool $forceDomainOverride = false): ?array { $errors = []; $conflicts = []; $urls = collect($urlsArray)->flatMap(function ($item) { $urlValue = data_get($item, 'url'); if (blank($urlValue)) { return []; } return str($urlValue)->replaceStart(',', '')->replaceEnd(',', '')->trim()->explode(',')->map(fn ($url) => trim($url))->filter(); }); $urls = $urls->map(function ($url) use (&$errors) { if (! filter_var($url, FILTER_VALIDATE_URL)) { $errors[] = "Invalid URL: {$url}"; return $url; } $scheme = parse_url($url, PHP_URL_SCHEME) ?? ''; if (! in_array(strtolower($scheme), ['http', 'https'])) { $errors[] = "Invalid URL scheme: {$scheme} for URL: {$url}. Only http and https are supported."; } return $url; }); $duplicates = $urls->duplicates()->unique()->values(); if ($duplicates->isNotEmpty() && ! $forceDomainOverride) { $errors[] = 'The current request contains conflicting URLs across containers: '.implode(', ', $duplicates->toArray()).'. Use force_domain_override=true to proceed.'; } if (count($errors) > 0) { return ['errors' => $errors]; } collect($urlsArray)->each(function ($item) use ($service, $teamId, $forceDomainOverride, &$errors, &$conflicts) { $name = data_get($item, 'name'); $containerUrls = data_get($item, 'url'); if (blank($name)) { $errors[] = 'Service container name is required to apply URLs.'; return; } $application = $service->applications()->where('name', $name)->first(); if (! $application) { $errors[] = "Service container with '{$name}' not found."; return; } if (filled($containerUrls)) { $containerUrls = str($containerUrls)->replaceStart(',', '')->replaceEnd(',', '')->trim(); $containerUrls = str($containerUrls)->explode(',')->map(fn ($url) => str(trim($url))->lower()); $result = checkIfDomainIsAlreadyUsedViaAPI($containerUrls, $teamId, $application->uuid); if (isset($result['error'])) { $errors[] = $result['error']; return; } if ($result['hasConflicts'] && ! $forceDomainOverride) { $conflicts = array_merge($conflicts, $result['conflicts']); return; } $containerUrls = $containerUrls->filter(fn ($u) => filled($u))->unique()->implode(','); } else { $containerUrls = null; } $application->fqdn = $containerUrls; $application->save(); }); if (! empty($errors)) { return ['errors' => $errors]; } if (! empty($conflicts)) { return [ 'conflicts' => $conflicts, 'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.', ]; } return null; } #[OA\Get( summary: 'List', description: 'List all services.', path: '/services', operationId: 'list-services', security: [ ['bearerAuth' => []], ], tags: ['Services'], responses: [ new OA\Response( response: 200, description: 'Get all services', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/Service') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function services(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $projects = Project::where('team_id', $teamId)->get(); $services = collect(); foreach ($projects as $project) { $services->push($project->services()->get()); } foreach ($services as $service) { $service = $this->removeSensitiveData($service); } return response()->json($services->flatten()); } #[OA\Post( summary: 'Create service', description: 'Create a one-click / custom service', path: '/services', operationId: 'create-service', security: [ ['bearerAuth' => []], ], tags: ['Services'], requestBody: new OA\RequestBody( required: true, content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['server_uuid', 'project_uuid', 'environment_name', 'environment_uuid'], properties: [ 'type' => ['description' => 'The one-click service type (e.g. "actualbudget", "calibre-web", "gitea-with-mysql" ...)', 'type' => 'string'], 'name' => ['type' => 'string', 'maxLength' => 255, 'description' => 'Name of the service.'], 'description' => ['type' => 'string', 'nullable' => true, 'description' => 'Description of the service.'], 'project_uuid' => ['type' => 'string', 'description' => 'Project UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'Environment name. You need to provide at least one of environment_name or environment_uuid.'], 'environment_uuid' => ['type' => 'string', 'description' => 'Environment UUID. You need to provide at least one of environment_name or environment_uuid.'], 'server_uuid' => ['type' => 'string', 'description' => 'Server UUID.'], 'destination_uuid' => ['type' => 'string', 'description' => 'Destination UUID. Required if server has multiple destinations.'], 'instant_deploy' => ['type' => 'boolean', 'default' => false, 'description' => 'Start the service immediately after creation.'], 'docker_compose_raw' => ['type' => 'string', 'description' => 'The base64 encoded Docker Compose content.'], 'urls' => [ 'type' => 'array', 'description' => 'Array of URLs to be applied to containers of a service.', 'items' => new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The service name as defined in docker-compose.'], 'url' => ['type' => 'string', 'description' => 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io").'], ], ), ], 'force_domain_override' => ['type' => 'boolean', 'default' => false, 'description' => 'Force domain override even if conflicts are detected.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Service created successfully.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'description' => 'Service UUID.'], 'domains' => ['type' => 'array', 'items' => ['type' => 'string'], 'description' => 'Service domains.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_service(Request $request) { $allowedFields = ['type', 'name', 'description', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'docker_compose_raw', 'urls', 'force_domain_override']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $this->authorize('create', Service::class); $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $validationRules = [ 'type' => 'string|required_without:docker_compose_raw', 'docker_compose_raw' => 'string|required_without:type', 'project_uuid' => 'string|required', 'environment_name' => 'string|nullable', 'environment_uuid' => 'string|nullable', 'server_uuid' => 'string|required', 'destination_uuid' => 'string|nullable', 'name' => 'string|max:255', 'description' => 'string|nullable', 'instant_deploy' => 'boolean', 'urls' => 'array|nullable', 'urls.*' => 'array:name,url', 'urls.*.name' => 'string|required', 'urls.*.url' => 'string|nullable', 'force_domain_override' => 'boolean', ]; $validationMessages = [ 'urls.*.array' => 'An item in the urls array has invalid fields. Only name and url fields are supported.', ]; $validator = Validator::make($request->all(), $validationRules, $validationMessages); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if (filled($request->type) && filled($request->docker_compose_raw)) { return response()->json([ 'message' => 'You cannot provide both service type and docker_compose_raw. Use one or the other.', ], 422); } $environmentUuid = $request->environment_uuid; $environmentName = $request->environment_name; if (blank($environmentUuid) && blank($environmentName)) { return response()->json(['message' => 'You need to provide at least one of environment_name or environment_uuid.'], 422); } $serverUuid = $request->server_uuid; $instantDeploy = $request->instant_deploy ?? false; if ($request->is_public && ! $request->public_port) { $request->offsetSet('is_public', false); } $project = Project::whereTeamId($teamId)->whereUuid($request->project_uuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $environment = $project->environments()->where('name', $environmentName)->first(); if (! $environment) { $environment = $project->environments()->where('uuid', $environmentUuid)->first(); } if (! $environment) { return response()->json(['message' => 'Environment not found.'], 404); } $server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first(); if (! $server) { return response()->json(['message' => 'Server not found.'], 404); } $destinations = $server->destinations(); if ($destinations->count() == 0) { return response()->json(['message' => 'Server has no destinations.'], 400); } if ($destinations->count() > 1 && ! $request->has('destination_uuid')) { return response()->json(['message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400); } $destination = $destinations->first(); if ($destinations->count() > 1 && $request->has('destination_uuid')) { $destination = $destinations->where('uuid', $request->destination_uuid)->first(); if (! $destination) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'destination_uuid' => 'Provided destination_uuid does not belong to the specified server.', ], ], 422); } } $services = get_service_templates(); $serviceKeys = $services->keys(); if ($serviceKeys->contains($request->type)) { $oneClickServiceName = $request->type; $oneClickService = data_get($services, "$oneClickServiceName.compose"); $oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null); if ($oneClickDotEnvs) { $oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) { return ! empty($value); }); } if ($oneClickService) { $dockerComposeRaw = base64_decode($oneClickService); // Validate for command injection BEFORE creating service try { validateDockerComposeForInjection($dockerComposeRaw); } catch (\Exception $e) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => $e->getMessage(), ], ], 422); } $servicePayload = [ 'name' => "$oneClickServiceName-".str()->random(10), 'docker_compose_raw' => $dockerComposeRaw, 'environment_id' => $environment->id, 'service_type' => $oneClickServiceName, 'server_id' => $server->id, 'destination_id' => $destination->id, 'destination_type' => $destination->getMorphClass(), ]; if (in_array($oneClickServiceName, NEEDS_TO_CONNECT_TO_PREDEFINED_NETWORK)) { data_set($servicePayload, 'connect_to_docker_network', true); } $service = Service::create($servicePayload); $service->name = $request->name ?? "$oneClickServiceName-".$service->uuid; $service->description = $request->description; $service->save(); if ($oneClickDotEnvs?->count() > 0) { $oneClickDotEnvs->each(function ($value) use ($service) { $key = str()->before($value, '='); $value = str(str()->after($value, '=')); $generatedValue = $value; if ($value->contains('SERVICE_')) { $command = $value->after('SERVICE_')->beforeLast('_'); $generatedValue = generateEnvValue($command->value(), $service); } EnvironmentVariable::create([ 'key' => $key, 'value' => $generatedValue, 'resourceable_id' => $service->id, 'resourceable_type' => $service->getMorphClass(), 'is_preview' => false, ]); }); } $service->parse(isNew: true); // Apply service-specific application prerequisites applyServiceApplicationPrerequisites($service); if ($request->has('urls') && is_array($request->urls)) { $urlResult = $this->applyServiceUrls($service, $request->urls, $teamId, $request->boolean('force_domain_override')); if ($urlResult !== null) { $service->delete(); if (isset($urlResult['errors'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $urlResult['errors'], ], 422); } if (isset($urlResult['conflicts'])) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $urlResult['conflicts'], 'warning' => $urlResult['warning'], ], 409); } } } if ($instantDeploy) { StartService::dispatch($service); } return response()->json([ 'uuid' => $service->uuid, 'domains' => $service->applications()->pluck('fqdn')->filter()->sort()->values(), ])->setStatusCode(201); } return response()->json(['message' => 'Service not found.', 'valid_service_types' => $serviceKeys], 404); } elseif (filled($request->docker_compose_raw)) { $allowedFields = ['name', 'description', 'project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'instant_deploy', 'docker_compose_raw', 'connect_to_docker_network', 'urls', 'force_domain_override']; $validationRules = [ 'project_uuid' => 'string|required', 'environment_name' => 'string|nullable', 'environment_uuid' => 'string|nullable', 'server_uuid' => 'string|required', 'destination_uuid' => 'string', 'name' => 'string|max:255', 'description' => 'string|nullable', 'instant_deploy' => 'boolean', 'connect_to_docker_network' => 'boolean', 'docker_compose_raw' => 'string|required', 'urls' => 'array|nullable', 'urls.*' => 'array:name,url', 'urls.*.name' => 'string|required', 'urls.*.url' => 'string|nullable', 'force_domain_override' => 'boolean', ]; $validationMessages = [ 'urls.*.array' => 'An item in the urls array has invalid fields. Only name and url fields are supported.', ]; $validator = Validator::make($request->all(), $validationRules, $validationMessages); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } $environmentUuid = $request->environment_uuid; $environmentName = $request->environment_name; if (blank($environmentUuid) && blank($environmentName)) { return response()->json(['message' => 'You need to provide at least one of environment_name or environment_uuid.'], 422); } $serverUuid = $request->server_uuid; $projectUuid = $request->project_uuid; $project = Project::whereTeamId($teamId)->whereUuid($projectUuid)->first(); if (! $project) { return response()->json(['message' => 'Project not found.'], 404); } $environment = $project->environments()->where('name', $environmentName)->first(); if (! $environment) { $environment = $project->environments()->where('uuid', $environmentUuid)->first(); } if (! $environment) { return response()->json(['message' => 'Environment not found.'], 404); } $server = Server::whereTeamId($teamId)->whereUuid($serverUuid)->first(); if (! $server) { return response()->json(['message' => 'Server not found.'], 404); } $destinations = $server->destinations(); if ($destinations->count() == 0) { return response()->json(['message' => 'Server has no destinations.'], 400); } if ($destinations->count() > 1 && ! $request->has('destination_uuid')) { return response()->json(['message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400); } $destination = $destinations->first(); if ($destinations->count() > 1 && $request->has('destination_uuid')) { $destination = $destinations->where('uuid', $request->destination_uuid)->first(); if (! $destination) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'destination_uuid' => 'Provided destination_uuid does not belong to the specified server.', ], ], 422); } } if (! isBase64Encoded($request->docker_compose_raw)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', ], ], 422); } $dockerComposeRaw = base64_decode($request->docker_compose_raw); if (mb_detect_encoding($dockerComposeRaw, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', ], ], 422); } $dockerCompose = base64_decode($request->docker_compose_raw); $dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); // Validate for command injection BEFORE saving to database try { validateDockerComposeForInjection($dockerComposeRaw); } catch (\Exception $e) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => $e->getMessage(), ], ], 422); } $connectToDockerNetwork = $request->connect_to_docker_network ?? false; $instantDeploy = $request->instant_deploy ?? false; $service = new Service; $service->name = $request->name ?? 'service-'.str()->random(10); $service->description = $request->description; $service->docker_compose_raw = $dockerComposeRaw; $service->environment_id = $environment->id; $service->server_id = $server->id; $service->destination_id = $destination->id; $service->destination_type = $destination->getMorphClass(); $service->connect_to_docker_network = $connectToDockerNetwork; $service->save(); $service->parse(isNew: true); if ($request->has('urls') && is_array($request->urls)) { $urlResult = $this->applyServiceUrls($service, $request->urls, $teamId, $request->boolean('force_domain_override')); if ($urlResult !== null) { $service->delete(); if (isset($urlResult['errors'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $urlResult['errors'], ], 422); } if (isset($urlResult['conflicts'])) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $urlResult['conflicts'], 'warning' => $urlResult['warning'], ], 409); } } } if ($instantDeploy) { StartService::dispatch($service); } return response()->json([ 'uuid' => $service->uuid, 'domains' => $service->applications()->pluck('fqdn')->filter()->sort()->values(), ])->setStatusCode(201); } elseif (filled($request->type)) { return response()->json([ 'message' => 'Invalid service type.', 'valid_service_types' => $serviceKeys, ], 404); } } #[OA\Get( summary: 'Get', description: 'Get service by UUID.', path: '/services/{uuid}', operationId: 'get-service-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Service UUID', schema: new OA\Schema(type: 'string')), ], responses: [ new OA\Response( response: 200, description: 'Get a service by UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( ref: '#/components/schemas/Service' ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function service_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('view', $service); $service = $service->load(['applications', 'databases']); return response()->json($this->removeSensitiveData($service)); } #[OA\Delete( summary: 'Delete', description: 'Delete service by UUID.', path: '/services/{uuid}', operationId: 'delete-service-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Service UUID', schema: new OA\Schema(type: 'string')), new OA\Parameter(name: 'delete_configurations', in: 'query', required: false, description: 'Delete configurations.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'delete_volumes', in: 'query', required: false, description: 'Delete volumes.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'docker_cleanup', in: 'query', required: false, description: 'Run docker cleanup.', schema: new OA\Schema(type: 'boolean', default: true)), new OA\Parameter(name: 'delete_connected_networks', in: 'query', required: false, description: 'Delete connected networks.', schema: new OA\Schema(type: 'boolean', default: true)), ], responses: [ new OA\Response( response: 200, description: 'Delete a service by UUID', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Service deletion request queued.'], ], ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function delete_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } if (! $request->uuid) { return response()->json(['message' => 'UUID is required.'], 404); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('delete', $service); DeleteResourceJob::dispatch( resource: $service, deleteVolumes: $request->boolean('delete_volumes', true), deleteConnectedNetworks: $request->boolean('delete_connected_networks', true), deleteConfigurations: $request->boolean('delete_configurations', true), dockerCleanup: $request->boolean('docker_cleanup', true) ); return response()->json([ 'message' => 'Service deletion request queued.', ]); } #[OA\Patch( summary: 'Update', description: 'Update service by UUID.', path: '/services/{uuid}', operationId: 'update-service-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Service updated.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The service name.'], 'description' => ['type' => 'string', 'description' => 'The service description.'], 'project_uuid' => ['type' => 'string', 'description' => 'The project UUID.'], 'environment_name' => ['type' => 'string', 'description' => 'The environment name.'], 'environment_uuid' => ['type' => 'string', 'description' => 'The environment UUID.'], 'server_uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'destination_uuid' => ['type' => 'string', 'description' => 'The destination UUID.'], 'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the service should be deployed instantly.'], 'connect_to_docker_network' => ['type' => 'boolean', 'default' => false, 'description' => 'Connect the service to the predefined docker network.'], 'docker_compose_raw' => ['type' => 'string', 'description' => 'The base64 encoded Docker Compose content.'], 'urls' => [ 'type' => 'array', 'description' => 'Array of URLs to be applied to containers of a service.', 'items' => new OA\Schema( type: 'object', properties: [ 'name' => ['type' => 'string', 'description' => 'The service name as defined in docker-compose.'], 'url' => ['type' => 'string', 'description' => 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io").'], ], ), ], 'force_domain_override' => ['type' => 'boolean', 'default' => false, 'description' => 'Force domain override even if conflicts are detected.'], ], ) ), ] ), responses: [ new OA\Response( response: 200, description: 'Service updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'description' => 'Service UUID.'], 'domains' => ['type' => 'array', 'items' => ['type' => 'string'], 'description' => 'Service domains.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 409, description: 'Domain conflicts detected.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'], 'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'], 'conflicts' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'domain' => ['type' => 'string', 'example' => 'example.com'], 'resource_name' => ['type' => 'string', 'example' => 'My Application'], 'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'], 'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'], 'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''], ] ), ], ] ) ), ] ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $return = validateIncomingRequest($request); if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('update', $service); $allowedFields = ['name', 'description', 'instant_deploy', 'docker_compose_raw', 'connect_to_docker_network', 'urls', 'force_domain_override']; $validationRules = [ 'name' => 'string|max:255', 'description' => 'string|nullable', 'instant_deploy' => 'boolean', 'connect_to_docker_network' => 'boolean', 'docker_compose_raw' => 'string|nullable', 'urls' => 'array|nullable', 'urls.*' => 'array:name,url', 'urls.*.name' => 'string|required', 'urls.*.url' => 'string|nullable', 'force_domain_override' => 'boolean', ]; $validationMessages = [ 'urls.*.array' => 'An item in the urls array has invalid fields. Only name and url fields are supported.', ]; $validator = Validator::make($request->all(), $validationRules, $validationMessages); $extraFields = array_diff(array_keys($request->all()), $allowedFields); if ($validator->fails() || ! empty($extraFields)) { $errors = $validator->errors(); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); } } return response()->json([ 'message' => 'Validation failed.', 'errors' => $errors, ], 422); } if ($request->has('docker_compose_raw')) { if (! isBase64Encoded($request->docker_compose_raw)) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', ], ], 422); } $dockerComposeRaw = base64_decode($request->docker_compose_raw); if (mb_detect_encoding($dockerComposeRaw, 'UTF-8', true) === false) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => 'The docker_compose_raw should be base64 encoded.', ], ], 422); } $dockerCompose = base64_decode($request->docker_compose_raw); $dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); // Validate for command injection BEFORE saving to database try { validateDockerComposeForInjection($dockerComposeRaw); } catch (\Exception $e) { return response()->json([ 'message' => 'Validation failed.', 'errors' => [ 'docker_compose_raw' => $e->getMessage(), ], ], 422); } $service->docker_compose_raw = $dockerComposeRaw; } if ($request->has('name')) { $service->name = $request->name; } if ($request->has('description')) { $service->description = $request->description; } if ($request->has('connect_to_docker_network')) { $service->connect_to_docker_network = $request->connect_to_docker_network; } $service->save(); $service->parse(); if ($request->has('urls') && is_array($request->urls)) { $urlResult = $this->applyServiceUrls($service, $request->urls, $teamId, $request->boolean('force_domain_override')); if ($urlResult !== null) { if (isset($urlResult['errors'])) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $urlResult['errors'], ], 422); } if (isset($urlResult['conflicts'])) { return response()->json([ 'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.', 'conflicts' => $urlResult['conflicts'], 'warning' => $urlResult['warning'], ], 409); } } } if ($request->instant_deploy) { StartService::dispatch($service); } return response()->json([ 'uuid' => $service->uuid, 'domains' => $service->applications()->pluck('fqdn')->filter()->sort()->values(), ])->setStatusCode(200); } #[OA\Get( summary: 'List Envs', description: 'List all envs by service UUID.', path: '/services/{uuid}/envs', operationId: 'list-envs-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'All environment variables by service UUID.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/EnvironmentVariable') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function envs(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('manageEnvironment', $service); $envs = $service->environment_variables->map(function ($env) { $env->makeHidden([ 'application_id', 'standalone_clickhouse_id', 'standalone_dragonfly_id', 'standalone_keydb_id', 'standalone_mariadb_id', 'standalone_mongodb_id', 'standalone_mysql_id', 'standalone_postgresql_id', 'standalone_redis_id', ]); return $this->removeSensitiveData($env); }); return response()->json($envs); } #[OA\Patch( summary: 'Update Env', description: 'Update env by service UUID.', path: '/services/{uuid}/envs', operationId: 'update-env-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Env updated.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['key', 'value'], properties: [ 'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'], 'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'], 'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'], 'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'], 'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'], 'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'], ], ), ), ], ), responses: [ new OA\Response( response: 201, description: 'Environment variable updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( ref: '#/components/schemas/EnvironmentVariable' ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function update_env_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('manageEnvironment', $service); $validator = customApiValidator($request->all(), [ 'key' => 'string|required', 'value' => 'string|nullable', 'is_literal' => 'boolean', 'is_multiline' => 'boolean', 'is_shown_once' => 'boolean', 'comment' => 'string|nullable|max:256', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $key = str($request->key)->trim()->replace(' ', '_')->value; $env = $service->environment_variables()->where('key', $key)->first(); if (! $env) { return response()->json(['message' => 'Environment variable not found.'], 404); } $env->value = $request->value; if ($request->has('is_literal')) { $env->is_literal = $request->is_literal; } if ($request->has('is_multiline')) { $env->is_multiline = $request->is_multiline; } if ($request->has('is_shown_once')) { $env->is_shown_once = $request->is_shown_once; } if ($request->has('comment')) { $env->comment = $request->comment; } $env->save(); return response()->json($this->removeSensitiveData($env))->setStatusCode(201); } #[OA\Patch( summary: 'Update Envs (Bulk)', description: 'Update multiple envs by service UUID.', path: '/services/{uuid}/envs/bulk', operationId: 'update-envs-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( description: 'Bulk envs updated.', required: true, content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', required: ['data'], properties: [ 'data' => [ 'type' => 'array', 'items' => new OA\Schema( type: 'object', properties: [ 'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'], 'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'], 'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'], 'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'], 'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'], 'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'], ], ), ], ], ), ), ], ), responses: [ new OA\Response( response: 201, description: 'Environment variables updated.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/EnvironmentVariable') ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_bulk_envs(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('manageEnvironment', $service); $bulk_data = $request->get('data'); if (! $bulk_data) { return response()->json(['message' => 'Bulk data is required.'], 400); } $updatedEnvs = collect(); foreach ($bulk_data as $item) { $validator = customApiValidator($item, [ 'key' => 'string|required', 'value' => 'string|nullable', 'is_literal' => 'boolean', 'is_multiline' => 'boolean', 'is_shown_once' => 'boolean', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $key = str($item['key'])->trim()->replace(' ', '_')->value; $env = $service->environment_variables()->updateOrCreate( ['key' => $key], $item ); $updatedEnvs->push($this->removeSensitiveData($env)); } return response()->json($updatedEnvs)->setStatusCode(201); } #[OA\Post( summary: 'Create Env', description: 'Create env by service UUID.', path: '/services/{uuid}/envs', operationId: 'create-env-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], requestBody: new OA\RequestBody( required: true, description: 'Env created.', content: new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'], 'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'], 'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'], 'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'], 'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'], 'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'], ], ), ), ), responses: [ new OA\Response( response: 201, description: 'Environment variable created.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'uuid' => ['type' => 'string', 'example' => 'nc0k04gk8g0cgsk440g0koko'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), new OA\Response( response: 422, ref: '#/components/responses/422', ), ] )] public function create_env(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('manageEnvironment', $service); $validator = customApiValidator($request->all(), [ 'key' => 'string|required', 'value' => 'string|nullable', 'is_literal' => 'boolean', 'is_multiline' => 'boolean', 'is_shown_once' => 'boolean', 'comment' => 'string|nullable|max:256', ]); if ($validator->fails()) { return response()->json([ 'message' => 'Validation failed.', 'errors' => $validator->errors(), ], 422); } $key = str($request->key)->trim()->replace(' ', '_')->value; $existingEnv = $service->environment_variables()->where('key', $key)->first(); if ($existingEnv) { return response()->json([ 'message' => 'Environment variable already exists. Use PATCH request to update it.', ], 409); } $env = $service->environment_variables()->create([ 'key' => $key, 'value' => $request->value, 'is_literal' => $request->is_literal ?? false, 'is_multiline' => $request->is_multiline ?? false, 'is_shown_once' => $request->is_shown_once ?? false, 'comment' => $request->comment ?? null, ]); return response()->json($this->removeSensitiveData($env))->setStatusCode(201); } #[OA\Delete( summary: 'Delete Env', description: 'Delete env by UUID.', path: '/services/{uuid}/envs/{env_uuid}', operationId: 'delete-env-by-service-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'env_uuid', in: 'path', description: 'UUID of the environment variable.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Environment variable deleted.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Environment variable deleted.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function delete_env_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('manageEnvironment', $service); $env = EnvironmentVariable::where('uuid', $request->env_uuid) ->where('resourceable_type', Service::class) ->where('resourceable_id', $service->id) ->first(); if (! $env) { return response()->json(['message' => 'Environment variable not found.'], 404); } $env->forceDelete(); return response()->json(['message' => 'Environment variable deleted.']); } #[OA\Get( summary: 'Start', description: 'Start service. `Post` request is also accepted.', path: '/services/{uuid}/start', operationId: 'start-service-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), ], responses: [ new OA\Response( response: 200, description: 'Start service.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Service starting request queued.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_deploy(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('deploy', $service); if (str($service->status)->contains('running')) { return response()->json(['message' => 'Service is already running.'], 400); } StartService::dispatch($service); return response()->json( [ 'message' => 'Service starting request queued.', ], 200 ); } #[OA\Get( summary: 'Stop', description: 'Stop service. `Post` request is also accepted.', path: '/services/{uuid}/stop', operationId: 'stop-service-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'docker_cleanup', in: 'query', description: 'Perform docker cleanup (prune networks, volumes, etc.).', schema: new OA\Schema( type: 'boolean', default: true, ) ), ], responses: [ new OA\Response( response: 200, description: 'Stop service.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Service stopping request queued.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_stop(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('stop', $service); if (str($service->status)->contains('stopped') || str($service->status)->contains('exited')) { return response()->json(['message' => 'Service is already stopped.'], 400); } $dockerCleanup = $request->boolean('docker_cleanup', true); StopService::dispatch($service, false, $dockerCleanup); return response()->json( [ 'message' => 'Service stopping request queued.', ], 200 ); } #[OA\Get( summary: 'Restart', description: 'Restart service. `Post` request is also accepted.', path: '/services/{uuid}/restart', operationId: 'restart-service-by-uuid', security: [ ['bearerAuth' => []], ], tags: ['Services'], parameters: [ new OA\Parameter( name: 'uuid', in: 'path', description: 'UUID of the service.', required: true, schema: new OA\Schema( type: 'string', ) ), new OA\Parameter( name: 'latest', in: 'query', description: 'Pull latest images.', schema: new OA\Schema( type: 'boolean', default: false, ) ), ], responses: [ new OA\Response( response: 200, description: 'Restart service.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'object', properties: [ 'message' => ['type' => 'string', 'example' => 'Service restaring request queued.'], ] ) ), ] ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function action_restart(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $uuid = $request->route('uuid'); if (! $uuid) { return response()->json(['message' => 'UUID is required.'], 400); } $service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first(); if (! $service) { return response()->json(['message' => 'Service not found.'], 404); } $this->authorize('deploy', $service); $pullLatest = $request->boolean('latest'); RestartService::dispatch($service, $pullLatest); return response()->json( [ 'message' => 'Service restarting request queued.', ], 200 ); } } ================================================ FILE: app/Http/Controllers/Api/TeamController.php ================================================ makeHidden([ 'custom_server_limit', 'pivot', ]); if (request()->attributes->get('can_read_sensitive', false) === false) { $team->makeHidden([ 'smtp_username', 'smtp_password', 'resend_api_key', 'telegram_token', ]); } return serializeApiResponse($team); } #[OA\Get( summary: 'List', description: 'Get all teams.', path: '/teams', operationId: 'list-teams', security: [ ['bearerAuth' => []], ], tags: ['Teams'], responses: [ new OA\Response( response: 200, description: 'List of teams.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/Team') ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function teams(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $teams = auth()->user()->teams->sortBy('id'); $teams = $teams->map(function ($team) { return $this->removeSensitiveData($team); }); return response()->json( $teams, ); } #[OA\Get( summary: 'Get', description: 'Get team by TeamId.', path: '/teams/{id}', operationId: 'get-team-by-id', security: [ ['bearerAuth' => []], ], tags: ['Teams'], parameters: [ new OA\Parameter(name: 'id', in: 'path', required: true, description: 'Team ID', schema: new OA\Schema(type: 'integer')), ], responses: [ new OA\Response( response: 200, description: 'List of teams.', content: new OA\JsonContent(ref: '#/components/schemas/Team') ), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function team_by_id(Request $request) { $id = $request->id; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $teams = auth()->user()->teams; $team = $teams->where('id', $id)->first(); if (is_null($team)) { return response()->json(['message' => 'Team not found.'], 404); } $team = $this->removeSensitiveData($team); return response()->json( serializeApiResponse($team), ); } #[OA\Get( summary: 'Members', description: 'Get members by TeamId.', path: '/teams/{id}/members', operationId: 'get-members-by-team-id', security: [ ['bearerAuth' => []], ], tags: ['Teams'], parameters: [ new OA\Parameter(name: 'id', in: 'path', required: true, description: 'Team ID', schema: new OA\Schema(type: 'integer')), ], responses: [ new OA\Response( response: 200, description: 'List of members.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/User') ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), new OA\Response( response: 404, ref: '#/components/responses/404', ), ] )] public function members_by_id(Request $request) { $id = $request->id; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $teams = auth()->user()->teams; $team = $teams->where('id', $id)->first(); if (is_null($team)) { return response()->json(['message' => 'Team not found.'], 404); } $members = $team->members; $members->makeHidden([ 'pivot', 'email_change_code', 'email_change_code_expires_at', ]); return response()->json( serializeApiResponse($members), ); } #[OA\Get( summary: 'Authenticated Team', description: 'Get currently authenticated team.', path: '/teams/current', operationId: 'get-current-team', security: [ ['bearerAuth' => []], ], tags: ['Teams'], responses: [ new OA\Response( response: 200, description: 'Current Team.', content: new OA\JsonContent(ref: '#/components/schemas/Team')), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function current_team(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $team = auth()->user()->teams->where('id', $teamId)->first(); if (is_null($team)) { return response()->json(['message' => 'Team not found.'], 404); } return response()->json( $this->removeSensitiveData($team), ); } #[OA\Get( summary: 'Authenticated Team Members', description: 'Get currently authenticated team members.', path: '/teams/current/members', operationId: 'get-current-team-members', security: [ ['bearerAuth' => []], ], tags: ['Teams'], responses: [ new OA\Response( response: 200, description: 'Currently authenticated team members.', content: [ new OA\MediaType( mediaType: 'application/json', schema: new OA\Schema( type: 'array', items: new OA\Items(ref: '#/components/schemas/User') ) ), ]), new OA\Response( response: 401, ref: '#/components/responses/401', ), new OA\Response( response: 400, ref: '#/components/responses/400', ), ] )] public function current_team_members(Request $request) { $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); } $team = auth()->user()->teams->where('id', $teamId)->first(); if (is_null($team)) { return response()->json(['message' => 'Team not found.'], 404); } $team->members->makeHidden([ 'pivot', 'email_change_code', 'email_change_code_expires_at', ]); return response()->json( serializeApiResponse($team->members), ); } } ================================================ FILE: app/Http/Controllers/Controller.php ================================================ user()?->currentTeam()->id !== 0) { return redirect(RouteServiceProvider::HOME); } TestEvent::dispatch(); return 'Look at your other tab.'; } public function verify() { return view('auth.verify-email'); } public function email_verify(EmailVerificationRequest $request) { $request->fulfill(); return redirect(RouteServiceProvider::HOME); } public function forgot_password(Request $request) { if (is_transactional_emails_enabled()) { $arrayOfRequest = $request->only(Fortify::email()); $request->merge([ 'email' => Str::lower($arrayOfRequest['email']), ]); $type = set_transanctional_email_settings(); if (blank($type)) { return response()->json(['message' => 'Transactional emails are not active'], 400); } $request->validate([Fortify::email() => 'required|email']); $status = Password::broker(config('fortify.passwords'))->sendResetLink( $request->only(Fortify::email()) ); if ($status == Password::RESET_LINK_SENT) { return app(SuccessfulPasswordResetLinkRequestResponse::class, ['status' => $status]); } if ($status == Password::RESET_THROTTLED) { return response('Already requested a password reset in the past minutes.', 400); } return app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]); } return response()->json(['message' => 'Transactional emails are not active'], 400); } public function link() { $token = request()->get('token'); if ($token) { $decrypted = Crypt::decryptString($token); $email = str($decrypted)->before('@@@'); $password = str($decrypted)->after('@@@'); $user = User::whereEmail($email)->first(); if (! $user) { return redirect()->route('login'); } if (Hash::check($password, $user->password)) { $invitation = TeamInvitation::whereEmail($email); if ($invitation->exists()) { $team = $invitation->first()->team; $user->teams()->attach($team->id, ['role' => $invitation->first()->role]); $invitation->delete(); } else { $team = $user->teams()->first(); } if (is_null(data_get($user, 'email_verified_at'))) { $user->email_verified_at = now(); $user->save(); } Auth::login($user); session(['currentTeam' => $team]); return redirect()->route('dashboard'); } } return redirect()->route('login')->with('error', 'Invalid credentials.'); } public function acceptInvitation() { $resetPassword = request()->query('reset-password'); $invitationUuid = request()->route('uuid'); $invitation = TeamInvitation::whereUuid($invitationUuid)->firstOrFail(); $user = User::whereEmail($invitation->email)->firstOrFail(); if (Auth::id() !== $user->id) { abort(400, 'You are not allowed to accept this invitation.'); } $invitationValid = $invitation->isValid(); if ($invitationValid) { if ($resetPassword) { $user->update([ 'password' => Hash::make($invitationUuid), 'force_password_reset' => true, ]); } if ($user->teams()->where('team_id', $invitation->team->id)->exists()) { $invitation->delete(); return redirect()->route('team.index'); } $user->teams()->attach($invitation->team->id, ['role' => $invitation->role]); $invitation->delete(); refreshSession($invitation->team); return redirect()->route('team.index'); } else { abort(400, 'Invitation expired.'); } } public function revokeInvitation() { $invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail(); $user = User::whereEmail($invitation->email)->firstOrFail(); if (is_null(Auth::user())) { return redirect()->route('login'); } if (Auth::id() !== $user->id) { abort(401); } $invitation->delete(); return redirect()->route('team.index'); } } ================================================ FILE: app/Http/Controllers/OauthController.php ================================================ redirect(); } public function callback(string $provider) { try { $oauthUser = get_socialite_provider($provider)->user(); $user = User::whereEmail($oauthUser->email)->first(); if (! $user) { $settings = instanceSettings(); if (! $settings->is_registration_enabled) { abort(403, 'Registration is disabled'); } $user = User::create([ 'name' => $oauthUser->name, 'email' => $oauthUser->email, ]); } Auth::login($user); return redirect('/'); } catch (\Exception $e) { $errorCode = $e instanceof HttpException ? 'auth.failed' : 'auth.failed.callback'; return redirect()->route('login')->withErrors([__($errorCode)]); } } } ================================================ FILE: app/Http/Controllers/UploadController.php ================================================ route('databaseUuid'); $resource = getResourceByUuid($databaseIdentifier, data_get(auth()->user()->currentTeam(), 'id')); if (is_null($resource)) { return response()->json(['error' => 'You do not have permission for this database'], 500); } $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request)); if ($receiver->isUploaded() === false) { throw new UploadMissingFileException; } $save = $receiver->receive(); if ($save->isFinished()) { // Use the original identifier from the route to maintain path consistency // For ServiceDatabase: {name}-{service_uuid} // For standalone databases: {uuid} return $this->saveFile($save->getFile(), $databaseIdentifier); } $handler = $save->handler(); return response()->json([ 'done' => $handler->getPercentageDone(), 'status' => true, ]); } // protected function saveFileToS3($file) // { // $fileName = $this->createFilename($file); // $disk = Storage::disk('s3'); // // It's better to use streaming Streaming (laravel 5.4+) // $disk->putFileAs('photos', $file, $fileName); // // for older laravel // // $disk->put($fileName, file_get_contents($file), 'public'); // $mime = str_replace('/', '-', $file->getMimeType()); // // We need to delete the file when uploaded to s3 // unlink($file->getPathname()); // return response()->json([ // 'path' => $disk->url($fileName), // 'name' => $fileName, // 'mime_type' => $mime // ]); // } protected function saveFile(UploadedFile $file, string $resourceIdentifier) { $mime = str_replace('/', '-', $file->getMimeType()); $filePath = "upload/{$resourceIdentifier}"; $finalPath = storage_path('app/'.$filePath); $file->move($finalPath, 'restore'); return response()->json([ 'mime_type' => $mime, ]); } protected function createFilename(UploadedFile $file) { $extension = $file->getClientOriginalExtension(); $filename = str_replace('.'.$extension, '', $file->getClientOriginalName()); // Filename without extension $filename .= '_'.md5(time()).'.'.$extension; return $filename; } } ================================================ FILE: app/Http/Controllers/Webhook/Bitbucket.php ================================================ collect(); $headers = $request->headers->all(); $x_bitbucket_token = data_get($headers, 'x-hub-signature.0', ''); $x_bitbucket_event = data_get($headers, 'x-event-key.0', ''); $handled_events = collect(['repo:push', 'pullrequest:updated', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']); if (! $handled_events->contains($x_bitbucket_event)) { return response([ 'status' => 'failed', 'message' => 'Nothing to do. Event not handled.', ]); } if ($x_bitbucket_event === 'repo:push') { $branch = data_get($payload, 'push.changes.0.new.name'); $full_name = data_get($payload, 'repository.full_name'); $commit = data_get($payload, 'push.changes.0.new.target.hash'); if (! $branch) { return response([ 'status' => 'failed', 'message' => 'Nothing to do. No branch found in the request.', ]); } } if ($x_bitbucket_event === 'pullrequest:updated' || $x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') { $branch = data_get($payload, 'pullrequest.destination.branch.name'); $base_branch = data_get($payload, 'pullrequest.source.branch.name'); $full_name = data_get($payload, 'repository.full_name'); $pull_request_id = data_get($payload, 'pullrequest.id'); $pull_request_html_url = data_get($payload, 'pullrequest.links.html.href'); $commit = data_get($payload, 'pullrequest.source.commit.hash'); } $applications = Application::where('git_repository', 'like', "%$full_name%"); $applications = $applications->where('git_branch', $branch)->get(); if ($applications->isEmpty()) { return response([ 'status' => 'failed', 'message' => "Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name.", ]); } foreach ($applications as $application) { $webhook_secret = data_get($application, 'manual_webhook_secret_bitbucket'); $payload = $request->getContent(); [$algo, $hash] = explode('=', $x_bitbucket_token, 2); $payloadHash = hash_hmac($algo, $payload, $webhook_secret); if (! hash_equals($hash, $payloadHash) && ! isDev()) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Invalid signature.', ]); continue; } $isFunctional = $application->destination->server->isFunctional(); if (! $isFunctional) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Server is not functional.', ]); continue; } if ($x_bitbucket_event === 'repo:push') { if ($application->isDeployable()) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, commit: $commit, force_rebuild: false, is_webhook: true ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } elseif ($result['status'] === 'skipped') { $return_payloads->push([ 'application' => $application->name, 'status' => 'skipped', 'message' => $result['message'], ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Deployment queued.', ]); } } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Auto deployment disabled.', ]); } } if ($x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:updated') { if ($application->isPRDeployable()) { $deployment_uuid = new Cuid2; $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if (! $found) { if ($application->build_pack === 'dockercompose') { $pr_app = ApplicationPreview::create([ 'git_type' => 'bitbucket', 'application_id' => $application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, 'docker_compose_domains' => $application->docker_compose_domains, ]); $pr_app->generate_preview_fqdn_compose(); } else { $pr_app = ApplicationPreview::create([ 'git_type' => 'bitbucket', 'application_id' => $application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, ]); $pr_app->generate_preview_fqdn(); } } $result = queue_application_deployment( application: $application, pull_request_id: $pull_request_id, deployment_uuid: $deployment_uuid, force_rebuild: false, commit: $commit, is_webhook: true, git_type: 'bitbucket' ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } elseif ($result['status'] === 'skipped') { $return_payloads->push([ 'application' => $application->name, 'status' => 'skipped', 'message' => $result['message'], ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Preview deployment queued.', ]); } } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Preview deployments disabled.', ]); } } if ($x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') { $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if ($found) { // Use comprehensive cleanup that cancels active deployments, // kills helper containers, and removes all PR containers CleanupPreviewDeployment::run($application, $pull_request_id, $found); $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Preview deployment closed.', ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'No preview deployment found.', ]); } } } return response($return_payloads); } catch (Exception $e) { return handleError($e); } } } ================================================ FILE: app/Http/Controllers/Webhook/Gitea.php ================================================ header('X-Gitea-Delivery'); $x_gitea_event = Str::lower($request->header('X-Gitea-Event')); $x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256='); $content_type = $request->header('Content-Type'); $payload = $request->collect(); if ($x_gitea_event === 'ping') { // Just pong return response('pong'); } if ($content_type !== 'application/json') { $payload = json_decode(data_get($payload, 'payload'), true); } if ($x_gitea_event === 'push') { $branch = data_get($payload, 'ref'); $full_name = data_get($payload, 'repository.full_name'); if (Str::isMatch('/refs\/heads\/*/', $branch)) { $branch = Str::after($branch, 'refs/heads/'); } $added_files = data_get($payload, 'commits.*.added'); $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); } if ($x_gitea_event === 'pull_request') { $action = data_get($payload, 'action'); $full_name = data_get($payload, 'repository.full_name'); $pull_request_id = data_get($payload, 'number'); $pull_request_html_url = data_get($payload, 'pull_request.html_url'); $branch = data_get($payload, 'pull_request.head.ref'); $base_branch = data_get($payload, 'pull_request.base.ref'); } if (! $branch) { return response('Nothing to do. No branch found in the request.'); } $applications = Application::where('git_repository', 'like', "%$full_name%"); if ($x_gitea_event === 'push') { $applications = $applications->where('git_branch', $branch)->get(); if ($applications->isEmpty()) { return response("Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name."); } } if ($x_gitea_event === 'pull_request') { $applications = $applications->where('git_branch', $base_branch)->get(); if ($applications->isEmpty()) { return response("Nothing to do. No applications found with branch '$base_branch'."); } } foreach ($applications as $application) { $webhook_secret = data_get($application, 'manual_webhook_secret_gitea'); $hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret); if (! hash_equals($x_hub_signature_256, $hmac) && ! isDev()) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Invalid signature.', ]); continue; } $isFunctional = $application->destination->server->isFunctional(); if (! $isFunctional) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Server is not functional.', ]); continue; } if ($x_gitea_event === 'push') { if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || blank($application->watch_paths)) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, force_rebuild: false, commit: data_get($payload, 'after', 'HEAD'), is_webhook: true, ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } elseif ($result['status'] === 'skipped') { $return_payloads->push([ 'application' => $application->name, 'status' => 'skipped', 'message' => $result['message'], ]); } else { $return_payloads->push([ 'status' => 'success', 'message' => 'Deployment queued.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); } } else { $paths = str($application->watch_paths)->explode("\n"); $return_payloads->push([ 'status' => 'failed', 'message' => 'Changed files do not match watch paths. Ignoring deployment.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, 'details' => [ 'changed_files' => $changed_files, 'watch_paths' => $paths, ], ]); } } else { $return_payloads->push([ 'status' => 'failed', 'message' => 'Deployments disabled.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); } } if ($x_gitea_event === 'pull_request') { if ($action === 'opened' || $action === 'synchronized' || $action === 'reopened') { if ($application->isPRDeployable()) { $deployment_uuid = new Cuid2; $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if (! $found) { if ($application->build_pack === 'dockercompose') { $pr_app = ApplicationPreview::create([ 'git_type' => 'gitea', 'application_id' => $application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, 'docker_compose_domains' => $application->docker_compose_domains, ]); $pr_app->generate_preview_fqdn_compose(); } else { $pr_app = ApplicationPreview::create([ 'git_type' => 'gitea', 'application_id' => $application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, ]); $pr_app->generate_preview_fqdn(); } } $result = queue_application_deployment( application: $application, pull_request_id: $pull_request_id, deployment_uuid: $deployment_uuid, force_rebuild: false, commit: data_get($payload, 'head.sha', 'HEAD'), is_webhook: true, git_type: 'gitea' ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } elseif ($result['status'] === 'skipped') { $return_payloads->push([ 'application' => $application->name, 'status' => 'skipped', 'message' => $result['message'], ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Preview deployment queued.', ]); } } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Preview deployments disabled.', ]); } } if ($action === 'closed') { $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if ($found) { // Use comprehensive cleanup that cancels active deployments, // kills helper containers, and removes all PR containers CleanupPreviewDeployment::run($application, $pull_request_id, $found); $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Preview deployment closed.', ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'No preview deployment found.', ]); } } } } return response($return_payloads); } catch (Exception $e) { return handleError($e); } } } ================================================ FILE: app/Http/Controllers/Webhook/Github.php ================================================ header('X-GitHub-Delivery'); $x_github_event = Str::lower($request->header('X-GitHub-Event')); $x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256='); $content_type = $request->header('Content-Type'); $payload = $request->collect(); if ($x_github_event === 'ping') { // Just pong return response('pong'); } if ($content_type !== 'application/json') { $payload = json_decode(data_get($payload, 'payload'), true); } if ($x_github_event === 'push') { $branch = data_get($payload, 'ref'); $full_name = data_get($payload, 'repository.full_name'); if (Str::isMatch('/refs\/heads\/*/', $branch)) { $branch = Str::after($branch, 'refs/heads/'); } $added_files = data_get($payload, 'commits.*.added'); $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); } if ($x_github_event === 'pull_request') { $action = data_get($payload, 'action'); $full_name = data_get($payload, 'repository.full_name'); $pull_request_id = data_get($payload, 'number'); $pull_request_html_url = data_get($payload, 'pull_request.html_url'); $branch = data_get($payload, 'pull_request.head.ref'); $base_branch = data_get($payload, 'pull_request.base.ref'); $before_sha = data_get($payload, 'before'); $after_sha = data_get($payload, 'after', data_get($payload, 'pull_request.head.sha')); $author_association = data_get($payload, 'pull_request.author_association'); } if (! $branch) { return response('Nothing to do. No branch found in the request.'); } $applications = Application::where('git_repository', 'like', "%$full_name%"); if ($x_github_event === 'push') { $applications = $applications->where('git_branch', $branch)->get(); if ($applications->isEmpty()) { return response("Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name."); } } if ($x_github_event === 'pull_request') { $applications = $applications->where('git_branch', $base_branch)->get(); if ($applications->isEmpty()) { return response("Nothing to do. No applications found for repo $full_name and branch '$base_branch'."); } } $applicationsByServer = $applications->groupBy(function ($app) { return $app->destination->server_id; }); foreach ($applicationsByServer as $serverId => $serverApplications) { foreach ($serverApplications as $application) { $webhook_secret = data_get($application, 'manual_webhook_secret_github'); $hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret); if (! hash_equals($x_hub_signature_256, $hmac) && ! isDev()) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Invalid signature.', ]); continue; } $isFunctional = $application->destination->server->isFunctional(); if (! $isFunctional) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Server is not functional.', ]); continue; } if ($x_github_event === 'push') { if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || blank($application->watch_paths)) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, force_rebuild: false, commit: data_get($payload, 'after', 'HEAD'), is_webhook: true, ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } elseif ($result['status'] === 'skipped') { $return_payloads->push([ 'application' => $application->name, 'status' => 'skipped', 'message' => $result['message'], ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Deployment queued.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, 'deployment_uuid' => $result['deployment_uuid'], ]); } } else { $paths = str($application->watch_paths)->explode("\n"); $return_payloads->push([ 'status' => 'failed', 'message' => 'Changed files do not match watch paths. Ignoring deployment.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, 'details' => [ 'changed_files' => $changed_files, 'watch_paths' => $paths, ], ]); } } else { $return_payloads->push([ 'status' => 'failed', 'message' => 'Deployments disabled.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); } } if ($x_github_event === 'pull_request') { // Check if PR deployments are enabled (but allow 'closed' action to cleanup) if (! $application->isPRDeployable() && $action !== 'closed') { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Preview deployments disabled.', ]); continue; } ProcessGithubPullRequestWebhook::dispatch( applicationId: $application->id, githubAppId: null, action: $action, pullRequestId: $pull_request_id, pullRequestHtmlUrl: $pull_request_html_url, beforeSha: $before_sha, afterSha: $after_sha, commitSha: data_get($payload, 'pull_request.head.sha', 'HEAD'), authorAssociation: $author_association, fullName: $full_name, ); $return_payloads->push([ 'application' => $application->name, 'status' => 'queued', 'message' => 'PR webhook received, processing queued.', ]); } } } return response($return_payloads); } catch (Exception $e) { return handleError($e); } } public function normal(Request $request) { try { $return_payloads = collect([]); $id = null; $x_github_delivery = $request->header('X-GitHub-Delivery'); $x_github_event = Str::lower($request->header('X-GitHub-Event')); $x_github_hook_installation_target_id = $request->header('X-GitHub-Hook-Installation-Target-Id'); $x_hub_signature_256 = Str::after($request->header('X-Hub-Signature-256'), 'sha256='); $payload = $request->collect(); if ($x_github_event === 'ping') { // Just pong return response('pong'); } $github_app = GithubApp::where('app_id', $x_github_hook_installation_target_id)->first(); if (is_null($github_app)) { return response('Nothing to do. No GitHub App found.'); } $webhook_secret = data_get($github_app, 'webhook_secret'); $hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret); if (config('app.env') !== 'local') { if (! hash_equals($x_hub_signature_256, $hmac)) { return response('Invalid signature.'); } } if ($x_github_event === 'installation' || $x_github_event === 'installation_repositories') { // Installation handled by setup redirect url. Repositories queried on-demand. $action = data_get($payload, 'action'); if ($action === 'new_permissions_accepted') { GithubAppPermissionJob::dispatch($github_app); } return response('cool'); } if ($x_github_event === 'push') { $id = data_get($payload, 'repository.id'); $branch = data_get($payload, 'ref'); if (Str::isMatch('/refs\/heads\/*/', $branch)) { $branch = Str::after($branch, 'refs/heads/'); } $added_files = data_get($payload, 'commits.*.added'); $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); } if ($x_github_event === 'pull_request') { $action = data_get($payload, 'action'); $id = data_get($payload, 'repository.id'); $pull_request_id = data_get($payload, 'number'); $pull_request_html_url = data_get($payload, 'pull_request.html_url'); $branch = data_get($payload, 'pull_request.head.ref'); $base_branch = data_get($payload, 'pull_request.base.ref'); $before_sha = data_get($payload, 'before'); $after_sha = data_get($payload, 'after', data_get($payload, 'pull_request.head.sha')); $author_association = data_get($payload, 'pull_request.author_association'); } if (! $id || ! $branch) { return response('Nothing to do. No id or branch found.'); } $applications = Application::where('repository_project_id', $id) ->where('source_id', $github_app->id) ->whereRelation('source', 'is_public', false); if ($x_github_event === 'push') { $applications = $applications->where('git_branch', $branch)->get(); if ($applications->isEmpty()) { return response("Nothing to do. No applications found with branch '$branch'."); } } if ($x_github_event === 'pull_request') { $applications = $applications->where('git_branch', $base_branch)->get(); if ($applications->isEmpty()) { return response("Nothing to do. No applications found with branch '$base_branch'."); } } $applicationsByServer = $applications->groupBy(function ($app) { return $app->destination->server_id; }); foreach ($applicationsByServer as $serverId => $serverApplications) { foreach ($serverApplications as $application) { $isFunctional = $application->destination->server->isFunctional(); if (! $isFunctional) { $return_payloads->push([ 'status' => 'failed', 'message' => 'Server is not functional.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); continue; } if ($x_github_event === 'push') { if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || blank($application->watch_paths)) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, commit: data_get($payload, 'after', 'HEAD'), force_rebuild: false, is_webhook: true, ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } $return_payloads->push([ 'status' => $result['status'], 'message' => $result['message'], 'application_uuid' => $application->uuid, 'application_name' => $application->name, 'deployment_uuid' => $result['deployment_uuid'] ?? null, ]); } else { $paths = str($application->watch_paths)->explode("\n"); $return_payloads->push([ 'status' => 'failed', 'message' => 'Changed files do not match watch paths. Ignoring deployment.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, 'details' => [ 'changed_files' => $changed_files, 'watch_paths' => $paths, ], ]); } } else { $return_payloads->push([ 'status' => 'failed', 'message' => 'Deployments disabled.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); } } if ($x_github_event === 'pull_request') { // Check if PR deployments are enabled (but allow 'closed' action to cleanup) if (! $application->isPRDeployable() && $action !== 'closed') { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Preview deployments disabled.', ]); continue; } $full_name = data_get($payload, 'repository.full_name'); ProcessGithubPullRequestWebhook::dispatch( applicationId: $application->id, githubAppId: $github_app->id, action: $action, pullRequestId: $pull_request_id, pullRequestHtmlUrl: $pull_request_html_url, beforeSha: $before_sha, afterSha: $after_sha, commitSha: data_get($payload, 'pull_request.head.sha', 'HEAD'), authorAssociation: $author_association, fullName: $full_name, ); $return_payloads->push([ 'application' => $application->name, 'status' => 'queued', 'message' => 'PR webhook received, processing queued.', ]); } } } return response($return_payloads); } catch (Exception $e) { return handleError($e); } } public function redirect(Request $request) { try { $code = $request->get('code'); $state = $request->get('state'); $github_app = GithubApp::where('uuid', $state)->firstOrFail(); $api_url = data_get($github_app, 'api_url'); $data = Http::withBody(null)->accept('application/vnd.github+json')->post("$api_url/app-manifests/$code/conversions")->throw()->json(); $id = data_get($data, 'id'); $slug = data_get($data, 'slug'); $client_id = data_get($data, 'client_id'); $client_secret = data_get($data, 'client_secret'); $private_key = data_get($data, 'pem'); $webhook_secret = data_get($data, 'webhook_secret'); $private_key = PrivateKey::create([ 'name' => "github-app-{$slug}", 'private_key' => $private_key, 'team_id' => $github_app->team_id, 'is_git_related' => true, ]); $github_app->name = $slug; $github_app->app_id = $id; $github_app->client_id = $client_id; $github_app->client_secret = $client_secret; $github_app->webhook_secret = $webhook_secret; $github_app->private_key_id = $private_key->id; $github_app->save(); return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]); } catch (Exception $e) { return handleError($e); } } public function install(Request $request) { try { $installation_id = $request->get('installation_id'); $source = $request->get('source'); $setup_action = $request->get('setup_action'); $github_app = GithubApp::where('uuid', $source)->firstOrFail(); if ($setup_action === 'install') { $github_app->installation_id = $installation_id; $github_app->save(); } return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]); } catch (Exception $e) { return handleError($e); } } } ================================================ FILE: app/Http/Controllers/Webhook/Gitlab.php ================================================ collect(); $headers = $request->headers->all(); $x_gitlab_token = data_get($headers, 'x-gitlab-token.0'); $x_gitlab_event = data_get($payload, 'object_kind'); $allowed_events = ['push', 'merge_request']; if (! in_array($x_gitlab_event, $allowed_events)) { $return_payloads->push([ 'status' => 'failed', 'message' => 'Event not allowed. Only push and merge_request events are allowed.', ]); return response($return_payloads); } if (empty($x_gitlab_token)) { $return_payloads->push([ 'status' => 'failed', 'message' => 'Invalid signature.', ]); return response($return_payloads); } if ($x_gitlab_event === 'push') { $branch = data_get($payload, 'ref'); $full_name = data_get($payload, 'project.path_with_namespace'); if (Str::isMatch('/refs\/heads\/*/', $branch)) { $branch = Str::after($branch, 'refs/heads/'); } if (! $branch) { $return_payloads->push([ 'status' => 'failed', 'message' => 'Nothing to do. No branch found in the request.', ]); return response($return_payloads); } $added_files = data_get($payload, 'commits.*.added'); $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); } if ($x_gitlab_event === 'merge_request') { $action = data_get($payload, 'object_attributes.action'); $branch = data_get($payload, 'object_attributes.source_branch'); $base_branch = data_get($payload, 'object_attributes.target_branch'); $full_name = data_get($payload, 'project.path_with_namespace'); $pull_request_id = data_get($payload, 'object_attributes.iid'); $pull_request_html_url = data_get($payload, 'object_attributes.url'); if (! $branch) { $return_payloads->push([ 'status' => 'failed', 'message' => 'Nothing to do. No branch found in the request.', ]); return response($return_payloads); } } $applications = Application::where('git_repository', 'like', "%$full_name%"); if ($x_gitlab_event === 'push') { $applications = $applications->where('git_branch', $branch)->get(); if ($applications->isEmpty()) { $return_payloads->push([ 'status' => 'failed', 'message' => "Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name.", ]); return response($return_payloads); } } if ($x_gitlab_event === 'merge_request') { $applications = $applications->where('git_branch', $base_branch)->get(); if ($applications->isEmpty()) { $return_payloads->push([ 'status' => 'failed', 'message' => "Nothing to do. No applications found with branch '$base_branch'.", ]); return response($return_payloads); } } foreach ($applications as $application) { $webhook_secret = data_get($application, 'manual_webhook_secret_gitlab'); if (! hash_equals($webhook_secret ?? '', $x_gitlab_token ?? '')) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Invalid signature.', ]); continue; } $isFunctional = $application->destination->server->isFunctional(); if (! $isFunctional) { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Server is not functional', ]); continue; } if ($x_gitlab_event === 'push') { if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || blank($application->watch_paths)) { $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $application, deployment_uuid: $deployment_uuid, commit: data_get($payload, 'after', 'HEAD'), force_rebuild: false, is_webhook: true, ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } elseif ($result['status'] === 'skipped') { $return_payloads->push([ 'status' => $result['status'], 'message' => $result['message'], 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); } else { $return_payloads->push([ 'status' => 'success', 'message' => 'Deployment queued.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); } } else { $paths = str($application->watch_paths)->explode("\n"); $return_payloads->push([ 'status' => 'failed', 'message' => 'Changed files do not match watch paths. Ignoring deployment.', 'application_uuid' => $application->uuid, 'application_name' => $application->name, 'details' => [ 'changed_files' => $changed_files, 'watch_paths' => $paths, ], ]); } } else { $return_payloads->push([ 'status' => 'failed', 'message' => 'Deployments disabled', 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); } } if ($x_gitlab_event === 'merge_request') { if ($action === 'open' || $action === 'opened' || $action === 'synchronize' || $action === 'reopened' || $action === 'reopen' || $action === 'update') { if ($application->isPRDeployable()) { $deployment_uuid = new Cuid2; $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if (! $found) { if ($application->build_pack === 'dockercompose') { $pr_app = ApplicationPreview::create([ 'git_type' => 'gitlab', 'application_id' => $application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, 'docker_compose_domains' => $application->docker_compose_domains, ]); $pr_app->generate_preview_fqdn_compose(); } else { $pr_app = ApplicationPreview::create([ 'git_type' => 'gitlab', 'application_id' => $application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, ]); $pr_app->generate_preview_fqdn(); } } $result = queue_application_deployment( application: $application, pull_request_id: $pull_request_id, deployment_uuid: $deployment_uuid, commit: data_get($payload, 'object_attributes.last_commit.id', 'HEAD'), force_rebuild: false, is_webhook: true, git_type: 'gitlab' ); if ($result['status'] === 'queue_full') { return response($result['message'], 429)->header('Retry-After', 60); } elseif ($result['status'] === 'skipped') { $return_payloads->push([ 'application' => $application->name, 'status' => 'skipped', 'message' => $result['message'], ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Preview Deployment queued', ]); } } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'Preview deployments disabled', ]); } } elseif ($action === 'closed' || $action === 'close' || $action === 'merge') { $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if ($found) { // Use comprehensive cleanup that cancels active deployments, // kills helper containers, and removes all PR containers CleanupPreviewDeployment::run($application, $pull_request_id, $found); $return_payloads->push([ 'application' => $application->name, 'status' => 'success', 'message' => 'Preview deployment closed.', ]); } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'No preview deployment found.', ]); } } else { $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', 'message' => 'No action found. Contact us for debugging.', ]); } } } return response($return_payloads); } catch (Exception $e) { return handleError($e); } } } ================================================ FILE: app/Http/Controllers/Webhook/Stripe.php ================================================ header('Stripe-Signature'); $event = \Stripe\Webhook::constructEvent( $request->getContent(), $signature, $webhookSecret ); StripeProcessJob::dispatch($event); return response('Webhook received. Cool cool cool cool cool.', 200); } catch (Exception $e) { return response($e->getMessage(), 400); } } } ================================================ FILE: app/Http/Kernel.php ================================================ */ 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, \App\Http\Middleware\CheckForcePasswordReset::class, \App\Http\Middleware\DecideWhatToDoWithUser::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 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, 'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class, 'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class, 'api.ability' => \App\Http\Middleware\ApiAbility::class, 'api.sensitive' => \App\Http\Middleware\ApiSensitiveData::class, 'can.create.resources' => \App\Http\Middleware\CanCreateResources::class, 'can.update.resource' => \App\Http\Middleware\CanUpdateResource::class, 'can.access.terminal' => \App\Http\Middleware\CanAccessTerminal::class, ]; } ================================================ FILE: app/Http/Middleware/ApiAbility.php ================================================ user()->tokenCan('root')) { return $next($request); } return parent::handle($request, $next, ...$abilities); } catch (\Illuminate\Auth\AuthenticationException $e) { return response()->json([ 'message' => 'Unauthenticated.', ], 401); } catch (\Exception $e) { return response()->json([ 'message' => 'Missing required permissions: '.implode(', ', $abilities), ], 403); } } } ================================================ FILE: app/Http/Middleware/ApiAllowed.php ================================================ is_api_enabled === false) { return response()->json(['success' => true, 'message' => 'API is disabled.'], 403); } if ($settings->allowed_ips) { // Check for special case: 0.0.0.0 means allow all if (trim($settings->allowed_ips) === '0.0.0.0') { return $next($request); } $allowedIps = explode(',', $settings->allowed_ips); $allowedIps = array_map('trim', $allowedIps); $allowedIps = array_filter($allowedIps); // Remove empty entries if (! empty($allowedIps) && ! checkIPAgainstAllowlist($request->ip(), $allowedIps)) { return response()->json(['success' => true, 'message' => 'You are not allowed to access the API.'], 403); } } return $next($request); } } ================================================ FILE: app/Http/Middleware/ApiSensitiveData.php ================================================ user()->currentAccessToken(); // Allow access to sensitive data if token has root or read:sensitive permission $request->attributes->add([ 'can_read_sensitive' => $token->can('root') || $token->can('read:sensitive'), ]); return $next($request); } } ================================================ FILE: app/Http/Middleware/Authenticate.php ================================================ expectsJson() ? null : route('login'); } } ================================================ FILE: app/Http/Middleware/CanAccessTerminal.php ================================================ check()) { abort(401, 'Authentication required'); } // Only admins/owners can access terminal functionality if (! auth()->user()->can('canAccessTerminal')) { abort(403, 'Access to terminal functionality is restricted to team administrators'); } return $next($request); } } ================================================ FILE: app/Http/Middleware/CanCreateResources.php ================================================ route('application_uuid')) { // $resource = Application::where('uuid', $request->route('application_uuid'))->first(); // } elseif ($request->route('service_uuid')) { // $resource = Service::where('uuid', $request->route('service_uuid'))->first(); // } elseif ($request->route('stack_service_uuid')) { // // Handle ServiceApplication or ServiceDatabase // $stack_service_uuid = $request->route('stack_service_uuid'); // $resource = ServiceApplication::where('uuid', $stack_service_uuid)->first() ?? // ServiceDatabase::where('uuid', $stack_service_uuid)->first(); // } elseif ($request->route('database_uuid')) { // // Try different database types // $database_uuid = $request->route('database_uuid'); // $resource = StandalonePostgresql::where('uuid', $database_uuid)->first() ?? // StandaloneMysql::where('uuid', $database_uuid)->first() ?? // StandaloneMariadb::where('uuid', $database_uuid)->first() ?? // StandaloneRedis::where('uuid', $database_uuid)->first() ?? // StandaloneKeydb::where('uuid', $database_uuid)->first() ?? // StandaloneDragonfly::where('uuid', $database_uuid)->first() ?? // StandaloneClickhouse::where('uuid', $database_uuid)->first() ?? // StandaloneMongodb::where('uuid', $database_uuid)->first(); // } elseif ($request->route('server_uuid')) { // // For server routes, check if user can manage servers // if (! auth()->user()->isAdmin()) { // abort(403, 'You do not have permission to access this resource.'); // } // return $next($request); // } elseif ($request->route('environment_uuid')) { // $resource = Environment::where('uuid', $request->route('environment_uuid'))->first(); // } elseif ($request->route('project_uuid')) { // $resource = Project::ownedByCurrentTeam()->where('uuid', $request->route('project_uuid'))->first(); // } // if (! $resource) { // abort(404, 'Resource not found.'); // } // if (! Gate::allows('update', $resource)) { // abort(403, 'You do not have permission to update this resource.'); // } // return $next($request); } } ================================================ FILE: app/Http/Middleware/CheckForcePasswordReset.php ================================================ user()) { if ($request->path() === 'auth/link') { auth()->logout(); request()->session()->invalidate(); request()->session()->regenerateToken(); return $next($request); } $force_password_reset = auth()->user()->force_password_reset; if ($force_password_reset) { if ($request->routeIs('auth.force-password-reset') || $request->path() === 'force-password-reset' || $request->path() === 'two-factor-challenge' || $request->path() === 'livewire/update' || $request->path() === 'logout') { return $next($request); } return redirect()->route('auth.force-password-reset'); } } return $next($request); } } ================================================ FILE: app/Http/Middleware/DecideWhatToDoWithUser.php ================================================ user()?->teams?->count() === 0) { $currentTeam = auth()->user()?->recreate_personal_team(); refreshSession($currentTeam); } if (auth()?->user()?->currentTeam()) { refreshSession(auth()->user()->currentTeam()); } elseif (auth()?->user()?->teams?->count() > 0) { // User's session team is invalid (e.g., removed from team), switch to first available team refreshSession(auth()->user()->teams->first()); } if (! auth()->user() || ! isCloud()) { if (! isCloud() && showBoarding() && ! in_array($request->path(), allowedPathsForBoardingAccounts())) { return redirect()->route('onboarding'); } return $next($request); } // Instance admins can access settings and admin routes regardless of subscription if (isInstanceAdmin() && ($request->routeIs('settings.*') || $request->path() === 'admin')) { return $next($request); } if (! auth()->user()->hasVerifiedEmail()) { if ($request->path() === 'verify' || in_array($request->path(), allowedPathsForInvalidAccounts()) || $request->routeIs('verify.verify')) { return $next($request); } return redirect()->route('verify.email'); } if (! isSubscriptionActive() && ! isSubscriptionOnGracePeriod()) { if (! in_array($request->path(), allowedPathsForUnsubscribedAccounts())) { if (Str::startsWith($request->path(), 'invitations')) { return $next($request); } return redirect()->route('subscription.index'); } } if (showBoarding() && ! in_array($request->path(), allowedPathsForBoardingAccounts())) { if (Str::startsWith($request->path(), 'invitations')) { return $next($request); } return redirect()->route('onboarding'); } if (auth()->user()->hasVerifiedEmail() && $request->path() === 'verify') { return redirect(RouteServiceProvider::HOME); } if (isSubscriptionActive() && $request->routeIs('subscription.index')) { return redirect(RouteServiceProvider::HOME); } return $next($request); } } ================================================ FILE: app/Http/Middleware/EncryptCookies.php ================================================ */ protected $except = [ // ]; } ================================================ FILE: app/Http/Middleware/PreventRequestsDuringMaintenance.php ================================================ */ protected $except = [ 'webhooks/*', '/api/health', ]; } ================================================ FILE: app/Http/Middleware/RedirectIfAuthenticated.php ================================================ check()) { return redirect(RouteServiceProvider::HOME); } } return $next($request); } } ================================================ FILE: app/Http/Middleware/TrimStrings.php ================================================ */ protected $except = [ 'current_password', 'password', 'password_confirmation', ]; } ================================================ FILE: app/Http/Middleware/TrustHosts.php ================================================ is( 'terminal/auth', 'terminal/auth/ips', 'api/*', 'webhooks/*' )) { return $next($request); } // Skip host validation if no FQDN is configured (initial setup) $fqdnHost = Cache::get('instance_settings_fqdn_host'); if ($fqdnHost === '' || $fqdnHost === null) { return $next($request); } // For all other routes, use parent's host validation return parent::handle($request, $next); } /** * Get the host patterns that should be trusted. * * @return array */ public function hosts(): array { $trustedHosts = []; // Trust the configured FQDN from InstanceSettings (cached to avoid DB query on every request) // Use empty string as sentinel value instead of null so negative results are cached $fqdnHost = Cache::remember('instance_settings_fqdn_host', 300, function () { try { $settings = InstanceSettings::get(); if ($settings && $settings->fqdn) { $url = Url::fromString($settings->fqdn); $host = $url->getHost(); return $host ?: ''; } } catch (\Exception $e) { // If instance settings table doesn't exist yet (during installation), // return empty string (sentinel) so this result is cached } return ''; }); // Convert sentinel value back to null for consumption $fqdnHost = $fqdnHost !== '' ? $fqdnHost : null; if ($fqdnHost) { $trustedHosts[] = $fqdnHost; } // Trust the APP_URL host itself (not just subdomains) $appUrl = config('app.url'); if ($appUrl) { try { $appUrlHost = parse_url($appUrl, PHP_URL_HOST); if ($appUrlHost && ! in_array($appUrlHost, $trustedHosts, true)) { $trustedHosts[] = $appUrlHost; } } catch (\Exception $e) { // Ignore parse errors } } // Trust all subdomains of APP_URL as fallback $trustedHosts[] = $this->allSubdomainsOfApplicationUrl(); // Always trust loopback addresses so local access works even when FQDN is configured foreach (['localhost', '127.0.0.1', '[::1]'] as $localHost) { if (! in_array($localHost, $trustedHosts, true)) { $trustedHosts[] = $localHost; } } return array_filter($trustedHosts); } } ================================================ FILE: app/Http/Middleware/TrustProxies.php ================================================ |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; /** * Handle the request. * * Wraps $next so that after proxy headers are resolved (X-Forwarded-Proto processed), * the Secure cookie flag is auto-enabled when the request is over HTTPS. * This ensures session cookies are correctly marked Secure when behind an HTTPS * reverse proxy (Cloudflare Tunnel, nginx, etc.) even when SESSION_SECURE_COOKIE * is not explicitly set in .env. */ public function handle($request, \Closure $next) { return parent::handle($request, function ($request) use ($next) { // At this point proxy headers have been applied to the request, // so $request->secure() correctly reflects the actual protocol. if ($request->secure() && config('session.secure') === null) { config(['session.secure' => true]); } return $next($request); }); } } ================================================ FILE: app/Http/Middleware/ValidateSignature.php ================================================ */ protected $except = [ // 'fbclid', // 'utm_campaign', // 'utm_content', // 'utm_medium', // 'utm_source', // 'utm_term', ]; } ================================================ FILE: app/Http/Middleware/VerifyCsrfToken.php ================================================ */ protected $except = [ 'webhooks/*', ]; } ================================================ FILE: app/Jobs/ApplicationDeploymentJob.php ================================================ application_deployment_queue_id]; } public function __construct(public int $application_deployment_queue_id) { $this->onQueue('high'); $this->application_deployment_queue = ApplicationDeploymentQueue::find($this->application_deployment_queue_id); $this->nixpacks_plan_json = collect([]); $this->application = Application::find($this->application_deployment_queue->application_id); $this->build_pack = data_get($this->application, 'build_pack'); $this->build_args = collect([]); $this->build_secrets = ''; $this->deployment_uuid = $this->application_deployment_queue->deployment_uuid; $this->pull_request_id = $this->application_deployment_queue->pull_request_id; $this->commit = $this->application_deployment_queue->commit; $this->rollback = $this->application_deployment_queue->rollback; $this->disableBuildCache = $this->application->settings->disable_build_cache; $this->force_rebuild = $this->application_deployment_queue->force_rebuild; if ($this->disableBuildCache) { $this->force_rebuild = true; } $this->restart_only = $this->application_deployment_queue->restart_only; $this->restart_only = $this->restart_only && $this->application->build_pack !== 'dockerimage' && $this->application->build_pack !== 'dockerfile'; $this->only_this_server = $this->application_deployment_queue->only_this_server; $this->git_type = data_get($this->application_deployment_queue, 'git_type'); $source = data_get($this->application, 'source'); if ($source) { $this->source = $source->getMorphClass()::where('id', $this->application->source->id)->first(); } $this->server = Server::find($this->application_deployment_queue->server_id); $this->timeout = $this->server->settings->dynamic_timeout; $this->destination = $this->server->destinations()->where('id', $this->application_deployment_queue->destination_id)->first(); $this->server = $this->mainServer = $this->destination->server; $this->serverUser = $this->server->user; $this->is_this_additional_server = $this->application->additional_servers()->wherePivot('server_id', $this->server->id)->count() > 0; $this->preserveRepository = $this->application->settings->is_preserve_repository_enabled; $this->basedir = $this->application->generateBaseDir($this->deployment_uuid); $this->workdir = "{$this->basedir}".rtrim($this->application->base_directory, '/'); $this->configuration_dir = application_configuration_dir()."/{$this->application->uuid}"; $this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->container_name = generateApplicationContainerName($this->application, $this->pull_request_id); if ($this->application->settings->custom_internal_name && ! $this->application->settings->is_consistent_container_name_enabled) { if ($this->pull_request_id === 0) { $this->container_name = $this->application->settings->custom_internal_name; } else { $this->container_name = addPreviewDeploymentSuffix($this->application->settings->custom_internal_name, $this->pull_request_id); } } $this->saved_outputs = collect(); // Set preview fqdn if ($this->pull_request_id !== 0) { $this->preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id); if ($this->preview) { if ($this->application->build_pack === 'dockercompose') { $this->preview->generate_preview_fqdn_compose(); } else { $this->preview->generate_preview_fqdn(); } } if ($this->application->is_github_based()) { ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::IN_PROGRESS); } if ($this->application->build_pack === 'dockerfile') { if (data_get($this->application, 'dockerfile_location')) { $this->dockerfile_location = $this->validatePathField($this->application->dockerfile_location, 'dockerfile_location'); } } } } public function handle(): void { // Check if deployment was cancelled before we even started $this->application_deployment_queue->refresh(); if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) { $this->application_deployment_queue->addLogEntry('Deployment was cancelled before starting.'); return; } $this->application_deployment_queue->update([ 'status' => ApplicationDeploymentStatus::IN_PROGRESS->value, 'horizon_job_worker' => gethostname(), ]); if ($this->server->isFunctional() === false) { $this->application_deployment_queue->addLogEntry('Server is not functional.'); $this->fail('Server is not functional.'); return; } try { // Make sure the private key is stored in the filesystem $this->server->privateKey->storeInFileSystem(); // Generate custom host<->ip mapping $allContainers = instant_remote_process(["docker network inspect {$this->destination->network} -f '{{json .Containers}}' "], $this->server); if (! is_null($allContainers)) { $allContainers = format_docker_command_output_to_json($allContainers); $ips = collect([]); if (count($allContainers) > 0) { $allContainers = $allContainers[0]; $allContainers = collect($allContainers)->sort()->values(); foreach ($allContainers as $container) { $containerName = data_get($container, 'Name'); if ($containerName === 'coolify-proxy') { continue; } if (preg_match('/-(\d{12})/', $containerName)) { continue; } $containerIp = data_get($container, 'IPv4Address'); if ($containerName && $containerIp) { $containerIp = str($containerIp)->before('/'); $ips->put($containerName, $containerIp->value()); } } } $this->addHosts = $ips->map(function ($ip, $name) { return "--add-host $name:$ip"; })->implode(' '); } if ($this->application->dockerfile_target_build) { $this->buildTarget = " --target {$this->application->dockerfile_target_build} "; } // Check custom port ['repository' => $this->customRepository, 'port' => $this->customPort] = $this->application->customRepository(); if (data_get($this->application, 'settings.is_build_server_enabled')) { $teamId = data_get($this->application, 'environment.project.team.id'); $buildServers = Server::buildServers($teamId)->get(); if ($buildServers->count() === 0) { $this->application_deployment_queue->addLogEntry('No suitable build server found. Using the deployment server.'); $this->build_server = $this->server; } else { $this->build_server = $buildServers->random(); $this->application_deployment_queue->build_server_id = $this->build_server->id; $this->application_deployment_queue->addLogEntry("Found a suitable build server ({$this->build_server->name})."); $this->use_build_server = true; } } else { $this->build_server = $this->server; } $this->detectBuildKitCapabilities(); $this->decide_what_to_do(); } catch (Exception $e) { if ($this->pull_request_id !== 0 && $this->application->is_github_based()) { ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::ERROR); } $this->fail($e); throw $e; } finally { // Wrap cleanup operations in try-catch to prevent exceptions from interfering // with Laravel's job failure handling and status updates try { $this->application_deployment_queue->update([ 'finished_at' => Carbon::now()->toImmutable(), ]); } catch (Exception $e) { // Log but don't fail - finished_at is not critical \Log::warning('Failed to update finished_at for deployment '.$this->deployment_uuid.': '.$e->getMessage()); } try { if ($this->use_build_server) { $this->server = $this->build_server; } else { $this->write_deployment_configurations(); } } catch (Exception $e) { // Log but don't fail - configuration writing errors shouldn't prevent status updates $this->application_deployment_queue->addLogEntry('Warning: Failed to write deployment configurations: '.$e->getMessage(), 'stderr'); } try { $this->application_deployment_queue->addLogEntry("Gracefully shutting down build container: {$this->deployment_uuid}"); $this->graceful_shutdown_container($this->deployment_uuid, skipRemove: true); } catch (Exception $e) { // Log but don't fail - container cleanup errors are expected when container is already gone \Log::warning('Failed to shutdown container '.$this->deployment_uuid.': '.$e->getMessage()); } try { ServiceStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id')); } catch (Exception $e) { // Log but don't fail - event dispatch errors shouldn't prevent status updates \Log::warning('Failed to dispatch ServiceStatusChanged for deployment '.$this->deployment_uuid.': '.$e->getMessage()); } } } private function detectBuildKitCapabilities(): void { $serverToCheck = $this->use_build_server ? $this->build_server : $this->server; $serverName = $this->use_build_server ? "build server ({$serverToCheck->name})" : "deployment server ({$serverToCheck->name})"; try { $dockerVersion = instant_remote_process( ["docker version --format '{{.Server.Version}}'"], $serverToCheck ); $versionParts = explode('.', $dockerVersion); $majorVersion = (int) $versionParts[0]; $minorVersion = (int) ($versionParts[1] ?? 0); if ($majorVersion < 18 || ($majorVersion == 18 && $minorVersion < 9)) { $this->dockerBuildkitSupported = false; $this->application_deployment_queue->addLogEntry("Docker {$dockerVersion} on {$serverName} does not support BuildKit (requires 18.09+)."); return; } // Check buildx availability (always installed by Coolify on Docker 24.0+) $buildxAvailable = instant_remote_process( ["docker buildx version >/dev/null 2>&1 && echo 'available' || echo 'not-available'"], $serverToCheck ); if (trim($buildxAvailable) === 'available') { $this->dockerBuildkitSupported = true; $this->application_deployment_queue->addLogEntry("Docker {$dockerVersion} with BuildKit and Buildx detected on {$serverName}."); } else { // Fallback: test DOCKER_BUILDKIT=1 support via --progress flag $buildkitTest = instant_remote_process( ["DOCKER_BUILDKIT=1 docker build --help 2>&1 | grep -q '\\-\\-progress' && echo 'supported' || echo 'not-supported'"], $serverToCheck ); if (trim($buildkitTest) === 'supported') { $this->dockerBuildkitSupported = true; $this->application_deployment_queue->addLogEntry("Docker {$dockerVersion} with BuildKit support detected on {$serverName}."); } else { $this->dockerBuildkitSupported = false; $this->application_deployment_queue->addLogEntry("Docker {$dockerVersion} on {$serverName} does not support BuildKit. Build output progress will be limited."); } } // If build secrets are enabled and BuildKit is available, verify --secret flag support if ($this->application->settings->use_build_secrets && $this->dockerBuildkitSupported) { $secretsTest = instant_remote_process( ["docker build --help 2>&1 | grep -q 'secret' && echo 'supported' || echo 'not-supported'"], $serverToCheck ); if (trim($secretsTest) === 'supported') { $this->dockerSecretsSupported = true; $this->application_deployment_queue->addLogEntry('Build secrets are enabled and will be used for enhanced security.'); } else { $this->dockerSecretsSupported = false; $this->application_deployment_queue->addLogEntry("Docker on {$serverName} does not support build secrets. Using traditional build arguments."); } } } catch (\Exception $e) { $this->dockerBuildkitSupported = false; $this->dockerSecretsSupported = false; $this->application_deployment_queue->addLogEntry("Could not detect BuildKit capabilities on {$serverName}: {$e->getMessage()}"); } } private function decide_what_to_do() { if ($this->restart_only) { $this->just_restart(); return; } elseif ($this->pull_request_id !== 0) { $this->deploy_pull_request(); } elseif ($this->application->dockerfile) { $this->deploy_simple_dockerfile(); } elseif ($this->application->build_pack === 'dockercompose') { $this->deploy_docker_compose_buildpack(); } elseif ($this->application->build_pack === 'dockerimage') { $this->deploy_dockerimage_buildpack(); } elseif ($this->application->build_pack === 'dockerfile') { $this->deploy_dockerfile_buildpack(); } elseif ($this->application->build_pack === 'static') { $this->deploy_static_buildpack(); } else { $this->deploy_nixpacks_buildpack(); } $this->post_deployment(); } private function post_deployment() { // Mark deployment as complete FIRST, before any other operations // This ensures the deployment status is FINISHED even if subsequent operations fail $this->completeDeployment(); // Then handle side effects - these should not fail the deployment try { GetContainersStatus::dispatch($this->server); } catch (\Exception $e) { \Log::warning('Failed to dispatch GetContainersStatus for deployment '.$this->deployment_uuid.': '.$e->getMessage()); } if ($this->pull_request_id !== 0) { if ($this->application->is_github_based()) { try { ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::FINISHED); } catch (\Exception $e) { \Log::warning('Failed to dispatch PR update for deployment '.$this->deployment_uuid.': '.$e->getMessage()); } } } try { $this->run_post_deployment_command(); } catch (\Exception $e) { \Log::warning('Post deployment command failed for '.$this->deployment_uuid.': '.$e->getMessage()); } try { $this->application->isConfigurationChanged(true); } catch (\Exception $e) { \Log::warning('Failed to mark configuration as changed for deployment '.$this->deployment_uuid.': '.$e->getMessage()); } } private function deploy_simple_dockerfile() { if ($this->use_build_server) { $this->server = $this->build_server; } $dockerfile_base64 = base64_encode($this->application->dockerfile); $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->application->name} to {$this->server->name}."); $this->prepare_builder_image(); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d | tee {$this->workdir}{$this->dockerfile_location} > /dev/null"), ], ); $this->generate_image_names(); $this->generate_compose_file(); // Save build-time .env file BEFORE the build $this->save_buildtime_environment_variables(); $this->generate_build_env_variables(); $this->add_build_env_variables_to_dockerfile(); $this->build_image(); // Save runtime environment variables AFTER the build // This overwrites the build-time .env with ALL variables (build-time + runtime) $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); } private function deploy_dockerimage_buildpack() { $this->dockerImage = $this->application->docker_registry_image_name; if (str($this->application->docker_registry_image_tag)->isEmpty()) { $this->dockerImageTag = 'latest'; } else { $this->dockerImageTag = $this->application->docker_registry_image_tag; } // Check if this is an image hash deployment $isImageHash = str($this->dockerImageTag)->startsWith('sha256-'); $displayName = $isImageHash ? "{$this->dockerImage}@sha256:".str($this->dockerImageTag)->after('sha256-') : "{$this->dockerImage}:{$this->dockerImageTag}"; $this->application_deployment_queue->addLogEntry("Starting deployment of {$displayName} to {$this->server->name}."); $this->generate_image_names(); $this->prepare_builder_image(); $this->generate_compose_file(); // Save runtime environment variables (including empty .env file if no variables defined) $this->save_runtime_environment_variables(); $this->rolling_update(); } private function deploy_docker_compose_buildpack() { if (data_get($this->application, 'docker_compose_location')) { $this->docker_compose_location = $this->validatePathField($this->application->docker_compose_location, 'docker_compose_location'); } if (data_get($this->application, 'docker_compose_custom_start_command')) { $this->docker_compose_custom_start_command = $this->application->docker_compose_custom_start_command; if (! str($this->docker_compose_custom_start_command)->contains('--project-directory')) { $this->docker_compose_custom_start_command = str($this->docker_compose_custom_start_command)->replaceFirst('compose', 'compose --project-directory '.$this->workdir)->value(); } } if (data_get($this->application, 'docker_compose_custom_build_command')) { $this->docker_compose_custom_build_command = $this->application->docker_compose_custom_build_command; if (! str($this->docker_compose_custom_build_command)->contains('--project-directory')) { $this->docker_compose_custom_build_command = str($this->docker_compose_custom_build_command)->replaceFirst('compose', 'compose --project-directory '.$this->workdir)->value(); } } if ($this->pull_request_id === 0) { $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->application->name} to {$this->server->name}."); } else { $this->application_deployment_queue->addLogEntry("Starting pull request (#{$this->pull_request_id}) deployment of {$this->customRepository}:{$this->application->git_branch} to {$this->server->name}."); } $this->prepare_builder_image(); $this->check_git_if_build_needed(); $this->clone_repository(); if ($this->preserveRepository) { foreach ($this->application->fileStorages as $fileStorage) { $path = $fileStorage->fs_path; $saveName = 'file_stat_'.$fileStorage->id; $realPathInGit = str($path)->replace($this->application->workdir(), $this->workdir)->value(); // check if the file is a directory or a file inside the repository $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "stat -c '%F' {$realPathInGit}"), 'hidden' => true, 'ignore_errors' => true, 'save' => $saveName] ); if ($this->saved_outputs->has($saveName)) { $fileStat = $this->saved_outputs->get($saveName); if ($fileStat->value() === 'directory' && ! $fileStorage->is_directory) { $fileStorage->is_directory = true; $fileStorage->content = null; $fileStorage->save(); $fileStorage->deleteStorageOnServer(); $fileStorage->saveStorageOnServer(); } elseif ($fileStat->value() === 'regular file' && $fileStorage->is_directory) { $fileStorage->is_directory = false; $fileStorage->is_based_on_git = true; $fileStorage->save(); $fileStorage->deleteStorageOnServer(); $fileStorage->saveStorageOnServer(); } } } } $this->generate_image_names(); $this->cleanup_git(); $this->generate_build_env_variables(); $this->application->loadComposeFile(isInit: false); if ($this->application->settings->is_raw_compose_deployment_enabled) { $this->application->oldRawParser(); $yaml = $composeFile = $this->application->docker_compose_raw; // For raw compose, we cannot automatically add secrets configuration // User must define it manually in their docker-compose file if ($this->dockerSecretsSupported && ! empty($this->build_secrets)) { $this->application_deployment_queue->addLogEntry('Build secrets are configured. Ensure your docker-compose file includes build.secrets configuration for services that need them.'); } } else { $composeFile = $this->application->parse(pull_request_id: $this->pull_request_id, preview_id: data_get($this->preview, 'id'), commit: $this->commit); // Always add .env file to services $services = collect(data_get($composeFile, 'services', [])); $services = $services->map(function ($service, $name) { $service['env_file'] = ['.env']; return $service; }); $composeFile['services'] = $services->toArray(); if (empty($composeFile)) { $this->application_deployment_queue->addLogEntry('Failed to parse docker-compose file.'); $this->fail('Failed to parse docker-compose file.'); return; } // Add build secrets to compose file if enabled and BuildKit is supported if ($this->dockerSecretsSupported && ! empty($this->build_secrets)) { $composeFile = $this->add_build_secrets_to_compose($composeFile); } $yaml = Yaml::dump(convertToArray($composeFile), 10); } $this->docker_compose_base64 = base64_encode($yaml); $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d | tee {$this->workdir}{$this->docker_compose_location} > /dev/null"), 'hidden' => true, ]); // Modify Dockerfiles for ARGs and build secrets $this->modify_dockerfiles_for_compose($composeFile); // Build new container to limit downtime. $this->application_deployment_queue->addLogEntry('Pulling & building required images.'); // Save build-time .env file BEFORE the build $this->save_buildtime_environment_variables(); if ($this->docker_compose_custom_build_command) { // Auto-inject -f (compose file) and --env-file flags using helper function $build_command = injectDockerComposeFlags( $this->docker_compose_custom_build_command, "{$this->workdir}{$this->docker_compose_location}", self::BUILD_TIME_ENV_PATH ); // Prepend DOCKER_BUILDKIT=1 if BuildKit is supported if ($this->dockerBuildkitSupported) { $build_command = "DOCKER_BUILDKIT=1 {$build_command}"; } // Inject build arguments after build subcommand if not using build secrets if (! $this->application->settings->use_build_secrets && $this->build_args instanceof \Illuminate\Support\Collection && $this->build_args->isNotEmpty()) { $build_args_string = $this->build_args->implode(' '); // Inject build args right after 'build' subcommand (not at the end) $original_command = $build_command; $build_command = injectDockerComposeBuildArgs($build_command, $build_args_string); // Only log if build args were actually injected (command was modified) if ($build_command !== $original_command) { $this->application_deployment_queue->addLogEntry('Adding build arguments to custom Docker Compose build command.'); } } try { $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$build_command}"), 'hidden' => true], ); } catch (\RuntimeException $e) { if (str_contains($e->getMessage(), "matching `'") || str_contains($e->getMessage(), 'unexpected EOF')) { throw new DeploymentException("Custom build command failed due to shell syntax error. Please check your command for special characters (like unmatched quotes): {$this->docker_compose_custom_build_command}"); } throw $e; } } else { $command = "{$this->coolify_variables} docker compose"; // Prepend DOCKER_BUILDKIT=1 if BuildKit is supported if ($this->dockerBuildkitSupported) { $command = "DOCKER_BUILDKIT=1 {$command}"; } // Use build-time .env file from /artifacts (outside Docker context to prevent it from being in the image) $command .= ' --env-file '.self::BUILD_TIME_ENV_PATH; if ($this->force_rebuild) { $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull --no-cache"; } else { $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull"; } if (! $this->application->settings->use_build_secrets && $this->build_args instanceof \Illuminate\Support\Collection && $this->build_args->isNotEmpty()) { $build_args_string = $this->build_args->implode(' '); $command .= " {$build_args_string}"; $this->application_deployment_queue->addLogEntry('Adding build arguments to Docker Compose build command.'); } $this->execute_remote_command( [executeInDocker($this->deployment_uuid, $command), 'hidden' => true], ); } // Save runtime environment variables AFTER the build // This overwrites the build-time .env with ALL variables (build-time + runtime) $this->save_runtime_environment_variables(); $this->stop_running_container(force: true); $this->application_deployment_queue->addLogEntry('Starting new application.'); $networkId = $this->application->uuid; if ($this->pull_request_id !== 0) { $networkId = "{$this->application->uuid}-{$this->pull_request_id}"; } if ($this->server->isSwarm()) { // TODO } else { $this->execute_remote_command([ "docker network inspect '{$networkId}' >/dev/null 2>&1 || docker network create --attachable '{$networkId}' >/dev/null || true", 'hidden' => true, 'ignore_errors' => true, ], [ "docker network connect {$networkId} coolify-proxy >/dev/null 2>&1 || true", 'hidden' => true, 'ignore_errors' => true, ]); } // Start compose file $server_workdir = $this->application->workdir(); if ($this->application->settings->is_raw_compose_deployment_enabled) { if ($this->docker_compose_custom_start_command) { // Auto-inject -f (compose file) and --env-file flags using helper function $start_command = injectDockerComposeFlags( $this->docker_compose_custom_start_command, "{$server_workdir}{$this->docker_compose_location}", "{$server_workdir}/.env" ); $this->write_deployment_configurations(); try { $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "cd {$this->workdir} && {$start_command}"), 'hidden' => true], ); } catch (\RuntimeException $e) { if (str_contains($e->getMessage(), "matching `'") || str_contains($e->getMessage(), 'unexpected EOF')) { throw new DeploymentException("Custom start command failed due to shell syntax error. Please check your command for special characters (like unmatched quotes): {$this->docker_compose_custom_start_command}"); } throw $e; } } else { $this->write_deployment_configurations(); $this->docker_compose_location = '/docker-compose.yaml'; $command = "{$this->coolify_variables} docker compose"; // Always use .env file $command .= " --env-file {$server_workdir}/.env"; $command .= " --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d"; $this->execute_remote_command( ['command' => $command, 'hidden' => true], ); } } else { if ($this->docker_compose_custom_start_command) { // Auto-inject -f (compose file) and --env-file flags using helper function // Use $this->workdir for non-preserve-repository mode $workdir_path = $this->preserveRepository ? $server_workdir : $this->workdir; $start_command = injectDockerComposeFlags( $this->docker_compose_custom_start_command, "{$workdir_path}{$this->docker_compose_location}", "{$workdir_path}/.env" ); $this->write_deployment_configurations(); if ($this->preserveRepository) { $this->execute_remote_command( ['command' => "cd {$server_workdir} && {$start_command}", 'hidden' => true], ); } else { $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$start_command}"), 'hidden' => true], ); } } else { $command = "{$this->coolify_variables} docker compose"; if ($this->preserveRepository) { // Always use .env file $command .= " --env-file {$server_workdir}/.env"; $command .= " --project-name {$this->application->uuid} --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d"; $this->write_deployment_configurations(); $this->execute_remote_command( ['command' => $command, 'hidden' => true], ); } else { // Always use .env file $command .= " --env-file {$this->workdir}/.env"; $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"; $this->execute_remote_command( [executeInDocker($this->deployment_uuid, $command), 'hidden' => true], ); $this->write_deployment_configurations(); } } } $this->application_deployment_queue->addLogEntry('New container started.'); } private function deploy_dockerfile_buildpack() { $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch} to {$this->server->name}."); if ($this->use_build_server) { $this->server = $this->build_server; } if (data_get($this->application, 'dockerfile_location')) { $this->dockerfile_location = $this->validatePathField($this->application->dockerfile_location, 'dockerfile_location'); } $this->prepare_builder_image(); $this->check_git_if_build_needed(); $this->generate_image_names(); $this->clone_repository(); if (! $this->force_rebuild) { $this->check_image_locally_or_remotely(); if ($this->should_skip_build()) { return; } } $this->cleanup_git(); $this->generate_compose_file(); // Save build-time .env file BEFORE the build $this->save_buildtime_environment_variables(); $this->generate_build_env_variables(); $this->add_build_env_variables_to_dockerfile(); $this->build_image(); // Save runtime environment variables AFTER the build // This overwrites the build-time .env with ALL variables (build-time + runtime) $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); } private function deploy_nixpacks_buildpack() { if ($this->use_build_server) { $this->server = $this->build_server; } $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch} to {$this->server->name}."); $this->prepare_builder_image(); $this->check_git_if_build_needed(); $this->generate_image_names(); if (! $this->force_rebuild) { $this->check_image_locally_or_remotely(); if ($this->should_skip_build()) { return; } } $this->clone_repository(); $this->cleanup_git(); $this->generate_nixpacks_confs(); $this->generate_compose_file(); // Save build-time .env file BEFORE the build for Nixpacks $this->save_buildtime_environment_variables(); $this->generate_build_env_variables(); $this->build_image(); // For Nixpacks, save runtime environment variables AFTER the build // This overwrites the build-time .env with ALL variables (build-time + runtime) $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); } private function deploy_static_buildpack() { if ($this->use_build_server) { $this->server = $this->build_server; } $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch} to {$this->server->name}."); $this->prepare_builder_image(); $this->check_git_if_build_needed(); $this->generate_image_names(); if (! $this->force_rebuild) { $this->check_image_locally_or_remotely(); if ($this->should_skip_build()) { return; } } $this->clone_repository(); $this->cleanup_git(); $this->generate_compose_file(); // Save build-time .env file BEFORE the build $this->save_buildtime_environment_variables(); $this->build_static_image(); // Save runtime environment variables AFTER the build // This overwrites the build-time .env with ALL variables (build-time + runtime) $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); } private function write_deployment_configurations() { if ($this->preserveRepository) { if ($this->use_build_server) { $this->server = $this->mainServer; } if (str($this->configuration_dir)->isNotEmpty()) { $this->execute_remote_command( [ "mkdir -p $this->configuration_dir", ], [ "docker cp {$this->deployment_uuid}:{$this->workdir}/. {$this->configuration_dir}", ], ); } foreach ($this->application->fileStorages as $fileStorage) { if (! $fileStorage->is_based_on_git && ! $fileStorage->is_directory) { $fileStorage->saveStorageOnServer(); } } if ($this->use_build_server) { $this->server = $this->build_server; } } if (isset($this->docker_compose_base64)) { if ($this->use_build_server) { $this->server = $this->mainServer; } $readme = generate_readme_file($this->application->name, $this->application_deployment_queue->updated_at); $mainDir = $this->configuration_dir; if ($this->application->settings->is_raw_compose_deployment_enabled) { $mainDir = $this->application->workdir(); } if ($this->pull_request_id === 0) { $composeFileName = "$mainDir/docker-compose.yaml"; } else { $composeFileName = "$mainDir/".addPreviewDeploymentSuffix('docker-compose', $this->pull_request_id).'.yaml'; $this->docker_compose_location = '/'.addPreviewDeploymentSuffix('docker-compose', $this->pull_request_id).'.yaml'; } $this->execute_remote_command( [ "mkdir -p $mainDir", ], [ "echo '{$this->docker_compose_base64}' | base64 -d | tee $composeFileName > /dev/null", ], [ "echo '{$readme}' > $mainDir/README.md", ] ); if ($this->use_build_server) { $this->server = $this->build_server; } } } private function push_to_docker_registry() { $forceFail = true; if (str($this->application->docker_registry_image_name)->isEmpty()) { return; } if ($this->restart_only) { return; } if ($this->application->build_pack === 'dockerimage') { return; } if ($this->use_build_server) { $forceFail = true; } if ($this->server->isSwarm() && $this->build_pack !== 'dockerimage') { $forceFail = true; } if ($this->application->additional_servers->count() > 0) { $forceFail = true; } if ($this->is_this_additional_server) { return; } try { instant_remote_process(["docker images --format '{{json .}}' {$this->production_image_name}"], $this->server); $this->application_deployment_queue->addLogEntry('----------------------------------------'); $this->application_deployment_queue->addLogEntry("Pushing image to docker registry ({$this->production_image_name})."); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "docker push {$this->production_image_name}"), 'hidden' => true, ], ); if ($this->application->docker_registry_image_tag) { // Tag image with docker_registry_image_tag $this->application_deployment_queue->addLogEntry("Tagging and pushing image with {$this->application->docker_registry_image_tag} tag."); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "docker tag {$this->production_image_name} {$this->application->docker_registry_image_name}:{$this->application->docker_registry_image_tag}"), 'ignore_errors' => true, 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, "docker push {$this->application->docker_registry_image_name}:{$this->application->docker_registry_image_tag}"), 'ignore_errors' => true, 'hidden' => true, ], ); } } catch (Exception $e) { $this->application_deployment_queue->addLogEntry('Failed to push image to docker registry. Please check debug logs for more information.'); if ($forceFail) { throw new DeploymentException(get_class($e).': '.$e->getMessage(), $e->getCode(), $e); } } } private function generate_image_names() { if ($this->application->dockerfile) { if ($this->application->docker_registry_image_name) { $this->build_image_name = "{$this->application->docker_registry_image_name}:build"; $this->production_image_name = "{$this->application->docker_registry_image_name}:latest"; } else { $this->build_image_name = "{$this->application->uuid}:build"; $this->production_image_name = "{$this->application->uuid}:latest"; } } elseif ($this->application->build_pack === 'dockerimage') { // Check if this is an image hash deployment if (str($this->dockerImageTag)->startsWith('sha256-')) { $hash = str($this->dockerImageTag)->after('sha256-'); $this->production_image_name = "{$this->dockerImage}@sha256:{$hash}"; } else { $this->production_image_name = "{$this->dockerImage}:{$this->dockerImageTag}"; } } elseif ($this->pull_request_id !== 0) { if ($this->application->docker_registry_image_name) { $this->build_image_name = "{$this->application->docker_registry_image_name}:pr-{$this->pull_request_id}-build"; $this->production_image_name = "{$this->application->docker_registry_image_name}:pr-{$this->pull_request_id}"; } else { $this->build_image_name = "{$this->application->uuid}:pr-{$this->pull_request_id}-build"; $this->production_image_name = "{$this->application->uuid}:pr-{$this->pull_request_id}"; } } else { $this->dockerImageTag = str($this->commit)->substr(0, 128); // if ($this->application->docker_registry_image_tag) { // $this->dockerImageTag = $this->application->docker_registry_image_tag; // } if ($this->application->docker_registry_image_name) { $this->build_image_name = "{$this->application->docker_registry_image_name}:{$this->dockerImageTag}-build"; $this->production_image_name = "{$this->application->docker_registry_image_name}:{$this->dockerImageTag}"; } else { $this->build_image_name = "{$this->application->uuid}:{$this->dockerImageTag}-build"; $this->production_image_name = "{$this->application->uuid}:{$this->dockerImageTag}"; } } } private function just_restart() { $this->application_deployment_queue->addLogEntry("Restarting {$this->customRepository}:{$this->application->git_branch} on {$this->server->name}."); $this->prepare_builder_image(); $this->check_git_if_build_needed(); $this->generate_image_names(); $this->check_image_locally_or_remotely(); $this->should_skip_build(); $this->completeDeployment(); } private function should_skip_build() { if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty()) { if ($this->is_this_additional_server) { $this->skip_build = true; $this->application_deployment_queue->addLogEntry("Image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); $this->generate_compose_file(); // Save runtime environment variables even when skipping build $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); return true; } if (! $this->application->isConfigurationChanged()) { $this->application_deployment_queue->addLogEntry("No configuration changed & image found ({$this->production_image_name}) with the same Git Commit SHA. Build step skipped."); $this->skip_build = true; $this->generate_compose_file(); // Save runtime environment variables even when skipping build $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); return true; } else { $this->application_deployment_queue->addLogEntry('Configuration changed. Rebuilding image.'); } } else { $this->application_deployment_queue->addLogEntry("Image not found ({$this->production_image_name}). Building new image."); } if ($this->restart_only) { $this->restart_only = false; $this->decide_what_to_do(); } return false; } private function check_image_locally_or_remotely() { $this->execute_remote_command([ "docker images -q {$this->production_image_name} 2>/dev/null", 'hidden' => true, 'save' => 'local_image_found', ]); if (str($this->saved_outputs->get('local_image_found'))->isEmpty() && $this->application->docker_registry_image_name) { $this->execute_remote_command([ "docker pull {$this->production_image_name} 2>/dev/null", 'ignore_errors' => true, 'hidden' => true, ]); $this->execute_remote_command([ "docker images -q {$this->production_image_name} 2>/dev/null", 'hidden' => true, 'save' => 'local_image_found', ]); } } private function generate_runtime_environment_variables() { $envs = collect([]); $sort = $this->application->settings->is_env_sorting_enabled; if ($sort) { $sorted_environment_variables = $this->application->environment_variables->sortBy('key'); $sorted_environment_variables_preview = $this->application->environment_variables_preview->sortBy('key'); } else { $sorted_environment_variables = $this->application->environment_variables->sortBy('id'); $sorted_environment_variables_preview = $this->application->environment_variables_preview->sortBy('id'); } if ($this->build_pack === 'dockercompose') { $sorted_environment_variables = $sorted_environment_variables->filter(function ($env) { return ! str($env->key)->startsWith('SERVICE_FQDN_') && ! str($env->key)->startsWith('SERVICE_URL_') && ! str($env->key)->startsWith('SERVICE_NAME_'); }); $sorted_environment_variables_preview = $sorted_environment_variables_preview->filter(function ($env) { return ! str($env->key)->startsWith('SERVICE_FQDN_') && ! str($env->key)->startsWith('SERVICE_URL_') && ! str($env->key)->startsWith('SERVICE_NAME_'); }); } $ports = $this->application->main_port(); $coolify_envs = $this->generate_coolify_env_variables(); $coolify_envs->each(function ($item, $key) use ($envs) { $envs->push($key.'='.$item); }); if ($this->pull_request_id === 0) { // Generate SERVICE_ variables first for dockercompose if ($this->build_pack === 'dockercompose') { $domains = collect(json_decode($this->application->docker_compose_domains)) ?? collect([]); // Generate SERVICE_FQDN & SERVICE_URL for dockercompose foreach ($domains as $forServiceName => $domain) { $parsedDomain = data_get($domain, 'domain'); if (filled($parsedDomain)) { $parsedDomain = str($parsedDomain)->explode(',')->first(); $coolifyUrl = Url::fromString($parsedDomain); $coolifyScheme = $coolifyUrl->getScheme(); $coolifyFqdn = $coolifyUrl->getHost(); $coolifyUrl = $coolifyUrl->withScheme($coolifyScheme)->withHost($coolifyFqdn)->withPort(null); $envs->push('SERVICE_URL_'.str($forServiceName)->upper().'='.$coolifyUrl->__toString()); $envs->push('SERVICE_FQDN_'.str($forServiceName)->upper().'='.$coolifyFqdn); } } // Generate SERVICE_NAME for dockercompose services from processed compose if ($this->application->settings->is_raw_compose_deployment_enabled) { $dockerCompose = Yaml::parse($this->application->docker_compose_raw); } else { $dockerCompose = Yaml::parse($this->application->docker_compose); } $services = data_get($dockerCompose, 'services', []); foreach ($services as $serviceName => $_) { $envs->push('SERVICE_NAME_'.str($serviceName)->replace('-', '_')->replace('.', '_')->upper().'='.$serviceName); } } // Filter runtime variables (only include variables that are available at runtime) $runtime_environment_variables = $sorted_environment_variables->filter(function ($env) { return $env->is_runtime; }); // Sort runtime environment variables: those referencing SERVICE_ variables come after others $runtime_environment_variables = $runtime_environment_variables->sortBy(function ($env) { if (str($env->value)->startsWith('$SERVICE_') || str($env->value)->contains('${SERVICE_')) { return 2; } return 1; }); foreach ($runtime_environment_variables as $env) { $envs->push($env->key.'='.$env->real_value); } // Check for PORT environment variable mismatch with ports_exposes if ($this->build_pack !== 'dockercompose') { $detectedPort = $this->application->detectPortFromEnvironment(false); if ($detectedPort && ! empty($ports) && ! in_array($detectedPort, $ports)) { $this->application_deployment_queue->addLogEntry( "Warning: PORT environment variable ({$detectedPort}) does not match configured ports_exposes: ".implode(',', $ports).'. It could case "bad gateway" or "no server" errors. Check the "General" page to fix it.', 'stderr' ); } } // Add PORT if not exists, use the first port as default if ($this->build_pack !== 'dockercompose') { if ($this->application->environment_variables->where('key', 'PORT')->isEmpty()) { $envs->push("PORT={$ports[0]}"); } } // Add HOST if not exists if ($this->application->environment_variables->where('key', 'HOST')->isEmpty()) { $envs->push('HOST=0.0.0.0'); } } else { // Generate SERVICE_ variables first for dockercompose preview if ($this->build_pack === 'dockercompose') { $domains = collect(json_decode(data_get($this->preview, 'docker_compose_domains'))) ?? collect([]); // Generate SERVICE_FQDN & SERVICE_URL for dockercompose foreach ($domains as $forServiceName => $domain) { $parsedDomain = data_get($domain, 'domain'); if (filled($parsedDomain)) { $parsedDomain = str($parsedDomain)->explode(',')->first(); $coolifyUrl = Url::fromString($parsedDomain); $coolifyScheme = $coolifyUrl->getScheme(); $coolifyFqdn = $coolifyUrl->getHost(); $coolifyUrl = $coolifyUrl->withScheme($coolifyScheme)->withHost($coolifyFqdn)->withPort(null); $envs->push('SERVICE_URL_'.str($forServiceName)->replace('-', '_')->replace('.', '_')->upper().'='.$coolifyUrl->__toString()); $envs->push('SERVICE_FQDN_'.str($forServiceName)->replace('-', '_')->replace('.', '_')->upper().'='.$coolifyFqdn); } } // Generate SERVICE_NAME for dockercompose services $rawDockerCompose = Yaml::parse($this->application->docker_compose_raw); $rawServices = data_get($rawDockerCompose, 'services', []); foreach ($rawServices as $rawServiceName => $_) { $envs->push('SERVICE_NAME_'.str($rawServiceName)->replace('-', '_')->replace('.', '_')->upper().'='.addPreviewDeploymentSuffix($rawServiceName, $this->pull_request_id)); } } // Filter runtime variables for preview (only include variables that are available at runtime) $runtime_environment_variables_preview = $sorted_environment_variables_preview->filter(function ($env) { return $env->is_runtime; }); // Sort runtime environment variables: those referencing SERVICE_ variables come after others $runtime_environment_variables_preview = $runtime_environment_variables_preview->sortBy(function ($env) { if (str($env->value)->startsWith('$SERVICE_') || str($env->value)->contains('${SERVICE_')) { return 2; } return 1; }); foreach ($runtime_environment_variables_preview as $env) { $envs->push($env->key.'='.$env->real_value); } // Add PORT if not exists, use the first port as default if ($this->build_pack !== 'dockercompose') { if ($this->application->environment_variables_preview->where('key', 'PORT')->isEmpty()) { $envs->push("PORT={$ports[0]}"); } } // Add HOST if not exists if ($this->application->environment_variables_preview->where('key', 'HOST')->isEmpty()) { $envs->push('HOST=0.0.0.0'); } } // Return the generated environment variables instead of storing them globally return $envs; } private function save_runtime_environment_variables() { // This method saves the .env file with ALL runtime variables // For builds, it should be called AFTER the build to include runtime-only variables // Generate runtime environment variables locally $environment_variables = $this->generate_runtime_environment_variables(); // Handle empty environment variables if ($environment_variables->isEmpty()) { // For Docker Compose and Docker Image, we need to create an empty .env file // because we always reference it in the compose file if ($this->build_pack === 'dockercompose' || $this->build_pack === 'dockerimage') { $this->application_deployment_queue->addLogEntry('Creating empty .env file (no environment variables defined).'); // Create empty .env file $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "touch $this->workdir/.env"), ] ); // Also create in configuration directory if ($this->use_build_server) { $this->server = $this->mainServer; $this->execute_remote_command( [ "touch $this->configuration_dir/.env", ] ); $this->server = $this->build_server; } else { $this->execute_remote_command( [ "touch $this->configuration_dir/.env", ] ); } } else { // For non-Docker Compose deployments, clean up any existing .env files if ($this->use_build_server) { $this->server = $this->mainServer; $this->execute_remote_command( [ 'command' => "rm -f $this->configuration_dir/.env", 'hidden' => true, 'ignore_errors' => true, ] ); $this->server = $this->build_server; $this->execute_remote_command( [ 'command' => "rm -f $this->configuration_dir/.env", 'hidden' => true, 'ignore_errors' => true, ] ); } else { $this->execute_remote_command( [ 'command' => "rm -f $this->configuration_dir/.env", 'hidden' => true, 'ignore_errors' => true, ] ); } } return; } // Write the environment variables to file $envs_base64 = base64_encode($environment_variables->implode("\n")); // Write .env file to workdir (for container runtime) $this->application_deployment_queue->addLogEntry('Creating .env file with runtime variables for container.', hidden: true); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee $this->workdir/.env > /dev/null"), ] ); if (isDev()) { $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "cat $this->workdir/.env"), 'hidden' => true, ] ); } // Write .env file to configuration directory if ($this->use_build_server) { $this->server = $this->mainServer; $this->execute_remote_command( [ "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/.env > /dev/null", ] ); $this->server = $this->build_server; } else { $this->execute_remote_command( [ "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/.env > /dev/null", ] ); } } private function generate_buildtime_environment_variables() { if (isDev()) { $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); $this->application_deployment_queue->addLogEntry('[DEBUG] Generating build-time environment variables'); $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); } // Use associative array for automatic deduplication $envs_dict = []; // 1. Add nixpacks plan variables FIRST (lowest priority - can be overridden) if ($this->build_pack === 'nixpacks' && isset($this->nixpacks_plan_json) && $this->nixpacks_plan_json->isNotEmpty()) { $planVariables = data_get($this->nixpacks_plan_json, 'variables', []); if (! empty($planVariables)) { if (isDev()) { $this->application_deployment_queue->addLogEntry('[DEBUG] Adding '.count($planVariables).' nixpacks plan variables to buildtime.env'); } foreach ($planVariables as $key => $value) { // Skip COOLIFY_* and SERVICE_* - they'll be added later with higher priority if (str_starts_with($key, 'COOLIFY_') || str_starts_with($key, 'SERVICE_')) { continue; } $escapedValue = escapeBashEnvValue($value); $envs_dict[$key] = $escapedValue; if (isDev()) { $this->application_deployment_queue->addLogEntry("[DEBUG] Nixpacks var: {$key}={$escapedValue}"); } } } } // 2. Add COOLIFY variables (can override nixpacks, but shouldn't happen in practice) $coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true); foreach ($coolify_envs as $key => $item) { $envs_dict[$key] = escapeBashEnvValue($item); } // 3. Add SERVICE_NAME, SERVICE_FQDN, SERVICE_URL variables for Docker Compose builds if ($this->build_pack === 'dockercompose') { if ($this->pull_request_id === 0) { // Generate SERVICE_NAME for dockercompose services from processed compose if ($this->application->settings->is_raw_compose_deployment_enabled) { $dockerCompose = Yaml::parse($this->application->docker_compose_raw); } else { $dockerCompose = Yaml::parse($this->application->docker_compose); } $services = data_get($dockerCompose, 'services', []); foreach ($services as $serviceName => $_) { $envs_dict['SERVICE_NAME_'.str($serviceName)->replace('-', '_')->replace('.', '_')->upper()] = escapeBashEnvValue($serviceName); } // Generate SERVICE_FQDN & SERVICE_URL for non-PR deployments $domains = collect(json_decode($this->application->docker_compose_domains)) ?? collect([]); foreach ($domains as $forServiceName => $domain) { $parsedDomain = data_get($domain, 'domain'); if (filled($parsedDomain)) { $parsedDomain = str($parsedDomain)->explode(',')->first(); $coolifyUrl = Url::fromString($parsedDomain); $coolifyScheme = $coolifyUrl->getScheme(); $coolifyFqdn = $coolifyUrl->getHost(); $coolifyUrl = $coolifyUrl->withScheme($coolifyScheme)->withHost($coolifyFqdn)->withPort(null); $envs_dict['SERVICE_URL_'.str($forServiceName)->replace('-', '_')->replace('.', '_')->upper()] = escapeBashEnvValue($coolifyUrl->__toString()); $envs_dict['SERVICE_FQDN_'.str($forServiceName)->replace('-', '_')->replace('.', '_')->upper()] = escapeBashEnvValue($coolifyFqdn); } } } else { // Generate SERVICE_NAME for preview deployments $rawDockerCompose = Yaml::parse($this->application->docker_compose_raw); $rawServices = data_get($rawDockerCompose, 'services', []); foreach ($rawServices as $rawServiceName => $_) { $envs_dict['SERVICE_NAME_'.str($rawServiceName)->replace('-', '_')->replace('.', '_')->upper()] = escapeBashEnvValue(addPreviewDeploymentSuffix($rawServiceName, $this->pull_request_id)); } // Generate SERVICE_FQDN & SERVICE_URL for preview deployments with PR-specific domains $domains = collect(json_decode(data_get($this->preview, 'docker_compose_domains'))) ?? collect([]); foreach ($domains as $forServiceName => $domain) { $parsedDomain = data_get($domain, 'domain'); if (filled($parsedDomain)) { $parsedDomain = str($parsedDomain)->explode(',')->first(); $coolifyUrl = Url::fromString($parsedDomain); $coolifyScheme = $coolifyUrl->getScheme(); $coolifyFqdn = $coolifyUrl->getHost(); $coolifyUrl = $coolifyUrl->withScheme($coolifyScheme)->withHost($coolifyFqdn)->withPort(null); $envs_dict['SERVICE_URL_'.str($forServiceName)->replace('-', '_')->replace('.', '_')->upper()] = escapeBashEnvValue($coolifyUrl->__toString()); $envs_dict['SERVICE_FQDN_'.str($forServiceName)->replace('-', '_')->replace('.', '_')->upper()] = escapeBashEnvValue($coolifyFqdn); } } } } // 4. Add user-defined build-time variables LAST (highest priority - can override everything) if ($this->pull_request_id === 0) { $sorted_environment_variables = $this->application->environment_variables() ->where('is_buildtime', true) // ONLY build-time variables ->orderBy($this->application->settings->is_env_sorting_enabled ? 'key' : 'id') ->get(); // For Docker Compose, filter out SERVICE_FQDN and SERVICE_URL as we generate these if ($this->build_pack === 'dockercompose') { $sorted_environment_variables = $sorted_environment_variables->filter(function ($env) { return ! str($env->key)->startsWith('SERVICE_FQDN_') && ! str($env->key)->startsWith('SERVICE_URL_'); }); } foreach ($sorted_environment_variables as $env) { // For literal/multiline vars, real_value includes quotes that we need to remove if ($env->is_literal || $env->is_multiline) { // Strip outer quotes from real_value and apply proper bash escaping $value = trim($env->real_value, "'"); $escapedValue = escapeBashEnvValue($value); if (isDev() && isset($envs_dict[$env->key])) { $this->application_deployment_queue->addLogEntry("[DEBUG] User override: {$env->key} (was: {$envs_dict[$env->key]}, now: {$escapedValue})"); } $envs_dict[$env->key] = $escapedValue; if (isDev()) { $this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}"); $this->application_deployment_queue->addLogEntry('[DEBUG] Type: literal/multiline'); $this->application_deployment_queue->addLogEntry("[DEBUG] raw real_value: {$env->real_value}"); $this->application_deployment_queue->addLogEntry("[DEBUG] stripped value: {$value}"); $this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}"); } } else { // For normal vars, use double quotes to allow $VAR expansion $escapedValue = escapeBashDoubleQuoted($env->real_value); if (isDev() && isset($envs_dict[$env->key])) { $this->application_deployment_queue->addLogEntry("[DEBUG] User override: {$env->key} (was: {$envs_dict[$env->key]}, now: {$escapedValue})"); } $envs_dict[$env->key] = $escapedValue; if (isDev()) { $this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}"); $this->application_deployment_queue->addLogEntry('[DEBUG] Type: normal (allows expansion)'); $this->application_deployment_queue->addLogEntry("[DEBUG] real_value: {$env->real_value}"); $this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}"); } } } } else { $sorted_environment_variables = $this->application->environment_variables_preview() ->where('is_buildtime', true) // ONLY build-time variables ->orderBy($this->application->settings->is_env_sorting_enabled ? 'key' : 'id') ->get(); // For Docker Compose, filter out SERVICE_FQDN and SERVICE_URL as we generate these with PR-specific values if ($this->build_pack === 'dockercompose') { $sorted_environment_variables = $sorted_environment_variables->filter(function ($env) { return ! str($env->key)->startsWith('SERVICE_FQDN_') && ! str($env->key)->startsWith('SERVICE_URL_'); }); } foreach ($sorted_environment_variables as $env) { // For literal/multiline vars, real_value includes quotes that we need to remove if ($env->is_literal || $env->is_multiline) { // Strip outer quotes from real_value and apply proper bash escaping $value = trim($env->real_value, "'"); $escapedValue = escapeBashEnvValue($value); if (isDev() && isset($envs_dict[$env->key])) { $this->application_deployment_queue->addLogEntry("[DEBUG] User override: {$env->key} (was: {$envs_dict[$env->key]}, now: {$escapedValue})"); } $envs_dict[$env->key] = $escapedValue; if (isDev()) { $this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}"); $this->application_deployment_queue->addLogEntry('[DEBUG] Type: literal/multiline'); $this->application_deployment_queue->addLogEntry("[DEBUG] raw real_value: {$env->real_value}"); $this->application_deployment_queue->addLogEntry("[DEBUG] stripped value: {$value}"); $this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}"); } } else { // For normal vars, use double quotes to allow $VAR expansion $escapedValue = escapeBashDoubleQuoted($env->real_value); if (isDev() && isset($envs_dict[$env->key])) { $this->application_deployment_queue->addLogEntry("[DEBUG] User override: {$env->key} (was: {$envs_dict[$env->key]}, now: {$escapedValue})"); } $envs_dict[$env->key] = $escapedValue; if (isDev()) { $this->application_deployment_queue->addLogEntry("[DEBUG] Build-time env: {$env->key}"); $this->application_deployment_queue->addLogEntry('[DEBUG] Type: normal (allows expansion)'); $this->application_deployment_queue->addLogEntry("[DEBUG] real_value: {$env->real_value}"); $this->application_deployment_queue->addLogEntry("[DEBUG] final escaped: {$escapedValue}"); } } } } // Convert dictionary back to collection in KEY=VALUE format $envs = collect([]); foreach ($envs_dict as $key => $value) { $envs->push($key.'='.$value); } // Return the generated environment variables if (isDev()) { $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); $this->application_deployment_queue->addLogEntry("[DEBUG] Total build-time env variables: {$envs->count()}"); $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); } return $envs; } private function save_buildtime_environment_variables() { // Generate build-time environment variables locally $environment_variables = $this->generate_buildtime_environment_variables(); // Save .env file for build phase in /artifacts to prevent it from being copied into Docker images if ($environment_variables->isNotEmpty()) { $envs_base64 = base64_encode($environment_variables->implode("\n")); $this->application_deployment_queue->addLogEntry('Creating build-time .env file in /artifacts (outside Docker context).', hidden: true); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee ".self::BUILD_TIME_ENV_PATH.' > /dev/null'), ] ); if (isDev()) { $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_TIME_ENV_PATH), 'hidden' => true, ] ); } } elseif ($this->build_pack === 'dockercompose' || $this->build_pack === 'dockerfile') { // For Docker Compose and Dockerfile, create an empty .env file even if there are no build-time variables // This ensures the file exists when referenced in build commands $this->application_deployment_queue->addLogEntry('Creating empty build-time .env file in /artifacts (no build-time variables defined).', hidden: true); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, 'touch '.self::BUILD_TIME_ENV_PATH), ] ); } } private function elixir_finetunes() { if ($this->pull_request_id === 0) { $envType = 'environment_variables'; } else { $envType = 'environment_variables_preview'; } $mix_env = $this->application->{$envType}->where('key', 'MIX_ENV')->first(); if (! $mix_env) { $this->application_deployment_queue->addLogEntry('MIX_ENV environment variable not found.', type: 'error'); $this->application_deployment_queue->addLogEntry('Please add MIX_ENV environment variable and set it to be build time variable if you facing any issues with the deployment.', type: 'error'); } $secret_key_base = $this->application->{$envType}->where('key', 'SECRET_KEY_BASE')->first(); if (! $secret_key_base) { $this->application_deployment_queue->addLogEntry('SECRET_KEY_BASE environment variable not found.', type: 'error'); $this->application_deployment_queue->addLogEntry('Please add SECRET_KEY_BASE environment variable and set it to be build time variable if you facing any issues with the deployment.', type: 'error'); } $database_url = $this->application->{$envType}->where('key', 'DATABASE_URL')->first(); if (! $database_url) { $this->application_deployment_queue->addLogEntry('DATABASE_URL environment variable not found.', type: 'error'); $this->application_deployment_queue->addLogEntry('Please add DATABASE_URL environment variable and set it to be build time variable if you facing any issues with the deployment.', type: 'error'); } } private function laravel_finetunes() { if ($this->pull_request_id === 0) { $envType = 'environment_variables'; } else { $envType = 'environment_variables_preview'; } $nixpacks_php_fallback_path = $this->application->{$envType}->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first(); $nixpacks_php_root_dir = $this->application->{$envType}->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first(); if (! $nixpacks_php_fallback_path) { $nixpacks_php_fallback_path = new EnvironmentVariable; $nixpacks_php_fallback_path->key = 'NIXPACKS_PHP_FALLBACK_PATH'; $nixpacks_php_fallback_path->value = '/index.php'; $nixpacks_php_fallback_path->resourceable_id = $this->application->id; $nixpacks_php_fallback_path->resourceable_type = 'App\Models\Application'; $nixpacks_php_fallback_path->save(); } if (! $nixpacks_php_root_dir) { $nixpacks_php_root_dir = new EnvironmentVariable; $nixpacks_php_root_dir->key = 'NIXPACKS_PHP_ROOT_DIR'; $nixpacks_php_root_dir->value = '/app/public'; $nixpacks_php_root_dir->resourceable_id = $this->application->id; $nixpacks_php_root_dir->resourceable_type = 'App\Models\Application'; $nixpacks_php_root_dir->save(); } return [$nixpacks_php_fallback_path, $nixpacks_php_root_dir]; } private function rolling_update() { try { $this->checkForCancellation(); if ($this->server->isSwarm()) { $this->application_deployment_queue->addLogEntry('Rolling update started.'); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "docker stack deploy --detach=true --with-registry-auth -c {$this->workdir}{$this->docker_compose_location} {$this->application->uuid}"), ], ); $this->application_deployment_queue->addLogEntry('Rolling update completed.'); } else { if ($this->use_build_server) { $this->write_deployment_configurations(); $this->server = $this->mainServer; } if (count($this->application->ports_mappings_array) > 0 || (bool) $this->application->settings->is_consistent_container_name_enabled || str($this->application->settings->custom_internal_name)->isNotEmpty() || $this->pull_request_id !== 0 || str($this->application->custom_docker_run_options)->contains('--ip') || str($this->application->custom_docker_run_options)->contains('--ip6')) { $this->application_deployment_queue->addLogEntry('----------------------------------------'); if (count($this->application->ports_mappings_array) > 0) { $this->application_deployment_queue->addLogEntry('Application has ports mapped to the host system, rolling update is not supported.'); } if ((bool) $this->application->settings->is_consistent_container_name_enabled) { $this->application_deployment_queue->addLogEntry('Consistent container name feature enabled, rolling update is not supported.'); } if (str($this->application->settings->custom_internal_name)->isNotEmpty()) { $this->application_deployment_queue->addLogEntry('Custom internal name is set, rolling update is not supported.'); } if ($this->pull_request_id !== 0) { $this->application->settings->is_consistent_container_name_enabled = true; $this->application_deployment_queue->addLogEntry('Pull request deployment, rolling update is not supported.'); } if (str($this->application->custom_docker_run_options)->contains('--ip') || str($this->application->custom_docker_run_options)->contains('--ip6')) { $this->application_deployment_queue->addLogEntry('Custom IP address is set, rolling update is not supported.'); } $this->stop_running_container(force: true); $this->start_by_compose_file(); } else { $this->application_deployment_queue->addLogEntry('----------------------------------------'); $this->application_deployment_queue->addLogEntry('Rolling update started.'); $this->start_by_compose_file(); $this->health_check(); $this->stop_running_container(); $this->application_deployment_queue->addLogEntry('Rolling update completed.'); } } } catch (Exception $e) { throw new DeploymentException('Rolling update failed ('.get_class($e).'): '.$e->getMessage(), $e->getCode(), $e); } } private function health_check() { try { if ($this->server->isSwarm()) { // Implement healthcheck for swarm } else { if ($this->application->isHealthcheckDisabled() && $this->application->custom_healthcheck_found === false) { $this->newVersionIsHealthy = true; return; } if ($this->application->custom_healthcheck_found) { $this->application_deployment_queue->addLogEntry('Custom healthcheck found in Dockerfile.'); } if ($this->container_name) { $counter = 1; $this->application_deployment_queue->addLogEntry('Waiting for healthcheck to pass on the new container.'); if ($this->full_healthcheck_url && ! $this->application->custom_healthcheck_found) { $healthcheckLabel = $this->application->health_check_type === 'cmd' ? 'Healthcheck command' : 'Healthcheck URL'; $this->application_deployment_queue->addLogEntry("{$healthcheckLabel} (inside the container): {$this->full_healthcheck_url}"); } $this->application_deployment_queue->addLogEntry("Waiting for the start period ({$this->application->health_check_start_period} seconds) before starting healthcheck."); $sleeptime = 0; while ($sleeptime < $this->application->health_check_start_period) { Sleep::for(1)->seconds(); $sleeptime++; } while ($counter <= $this->application->health_check_retries) { $this->execute_remote_command( [ "docker inspect --format='{{json .State.Health.Status}}' {$this->container_name}", 'hidden' => true, 'save' => 'health_check', 'append' => false, ], [ "docker inspect --format='{{json .State.Health.Log}}' {$this->container_name}", 'hidden' => true, 'save' => 'health_check_logs', 'append' => false, ], ); $this->application_deployment_queue->addLogEntry("Attempt {$counter} of {$this->application->health_check_retries} | Healthcheck status: {$this->saved_outputs->get('health_check')}"); $health_check_logs = data_get(collect(json_decode($this->saved_outputs->get('health_check_logs')))->last(), 'Output', '(no logs)'); if (empty($health_check_logs)) { $health_check_logs = '(no logs)'; } $health_check_return_code = data_get(collect(json_decode($this->saved_outputs->get('health_check_logs')))->last(), 'ExitCode', '(no return code)'); if ($health_check_logs !== '(no logs)' || $health_check_return_code !== '(no return code)') { $this->application_deployment_queue->addLogEntry("Healthcheck logs: {$health_check_logs} | Return code: {$health_check_return_code}"); } if (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'healthy') { $this->newVersionIsHealthy = true; $this->application->update(['status' => 'running']); $this->application_deployment_queue->addLogEntry('New container is healthy.'); break; } elseif (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'unhealthy') { $this->newVersionIsHealthy = false; $this->application_deployment_queue->addLogEntry('New container is unhealthy.', type: 'error'); $this->query_logs(); break; } $counter++; $sleeptime = 0; while ($sleeptime < $this->application->health_check_interval) { Sleep::for(1)->seconds(); $sleeptime++; } } if (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'starting') { $this->query_logs(); } } } } catch (Exception $e) { throw new DeploymentException('Health check failed ('.get_class($e).'): '.$e->getMessage(), $e->getCode(), $e); } } private function query_logs() { $this->application_deployment_queue->addLogEntry('----------------------------------------'); $this->application_deployment_queue->addLogEntry('Container logs:'); $this->execute_remote_command( [ 'command' => "docker logs -n 100 {$this->container_name}", 'type' => 'stderr', 'ignore_errors' => true, ], ); $this->application_deployment_queue->addLogEntry('----------------------------------------'); } private function deploy_pull_request() { if ($this->application->build_pack === 'dockercompose') { $this->deploy_docker_compose_buildpack(); return; } if ($this->use_build_server) { $this->server = $this->build_server; } $this->newVersionIsHealthy = true; $this->generate_image_names(); $this->application_deployment_queue->addLogEntry("Starting pull request (#{$this->pull_request_id}) deployment of {$this->customRepository}:{$this->application->git_branch}."); $this->prepare_builder_image(); $this->check_git_if_build_needed(); $this->clone_repository(); $this->cleanup_git(); if ($this->application->build_pack === 'nixpacks') { $this->generate_nixpacks_confs(); } $this->generate_compose_file(); // Save build-time .env file BEFORE the build $this->save_buildtime_environment_variables(); $this->generate_build_env_variables(); if ($this->application->build_pack === 'dockerfile') { $this->add_build_env_variables_to_dockerfile(); } $this->build_image(); // This overwrites the build-time .env with ALL variables (build-time + runtime) $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); } private function create_workdir() { if ($this->use_build_server) { $this->server = $this->mainServer; $this->execute_remote_command( [ 'command' => "mkdir -p {$this->configuration_dir}", ], ); $this->server = $this->build_server; $this->execute_remote_command( [ 'command' => executeInDocker($this->deployment_uuid, "mkdir -p {$this->workdir}"), ], [ 'command' => "mkdir -p {$this->configuration_dir}", ], ); } else { $this->execute_remote_command( [ 'command' => executeInDocker($this->deployment_uuid, "mkdir -p {$this->workdir}"), ], [ 'command' => "mkdir -p {$this->configuration_dir}", ], ); } } private function prepare_builder_image(bool $firstTry = true) { $this->checkForCancellation(); $helperImage = config('constants.coolify.helper_image'); $helperImage = "{$helperImage}:".getHelperVersion(); // Get user home directory $this->serverUserHomeDir = instant_remote_process(['echo $HOME'], $this->server); $this->dockerConfigFileExists = instant_remote_process(["test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'"], $this->server); $env_flags = $this->generate_docker_env_flags_for_secrets(); if ($this->use_build_server) { if ($this->dockerConfigFileExists === 'NOK') { throw new DeploymentException('Docker config file (~/.docker/config.json) not found on the build server. Please run "docker login" to login to the docker registry on the server.'); } $runCommand = "docker run -d --name {$this->deployment_uuid} {$env_flags} --rm -v {$this->serverUserHomeDir}/.docker/config.json:/root/.docker/config.json:ro -v /var/run/docker.sock:/var/run/docker.sock {$helperImage}"; } else { if ($this->dockerConfigFileExists === 'OK') { $runCommand = "docker run -d --network {$this->destination->network} --name {$this->deployment_uuid} {$env_flags} --rm -v {$this->serverUserHomeDir}/.docker/config.json:/root/.docker/config.json:ro -v /var/run/docker.sock:/var/run/docker.sock {$helperImage}"; } else { $runCommand = "docker run -d --network {$this->destination->network} --name {$this->deployment_uuid} {$env_flags} --rm -v /var/run/docker.sock:/var/run/docker.sock {$helperImage}"; } } if ($firstTry) { $this->application_deployment_queue->addLogEntry("Preparing container with helper image: $helperImage"); } else { $this->application_deployment_queue->addLogEntry('Preparing container with helper image with updated envs.'); } $this->graceful_shutdown_container($this->deployment_uuid, skipRemove: true); $this->execute_remote_command( [ $runCommand, 'hidden' => true, ], [ 'command' => executeInDocker($this->deployment_uuid, "mkdir -p {$this->basedir}"), ], ); $this->run_pre_deployment_command(); } private function restart_builder_container_with_actual_commit() { // Stop the current helper container (no need for rm -f as it was started with --rm) $this->graceful_shutdown_container($this->deployment_uuid, skipRemove: true); // Clear cached env_args to force regeneration with actual SOURCE_COMMIT value $this->env_args = null; // Restart the helper container with updated environment variables (including actual SOURCE_COMMIT) $this->prepare_builder_image(firstTry: false); } private function deploy_to_additional_destinations() { if ($this->application->additional_networks->count() === 0) { return; } if ($this->pull_request_id !== 0) { return; } $destination_ids = $this->application->additional_networks->pluck('id'); if ($this->server->isSwarm()) { $this->application_deployment_queue->addLogEntry('Additional destinations are not supported in swarm mode.'); return; } if ($destination_ids->contains($this->destination->id)) { return; } foreach ($destination_ids as $destination_id) { $destination = StandaloneDocker::find($destination_id); if (! $destination) { continue; } $server = $destination->server; if ($server->team_id !== $this->mainServer->team_id) { $this->application_deployment_queue->addLogEntry("Skipping deployment to {$server->name}. Not in the same team?!"); continue; } $deployment_uuid = new Cuid2; queue_application_deployment( deployment_uuid: $deployment_uuid, application: $this->application, server: $server, destination: $destination, no_questions_asked: true, ); $this->application_deployment_queue->addLogEntry("Deployment to {$server->name}. Logs: ".route('project.application.deployment.show', [ 'project_uuid' => data_get($this->application, 'environment.project.uuid'), 'application_uuid' => data_get($this->application, 'uuid'), 'deployment_uuid' => $deployment_uuid, 'environment_uuid' => data_get($this->application, 'environment.uuid'), ])); } } private function set_coolify_variables() { $this->coolify_variables = ''; // Only include SOURCE_COMMIT in build context if enabled in settings if ($this->application->settings->include_source_commit_in_build) { $this->coolify_variables .= "SOURCE_COMMIT={$this->commit} "; } if ($this->pull_request_id === 0) { $fqdn = $this->application->fqdn; } else { $fqdn = $this->preview->fqdn; } if (isset($fqdn)) { $url = Url::fromString($fqdn); $fqdn = $url->getHost(); $url = $url->withHost($fqdn)->withPort(null)->__toString(); if ((int) $this->application->compose_parsing_version >= 3) { $this->coolify_variables .= "COOLIFY_URL={$url} "; $this->coolify_variables .= "COOLIFY_FQDN={$fqdn} "; } else { $this->coolify_variables .= "COOLIFY_URL={$fqdn} "; $this->coolify_variables .= "COOLIFY_FQDN={$url} "; } } if (isset($this->application->git_branch)) { $this->coolify_variables .= "COOLIFY_BRANCH={$this->application->git_branch} "; } $this->coolify_variables .= "COOLIFY_RESOURCE_UUID={$this->application->uuid} "; } private function check_git_if_build_needed() { if (is_object($this->source) && $this->source->getMorphClass() === \App\Models\GithubApp::class && $this->source->is_public === false) { $repository = githubApi($this->source, "repos/{$this->customRepository}"); $data = data_get($repository, 'data'); $repository_project_id = data_get($data, 'id'); if (isset($repository_project_id)) { if (blank($this->application->repository_project_id) || $this->application->repository_project_id !== $repository_project_id) { $this->application->repository_project_id = $repository_project_id; $this->application->save(); } } } $this->generate_git_import_commands(); $local_branch = $this->branch; if ($this->pull_request_id !== 0) { $local_branch = "pull/{$this->pull_request_id}/head"; } // Build an exact refspec for ls-remote so we don't match similarly named branches (e.g., changeset-release/main) if ($this->pull_request_id === 0) { $lsRemoteRef = "refs/heads/{$local_branch}"; } else { if ($this->git_type === 'github' || $this->git_type === 'gitea') { $lsRemoteRef = "refs/pull/{$this->pull_request_id}/head"; } elseif ($this->git_type === 'gitlab') { $lsRemoteRef = "refs/merge-requests/{$this->pull_request_id}/head"; } else { // Fallback to the original value if provider-specific ref is unknown $lsRemoteRef = $local_branch; } } $private_key = data_get($this->application, 'private_key.private_key'); if ($private_key) { $private_key = base64_encode($private_key); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, 'mkdir -p /root/.ssh'), ], [ executeInDocker($this->deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"), ], [ executeInDocker($this->deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'), ], [ executeInDocker($this->deployment_uuid, "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git ls-remote {$this->fullRepoUrl} {$lsRemoteRef}"), 'hidden' => true, 'save' => 'git_commit_sha', ] ); } else { $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git ls-remote {$this->fullRepoUrl} {$lsRemoteRef}"), 'hidden' => true, 'save' => 'git_commit_sha', ], ); } if ($this->saved_outputs->get('git_commit_sha') && ! $this->rollback) { // Extract commit SHA from git ls-remote output, handling multi-line output (e.g., redirect warnings) // Expected format: "commit_sha\trefs/heads/branch" possibly preceded by warning lines // Note: Git warnings can be on the same line as the result (no newline) $lsRemoteOutput = $this->saved_outputs->get('git_commit_sha'); // Find the part containing a tab (the actual ls-remote result) // Handle cases where warning is on the same line as the result if ($lsRemoteOutput->contains("\t")) { // Get everything from the last occurrence of a valid commit SHA pattern before the tab // A valid commit SHA is 40 hex characters $output = $lsRemoteOutput->value(); // Extract the line with the tab (actual ls-remote result) preg_match('/\b([0-9a-fA-F]{40})(?=\s*\t)/', $output, $matches); if (isset($matches[1])) { $this->commit = $matches[1]; $this->application_deployment_queue->commit = $this->commit; $this->application_deployment_queue->save(); } } } $this->set_coolify_variables(); // Restart helper container with actual SOURCE_COMMIT value if ($this->application->settings->use_build_secrets && $this->commit !== 'HEAD') { $this->application_deployment_queue->addLogEntry('Restarting helper container with actual SOURCE_COMMIT value.'); $this->restart_builder_container_with_actual_commit(); } } private function clone_repository() { $importCommands = $this->generate_git_import_commands(); $this->application_deployment_queue->addLogEntry("\n----------------------------------------"); $this->application_deployment_queue->addLogEntry("Importing {$this->customRepository}:{$this->application->git_branch} (commit sha {$this->commit}) to {$this->basedir}."); if ($this->pull_request_id !== 0) { $this->application_deployment_queue->addLogEntry("Checking out tag pull/{$this->pull_request_id}/head."); } $this->execute_remote_command( [ $importCommands, 'hidden' => true, ] ); $this->create_workdir(); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "cd {$this->workdir} && git log -1 ".escapeshellarg($this->commit).' --pretty=%B'), 'hidden' => true, 'save' => 'commit_message', ] ); if ($this->saved_outputs->get('commit_message')) { $commit_message = str($this->saved_outputs->get('commit_message')); $this->application_deployment_queue->commit_message = $commit_message->value(); ApplicationDeploymentQueue::whereCommit($this->commit)->whereApplicationId($this->application->id)->update( ['commit_message' => $commit_message->value()] ); } } private function generate_git_import_commands() { ['commands' => $commands, 'branch' => $this->branch, 'fullRepoUrl' => $this->fullRepoUrl] = $this->application->generateGitImportCommands( deployment_uuid: $this->deployment_uuid, pull_request_id: $this->pull_request_id, git_type: $this->git_type, commit: $this->commit ); return $commands; } private function cleanup_git() { $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "rm -fr {$this->basedir}/.git")], ); } private function generate_nixpacks_confs() { $nixpacks_command = $this->nixpacks_build_cmd(); $this->application_deployment_queue->addLogEntry("Generating nixpacks configuration with: $nixpacks_command"); $this->execute_remote_command( [executeInDocker($this->deployment_uuid, $nixpacks_command), 'save' => 'nixpacks_plan', 'hidden' => true], [executeInDocker($this->deployment_uuid, "nixpacks detect {$this->workdir}"), 'save' => 'nixpacks_type', 'hidden' => true], ); if ($this->saved_outputs->get('nixpacks_type')) { $this->nixpacks_type = $this->saved_outputs->get('nixpacks_type'); if (str($this->nixpacks_type)->isEmpty()) { throw new DeploymentException('Nixpacks failed to detect the application type. Please check the documentation of Nixpacks: https://nixpacks.com/docs/providers'); } } if ($this->saved_outputs->get('nixpacks_plan')) { $this->nixpacks_plan = $this->saved_outputs->get('nixpacks_plan'); if ($this->nixpacks_plan) { $this->application_deployment_queue->addLogEntry("Found application type: {$this->nixpacks_type}."); $this->application_deployment_queue->addLogEntry("If you need further customization, please check the documentation of Nixpacks: https://nixpacks.com/docs/providers/{$this->nixpacks_type}"); $parsed = json_decode($this->nixpacks_plan, true); // Do any modifications here // We need to generate envs here because nixpacks need to know to generate a proper Dockerfile $this->generate_env_variables(); $merged_envs = collect(data_get($parsed, 'variables', []))->merge($this->env_args); $aptPkgs = data_get($parsed, 'phases.setup.aptPkgs', []); if (count($aptPkgs) === 0) { $aptPkgs = ['curl', 'wget']; data_set($parsed, 'phases.setup.aptPkgs', ['curl', 'wget']); } else { if (! in_array('curl', $aptPkgs)) { $aptPkgs[] = 'curl'; } if (! in_array('wget', $aptPkgs)) { $aptPkgs[] = 'wget'; } data_set($parsed, 'phases.setup.aptPkgs', $aptPkgs); } data_set($parsed, 'variables', $merged_envs->toArray()); $is_laravel = data_get($parsed, 'variables.IS_LARAVEL', false); if ($is_laravel) { $variables = $this->laravel_finetunes(); data_set($parsed, 'variables.NIXPACKS_PHP_FALLBACK_PATH', $variables[0]->value); data_set($parsed, 'variables.NIXPACKS_PHP_ROOT_DIR', $variables[1]->value); } if ($this->nixpacks_type === 'elixir') { $this->elixir_finetunes(); } if ($this->nixpacks_type === 'node') { // Check if NIXPACKS_NODE_VERSION is set $variables = data_get($parsed, 'variables', []); if (! isset($variables['NIXPACKS_NODE_VERSION'])) { $this->application_deployment_queue->addLogEntry('----------------------------------------'); $this->application_deployment_queue->addLogEntry('⚠️ NIXPACKS_NODE_VERSION not set. Nixpacks will use Node.js 18 by default, which is EOL.'); $this->application_deployment_queue->addLogEntry('You can override this by setting NIXPACKS_NODE_VERSION=22 in your environment variables.'); } } $this->nixpacks_plan = json_encode($parsed, JSON_PRETTY_PRINT); $this->nixpacks_plan_json = collect($parsed); if (isDev()) { $this->application_deployment_queue->addLogEntry("Final Nixpacks plan: {$this->nixpacks_plan}", hidden: true); } else { $parsedForLog = $parsed; unset($parsedForLog['variables']); // remove variables section to avoid exposing ENVs in production logs $this->application_deployment_queue->addLogEntry('Final Nixpacks plan: '.json_encode($parsedForLog, JSON_PRETTY_PRINT), hidden: true); } if ($this->nixpacks_type === 'rust') { // temporary: disable healthcheck for rust because the start phase does not have curl/wget $this->application->health_check_enabled = false; $this->application->save(); } } } } private function nixpacks_build_cmd() { $this->generate_nixpacks_env_variables(); $nixpacks_command = "nixpacks plan -f json {$this->env_nixpacks_args}"; if ($this->application->build_command) { $nixpacks_command .= " --build-cmd \"{$this->application->build_command}\""; } if ($this->application->start_command) { $nixpacks_command .= " --start-cmd \"{$this->application->start_command}\""; } if ($this->application->install_command) { $nixpacks_command .= " --install-cmd \"{$this->application->install_command}\""; } $nixpacks_command .= " {$this->workdir}"; return $nixpacks_command; } private function generate_nixpacks_env_variables() { $this->env_nixpacks_args = collect([]); if ($this->pull_request_id === 0) { foreach ($this->application->nixpacks_environment_variables as $env) { if (! is_null($env->real_value) && $env->real_value !== '') { $this->env_nixpacks_args->push("--env {$env->key}={$env->real_value}"); } } } else { foreach ($this->application->nixpacks_environment_variables_preview as $env) { if (! is_null($env->real_value) && $env->real_value !== '') { $this->env_nixpacks_args->push("--env {$env->key}={$env->real_value}"); } } } // Add COOLIFY_* environment variables to Nixpacks build context $coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true); $coolify_envs->each(function ($value, $key) { // Only add environment variables with non-null and non-empty values if (! is_null($value) && $value !== '') { $this->env_nixpacks_args->push("--env {$key}={$value}"); } }); $this->env_nixpacks_args = $this->env_nixpacks_args->implode(' '); } private function generate_coolify_env_variables(bool $forBuildTime = false): Collection { $coolify_envs = collect([]); $local_branch = $this->branch; if ($this->pull_request_id !== 0) { // Only add SOURCE_COMMIT for runtime OR when explicitly enabled for build-time // SOURCE_COMMIT changes with each commit and breaks Docker cache if included in build if (! $forBuildTime || $this->application->settings->include_source_commit_in_build) { if ($this->application->environment_variables_preview->where('key', 'SOURCE_COMMIT')->isEmpty()) { if (! is_null($this->commit)) { $coolify_envs->put('SOURCE_COMMIT', $this->commit); } else { $coolify_envs->put('SOURCE_COMMIT', 'unknown'); } } } if ($this->application->environment_variables_preview->where('key', 'COOLIFY_FQDN')->isEmpty()) { if ((int) $this->application->compose_parsing_version >= 3) { $coolify_envs->put('COOLIFY_URL', $this->preview->fqdn); } else { $coolify_envs->put('COOLIFY_FQDN', $this->preview->fqdn); } } if ($this->application->environment_variables_preview->where('key', 'COOLIFY_URL')->isEmpty()) { $url = str($this->preview->fqdn)->replace('http://', '')->replace('https://', ''); if ((int) $this->application->compose_parsing_version >= 3) { $coolify_envs->put('COOLIFY_FQDN', $url); } else { $coolify_envs->put('COOLIFY_URL', $url); } } if ($this->application->build_pack !== 'dockercompose' || $this->application->compose_parsing_version === '1' || $this->application->compose_parsing_version === '2') { if ($this->application->environment_variables_preview->where('key', 'COOLIFY_BRANCH')->isEmpty()) { $coolify_envs->put('COOLIFY_BRANCH', $local_branch); } if ($this->application->environment_variables_preview->where('key', 'COOLIFY_RESOURCE_UUID')->isEmpty()) { $coolify_envs->put('COOLIFY_RESOURCE_UUID', $this->application->uuid); } // Only add COOLIFY_CONTAINER_NAME for runtime (not build-time) - it changes every deployment and breaks Docker cache if (! $forBuildTime) { if ($this->application->environment_variables_preview->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) { $coolify_envs->put('COOLIFY_CONTAINER_NAME', $this->container_name); } } } add_coolify_default_environment_variables($this->application, $coolify_envs, $this->application->environment_variables_preview); } else { // Only add SOURCE_COMMIT for runtime OR when explicitly enabled for build-time // SOURCE_COMMIT changes with each commit and breaks Docker cache if included in build if (! $forBuildTime || $this->application->settings->include_source_commit_in_build) { if ($this->application->environment_variables->where('key', 'SOURCE_COMMIT')->isEmpty()) { if (! is_null($this->commit)) { $coolify_envs->put('SOURCE_COMMIT', $this->commit); } else { $coolify_envs->put('SOURCE_COMMIT', 'unknown'); } } } if ($this->application->environment_variables->where('key', 'COOLIFY_FQDN')->isEmpty()) { if ((int) $this->application->compose_parsing_version >= 3) { $coolify_envs->put('COOLIFY_URL', $this->application->fqdn); } else { $coolify_envs->put('COOLIFY_FQDN', $this->application->fqdn); } } if ($this->application->environment_variables->where('key', 'COOLIFY_URL')->isEmpty()) { $url = str($this->application->fqdn)->replace('http://', '')->replace('https://', ''); if ((int) $this->application->compose_parsing_version >= 3) { $coolify_envs->put('COOLIFY_FQDN', $url); } else { $coolify_envs->put('COOLIFY_URL', $url); } } if ($this->application->build_pack !== 'dockercompose' || $this->application->compose_parsing_version === '1' || $this->application->compose_parsing_version === '2') { if ($this->application->environment_variables->where('key', 'COOLIFY_BRANCH')->isEmpty()) { $coolify_envs->put('COOLIFY_BRANCH', $local_branch); } if ($this->application->environment_variables->where('key', 'COOLIFY_RESOURCE_UUID')->isEmpty()) { $coolify_envs->put('COOLIFY_RESOURCE_UUID', $this->application->uuid); } // Only add COOLIFY_CONTAINER_NAME for runtime (not build-time) - it changes every deployment and breaks Docker cache if (! $forBuildTime) { if ($this->application->environment_variables->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) { $coolify_envs->put('COOLIFY_CONTAINER_NAME', $this->container_name); } } } add_coolify_default_environment_variables($this->application, $coolify_envs, $this->application->environment_variables); } return $coolify_envs; } private function generate_env_variables() { $this->env_args = collect([]); // Only include SOURCE_COMMIT in build args if enabled in settings if ($this->application->settings->include_source_commit_in_build) { $this->env_args->put('SOURCE_COMMIT', $this->commit); } $coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true); $coolify_envs->each(function ($value, $key) { if (! is_null($value) && $value !== '') { $this->env_args->put($key, $value); } }); // For build process, include only environment variables where is_buildtime = true if ($this->pull_request_id === 0) { $envs = $this->application->environment_variables() ->where('key', 'not like', 'NIXPACKS_%') ->where('is_buildtime', true) ->get(); foreach ($envs as $env) { if (! is_null($env->real_value)) { $this->env_args->put($env->key, $env->real_value); } } } else { $envs = $this->application->environment_variables_preview() ->where('key', 'not like', 'NIXPACKS_%') ->where('is_buildtime', true) ->get(); foreach ($envs as $env) { if (! is_null($env->real_value)) { $this->env_args->put($env->key, $env->real_value); } } } } private function generate_compose_file() { $this->checkForCancellation(); $this->create_workdir(); $ports = $this->application->main_port(); $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->application->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); if (data_get($this->application, 'custom_labels')) { $this->application->parseContainerLabels(); $labels = collect(preg_split("/\r\n|\n|\r/", base64_decode($this->application->custom_labels))); $labels = $labels->filter(function ($value, $key) { return ! Str::startsWith($value, 'coolify.'); }); $this->application->custom_labels = base64_encode($labels->implode("\n")); $this->application->save(); } else { if ($this->application->settings->is_container_label_readonly_enabled) { $labels = collect(generateLabelsApplication($this->application, $this->preview)); } } if ($this->pull_request_id !== 0) { $labels = collect(generateLabelsApplication($this->application, $this->preview)); } if ($this->application->settings->is_container_label_escape_enabled) { $labels = $labels->map(function ($value, $key) { return escapeDollarSign($value); }); } $labels = $labels->merge(defaultLabels($this->application->id, $this->application->uuid, $this->application->project()->name, $this->application->name, $this->application->environment->name, $this->pull_request_id))->toArray(); // Check for custom HEALTHCHECK if ($this->application->build_pack === 'dockerfile' || $this->application->dockerfile) { $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'save' => 'dockerfile_from_repo', 'ignore_errors' => true, ]); $this->application->parseHealthcheckFromDockerfile($this->saved_outputs->get('dockerfile_from_repo')); } $custom_network_aliases = []; if (! empty($this->application->custom_network_aliases_array)) { $custom_network_aliases = $this->application->custom_network_aliases_array; } $docker_compose = [ 'services' => [ $this->container_name => [ 'image' => $this->production_image_name, 'container_name' => $this->container_name, 'restart' => RESTART_MODE, 'expose' => $ports, 'networks' => [ $this->destination->network => [ 'aliases' => array_merge( [$this->container_name], $custom_network_aliases ), ], ], 'mem_limit' => $this->application->limits_memory, 'memswap_limit' => $this->application->limits_memory_swap, 'mem_swappiness' => $this->application->limits_memory_swappiness, 'mem_reservation' => $this->application->limits_memory_reservation, 'cpus' => (float) $this->application->limits_cpus, 'cpu_shares' => $this->application->limits_cpu_shares, ], ], 'networks' => [ $this->destination->network => [ 'external' => true, 'name' => $this->destination->network, 'attachable' => true, ], ], ]; // Always use .env file $docker_compose['services'][$this->container_name]['env_file'] = ['.env']; // Only add Coolify healthcheck if no custom HEALTHCHECK found in Dockerfile // If custom_healthcheck_found is true, the Dockerfile's HEALTHCHECK will be used // If healthcheck is disabled, no healthcheck will be added if (! $this->application->custom_healthcheck_found && ! $this->application->isHealthcheckDisabled()) { $docker_compose['services'][$this->container_name]['healthcheck'] = [ 'test' => [ 'CMD-SHELL', $this->generate_healthcheck_commands(), ], 'interval' => $this->application->health_check_interval.'s', 'timeout' => $this->application->health_check_timeout.'s', 'retries' => $this->application->health_check_retries, 'start_period' => $this->application->health_check_start_period.'s', ]; } if (! is_null($this->application->limits_cpuset)) { data_set($docker_compose, 'services.'.$this->container_name.'.cpuset', $this->application->limits_cpuset); } if ($this->mainServer->isSwarm()) { data_forget($docker_compose, 'services.'.$this->container_name.'.container_name'); data_forget($docker_compose, 'services.'.$this->container_name.'.expose'); data_forget($docker_compose, 'services.'.$this->container_name.'.restart'); data_forget($docker_compose, 'services.'.$this->container_name.'.mem_limit'); data_forget($docker_compose, 'services.'.$this->container_name.'.memswap_limit'); data_forget($docker_compose, 'services.'.$this->container_name.'.mem_swappiness'); data_forget($docker_compose, 'services.'.$this->container_name.'.mem_reservation'); data_forget($docker_compose, 'services.'.$this->container_name.'.cpus'); data_forget($docker_compose, 'services.'.$this->container_name.'.cpuset'); data_forget($docker_compose, 'services.'.$this->container_name.'.cpu_shares'); $docker_compose['services'][$this->container_name]['deploy'] = [ 'mode' => 'replicated', 'replicas' => data_get($this->application, 'swarm_replicas', 1), 'update_config' => [ 'order' => 'start-first', ], 'rollback_config' => [ 'order' => 'start-first', ], 'labels' => $labels, 'resources' => [ 'limits' => [ 'cpus' => $this->application->limits_cpus, 'memory' => $this->application->limits_memory, ], 'reservations' => [ 'cpus' => $this->application->limits_cpus, 'memory' => $this->application->limits_memory, ], ], ]; if (data_get($this->application, 'swarm_placement_constraints')) { $swarm_placement_constraints = Yaml::parse(base64_decode(data_get($this->application, 'swarm_placement_constraints'))); $docker_compose['services'][$this->container_name]['deploy'] = array_merge( $docker_compose['services'][$this->container_name]['deploy'], $swarm_placement_constraints ); } if (data_get($this->application, 'settings.is_swarm_only_worker_nodes')) { $docker_compose['services'][$this->container_name]['deploy']['placement']['constraints'][] = 'node.role == worker'; } if ($this->pull_request_id !== 0) { $docker_compose['services'][$this->container_name]['deploy']['replicas'] = 1; } } else { $docker_compose['services'][$this->container_name]['labels'] = $labels; } if ($this->mainServer->isLogDrainEnabled() && $this->application->isLogDrainEnabled()) { $docker_compose['services'][$this->container_name]['logging'] = generate_fluentd_configuration(); } if ($this->application->settings->is_gpu_enabled) { $docker_compose['services'][$this->container_name]['deploy']['resources']['reservations']['devices'] = [ [ 'driver' => data_get($this->application, 'settings.gpu_driver', 'nvidia'), 'capabilities' => ['gpu'], 'options' => data_get($this->application, 'settings.gpu_options', []), ], ]; if (data_get($this->application, 'settings.gpu_count')) { $count = data_get($this->application, 'settings.gpu_count'); if ($count === 'all') { $docker_compose['services'][$this->container_name]['deploy']['resources']['reservations']['devices'][0]['count'] = $count; } else { $docker_compose['services'][$this->container_name]['deploy']['resources']['reservations']['devices'][0]['count'] = (int) $count; } } elseif (data_get($this->application, 'settings.gpu_device_ids')) { $docker_compose['services'][$this->container_name]['deploy']['resources']['reservations']['devices'][0]['ids'] = data_get($this->application, 'settings.gpu_device_ids'); } } if ($this->application->isHealthcheckDisabled()) { data_forget($docker_compose, 'services.'.$this->container_name.'.healthcheck'); } if (count($this->application->ports_mappings_array) > 0 && $this->pull_request_id === 0) { $docker_compose['services'][$this->container_name]['ports'] = $this->application->ports_mappings_array; } if (count($persistent_storages) > 0) { if (! data_get($docker_compose, 'services.'.$this->container_name.'.volumes')) { $docker_compose['services'][$this->container_name]['volumes'] = []; } $docker_compose['services'][$this->container_name]['volumes'] = array_merge($docker_compose['services'][$this->container_name]['volumes'], $persistent_storages); } if (count($persistent_file_volumes) > 0) { if (! data_get($docker_compose, 'services.'.$this->container_name.'.volumes')) { $docker_compose['services'][$this->container_name]['volumes'] = []; } $docker_compose['services'][$this->container_name]['volumes'] = array_merge($docker_compose['services'][$this->container_name]['volumes'], $persistent_file_volumes->map(function ($item) { return "$item->fs_path:$item->mount_path"; })->toArray()); } if (count($volume_names) > 0) { $docker_compose['volumes'] = $volume_names; } if ($this->pull_request_id === 0) { $custom_compose = convertDockerRunToCompose($this->application->custom_docker_run_options); if ((bool) $this->application->settings->is_consistent_container_name_enabled) { if (! $this->application->settings->custom_internal_name) { $docker_compose['services'][$this->application->uuid] = $docker_compose['services'][$this->container_name]; if (count($custom_compose) > 0) { $ipv4 = data_get($custom_compose, 'ip.0'); $ipv6 = data_get($custom_compose, 'ip6.0'); data_forget($custom_compose, 'ip'); data_forget($custom_compose, 'ip6'); if ($ipv4 || $ipv6) { data_forget($docker_compose['services'][$this->application->uuid], 'networks'); } if ($ipv4) { $docker_compose['services'][$this->application->uuid]['networks'][$this->destination->network]['ipv4_address'] = $ipv4; } if ($ipv6) { $docker_compose['services'][$this->application->uuid]['networks'][$this->destination->network]['ipv6_address'] = $ipv6; } $docker_compose['services'][$this->application->uuid] = array_merge_recursive($docker_compose['services'][$this->application->uuid], $custom_compose); } } } else { if (count($custom_compose) > 0) { $ipv4 = data_get($custom_compose, 'ip.0'); $ipv6 = data_get($custom_compose, 'ip6.0'); data_forget($custom_compose, 'ip'); data_forget($custom_compose, 'ip6'); if ($ipv4 || $ipv6) { data_forget($docker_compose['services'][$this->container_name], 'networks'); } if ($ipv4) { $docker_compose['services'][$this->container_name]['networks'][$this->destination->network]['ipv4_address'] = $ipv4; } if ($ipv6) { $docker_compose['services'][$this->container_name]['networks'][$this->destination->network]['ipv6_address'] = $ipv6; } $docker_compose['services'][$this->container_name] = array_merge_recursive($docker_compose['services'][$this->container_name], $custom_compose); } } } $this->docker_compose = Yaml::dump($docker_compose, 10); $this->docker_compose_base64 = base64_encode($this->docker_compose); $this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d | tee {$this->workdir}/docker-compose.yaml > /dev/null"), 'hidden' => true]); } private function generate_local_persistent_volumes() { $local_persistent_volumes = []; foreach ($this->application->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path !== '' && $persistentStorage->host_path !== null) { $volume_name = $persistentStorage->host_path; } else { $volume_name = $persistentStorage->name; } if ($this->pull_request_id !== 0) { $volume_name = addPreviewDeploymentSuffix($volume_name, $this->pull_request_id); } $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; } return $local_persistent_volumes; } private function generate_local_persistent_volumes_only_volume_names() { $local_persistent_volumes_names = []; foreach ($this->application->persistentStorages as $persistentStorage) { if ($persistentStorage->host_path) { continue; } $name = $persistentStorage->name; if ($this->pull_request_id !== 0) { $name = addPreviewDeploymentSuffix($name, $this->pull_request_id); } $local_persistent_volumes_names[$name] = [ 'name' => $name, 'external' => false, ]; } return $local_persistent_volumes_names; } private function generate_healthcheck_commands() { // Handle CMD type healthcheck if ($this->application->health_check_type === 'cmd' && ! empty($this->application->health_check_command)) { $command = str_replace(["\r\n", "\r", "\n"], ' ', $this->application->health_check_command); $this->full_healthcheck_url = $command; return $command; } // HTTP type healthcheck (default) if (! $this->application->health_check_port) { $health_check_port = (int) $this->application->ports_exposes_array[0]; } else { $health_check_port = (int) $this->application->health_check_port; } if ($this->application->settings->is_static || $this->application->build_pack === 'static') { $health_check_port = 80; } $method = $this->sanitizeHealthCheckValue($this->application->health_check_method, '/^[A-Z]+$/', 'GET'); $scheme = $this->sanitizeHealthCheckValue($this->application->health_check_scheme, '/^https?$/', 'http'); $host = $this->sanitizeHealthCheckValue($this->application->health_check_host, '/^[a-zA-Z0-9.\-_]+$/', 'localhost'); $path = $this->application->health_check_path ? $this->sanitizeHealthCheckValue($this->application->health_check_path, '#^[a-zA-Z0-9/\-_.~%]+$#', '/') : null; $url = escapeshellarg("{$scheme}://{$host}:{$health_check_port}".($path ?? '/')); $method = escapeshellarg($method); if ($path) { $this->full_healthcheck_url = "{$this->application->health_check_method}: {$scheme}://{$host}:{$health_check_port}{$path}"; } else { $this->full_healthcheck_url = "{$this->application->health_check_method}: {$scheme}://{$host}:{$health_check_port}/"; } $generated_healthchecks_commands = [ "curl -s -X {$method} -f {$url} > /dev/null || wget -q -O- {$url} > /dev/null || exit 1", ]; return implode(' ', $generated_healthchecks_commands); } private function sanitizeHealthCheckValue(string $value, string $pattern, string $default): string { if (preg_match($pattern, $value)) { return $value; } return $default; } private function pull_latest_image($image) { $this->application_deployment_queue->addLogEntry("Pulling latest image ($image) from the registry."); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "docker pull {$image}"), 'hidden' => true, ] ); } private function build_static_image() { $this->application_deployment_queue->addLogEntry('----------------------------------------'); $this->application_deployment_queue->addLogEntry('Static deployment. Copying static assets to the image.'); if ($this->application->static_image) { $this->pull_latest_image($this->application->static_image); } $dockerfile = base64_encode("FROM {$this->application->static_image} WORKDIR /usr/share/nginx/html/ LABEL coolify.deploymentId={$this->deployment_uuid} COPY . . RUN rm -f /usr/share/nginx/html/nginx.conf RUN rm -f /usr/share/nginx/html/Dockerfile RUN rm -f /usr/share/nginx/html/docker-compose.yaml RUN rm -f /usr/share/nginx/html/.env COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); if (str($this->application->custom_nginx_configuration)->isNotEmpty()) { $nginx_config = base64_encode($this->application->custom_nginx_configuration); } else { if ($this->application->settings->is_spa) { $nginx_config = base64_encode(defaultNginxConfiguration('spa')); } else { $nginx_config = base64_encode(defaultNginxConfiguration()); } } if ($this->dockerBuildkitSupported) { $build_command = "DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile --progress plain -t {$this->production_image_name} {$this->workdir}"; } else { $build_command = "docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile -t {$this->production_image_name} {$this->workdir}"; } $base64_build_command = base64_encode($build_command); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$dockerfile}' | base64 -d | tee {$this->workdir}/Dockerfile > /dev/null"), ], [ executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d | tee {$this->workdir}/nginx.conf > /dev/null"), ], [ executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ] ); $this->application_deployment_queue->addLogEntry('Building docker image completed.'); } /** * Wrap a docker build command with environment export from build-time .env file * This enables shell interpolation of variables (e.g., APP_URL=$COOLIFY_URL) * * @param string $build_command The docker build command to wrap * @return string The wrapped command with export statement */ private function wrap_build_command_with_env_export(string $build_command): string { return "cd {$this->workdir} && set -a && source ".self::BUILD_TIME_ENV_PATH." && set +a && {$build_command}"; } private function build_image() { // Add Coolify related variables to the build args/secrets if (! $this->dockerSecretsSupported) { // Traditional build args approach - generate COOLIFY_ variables locally $coolify_envs = $this->generate_coolify_env_variables(forBuildTime: true); $coolify_envs->each(function ($value, $key) { $this->build_args->push("--build-arg '{$key}'"); }); } // Always convert build_args Collection to string for command interpolation $this->build_args = $this->build_args instanceof \Illuminate\Support\Collection ? $this->build_args->implode(' ') : (string) $this->build_args; $this->application_deployment_queue->addLogEntry('----------------------------------------'); if ($this->disableBuildCache) { $this->application_deployment_queue->addLogEntry('Docker build cache is disabled. It will not be used during the build process.'); } if ($this->application->build_pack === 'static') { $this->application_deployment_queue->addLogEntry('Static deployment. Copying static assets to the image.'); } else { $this->application_deployment_queue->addLogEntry('Building docker image started.'); $this->application_deployment_queue->addLogEntry('To check the current progress, click on Show Debug Logs.'); } if ($this->application->settings->is_static) { if ($this->application->static_image) { $this->pull_latest_image($this->application->static_image); $this->application_deployment_queue->addLogEntry('Continuing with the building process.'); } if ($this->application->build_pack === 'nixpacks') { $this->nixpacks_plan = base64_encode($this->nixpacks_plan); $this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d | tee ".self::NIXPACKS_PLAN_PATH.' > /dev/null'), 'hidden' => true]); if ($this->force_rebuild) { $this->execute_remote_command([ executeInDocker($this->deployment_uuid, 'nixpacks build -c '.self::NIXPACKS_PLAN_PATH." --no-cache --no-error-without-start -n {$this->build_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, "cat {$this->workdir}/.nixpacks/Dockerfile"), 'hidden' => true, ]); if ($this->dockerSecretsSupported) { // Modify the nixpacks Dockerfile to use build secrets $this->modify_dockerfile_for_secrets("{$this->workdir}/.nixpacks/Dockerfile"); $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile{$secrets_flags} --progress plain -t {$this->build_image_name} {$this->workdir}"); } elseif ($this->dockerBuildkitSupported) { // BuildKit without secrets $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile --progress plain -t {$this->build_image_name} {$this->build_args} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build --no-cache {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile -t {$this->build_image_name} {$this->build_args} {$this->workdir}"); } } else { $this->execute_remote_command([ executeInDocker($this->deployment_uuid, 'nixpacks build -c '.self::NIXPACKS_PLAN_PATH." --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->build_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, "cat {$this->workdir}/.nixpacks/Dockerfile"), 'hidden' => true, ]); if ($this->dockerSecretsSupported) { // Modify the nixpacks Dockerfile to use build secrets $this->modify_dockerfile_for_secrets("{$this->workdir}/.nixpacks/Dockerfile"); $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile{$secrets_flags} --progress plain -t {$this->build_image_name} {$this->workdir}"); } elseif ($this->dockerBuildkitSupported) { // BuildKit without secrets $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile --progress plain -t {$this->build_image_name} {$this->build_args} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile -t {$this->build_image_name} {$this->build_args} {$this->workdir}"); } } $base64_build_command = base64_encode($build_command); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ] ); $this->execute_remote_command([executeInDocker($this->deployment_uuid, 'rm '.self::NIXPACKS_PLAN_PATH), 'hidden' => true]); } else { // Dockerfile buildpack if ($this->dockerSecretsSupported) { // Modify the Dockerfile to use build secrets $this->modify_dockerfile_for_secrets("{$this->workdir}{$this->dockerfile_location}"); $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location}{$secrets_flags} --progress plain -t $this->build_image_name {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location}{$secrets_flags} --progress plain -t $this->build_image_name {$this->workdir}"); } } elseif ($this->dockerBuildkitSupported) { // BuildKit without secrets if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} --progress plain -t $this->build_image_name {$this->build_args} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} --progress plain -t $this->build_image_name {$this->build_args} {$this->workdir}"); } } else { // Traditional build with args if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("docker build --no-cache {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} -t $this->build_image_name {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} -t $this->build_image_name {$this->workdir}"); } } $base64_build_command = base64_encode($build_command); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ] ); } $publishDir = trim($this->application->publish_directory, '/'); $publishDir = $publishDir ? "/{$publishDir}" : ''; $dockerfile = base64_encode("FROM {$this->application->static_image} WORKDIR /usr/share/nginx/html/ LABEL coolify.deploymentId={$this->deployment_uuid} COPY --from=$this->build_image_name /app{$publishDir} . COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); if (str($this->application->custom_nginx_configuration)->isNotEmpty()) { $nginx_config = base64_encode($this->application->custom_nginx_configuration); } else { if ($this->application->settings->is_spa) { $nginx_config = base64_encode(defaultNginxConfiguration('spa')); } else { $nginx_config = base64_encode(defaultNginxConfiguration()); } } if ($this->dockerBuildkitSupported) { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile {$this->build_args} -t {$this->production_image_name} {$this->workdir}"); } $base64_build_command = base64_encode($build_command); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$dockerfile}' | base64 -d | tee {$this->workdir}/Dockerfile > /dev/null"), ], [ executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d | tee {$this->workdir}/nginx.conf > /dev/null"), ], [ executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ] ); } else { // Pure Dockerfile based deployment if ($this->application->dockerfile) { if ($this->dockerSecretsSupported) { // Modify the Dockerfile to use build secrets $this->modify_dockerfile_for_secrets("{$this->workdir}{$this->dockerfile_location}"); $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; if ($this->force_rebuild) { $build_command = "DOCKER_BUILDKIT=1 docker build --no-cache --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location}{$secrets_flags} --progress plain -t {$this->production_image_name} {$this->workdir}"; } else { $build_command = "DOCKER_BUILDKIT=1 docker build --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location}{$secrets_flags} --progress plain -t {$this->production_image_name} {$this->workdir}"; } } elseif ($this->dockerBuildkitSupported) { // BuildKit without secrets if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} --progress plain -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} --progress plain -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } } else { // Traditional build with args (no --progress for legacy builder compatibility) if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("docker build --no-cache --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} -t {$this->production_image_name} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} -t {$this->production_image_name} {$this->workdir}"); } } $base64_build_command = base64_encode($build_command); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ] ); } else { if ($this->application->build_pack === 'nixpacks') { $this->nixpacks_plan = base64_encode($this->nixpacks_plan); $this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d | tee ".self::NIXPACKS_PLAN_PATH.' > /dev/null'), 'hidden' => true]); if ($this->force_rebuild) { $this->execute_remote_command([ executeInDocker($this->deployment_uuid, 'nixpacks build -c '.self::NIXPACKS_PLAN_PATH." --no-cache --no-error-without-start -n {$this->production_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, "cat {$this->workdir}/.nixpacks/Dockerfile"), 'hidden' => true, ]); if ($this->dockerSecretsSupported) { // Modify the nixpacks Dockerfile to use build secrets $this->modify_dockerfile_for_secrets("{$this->workdir}/.nixpacks/Dockerfile"); $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile{$secrets_flags} --progress plain -t {$this->production_image_name} {$this->workdir}"); } elseif ($this->dockerBuildkitSupported) { // BuildKit without secrets $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile --progress plain -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build --no-cache {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } } else { $this->execute_remote_command([ executeInDocker($this->deployment_uuid, 'nixpacks build -c '.self::NIXPACKS_PLAN_PATH." --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->production_image_name} {$this->workdir} -o {$this->workdir}"), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, "cat {$this->workdir}/.nixpacks/Dockerfile"), 'hidden' => true, ]); if ($this->dockerSecretsSupported) { // Modify the nixpacks Dockerfile to use build secrets $this->modify_dockerfile_for_secrets("{$this->workdir}/.nixpacks/Dockerfile"); $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile{$secrets_flags} --progress plain -t {$this->production_image_name} {$this->workdir}"); } elseif ($this->dockerBuildkitSupported) { // BuildKit without secrets $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile --progress plain -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build {$this->addHosts} --network host -f {$this->workdir}/.nixpacks/Dockerfile -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } } $base64_build_command = base64_encode($build_command); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ] ); $this->execute_remote_command([executeInDocker($this->deployment_uuid, 'rm '.self::NIXPACKS_PLAN_PATH), 'hidden' => true]); } else { // Dockerfile buildpack if ($this->dockerSecretsSupported) { // Modify the Dockerfile to use build secrets $this->modify_dockerfile_for_secrets("{$this->workdir}{$this->dockerfile_location}"); // Use BuildKit with secrets $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location}{$secrets_flags} --progress plain -t {$this->production_image_name} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location}{$secrets_flags} --progress plain -t {$this->production_image_name} {$this->workdir}"); } } elseif ($this->dockerBuildkitSupported) { // BuildKit without secrets if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build --no-cache {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} --progress plain -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("DOCKER_BUILDKIT=1 docker build {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} --progress plain -t {$this->production_image_name} {$this->build_args} {$this->workdir}"); } } else { // Traditional build with args if ($this->force_rebuild) { $build_command = $this->wrap_build_command_with_env_export("docker build --no-cache {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} -t {$this->production_image_name} {$this->workdir}"); } else { $build_command = $this->wrap_build_command_with_env_export("docker build {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} -t {$this->production_image_name} {$this->workdir}"); } } $base64_build_command = base64_encode($build_command); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true, ] ); } } } $this->application_deployment_queue->addLogEntry('Building docker image completed.'); } private function graceful_shutdown_container(string $containerName, bool $skipRemove = false) { try { $timeout = isDev() ? 1 : 30; if ($skipRemove) { $this->execute_remote_command( ["docker stop -t $timeout $containerName", 'hidden' => true, 'ignore_errors' => true] ); } else { $this->execute_remote_command( ["docker stop -t $timeout $containerName", 'hidden' => true, 'ignore_errors' => true], ["docker rm -f $containerName", 'hidden' => true, 'ignore_errors' => true] ); } } catch (Exception $error) { $this->application_deployment_queue->addLogEntry("Error stopping container $containerName: ".$error->getMessage(), 'stderr'); } } private function stop_running_container(bool $force = false) { try { $this->application_deployment_queue->addLogEntry('Removing old containers.'); if ($this->newVersionIsHealthy || $force) { if ($this->application->settings->is_consistent_container_name_enabled || str($this->application->settings->custom_internal_name)->isNotEmpty()) { $this->graceful_shutdown_container($this->container_name); } else { $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id); if ($this->pull_request_id === 0) { $containers = $containers->filter(function ($container) { return data_get($container, 'Names') !== $this->container_name && data_get($container, 'Names') !== addPreviewDeploymentSuffix($this->container_name, $this->pull_request_id); }); } $containers->each(function ($container) { $this->graceful_shutdown_container(data_get($container, 'Names')); }); } } else { if ($this->application->dockerfile || $this->application->build_pack === 'dockerfile' || $this->application->build_pack === 'dockerimage') { $this->application_deployment_queue->addLogEntry('----------------------------------------'); $this->application_deployment_queue->addLogEntry("WARNING: Dockerfile or Docker Image based deployment detected. The healthcheck needs a curl or wget command to check the health of the application. Please make sure that it is available in the image or turn off healthcheck on Coolify's UI."); $this->application_deployment_queue->addLogEntry('----------------------------------------'); } $this->application_deployment_queue->addLogEntry('New container is not healthy, rolling back to the old container.'); $this->failDeployment(); $this->graceful_shutdown_container($this->container_name); } } catch (Exception $e) { // If new version is healthy, this is just cleanup - don't fail the deployment if ($this->newVersionIsHealthy || $force) { $this->application_deployment_queue->addLogEntry( "Warning: Could not remove old container: {$e->getMessage()}", 'stderr', hidden: true ); return; // Don't re-throw - cleanup failures shouldn't fail successful deployments } // Only re-throw if deployment hasn't succeeded yet throw new DeploymentException("Failed to stop running container: {$e->getMessage()}", $e->getCode(), $e); } } private function start_by_compose_file() { try { // Ensure .env file exists before docker compose tries to load it (defensive programming) $this->execute_remote_command( ["touch {$this->configuration_dir}/.env", 'hidden' => true], ); if ($this->application->build_pack === 'dockerimage') { $this->application_deployment_queue->addLogEntry('Pulling latest images from the registry.'); $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} pull"), 'hidden' => true], [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} up --build -d"), 'hidden' => true], ); } else { if ($this->use_build_server) { $this->execute_remote_command( ["{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->configuration_dir} -f {$this->configuration_dir}{$this->docker_compose_location} up --pull always --build -d", 'hidden' => true], ); } else { $this->execute_remote_command( [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up --build -d"), 'hidden' => true], ); } } $this->application_deployment_queue->addLogEntry('New container started.'); } catch (Exception $e) { throw new DeploymentException("Failed to start container: {$e->getMessage()}", $e->getCode(), $e); } } private function analyzeBuildTimeVariables($variables) { $userDefinedVariables = collect([]); $dbVariables = $this->pull_request_id === 0 ? $this->application->environment_variables() ->where('is_buildtime', true) ->pluck('key') : $this->application->environment_variables_preview() ->where('is_buildtime', true) ->pluck('key'); foreach ($variables as $key => $value) { if ($dbVariables->contains($key)) { $userDefinedVariables->put($key, $value); } } if ($userDefinedVariables->isEmpty()) { return; } $variablesArray = $userDefinedVariables->toArray(); $warnings = self::analyzeBuildVariables($variablesArray); if (empty($warnings)) { return; } $this->application_deployment_queue->addLogEntry('----------------------------------------'); foreach ($warnings as $warning) { $messages = self::formatBuildWarning($warning); foreach ($messages as $message) { $this->application_deployment_queue->addLogEntry($message, type: 'warning'); } $this->application_deployment_queue->addLogEntry(''); } // Add general advice $this->application_deployment_queue->addLogEntry('💡 Tips to resolve build issues:', type: 'info'); $this->application_deployment_queue->addLogEntry(' 1. Set these variables as "Runtime only" in the environment variables settings', type: 'info'); $this->application_deployment_queue->addLogEntry(' 2. Use different values for build-time (e.g., NODE_ENV=development for build)', type: 'info'); $this->application_deployment_queue->addLogEntry(' 3. Consider using multi-stage Docker builds to separate build and runtime environments', type: 'info'); } private function generate_build_env_variables() { if ($this->application->build_pack === 'nixpacks') { $variables = collect($this->nixpacks_plan_json->get('variables')); } else { $this->generate_env_variables(); $variables = collect([])->merge($this->env_args); } // Analyze build variables for potential issues if ($variables->isNotEmpty()) { $this->analyzeBuildTimeVariables($variables); } if ($this->dockerSecretsSupported) { $this->generate_build_secrets($variables); $this->build_args = ''; } else { $secrets_hash = ''; if ($variables->isNotEmpty()) { $secrets_hash = $this->generate_secrets_hash($variables); } $env_vars = $this->pull_request_id === 0 ? $this->application->environment_variables()->where('is_buildtime', true)->get() : $this->application->environment_variables_preview()->where('is_buildtime', true)->get(); // Map variables to include is_multiline flag $vars_with_metadata = $variables->map(function ($value, $key) use ($env_vars) { $env = $env_vars->firstWhere('key', $key); return [ 'key' => $key, 'value' => $value, 'is_multiline' => $env ? $env->is_multiline : false, ]; }); $this->build_args = generateDockerBuildArgs($vars_with_metadata); if ($secrets_hash) { $this->build_args->push("--build-arg COOLIFY_BUILD_SECRETS_HASH={$secrets_hash}"); } } } private function generate_docker_env_flags_for_secrets() { // Only generate env flags if build secrets are enabled if (! $this->application->settings->use_build_secrets) { return ''; } // Generate env variables if not already done // This populates $this->env_args with both user-defined and COOLIFY_* variables if (! $this->env_args || $this->env_args->isEmpty()) { $this->generate_env_variables(); } $variables = $this->env_args; if ($variables->isEmpty()) { return ''; } $secrets_hash = $this->generate_secrets_hash($variables); // Get database env vars to check for multiline flag $env_vars = $this->pull_request_id === 0 ? $this->application->environment_variables()->where('is_buildtime', true)->get() : $this->application->environment_variables_preview()->where('is_buildtime', true)->get(); // Map to simple array format for the helper function $vars_array = $variables->map(function ($value, $key) use ($env_vars) { $env = $env_vars->firstWhere('key', $key); return [ 'key' => $key, 'value' => $value, 'is_multiline' => $env ? $env->is_multiline : false, ]; }); $env_flags = generateDockerEnvFlags($vars_array); $env_flags .= " -e COOLIFY_BUILD_SECRETS_HASH={$secrets_hash}"; return $env_flags; } private function generate_build_secrets(Collection $variables) { if ($variables->isEmpty()) { $this->build_secrets = ''; return; } $this->build_secrets = $variables ->map(function ($value, $key) { return "--secret id={$key},env={$key}"; }) ->implode(' '); $this->build_secrets .= ' --secret id=COOLIFY_BUILD_SECRETS_HASH,env=COOLIFY_BUILD_SECRETS_HASH'; } private function generate_secrets_hash($variables) { if (! $this->secrets_hash_key) { // Use APP_KEY as deterministic hash key to preserve Docker build cache // Random keys would change every deployment, breaking cache even when secrets haven't changed $this->secrets_hash_key = config('app.key'); } if ($variables instanceof Collection) { $secrets_string = $variables ->mapWithKeys(function ($value, $key) { return [$key => $value]; }) ->sortKeys() ->map(function ($value, $key) { return "{$key}={$value}"; }) ->implode('|'); } else { $secrets_string = $variables ->map(function ($env) { return "{$env->key}={$env->real_value}"; }) ->sort() ->implode('|'); } return hash_hmac('sha256', $secrets_string, $this->secrets_hash_key); } protected function findFromInstructionLines($dockerfile): array { $fromLines = []; foreach ($dockerfile as $index => $line) { $trimmedLine = trim($line); // Check if line starts with FROM (case-insensitive) if (preg_match('/^FROM\s+/i', $trimmedLine)) { $fromLines[] = $index; } } return $fromLines; } private function add_build_env_variables_to_dockerfile() { if ($this->dockerSecretsSupported) { // We dont need to add ARG declarations when using Docker build secrets, as variables are passed with --secret flag return; } // Skip ARG injection if disabled by user - preserves Docker build cache if ($this->application->settings->inject_build_args_to_dockerfile === false) { $this->application_deployment_queue->addLogEntry('Skipping Dockerfile ARG injection (disabled in settings).', hidden: true); return; } $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'save' => 'dockerfile', 'ignore_errors' => true, ]); $dockerfile = collect(str($this->saved_outputs->get('dockerfile'))->trim()->explode("\n")); // Find all FROM instruction positions $fromLines = $this->findFromInstructionLines($dockerfile); // If no FROM instructions found, skip ARG insertion if (empty($fromLines)) { return; } // Collect all ARG statements to insert $argsToInsert = collect(); if ($this->pull_request_id === 0) { // Only add environment variables that are available during build $envs = $this->application->environment_variables() ->where('key', 'not like', 'NIXPACKS_%') ->where('is_buildtime', true) ->get(); foreach ($envs as $env) { if (data_get($env, 'is_multiline') === true) { $argsToInsert->push("ARG {$env->key}"); } else { $argsToInsert->push("ARG {$env->key}={$env->real_value}"); } } // Add Coolify variables as ARGs if ($this->coolify_variables) { $coolify_vars = collect(explode(' ', trim($this->coolify_variables))) ->filter() ->map(function ($var) { return "ARG {$var}"; }); $argsToInsert = $argsToInsert->merge($coolify_vars); } } else { // Only add preview environment variables that are available during build $envs = $this->application->environment_variables_preview() ->where('key', 'not like', 'NIXPACKS_%') ->where('is_buildtime', true) ->get(); foreach ($envs as $env) { if (data_get($env, 'is_multiline') === true) { $argsToInsert->push("ARG {$env->key}"); } else { $argsToInsert->push("ARG {$env->key}={$env->real_value}"); } } // Add Coolify variables as ARGs if ($this->coolify_variables) { $coolify_vars = collect(explode(' ', trim($this->coolify_variables))) ->filter() ->map(function ($var) { return "ARG {$var}"; }); $argsToInsert = $argsToInsert->merge($coolify_vars); } } // Development logging to show what ARGs are being injected if (isDev()) { $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); $this->application_deployment_queue->addLogEntry('[DEBUG] Dockerfile ARG Injection'); $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); $this->application_deployment_queue->addLogEntry('[DEBUG] ARGs to inject: '.$argsToInsert->count()); foreach ($argsToInsert as $arg) { // Only show ARG key, not the value (for security) $argKey = str($arg)->after('ARG ')->before('=')->toString(); $this->application_deployment_queue->addLogEntry("[DEBUG] - {$argKey}"); } } // Insert ARGs after each FROM instruction (in reverse order to maintain correct line numbers) if ($argsToInsert->isNotEmpty()) { foreach (array_reverse($fromLines) as $fromLineIndex) { // Insert all ARGs after this FROM instruction foreach ($argsToInsert->reverse() as $arg) { $dockerfile->splice($fromLineIndex + 1, 0, [$arg]); } } $envs_mapped = $envs->mapWithKeys(function ($env) { return [$env->key => $env->real_value]; }); $secrets_hash = $this->generate_secrets_hash($envs_mapped); $argsToInsert->push("ARG COOLIFY_BUILD_SECRETS_HASH={$secrets_hash}"); } $dockerfile_base64 = base64_encode($dockerfile->implode("\n")); $this->application_deployment_queue->addLogEntry('Final Dockerfile:', type: 'info', hidden: true); $this->execute_remote_command( [ executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d | tee {$this->workdir}{$this->dockerfile_location} > /dev/null"), 'hidden' => true, ], [ executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'ignore_errors' => true, ]); } private function modify_dockerfile_for_secrets($dockerfile_path) { // Only process if build secrets are enabled and we have secrets to mount if (! $this->application->settings->use_build_secrets || empty($this->build_secrets)) { return; } // Read the Dockerfile $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "cat {$dockerfile_path}"), 'hidden' => true, 'save' => 'dockerfile_content', ]); $dockerfile = str($this->saved_outputs->get('dockerfile_content'))->trim()->explode("\n"); // Add BuildKit syntax directive if not present if (! str_starts_with($dockerfile->first(), '# syntax=')) { $dockerfile->prepend('# syntax=docker/dockerfile:1'); } // Generate env variables if not already done // This populates $this->env_args with both user-defined and COOLIFY_* variables if (! $this->env_args || $this->env_args->isEmpty()) { $this->generate_env_variables(); } $variables = $this->env_args; if ($variables->isEmpty()) { return; } // Generate mount strings for all secrets $mountStrings = $variables->map(fn ($value, $key) => "--mount=type=secret,id={$key},env={$key}")->implode(' '); // Add mount for the secrets hash to ensure cache invalidation $mountStrings .= ' --mount=type=secret,id=COOLIFY_BUILD_SECRETS_HASH,env=COOLIFY_BUILD_SECRETS_HASH'; $modified = false; $dockerfile = $dockerfile->map(function ($line) use ($mountStrings, &$modified) { $trimmed = ltrim($line); // Skip lines that already have secret mounts or are not RUN commands if (str_contains($line, '--mount=type=secret') || ! str_starts_with($trimmed, 'RUN')) { return $line; } // Add mount strings to RUN command $originalCommand = trim(substr($trimmed, 3)); $modified = true; return "RUN {$mountStrings} {$originalCommand}"; }); if ($modified) { // Write the modified Dockerfile back $dockerfile_base64 = base64_encode($dockerfile->implode("\n")); $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d | tee {$dockerfile_path} > /dev/null"), 'hidden' => true, ]); } } private function modify_dockerfiles_for_compose($composeFile) { if ($this->application->build_pack !== 'dockercompose') { return; } // Skip ARG injection if disabled by user - preserves Docker build cache if ($this->application->settings->inject_build_args_to_dockerfile === false) { $this->application_deployment_queue->addLogEntry('Skipping Docker Compose Dockerfile ARG injection (disabled in settings).', hidden: true); return; } // Generate env variables if not already done // This populates $this->env_args with both user-defined and COOLIFY_* variables if (! $this->env_args || $this->env_args->isEmpty()) { $this->generate_env_variables(); } $variables = $this->env_args; if ($variables->isEmpty()) { $this->application_deployment_queue->addLogEntry('No build-time variables to add to Dockerfiles.'); return; } $services = data_get($composeFile, 'services', []); foreach ($services as $serviceName => $service) { if (! isset($service['build'])) { continue; } $context = '.'; $dockerfile = 'Dockerfile'; if (is_string($service['build'])) { $context = $service['build']; } elseif (is_array($service['build'])) { $context = data_get($service['build'], 'context', '.'); $dockerfile = data_get($service['build'], 'dockerfile', 'Dockerfile'); } $dockerfilePath = rtrim($context, '/').'/'.ltrim($dockerfile, '/'); if (str_starts_with($dockerfilePath, './')) { $dockerfilePath = substr($dockerfilePath, 2); } if (str_starts_with($dockerfilePath, '/')) { $dockerfilePath = substr($dockerfilePath, 1); } $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "test -f {$this->workdir}/{$dockerfilePath} && echo 'exists' || echo 'not found'"), 'hidden' => true, 'save' => 'dockerfile_check_'.$serviceName, ]); if (str($this->saved_outputs->get('dockerfile_check_'.$serviceName))->trim()->toString() !== 'exists') { $this->application_deployment_queue->addLogEntry("Dockerfile not found for service {$serviceName} at {$dockerfilePath}, skipping ARG injection."); continue; } $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "cat {$this->workdir}/{$dockerfilePath}"), 'hidden' => true, 'save' => 'dockerfile_content_'.$serviceName, ]); $dockerfileContent = $this->saved_outputs->get('dockerfile_content_'.$serviceName); if (! $dockerfileContent) { continue; } $dockerfile_lines = collect(str($dockerfileContent)->trim()->explode("\n")); $fromIndices = []; $dockerfile_lines->each(function ($line, $index) use (&$fromIndices) { if (str($line)->trim()->startsWith('FROM')) { $fromIndices[] = $index; } }); if (empty($fromIndices)) { $this->application_deployment_queue->addLogEntry("No FROM instruction found in Dockerfile for service {$serviceName}, skipping."); continue; } $isMultiStage = count($fromIndices) > 1; $argsToAdd = collect([]); foreach ($variables as $key => $value) { $argsToAdd->push("ARG {$key}"); } if ($argsToAdd->isEmpty()) { $this->application_deployment_queue->addLogEntry("Service {$serviceName}: No build-time variables to add."); continue; } // Development logging to show what ARGs are being injected for Docker Compose if (isDev()) { $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); $this->application_deployment_queue->addLogEntry("[DEBUG] Docker Compose ARG Injection - Service: {$serviceName}"); $this->application_deployment_queue->addLogEntry('[DEBUG] ========================================'); $this->application_deployment_queue->addLogEntry('[DEBUG] ARGs to inject: '.$argsToAdd->count()); foreach ($argsToAdd as $arg) { $argKey = str($arg)->after('ARG ')->toString(); $this->application_deployment_queue->addLogEntry("[DEBUG] - {$argKey}"); } } $totalAdded = 0; $offset = 0; foreach ($fromIndices as $stageIndex => $fromIndex) { $adjustedIndex = $fromIndex + $offset; $stageStart = $adjustedIndex + 1; $stageEnd = isset($fromIndices[$stageIndex + 1]) ? $fromIndices[$stageIndex + 1] + $offset : $dockerfile_lines->count(); $existingStageArgs = collect([]); for ($i = $stageStart; $i < $stageEnd; $i++) { $line = $dockerfile_lines->get($i); if (! $line || ! str($line)->trim()->startsWith('ARG')) { break; } $parts = explode(' ', trim($line), 2); if (count($parts) >= 2) { $argPart = $parts[1]; $keyValue = explode('=', $argPart, 2); $existingStageArgs->push($keyValue[0]); } } $stageArgsToAdd = $argsToAdd->filter(function ($arg) use ($existingStageArgs) { $key = str($arg)->after('ARG ')->trim()->toString(); return ! $existingStageArgs->contains($key); }); if ($stageArgsToAdd->isNotEmpty()) { $dockerfile_lines->splice($adjustedIndex + 1, 0, $stageArgsToAdd->toArray()); $totalAdded += $stageArgsToAdd->count(); $offset += $stageArgsToAdd->count(); } } if ($totalAdded > 0) { $dockerfile_base64 = base64_encode($dockerfile_lines->implode("\n")); $this->execute_remote_command([ executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d | tee {$this->workdir}/{$dockerfilePath} > /dev/null"), 'hidden' => true, ]); $stageInfo = $isMultiStage ? ' (multi-stage build, added to '.count($fromIndices).' stages)' : ''; $this->application_deployment_queue->addLogEntry("Added {$totalAdded} ARG declarations to Dockerfile for service {$serviceName}{$stageInfo}."); } else { $this->application_deployment_queue->addLogEntry("Service {$serviceName}: All required ARG declarations already exist."); } if ($this->dockerSecretsSupported && ! empty($this->build_secrets)) { $fullDockerfilePath = "{$this->workdir}/{$dockerfilePath}"; $this->modify_dockerfile_for_secrets($fullDockerfilePath); $this->application_deployment_queue->addLogEntry("Modified Dockerfile for service {$serviceName} to use build secrets."); } } } private function add_build_secrets_to_compose($composeFile) { // Generate env variables if not already done // This populates $this->env_args with both user-defined and COOLIFY_* variables if (! $this->env_args || $this->env_args->isEmpty()) { $this->generate_env_variables(); } $variables = $this->env_args; if ($variables->isEmpty()) { return $composeFile; } $secrets = []; foreach ($variables as $key => $value) { $secrets[$key] = [ 'environment' => $key, ]; } $services = data_get($composeFile, 'services', []); foreach ($services as $serviceName => &$service) { if (isset($service['build'])) { if (is_string($service['build'])) { $service['build'] = [ 'context' => $service['build'], ]; } if (! isset($service['build']['secrets'])) { $service['build']['secrets'] = []; } foreach ($variables as $key => $value) { if (! in_array($key, $service['build']['secrets'])) { $service['build']['secrets'][] = $key; } } } } $composeFile['services'] = $services; $existingSecrets = data_get($composeFile, 'secrets', []); if ($existingSecrets instanceof \Illuminate\Support\Collection) { $existingSecrets = $existingSecrets->toArray(); } $composeFile['secrets'] = array_replace($existingSecrets, $secrets); $this->application_deployment_queue->addLogEntry('Added build secrets configuration to docker-compose file (using environment variables).'); return $composeFile; } private function validatePathField(string $value, string $fieldName): string { if (! preg_match(\App\Support\ValidationPatterns::FILE_PATH_PATTERN, $value)) { throw new \RuntimeException("Invalid {$fieldName}: contains forbidden characters."); } if (str_contains($value, '..')) { throw new \RuntimeException("Invalid {$fieldName}: path traversal detected."); } return $value; } private function run_pre_deployment_command() { if (empty($this->application->pre_deployment_command)) { return; } $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id); if ($containers->count() == 0) { return; } $this->application_deployment_queue->addLogEntry('Executing pre-deployment command (see debug log for output/errors).'); foreach ($containers as $container) { $containerName = data_get($container, 'Names'); if ($containers->count() == 1 || str_starts_with($containerName, $this->application->pre_deployment_command_container.'-'.$this->application->uuid)) { $cmd = "sh -c '".str_replace("'", "'\''", $this->application->pre_deployment_command)."'"; $exec = "docker exec {$containerName} {$cmd}"; $this->execute_remote_command( [ 'command' => $exec, 'hidden' => true, ], ); return; } } throw new DeploymentException('Pre-deployment command: Could not find a valid container. Is the container name correct?'); } private function run_post_deployment_command() { if (empty($this->application->post_deployment_command)) { return; } $this->application_deployment_queue->addLogEntry('----------------------------------------'); $this->application_deployment_queue->addLogEntry('Executing post-deployment command (see debug log for output).'); $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id); foreach ($containers as $container) { $containerName = data_get($container, 'Names'); if ($containers->count() == 1 || str_starts_with($containerName, $this->application->post_deployment_command_container.'-'.$this->application->uuid)) { $cmd = "sh -c '".str_replace("'", "'\''", $this->application->post_deployment_command)."'"; $exec = "docker exec {$containerName} {$cmd}"; try { $this->execute_remote_command( [ 'command' => $exec, 'hidden' => true, 'save' => 'post-deployment-command-output', ], ); } catch (Exception $e) { $post_deployment_command_output = $this->saved_outputs->get('post-deployment-command-output'); if ($post_deployment_command_output) { $this->application_deployment_queue->addLogEntry('Post-deployment command failed.'); $this->application_deployment_queue->addLogEntry($post_deployment_command_output, 'stderr'); } } return; } } throw new DeploymentException('Post-deployment command: Could not find a valid container. Is the container name correct?'); } /** * Check if the deployment was cancelled and abort if it was */ private function checkForCancellation(): void { $this->application_deployment_queue->refresh(); if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) { $this->application_deployment_queue->addLogEntry('Deployment cancelled by user, stopping execution.'); throw new DeploymentException('Deployment cancelled by user', 69420); } } /** * Transition deployment to a new status with proper validation and side effects. * This is the single source of truth for status transitions. */ private function transitionToStatus(ApplicationDeploymentStatus $status): void { if ($this->isInTerminalState()) { return; } $this->updateDeploymentStatus($status); $this->handleStatusTransition($status); queue_next_deployment($this->application); } /** * Check if deployment is in a terminal state (FINISHED, FAILED or CANCELLED). * Terminal states cannot be changed. */ private function isInTerminalState(): bool { $this->application_deployment_queue->refresh(); if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::FINISHED->value) { return true; } if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::FAILED->value) { return true; } if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) { $this->application_deployment_queue->addLogEntry('Deployment cancelled by user, stopping execution.'); throw new DeploymentException('Deployment cancelled by user', 69420); } return false; } /** * Update the deployment status in the database. */ private function updateDeploymentStatus(ApplicationDeploymentStatus $status): void { $this->application_deployment_queue->update([ 'status' => $status->value, ]); } /** * Execute status-specific side effects (events, notifications, additional deployments). */ private function handleStatusTransition(ApplicationDeploymentStatus $status): void { match ($status) { ApplicationDeploymentStatus::FINISHED => $this->handleSuccessfulDeployment(), ApplicationDeploymentStatus::FAILED => $this->handleFailedDeployment(), default => null, }; } /** * Handle side effects when deployment succeeds. */ private function handleSuccessfulDeployment(): void { // Reset restart count after successful deployment // This is done here (not in Livewire) to avoid race conditions // with GetContainersStatus reading old container restart counts $this->application->update([ 'restart_count' => 0, 'last_restart_at' => null, 'last_restart_type' => null, ]); event(new ApplicationConfigurationChanged($this->application->team()->id)); if (! $this->only_this_server) { $this->deploy_to_additional_destinations(); } $this->sendDeploymentNotification(DeploymentSuccess::class); } /** * Handle side effects when deployment fails. */ private function handleFailedDeployment(): void { $this->sendDeploymentNotification(DeploymentFailed::class); } /** * Send deployment status notification to the team. */ private function sendDeploymentNotification(string $notificationClass): void { $this->application->environment->project->team?->notify( new $notificationClass($this->application, $this->deployment_uuid, $this->preview) ); } /** * Complete deployment successfully. * Sends success notification and triggers additional deployments if needed. */ private function completeDeployment(): void { $this->transitionToStatus(ApplicationDeploymentStatus::FINISHED); } /** * Fail the deployment. * Sends failure notification and queues next deployment. */ protected function failDeployment(): void { $this->transitionToStatus(ApplicationDeploymentStatus::FAILED); } public function failed(Throwable $exception): void { $this->failDeployment(); // Log comprehensive error information $errorMessage = $exception->getMessage() ?: 'Unknown error occurred'; $errorCode = $exception->getCode(); $errorClass = get_class($exception); $this->application_deployment_queue->addLogEntry('========================================', 'stderr'); $this->application_deployment_queue->addLogEntry("Deployment failed: {$errorMessage}", 'stderr'); $this->application_deployment_queue->addLogEntry("Error type: {$errorClass}", 'stderr', hidden: true); $this->application_deployment_queue->addLogEntry("Error code: {$errorCode}", 'stderr', hidden: true); // Log the exception file and line for debugging $this->application_deployment_queue->addLogEntry("Location: {$exception->getFile()}:{$exception->getLine()}", 'stderr', hidden: true); // Log previous exceptions if they exist (for chained exceptions) $previous = $exception->getPrevious(); if ($previous) { $this->application_deployment_queue->addLogEntry('Caused by:', 'stderr', hidden: true); $previousMessage = $previous->getMessage() ?: 'No message'; $previousClass = get_class($previous); $this->application_deployment_queue->addLogEntry(" {$previousClass}: {$previousMessage}", 'stderr', hidden: true); $this->application_deployment_queue->addLogEntry(" at {$previous->getFile()}:{$previous->getLine()}", 'stderr', hidden: true); } // Log first few lines of stack trace for debugging $trace = $exception->getTraceAsString(); $traceLines = explode("\n", $trace); $this->application_deployment_queue->addLogEntry('Stack trace (first 5 lines):', 'stderr', hidden: true); foreach (array_slice($traceLines, 0, 5) as $traceLine) { $this->application_deployment_queue->addLogEntry(" {$traceLine}", 'stderr', hidden: true); } $this->application_deployment_queue->addLogEntry('========================================', 'stderr'); if ($this->application->build_pack !== 'dockercompose') { $code = $exception->getCode(); if ($code !== 69420) { // 69420 means failed to push the image to the registry, so we don't need to remove the new version as it is the currently running one if ($this->application->settings->is_consistent_container_name_enabled || str($this->application->settings->custom_internal_name)->isNotEmpty() || $this->pull_request_id !== 0) { // do not remove already running container for PR deployments } else { $this->application_deployment_queue->addLogEntry('Deployment failed. Removing the new version of your application.', 'stderr'); $this->execute_remote_command( ["docker rm -f $this->container_name >/dev/null 2>&1", 'hidden' => true, 'ignore_errors' => true] ); } } } } } ================================================ FILE: app/Jobs/ApplicationPullRequestUpdateJob.php ================================================ onQueue('high'); } public function handle() { try { if ($this->application->is_public_repository()) { return; } $serviceName = $this->application->name; if ($this->status === ProcessStatus::CLOSED) { $this->delete_comment(); return; } match ($this->status) { ProcessStatus::QUEUED => $this->body = "The preview deployment for **{$serviceName}** is queued. ⏳\n\n", ProcessStatus::IN_PROGRESS => $this->body = "The preview deployment for **{$serviceName}** is in progress. 🟡\n\n", ProcessStatus::FINISHED => $this->body = "The preview deployment for **{$serviceName}** is ready. 🟢\n\n".$this->getPreviewLinks(), ProcessStatus::ERROR => $this->body = "The preview deployment for **{$serviceName}** failed. 🔴\n\n", ProcessStatus::KILLED => $this->body = "The preview deployment for **{$serviceName}** was killed. ⚫\n\n", ProcessStatus::CANCELLED => $this->body = "The preview deployment for **{$serviceName}** was cancelled. 🚫\n\n", ProcessStatus::CLOSED => '', // Already handled above, but included for completeness }; $this->build_logs_url = base_url()."/project/{$this->application->environment->project->uuid}/environment/{$this->application->environment->uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; $application_logs_url = base_url()."/project/{$this->application->environment->project->uuid}/environment/{$this->application->environment->uuid}/application/{$this->application->uuid}/logs"; $this->body .= '[Open Build Logs]('.$this->build_logs_url.') | [Open Application Logs]('.$application_logs_url.")\n\n\n"; $this->body .= 'Last updated at: '.now()->toDateTimeString().' CET'; if ($this->preview->pull_request_issue_comment_id) { $this->update_comment(); } else { $this->create_comment(); } } catch (\Throwable $e) { return $e; } } private function update_comment() { ['data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'patch', data: [ 'body' => $this->body, ], throwError: false); if (data_get($data, 'message') === 'Not Found') { $this->create_comment(); } } private function create_comment() { ['data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/{$this->preview->pull_request_id}/comments", method: 'post', data: [ 'body' => $this->body, ]); $this->preview->pull_request_issue_comment_id = $data['id']; $this->preview->save(); } private function delete_comment() { githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'delete'); } private function getPreviewLinks(): string { if ($this->application->build_pack === 'dockercompose') { $dockerComposeDomains = json_decode($this->preview->docker_compose_domains, true) ?? []; $links = []; foreach ($dockerComposeDomains as $serviceName => $config) { $domain = data_get($config, 'domain'); if (! empty($domain)) { $firstDomain = str($domain)->explode(',')->first(); $firstDomain = trim($firstDomain); if (! empty($firstDomain)) { $links[] = "[Open {$serviceName}]({$firstDomain})"; } } } return ! empty($links) ? implode(' | ', $links).' | ' : ''; } return $this->preview->fqdn ? "[Open Preview]({$this->preview->fqdn}) | " : ''; } } ================================================ FILE: app/Jobs/CheckAndStartSentinelJob.php ================================================ server, false, 10); $sentinelFoundJson = json_decode($sentinelFound, true); $sentinelStatus = data_get($sentinelFoundJson, '0.State.Status', 'exited'); if ($sentinelStatus !== 'running') { StartSentinel::run(server: $this->server, restart: true, latestVersion: $latestVersion); return; } // If sentinel is running, check if it needs an update $runningVersion = instant_remote_process_with_timeout(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/version"'], $this->server, false); if (empty($runningVersion)) { $runningVersion = '0.0.0'; } if ($latestVersion === '0.0.0' && $runningVersion === '0.0.0') { StartSentinel::run(server: $this->server, restart: true, latestVersion: 'latest'); return; } else { if (version_compare($runningVersion, $latestVersion, '<')) { StartSentinel::run(server: $this->server, restart: true, latestVersion: $latestVersion); return; } } } } ================================================ FILE: app/Jobs/CheckForUpdatesJob.php ================================================ get(config('constants.coolify.versions_url')); if ($response->successful()) { $versions = $response->json(); $latest_version = data_get($versions, 'coolify.v4.version'); $current_version = config('constants.coolify.version'); // Read existing cached version $existingVersions = null; $existingCoolifyVersion = null; if (File::exists(base_path('versions.json'))) { $existingVersions = json_decode(File::get(base_path('versions.json')), true); $existingCoolifyVersion = data_get($existingVersions, 'coolify.v4.version'); } // Determine the BEST version to use (CDN, cache, or current) $bestVersion = $latest_version; // Check if cache has newer version than CDN if ($existingCoolifyVersion && version_compare($existingCoolifyVersion, $bestVersion, '>')) { Log::warning('CDN served older Coolify version than cache', [ 'cdn_version' => $latest_version, 'cached_version' => $existingCoolifyVersion, 'current_version' => $current_version, ]); $bestVersion = $existingCoolifyVersion; } // CRITICAL: Never allow bestVersion to be older than currently running version if (version_compare($bestVersion, $current_version, '<')) { Log::warning('Version downgrade prevented in CheckForUpdatesJob', [ 'cdn_version' => $latest_version, 'cached_version' => $existingCoolifyVersion, 'current_version' => $current_version, 'attempted_best' => $bestVersion, 'using' => $current_version, ]); $bestVersion = $current_version; } // Use data_set() for safe mutation (fixes #3) data_set($versions, 'coolify.v4.version', $bestVersion); $latest_version = $bestVersion; // ALWAYS write versions.json (for Sentinel, Helper, Traefik updates) File::put(base_path('versions.json'), json_encode($versions, JSON_PRETTY_PRINT)); // Invalidate cache to ensure fresh data is loaded invalidate_versions_cache(); // Only mark new version available if Coolify version actually increased if (version_compare($latest_version, $current_version, '>')) { // New version available $settings->update(['new_version_available' => true]); } else { $settings->update(['new_version_available' => false]); } } } catch (\Throwable $e) { // Consider implementing a notification to administrators } } } ================================================ FILE: app/Jobs/CheckHelperImageJob.php ================================================ get(config('constants.coolify.versions_url')); if ($response->successful()) { $versions = $response->json(); $settings = instanceSettings(); $latest_version = data_get($versions, 'coolify.helper.version'); $current_version = $settings->helper_version; if (version_compare($latest_version, $current_version, '>')) { $settings->update(['helper_version' => $latest_version]); } } } catch (\Throwable $e) { send_internal_notification('CheckHelperImageJob failed with: '.$e->getMessage()); throw $e; } } } ================================================ FILE: app/Jobs/CheckTraefikVersionForServerJob.php ================================================ server); // Update detected version in database $this->server->update(['detected_traefik_version' => $currentVersion]); if (! $currentVersion) { ProxyStatusChangedUI::dispatch($this->server->team_id); return; } // Check if image tag is 'latest' by inspecting the image (makes SSH call) $imageTag = instant_remote_process([ "docker inspect coolify-proxy --format '{{.Config.Image}}' 2>/dev/null", ], $this->server, false); // Handle empty/null response from SSH command if (empty(trim($imageTag))) { ProxyStatusChangedUI::dispatch($this->server->team_id); return; } if (str_contains(strtolower(trim($imageTag)), ':latest')) { ProxyStatusChangedUI::dispatch($this->server->team_id); return; } // Parse current version to extract major.minor.patch $current = ltrim($currentVersion, 'v'); if (! preg_match('/^(\d+\.\d+)\.(\d+)$/', $current, $matches)) { ProxyStatusChangedUI::dispatch($this->server->team_id); return; } $currentBranch = $matches[1]; // e.g., "3.6" // Find the latest version for this branch $latestForBranch = $this->traefikVersions["v{$currentBranch}"] ?? null; if (! $latestForBranch) { // User is on a branch we don't track - check if newer branches exist $newerBranchInfo = $this->getNewerBranchInfo($currentBranch); if ($newerBranchInfo) { $this->storeOutdatedInfo($current, $newerBranchInfo['latest'], 'minor_upgrade', $newerBranchInfo['target']); } else { // No newer branch found, clear outdated info $this->server->update(['traefik_outdated_info' => null]); } ProxyStatusChangedUI::dispatch($this->server->team_id); return; } // Compare patch version within the same branch $latest = ltrim($latestForBranch, 'v'); // Always check for newer branches first $newerBranchInfo = $this->getNewerBranchInfo($currentBranch); if (version_compare($current, $latest, '<')) { // Patch update available $this->storeOutdatedInfo($current, $latest, 'patch_update', null, $newerBranchInfo); } elseif ($newerBranchInfo) { // Only newer branch available (no patch update) $this->storeOutdatedInfo($current, $newerBranchInfo['latest'], 'minor_upgrade', $newerBranchInfo['target']); } else { // Fully up to date $this->server->update(['traefik_outdated_info' => null]); } // Dispatch UI update event so warning state refreshes in real-time ProxyStatusChangedUI::dispatch($this->server->team_id); } /** * Get information about newer branches if available. */ private function getNewerBranchInfo(string $currentBranch): ?array { $newestBranch = null; $newestVersion = null; foreach ($this->traefikVersions as $branch => $version) { $branchNum = ltrim($branch, 'v'); if (version_compare($branchNum, $currentBranch, '>')) { if (! $newestVersion || version_compare($version, $newestVersion, '>')) { $newestBranch = $branchNum; $newestVersion = $version; } } } if ($newestVersion) { return [ 'target' => "v{$newestBranch}", 'latest' => ltrim($newestVersion, 'v'), ]; } return null; } /** * Store outdated information in database and send immediate notification. */ private function storeOutdatedInfo(string $current, string $latest, string $type, ?string $upgradeTarget = null, ?array $newerBranchInfo = null): void { $outdatedInfo = [ 'current' => $current, 'latest' => $latest, 'type' => $type, 'checked_at' => now()->toIso8601String(), ]; // For minor upgrades, add the upgrade_target field (e.g., "v3.6") if ($type === 'minor_upgrade' && $upgradeTarget) { $outdatedInfo['upgrade_target'] = $upgradeTarget; } // If there's a newer branch available (even for patch updates), include that info if ($newerBranchInfo) { $outdatedInfo['newer_branch_target'] = $newerBranchInfo['target']; $outdatedInfo['newer_branch_latest'] = $newerBranchInfo['latest']; } $this->server->update(['traefik_outdated_info' => $outdatedInfo]); // Send immediate notification to the team $this->sendNotification($outdatedInfo); } /** * Send notification to team about outdated Traefik. */ private function sendNotification(array $outdatedInfo): void { // Attach the outdated info as a dynamic property for the notification $this->server->outdatedInfo = $outdatedInfo; // Get the team and send notification $team = $this->server->team()->first(); if ($team) { $team->notify(new TraefikVersionOutdated(collect([$this->server]))); } } } ================================================ FILE: app/Jobs/CheckTraefikVersionJob.php ================================================ whereProxyType(ProxyTypes::TRAEFIK->value) ->whereRelation('settings', 'is_reachable', true) ->whereRelation('settings', 'is_usable', true) ->get(); if ($servers->isEmpty()) { return; } // Dispatch individual server check jobs in parallel // Each job will send immediate notifications when outdated Traefik is detected foreach ($servers as $server) { CheckTraefikVersionForServerJob::dispatch($server, $traefikVersions); } } } ================================================ FILE: app/Jobs/CleanupHelperContainersJob.php ================================================ server->id) ->whereIn('status', [ ApplicationDeploymentStatus::IN_PROGRESS->value, ApplicationDeploymentStatus::QUEUED->value, ]) ->pluck('deployment_uuid') ->toArray(); \Log::info('CleanupHelperContainersJob - Active deployments', [ 'server' => $this->server->name, 'active_deployment_uuids' => $activeDeployments, ]); $containers = instant_remote_process_with_timeout(['docker container ps --format \'{{json .}}\' | jq -s \'map(select(.Image | contains("'.config('constants.coolify.registry_url').'/coollabsio/coolify-helper")))\''], $this->server, false); $helperContainers = collect(json_decode($containers)); if ($helperContainers->count() > 0) { foreach ($helperContainers as $container) { $containerId = data_get($container, 'ID'); $containerName = data_get($container, 'Names'); // Check if this container belongs to an active deployment $isActiveDeployment = false; foreach ($activeDeployments as $deploymentUuid) { if (str_contains($containerName, $deploymentUuid)) { $isActiveDeployment = true; break; } } if ($isActiveDeployment) { \Log::info('CleanupHelperContainersJob - Skipping active deployment container', [ 'container' => $containerName, 'id' => $containerId, ]); continue; } \Log::info('CleanupHelperContainersJob - Removing orphaned helper container', [ 'container' => $containerName, 'id' => $containerId, ]); instant_remote_process_with_timeout(['docker container rm -f '.$containerId], $this->server, false); } } } catch (\Throwable $e) { send_internal_notification('CleanupHelperContainersJob failed with error: '.$e->getMessage()); } } } ================================================ FILE: app/Jobs/CleanupInstanceStuffsJob.php ================================================ expireAfter(60)->dontRelease()]; } public function handle(): void { try { $this->cleanupInvitationLink(); $this->cleanupExpiredEmailChangeRequests(); } catch (\Throwable $e) { Log::error('CleanupInstanceStuffsJob failed with error: '.$e->getMessage()); } } private function cleanupInvitationLink() { $invitation = TeamInvitation::all(); foreach ($invitation as $item) { $item->isValid(); } } private function cleanupExpiredEmailChangeRequests() { User::whereNotNull('email_change_code_expires_at') ->where('email_change_code_expires_at', '<', now()) ->update([ 'pending_email' => null, 'email_change_code' => null, 'email_change_code_expires_at' => null, ]); } } ================================================ FILE: app/Jobs/CleanupOrphanedPreviewContainersJob.php ================================================ expireAfter(600)->dontRelease()]; } public function handle(): void { try { $servers = $this->getServersToCheck(); foreach ($servers as $server) { $this->cleanupOrphanedContainersOnServer($server); } } catch (\Throwable $e) { Log::error('CleanupOrphanedPreviewContainersJob failed: '.$e->getMessage()); send_internal_notification('CleanupOrphanedPreviewContainersJob failed with error: '.$e->getMessage()); } } /** * Get all functional servers to check for orphaned containers. */ private function getServersToCheck(): \Illuminate\Support\Collection { $query = Server::whereRelation('settings', 'is_usable', true) ->whereRelation('settings', 'is_reachable', true) ->where('ip', '!=', '1.2.3.4'); if (isCloud()) { $query = $query->whereRelation('team.subscription', 'stripe_invoice_paid', true); } return $query->get()->filter(fn ($server) => $server->isFunctional()); } /** * Find and clean up orphaned PR containers on a specific server. */ private function cleanupOrphanedContainersOnServer(Server $server): void { try { $prContainers = $this->getPRContainersOnServer($server); if ($prContainers->isEmpty()) { return; } $orphanedCount = 0; foreach ($prContainers as $container) { if ($this->isOrphanedContainer($container)) { $this->removeContainer($container, $server); $orphanedCount++; } } if ($orphanedCount > 0) { Log::info("CleanupOrphanedPreviewContainersJob - Removed {$orphanedCount} orphaned PR containers", [ 'server' => $server->name, ]); } } catch (\Throwable $e) { Log::warning("CleanupOrphanedPreviewContainersJob - Error on server {$server->name}: {$e->getMessage()}"); } } /** * Get all PR containers on a server (containers with pullRequestId > 0). */ private function getPRContainersOnServer(Server $server): \Illuminate\Support\Collection { try { $output = instant_remote_process([ "docker ps -a --filter 'label=coolify.pullRequestId' --format '{{json .}}'", ], $server, false); if (empty($output)) { return collect(); } return format_docker_command_output_to_json($output) ->filter(function ($container) { // Only include PR containers (pullRequestId > 0) $prId = $this->extractPullRequestId($container); return $prId !== null && $prId > 0; }); } catch (\Throwable $e) { Log::debug("Failed to get PR containers on server {$server->name}: {$e->getMessage()}"); return collect(); } } /** * Extract pull request ID from container labels. */ private function extractPullRequestId($container): ?int { $labels = data_get($container, 'Labels', ''); if (preg_match('/coolify\.pullRequestId=(\d+)/', $labels, $matches)) { return (int) $matches[1]; } return null; } /** * Extract application ID from container labels. */ private function extractApplicationId($container): ?int { $labels = data_get($container, 'Labels', ''); if (preg_match('/coolify\.applicationId=(\d+)/', $labels, $matches)) { return (int) $matches[1]; } return null; } /** * Check if a container is orphaned (no corresponding ApplicationPreview record). */ private function isOrphanedContainer($container): bool { $applicationId = $this->extractApplicationId($container); $pullRequestId = $this->extractPullRequestId($container); if ($applicationId === null || $pullRequestId === null) { return false; } // Check if ApplicationPreview record exists (including soft-deleted) $previewExists = ApplicationPreview::withTrashed() ->where('application_id', $applicationId) ->where('pull_request_id', $pullRequestId) ->exists(); // If preview exists (even soft-deleted), container should be handled by DeleteResourceJob // If preview doesn't exist at all, it's truly orphaned return ! $previewExists; } /** * Remove an orphaned container from the server. */ private function removeContainer($container, Server $server): void { $containerName = data_get($container, 'Names'); if (empty($containerName)) { Log::warning('CleanupOrphanedPreviewContainersJob - Cannot remove container: missing container name', [ 'container_data' => $container, 'server' => $server->name, ]); return; } $applicationId = $this->extractApplicationId($container); $pullRequestId = $this->extractPullRequestId($container); Log::info('CleanupOrphanedPreviewContainersJob - Removing orphaned container', [ 'container' => $containerName, 'application_id' => $applicationId, 'pull_request_id' => $pullRequestId, 'server' => $server->name, ]); $escapedContainerName = escapeshellarg($containerName); try { instant_remote_process( ["docker rm -f {$escapedContainerName}"], $server, false ); } catch (\Throwable $e) { Log::warning("Failed to remove orphaned container {$containerName}: {$e->getMessage()}"); } } } ================================================ FILE: app/Jobs/CleanupStaleMultiplexedConnections.php ================================================ cleanupStaleConnections(); $this->cleanupNonExistentServerConnections(); } private function cleanupStaleConnections() { $muxFiles = Storage::disk('ssh-mux')->files(); foreach ($muxFiles as $muxFile) { $serverUuid = $this->extractServerUuidFromMuxFile($muxFile); $server = Server::where('uuid', $serverUuid)->first(); if (! $server) { $this->removeMultiplexFile($muxFile); continue; } $muxSocket = "/var/www/html/storage/app/ssh/mux/{$muxFile}"; $checkCommand = "ssh -O check -o ControlPath={$muxSocket} {$server->user}@{$server->ip} 2>/dev/null"; $checkProcess = Process::run($checkCommand); if ($checkProcess->exitCode() !== 0) { $this->removeMultiplexFile($muxFile); } else { $muxContent = Storage::disk('ssh-mux')->get($muxFile); $establishedAt = Carbon::parse(substr($muxContent, 37)); $expirationTime = $establishedAt->addSeconds(config('constants.ssh.mux_persist_time')); if (Carbon::now()->isAfter($expirationTime)) { $this->removeMultiplexFile($muxFile); } } } } private function cleanupNonExistentServerConnections() { $muxFiles = Storage::disk('ssh-mux')->files(); $existingServerUuids = Server::pluck('uuid')->toArray(); foreach ($muxFiles as $muxFile) { $serverUuid = $this->extractServerUuidFromMuxFile($muxFile); if (! in_array($serverUuid, $existingServerUuids)) { $this->removeMultiplexFile($muxFile); } } } private function extractServerUuidFromMuxFile($muxFile) { return substr($muxFile, 4); } private function removeMultiplexFile($muxFile) { $muxSocket = "/var/www/html/storage/app/ssh/mux/{$muxFile}"; $closeCommand = "ssh -O exit -o ControlPath={$muxSocket} localhost 2>/dev/null"; Process::run($closeCommand); Storage::disk('ssh-mux')->delete($muxFile); } } ================================================ FILE: app/Jobs/ConnectProxyToNetworksJob.php ================================================ server->uuid)) ->expireAfter(60) ->dontRelease(), ]; } public function __construct(public Server $server) {} public function handle() { if (! $this->server->isFunctional()) { return; } $connectProxyToDockerNetworks = connectProxyToNetworks($this->server); if (empty($connectProxyToDockerNetworks)) { return; } instant_remote_process($connectProxyToDockerNetworks, $this->server, false); } } ================================================ FILE: app/Jobs/CoolifyTask.php ================================================ onQueue('high'); } /** * Execute the job. */ public function handle(): void { $remote_process = resolve(RunRemoteProcess::class, [ 'activity' => $this->activity, 'ignore_errors' => $this->ignore_errors, 'call_event_on_finish' => $this->call_event_on_finish, 'call_event_data' => $this->call_event_data, ]); $remote_process(); } /** * Calculate the number of seconds to wait before retrying the job. */ public function backoff(): array { return [30, 90, 180]; // 30s, 90s, 180s between retries } /** * Handle a job failure. */ public function failed(?\Throwable $exception): void { Log::channel('scheduled-errors')->error('CoolifyTask permanently failed', [ 'job' => 'CoolifyTask', 'activity_id' => $this->activity->id, 'server_uuid' => $this->activity->getExtraProperty('server_uuid'), 'command_preview' => substr($this->activity->getExtraProperty('command') ?? '', 0, 200), 'error' => $exception?->getMessage(), 'total_attempts' => $this->attempts(), 'trace' => $exception?->getTraceAsString(), ]); // Update activity status to reflect permanent failure $this->activity->properties = $this->activity->properties->merge([ 'status' => ProcessStatus::ERROR->value, 'error' => $exception?->getMessage() ?? 'Job permanently failed', 'failed_at' => now()->toIso8601String(), ]); $this->activity->save(); // Dispatch cleanup event on failure (same as on success) if ($this->call_event_on_finish) { try { $eventClass = "App\\Events\\$this->call_event_on_finish"; if (! is_null($this->call_event_data)) { event(new $eventClass($this->call_event_data)); } else { event(new $eventClass($this->activity->causer_id)); } Log::info('Cleanup event dispatched after job failure', [ 'event' => $this->call_event_on_finish, ]); } catch (\Throwable $e) { Log::error('Error dispatching cleanup event on failure: '.$e->getMessage()); } } } } ================================================ FILE: app/Jobs/DatabaseBackupJob.php ================================================ onQueue('high'); $this->timeout = $backup->timeout ?? 3600; } public function handle(): void { try { $databasesToBackup = null; $this->team = Team::find($this->backup->team_id); if (! $this->team) { $this->backup->delete(); return; } if (data_get($this->backup, 'database_type') === \App\Models\ServiceDatabase::class) { $this->database = data_get($this->backup, 'database'); $this->server = $this->database->service->server; $this->s3 = $this->backup->s3; } else { $this->database = data_get($this->backup, 'database'); $this->server = $this->database->destination->server; $this->s3 = $this->backup->s3; } if (is_null($this->server)) { throw new \Exception('Server not found?!'); } if (is_null($this->database)) { throw new \Exception('Database not found?!'); } BackupCreated::dispatch($this->team->id); $status = str(data_get($this->database, 'status')); if (! $status->startsWith('running') && $this->database->id !== 0) { Log::info('DatabaseBackupJob skipped: database not running', [ 'backup_id' => $this->backup->id, 'database_id' => $this->database->id, 'status' => (string) $status, ]); return; } if (data_get($this->backup, 'database_type') === \App\Models\ServiceDatabase::class) { $databaseType = $this->database->databaseType(); $serviceUuid = $this->database->service->uuid; $serviceName = str($this->database->service->name)->slug(); if (str($databaseType)->contains('postgres')) { $this->container_name = "{$this->database->name}-$serviceUuid"; $this->directory_name = $serviceName.'-'.$this->container_name; $commands[] = "docker exec $this->container_name env | grep POSTGRES_"; $envs = instant_remote_process($commands, $this->server, true, false, null, disableMultiplexing: true); $envs = str($envs)->explode("\n"); $user = $envs->filter(function ($env) { return str($env)->startsWith('POSTGRES_USER='); })->first(); if ($user) { $this->database->postgres_user = str($user)->after('POSTGRES_USER=')->value(); } else { $this->database->postgres_user = 'postgres'; } $db = $envs->filter(function ($env) { return str($env)->startsWith('POSTGRES_DB='); })->first(); if ($db) { $databasesToBackup = str($db)->after('POSTGRES_DB=')->value(); } else { $databasesToBackup = $this->database->postgres_user; } $this->postgres_password = $envs->filter(function ($env) { return str($env)->startsWith('POSTGRES_PASSWORD='); })->first(); if ($this->postgres_password) { $this->postgres_password = str($this->postgres_password)->after('POSTGRES_PASSWORD=')->value(); } } elseif (str($databaseType)->contains('mysql')) { $this->container_name = "{$this->database->name}-$serviceUuid"; $this->directory_name = $serviceName.'-'.$this->container_name; $commands[] = "docker exec $this->container_name env | grep MYSQL_"; $envs = instant_remote_process($commands, $this->server, true, false, null, disableMultiplexing: true); $envs = str($envs)->explode("\n"); $rootPassword = $envs->filter(function ($env) { return str($env)->startsWith('MYSQL_ROOT_PASSWORD='); })->first(); if ($rootPassword) { $this->database->mysql_root_password = str($rootPassword)->after('MYSQL_ROOT_PASSWORD=')->value(); } $db = $envs->filter(function ($env) { return str($env)->startsWith('MYSQL_DATABASE='); })->first(); if ($db) { $databasesToBackup = str($db)->after('MYSQL_DATABASE=')->value(); } else { throw new \Exception('MYSQL_DATABASE not found'); } } elseif (str($databaseType)->contains('mariadb')) { $this->container_name = "{$this->database->name}-$serviceUuid"; $this->directory_name = $serviceName.'-'.$this->container_name; $commands[] = "docker exec $this->container_name env"; $envs = instant_remote_process($commands, $this->server, true, false, null, disableMultiplexing: true); $envs = str($envs)->explode("\n"); $rootPassword = $envs->filter(function ($env) { return str($env)->startsWith('MARIADB_ROOT_PASSWORD='); })->first(); if ($rootPassword) { $this->database->mariadb_root_password = str($rootPassword)->after('MARIADB_ROOT_PASSWORD=')->value(); } else { $rootPassword = $envs->filter(function ($env) { return str($env)->startsWith('MYSQL_ROOT_PASSWORD='); })->first(); if ($rootPassword) { $this->database->mariadb_root_password = str($rootPassword)->after('MYSQL_ROOT_PASSWORD=')->value(); } } $db = $envs->filter(function ($env) { return str($env)->startsWith('MARIADB_DATABASE='); })->first(); if ($db) { $databasesToBackup = str($db)->after('MARIADB_DATABASE=')->value(); } else { $db = $envs->filter(function ($env) { return str($env)->startsWith('MYSQL_DATABASE='); })->first(); if ($db) { $databasesToBackup = str($db)->after('MYSQL_DATABASE=')->value(); } else { throw new \Exception('MARIADB_DATABASE or MYSQL_DATABASE not found'); } } } elseif (str($databaseType)->contains('mongo')) { $databasesToBackup = ['*']; $this->container_name = "{$this->database->name}-$serviceUuid"; $this->directory_name = $serviceName.'-'.$this->container_name; // Try to extract MongoDB credentials from environment variables try { $commands = []; $commands[] = "docker exec $this->container_name env | grep MONGO_INITDB_"; $envs = instant_remote_process($commands, $this->server, true, false, null, disableMultiplexing: true); if (filled($envs)) { $envs = str($envs)->explode("\n"); $rootPassword = $envs->filter(function ($env) { return str($env)->startsWith('MONGO_INITDB_ROOT_PASSWORD='); })->first(); if ($rootPassword) { $this->mongo_root_password = str($rootPassword)->after('MONGO_INITDB_ROOT_PASSWORD=')->value(); } $rootUsername = $envs->filter(function ($env) { return str($env)->startsWith('MONGO_INITDB_ROOT_USERNAME='); })->first(); if ($rootUsername) { $this->mongo_root_username = str($rootUsername)->after('MONGO_INITDB_ROOT_USERNAME=')->value(); } } } catch (\Throwable $e) { // Continue without env vars - will be handled in backup_standalone_mongodb method } } } else { $databaseName = str($this->database->name)->slug()->value(); $this->container_name = $this->database->uuid; $this->directory_name = $databaseName.'-'.$this->container_name; $databaseType = $this->database->type(); $databasesToBackup = data_get($this->backup, 'databases_to_backup'); } if (blank($databasesToBackup)) { if (str($databaseType)->contains('postgres')) { $databasesToBackup = [$this->database->postgres_db]; } elseif (str($databaseType)->contains('mongo')) { $databasesToBackup = ['*']; } elseif (str($databaseType)->contains('mysql')) { $databasesToBackup = [$this->database->mysql_database]; } elseif (str($databaseType)->contains('mariadb')) { $databasesToBackup = [$this->database->mariadb_database]; } else { return; } } else { if (str($databaseType)->contains('postgres')) { // Format: db1,db2,db3 $databasesToBackup = explode(',', $databasesToBackup); $databasesToBackup = array_map('trim', $databasesToBackup); } elseif (str($databaseType)->contains('mongo')) { // Format: db1:collection1,collection2|db2:collection3,collection4 // Only explode if it's a string, not if it's already an array if (is_string($databasesToBackup)) { $databasesToBackup = explode('|', $databasesToBackup); $databasesToBackup = array_map('trim', $databasesToBackup); } } elseif (str($databaseType)->contains('mysql')) { // Format: db1,db2,db3 $databasesToBackup = explode(',', $databasesToBackup); $databasesToBackup = array_map('trim', $databasesToBackup); } elseif (str($databaseType)->contains('mariadb')) { // Format: db1,db2,db3 $databasesToBackup = explode(',', $databasesToBackup); $databasesToBackup = array_map('trim', $databasesToBackup); } else { return; } } $this->backup_dir = backup_dir().'/databases/'.str($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name; if ($this->database->name === 'coolify-db') { $databasesToBackup = ['coolify']; $this->directory_name = $this->container_name = 'coolify-db'; $ip = Str::slug($this->server->ip); $this->backup_dir = backup_dir().'/coolify'."/coolify-db-$ip"; } foreach ($databasesToBackup as $database) { // Generate unique UUID for each database backup execution $attempts = 0; do { $this->backup_log_uuid = (string) new Cuid2; $exists = ScheduledDatabaseBackupExecution::where('uuid', $this->backup_log_uuid)->exists(); $attempts++; if ($attempts >= 3 && $exists) { throw new \Exception('Unable to generate unique UUID for backup execution after 3 attempts'); } } while ($exists); $size = 0; $localBackupSucceeded = false; $s3UploadError = null; // Step 1: Create local backup try { if (str($databaseType)->contains('postgres')) { $this->backup_file = "/pg-dump-$database-".Carbon::now()->timestamp.'.dmp'; if ($this->backup->dump_all) { $this->backup_file = '/pg-dump-all-'.Carbon::now()->timestamp.'.gz'; } $this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_log = ScheduledDatabaseBackupExecution::create([ 'uuid' => $this->backup_log_uuid, 'database_name' => $database, 'filename' => $this->backup_location, 'scheduled_database_backup_id' => $this->backup->id, 'local_storage_deleted' => false, ]); $this->backup_standalone_postgresql($database); } elseif (str($databaseType)->contains('mongo')) { if ($database === '*') { $database = 'all'; $databaseName = 'all'; } else { if (str($database)->contains(':')) { $databaseName = str($database)->before(':'); } else { $databaseName = $database; } } $this->backup_file = "/mongo-dump-$databaseName-".Carbon::now()->timestamp.'.tar.gz'; $this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_log = ScheduledDatabaseBackupExecution::create([ 'uuid' => $this->backup_log_uuid, 'database_name' => $databaseName, 'filename' => $this->backup_location, 'scheduled_database_backup_id' => $this->backup->id, 'local_storage_deleted' => false, ]); $this->backup_standalone_mongodb($database); } elseif (str($databaseType)->contains('mysql')) { $this->backup_file = "/mysql-dump-$database-".Carbon::now()->timestamp.'.dmp'; if ($this->backup->dump_all) { $this->backup_file = '/mysql-dump-all-'.Carbon::now()->timestamp.'.gz'; } $this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_log = ScheduledDatabaseBackupExecution::create([ 'uuid' => $this->backup_log_uuid, 'database_name' => $database, 'filename' => $this->backup_location, 'scheduled_database_backup_id' => $this->backup->id, 'local_storage_deleted' => false, ]); $this->backup_standalone_mysql($database); } elseif (str($databaseType)->contains('mariadb')) { $this->backup_file = "/mariadb-dump-$database-".Carbon::now()->timestamp.'.dmp'; if ($this->backup->dump_all) { $this->backup_file = '/mariadb-dump-all-'.Carbon::now()->timestamp.'.gz'; } $this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_log = ScheduledDatabaseBackupExecution::create([ 'uuid' => $this->backup_log_uuid, 'database_name' => $database, 'filename' => $this->backup_location, 'scheduled_database_backup_id' => $this->backup->id, 'local_storage_deleted' => false, ]); $this->backup_standalone_mariadb($database); } else { throw new \Exception('Unsupported database type'); } $size = $this->calculate_size(); // Verify local backup succeeded if ($size > 0) { $localBackupSucceeded = true; } else { throw new \Exception('Local backup file is empty or was not created'); } } catch (\Throwable $e) { // Local backup failed if ($this->backup_log) { $this->backup_log->update([ 'status' => 'failed', 'message' => $this->error_output ?? $this->backup_output ?? $e->getMessage(), 'size' => $size, 'filename' => null, 's3_uploaded' => null, ]); } $this->team?->notify(new BackupFailed($this->backup, $this->database, $this->error_output ?? $this->backup_output ?? $e->getMessage(), $database)); continue; } // Step 2: Upload to S3 if enabled (independent of local backup) $localStorageDeleted = false; if ($this->backup->save_s3 && $localBackupSucceeded) { try { $this->upload_to_s3(); // If local backup is disabled, delete the local file immediately after S3 upload if ($this->backup->disable_local_backup) { deleteBackupsLocally($this->backup_location, $this->server); $localStorageDeleted = true; } } catch (\Throwable $e) { // S3 upload failed but local backup succeeded $s3UploadError = $e->getMessage(); } } // Step 3: Update status and send notifications based on results if ($localBackupSucceeded) { $message = $this->backup_output; if ($s3UploadError) { $message = $message ? $message."\n\nWarning: S3 upload failed: ".$s3UploadError : 'Warning: S3 upload failed: '.$s3UploadError; } $this->backup_log->update([ 'status' => 'success', 'message' => $message, 'size' => $size, 's3_uploaded' => $this->backup->save_s3 ? $this->s3_uploaded : null, 'local_storage_deleted' => $localStorageDeleted, ]); // Send appropriate notification if ($s3UploadError) { $this->team->notify(new BackupSuccessWithS3Warning($this->backup, $this->database, $database, $s3UploadError)); } else { $this->team->notify(new BackupSuccess($this->backup, $this->database, $database)); } } } if ($this->backup_log && $this->backup_log->status === 'success') { removeOldBackups($this->backup); } } catch (\Throwable $e) { throw $e; } finally { if ($this->team) { BackupCreated::dispatch($this->team->id); } if ($this->backup_log) { $this->backup_log->update([ 'finished_at' => Carbon::now()->toImmutable(), ]); } } } private function backup_standalone_mongodb(string $databaseWithCollections): void { try { $url = $this->database->internal_db_url; if (blank($url)) { // For service-based MongoDB, try to build URL from environment variables if (filled($this->mongo_root_username) && filled($this->mongo_root_password)) { // Use container name instead of server IP for service-based MongoDB $url = "mongodb://{$this->mongo_root_username}:{$this->mongo_root_password}@{$this->container_name}:27017"; } else { // If no environment variables are available, throw an exception throw new \Exception('MongoDB credentials not found. Ensure MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD environment variables are available in the container.'); } } Log::info('MongoDB backup URL configured', ['has_url' => filled($url), 'using_env_vars' => blank($this->database->internal_db_url)]); if ($databaseWithCollections === 'all') { $commands[] = 'mkdir -p '.$this->backup_dir; if (str($this->database->image)->startsWith('mongo:4')) { $commands[] = "docker exec $this->container_name mongodump --uri=\"$url\" --gzip --archive > $this->backup_location"; } else { $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=\"$url\" --gzip --archive > $this->backup_location"; } } else { if (str($databaseWithCollections)->contains(':')) { $databaseName = str($databaseWithCollections)->before(':'); $collectionsToExclude = str($databaseWithCollections)->after(':')->explode(','); } else { $databaseName = $databaseWithCollections; $collectionsToExclude = collect(); } $commands[] = 'mkdir -p '.$this->backup_dir; // Validate and escape database name to prevent command injection validateShellSafePath($databaseName, 'database name'); $escapedDatabaseName = escapeshellarg($databaseName); if ($collectionsToExclude->count() === 0) { if (str($this->database->image)->startsWith('mongo:4')) { $commands[] = "docker exec $this->container_name mongodump --uri=\"$url\" --gzip --archive > $this->backup_location"; } else { $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=\"$url\" --db $escapedDatabaseName --gzip --archive > $this->backup_location"; } } else { if (str($this->database->image)->startsWith('mongo:4')) { $commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --excludeCollection ".$collectionsToExclude->implode(' --excludeCollection ')." --archive > $this->backup_location"; } else { $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=\"$url\" --db $escapedDatabaseName --gzip --excludeCollection ".$collectionsToExclude->implode(' --excludeCollection ')." --archive > $this->backup_location"; } } } $this->backup_output = instant_remote_process($commands, $this->server, true, false, $this->timeout, disableMultiplexing: true); $this->backup_output = trim($this->backup_output); if ($this->backup_output === '') { $this->backup_output = null; } } catch (\Throwable $e) { $this->add_to_error_output($e->getMessage()); throw $e; } } private function backup_standalone_postgresql(string $database): void { try { $commands[] = 'mkdir -p '.$this->backup_dir; $backupCommand = 'docker exec'; if ($this->postgres_password) { $backupCommand .= " -e PGPASSWORD=\"{$this->postgres_password}\""; } if ($this->backup->dump_all) { $backupCommand .= " $this->container_name pg_dumpall --username {$this->database->postgres_user} | gzip > $this->backup_location"; } else { // Validate and escape database name to prevent command injection validateShellSafePath($database, 'database name'); $escapedDatabase = escapeshellarg($database); $backupCommand .= " $this->container_name pg_dump --format=custom --no-acl --no-owner --username {$this->database->postgres_user} $escapedDatabase > $this->backup_location"; } $commands[] = $backupCommand; $this->backup_output = instant_remote_process($commands, $this->server, true, false, $this->timeout, disableMultiplexing: true); $this->backup_output = trim($this->backup_output); if ($this->backup_output === '') { $this->backup_output = null; } } catch (\Throwable $e) { $this->add_to_error_output($e->getMessage()); throw $e; } } private function backup_standalone_mysql(string $database): void { try { $commands[] = 'mkdir -p '.$this->backup_dir; if ($this->backup->dump_all) { $commands[] = "docker exec $this->container_name mysqldump -u root -p\"{$this->database->mysql_root_password}\" --all-databases --single-transaction --quick --lock-tables=false --compress | gzip > $this->backup_location"; } else { // Validate and escape database name to prevent command injection validateShellSafePath($database, 'database name'); $escapedDatabase = escapeshellarg($database); $commands[] = "docker exec $this->container_name mysqldump -u root -p\"{$this->database->mysql_root_password}\" $escapedDatabase > $this->backup_location"; } $this->backup_output = instant_remote_process($commands, $this->server, true, false, $this->timeout, disableMultiplexing: true); $this->backup_output = trim($this->backup_output); if ($this->backup_output === '') { $this->backup_output = null; } } catch (\Throwable $e) { $this->add_to_error_output($e->getMessage()); throw $e; } } private function backup_standalone_mariadb(string $database): void { try { $commands[] = 'mkdir -p '.$this->backup_dir; if ($this->backup->dump_all) { $commands[] = "docker exec $this->container_name mariadb-dump -u root -p\"{$this->database->mariadb_root_password}\" --all-databases --single-transaction --quick --lock-tables=false --compress > $this->backup_location"; } else { // Validate and escape database name to prevent command injection validateShellSafePath($database, 'database name'); $escapedDatabase = escapeshellarg($database); $commands[] = "docker exec $this->container_name mariadb-dump -u root -p\"{$this->database->mariadb_root_password}\" $escapedDatabase > $this->backup_location"; } $this->backup_output = instant_remote_process($commands, $this->server, true, false, $this->timeout, disableMultiplexing: true); $this->backup_output = trim($this->backup_output); if ($this->backup_output === '') { $this->backup_output = null; } } catch (\Throwable $e) { $this->add_to_error_output($e->getMessage()); throw $e; } } private function add_to_backup_output($output): void { if ($this->backup_output) { $this->backup_output = $this->backup_output."\n".$output; } else { $this->backup_output = $output; } } private function add_to_error_output($output): void { if ($this->error_output) { $this->error_output = $this->error_output."\n".$output; } else { $this->error_output = $output; } } private function calculate_size() { return instant_remote_process(["du -b $this->backup_location | cut -f1"], $this->server, false, false, null, disableMultiplexing: true); } private function upload_to_s3(): void { try { if (is_null($this->s3)) { return; } $key = $this->s3->key; $secret = $this->s3->secret; // $region = $this->s3->region; $bucket = $this->s3->bucket; $endpoint = $this->s3->endpoint; $this->s3->testConnection(shouldSave: true); if (data_get($this->backup, 'database_type') === \App\Models\ServiceDatabase::class) { $network = $this->database->service->destination->network; } else { $network = $this->database->destination->network; } $fullImageName = $this->getFullImageName(); $containerExists = instant_remote_process(["docker ps -a -q -f name=backup-of-{$this->backup_log_uuid}"], $this->server, false, false, null, disableMultiplexing: true); if (filled($containerExists)) { instant_remote_process(["docker rm -f backup-of-{$this->backup_log_uuid}"], $this->server, false, false, null, disableMultiplexing: true); } if (isDev()) { if ($this->database->name === 'coolify-db') { $backup_location_from = '/var/lib/docker/volumes/coolify_dev_backups_data/_data/coolify/coolify-db-'.$this->server->ip.$this->backup_file; $commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup_log_uuid} --rm -v $backup_location_from:$this->backup_location:ro {$fullImageName}"; } else { $backup_location_from = '/var/lib/docker/volumes/coolify_dev_backups_data/_data/databases/'.str($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name.$this->backup_file; $commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup_log_uuid} --rm -v $backup_location_from:$this->backup_location:ro {$fullImageName}"; } } else { $commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup_log_uuid} --rm -v $this->backup_location:$this->backup_location:ro {$fullImageName}"; } // Escape S3 credentials to prevent command injection $escapedEndpoint = escapeshellarg($endpoint); $escapedKey = escapeshellarg($key); $escapedSecret = escapeshellarg($secret); $commands[] = "docker exec backup-of-{$this->backup_log_uuid} mc alias set temporary {$escapedEndpoint} {$escapedKey} {$escapedSecret}"; $commands[] = "docker exec backup-of-{$this->backup_log_uuid} mc cp $this->backup_location temporary/$bucket{$this->backup_dir}/"; instant_remote_process($commands, $this->server, true, false, null, disableMultiplexing: true); $this->s3_uploaded = true; } catch (\Throwable $e) { $this->s3_uploaded = false; $this->add_to_error_output($e->getMessage()); throw $e; } finally { $command = "docker rm -f backup-of-{$this->backup_log_uuid}"; instant_remote_process([$command], $this->server, true, false, null, disableMultiplexing: true); } } private function getFullImageName(): string { $helperImage = config('constants.coolify.helper_image'); $latestVersion = getHelperVersion(); return "{$helperImage}:{$latestVersion}"; } public function failed(?Throwable $exception): void { Log::channel('scheduled-errors')->error('DatabaseBackup permanently failed', [ 'job' => 'DatabaseBackupJob', 'backup_id' => $this->backup->uuid, 'database' => $this->database?->name ?? 'unknown', 'database_type' => get_class($this->database ?? new \stdClass), 'server' => $this->server?->name ?? 'unknown', 'total_attempts' => $this->attempts(), 'error' => $exception?->getMessage(), 'trace' => $exception?->getTraceAsString(), ]); $log = ScheduledDatabaseBackupExecution::where('uuid', $this->backup_log_uuid)->first(); if ($log) { $log->update([ 'status' => 'failed', 'message' => 'Job permanently failed after '.$this->attempts().' attempts: '.($exception?->getMessage() ?? 'Unknown error'), 'size' => 0, 'filename' => null, 'finished_at' => Carbon::now(), ]); } // Notify team about permanent failure if ($this->team) { $databaseName = $log?->database_name ?? 'unknown'; $output = $this->backup_output ?? $exception?->getMessage() ?? 'Unknown error'; $this->team->notify(new BackupFailed($this->backup, $this->database, $output, $databaseName)); } } } ================================================ FILE: app/Jobs/DeleteResourceJob.php ================================================ onQueue('high'); } public function handle() { try { // Handle ApplicationPreview instances separately if ($this->resource instanceof ApplicationPreview) { $this->deleteApplicationPreview(); return; } switch ($this->resource->type()) { case 'application': StopApplication::run($this->resource, previewDeployments: true, dockerCleanup: $this->dockerCleanup); break; case 'standalone-postgresql': case 'standalone-redis': case 'standalone-mongodb': case 'standalone-mysql': case 'standalone-mariadb': case 'standalone-keydb': case 'standalone-dragonfly': case 'standalone-clickhouse': StopDatabase::run($this->resource, dockerCleanup: $this->dockerCleanup); break; case 'service': StopService::run($this->resource, $this->deleteConnectedNetworks, $this->dockerCleanup); DeleteService::run($this->resource, $this->deleteVolumes, $this->deleteConnectedNetworks, $this->deleteConfigurations, $this->dockerCleanup); return; } if ($this->deleteConfigurations) { $this->resource->deleteConfigurations(); } if ($this->deleteVolumes) { $this->resource->deleteVolumes(); $this->resource->persistentStorages()->delete(); } $this->resource->fileStorages()->delete(); // these are file mounts which should probably have their own flag $isDatabase = $this->resource instanceof StandalonePostgresql || $this->resource instanceof StandaloneRedis || $this->resource instanceof StandaloneMongodb || $this->resource instanceof StandaloneMysql || $this->resource instanceof StandaloneMariadb || $this->resource instanceof StandaloneKeydb || $this->resource instanceof StandaloneDragonfly || $this->resource instanceof StandaloneClickhouse; if ($isDatabase) { $this->resource->sslCertificates()->delete(); $this->resource->scheduledBackups()->delete(); $this->resource->tags()->detach(); } $this->resource->environment_variables()->delete(); if ($this->deleteConnectedNetworks && $this->resource->type() === 'application') { $this->resource->deleteConnectedNetworks(); } } catch (\Throwable $e) { throw $e; } finally { $this->resource->forceDelete(); if ($this->dockerCleanup) { $server = data_get($this->resource, 'server') ?? data_get($this->resource, 'destination.server'); if ($server) { CleanupDocker::dispatch($server, false, false); } } Artisan::queue('cleanup:stucked-resources'); } } private function deleteApplicationPreview() { $application = $this->resource->application; $server = $application->destination->server; $pull_request_id = $this->resource->pull_request_id; // Ensure the preview is soft deleted (may already be done in Livewire component) if (! $this->resource->trashed()) { $this->resource->delete(); } // Cancel any active deployments for this PR (same logic as API cancel_deployment) $activeDeployments = \App\Models\ApplicationDeploymentQueue::where('application_id', $application->id) ->where('pull_request_id', $pull_request_id) ->whereIn('status', [ \App\Enums\ApplicationDeploymentStatus::QUEUED->value, \App\Enums\ApplicationDeploymentStatus::IN_PROGRESS->value, ]) ->get(); foreach ($activeDeployments as $activeDeployment) { try { // Mark deployment as cancelled $activeDeployment->update([ 'status' => \App\Enums\ApplicationDeploymentStatus::CANCELLED_BY_USER->value, ]); // Add cancellation log entry $activeDeployment->addLogEntry('Deployment cancelled: Pull request closed.', 'stderr'); // Check if helper container exists and kill it $deployment_uuid = $activeDeployment->deployment_uuid; $escapedDeploymentUuid = escapeshellarg($deployment_uuid); $checkCommand = "docker ps -a --filter name={$escapedDeploymentUuid} --format '{{.Names}}'"; $containerExists = instant_remote_process([$checkCommand], $server); if ($containerExists && str($containerExists)->trim()->isNotEmpty()) { instant_remote_process(["docker rm -f {$escapedDeploymentUuid}"], $server); $activeDeployment->addLogEntry('Deployment container stopped.'); } else { $activeDeployment->addLogEntry('Helper container not yet started. Deployment will be cancelled when job checks status.'); } } catch (\Throwable $e) { // Silently handle errors during deployment cancellation } } try { if ($server->isSwarm()) { $escapedStackName = escapeshellarg("{$application->uuid}-{$pull_request_id}"); instant_remote_process(["docker stack rm {$escapedStackName}"], $server); } else { $containers = getCurrentApplicationContainerStatus($server, $application->id, $pull_request_id)->toArray(); $this->stopPreviewContainers($containers, $server); } } catch (\Throwable $e) { // Log the error but don't fail the job \Log::warning('Error stopping preview containers for application '.$application->uuid.', PR #'.$pull_request_id.': '.$e->getMessage()); } // Finally, force delete to trigger resource cleanup $this->resource->forceDelete(); } private function stopPreviewContainers(array $containers, $server, int $timeout = 30) { if (empty($containers)) { return; } $containerNames = []; foreach ($containers as $container) { $containerNames[] = str_replace('/', '', $container['Names']); } $containerList = implode(' ', array_map('escapeshellarg', $containerNames)); $commands = [ "docker stop -t $timeout $containerList", "docker rm -f $containerList", ]; instant_remote_process( command: $commands, server: $server, throwError: false ); } } ================================================ FILE: app/Jobs/DockerCleanupJob.php ================================================ server->uuid))->expireAfter(600)->dontRelease()]; } public function __construct( public Server $server, public bool $manualCleanup = false, public bool $deleteUnusedVolumes = false, public bool $deleteUnusedNetworks = false ) {} public function handle(): void { try { if (! $this->server->isFunctional()) { return; } $this->execution_log = DockerCleanupExecution::create([ 'server_id' => $this->server->id, ]); $this->usageBefore = $this->server->getDiskUsage(); if ($this->manualCleanup || $this->server->settings->force_docker_cleanup) { $cleanup_log = CleanupDocker::run( server: $this->server, deleteUnusedVolumes: $this->deleteUnusedVolumes, deleteUnusedNetworks: $this->deleteUnusedNetworks ); $usageAfter = $this->server->getDiskUsage(); $message = ($this->manualCleanup ? 'Manual' : 'Forced').' Docker cleanup job executed successfully. Disk usage before: '.$this->usageBefore.'%, Disk usage after: '.$usageAfter.'%.'; $this->execution_log->update([ 'status' => 'success', 'message' => $message, 'cleanup_log' => $cleanup_log, ]); $this->server->team?->notify(new DockerCleanupSuccess($this->server, $message)); event(new DockerCleanupDone($this->execution_log)); return; } if (str($this->usageBefore)->isEmpty() || $this->usageBefore === null || $this->usageBefore === 0) { $cleanup_log = CleanupDocker::run( server: $this->server, deleteUnusedVolumes: $this->deleteUnusedVolumes, deleteUnusedNetworks: $this->deleteUnusedNetworks ); $message = 'Docker cleanup job executed successfully, but no disk usage could be determined.'; $this->execution_log->update([ 'status' => 'success', 'message' => $message, 'cleanup_log' => $cleanup_log, ]); $this->server->team?->notify(new DockerCleanupSuccess($this->server, $message)); event(new DockerCleanupDone($this->execution_log)); return; } if ($this->usageBefore >= $this->server->settings->docker_cleanup_threshold) { $cleanup_log = CleanupDocker::run( server: $this->server, deleteUnusedVolumes: $this->deleteUnusedVolumes, deleteUnusedNetworks: $this->deleteUnusedNetworks ); $usageAfter = $this->server->getDiskUsage(); $diskSaved = $this->usageBefore - $usageAfter; if ($diskSaved > 0) { $message = 'Saved '.$diskSaved.'% disk space. Disk usage before: '.$this->usageBefore.'%, Disk usage after: '.$usageAfter.'%.'; } else { $message = 'Docker cleanup job executed successfully, but no disk space was saved. Disk usage before: '.$this->usageBefore.'%, Disk usage after: '.$usageAfter.'%.'; } $this->execution_log->update([ 'status' => 'success', 'message' => $message, 'cleanup_log' => $cleanup_log, ]); $this->server->team?->notify(new DockerCleanupSuccess($this->server, $message)); event(new DockerCleanupDone($this->execution_log)); } else { $message = 'No cleanup needed for '.$this->server->name; $this->execution_log->update([ 'status' => 'success', 'message' => $message, ]); $this->server->team?->notify(new DockerCleanupSuccess($this->server, $message)); event(new DockerCleanupDone($this->execution_log)); } } catch (\Throwable $e) { if ($this->execution_log) { $this->execution_log->update([ 'status' => 'failed', 'message' => $e->getMessage(), ]); event(new DockerCleanupDone($this->execution_log)); } $this->server->team?->notify(new DockerCleanupFailed($this->server, 'Docker cleanup job failed with the following error: '.$e->getMessage())); throw $e; } finally { if ($this->execution_log) { $this->execution_log->update([ 'finished_at' => Carbon::now()->toImmutable(), ]); } } } } ================================================ FILE: app/Jobs/GithubAppPermissionJob.php ================================================ github_app); $response = Http::withHeaders([ 'Authorization' => "Bearer $github_access_token", 'Accept' => 'application/vnd.github+json', ])->get("{$this->github_app->api_url}/app"); if (! $response->successful()) { throw new \RuntimeException('Failed to fetch GitHub app permissions: '.$response->body()); } $response = $response->json(); $permissions = data_get($response, 'permissions'); $this->github_app->contents = data_get($permissions, 'contents'); $this->github_app->metadata = data_get($permissions, 'metadata'); $this->github_app->pull_requests = data_get($permissions, 'pull_requests'); $this->github_app->administration = data_get($permissions, 'administration'); $this->github_app->save(); $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); } catch (\Throwable $e) { send_internal_notification('GithubAppPermissionJob failed with: '.$e->getMessage()); throw $e; } } } ================================================ FILE: app/Jobs/ProcessGithubPullRequestWebhook.php ================================================ onQueue('high'); } public function handle(): void { $application = Application::find($this->applicationId); if (! $application) { return; } $githubApp = $this->githubAppId ? GithubApp::find($this->githubAppId) : null; if ($this->action === 'closed' || $this->action === 'close') { $this->handleClosedAction($application); return; } if ($this->action === 'opened' || $this->action === 'synchronize' || $this->action === 'reopened') { $this->handleOpenAction($application, $githubApp); } } private function handleClosedAction(Application $application): void { $found = ApplicationPreview::where('application_id', $application->id) ->where('pull_request_id', $this->pullRequestId) ->first(); if ($found) { ApplicationPullRequestUpdateJob::dispatchSync( application: $application, preview: $found, status: ProcessStatus::CLOSED ); CleanupPreviewDeployment::run($application, $this->pullRequestId, $found); } } private function handleOpenAction(Application $application, ?GithubApp $githubApp): void { if (! $application->isPRDeployable()) { return; } // Check if PR deployments from public contributors are restricted if (! $application->settings->is_pr_deployments_public_enabled) { $trustedAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR', 'CONTRIBUTOR']; if (! in_array($this->authorAssociation, $trustedAssociations)) { return; } } // Get changed files for watch path filtering $changed_files = collect(); $repository_parts = explode('/', $this->fullName); $owner = $repository_parts[0] ?? ''; $repo = $repository_parts[1] ?? ''; if ($this->action === 'synchronize' && $this->beforeSha && $this->afterSha) { // For synchronize events, get files changed between before and after commits $changed_files = collect(getGithubCommitRangeFiles($githubApp, $owner, $repo, $this->beforeSha, $this->afterSha)); } elseif ($this->action === 'opened' || $this->action === 'reopened') { // For opened/reopened events, get all files in the PR $changed_files = collect(getGithubPullRequestFiles($githubApp, $owner, $repo, $this->pullRequestId)); } // Apply watch path filtering $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if (! $is_watch_path_triggered && ! blank($application->watch_paths)) { return; } // Create ApplicationPreview if not exists $found = ApplicationPreview::where('application_id', $application->id) ->where('pull_request_id', $this->pullRequestId) ->first(); if (! $found) { if ($application->build_pack === 'dockercompose') { $preview = ApplicationPreview::create([ 'git_type' => 'github', 'application_id' => $application->id, 'pull_request_id' => $this->pullRequestId, 'pull_request_html_url' => $this->pullRequestHtmlUrl, 'docker_compose_domains' => $application->docker_compose_domains, ]); $preview->generate_preview_fqdn_compose(); } else { $preview = ApplicationPreview::create([ 'git_type' => 'github', 'application_id' => $application->id, 'pull_request_id' => $this->pullRequestId, 'pull_request_html_url' => $this->pullRequestHtmlUrl, ]); $preview->generate_preview_fqdn(); } } // Queue the deployment $deployment_uuid = new Cuid2; queue_application_deployment( application: $application, pull_request_id: $this->pullRequestId, deployment_uuid: $deployment_uuid, force_rebuild: false, commit: $this->commitSha, is_webhook: true, git_type: 'github' ); } } ================================================ FILE: app/Jobs/PullChangelog.php ================================================ onQueue('high'); } public function handle(): void { try { // Fetch from CDN instead of GitHub API to avoid rate limits $cdnUrl = config('constants.coolify.releases_url'); $response = Http::retry(3, 1000) ->timeout(30) ->get($cdnUrl); if ($response->successful()) { $releases = $response->json(); // Limit to 10 releases for processing (same as before) $releases = array_slice($releases, 0, 10); $changelog = $this->transformReleasesToChangelog($releases); // Group entries by month and save them $this->saveChangelogEntries($changelog); } else { // Log error instead of sending notification Log::error('PullChangelogFromGitHub: Failed to fetch from CDN', [ 'status' => $response->status(), 'url' => $cdnUrl, ]); } } catch (\Throwable $e) { // Log error instead of sending notification Log::error('PullChangelogFromGitHub: Exception occurred', [ 'message' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } } private function transformReleasesToChangelog(array $releases): array { $entries = []; foreach ($releases as $release) { // Skip drafts and pre-releases if desired if ($release['draft']) { continue; } $publishedAt = Carbon::parse($release['published_at']); $entry = [ 'tag_name' => $release['tag_name'], 'title' => $release['name'] ?: $release['tag_name'], 'content' => $release['body'] ?: 'No release notes available.', 'published_at' => $publishedAt->toISOString(), ]; $entries[] = $entry; } return $entries; } private function saveChangelogEntries(array $entries): void { // Create changelogs directory if it doesn't exist $changelogsDir = base_path('changelogs'); if (! File::exists($changelogsDir)) { File::makeDirectory($changelogsDir, 0755, true); } // Group entries by year-month $groupedEntries = []; foreach ($entries as $entry) { $date = Carbon::parse($entry['published_at']); $monthKey = $date->format('Y-m'); if (! isset($groupedEntries[$monthKey])) { $groupedEntries[$monthKey] = []; } $groupedEntries[$monthKey][] = $entry; } // Save each month's entries to separate files foreach ($groupedEntries as $month => $monthEntries) { // Sort entries by published date (newest first) usort($monthEntries, function ($a, $b) { return Carbon::parse($b['published_at'])->timestamp - Carbon::parse($a['published_at'])->timestamp; }); $monthData = [ 'entries' => $monthEntries, 'last_updated' => now()->toISOString(), ]; $filePath = base_path("changelogs/{$month}.json"); File::put($filePath, json_encode($monthData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } } } ================================================ FILE: app/Jobs/PullTemplatesFromCDN.php ================================================ onQueue('high'); } public function handle(): void { try { if (isDev()) { return; } $response = Http::retry(3, 1000)->get(config('constants.services.official')); if ($response->successful()) { $services = $response->json(); File::put(base_path('templates/'.config('constants.services.file_name')), json_encode($services)); } else { send_internal_notification('PullTemplatesAndVersions failed with: '.$response->status().' '.$response->body()); } } catch (\Throwable $e) { send_internal_notification('PullTemplatesAndVersions failed with: '.$e->getMessage()); } } } ================================================ FILE: app/Jobs/PushServerUpdateJob.php ================================================ server->uuid))->expireAfter(30)->dontRelease()]; } public function backoff(): int { return isDev() ? 1 : 3; } public function __construct(public Server $server, public $data) { $this->containers = collect(); $this->foundApplicationIds = collect(); $this->foundDatabaseUuids = collect(); $this->foundServiceApplicationIds = collect(); $this->foundApplicationPreviewsIds = collect(); $this->foundServiceDatabaseIds = collect(); $this->applicationContainerStatuses = collect(); $this->serviceContainerStatuses = collect(); $this->allApplicationIds = collect(); $this->allDatabaseUuids = collect(); $this->allTcpProxyUuids = collect(); $this->allServiceApplicationIds = collect(); $this->allServiceDatabaseIds = collect(); } public function handle() { // Defensive initialization for Collection properties to handle queue deserialization edge cases $this->serviceContainerStatuses ??= collect(); $this->applicationContainerStatuses ??= collect(); $this->foundApplicationIds ??= collect(); $this->foundDatabaseUuids ??= collect(); $this->foundServiceApplicationIds ??= collect(); $this->foundApplicationPreviewsIds ??= collect(); $this->foundServiceDatabaseIds ??= collect(); $this->allApplicationIds ??= collect(); $this->allDatabaseUuids ??= collect(); $this->allTcpProxyUuids ??= collect(); $this->allServiceApplicationIds ??= collect(); $this->allServiceDatabaseIds ??= collect(); // TODO: Swarm is not supported yet if (! $this->data) { throw new \Exception('No data provided'); } $data = collect($this->data); $this->server->sentinelHeartbeat(); $this->containers = collect(data_get($data, 'containers')); $filesystemUsageRoot = data_get($data, 'filesystem_usage_root.used_percentage'); // Only dispatch storage check when disk percentage actually changes $storageCacheKey = 'storage-check:'.$this->server->id; $lastPercentage = Cache::get($storageCacheKey); if ($lastPercentage === null || (string) $lastPercentage !== (string) $filesystemUsageRoot) { Cache::put($storageCacheKey, $filesystemUsageRoot, 600); ServerStorageCheckJob::dispatch($this->server, $filesystemUsageRoot); } if ($this->containers->isEmpty()) { return; } $this->applications = $this->server->applications(); $this->databases = $this->server->databases(); $this->previews = $this->server->previews(); // Eager load service applications and databases to avoid N+1 queries $this->services = $this->server->services() ->with(['applications:id,service_id', 'databases:id,service_id']) ->get(); $this->allApplicationIds = $this->applications->filter(function ($application) { return $application->additional_servers_count === 0; })->pluck('id'); $this->allApplicationsWithAdditionalServers = $this->applications->filter(function ($application) { return $application->additional_servers_count > 0; }); $this->allApplicationPreviewsIds = $this->previews->map(function ($preview) { return $preview->application_id.':'.$preview->pull_request_id; }); $this->allDatabaseUuids = $this->databases->pluck('uuid'); $this->allTcpProxyUuids = $this->databases->where('is_public', true)->pluck('uuid'); // Use eager-loaded relationships instead of querying in loop $this->allServiceApplicationIds = $this->services->flatMap(fn ($service) => $service->applications->pluck('id')); $this->allServiceDatabaseIds = $this->services->flatMap(fn ($service) => $service->databases->pluck('id')); foreach ($this->containers as $container) { $containerStatus = data_get($container, 'state', 'exited'); $rawHealthStatus = data_get($container, 'health_status'); $containerHealth = $rawHealthStatus ?? 'unknown'; // Only append health status if container is not exited if ($containerStatus !== 'exited') { $containerStatus = "$containerStatus:$containerHealth"; } $labels = collect(data_get($container, 'labels')); $coolify_managed = $labels->has('coolify.managed'); if (! $coolify_managed) { continue; } $name = data_get($container, 'name'); if ($name === 'coolify-log-drain' && $this->isRunning($containerStatus)) { $this->foundLogDrainContainer = true; } if ($labels->has('coolify.applicationId')) { $applicationId = $labels->get('coolify.applicationId'); $pullRequestId = $labels->get('coolify.pullRequestId', '0'); try { if ($pullRequestId === '0') { if ($this->allApplicationIds->contains($applicationId)) { $this->foundApplicationIds->push($applicationId); } // Store container status for aggregation if (! $this->applicationContainerStatuses->has($applicationId)) { $this->applicationContainerStatuses->put($applicationId, collect()); } $containerName = $labels->get('com.docker.compose.service'); if ($containerName) { $this->applicationContainerStatuses->get($applicationId)->put($containerName, $containerStatus); } } else { $previewKey = $applicationId.':'.$pullRequestId; if ($this->allApplicationPreviewsIds->contains($previewKey)) { $this->foundApplicationPreviewsIds->push($previewKey); } $this->updateApplicationPreviewStatus($applicationId, $pullRequestId, $containerStatus); } } catch (\Exception $e) { } } elseif ($labels->has('coolify.serviceId')) { $serviceId = $labels->get('coolify.serviceId'); $subType = $labels->get('coolify.service.subType'); $subId = $labels->get('coolify.service.subId'); if (empty(trim((string) $subId))) { continue; } if ($subType === 'application') { $this->foundServiceApplicationIds->push($subId); // Store container status for aggregation $key = $serviceId.':'.$subType.':'.$subId; if (! $this->serviceContainerStatuses->has($key)) { $this->serviceContainerStatuses->put($key, collect()); } $containerName = $labels->get('com.docker.compose.service'); if ($containerName) { $this->serviceContainerStatuses->get($key)->put($containerName, $containerStatus); } } elseif ($subType === 'database') { $this->foundServiceDatabaseIds->push($subId); // Store container status for aggregation $key = $serviceId.':'.$subType.':'.$subId; if (! $this->serviceContainerStatuses->has($key)) { $this->serviceContainerStatuses->put($key, collect()); } $containerName = $labels->get('com.docker.compose.service'); if ($containerName) { $this->serviceContainerStatuses->get($key)->put($containerName, $containerStatus); } } } else { $uuid = $labels->get('com.docker.compose.service'); $type = $labels->get('coolify.type'); if ($name === 'coolify-proxy' && $this->isRunning($containerStatus)) { $this->foundProxy = true; } elseif ($type === 'service' && $this->isRunning($containerStatus)) { } else { if ($this->allDatabaseUuids->contains($uuid) && $this->isActiveOrTransient($containerStatus)) { $this->foundDatabaseUuids->push($uuid); // TCP proxy should only be started/managed when database is actually running if ($this->allTcpProxyUuids->contains($uuid) && $this->isRunning($containerStatus)) { $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: true); } else { $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: false); } } } } } $this->updateProxyStatus(); $this->updateNotFoundApplicationStatus(); $this->updateNotFoundApplicationPreviewStatus(); $this->updateNotFoundDatabaseStatus(); $this->updateNotFoundServiceStatus(); $this->updateAdditionalServersStatus(); // Aggregate multi-container application statuses $this->aggregateMultiContainerStatuses(); // Aggregate multi-container service statuses $this->aggregateServiceContainerStatuses(); $this->checkLogDrainContainer(); } private function aggregateMultiContainerStatuses() { if ($this->applicationContainerStatuses->isEmpty()) { return; } foreach ($this->applicationContainerStatuses as $applicationId => $containerStatuses) { $application = $this->applications->where('id', $applicationId)->first(); if (! $application) { continue; } // Parse docker compose to check for excluded containers $dockerComposeRaw = data_get($application, 'docker_compose_raw'); $excludedContainers = $this->getExcludedContainersFromDockerCompose($dockerComposeRaw); // Filter out excluded containers $relevantStatuses = $containerStatuses->filter(function ($status, $containerName) use ($excludedContainers) { return ! $excludedContainers->contains($containerName); }); // If all containers are excluded, calculate status from excluded containers if ($relevantStatuses->isEmpty()) { $aggregatedStatus = $this->calculateExcludedStatusFromStrings($containerStatuses); if ($aggregatedStatus && $application->status !== $aggregatedStatus) { $application->status = $aggregatedStatus; $application->save(); } elseif ($aggregatedStatus) { $application->update(['last_online_at' => now()]); } continue; } // Use ContainerStatusAggregator service for state machine logic // Use preserveRestarting: true so applications show "Restarting" instead of "Degraded" $aggregator = new ContainerStatusAggregator; $aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, 0, preserveRestarting: true); // Update application status with aggregated result if ($aggregatedStatus && $application->status !== $aggregatedStatus) { $application->status = $aggregatedStatus; $application->save(); } elseif ($aggregatedStatus) { $application->update(['last_online_at' => now()]); } } } private function aggregateServiceContainerStatuses() { if ($this->serviceContainerStatuses->isEmpty()) { return; } foreach ($this->serviceContainerStatuses as $key => $containerStatuses) { // Parse key: serviceId:subType:subId [$serviceId, $subType, $subId] = explode(':', $key); if (empty($subId)) { continue; } $service = $this->services->where('id', $serviceId)->first(); if (! $service) { continue; } // Get the service sub-resource (ServiceApplication or ServiceDatabase) $subResource = null; if ($subType === 'application') { $subResource = $service->applications->where('id', $subId)->first(); } elseif ($subType === 'database') { $subResource = $service->databases->where('id', $subId)->first(); } if (! $subResource) { continue; } // Parse docker compose from service to check for excluded containers $dockerComposeRaw = data_get($service, 'docker_compose_raw'); $excludedContainers = $this->getExcludedContainersFromDockerCompose($dockerComposeRaw); // Filter out excluded containers $relevantStatuses = $containerStatuses->filter(function ($status, $containerName) use ($excludedContainers) { return ! $excludedContainers->contains($containerName); }); // If all containers are excluded, calculate status from excluded containers if ($relevantStatuses->isEmpty()) { $aggregatedStatus = $this->calculateExcludedStatusFromStrings($containerStatuses); if ($aggregatedStatus && $subResource->status !== $aggregatedStatus) { $subResource->status = $aggregatedStatus; $subResource->save(); } elseif ($aggregatedStatus) { $subResource->update(['last_online_at' => now()]); } continue; } // Use ContainerStatusAggregator service for state machine logic // NOTE: Sentinel does NOT provide restart count data, so maxRestartCount is always 0 // Use preserveRestarting: true so individual sub-resources show "Restarting" instead of "Degraded" $aggregator = new ContainerStatusAggregator; $aggregatedStatus = $aggregator->aggregateFromStrings($relevantStatuses, 0, preserveRestarting: true); // Update service sub-resource status with aggregated result if ($aggregatedStatus && $subResource->status !== $aggregatedStatus) { $subResource->status = $aggregatedStatus; $subResource->save(); } elseif ($aggregatedStatus) { $subResource->update(['last_online_at' => now()]); } } } private function updateApplicationStatus(string $applicationId, string $containerStatus) { $application = $this->applications->where('id', $applicationId)->first(); if (! $application) { return; } if ($application->status !== $containerStatus) { $application->status = $containerStatus; $application->save(); } else { $application->update(['last_online_at' => now()]); } } private function updateApplicationPreviewStatus(string $applicationId, string $pullRequestId, string $containerStatus) { $application = $this->previews->where('application_id', $applicationId) ->where('pull_request_id', $pullRequestId) ->first(); if (! $application) { return; } if ($application->status !== $containerStatus) { $application->status = $containerStatus; $application->save(); } else { $application->update(['last_online_at' => now()]); } } private function updateNotFoundApplicationStatus() { $notFoundApplicationIds = $this->allApplicationIds->diff($this->foundApplicationIds); if ($notFoundApplicationIds->isEmpty()) { return; } // Only protection: Verify we received any container data at all // If containers collection is completely empty, Sentinel might have failed if ($this->containers->isEmpty()) { return; } // Batch update: mark all not-found applications as exited (excluding already exited ones) Application::whereIn('id', $notFoundApplicationIds) ->where('status', 'not like', 'exited%') ->update(['status' => 'exited']); } private function updateNotFoundApplicationPreviewStatus() { $notFoundApplicationPreviewsIds = $this->allApplicationPreviewsIds->diff($this->foundApplicationPreviewsIds); if ($notFoundApplicationPreviewsIds->isEmpty()) { return; } // Only protection: Verify we received any container data at all // If containers collection is completely empty, Sentinel might have failed if ($this->containers->isEmpty()) { return; } // Collect IDs of previews that need to be marked as exited $previewIdsToUpdate = collect(); foreach ($notFoundApplicationPreviewsIds as $previewKey) { // Parse the previewKey format "application_id:pull_request_id" $parts = explode(':', $previewKey); if (count($parts) !== 2) { continue; } $applicationId = $parts[0]; $pullRequestId = $parts[1]; $applicationPreview = $this->previews->where('application_id', $applicationId) ->where('pull_request_id', $pullRequestId) ->first(); if ($applicationPreview && ! str($applicationPreview->status)->startsWith('exited')) { $previewIdsToUpdate->push($applicationPreview->id); } } // Batch update all collected preview IDs if ($previewIdsToUpdate->isNotEmpty()) { ApplicationPreview::whereIn('id', $previewIdsToUpdate)->update(['status' => 'exited']); } } private function updateProxyStatus() { // If proxy is not found, start it if ($this->server->isProxyShouldRun()) { if ($this->foundProxy === false) { try { if (CheckProxy::run($this->server)) { StartProxy::run($this->server, async: false); $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server)); } } catch (\Throwable $e) { } } else { // Connect proxy to networks periodically (every 10 min) to avoid excessive job dispatches. // On-demand triggers (new network, service deploy) use dispatchSync() and bypass this. $proxyCacheKey = 'connect-proxy:'.$this->server->id; if (! Cache::has($proxyCacheKey)) { Cache::put($proxyCacheKey, true, 600); ConnectProxyToNetworksJob::dispatch($this->server); } } } } private function updateDatabaseStatus(string $databaseUuid, string $containerStatus, bool $tcpProxy = false) { $database = $this->databases->where('uuid', $databaseUuid)->first(); if (! $database) { return; } if ($database->status !== $containerStatus) { $database->status = $containerStatus; $database->save(); } else { $database->update(['last_online_at' => now()]); } if ($this->isRunning($containerStatus) && $tcpProxy) { $tcpProxyContainerFound = $this->containers->filter(function ($value, $key) use ($databaseUuid) { return data_get($value, 'name') === "$databaseUuid-proxy" && data_get($value, 'state') === 'running'; })->first(); if (! $tcpProxyContainerFound) { StartDatabaseProxy::dispatch($database); $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server)); } } elseif ($this->isRunning($containerStatus) && ! $tcpProxy) { // Clean up orphaned proxy containers when is_public=false $orphanedProxy = $this->containers->filter(function ($value, $key) use ($databaseUuid) { return data_get($value, 'name') === "$databaseUuid-proxy" && data_get($value, 'state') === 'running'; })->first(); if ($orphanedProxy) { StopDatabaseProxy::dispatch($database); } } } private function updateNotFoundDatabaseStatus() { $notFoundDatabaseUuids = $this->allDatabaseUuids->diff($this->foundDatabaseUuids); if ($notFoundDatabaseUuids->isEmpty()) { return; } // Only protection: Verify we received any container data at all // If containers collection is completely empty, Sentinel might have failed if ($this->containers->isEmpty()) { return; } $notFoundDatabaseUuids->each(function ($databaseUuid) { $database = $this->databases->where('uuid', $databaseUuid)->first(); if ($database) { if (! str($database->status)->startsWith('exited')) { $database->update([ 'status' => 'exited', 'restart_count' => 0, 'last_restart_at' => null, 'last_restart_type' => null, ]); } if ($database->is_public) { StopDatabaseProxy::dispatch($database); } } }); } private function updateNotFoundServiceStatus() { $notFoundServiceApplicationIds = $this->allServiceApplicationIds->diff($this->foundServiceApplicationIds); $notFoundServiceDatabaseIds = $this->allServiceDatabaseIds->diff($this->foundServiceDatabaseIds); // Batch update service applications if ($notFoundServiceApplicationIds->isNotEmpty()) { ServiceApplication::whereIn('id', $notFoundServiceApplicationIds) ->where('status', '!=', 'exited') ->update(['status' => 'exited']); } // Batch update service databases if ($notFoundServiceDatabaseIds->isNotEmpty()) { ServiceDatabase::whereIn('id', $notFoundServiceDatabaseIds) ->where('status', '!=', 'exited') ->update(['status' => 'exited']); } } private function updateAdditionalServersStatus() { $this->allApplicationsWithAdditionalServers->each(function ($application) { ComplexStatusCheck::run($application); }); } private function isRunning(string $containerStatus) { return str($containerStatus)->contains('running'); } /** * Check if container is in an active or transient state. * Active states: running * Transient states: restarting, starting, created, paused * * These states indicate the container exists and should be tracked. * Terminal states (exited, dead, removing) should NOT be tracked. */ private function isActiveOrTransient(string $containerStatus): bool { return str($containerStatus)->contains('running') || str($containerStatus)->contains('restarting') || str($containerStatus)->contains('starting') || str($containerStatus)->contains('created') || str($containerStatus)->contains('paused'); } private function checkLogDrainContainer() { if ($this->server->isLogDrainEnabled() && $this->foundLogDrainContainer === false) { StartLogDrain::dispatch($this->server); } } } ================================================ FILE: app/Jobs/RegenerateSslCertJob.php ================================================ server_id) { $query->where('server_id', $this->server_id); } if (! $this->force_regeneration) { $query->where('valid_until', '<=', now()->addDays(14)); } $query->where('is_ca_certificate', false); $regenerated = collect(); $query->cursor()->each(function ($certificate) use ($regenerated) { try { $caCert = $certificate->server->sslCertificates() ->where('is_ca_certificate', true) ->first(); if (! $caCert) { Log::error("No CA certificate found for server_id: {$certificate->server_id}"); return; } SSLHelper::generateSslCertificate( commonName: $certificate->common_name, subjectAlternativeNames: $certificate->subject_alternative_names, resourceType: $certificate->resource_type, resourceId: $certificate->resource_id, serverId: $certificate->server_id, configurationDir: $certificate->configuration_dir, mountPath: $certificate->mount_path, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, ); $regenerated->push($certificate); } catch (\Exception $e) { Log::error('Failed to regenerate SSL certificate: '.$e->getMessage()); } }); if ($regenerated->isNotEmpty()) { $this->team?->notify(new SslExpirationNotification($regenerated)); } } } ================================================ FILE: app/Jobs/RestartProxyJob.php ================================================ server->uuid))->expireAfter(120)->dontRelease()]; } public function __construct(public Server $server) {} public function handle() { try { // Set status to restarting $this->server->proxy->status = 'restarting'; $this->server->proxy->force_stop = false; $this->server->save(); // Build combined stop + start commands for a single activity $commands = $this->buildRestartCommands(); // Create activity and dispatch immediately - returns Activity right away // The remote_process runs asynchronously, so UI gets activity ID instantly $activity = remote_process( $commands, $this->server, callEventOnFinish: 'ProxyStatusChanged', callEventData: $this->server->id ); // Store activity ID and notify UI immediately with it $this->activity_id = $activity->id; ProxyStatusChangedUI::dispatch($this->server->team_id, $this->activity_id); } catch (\Throwable $e) { // Set error status $this->server->proxy->status = 'error'; $this->server->save(); // Notify UI of error ProxyStatusChangedUI::dispatch($this->server->team_id); // Clear dashboard cache on error ProxyDashboardCacheService::clearCache($this->server); return handleError($e); } } /** * Build combined stop + start commands for proxy restart. * This creates a single command sequence that shows all logs in one activity. */ private function buildRestartCommands(): array { $proxyType = $this->server->proxyType(); $containerName = $this->server->isSwarm() ? 'coolify-proxy_traefik' : 'coolify-proxy'; $proxy_path = $this->server->proxyPath(); $stopTimeout = 30; // Get proxy configuration $configuration = GetProxyConfiguration::run($this->server); if (! $configuration) { throw new \Exception('Configuration is not synced'); } SaveProxyConfiguration::run($this->server, $configuration); $docker_compose_yml_base64 = base64_encode($configuration); $this->server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value(); $this->server->save(); $commands = collect([]); // === STOP PHASE === $commands = $commands->merge([ "echo 'Stopping proxy...'", "docker stop -t=$stopTimeout $containerName 2>/dev/null || true", "docker rm -f $containerName 2>/dev/null || true", '# Wait for container to be fully removed', 'for i in {1..15}; do', " if ! docker ps -a --format \"{{.Names}}\" | grep -q \"^$containerName$\"; then", " echo 'Container removed successfully.'", ' break', ' fi', ' echo "Waiting for container to be removed... ($i/15)"', ' sleep 1', ' # Force remove on each iteration in case it got stuck', " docker rm -f $containerName 2>/dev/null || true", 'done', '# Final verification and force cleanup', "if docker ps -a --format \"{{.Names}}\" | grep -q \"^$containerName$\"; then", " echo 'Container still exists after wait, forcing removal...'", " docker rm -f $containerName 2>/dev/null || true", ' sleep 2', 'fi', "echo 'Proxy stopped successfully.'", ]); // === START PHASE === if ($this->server->isSwarmManager()) { $commands = $commands->merge([ "echo 'Starting proxy (Swarm mode)...'", "mkdir -p $proxy_path/dynamic", "cd $proxy_path", "echo 'Creating required Docker Compose file.'", "echo 'Starting coolify-proxy.'", 'docker stack deploy --detach=true -c docker-compose.yml coolify-proxy', "echo 'Successfully started coolify-proxy.'", ]); } else { if (isDev() && $proxyType === ProxyTypes::CADDY->value) { $proxy_path = '/data/coolify/proxy/caddy'; } $caddyfile = 'import /dynamic/*.caddy'; $commands = $commands->merge([ "echo 'Starting proxy...'", "mkdir -p $proxy_path/dynamic", "cd $proxy_path", "echo '$caddyfile' > $proxy_path/dynamic/Caddyfile", "echo 'Creating required Docker Compose file.'", "echo 'Pulling docker image.'", 'docker compose pull', ]); // Ensure required networks exist BEFORE docker compose up $commands = $commands->merge(ensureProxyNetworksExist($this->server)); $commands = $commands->merge([ "echo 'Starting coolify-proxy.'", 'docker compose up -d --wait --remove-orphans', "echo 'Successfully started coolify-proxy.'", ]); $commands = $commands->merge(connectProxyToNetworks($this->server)); } return $commands->toArray(); } } ================================================ FILE: app/Jobs/ScheduledJobManager.php ================================================ onQueue($this->determineQueue()); } private function determineQueue(): string { $preferredQueue = 'crons'; $fallbackQueue = 'high'; $configuredQueues = explode(',', env('HORIZON_QUEUES', 'high,default')); return in_array($preferredQueue, $configuredQueues) ? $preferredQueue : $fallbackQueue; } /** * Get the middleware the job should pass through. */ public function middleware(): array { // Self-healing: clear any stale lock before WithoutOverlapping tries to acquire it. // Stale locks (TTL = -1) can occur during upgrades, Redis restarts, or edge cases. // @see https://github.com/coollabsio/coolify/issues/8327 self::clearStaleLockIfPresent(); return [ (new WithoutOverlapping('scheduled-job-manager')) ->expireAfter(90) // Lock expires after 90s to handle high-load environments with many tasks ->dontRelease(), // Don't re-queue on lock conflict ]; } /** * Clear a stale WithoutOverlapping lock if it has no TTL (TTL = -1). * * This provides continuous self-healing since it runs every time the job is dispatched. * Stale locks permanently block all scheduled job executions with no user-visible error. */ private static function clearStaleLockIfPresent(): void { try { $cachePrefix = config('cache.prefix', ''); $lockKey = $cachePrefix.'laravel-queue-overlap:'.self::class.':scheduled-job-manager'; $ttl = Redis::connection('default')->ttl($lockKey); if ($ttl === -1) { Redis::connection('default')->del($lockKey); Log::channel('scheduled')->warning('Cleared stale ScheduledJobManager lock', [ 'lock_key' => $lockKey, ]); } } catch (\Throwable $e) { // Never let lock cleanup failure prevent the job from running Log::channel('scheduled-errors')->error('Failed to check/clear stale lock', [ 'error' => $e->getMessage(), ]); } } public function handle(): void { // Freeze the execution time at the start of the job $this->executionTime = Carbon::now(); $this->dispatchedCount = 0; $this->skippedCount = 0; Log::channel('scheduled')->info('ScheduledJobManager started', [ 'execution_time' => $this->executionTime->toIso8601String(), ]); // Process backups - don't let failures stop task processing try { $this->processScheduledBackups(); } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Failed to process scheduled backups', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } // Process tasks - don't let failures stop the job manager try { $this->processScheduledTasks(); } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Failed to process scheduled tasks', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } // Process Docker cleanups - don't let failures stop the job manager try { $this->processDockerCleanups(); } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Failed to process docker cleanups', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } Log::channel('scheduled')->info('ScheduledJobManager completed', [ 'execution_time' => $this->executionTime->toIso8601String(), 'duration_ms' => $this->executionTime->diffInMilliseconds(Carbon::now()), 'dispatched' => $this->dispatchedCount, 'skipped' => $this->skippedCount, ]); // Write heartbeat so the UI can detect when the scheduler has stopped try { Cache::put('scheduled-job-manager:heartbeat', now()->toIso8601String(), 300); } catch (\Throwable) { // Non-critical; don't let heartbeat failure affect the job } } private function processScheduledBackups(): void { $backups = ScheduledDatabaseBackup::with(['database']) ->where('enabled', true) ->get(); foreach ($backups as $backup) { try { $server = $backup->server(); $skipReason = $this->getBackupSkipReason($backup, $server); if ($skipReason !== null) { $this->skippedCount++; $this->logSkip('backup', $skipReason, [ 'backup_id' => $backup->id, 'database_id' => $backup->database_id, 'database_type' => $backup->database_type, 'team_id' => $backup->team_id ?? null, ]); continue; } $serverTimezone = data_get($server->settings, 'server_timezone', config('app.timezone')); if (validate_timezone($serverTimezone) === false) { $serverTimezone = config('app.timezone'); } $frequency = $backup->frequency; if (isset(VALID_CRON_STRINGS[$frequency])) { $frequency = VALID_CRON_STRINGS[$frequency]; } if ($this->shouldRunNow($frequency, $serverTimezone, "scheduled-backup:{$backup->id}")) { DatabaseBackupJob::dispatch($backup); $this->dispatchedCount++; Log::channel('scheduled')->info('Backup dispatched', [ 'backup_id' => $backup->id, 'database_id' => $backup->database_id, 'database_type' => $backup->database_type, 'team_id' => $backup->team_id ?? null, 'server_id' => $server->id, ]); } } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Error processing backup', [ 'backup_id' => $backup->id, 'error' => $e->getMessage(), ]); } } } private function processScheduledTasks(): void { $tasks = ScheduledTask::with(['service', 'application']) ->where('enabled', true) ->get(); foreach ($tasks as $task) { try { $server = $task->server(); // Phase 1: Critical checks (always — cheap, handles orphans and infra issues) $criticalSkip = $this->getTaskCriticalSkipReason($task, $server); if ($criticalSkip !== null) { $this->skippedCount++; $this->logSkip('task', $criticalSkip, [ 'task_id' => $task->id, 'task_name' => $task->name, 'team_id' => $server?->team_id, ]); continue; } $serverTimezone = data_get($server->settings, 'server_timezone', config('app.timezone')); if (validate_timezone($serverTimezone) === false) { $serverTimezone = config('app.timezone'); } $frequency = $task->frequency; if (isset(VALID_CRON_STRINGS[$frequency])) { $frequency = VALID_CRON_STRINGS[$frequency]; } if (! $this->shouldRunNow($frequency, $serverTimezone, "scheduled-task:{$task->id}")) { continue; } // Phase 2: Runtime checks (only when cron is due — avoids noise for stopped resources) $runtimeSkip = $this->getTaskRuntimeSkipReason($task); if ($runtimeSkip !== null) { $this->skippedCount++; $this->logSkip('task', $runtimeSkip, [ 'task_id' => $task->id, 'task_name' => $task->name, 'team_id' => $server->team_id, ]); continue; } ScheduledTaskJob::dispatch($task); $this->dispatchedCount++; Log::channel('scheduled')->info('Task dispatched', [ 'task_id' => $task->id, 'task_name' => $task->name, 'team_id' => $server->team_id, 'server_id' => $server->id, ]); } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Error processing task', [ 'task_id' => $task->id, 'error' => $e->getMessage(), ]); } } } private function getBackupSkipReason(ScheduledDatabaseBackup $backup, ?Server $server): ?string { if (blank(data_get($backup, 'database'))) { $backup->delete(); return 'database_deleted'; } if (blank($server)) { $backup->delete(); return 'server_deleted'; } if ($server->isFunctional() === false) { return 'server_not_functional'; } if (isCloud() && data_get($server->team->subscription, 'stripe_invoice_paid', false) === false && $server->team->id !== 0) { return 'subscription_unpaid'; } return null; } private function getTaskCriticalSkipReason(ScheduledTask $task, ?Server $server): ?string { if (blank($server)) { $task->delete(); return 'server_deleted'; } if ($server->isFunctional() === false) { return 'server_not_functional'; } if (isCloud() && data_get($server->team->subscription, 'stripe_invoice_paid', false) === false && $server->team->id !== 0) { return 'subscription_unpaid'; } if (! $task->service && ! $task->application) { $task->delete(); return 'resource_deleted'; } return null; } private function getTaskRuntimeSkipReason(ScheduledTask $task): ?string { if ($task->application && str($task->application->status)->contains('running') === false) { return 'application_not_running'; } if ($task->service && str($task->service->status)->contains('running') === false) { return 'service_not_running'; } return null; } /** * Determine if a cron schedule should run now. * * When a dedupKey is provided, uses getPreviousRunDate() + last-dispatch tracking * instead of isDue(). This is resilient to queue delays — even if the job is delayed * by minutes, it still catches the missed cron window. Without dedupKey, falls back * to simple isDue() check. */ private function shouldRunNow(string $frequency, string $timezone, ?string $dedupKey = null): bool { $cron = new CronExpression($frequency); $baseTime = $this->executionTime ?? Carbon::now(); $executionTime = $baseTime->copy()->setTimezone($timezone); // No dedup key → simple isDue check (used by docker cleanups) if ($dedupKey === null) { return $cron->isDue($executionTime); } // Get the most recent time this cron was due (including current minute) $previousDue = Carbon::instance($cron->getPreviousRunDate($executionTime, allowCurrentDate: true)); $lastDispatched = Cache::get($dedupKey); if ($lastDispatched === null) { // First run after restart or cache loss: only fire if actually due right now. // Seed the cache so subsequent runs can use tolerance/catch-up logic. $isDue = $cron->isDue($executionTime); if ($isDue) { Cache::put($dedupKey, $executionTime->toIso8601String(), 86400); } return $isDue; } // Subsequent runs: fire if there's been a due time since last dispatch if ($previousDue->gt(Carbon::parse($lastDispatched))) { Cache::put($dedupKey, $executionTime->toIso8601String(), 86400); return true; } return false; } private function processDockerCleanups(): void { // Get all servers that need cleanup checks $servers = $this->getServersForCleanup(); foreach ($servers as $server) { try { $skipReason = $this->getDockerCleanupSkipReason($server); if ($skipReason !== null) { $this->skippedCount++; $this->logSkip('docker_cleanup', $skipReason, [ 'server_id' => $server->id, 'server_name' => $server->name, 'team_id' => $server->team_id, ]); continue; } $serverTimezone = data_get($server->settings, 'server_timezone', config('app.timezone')); if (validate_timezone($serverTimezone) === false) { $serverTimezone = config('app.timezone'); } $frequency = data_get($server->settings, 'docker_cleanup_frequency', '0 * * * *'); if (isset(VALID_CRON_STRINGS[$frequency])) { $frequency = VALID_CRON_STRINGS[$frequency]; } // Use the frozen execution time for consistent evaluation if ($this->shouldRunNow($frequency, $serverTimezone)) { DockerCleanupJob::dispatch( $server, false, $server->settings->delete_unused_volumes, $server->settings->delete_unused_networks ); $this->dispatchedCount++; Log::channel('scheduled')->info('Docker cleanup dispatched', [ 'server_id' => $server->id, 'server_name' => $server->name, 'team_id' => $server->team_id, ]); } } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Error processing docker cleanup', [ 'server_id' => $server->id, 'server_name' => $server->name, 'error' => $e->getMessage(), ]); } } } private function getServersForCleanup(): Collection { $query = Server::with('settings') ->where('ip', '!=', '1.2.3.4'); if (isCloud()) { $servers = $query->whereRelation('team.subscription', 'stripe_invoice_paid', true)->get(); $own = Team::find(0)->servers()->with('settings')->get(); return $servers->merge($own); } return $query->get(); } private function getDockerCleanupSkipReason(Server $server): ?string { if (! $server->isFunctional()) { return 'server_not_functional'; } // In cloud, check subscription status (except team 0) if (isCloud() && $server->team_id !== 0) { if (data_get($server->team->subscription, 'stripe_invoice_paid', false) === false) { return 'subscription_unpaid'; } } return null; } private function logSkip(string $type, string $reason, array $context = []): void { Log::channel('scheduled')->info(ucfirst(str_replace('_', ' ', $type)).' skipped', array_merge([ 'type' => $type, 'skip_reason' => $reason, 'execution_time' => $this->executionTime?->toIso8601String(), ], $context)); } } ================================================ FILE: app/Jobs/ScheduledTaskJob.php ================================================ onQueue('high'); $this->task = $task; if ($service = $task->service()->first()) { $this->resource = $service; } elseif ($application = $task->application()->first()) { $this->resource = $application; } else { throw new \RuntimeException('ScheduledTaskJob failed: No resource found.'); } $this->team = Team::findOrFail($task->team_id); $this->server_timezone = $this->getServerTimezone(); // Set timeout from task configuration $this->timeout = $this->task->timeout ?? 300; } private function getServerTimezone(): string { if ($this->resource instanceof Application) { return $this->resource->destination->server->settings->server_timezone; } elseif ($this->resource instanceof Service) { return $this->resource->server->settings->server_timezone; } return 'UTC'; } public function handle(): void { $startTime = Carbon::now(); try { $this->task_log = ScheduledTaskExecution::create([ 'scheduled_task_id' => $this->task->id, 'started_at' => $startTime, 'retry_count' => $this->attempts() - 1, ]); // Store execution ID for timeout handling $this->executionId = $this->task_log->id; $this->server = $this->resource->destination->server; if ($this->resource->type() === 'application') { $containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id, 0); if ($containers->count() > 0) { $containers->each(function ($container) { $this->containers[] = str_replace('/', '', $container['Names']); }); } } elseif ($this->resource->type() === 'service') { $this->resource->applications()->get()->each(function ($application) { if (str(data_get($application, 'status'))->contains('running')) { $this->containers[] = data_get($application, 'name').'-'.data_get($this->resource, 'uuid'); } }); $this->resource->databases()->get()->each(function ($database) { if (str(data_get($database, 'status'))->contains('running')) { $this->containers[] = data_get($database, 'name').'-'.data_get($this->resource, 'uuid'); } }); } if (count($this->containers) == 0) { throw new \Exception('ScheduledTaskJob failed: No containers running.'); } if (count($this->containers) > 1 && empty($this->task->container)) { throw new \Exception('ScheduledTaskJob failed: More than one container exists but no container name was provided.'); } foreach ($this->containers as $containerName) { if (count($this->containers) == 1 || str_starts_with($containerName, $this->task->container.'-'.$this->resource->uuid)) { $cmd = "sh -c '".str_replace("'", "'\''", $this->task->command)."'"; $exec = "docker exec {$containerName} {$cmd}"; // Disable SSH multiplexing to prevent race conditions when multiple tasks run concurrently // See: https://github.com/coollabsio/coolify/issues/6736 $this->task_output = instant_remote_process([$exec], $this->server, true, false, $this->timeout, disableMultiplexing: true); $this->task_log->update([ 'status' => 'success', 'message' => $this->task_output, ]); $this->team?->notify(new TaskSuccess($this->task, $this->task_output)); return; } } // No valid container was found. throw new NonReportableException('ScheduledTaskJob failed: No valid container was found. Is the container name correct?'); } catch (\Throwable $e) { if ($this->task_log) { $this->task_log->update([ 'status' => 'failed', 'message' => $this->task_output ?? $e->getMessage(), ]); } // Log the error to the scheduled-errors channel Log::channel('scheduled-errors')->error('ScheduledTask execution failed', [ 'job' => 'ScheduledTaskJob', 'task_id' => $this->task->uuid, 'task_name' => $this->task->name, 'server' => $this->server?->name ?? 'unknown', 'attempt' => $this->attempts(), 'error' => $e->getMessage(), ]); // Only notify and throw on final failure // Re-throw to trigger Laravel's retry mechanism with backoff throw $e; } finally { ScheduledTaskDone::dispatch($this->team->id); if ($this->task_log) { $finishedAt = Carbon::now(); $duration = round($startTime->floatDiffInSeconds($finishedAt), 2); $this->task_log->update([ 'finished_at' => $finishedAt->toImmutable(), 'duration' => $duration, ]); } } } /** * Calculate the number of seconds to wait before retrying the job. */ public function backoff(): array { return [30, 60, 120]; // 30s, 60s, 120s between retries } /** * Handle a job failure. */ public function failed(?\Throwable $exception): void { Log::channel('scheduled-errors')->error('ScheduledTask permanently failed', [ 'job' => 'ScheduledTaskJob', 'task_id' => $this->task->uuid, 'task_name' => $this->task->name, 'server' => $this->server?->name ?? 'unknown', 'total_attempts' => $this->attempts(), 'error' => $exception?->getMessage(), 'trace' => $exception?->getTraceAsString(), ]); // Reload execution log from database // When a job times out, failed() is called in a fresh process with the original // queue payload, so $executionId will be null. We need to query for the latest execution. $execution = null; // Try to find execution using stored ID first (works for non-timeout failures) if ($this->executionId) { $execution = ScheduledTaskExecution::find($this->executionId); } // If no stored ID or not found, query for the most recent execution log for this task if (! $execution) { $execution = ScheduledTaskExecution::query() ->where('scheduled_task_id', $this->task->id) ->orderBy('created_at', 'desc') ->first(); } // Last resort: check task_log property if (! $execution && $this->task_log) { $execution = $this->task_log; } if ($execution) { $errorMessage = 'Job permanently failed after '.$this->attempts().' attempts'; if ($exception) { $errorMessage .= ': '.$exception->getMessage(); } $execution->update([ 'status' => 'failed', 'message' => $errorMessage, 'error_details' => $exception?->getTraceAsString(), 'finished_at' => Carbon::now()->toImmutable(), ]); } else { Log::channel('scheduled-errors')->warning('Could not find execution log to update', [ 'execution_id' => $this->executionId, 'task_id' => $this->task->uuid, ]); } // Notify team about permanent failure $this->team?->notify(new TaskFailed($this->task, $exception?->getMessage() ?? 'Unknown error')); } } ================================================ FILE: app/Jobs/SendMessageToDiscordJob.php ================================================ onQueue('high'); } /** * Execute the job. */ public function handle(): void { Http::post($this->webhookUrl, $this->message->toPayload()); } } ================================================ FILE: app/Jobs/SendMessageToPushoverJob.php ================================================ onQueue('high'); } /** * Execute the job. */ public function handle(): void { $response = Http::post('https://api.pushover.net/1/messages.json', $this->message->toPayload($this->token, $this->user)); if ($response->failed()) { throw new \RuntimeException('Pushover notification failed with '.$response->status().' status code.'.$response->body()); } } } ================================================ FILE: app/Jobs/SendMessageToSlackJob.php ================================================ onQueue('high'); } public function handle(): void { if ($this->isSlackWebhook()) { $this->sendToSlack(); return; } /** * This works with Mattermost and as a fallback also with Slack, the notifications just look slightly different and advanced formatting for slack is not supported with Mattermost. * * @see https://github.com/coollabsio/coolify/pull/6139#issuecomment-3756777708 */ $this->sendToMattermost(); } private function isSlackWebhook(): bool { $parsedUrl = parse_url($this->webhookUrl); if ($parsedUrl === false) { return false; } $scheme = $parsedUrl['scheme'] ?? ''; $host = $parsedUrl['host'] ?? ''; return $scheme === 'https' && $host === 'hooks.slack.com'; } private function sendToSlack(): void { Http::post($this->webhookUrl, [ 'text' => $this->message->title, 'blocks' => [ [ 'type' => 'section', 'text' => [ 'type' => 'plain_text', 'text' => 'Coolify Notification', ], ], ], 'attachments' => [ [ 'color' => $this->message->color, 'blocks' => [ [ 'type' => 'header', 'text' => [ 'type' => 'plain_text', 'text' => $this->message->title, ], ], [ 'type' => 'section', 'text' => [ 'type' => 'mrkdwn', 'text' => $this->message->description, ], ], ], ], ], ]); } /** * @todo v5 refactor: Extract this into a separate SendMessageToMattermostJob.php triggered via the "mattermost" notification channel type. */ private function sendToMattermost(): void { $username = config('app.name'); Http::post($this->webhookUrl, [ 'username' => $username, 'attachments' => [ [ 'title' => $this->message->title, 'color' => $this->message->color, 'text' => $this->message->description, 'footer' => $username, ], ], ]); } } ================================================ FILE: app/Jobs/SendMessageToTelegramJob.php ================================================ onQueue('high'); } /** * Execute the job. */ public function handle(): void { $url = 'https://api.telegram.org/bot'.$this->token.'/sendMessage'; $inlineButtons = []; if (! empty($this->buttons)) { foreach ($this->buttons as $button) { $buttonUrl = data_get($button, 'url'); $text = data_get($button, 'text', 'Click here'); if ($buttonUrl && Str::contains($buttonUrl, 'http://localhost')) { $buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl); } $inlineButtons[] = [ 'text' => $text, 'url' => $buttonUrl, ]; } } $payload = [ // 'parse_mode' => 'markdown', 'reply_markup' => json_encode([ 'inline_keyboard' => [ [...$inlineButtons], ], ]), 'chat_id' => $this->chatId, 'text' => $this->text, ]; if ($this->threadId) { $payload['message_thread_id'] = $this->threadId; } $response = Http::post($url, $payload); if ($response->failed()) { throw new \RuntimeException('Telegram notification failed with '.$response->status().' status code.'.$response->body()); } } } ================================================ FILE: app/Jobs/SendWebhookJob.php ================================================ onQueue('high'); } /** * Execute the job. */ public function handle(): void { if (isDev()) { ray('Sending webhook notification', [ 'url' => $this->webhookUrl, 'payload' => $this->payload, ]); } $response = Http::post($this->webhookUrl, $this->payload); if (isDev()) { ray('Webhook response', [ 'status' => $response->status(), 'body' => $response->body(), 'successful' => $response->successful(), ]); } } } ================================================ FILE: app/Jobs/ServerCheckJob.php ================================================ server->uuid))->expireAfter(60)->dontRelease()]; } public function __construct(public Server $server) {} public function failed(?\Throwable $exception): void { if ($exception instanceof \Illuminate\Queue\TimeoutExceededException) { Log::warning('ServerCheckJob timed out', [ 'server_id' => $this->server->id, 'server_name' => $this->server->name, ]); // Delete the queue job so it doesn't appear in Horizon's failed list. $this->job?->delete(); } } public function handle() { try { if ($this->server->serverStatus() === false) { return 'Server is not reachable or not ready.'; } if (! $this->server->isSwarmWorker() && ! $this->server->isBuildServer()) { ['containers' => $this->containers, 'containerReplicates' => $containerReplicates] = $this->server->getContainers(); if (is_null($this->containers)) { return 'No containers found.'; } GetContainersStatus::run($this->server, $this->containers, $containerReplicates); if ($this->server->isSentinelEnabled()) { CheckAndStartSentinelJob::dispatch($this->server); } if ($this->server->isLogDrainEnabled()) { $this->checkLogDrainContainer(); } if ($this->server->proxySet() && ! $this->server->proxy->force_stop) { $this->server->proxyType(); $foundProxyContainer = $this->containers->filter(function ($value, $key) { if ($this->server->isSwarm()) { return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik'; } else { return data_get($value, 'Name') === '/coolify-proxy'; } })->first(); if (! $foundProxyContainer) { try { $shouldStart = CheckProxy::run($this->server); if ($shouldStart) { StartProxy::run($this->server, async: false); $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server)); } } catch (\Throwable $e) { } } else { $this->server->proxy->status = data_get($foundProxyContainer, 'State.Status'); $this->server->save(); ConnectProxyToNetworksJob::dispatchSync($this->server); } } } } catch (\Throwable $e) { return handleError($e); } } private function checkLogDrainContainer() { $foundLogDrainContainer = $this->containers->filter(function ($value, $key) { return data_get($value, 'Name') === '/coolify-log-drain'; })->first(); if ($foundLogDrainContainer) { $status = data_get($foundLogDrainContainer, 'State.Status'); if ($status !== 'running') { StartLogDrain::dispatch($this->server); } } else { StartLogDrain::dispatch($this->server); } } } ================================================ FILE: app/Jobs/ServerCleanupMux.php ================================================ server->serverStatus() === false) { return 'Server is not reachable or not ready.'; } SshMultiplexingHelper::removeMuxFile($this->server); } catch (\Throwable $e) { return handleError($e); } } } ================================================ FILE: app/Jobs/ServerConnectionCheckJob.php ================================================ server->uuid))->expireAfter(45)->dontRelease()]; } private function disableSshMux(): void { $configRepository = app(ConfigurationRepository::class); $configRepository->disableSshMux(); } public function handle() { try { // Check if server is disabled if ($this->server->settings->force_disabled) { $this->server->settings->update([ 'is_reachable' => false, 'is_usable' => false, ]); Log::debug('ServerConnectionCheck: Server is disabled', [ 'server_id' => $this->server->id, 'server_name' => $this->server->name, ]); return; } // Check Hetzner server status if applicable if ($this->server->hetzner_server_id && $this->server->cloudProviderToken) { $this->checkHetznerStatus(); } // Temporarily disable mux if requested if ($this->disableMux) { $this->disableSshMux(); } // Check basic connectivity first $isReachable = $this->checkConnection(); if (! $isReachable) { $this->server->settings->update([ 'is_reachable' => false, 'is_usable' => false, ]); Log::warning('ServerConnectionCheck: Server not reachable', [ 'server_id' => $this->server->id, 'server_name' => $this->server->name, 'server_ip' => $this->server->ip, ]); return; } // Server is reachable, check if Docker is available $isUsable = $this->checkDockerAvailability(); $this->server->settings->update([ 'is_reachable' => true, 'is_usable' => $isUsable, ]); } catch (\Throwable $e) { Log::error('ServerConnectionCheckJob failed', [ 'error' => $e->getMessage(), 'server_id' => $this->server->id, ]); $this->server->settings->update([ 'is_reachable' => false, 'is_usable' => false, ]); return; } } public function failed(?\Throwable $exception): void { if ($exception instanceof \Illuminate\Queue\TimeoutExceededException) { Log::warning('ServerConnectionCheckJob timed out', [ 'server_id' => $this->server->id, 'server_name' => $this->server->name, ]); $this->server->settings->update([ 'is_reachable' => false, 'is_usable' => false, ]); // Delete the queue job so it doesn't appear in Horizon's failed list. $this->job?->delete(); } } private function checkHetznerStatus(): void { $status = null; try { $hetznerService = new \App\Services\HetznerService($this->server->cloudProviderToken->token); $serverData = $hetznerService->getServer($this->server->hetzner_server_id); $status = $serverData['status'] ?? null; } catch (\Throwable $e) { Log::debug('ServerConnectionCheck: Hetzner status check failed', [ 'server_id' => $this->server->id, 'error' => $e->getMessage(), ]); } if ($this->server->hetzner_server_status !== $status) { $this->server->update(['hetzner_server_status' => $status]); $this->server->hetzner_server_status = $status; if ($status === 'off') { ray('Server is powered off, marking as unreachable'); throw new \Exception('Server is powered off'); } } } private function checkConnection(): bool { try { // Use instant_remote_process with a simple command // This will automatically handle mux, sudo, IPv6, Cloudflare tunnel, etc. $output = instant_remote_process_with_timeout( ['ls -la /'], $this->server, false // don't throw error ); return $output !== null; } catch (\Throwable $e) { Log::debug('ServerConnectionCheck: Connection check failed', [ 'server_id' => $this->server->id, 'error' => $e->getMessage(), ]); return false; } } private function checkDockerAvailability(): bool { try { // Use instant_remote_process to check Docker // The function will automatically handle sudo for non-root users $output = instant_remote_process_with_timeout( ['docker version --format json'], $this->server, false // don't throw error ); if ($output === null) { return false; } // Try to parse the JSON output to ensure Docker is really working $output = trim($output); if (! empty($output)) { $dockerInfo = json_decode($output, true); return isset($dockerInfo['Server']['Version']); } return false; } catch (\Throwable $e) { Log::debug('ServerConnectionCheck: Docker check failed', [ 'server_id' => $this->server->id, 'error' => $e->getMessage(), ]); return false; } } } ================================================ FILE: app/Jobs/ServerFilesFromServerJob.php ================================================ onQueue('high'); } public function handle() { $this->resource->getFilesFromServer(isInit: true); } } ================================================ FILE: app/Jobs/ServerLimitCheckJob.php ================================================ team->servers; $servers_count = $servers->count(); $number_of_servers_to_disable = $servers_count - $this->team->limits; if ($number_of_servers_to_disable > 0) { $servers = $servers->sortbyDesc('created_at'); $servers_to_disable = $servers->take($number_of_servers_to_disable); $servers_to_disable->each(function ($server) { $server->forceDisableServer(); $this->team->notify(new ForceDisabled($server)); }); } elseif ($number_of_servers_to_disable <= 0) { $servers->each(function ($server) { if ($server->isForceDisabled()) { $server->forceEnableServer(); $this->team->notify(new ForceEnabled($server)); } }); } } catch (\Throwable $e) { send_internal_notification('ServerLimitCheckJob failed with: '.$e->getMessage()); return handleError($e); } } } ================================================ FILE: app/Jobs/ServerManagerJob.php ================================================ onQueue('high'); } public function handle(): void { // Freeze the execution time at the start of the job $this->executionTime = Carbon::now(); if (isCloud()) { $this->checkFrequency = '*/5 * * * *'; } $this->settings = instanceSettings(); $this->instanceTimezone = $this->settings->instance_timezone ?: config('app.timezone'); if (validate_timezone($this->instanceTimezone) === false) { $this->instanceTimezone = config('app.timezone'); } // Get all servers to process $servers = $this->getServers(); // Dispatch ServerConnectionCheck for all servers efficiently $this->dispatchConnectionChecks($servers); // Process server-specific scheduled tasks $this->processScheduledTasks($servers); } private function getServers(): Collection { $allServers = Server::with('settings')->where('ip', '!=', '1.2.3.4'); if (isCloud()) { $servers = $allServers->whereRelation('team.subscription', 'stripe_invoice_paid', true)->get(); $own = Team::find(0)->servers()->with('settings')->get(); return $servers->merge($own); } else { return $allServers->get(); } } private function dispatchConnectionChecks(Collection $servers): void { if ($this->shouldRunNow($this->checkFrequency)) { $servers->each(function (Server $server) { try { // Skip SSH connection check if Sentinel is healthy — its heartbeat already proves connectivity if ($server->isSentinelEnabled() && $server->isSentinelLive()) { return; } ServerConnectionCheckJob::dispatch($server); } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Failed to dispatch ServerConnectionCheck', [ 'server_id' => $server->id, 'server_name' => $server->name, 'error' => get_class($e).': '.$e->getMessage(), ]); } }); } } private function processScheduledTasks(Collection $servers): void { foreach ($servers as $server) { try { $this->processServerTasks($server); } catch (\Exception $e) { Log::channel('scheduled-errors')->error('Error processing server tasks', [ 'server_id' => $server->id, 'server_name' => $server->name, 'error' => get_class($e).': '.$e->getMessage(), ]); } } } private function processServerTasks(Server $server): void { // Get server timezone (used for all scheduled tasks) $serverTimezone = data_get($server->settings, 'server_timezone', $this->instanceTimezone); if (validate_timezone($serverTimezone) === false) { $serverTimezone = config('app.timezone'); } // Check if we should run sentinel-based checks $lastSentinelUpdate = $server->sentinel_updated_at; $waitTime = $server->waitBeforeDoingSshCheck(); $sentinelOutOfSync = Carbon::parse($lastSentinelUpdate)->isBefore($this->executionTime->copy()->subSeconds($waitTime)); if ($sentinelOutOfSync) { // Dispatch ServerCheckJob if Sentinel is out of sync if ($this->shouldRunNow($this->checkFrequency, $serverTimezone)) { ServerCheckJob::dispatch($server); } } $isSentinelEnabled = $server->isSentinelEnabled(); $shouldRestartSentinel = $isSentinelEnabled && $this->shouldRunNow('0 0 * * *', $serverTimezone); // Dispatch Sentinel restart if due (daily for Sentinel-enabled servers) if ($shouldRestartSentinel) { CheckAndStartSentinelJob::dispatch($server); } // Dispatch ServerStorageCheckJob if due (only when Sentinel is out of sync or disabled) // When Sentinel is active, PushServerUpdateJob handles storage checks with real-time data if ($sentinelOutOfSync) { $serverDiskUsageCheckFrequency = data_get($server->settings, 'server_disk_usage_check_frequency', '0 23 * * *'); if (isset(VALID_CRON_STRINGS[$serverDiskUsageCheckFrequency])) { $serverDiskUsageCheckFrequency = VALID_CRON_STRINGS[$serverDiskUsageCheckFrequency]; } $shouldRunStorageCheck = $this->shouldRunNow($serverDiskUsageCheckFrequency, $serverTimezone); if ($shouldRunStorageCheck) { ServerStorageCheckJob::dispatch($server); } } // Dispatch ServerPatchCheckJob if due (weekly) $shouldRunPatchCheck = $this->shouldRunNow('0 0 * * 0', $serverTimezone); if ($shouldRunPatchCheck) { // Weekly on Sunday at midnight ServerPatchCheckJob::dispatch($server); } // Note: CheckAndStartSentinelJob is only dispatched daily (line above) for version updates. // Crash recovery is handled by sentinelOutOfSync → ServerCheckJob → CheckAndStartSentinelJob. } private function shouldRunNow(string $frequency, ?string $timezone = null): bool { $cron = new CronExpression($frequency); // Use the frozen execution time, not the current time $baseTime = $this->executionTime ?? Carbon::now(); $executionTime = $baseTime->copy()->setTimezone($timezone ?? config('app.timezone')); return $cron->isDue($executionTime); } } ================================================ FILE: app/Jobs/ServerPatchCheckJob.php ================================================ server->uuid))->expireAfter(600)->dontRelease()]; } public function __construct(public Server $server) {} public function handle(): void { try { if ($this->server->serverStatus() === false) { return; } $team = data_get($this->server, 'team'); if (! $team) { return; } // Check for updates $patchData = CheckUpdates::run($this->server); if (isset($patchData['error'])) { $team->notify(new ServerPatchCheck($this->server, $patchData)); return; // Skip if there's an error checking for updates } $totalUpdates = $patchData['total_updates'] ?? 0; // Only send notification if there are updates available if ($totalUpdates > 0) { $team->notify(new ServerPatchCheck($this->server, $patchData)); } } catch (\Throwable $e) { // Log error but don't fail the job \Illuminate\Support\Facades\Log::error('ServerPatchCheckJob failed: '.$e->getMessage(), [ 'server_id' => $this->server->id, 'server_name' => $this->server->name, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } } } ================================================ FILE: app/Jobs/ServerStorageCheckJob.php ================================================ $this->server->id, 'server_name' => $this->server->name, ]); // Delete the queue job so it doesn't appear in Horizon's failed list. $this->job?->delete(); } } public function handle() { try { if ($this->server->isFunctional() === false) { return 'Server is not functional.'; } $team = data_get($this->server, 'team'); $serverDiskUsageNotificationThreshold = data_get($this->server, 'settings.server_disk_usage_notification_threshold'); if (is_null($this->percentage)) { $this->percentage = $this->server->storageCheck(); } if (! $this->percentage) { return 'No percentage could be retrieved.'; } if ($this->percentage > $serverDiskUsageNotificationThreshold) { $executed = RateLimiter::attempt( 'high-disk-usage:'.$this->server->id, $maxAttempts = 0, function () use ($team, $serverDiskUsageNotificationThreshold) { $team->notify(new HighDiskUsage($this->server, $this->percentage, $serverDiskUsageNotificationThreshold)); }, $decaySeconds = 3600, ); if (! $executed) { return 'Too many messages sent!'; } } else { RateLimiter::hit('high-disk-usage:'.$this->server->id, 600); } } catch (\Throwable $e) { return handleError($e); } } } ================================================ FILE: app/Jobs/ServerStorageSaveJob.php ================================================ onQueue('high'); } public function handle() { $this->localFileVolume->saveStorageOnServer(); } } ================================================ FILE: app/Jobs/StripeProcessJob.php ================================================ onQueue('high'); } public function handle(): void { try { $excludedPlans = config('subscription.stripe_excluded_plans'); $type = data_get($this->event, 'type'); $this->type = $type; $data = data_get($this->event, 'data.object'); switch ($type) { case 'radar.early_fraud_warning.created': $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); $id = data_get($data, 'id'); $charge = data_get($data, 'charge'); if ($charge) { $stripe->refunds->create(['charge' => $charge]); } $pi = data_get($data, 'payment_intent'); $piData = $stripe->paymentIntents->retrieve($pi, []); $customerId = data_get($piData, 'customer'); $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); if ($subscription) { $subscriptionId = data_get($subscription, 'stripe_subscription_id'); $stripe->subscriptions->cancel($subscriptionId, []); $subscription->update([ 'stripe_invoice_paid' => false, ]); send_internal_notification("Early fraud warning created Refunded, subscription canceled. Charge: {$charge}, id: {$id}, pi: {$pi}"); } else { send_internal_notification("Early fraud warning: subscription not found. Charge: {$charge}, id: {$id}, pi: {$pi}"); throw new \RuntimeException("Early fraud warning: subscription not found. Charge: {$charge}, id: {$id}, pi: {$pi}"); } break; case 'checkout.session.completed': $clientReferenceId = data_get($data, 'client_reference_id'); if (is_null($clientReferenceId)) { // send_internal_notification('Checkout session completed without client reference id.'); break; } $userId = Str::before($clientReferenceId, ':'); $teamId = Str::after($clientReferenceId, ':'); $subscriptionId = data_get($data, 'subscription'); $customerId = data_get($data, 'customer'); $team = Team::find($teamId); $found = $team->members->where('id', $userId)->first(); if (! $found->isAdmin()) { // send_internal_notification("User {$userId} is not an admin or owner of team {$team->id}, customerid: {$customerId}, subscriptionid: {$subscriptionId}."); throw new \RuntimeException("User {$userId} is not an admin or owner of team {$team->id}, customerid: {$customerId}, subscriptionid: {$subscriptionId}."); } $subscription = Subscription::where('team_id', $teamId)->first(); if ($subscription) { // send_internal_notification('Old subscription activated for team: '.$teamId); $subscription->update([ 'stripe_subscription_id' => $subscriptionId, 'stripe_customer_id' => $customerId, 'stripe_invoice_paid' => true, 'stripe_past_due' => false, ]); } else { // send_internal_notification('New subscription for team: '.$teamId); Subscription::create([ 'team_id' => $teamId, 'stripe_subscription_id' => $subscriptionId, 'stripe_customer_id' => $customerId, 'stripe_invoice_paid' => true, 'stripe_past_due' => false, ]); } break; case 'invoice.paid': $customerId = data_get($data, 'customer'); $invoiceAmount = data_get($data, 'amount_paid', 0); $subscriptionId = data_get($data, 'subscription'); $planId = data_get($data, 'lines.data.0.plan.id'); if (Str::contains($excludedPlans, $planId)) { // send_internal_notification('Subscription excluded.'); break; } $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); if (! $subscription) { throw new \RuntimeException("No subscription found for customer: {$customerId}"); } if ($subscription->stripe_subscription_id) { try { $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); $stripeSubscription = $stripe->subscriptions->retrieve( $subscription->stripe_subscription_id ); switch ($stripeSubscription->status) { case 'active': $subscription->update([ 'stripe_invoice_paid' => true, 'stripe_past_due' => false, ]); break; case 'past_due': $subscription->update([ 'stripe_invoice_paid' => true, 'stripe_past_due' => true, ]); break; case 'canceled': case 'incomplete_expired': case 'unpaid': send_internal_notification( "Invoice paid for {$stripeSubscription->status} subscription. ". "Customer: {$customerId}, Amount: \${$invoiceAmount}" ); break; default: VerifyStripeSubscriptionStatusJob::dispatch($subscription) ->delay(now()->addSeconds(20)); break; } } catch (\Exception $e) { VerifyStripeSubscriptionStatusJob::dispatch($subscription) ->delay(now()->addSeconds(20)); send_internal_notification( 'Failed to verify subscription status in invoice.paid: '.$e->getMessage() ); } } else { VerifyStripeSubscriptionStatusJob::dispatch($subscription) ->delay(now()->addSeconds(20)); } break; case 'invoice.payment_failed': $customerId = data_get($data, 'customer'); $invoiceId = data_get($data, 'id'); $paymentIntentId = data_get($data, 'payment_intent'); $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); if (! $subscription) { // send_internal_notification('invoice.payment_failed failed but no subscription found in Coolify for customer: '.$customerId); throw new \RuntimeException("No subscription found for customer: {$customerId}"); } $team = data_get($subscription, 'team'); if (! $team) { // send_internal_notification('invoice.payment_failed failed but no team found in Coolify for customer: '.$customerId); throw new \RuntimeException("No team found in Coolify for customer: {$customerId}"); } // Verify payment status with Stripe API before sending failure notification if ($paymentIntentId) { try { $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); $paymentIntent = $stripe->paymentIntents->retrieve($paymentIntentId); if (in_array($paymentIntent->status, ['processing', 'succeeded', 'requires_action', 'requires_confirmation'])) { break; } if (! $subscription->stripe_invoice_paid && $subscription->created_at->diffInMinutes(now()) < 5) { SubscriptionInvoiceFailedJob::dispatch($team)->delay(now()->addSeconds(60)); break; } } catch (\Exception $e) { } } if (! $subscription->stripe_invoice_paid) { SubscriptionInvoiceFailedJob::dispatch($team); // send_internal_notification('Invoice payment failed: '.$customerId); } break; case 'payment_intent.payment_failed': $customerId = data_get($data, 'customer'); $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); if (! $subscription) { // send_internal_notification('payment_intent.payment_failed, no subscription found in Coolify for customer: '.$customerId); throw new \RuntimeException("No subscription found in Coolify for customer: {$customerId}"); } if ($subscription->stripe_invoice_paid) { // send_internal_notification('payment_intent.payment_failed but invoice is active for customer: '.$customerId); return; } // send_internal_notification('Subscription payment failed for customer: '.$customerId); break; case 'customer.subscription.created': $customerId = data_get($data, 'customer'); $subscriptionId = data_get($data, 'id'); $teamId = data_get($data, 'metadata.team_id'); $userId = data_get($data, 'metadata.user_id'); if (! $teamId || ! $userId) { $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); if ($subscription) { throw new \RuntimeException("Subscription already exists for customer: {$customerId}"); } throw new \RuntimeException('No team id or user id found'); } $team = Team::find($teamId); $found = $team->members->where('id', $userId)->first(); if (! $found->isAdmin()) { // send_internal_notification("User {$userId} is not an admin or owner of team {$team->id}, customerid: {$customerId}."); throw new \RuntimeException("User {$userId} is not an admin or owner of team {$team->id}, customerid: {$customerId}."); } $subscription = Subscription::where('team_id', $teamId)->first(); if ($subscription) { // send_internal_notification("Subscription already exists for team: {$teamId}"); throw new \RuntimeException("Subscription already exists for team: {$teamId}"); } else { Subscription::create([ 'team_id' => $teamId, 'stripe_subscription_id' => $subscriptionId, 'stripe_customer_id' => $customerId, 'stripe_invoice_paid' => false, ]); } case 'customer.subscription.updated': $teamId = data_get($data, 'metadata.team_id'); $userId = data_get($data, 'metadata.user_id'); $customerId = data_get($data, 'customer'); $status = data_get($data, 'status'); $subscriptionId = data_get($data, 'items.data.0.subscription') ?? data_get($data, 'id'); $planId = data_get($data, 'items.data.0.plan.id') ?? data_get($data, 'plan.id'); if (Str::contains($excludedPlans, $planId)) { // send_internal_notification('Subscription excluded.'); break; } $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); if (! $subscription) { if ($status === 'incomplete_expired') { // send_internal_notification('Subscription incomplete expired'); throw new \RuntimeException('Subscription incomplete expired'); } if ($teamId) { $subscription = Subscription::create([ 'team_id' => $teamId, 'stripe_subscription_id' => $subscriptionId, 'stripe_customer_id' => $customerId, 'stripe_invoice_paid' => false, ]); } else { // send_internal_notification('No subscription and team id found'); throw new \RuntimeException('No subscription and team id found'); } } $cancelAtPeriodEnd = data_get($data, 'cancel_at_period_end'); $feedback = data_get($data, 'cancellation_details.feedback'); $comment = data_get($data, 'cancellation_details.comment'); $lookup_key = data_get($data, 'items.data.0.price.lookup_key'); if (str($lookup_key)->contains('dynamic')) { $quantity = data_get($data, 'items.data.0.quantity', 2); $team = data_get($subscription, 'team'); if ($team) { $team->update([ 'custom_server_limit' => $quantity, ]); } ServerLimitCheckJob::dispatch($team); } $subscription->update([ 'stripe_feedback' => $feedback, 'stripe_comment' => $comment, 'stripe_plan_id' => $planId, 'stripe_cancel_at_period_end' => $cancelAtPeriodEnd, ]); if ($status === 'paused' || $status === 'incomplete_expired') { if ($subscription->stripe_subscription_id === $subscriptionId) { $subscription->update([ 'stripe_invoice_paid' => false, ]); } } if ($status === 'past_due') { if ($subscription->stripe_subscription_id === $subscriptionId) { $subscription->update([ 'stripe_past_due' => true, ]); // send_internal_notification('Past Due: '.$customerId.'Subscription ID: '.$subscriptionId); } } if ($status === 'unpaid') { if ($subscription->stripe_subscription_id === $subscriptionId) { $subscription->update([ 'stripe_invoice_paid' => false, ]); // send_internal_notification('Unpaid: '.$customerId.'Subscription ID: '.$subscriptionId); } $team = data_get($subscription, 'team'); if ($team) { $team->subscriptionEnded(); } else { // send_internal_notification('Subscription unpaid but no team found in Coolify for customer: '.$customerId); throw new \RuntimeException("No team found in Coolify for customer: {$customerId}"); } } if ($status === 'active') { if ($subscription->stripe_subscription_id === $subscriptionId) { $subscription->update([ 'stripe_past_due' => false, 'stripe_invoice_paid' => true, ]); } } if ($feedback) { $reason = "Cancellation feedback for {$customerId}: '".$feedback."'"; if ($comment) { $reason .= ' with comment: \''.$comment."'"; } } break; case 'customer.subscription.deleted': $customerId = data_get($data, 'customer'); $subscriptionId = data_get($data, 'id'); $subscription = Subscription::where('stripe_customer_id', $customerId)->where('stripe_subscription_id', $subscriptionId)->first(); if ($subscription) { $team = data_get($subscription, 'team'); if ($team) { $team->subscriptionEnded(); } else { // send_internal_notification('Subscription deleted but no team found in Coolify for customer: '.$customerId); throw new \RuntimeException("No team found in Coolify for customer: {$customerId}"); } } else { // send_internal_notification('Subscription deleted but no subscription found in Coolify for customer: '.$customerId); throw new \RuntimeException("No subscription found in Coolify for customer: {$customerId}"); } break; default: throw new \RuntimeException("Unhandled event type: {$type}"); } } catch (\Exception $e) { send_internal_notification('StripeProcessJob error: '.$e->getMessage()); } } } ================================================ FILE: app/Jobs/SubscriptionInvoiceFailedJob.php ================================================ onQueue('high'); } public function handle() { try { // Double-check subscription status before sending failure notification $subscription = $this->team->subscription; if ($subscription && $subscription->stripe_customer_id) { try { $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); if ($subscription->stripe_subscription_id) { $stripeSubscription = $stripe->subscriptions->retrieve($subscription->stripe_subscription_id); if (in_array($stripeSubscription->status, ['active', 'trialing'])) { if (! $subscription->stripe_invoice_paid) { $subscription->update([ 'stripe_invoice_paid' => true, 'stripe_past_due' => false, ]); } return; } } $invoices = $stripe->invoices->all([ 'customer' => $subscription->stripe_customer_id, 'limit' => 3, ]); foreach ($invoices->data as $invoice) { if ($invoice->paid && $invoice->created > (time() - 3600)) { $subscription->update([ 'stripe_invoice_paid' => true, 'stripe_past_due' => false, ]); return; } } } catch (\Exception $e) { } } // If we reach here, payment genuinely failed $session = getStripeCustomerPortalSession($this->team); $mail = new MailMessage; $mail->view('emails.subscription-invoice-failed', [ 'stripeCustomerPortal' => $session->url, ]); $mail->subject('Your last payment was failed for Coolify Cloud.'); $this->team->members()->each(function ($member) use ($mail) { if ($member->isAdmin()) { send_user_an_email($mail, $member->email); } }); } catch (\Throwable $e) { send_internal_notification('SubscriptionInvoiceFailedJob failed with: '.$e->getMessage()); throw $e; } } } ================================================ FILE: app/Jobs/SyncStripeSubscriptionsJob.php ================================================ onQueue('high'); } public function handle(?\Closure $onProgress = null): array { if (! isCloud() || ! isStripe()) { return ['error' => 'Not running on Cloud or Stripe not configured']; } $subscriptions = Subscription::whereNotNull('stripe_subscription_id') ->where('stripe_invoice_paid', true) ->get(); $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); // Bulk fetch all valid subscription IDs from Stripe (active + past_due) $validStripeIds = $this->fetchValidStripeSubscriptionIds($stripe, $onProgress); // Find DB subscriptions not in the valid set $staleSubscriptions = $subscriptions->filter( fn (Subscription $sub) => ! in_array($sub->stripe_subscription_id, $validStripeIds) ); // For each stale subscription, get the exact Stripe status and check for resubscriptions $discrepancies = []; $resubscribed = []; $errors = []; foreach ($staleSubscriptions as $subscription) { try { $stripeSubscription = $stripe->subscriptions->retrieve( $subscription->stripe_subscription_id ); $stripeStatus = $stripeSubscription->status; usleep(100000); // 100ms rate limit delay } catch (\Exception $e) { $errors[] = [ 'subscription_id' => $subscription->id, 'error' => $e->getMessage(), ]; continue; } // Check if this user resubscribed under a different customer/subscription $activeSub = $this->findActiveSubscriptionByEmail($stripe, $stripeSubscription->customer); if ($activeSub) { $resubscribed[] = [ 'subscription_id' => $subscription->id, 'team_id' => $subscription->team_id, 'email' => $activeSub['email'], 'old_stripe_subscription_id' => $subscription->stripe_subscription_id, 'old_stripe_customer_id' => $stripeSubscription->customer, 'new_stripe_subscription_id' => $activeSub['subscription_id'], 'new_stripe_customer_id' => $activeSub['customer_id'], 'new_status' => $activeSub['status'], ]; continue; } $discrepancies[] = [ 'subscription_id' => $subscription->id, 'team_id' => $subscription->team_id, 'stripe_subscription_id' => $subscription->stripe_subscription_id, 'stripe_status' => $stripeStatus, ]; if ($this->fix) { $subscription->update([ 'stripe_invoice_paid' => false, 'stripe_past_due' => false, ]); if ($stripeStatus === 'canceled') { $subscription->team?->subscriptionEnded(); } } } if ($this->fix && count($discrepancies) > 0) { send_internal_notification( 'SyncStripeSubscriptionsJob: Fixed '.count($discrepancies)." discrepancies:\n". json_encode($discrepancies, JSON_PRETTY_PRINT) ); } return [ 'total_checked' => $subscriptions->count(), 'discrepancies' => $discrepancies, 'resubscribed' => $resubscribed, 'errors' => $errors, 'fixed' => $this->fix, ]; } /** * Given a Stripe customer ID, get their email and search for other customers * with the same email that have an active subscription. * * @return array{email: string, customer_id: string, subscription_id: string, status: string}|null */ private function findActiveSubscriptionByEmail(\Stripe\StripeClient $stripe, string $customerId): ?array { try { $customer = $stripe->customers->retrieve($customerId); $email = $customer->email; if (! $email) { return null; } usleep(100000); $customers = $stripe->customers->all([ 'email' => $email, 'limit' => 10, ]); usleep(100000); foreach ($customers->data as $matchingCustomer) { if ($matchingCustomer->id === $customerId) { continue; } $subs = $stripe->subscriptions->all([ 'customer' => $matchingCustomer->id, 'limit' => 10, ]); usleep(100000); foreach ($subs->data as $sub) { if (in_array($sub->status, ['active', 'past_due'])) { return [ 'email' => $email, 'customer_id' => $matchingCustomer->id, 'subscription_id' => $sub->id, 'status' => $sub->status, ]; } } } } catch (\Exception $e) { // Silently skip — will fall through to normal discrepancy } return null; } /** * Bulk fetch all active and past_due subscription IDs from Stripe. * * @return array */ private function fetchValidStripeSubscriptionIds(\Stripe\StripeClient $stripe, ?\Closure $onProgress = null): array { $validIds = []; $fetched = 0; foreach (['active', 'past_due'] as $status) { foreach ($stripe->subscriptions->all(['status' => $status, 'limit' => 100])->autoPagingIterator() as $sub) { $validIds[] = $sub->id; $fetched++; if ($onProgress) { $onProgress($fetched); } } } return $validIds; } } ================================================ FILE: app/Jobs/UpdateCoolifyJob.php ================================================ onQueue('high'); } public function handle(): void { try { CheckForUpdatesJob::dispatchSync(); $settings = instanceSettings(); if (! $settings->new_version_available) { Log::info('No new version available. Skipping update.'); return; } $server = Server::findOrFail(0); if (! $server) { Log::error('Server not found. Cannot proceed with update.'); return; } Log::info('Starting Coolify update process...'); UpdateCoolify::run(false); // false means it's not a manual update $settings->update(['new_version_available' => false]); Log::info('Coolify update completed successfully.'); } catch (\Throwable $e) { Log::error('UpdateCoolifyJob failed: '.$e->getMessage()); // Consider implementing a notification to administrators } } } ================================================ FILE: app/Jobs/UpdateStripeCustomerEmailJob.php ================================================ onQueue('high'); } public function handle(): void { try { if (! isCloud() || ! $this->team->subscription) { Log::info('Skipping Stripe email update - not cloud or no subscription', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, ]); return; } // Check if the user changing email is a team owner $isOwner = $this->team->members() ->wherePivot('role', 'owner') ->where('users.id', $this->userId) ->exists(); if (! $isOwner) { Log::info('Skipping Stripe email update - user is not team owner', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, ]); return; } // Get current Stripe customer email to verify it matches the user's old email $stripe_customer_id = data_get($this->team, 'subscription.stripe_customer_id'); if (! $stripe_customer_id) { Log::info('Skipping Stripe email update - no Stripe customer ID', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, ]); return; } Stripe::setApiKey(config('subscription.stripe_api_key')); try { $stripeCustomer = \Stripe\Customer::retrieve($stripe_customer_id); $currentStripeEmail = $stripeCustomer->email; // Only update if the current Stripe email matches the user's old email if (strtolower($currentStripeEmail) !== strtolower($this->oldEmail)) { Log::info('Skipping Stripe email update - Stripe customer email does not match user old email', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, 'stripe_email' => $currentStripeEmail, 'user_old_email' => $this->oldEmail, ]); return; } // Update Stripe customer email \Stripe\Customer::update($stripe_customer_id, ['email' => $this->newEmail]); } catch (\Exception $e) { Log::error('Failed to retrieve or update Stripe customer', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, 'stripe_customer_id' => $stripe_customer_id, 'error' => $e->getMessage(), ]); throw $e; } Log::info('Successfully updated Stripe customer email', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, 'old_email' => $this->oldEmail, 'new_email' => $this->newEmail, ]); } catch (\Exception $e) { Log::error('Failed to update Stripe customer email', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, 'old_email' => $this->oldEmail, 'new_email' => $this->newEmail, 'error' => $e->getMessage(), 'attempt' => $this->attempts(), ]); // Re-throw to trigger retry throw $e; } } public function failed(\Throwable $exception): void { Log::error('Permanently failed to update Stripe customer email after all retries', [ 'team_id' => $this->team->id, 'user_id' => $this->userId, 'old_email' => $this->oldEmail, 'new_email' => $this->newEmail, 'error' => $exception->getMessage(), ]); } } ================================================ FILE: app/Jobs/ValidateAndInstallServerJob.php ================================================ onQueue('high'); } public function handle(): void { try { // Mark validation as in progress $this->server->update(['is_validating' => true]); Log::info('ValidateAndInstallServer: Starting validation', [ 'server_id' => $this->server->id, 'server_name' => $this->server->name, 'attempt' => $this->numberOfTries + 1, ]); // Validate connection ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); if (! $uptime) { $errorMessage = 'Server is not reachable. Please validate your configuration and connection.
Check this documentation for further help.

Error: '.$error; $this->server->update([ 'validation_logs' => $errorMessage, 'is_validating' => false, ]); Log::error('ValidateAndInstallServer: Server not reachable', [ 'server_id' => $this->server->id, 'error' => $error, ]); return; } // Validate OS $supportedOsType = $this->server->validateOS(); if (! $supportedOsType) { $errorMessage = 'Server OS type is not supported. Please install Docker manually before continuing: documentation.'; $this->server->update([ 'validation_logs' => $errorMessage, 'is_validating' => false, ]); Log::error('ValidateAndInstallServer: OS not supported', [ 'server_id' => $this->server->id, ]); return; } // Check and install prerequisites $validationResult = $this->server->validatePrerequisites(); if (! $validationResult['success']) { if ($this->numberOfTries >= $this->maxTries) { $missingCommands = implode(', ', $validationResult['missing']); $errorMessage = "Prerequisites ({$missingCommands}) could not be installed after {$this->maxTries} attempts. Please install them manually before continuing."; $this->server->update([ 'validation_logs' => $errorMessage, 'is_validating' => false, ]); Log::error('ValidateAndInstallServer: Prerequisites installation failed after max tries', [ 'server_id' => $this->server->id, 'attempts' => $this->numberOfTries, 'missing_commands' => $validationResult['missing'], 'found_commands' => $validationResult['found'], ]); return; } Log::info('ValidateAndInstallServer: Installing prerequisites', [ 'server_id' => $this->server->id, 'attempt' => $this->numberOfTries + 1, 'missing_commands' => $validationResult['missing'], 'found_commands' => $validationResult['found'], ]); // Install prerequisites $this->server->installPrerequisites(); // Retry validation after installation self::dispatch($this->server, $this->numberOfTries + 1)->delay(now()->addSeconds(30)); return; } // Check if Docker is installed $dockerInstalled = $this->server->validateDockerEngine(); $dockerComposeInstalled = $this->server->validateDockerCompose(); if (! $dockerInstalled || ! $dockerComposeInstalled) { // Try to install Docker if ($this->numberOfTries >= $this->maxTries) { $errorMessage = 'Docker Engine could not be installed after '.$this->maxTries.' attempts. Please install Docker manually before continuing: documentation.'; $this->server->update([ 'validation_logs' => $errorMessage, 'is_validating' => false, ]); Log::error('ValidateAndInstallServer: Docker installation failed after max tries', [ 'server_id' => $this->server->id, 'attempts' => $this->numberOfTries, ]); return; } Log::info('ValidateAndInstallServer: Installing Docker', [ 'server_id' => $this->server->id, 'attempt' => $this->numberOfTries + 1, ]); // Install Docker $this->server->installDocker(); // Retry validation after installation self::dispatch($this->server, $this->numberOfTries + 1)->delay(now()->addSeconds(30)); return; } // Validate Docker version $dockerVersion = $this->server->validateDockerEngineVersion(); if (! $dockerVersion) { $requiredDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.'); $errorMessage = 'Minimum Docker Engine version '.$requiredDockerVersion.' is not installed. Please install Docker manually before continuing: documentation.'; $this->server->update([ 'validation_logs' => $errorMessage, 'is_validating' => false, ]); Log::error('ValidateAndInstallServer: Docker version not sufficient', [ 'server_id' => $this->server->id, ]); return; } // Validation successful! Log::info('ValidateAndInstallServer: Validation successful', [ 'server_id' => $this->server->id, 'server_name' => $this->server->name, ]); // Start proxy if needed if (! $this->server->isBuildServer()) { $proxyShouldRun = CheckProxy::run($this->server, true); if ($proxyShouldRun) { // Ensure networks exist BEFORE dispatching async proxy startup // This prevents race condition where proxy tries to start before networks are created instant_remote_process(ensureProxyNetworksExist($this->server)->toArray(), $this->server, false); StartProxy::dispatch($this->server); } } // Mark validation as complete $this->server->update(['is_validating' => false]); // Refresh server to get latest state $this->server->refresh(); // Broadcast events to update UI ServerValidated::dispatch($this->server->team_id, $this->server->uuid); ServerReachabilityChanged::dispatch($this->server); } catch (\Throwable $e) { Log::error('ValidateAndInstallServer: Exception occurred', [ 'server_id' => $this->server->id, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); $this->server->update([ 'validation_logs' => 'An error occurred during validation: '.$e->getMessage(), 'is_validating' => false, ]); } } } ================================================ FILE: app/Jobs/VerifyStripeSubscriptionStatusJob.php ================================================ onQueue('high'); } public function handle(): void { // If no subscription ID yet, try to find it via customer if (! $this->subscription->stripe_subscription_id && $this->subscription->stripe_customer_id) { try { $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); $subscriptions = $stripe->subscriptions->all([ 'customer' => $this->subscription->stripe_customer_id, 'limit' => 1, ]); if ($subscriptions->data) { $this->subscription->update([ 'stripe_subscription_id' => $subscriptions->data[0]->id, ]); } } catch (\Exception $e) { // Continue without subscription ID } } if (! $this->subscription->stripe_subscription_id) { return; } try { $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); $stripeSubscription = $stripe->subscriptions->retrieve( $this->subscription->stripe_subscription_id ); switch ($stripeSubscription->status) { case 'active': $this->subscription->update([ 'stripe_invoice_paid' => true, 'stripe_past_due' => false, 'stripe_cancel_at_period_end' => $stripeSubscription->cancel_at_period_end, ]); break; case 'past_due': // Keep subscription active but mark as past_due $this->subscription->update([ 'stripe_invoice_paid' => true, 'stripe_past_due' => true, 'stripe_cancel_at_period_end' => $stripeSubscription->cancel_at_period_end, ]); break; case 'canceled': case 'incomplete_expired': case 'unpaid': // Ensure subscription is marked as inactive $this->subscription->update([ 'stripe_invoice_paid' => false, 'stripe_past_due' => false, ]); // Trigger subscription ended logic if canceled if ($stripeSubscription->status === 'canceled') { $team = $this->subscription->team; if ($team) { $team->subscriptionEnded(); } } break; default: send_internal_notification( 'Unknown subscription status in VerifyStripeSubscriptionStatusJob: '.$stripeSubscription->status. ' for customer: '.$this->subscription->stripe_customer_id ); break; } } catch (\Exception $e) { send_internal_notification( 'VerifyStripeSubscriptionStatusJob failed for subscription ID '.$this->subscription->id.': '.$e->getMessage() ); } } } ================================================ FILE: app/Jobs/VolumeCloneJob.php ================================================ onQueue('high'); } public function handle() { try { if (! $this->targetServer || $this->targetServer->id === $this->sourceServer->id) { $this->cloneLocalVolume(); } else { $this->cloneRemoteVolume(); } } catch (\Exception $e) { \Log::error("Failed to copy volume data for {$this->sourceVolume}: ".$e->getMessage()); throw $e; } } protected function cloneLocalVolume() { instant_remote_process([ "docker volume create $this->targetVolume", "docker run --rm -v $this->sourceVolume:/source -v $this->targetVolume:/target alpine sh -c 'cp -a /source/. /target/ && chown -R 1000:1000 /target'", ], $this->sourceServer); } protected function cloneRemoteVolume() { $sourceCloneDir = "{$this->cloneDir}/{$this->sourceVolume}"; $targetCloneDir = "{$this->cloneDir}/{$this->targetVolume}"; try { instant_remote_process([ "mkdir -p $sourceCloneDir", "chmod 777 $sourceCloneDir", "docker run --rm -v $this->sourceVolume:/source -v $sourceCloneDir:/clone alpine sh -c 'cd /source && tar czf /clone/volume-data.tar.gz .'", ], $this->sourceServer); instant_remote_process([ "mkdir -p $targetCloneDir", "chmod 777 $targetCloneDir", ], $this->targetServer); instant_scp( "$sourceCloneDir/volume-data.tar.gz", "$targetCloneDir/volume-data.tar.gz", $this->sourceServer, $this->targetServer ); instant_remote_process([ "docker volume create $this->targetVolume", "docker run --rm -v $this->targetVolume:/target -v $targetCloneDir:/clone alpine sh -c 'cd /target && tar xzf /clone/volume-data.tar.gz && chown -R 1000:1000 /target'", ], $this->targetServer); } catch (\Exception $e) { \Log::error("Failed to clone volume {$this->sourceVolume} to {$this->targetVolume}: ".$e->getMessage()); throw $e; } finally { try { instant_remote_process([ "rm -rf $sourceCloneDir", ], $this->sourceServer, false); } catch (\Exception $e) { \Log::warning('Failed to clean up source server clone directory: '.$e->getMessage()); } try { if ($this->targetServer) { instant_remote_process([ "rm -rf $targetCloneDir", ], $this->targetServer, false); } } catch (\Exception $e) { \Log::warning('Failed to clean up target server clone directory: '.$e->getMessage()); } } } } ================================================ FILE: app/Listeners/CloudflareTunnelChangedNotification.php ================================================ server = Server::where('id', $server_id)->firstOrFail(); // Check if cloudflare tunnel is running (container is healthy) - try 3 times with 5 second intervals $cloudflareHealthy = false; $attempts = 3; for ($i = 1; $i <= $attempts; $i++) { \Log::debug("Cloudflare health check attempt {$i}/{$attempts}", ['server_id' => $server_id]); $result = instant_remote_process_with_timeout(['docker inspect coolify-cloudflared | jq -e ".[0].State.Health.Status == \"healthy\""'], $this->server, false, 10); if (blank($result)) { \Log::debug("Cloudflare Tunnels container not found on attempt {$i}", ['server_id' => $server_id]); } elseif ($result === 'true') { \Log::debug("Cloudflare Tunnels container healthy on attempt {$i}", ['server_id' => $server_id]); $cloudflareHealthy = true; break; } else { \Log::debug("Cloudflare Tunnels container not healthy on attempt {$i}", ['server_id' => $server_id, 'result' => $result]); } // Sleep between attempts (except after the last attempt) if ($i < $attempts) { Sleep::for(5)->seconds(); } } if (! $cloudflareHealthy) { \Log::error('Cloudflare Tunnels container failed all health checks.', ['server_id' => $server_id, 'attempts' => $attempts]); return; } $this->server->settings->update([ 'is_cloudflare_tunnel' => true, ]); // Only update IP if it's not already set to the ssh_domain or if it's empty if ($this->server->ip !== $ssh_domain && ! empty($ssh_domain)) { \Log::debug('Cloudflare Tunnels configuration updated - updating IP address.', ['old_ip' => $this->server->ip, 'new_ip' => $ssh_domain]); $this->server->update(['ip' => $ssh_domain]); } else { \Log::debug('Cloudflare Tunnels configuration updated - IP address unchanged.', ['current_ip' => $this->server->ip]); } $teamId = $this->server->team_id; CloudflareTunnelConfigured::dispatch($teamId); } } ================================================ FILE: app/Listeners/ProxyStatusChangedNotification.php ================================================ data; if (is_null($serverId)) { return; } $server = Server::where('id', $serverId)->first(); if (is_null($server)) { return; } $proxyContainerName = 'coolify-proxy'; $status = getContainerStatus($server, $proxyContainerName); $server->proxy->set('status', $status); $server->save(); $versionCheckDispatched = false; if ($status === 'running') { $server->setupDefaultRedirect(); $server->setupDynamicProxyConfiguration(); $server->proxy->force_stop = false; $server->save(); // Check Traefik version after proxy is running if ($server->proxyType() === ProxyTypes::TRAEFIK->value) { $traefikVersions = get_traefik_versions(); if ($traefikVersions !== null) { // Version check job will dispatch ProxyStatusChangedUI when complete CheckTraefikVersionForServerJob::dispatch($server, $traefikVersions); $versionCheckDispatched = true; } else { Log::warning('Traefik version check skipped after proxy status change: versions.json data unavailable', [ 'server_id' => $server->id, 'server_name' => $server->name, ]); } } } // Only dispatch UI refresh if version check wasn't dispatched // (version check job handles its own UI refresh with updated version data) if (! $versionCheckDispatched) { ProxyStatusChangedUI::dispatch($server->team_id); } if ($status === 'created') { instant_remote_process([ 'docker rm -f coolify-proxy', ], $server); } } } ================================================ FILE: app/Livewire/ActivityMonitor.php ================================================ 'newMonitorActivity']; public function newMonitorActivity($activityId, $eventToDispatch = 'activityFinished', $eventData = null, $header = null) { // Reset event dispatched flag for new activity self::$eventDispatched = false; $this->activityId = $activityId; $this->eventToDispatch = $eventToDispatch; $this->eventData = $eventData; // Update header if provided if ($header !== null) { $this->header = $header; } $this->hydrateActivity(); $this->isPollingActive = true; } public function hydrateActivity() { if ($this->activityId === null) { $this->activity = null; return; } $this->activity = Activity::find($this->activityId); } public function updatedActivityId($value) { if ($value) { $this->hydrateActivity(); $this->isPollingActive = true; self::$eventDispatched = false; } } public function polling() { $this->hydrateActivity(); $exit_code = data_get($this->activity, 'properties.exitCode'); if ($exit_code !== null) { $this->isPollingActive = false; if ($exit_code === 0) { if ($this->eventToDispatch !== null) { if (str($this->eventToDispatch)->startsWith('App\\Events\\')) { $causer_id = data_get($this->activity, 'causer_id'); $user = User::find($causer_id); if ($user) { $teamId = data_get($this->activity, 'properties.team_id') ?? $user->currentTeam()?->id ?? $user->teams->first()?->id; if ($teamId && ! self::$eventDispatched) { if (filled($this->eventData)) { $this->eventToDispatch::dispatch($teamId, $this->eventData); } else { $this->eventToDispatch::dispatch($teamId); } self::$eventDispatched = true; } } return; } if (! self::$eventDispatched) { if (filled($this->eventData)) { $this->dispatch($this->eventToDispatch, $this->eventData); } else { $this->dispatch($this->eventToDispatch); } self::$eventDispatched = true; } } } } } } ================================================ FILE: app/Livewire/Admin/Index.php ================================================ route('dashboard'); } if (Auth::id() !== 0 && ! session('impersonating')) { return redirect()->route('dashboard'); } $this->getSubscribers(); } public function back() { if (session('impersonating')) { session()->forget('impersonating'); $user = User::find(0); $team_to_switch_to = $user->teams->first(); Auth::login($user); refreshSession($team_to_switch_to); return redirect(request()->header('Referer')); } } public function submitSearch() { if ($this->search !== '') { $this->foundUsers = User::where(function ($query) { $query->where('name', 'like', "%{$this->search}%") ->orWhere('email', 'like', "%{$this->search}%"); })->get(); } } public function getSubscribers() { $this->inactiveSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', false)->count(); $this->activeSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', true)->count(); } public function switchUser(int $user_id) { if (Auth::id() !== 0) { return redirect()->route('dashboard'); } session(['impersonating' => true]); $user = User::find($user_id); $team_to_switch_to = $user->teams->first(); // Cache::forget("team:{$user->id}"); Auth::login($user); refreshSession($team_to_switch_to); return redirect(request()->header('Referer')); } public function render() { return view('livewire.admin.index'); } } ================================================ FILE: app/Livewire/Boarding/Index.php ================================================ 'validateServer', 'prerequisitesInstalled' => 'handlePrerequisitesInstalled', ]; #[\Livewire\Attributes\Url(as: 'step', history: true)] public string $currentState = 'welcome'; #[\Livewire\Attributes\Url(keep: true)] public ?string $selectedServerType = null; public ?Collection $privateKeys = null; #[\Livewire\Attributes\Url(keep: true)] public ?int $selectedExistingPrivateKey = null; #[\Livewire\Attributes\Url(keep: true)] public ?string $privateKeyType = null; public ?string $privateKey = null; public ?string $publicKey = null; public ?string $privateKeyName = null; public ?string $privateKeyDescription = null; public ?PrivateKey $createdPrivateKey = null; public ?Collection $servers = null; #[\Livewire\Attributes\Url(keep: true)] public ?int $selectedExistingServer = null; public ?string $remoteServerName = null; public ?string $remoteServerDescription = null; public ?string $remoteServerHost = null; public ?int $remoteServerPort = 22; public ?string $remoteServerUser = 'root'; public bool $isSwarmManager = false; public bool $isCloudflareTunnel = false; public ?Server $createdServer = null; public Collection $projects; #[\Livewire\Attributes\Url(keep: true)] public ?int $selectedProject = null; public ?Project $createdProject = null; public bool $dockerInstallationStarted = false; public string $serverPublicKey; public bool $serverReachable = true; public ?string $minDockerVersion = null; public int $prerequisiteInstallAttempts = 0; public int $maxPrerequisiteInstallAttempts = 3; public function mount() { if (auth()->user()?->isMember() && auth()->user()->currentTeam()->show_boarding === true) { return redirect()->route('dashboard'); } $this->minDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.'); $this->privateKeyName = generate_random_name(); $this->remoteServerName = generate_random_name(); // Initialize collections to avoid null errors if ($this->privateKeys === null) { $this->privateKeys = collect(); } if ($this->servers === null) { $this->servers = collect(); } if (! isset($this->projects)) { $this->projects = collect(); } // Restore state when coming from URL with query params if ($this->selectedServerType === 'localhost' && $this->selectedExistingServer === 0) { $this->createdServer = Server::find(0); if ($this->createdServer) { $this->serverPublicKey = $this->createdServer->privateKey->getPublicKey(); } } if ($this->selectedServerType === 'remote') { if ($this->privateKeys->isEmpty()) { $this->privateKeys = PrivateKey::ownedAndOnlySShKeys(['name'])->where('id', '!=', 0)->get(); } if ($this->servers->isEmpty()) { $this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get(); } if ($this->selectedExistingServer) { $this->createdServer = Server::find($this->selectedExistingServer); if ($this->createdServer) { $this->serverPublicKey = $this->createdServer->privateKey->getPublicKey(); $this->updateServerDetails(); } } if ($this->selectedExistingPrivateKey) { $this->createdPrivateKey = PrivateKey::where('team_id', currentTeam()->id) ->where('id', $this->selectedExistingPrivateKey) ->first(); if ($this->createdPrivateKey) { $this->privateKey = $this->createdPrivateKey->private_key; $this->publicKey = $this->createdPrivateKey->getPublicKey(); } } // Auto-regenerate key pair for "Generate with Coolify" mode on page refresh if ($this->privateKeyType === 'create' && empty($this->privateKey)) { $this->createNewPrivateKey(); } } if ($this->selectedProject) { $this->createdProject = Project::find($this->selectedProject); if (! $this->createdProject) { $this->projects = Project::ownedByCurrentTeam(['name'])->get(); } } // Load projects when on create-project state (for page refresh) if ($this->currentState === 'create-project' && $this->projects->isEmpty()) { $this->projects = Project::ownedByCurrentTeam(['name'])->get(); } } public function explanation() { if (isCloud()) { return $this->setServerType('remote'); } $this->currentState = 'select-server-type'; } public function restartBoarding() { return redirect()->route('onboarding'); } public function skipBoarding() { Team::find(currentTeam()->id)->update([ 'show_boarding' => false, ]); refreshSession(); return redirect()->route('dashboard'); } public function setServerType(string $type) { $this->selectedServerType = $type; if ($this->selectedServerType === 'localhost') { $this->createdServer = Server::find(0); $this->selectedExistingServer = 0; if (! $this->createdServer) { return $this->dispatch('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.'); } $this->serverPublicKey = $this->createdServer->privateKey->getPublicKey(); return $this->validateServer('localhost'); } elseif ($this->selectedServerType === 'remote') { $this->privateKeys = PrivateKey::ownedAndOnlySShKeys(['name'])->where('id', '!=', 0)->get(); // Auto-select first key if available for better UX if ($this->privateKeys->count() > 0) { $this->selectedExistingPrivateKey = $this->privateKeys->first()->id; } // Onboarding always creates new servers, skip existing server selection $this->currentState = 'private-key'; } } private function updateServerDetails() { if ($this->createdServer) { $this->remoteServerPort = $this->createdServer->port; $this->remoteServerUser = $this->createdServer->user; } } public function getProxyType() { $this->selectProxy(ProxyTypes::TRAEFIK->value); $this->getProjects(); } public function selectExistingPrivateKey() { if (is_null($this->selectedExistingPrivateKey)) { $this->dispatch('error', 'Please select a private key.'); return; } $this->createdPrivateKey = PrivateKey::where('team_id', currentTeam()->id)->where('id', $this->selectedExistingPrivateKey)->first(); $this->privateKey = $this->createdPrivateKey->private_key; $this->currentState = 'create-server'; } public function createNewServer() { $this->selectedExistingServer = null; $this->currentState = 'private-key'; } public function setPrivateKey(string $type) { $this->selectedExistingPrivateKey = null; $this->privateKeyType = $type; if ($type === 'create') { $this->createNewPrivateKey(); } else { $this->privateKey = null; $this->publicKey = null; } $this->currentState = 'create-private-key'; } public function savePrivateKey() { $this->validate([ 'privateKeyName' => 'required|string|max:255', 'privateKeyDescription' => 'nullable|string|max:255', 'privateKey' => 'required|string', ]); try { $privateKey = PrivateKey::createAndStore([ 'name' => $this->privateKeyName, 'description' => $this->privateKeyDescription, 'private_key' => $this->privateKey, 'team_id' => currentTeam()->id, ]); $this->createdPrivateKey = $privateKey; $this->currentState = 'create-server'; } catch (\Exception $e) { $this->addError('privateKey', 'Failed to save private key: '.$e->getMessage()); } } public function saveServer() { $this->validate([ 'remoteServerName' => 'required|string', 'remoteServerHost' => 'required|string', 'remoteServerPort' => 'required|integer', 'remoteServerUser' => 'required|string', ]); $this->privateKey = formatPrivateKey($this->privateKey); $foundServer = Server::whereIp($this->remoteServerHost)->first(); if ($foundServer) { if ($foundServer->team_id === currentTeam()->id) { return $this->dispatch('error', 'A server with this IP/Domain already exists in your team.'); } return $this->dispatch('error', 'A server with this IP/Domain is already in use by another team.'); } $this->createdServer = Server::create([ 'name' => $this->remoteServerName, 'ip' => $this->remoteServerHost, 'port' => $this->remoteServerPort, 'user' => $this->remoteServerUser, 'description' => $this->remoteServerDescription, 'private_key_id' => $this->createdPrivateKey->id, 'team_id' => currentTeam()->id, ]); $this->createdServer->settings->is_swarm_manager = $this->isSwarmManager; $this->createdServer->settings->is_cloudflare_tunnel = $this->isCloudflareTunnel; $this->createdServer->settings->save(); $this->selectedExistingServer = $this->createdServer->id; $this->currentState = 'validate-server'; } public function installServer() { $this->dispatch('init', true); } public function validateServer() { try { $this->disableSshMux(); // EC2 does not have `uptime` command, lol instant_remote_process(['ls /'], $this->createdServer, true); $this->createdServer->settings()->update([ 'is_reachable' => true, ]); $this->serverReachable = true; } catch (\Throwable $e) { $this->serverReachable = false; $this->createdServer->settings()->update([ 'is_reachable' => false, ]); return handleError(error: $e, livewire: $this); } try { // Check prerequisites $validationResult = $this->createdServer->validatePrerequisites(); if (! $validationResult['success']) { // Check if we've exceeded max attempts if ($this->prerequisiteInstallAttempts >= $this->maxPrerequisiteInstallAttempts) { $missingCommands = implode(', ', $validationResult['missing']); throw new \Exception("Prerequisites ({$missingCommands}) could not be installed after {$this->maxPrerequisiteInstallAttempts} attempts. Please install them manually."); } // Start async installation and wait for completion via ActivityMonitor $activity = $this->createdServer->installPrerequisites(); $this->prerequisiteInstallAttempts++; $this->dispatch('activityMonitor', $activity->id, 'prerequisitesInstalled'); // Return early - handlePrerequisitesInstalled() will be called when installation completes return; } // Prerequisites are already installed, continue with validation $this->continueValidation(); } catch (\Throwable $e) { return handleError(error: $e, livewire: $this); } } public function handlePrerequisitesInstalled() { try { // Revalidate prerequisites after installation completes $validationResult = $this->createdServer->validatePrerequisites(); if (! $validationResult['success']) { // Installation completed but prerequisites still missing - retry $missingCommands = implode(', ', $validationResult['missing']); if ($this->prerequisiteInstallAttempts >= $this->maxPrerequisiteInstallAttempts) { throw new \Exception("Prerequisites ({$missingCommands}) could not be installed after {$this->maxPrerequisiteInstallAttempts} attempts. Please install them manually."); } // Try again $activity = $this->createdServer->installPrerequisites(); $this->prerequisiteInstallAttempts++; $this->dispatch('activityMonitor', $activity->id, 'prerequisitesInstalled'); return; } // Prerequisites validated successfully - continue with Docker validation $this->continueValidation(); } catch (\Throwable $e) { return handleError(error: $e, livewire: $this); } } private function continueValidation() { try { $dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this->createdServer, true); $dockerVersion = checkMinimumDockerEngineVersion($dockerVersion); if (is_null($dockerVersion)) { $this->currentState = 'validate-server'; throw new \Exception('Docker not found or old version is installed.'); } $this->createdServer->settings()->update([ 'is_usable' => true, ]); $this->getProxyType(); } catch (\Throwable $e) { $this->createdServer->settings()->update([ 'is_usable' => false, ]); return handleError(error: $e, livewire: $this); } } public function selectProxy(?string $proxyType = null) { if (! $proxyType) { return $this->getProjects(); } $this->createdServer->proxy->type = $proxyType; $this->createdServer->proxy->status = 'exited'; $this->createdServer->proxy->last_saved_settings = null; $this->createdServer->proxy->last_applied_settings = null; $this->createdServer->save(); $this->getProjects(); } public function getProjects() { $this->projects = Project::ownedByCurrentTeam(['name'])->get(); if ($this->projects->count() > 0) { $this->selectedProject = $this->projects->first()->id; } $this->currentState = 'create-project'; } public function selectExistingProject() { $this->createdProject = Project::find($this->selectedProject); $this->currentState = 'create-resource'; } public function createNewProject() { $this->createdProject = Project::create([ 'name' => 'My first project', 'team_id' => currentTeam()->id, 'uuid' => (string) new Cuid2, ]); $this->currentState = 'create-resource'; } public function showNewResource() { $this->skipBoarding(); return redirect()->route( 'project.resource.create', [ 'project_uuid' => $this->createdProject->uuid, 'environment_uuid' => $this->createdProject->environments->first()->uuid, 'server' => $this->createdServer->id, ] ); } public function saveAndValidateServer() { $this->validate([ 'remoteServerPort' => 'required|integer|min:1|max:65535', 'remoteServerUser' => 'required|string', ]); $this->createdServer->update([ 'port' => $this->remoteServerPort, 'user' => $this->remoteServerUser, 'timezone' => 'UTC', ]); $this->validateServer(); } private function createNewPrivateKey() { $this->privateKeyName = generate_random_name(); $this->privateKeyDescription = 'Created by Coolify'; ['private' => $this->privateKey, 'public' => $this->publicKey] = generateSSHKey(); } private function disableSshMux(): void { $configRepository = app(ConfigurationRepository::class); $configRepository->disableSshMux(); } public function render() { return view('livewire.boarding.index')->layout('layouts.boarding'); } } ================================================ FILE: app/Livewire/Dashboard.php ================================================ privateKeys = PrivateKey::ownedByCurrentTeamCached(); $this->servers = Server::ownedByCurrentTeamCached(); $this->projects = Project::ownedByCurrentTeam()->with('environments')->get(); } public function render() { return view('livewire.dashboard'); } } ================================================ FILE: app/Livewire/DeploymentsIndicator.php ================================================ whereIn('status', ['in_progress', 'queued']) ->whereIn('server_id', $servers->pluck('id')) ->orderBy('id') ->get([ 'id', 'application_id', 'application_name', 'deployment_url', 'pull_request_id', 'server_name', 'server_id', 'status', ]); } #[Computed] public function deploymentCount() { return $this->deployments->count(); } #[Computed] public function shouldReduceOpacity(): bool { return request()->routeIs('project.application.deployment.*'); } public function toggleExpanded() { $this->expanded = ! $this->expanded; } public function render() { return view('livewire.deployments-indicator'); } } ================================================ FILE: app/Livewire/Destination/Index.php ================================================ servers = Server::isUsable()->get(); } public function render() { return view('livewire.destination.index'); } } ================================================ FILE: app/Livewire/Destination/New/Docker.php ================================================ network = new Cuid2; $this->servers = Server::isUsable()->get(); if ($server_id) { $foundServer = $this->servers->find($server_id) ?: $this->servers->first(); if (! $foundServer) { throw new \Exception('Server not found.'); } $this->selectedServer = $foundServer; $this->serverId = $this->selectedServer->id; } else { $foundServer = $this->servers->first(); if (! $foundServer) { throw new \Exception('Server not found.'); } $this->selectedServer = $foundServer; $this->serverId = $this->selectedServer->id; } $this->generateName(); } public function updatedServerId() { $this->selectedServer = $this->servers->find($this->serverId); $this->generateName(); } public function generateName() { $name = data_get($this->selectedServer, 'name', new Cuid2); $this->name = str("{$name}-{$this->network}")->kebab(); } public function submit() { try { $this->authorize('create', StandaloneDocker::class); $this->validate(); if ($this->isSwarm) { $found = $this->selectedServer->swarmDockers()->where('network', $this->network)->first(); if ($found) { throw new \Exception('Network already added to this server.'); } else { $docker = SwarmDocker::create([ 'name' => $this->name, 'network' => $this->network, 'server_id' => $this->selectedServer->id, ]); } } else { $found = $this->selectedServer->standaloneDockers()->where('network', $this->network)->first(); if ($found) { throw new \Exception('Network already added to this server.'); } else { $docker = StandaloneDocker::create([ 'name' => $this->name, 'network' => $this->network, 'server_id' => $this->selectedServer->id, ]); } } redirectRoute($this, 'destination.show', [$docker->uuid]); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Destination/Show.php ================================================ first() ?? SwarmDocker::whereUuid($destination_uuid)->firstOrFail(); $ownedByTeam = Server::ownedByCurrentTeam()->each(function ($server) use ($destination) { if ($server->standaloneDockers->contains($destination) || $server->swarmDockers->contains($destination)) { $this->destination = $destination; $this->syncData(); } }); if ($ownedByTeam === false) { return redirect()->route('destination.index'); } $this->destination = $destination; $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->destination->name = $this->name; $this->destination->network = $this->network; $this->destination->server->ip = $this->serverIp; $this->destination->save(); } else { $this->name = $this->destination->name; $this->network = $this->destination->network; $this->serverIp = $this->destination->server->ip; } } public function submit() { try { $this->authorize('update', $this->destination); $this->syncData(true); $this->dispatch('success', 'Destination saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function delete() { try { $this->authorize('delete', $this->destination); if ($this->destination->getMorphClass() === \App\Models\StandaloneDocker::class) { if ($this->destination->attachedTo()) { return $this->dispatch('error', 'You must delete all resources before deleting this destination.'); } instant_remote_process(["docker network disconnect {$this->destination->network} coolify-proxy"], $this->destination->server, throwError: false); instant_remote_process(['docker network rm -f '.$this->destination->network], $this->destination->server); } $this->destination->delete(); return redirect()->route('destination.index'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.destination.show'); } } ================================================ FILE: app/Livewire/ForcePasswordReset.php ================================================ ['required', 'email'], 'password' => ['required', Password::defaults(), 'confirmed'], ]; } public function mount() { if (auth()->user()->force_password_reset === false) { return redirect()->route('dashboard'); } $this->email = auth()->user()->email; } public function render() { return view('livewire.force-password-reset')->layout('layouts.simple'); } public function submit() { if (auth()->user()->force_password_reset === false) { return redirect()->route('dashboard'); } try { $this->rateLimit(10); $this->validate(); $firstLogin = auth()->user()->created_at == auth()->user()->updated_at; auth()->user()->forceFill([ 'password' => Hash::make($this->password), 'force_password_reset' => false, ])->save(); if ($firstLogin) { send_internal_notification('First login for '.auth()->user()->email); } return redirect()->route('dashboard'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/GlobalSearch.php ================================================ searchQuery = ''; $this->isModalOpen = false; $this->searchResults = []; $this->allSearchableItems = []; $this->isCreateMode = false; $this->creatableItems = []; $this->autoOpenResource = null; $this->isSelectingResource = false; } public function openSearchModal() { $this->isModalOpen = true; $this->loadSearchableItems(); $this->loadCreatableItems(); $this->dispatch('search-modal-opened'); } public function closeSearchModal() { $this->isModalOpen = false; $this->searchQuery = ''; $this->previousTrimmedQuery = ''; $this->searchResults = []; } public static function getCacheKey($teamId) { return 'global_search_items_'.$teamId; } public static function clearTeamCache($teamId) { Cache::forget(self::getCacheKey($teamId)); } public function updatedSearchQuery() { $trimmedQuery = trim($this->searchQuery); // If only spaces were added/removed, don't trigger a search if ($trimmedQuery === $this->previousTrimmedQuery) { return; } $this->previousTrimmedQuery = $trimmedQuery; // If search query is empty, just clear results without processing if (empty($trimmedQuery)) { $this->searchResults = []; $this->isCreateMode = false; $this->creatableItems = []; $this->autoOpenResource = null; $this->isSelectingResource = false; $this->cancelResourceSelection(); return; } $query = strtolower($trimmedQuery); // Reset keyboard navigation index $this->dispatch('reset-selected-index'); // Only enter create mode if query is exactly "new" or starts with "new " (space after) if ($query === 'new' || str_starts_with($query, 'new ')) { $this->isCreateMode = true; $this->loadCreatableItems(); // Check for sub-commands like "new project", "new server", etc. $detectedType = $this->detectSpecificResource($query); if ($detectedType) { $this->navigateToResource($detectedType); } else { // If no specific resource detected, reset selection state $this->cancelResourceSelection(); } // Also search for existing resources that match the query // This allows users to find resources with "new" in their name $this->search(); } else { $this->isCreateMode = false; $this->creatableItems = []; $this->autoOpenResource = null; $this->isSelectingResource = false; $this->search(); } } private function detectSpecificResource(string $query): ?string { // Map of keywords to resource types - order matters for multi-word matches $resourceMap = [ // Quick Actions 'new project' => 'project', 'new server' => 'server', 'new team' => 'team', 'new storage' => 'storage', 'new s3' => 'storage', 'new private key' => 'private-key', 'new privatekey' => 'private-key', 'new key' => 'private-key', 'new github app' => 'source', 'new github' => 'source', 'new source' => 'source', // Applications - Git-based 'new public' => 'public', 'new public git' => 'public', 'new public repo' => 'public', 'new public repository' => 'public', 'new private github' => 'private-gh-app', 'new private gh' => 'private-gh-app', 'new private deploy' => 'private-deploy-key', 'new deploy key' => 'private-deploy-key', // Applications - Docker-based 'new dockerfile' => 'dockerfile', 'new docker compose' => 'docker-compose-empty', 'new compose' => 'docker-compose-empty', 'new docker image' => 'docker-image', 'new image' => 'docker-image', // Databases 'new postgresql' => 'postgresql', 'new postgres' => 'postgresql', 'new mysql' => 'mysql', 'new mariadb' => 'mariadb', 'new redis' => 'redis', 'new keydb' => 'keydb', 'new dragonfly' => 'dragonfly', 'new mongodb' => 'mongodb', 'new mongo' => 'mongodb', 'new clickhouse' => 'clickhouse', ]; foreach ($resourceMap as $command => $type) { if ($query === $command) { // Check if user has permission for this resource type if ($this->canCreateResource($type)) { return $type; } } } return null; } private function canCreateResource(string $type): bool { $user = auth()->user(); // Quick Actions if (in_array($type, ['server', 'storage', 'private-key'])) { return $user->isAdmin() || $user->isOwner(); } if ($type === 'team') { return true; } // Applications, Databases, Services, and other resources if (in_array($type, [ 'project', 'source', // Applications 'public', 'private-gh-app', 'private-deploy-key', 'dockerfile', 'docker-compose-empty', 'docker-image', // Databases 'postgresql', 'mysql', 'mariadb', 'redis', 'keydb', 'dragonfly', 'mongodb', 'clickhouse', ]) || str_starts_with($type, 'one-click-service-')) { return $user->can('createAnyResource'); } return false; } private function loadSearchableItems() { // Try to get from Redis cache first $cacheKey = self::getCacheKey(auth()->user()->currentTeam()->id); $this->allSearchableItems = Cache::remember($cacheKey, 300, function () { ray()->showQueries(); $items = collect(); $team = auth()->user()->currentTeam(); // Get all applications $applications = Application::ownedByCurrentTeam() ->with(['environment.project', 'previews:id,application_id,pull_request_id']) ->get() ->map(function ($app) { // Collect all FQDNs from the application $fqdns = collect([]); // For regular applications if ($app->fqdn) { $fqdns = collect(explode(',', $app->fqdn))->map(fn ($fqdn) => trim($fqdn)); } // For docker compose based applications if ($app->build_pack === 'dockercompose' && $app->docker_compose_domains) { try { $composeDomains = json_decode($app->docker_compose_domains, true); if (is_array($composeDomains)) { foreach ($composeDomains as $serviceName => $domains) { if (is_array($domains)) { $fqdns = $fqdns->merge($domains); } } } } catch (\Exception $e) { // Ignore JSON parsing errors } } $fqdnsString = $fqdns->implode(' '); // Add PR search terms if preview is enabled $prSearchTerms = ''; if ($app->preview_enabled ?? false) { $prIds = collect($app->previews ?? []) ->pluck('pull_request_id') ->map(fn ($id) => "pr-{$id} pr{$id} {$id}") ->implode(' '); $prSearchTerms = $prIds; } return [ 'id' => $app->id, 'name' => $app->name, 'type' => 'application', 'uuid' => $app->uuid, 'description' => $app->description, 'link' => $app->link(), 'project' => $app->environment->project->name ?? null, 'environment' => $app->environment->name ?? null, 'fqdns' => $fqdns->take(2)->implode(', '), // Show first 2 FQDNs in UI 'search_text' => strtolower($app->name.' '.$app->description.' '.$fqdnsString.' '.$app->uuid.' '.$prSearchTerms.' application applications app apps'), ]; }); // Get all services $services = Service::ownedByCurrentTeam() ->with(['environment.project', 'applications', 'databases']) ->get() ->map(function ($service) { // Collect all FQDNs from service applications $fqdns = collect([]); foreach ($service->applications as $app) { if ($app->fqdn) { $appFqdns = collect(explode(',', $app->fqdn))->map(fn ($fqdn) => trim($fqdn)); $fqdns = $fqdns->merge($appFqdns); } } $fqdnsString = $fqdns->implode(' '); // Collect service component names for container search $serviceAppNames = collect($service->applications ?? [])->pluck('name')->implode(' '); $serviceDbNames = collect($service->databases ?? [])->pluck('name')->implode(' '); return [ 'id' => $service->id, 'name' => $service->name, 'type' => 'service', 'uuid' => $service->uuid, 'description' => $service->description, 'link' => $service->link(), 'project' => $service->environment->project->name ?? null, 'environment' => $service->environment->name ?? null, 'fqdns' => $fqdns->take(2)->implode(', '), // Show first 2 FQDNs in UI 'search_text' => strtolower($service->name.' '.$service->description.' '.$fqdnsString.' '.$service->uuid.' '.$serviceAppNames.' '.$serviceDbNames.' service services'), ]; }); // Get all standalone databases $databases = collect(); // PostgreSQL $databases = $databases->merge( StandalonePostgresql::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'postgresql', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' postgresql '.$db->description.' database databases db'), ]; }) ); // MySQL $databases = $databases->merge( StandaloneMysql::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'mysql', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' mysql '.$db->description.' database databases db'), ]; }) ); // MariaDB $databases = $databases->merge( StandaloneMariadb::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'mariadb', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' mariadb '.$db->description.' database databases db'), ]; }) ); // MongoDB $databases = $databases->merge( StandaloneMongodb::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'mongodb', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' mongodb '.$db->description.' database databases db'), ]; }) ); // Redis $databases = $databases->merge( StandaloneRedis::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'redis', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' redis '.$db->description.' database databases db'), ]; }) ); // KeyDB $databases = $databases->merge( StandaloneKeydb::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'keydb', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' keydb '.$db->description.' database databases db'), ]; }) ); // Dragonfly $databases = $databases->merge( StandaloneDragonfly::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'dragonfly', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' dragonfly '.$db->description.' database databases db'), ]; }) ); // Clickhouse $databases = $databases->merge( StandaloneClickhouse::ownedByCurrentTeam() ->with(['environment.project']) ->get() ->map(function ($db) { return [ 'id' => $db->id, 'name' => $db->name, 'type' => 'database', 'subtype' => 'clickhouse', 'uuid' => $db->uuid, 'description' => $db->description, 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, 'search_text' => strtolower($db->name.' '.$db->uuid.' clickhouse '.$db->description.' database databases db'), ]; }) ); // Get all servers $servers = Server::ownedByCurrentTeam() ->get() ->map(function ($server) { return [ 'id' => $server->id, 'name' => $server->name, 'type' => 'server', 'uuid' => $server->uuid, 'description' => $server->description, 'link' => $server->url(), 'project' => null, 'environment' => null, 'search_text' => strtolower($server->name.' '.$server->ip.' '.$server->description.' server servers'), ]; }); ray($servers); // Get all projects $projects = Project::ownedByCurrentTeam() ->withCount(['environments', 'applications', 'services']) ->get() ->map(function ($project) { $resourceCount = $project->applications_count + $project->services_count; $resourceSummary = $resourceCount > 0 ? "{$resourceCount} resource".($resourceCount !== 1 ? 's' : '') : 'No resources'; return [ 'id' => $project->id, 'name' => $project->name, 'type' => 'project', 'uuid' => $project->uuid, 'description' => $project->description, 'link' => $project->navigateTo(), 'project' => null, 'environment' => null, 'resource_count' => $resourceSummary, 'environment_count' => $project->environments_count, 'search_text' => strtolower($project->name.' '.$project->description.' project projects'), ]; }); // Get all environments $environments = Environment::ownedByCurrentTeam() ->with('project') ->withCount(['applications', 'services']) ->get() ->map(function ($environment) { $resourceCount = $environment->applications_count + $environment->services_count; $resourceSummary = $resourceCount > 0 ? "{$resourceCount} resource".($resourceCount !== 1 ? 's' : '') : 'No resources'; // Build description with project context $descriptionParts = []; if ($environment->project) { $descriptionParts[] = "Project: {$environment->project->name}"; } if ($environment->description) { $descriptionParts[] = $environment->description; } if (empty($descriptionParts)) { $descriptionParts[] = $resourceSummary; } return [ 'id' => $environment->id, 'name' => $environment->name, 'type' => 'environment', 'uuid' => $environment->uuid, 'description' => implode(' • ', $descriptionParts), 'link' => route('project.resource.index', [ 'project_uuid' => $environment->project->uuid, 'environment_uuid' => $environment->uuid, ]), 'project' => $environment->project->name ?? null, 'environment' => null, 'resource_count' => $resourceSummary, 'search_text' => strtolower($environment->name.' '.$environment->description.' '.$environment->project->name.' environment'), ]; }); // Add navigation routes $navigation = collect([ [ 'name' => 'Dashboard', 'type' => 'navigation', 'description' => 'Go to main dashboard', 'link' => route('dashboard'), 'search_text' => 'dashboard home main overview', ], [ 'name' => 'Servers', 'type' => 'navigation', 'description' => 'View all servers', 'link' => route('server.index'), 'search_text' => 'servers all list view', ], [ 'name' => 'Projects', 'type' => 'navigation', 'description' => 'View all projects', 'link' => route('project.index'), 'search_text' => 'projects all list view', ], [ 'name' => 'Destinations', 'type' => 'navigation', 'description' => 'View all destinations', 'link' => route('destination.index'), 'search_text' => 'destinations docker networks', ], [ 'name' => 'Security', 'type' => 'navigation', 'description' => 'Manage private keys and API tokens', 'link' => route('security.private-key.index'), 'search_text' => 'security private keys ssh api tokens cloud-init scripts', ], [ 'name' => 'Cloud-Init Scripts', 'type' => 'navigation', 'description' => 'Manage reusable cloud-init scripts', 'link' => route('security.cloud-init-scripts'), 'search_text' => 'cloud-init scripts cloud init cloudinit initialization startup server setup', ], [ 'name' => 'Sources', 'type' => 'navigation', 'description' => 'Manage GitHub apps and Git sources', 'link' => route('source.all'), 'search_text' => 'sources github apps git repositories', ], [ 'name' => 'Storages', 'type' => 'navigation', 'description' => 'Manage S3 storage for backups', 'link' => route('storage.index'), 'search_text' => 'storages s3 backups', ], [ 'name' => 'Shared Variables', 'type' => 'navigation', 'description' => 'View all shared variables', 'link' => route('shared-variables.index'), 'search_text' => 'shared variables environment all', ], [ 'name' => 'Team Shared Variables', 'type' => 'navigation', 'description' => 'Manage team-wide shared variables', 'link' => route('shared-variables.team.index'), 'search_text' => 'shared variables team environment', ], [ 'name' => 'Project Shared Variables', 'type' => 'navigation', 'description' => 'Manage project shared variables', 'link' => route('shared-variables.project.index'), 'search_text' => 'shared variables project environment', ], [ 'name' => 'Environment Shared Variables', 'type' => 'navigation', 'description' => 'Manage environment shared variables', 'link' => route('shared-variables.environment.index'), 'search_text' => 'shared variables environment', ], [ 'name' => 'Tags', 'type' => 'navigation', 'description' => 'View resources by tags', 'link' => route('tags.show'), 'search_text' => 'tags labels organize', ], [ 'name' => 'Terminal', 'type' => 'navigation', 'description' => 'Access server terminal', 'link' => route('terminal'), 'search_text' => 'terminal ssh console shell command line', ], [ 'name' => 'Profile', 'type' => 'navigation', 'description' => 'Manage your profile and preferences', 'link' => route('profile'), 'search_text' => 'profile account user settings preferences', ], [ 'name' => 'Team', 'type' => 'navigation', 'description' => 'Manage team members and settings', 'link' => route('team.index'), 'search_text' => 'team settings members users invitations', ], [ 'name' => 'Notifications', 'type' => 'navigation', 'description' => 'Configure email, Discord, Telegram notifications', 'link' => route('notifications.email'), 'search_text' => 'notifications alerts email discord telegram slack pushover', ], ]); // Add instance settings only for self-hosted and root team if (! isCloud() && $team->id === 0) { $navigation->push([ 'name' => 'Settings', 'type' => 'navigation', 'description' => 'Instance settings and configuration', 'link' => route('settings.index'), 'search_text' => 'settings configuration instance', ]); } // Merge all collections $items = $items->merge($navigation) ->merge($applications) ->merge($services) ->merge($databases) ->merge($servers) ->merge($projects) ->merge($environments); return $items->toArray(); }); } private function search() { if (strlen($this->searchQuery) < 1) { $this->searchResults = []; return; } $query = strtolower($this->searchQuery); // Detect resource category queries $categoryMapping = [ 'server' => ['server', 'type' => 'server'], 'servers' => ['server', 'type' => 'server'], 'app' => ['application', 'type' => 'application'], 'apps' => ['application', 'type' => 'application'], 'application' => ['application', 'type' => 'application'], 'applications' => ['application', 'type' => 'application'], 'db' => ['database', 'type' => 'standalone-postgresql'], 'database' => ['database', 'type' => 'standalone-postgresql'], 'databases' => ['database', 'type' => 'standalone-postgresql'], 'service' => ['service', 'category' => 'Services'], 'services' => ['service', 'category' => 'Services'], 'project' => ['project', 'type' => 'project'], 'projects' => ['project', 'type' => 'project'], ]; $priorityCreatableItem = null; // Check if query matches a resource category if (isset($categoryMapping[$query])) { $this->loadCreatableItems(); $mapping = $categoryMapping[$query]; // Find the matching creatable item $priorityCreatableItem = collect($this->creatableItems) ->first(function ($item) use ($mapping) { if (isset($mapping['type'])) { return $item['type'] === $mapping['type']; } if (isset($mapping['category'])) { return isset($item['category']) && $item['category'] === $mapping['category']; } return false; }); if ($priorityCreatableItem) { $priorityCreatableItem['is_creatable_suggestion'] = true; } } // Search for matching creatable resources to show as suggestions (if no priority item) if (! $priorityCreatableItem) { $this->loadCreatableItems(); // Search in regular creatable items (apps, databases, quick actions) $creatableSuggestions = collect($this->creatableItems) ->filter(function ($item) use ($query) { $searchText = strtolower($item['name'].' '.$item['description'].' '.($item['type'] ?? '')); // Use word boundary matching to avoid substring matches (e.g., "wordpress" shouldn't match "classicpress") return preg_match('/\b'.preg_quote($query, '/').'/i', $searchText); }) ->map(function ($item) use ($query) { // Calculate match priority: name > type > description $name = strtolower($item['name']); $type = strtolower($item['type'] ?? ''); $description = strtolower($item['description']); if (preg_match('/\b'.preg_quote($query, '/').'/i', $name)) { $item['match_priority'] = 1; } elseif (preg_match('/\b'.preg_quote($query, '/').'/i', $type)) { $item['match_priority'] = 2; } else { $item['match_priority'] = 3; } $item['is_creatable_suggestion'] = true; return $item; }); // Also search in services (loaded on-demand) $serviceSuggestions = collect($this->services) ->filter(function ($item) use ($query) { $searchText = strtolower($item['name'].' '.$item['description'].' '.($item['type'] ?? '')); return preg_match('/\b'.preg_quote($query, '/').'/i', $searchText); }) ->map(function ($item) use ($query) { // Calculate match priority: name > type > description $name = strtolower($item['name']); $type = strtolower($item['type'] ?? ''); $description = strtolower($item['description']); if (preg_match('/\b'.preg_quote($query, '/').'/i', $name)) { $item['match_priority'] = 1; } elseif (preg_match('/\b'.preg_quote($query, '/').'/i', $type)) { $item['match_priority'] = 2; } else { $item['match_priority'] = 3; } $item['is_creatable_suggestion'] = true; return $item; }); // Merge and sort all suggestions $creatableSuggestions = $creatableSuggestions ->merge($serviceSuggestions) ->sortBy('match_priority') ->take(10) ->values() ->toArray(); } else { $creatableSuggestions = []; } // Case-insensitive search in existing resources $existingResults = collect($this->allSearchableItems) ->filter(function ($item) use ($query) { // Use word boundary matching to avoid substring matches (e.g., "wordpress" shouldn't match "classicpress") return preg_match('/\b'.preg_quote($query, '/').'/i', $item['search_text']); }) ->map(function ($item) use ($query) { // Calculate match priority: name > type > description $name = strtolower($item['name'] ?? ''); $type = strtolower($item['type'] ?? ''); $description = strtolower($item['description'] ?? ''); if (preg_match('/\b'.preg_quote($query, '/').'/i', $name)) { $item['match_priority'] = 1; } elseif (preg_match('/\b'.preg_quote($query, '/').'/i', $type)) { $item['match_priority'] = 2; } else { $item['match_priority'] = 3; } return $item; }) ->sortBy('match_priority') ->take(20) ->values() ->toArray(); // Merge results: existing resources first, then priority create item, then other creatable suggestions $results = []; // If we have existing results, show them first $results = array_merge($results, $existingResults); // Then show the priority "Create New" item (if exists) if ($priorityCreatableItem) { $results[] = $priorityCreatableItem; } // Finally show other creatable suggestions $results = array_merge($results, $creatableSuggestions); $this->searchResults = $results; } private function loadCreatableItems() { $items = collect(); $user = auth()->user(); // === Quick Actions Category === // Project - can be created if user has createAnyResource permission if ($user->can('createAnyResource')) { $items->push([ 'name' => 'Project', 'description' => 'Create a new project to organize your resources', 'quickcommand' => '(type: new project)', 'type' => 'project', 'category' => 'Quick Actions', 'component' => 'project.add-empty', ]); } // Server - can be created if user is admin or owner if ($user->isAdmin() || $user->isOwner()) { $items->push([ 'name' => 'Server', 'description' => 'Add a new server to deploy your applications', 'quickcommand' => '(type: new server)', 'type' => 'server', 'category' => 'Quick Actions', 'component' => 'server.create', ]); } // Team - can be created by anyone (they become owner of new team) $items->push([ 'name' => 'Team', 'description' => 'Create a new team to collaborate with others', 'quickcommand' => '(type: new team)', 'type' => 'team', 'category' => 'Quick Actions', 'component' => 'team.create', ]); // Storage - can be created if user is admin or owner if ($user->isAdmin() || $user->isOwner()) { $items->push([ 'name' => 'S3 Storage', 'description' => 'Add S3 storage for backups and file uploads', 'quickcommand' => '(type: new storage)', 'type' => 'storage', 'category' => 'Quick Actions', 'component' => 'storage.create', ]); } // Private Key - can be created if user is admin or owner if ($user->isAdmin() || $user->isOwner()) { $items->push([ 'name' => 'Private Key', 'description' => 'Add an SSH private key for server access', 'quickcommand' => '(type: new private key)', 'type' => 'private-key', 'category' => 'Quick Actions', 'component' => 'security.private-key.create', ]); } // GitHub Source - can be created if user has createAnyResource permission if ($user->can('createAnyResource')) { $items->push([ 'name' => 'GitHub App', 'description' => 'Connect a GitHub app for source control', 'quickcommand' => '(type: new github)', 'type' => 'source', 'category' => 'Quick Actions', 'component' => 'source.github.create', ]); } // === Applications Category === if ($user->can('createAnyResource')) { // Git-based applications $items->push([ 'name' => 'Public Git Repository', 'description' => 'Deploy from any public Git repository', 'quickcommand' => '(type: new public)', 'type' => 'public', 'category' => 'Applications', 'resourceType' => 'application', ]); $items->push([ 'name' => 'Private Repository (GitHub App)', 'description' => 'Deploy private repositories through GitHub Apps', 'quickcommand' => '(type: new private github)', 'type' => 'private-gh-app', 'category' => 'Applications', 'resourceType' => 'application', ]); $items->push([ 'name' => 'Private Repository (Deploy Key)', 'description' => 'Deploy private repositories with a deploy key', 'quickcommand' => '(type: new private deploy)', 'type' => 'private-deploy-key', 'category' => 'Applications', 'resourceType' => 'application', ]); // Docker-based applications $items->push([ 'name' => 'Dockerfile', 'description' => 'Deploy a simple Dockerfile without Git', 'quickcommand' => '(type: new dockerfile)', 'type' => 'dockerfile', 'category' => 'Applications', 'resourceType' => 'application', ]); $items->push([ 'name' => 'Docker Compose', 'description' => 'Deploy complex applications with Docker Compose', 'quickcommand' => '(type: new compose)', 'type' => 'docker-compose-empty', 'category' => 'Applications', 'resourceType' => 'application', ]); $items->push([ 'name' => 'Docker Image', 'description' => 'Deploy an existing Docker image from any registry', 'quickcommand' => '(type: new image)', 'type' => 'docker-image', 'category' => 'Applications', 'resourceType' => 'application', ]); } // === Databases Category === if ($user->can('createAnyResource')) { $items->push([ 'name' => 'PostgreSQL', 'description' => 'Robust, advanced open-source database', 'quickcommand' => '(type: new postgresql)', 'type' => 'postgresql', 'category' => 'Databases', 'resourceType' => 'database', ]); $items->push([ 'name' => 'MySQL', 'description' => 'Popular open-source relational database', 'quickcommand' => '(type: new mysql)', 'type' => 'mysql', 'category' => 'Databases', 'resourceType' => 'database', ]); $items->push([ 'name' => 'MariaDB', 'description' => 'Community-developed fork of MySQL', 'quickcommand' => '(type: new mariadb)', 'type' => 'mariadb', 'category' => 'Databases', 'resourceType' => 'database', ]); $items->push([ 'name' => 'Redis', 'description' => 'In-memory data structure store', 'quickcommand' => '(type: new redis)', 'type' => 'redis', 'category' => 'Databases', 'resourceType' => 'database', ]); $items->push([ 'name' => 'KeyDB', 'description' => 'High-performance Redis alternative', 'quickcommand' => '(type: new keydb)', 'type' => 'keydb', 'category' => 'Databases', 'resourceType' => 'database', ]); $items->push([ 'name' => 'Dragonfly', 'description' => 'Modern in-memory datastore', 'quickcommand' => '(type: new dragonfly)', 'type' => 'dragonfly', 'category' => 'Databases', 'resourceType' => 'database', ]); $items->push([ 'name' => 'MongoDB', 'description' => 'Document-oriented NoSQL database', 'quickcommand' => '(type: new mongodb)', 'type' => 'mongodb', 'category' => 'Databases', 'resourceType' => 'database', ]); $items->push([ 'name' => 'Clickhouse', 'description' => 'Column-oriented database for analytics', 'quickcommand' => '(type: new clickhouse)', 'type' => 'clickhouse', 'category' => 'Databases', 'resourceType' => 'database', ]); } // Merge with services $items = $items->merge(collect($this->services)); $this->creatableItems = $items->toArray(); } public function navigateToResource($type) { // Find the item by type - check regular items first, then services $item = collect($this->creatableItems)->firstWhere('type', $type); if (! $item) { $item = collect($this->services)->firstWhere('type', $type); } if (! $item) { return; } // If it has a component, it's a modal-based resource // Close search modal and open the appropriate creation modal if (isset($item['component'])) { $this->dispatch('closeSearchModal'); $this->dispatch('open-create-modal-'.$type); return; } // For applications, databases, and services, navigate to resource creation // with smart defaults (auto-select if only 1 server/project/environment) if (isset($item['resourceType'])) { $this->navigateToResourceCreation($type); } } private function navigateToResourceCreation($type) { // Start the selection flow $this->selectedResourceType = $type; $this->isSelectingResource = true; // Clear search query to show selection UI instead of creatable items $this->searchQuery = ''; // Reset selections $this->selectedServerId = null; $this->selectedDestinationUuid = null; $this->selectedProjectUuid = null; $this->selectedEnvironmentUuid = null; // Start loading servers first (in order: servers -> destinations -> projects -> environments) $this->loadServers(); } public function loadServers() { $this->loadingServers = true; $servers = Server::isUsable()->get()->sortBy('name'); $this->availableServers = $servers->map(fn ($s) => [ 'id' => $s->id, 'name' => $s->name, 'description' => $s->description, ])->toArray(); $this->loadingServers = false; // Auto-select if only one server if (count($this->availableServers) === 1) { $this->selectServer($this->availableServers[0]['id']); } } public function selectServer($serverId, $shouldProgress = true) { $this->selectedServerId = $serverId; if ($shouldProgress) { $this->loadDestinations(); } } public function loadDestinations() { $this->loadingDestinations = true; $server = Server::find($this->selectedServerId); if (! $server) { $this->loadingDestinations = false; return $this->dispatch('error', message: 'Server not found'); } $destinations = $server->destinations(); if ($destinations->isEmpty()) { $this->loadingDestinations = false; return $this->dispatch('error', message: 'No destinations found on this server'); } $this->availableDestinations = $destinations->map(fn ($d) => [ 'uuid' => $d->uuid, 'name' => $d->name, 'network' => $d->network ?? 'default', ])->toArray(); $this->loadingDestinations = false; // Auto-select if only one destination if (count($this->availableDestinations) === 1) { $this->selectDestination($this->availableDestinations[0]['uuid']); } } public function selectDestination($destinationUuid, $shouldProgress = true) { $this->selectedDestinationUuid = $destinationUuid; if ($shouldProgress) { $this->loadProjects(); } } public function loadProjects() { $this->loadingProjects = true; $user = auth()->user(); $team = $user->currentTeam(); $projects = Project::where('team_id', $team->id)->get(); if ($projects->isEmpty()) { $this->loadingProjects = false; return $this->dispatch('error', message: 'Please create a project first'); } $this->availableProjects = $projects->map(fn ($p) => [ 'uuid' => $p->uuid, 'name' => $p->name, 'description' => $p->description, ])->toArray(); $this->loadingProjects = false; // Auto-select if only one project if (count($this->availableProjects) === 1) { $this->selectProject($this->availableProjects[0]['uuid']); } } public function selectProject($projectUuid, $shouldProgress = true) { $this->selectedProjectUuid = $projectUuid; if ($shouldProgress) { $this->loadEnvironments(); } } public function loadEnvironments() { $this->loadingEnvironments = true; $project = Project::where('uuid', $this->selectedProjectUuid)->first(); if (! $project) { $this->loadingEnvironments = false; return; } $environments = $project->environments; if ($environments->isEmpty()) { $this->loadingEnvironments = false; return $this->dispatch('error', message: 'No environments found in project'); } $this->availableEnvironments = $environments->map(fn ($e) => [ 'uuid' => $e->uuid, 'name' => $e->name, 'description' => $e->description, ])->toArray(); $this->loadingEnvironments = false; // Auto-select if only one environment if (count($this->availableEnvironments) === 1) { $this->selectEnvironment($this->availableEnvironments[0]['uuid']); } } public function selectEnvironment($environmentUuid, $shouldProgress = true) { $this->selectedEnvironmentUuid = $environmentUuid; if ($shouldProgress) { $this->completeResourceCreation(); } } private function completeResourceCreation() { // All selections made - navigate to resource creation if ($this->selectedProjectUuid && $this->selectedEnvironmentUuid && $this->selectedResourceType && $this->selectedServerId !== null && $this->selectedDestinationUuid) { $queryParams = [ 'type' => $this->selectedResourceType, 'destination' => $this->selectedDestinationUuid, 'server_id' => $this->selectedServerId, ]; redirectRoute($this, 'project.resource.create', [ 'project_uuid' => $this->selectedProjectUuid, 'environment_uuid' => $this->selectedEnvironmentUuid, ] + $queryParams); } } public function cancelResourceSelection() { $this->isSelectingResource = false; $this->selectedResourceType = null; $this->selectedServerId = null; $this->selectedDestinationUuid = null; $this->selectedProjectUuid = null; $this->selectedEnvironmentUuid = null; $this->availableServers = []; $this->availableDestinations = []; $this->availableProjects = []; $this->availableEnvironments = []; $this->autoOpenResource = null; } public function goBack() { // From Environment Selection → go back to Project (if multiple) or further if ($this->selectedProjectUuid !== null) { $this->selectedProjectUuid = null; $this->selectedEnvironmentUuid = null; if (count($this->availableProjects) > 1) { return; // Stop here - user can choose a project } } // From Project Selection → go back to Destination (if multiple) or further if ($this->selectedDestinationUuid !== null) { $this->selectedDestinationUuid = null; $this->selectedProjectUuid = null; $this->selectedEnvironmentUuid = null; if (count($this->availableDestinations) > 1) { return; // Stop here - user can choose a destination } } // From Destination Selection → go back to Server (if multiple) or cancel if ($this->selectedServerId !== null) { $this->selectedServerId = null; $this->selectedDestinationUuid = null; $this->selectedProjectUuid = null; $this->selectedEnvironmentUuid = null; if (count($this->availableServers) > 1) { return; // Stop here - user can choose a server } } // All previous steps were auto-selected, cancel entirely $this->cancelResourceSelection(); } public function getFilteredCreatableItemsProperty() { $query = strtolower(trim($this->searchQuery)); // Check if query matches a category keyword $categoryKeywords = ['server', 'servers', 'app', 'apps', 'application', 'applications', 'db', 'database', 'databases', 'service', 'services', 'project', 'projects']; if (in_array($query, $categoryKeywords)) { return $this->filterCreatableItemsByCategory($query); } // Extract search term - everything after "new " if (str_starts_with($query, 'new ')) { $searchTerm = trim(substr($query, strlen('new '))); if (empty($searchTerm)) { return $this->creatableItems; } // Filter items by name or description return collect($this->creatableItems)->filter(function ($item) use ($searchTerm) { $searchText = strtolower($item['name'].' '.$item['description'].' '.$item['category']); return str_contains($searchText, $searchTerm); })->values()->toArray(); } return $this->creatableItems; } private function filterCreatableItemsByCategory($categoryKeyword) { // Map keywords to category names $categoryMap = [ 'server' => 'Quick Actions', 'servers' => 'Quick Actions', 'app' => 'Applications', 'apps' => 'Applications', 'application' => 'Applications', 'applications' => 'Applications', 'db' => 'Databases', 'database' => 'Databases', 'databases' => 'Databases', 'service' => 'Services', 'services' => 'Services', 'project' => 'Applications', 'projects' => 'Applications', ]; $category = $categoryMap[$categoryKeyword] ?? null; if (! $category) { return []; } return collect($this->creatableItems) ->filter(fn ($item) => $item['category'] === $category) ->values() ->toArray(); } public function getSelectedResourceNameProperty() { if (! $this->selectedResourceType) { return null; } // Load creatable items if not loaded yet if (empty($this->creatableItems)) { $this->loadCreatableItems(); } // Find the item by type - check regular items first, then services $item = collect($this->creatableItems)->firstWhere('type', $this->selectedResourceType); if (! $item) { $item = collect($this->services)->firstWhere('type', $this->selectedResourceType); } return $item ? $item['name'] : null; } public function getServicesProperty() { // Cache services in a static property to avoid reloading on every access static $cachedServices = null; if ($cachedServices !== null) { return $cachedServices; } $user = auth()->user(); if (! $user->can('createAnyResource')) { $cachedServices = []; return $cachedServices; } // Load all services $allServices = get_service_templates(); $items = collect(); foreach ($allServices as $serviceKey => $service) { $items->push([ 'name' => str($serviceKey)->headline()->toString(), 'description' => data_get($service, 'slogan', 'Deploy '.str($serviceKey)->headline()), 'type' => 'one-click-service-'.$serviceKey, 'category' => 'Services', 'resourceType' => 'service', 'logo' => data_get($service, 'logo'), ]); } $cachedServices = $items->toArray(); return $cachedServices; } public function render() { return view('livewire.global-search'); } } ================================================ FILE: app/Livewire/Help.php ================================================ validate(); $this->rateLimit(3, 30); $settings = instanceSettings(); $mail = new MailMessage; $mail->view( 'emails.help', [ 'description' => $this->description, ] ); $mail->subject("[HELP]: {$this->subject}"); $type = set_transanctional_email_settings($settings); // Sending feedback through Cloud API if (blank($type)) { $url = 'https://app.coolify.io/api/feedback'; Http::post($url, [ 'content' => 'User: `'.auth()->user()?->email.'` with subject: `'.$this->subject.'` has the following problem: `'.$this->description.'`', ]); } else { send_user_an_email($mail, auth()->user()?->email, 'feedback@coollabs.io'); } $this->dispatch('success', 'Feedback sent.', 'We will get in touch with you as soon as possible.'); $this->reset('description', 'subject'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.help')->layout('layouts.app'); } } ================================================ FILE: app/Livewire/LayoutPopups.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},TestEvent" => 'testEvent', ]; } public function testEvent() { $this->dispatch('success', 'Realtime events configured!'); } public function render() { return view('livewire.layout-popups'); } } ================================================ FILE: app/Livewire/MonacoEditor.php ================================================ '$refresh', ]; public function __construct( public ?string $id, public ?string $name, public ?string $type, public ?string $monacoContent, public ?string $value, public ?string $label, public ?string $placeholder, public bool $required, public bool $disabled, public bool $readonly, public bool $allowTab, public bool $spellcheck, public bool $autofocus, public ?string $helper, public bool $realtimeValidation, public bool $allowToPeak, public string $defaultClass, public string $defaultClassInput, public ?string $language ) { // } public function render() { if (is_null($this->id)) { $this->id = new Cuid2; } if (is_null($this->name)) { $this->name = $this->id; } return view('components.forms.monaco-editor'); } } ================================================ FILE: app/Livewire/NavbarDeleteTeam.php ================================================ team = currentTeam()->name; } public function delete($password, $selectedActions = []) { if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } $currentTeam = currentTeam(); $currentTeam->delete(); $currentTeam->members->each(function ($user) use ($currentTeam) { if ($user->id === Auth::id()) { return; } $user->teams()->detach($currentTeam); $session = DB::table('sessions')->where('user_id', $user->id)->first(); if ($session) { DB::table('sessions')->where('id', $session->id)->delete(); } }); refreshSession(); return redirectRoute($this, 'team.index'); } public function render() { return view('livewire.navbar-delete-team'); } } ================================================ FILE: app/Livewire/Notifications/Discord.php ================================================ team = auth()->user()->currentTeam(); $this->settings = $this->team->discordNotificationSettings; $this->authorize('view', $this->settings); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->authorize('update', $this->settings); $this->settings->discord_enabled = $this->discordEnabled; $this->settings->discord_webhook_url = $this->discordWebhookUrl; $this->settings->deployment_success_discord_notifications = $this->deploymentSuccessDiscordNotifications; $this->settings->deployment_failure_discord_notifications = $this->deploymentFailureDiscordNotifications; $this->settings->status_change_discord_notifications = $this->statusChangeDiscordNotifications; $this->settings->backup_success_discord_notifications = $this->backupSuccessDiscordNotifications; $this->settings->backup_failure_discord_notifications = $this->backupFailureDiscordNotifications; $this->settings->scheduled_task_success_discord_notifications = $this->scheduledTaskSuccessDiscordNotifications; $this->settings->scheduled_task_failure_discord_notifications = $this->scheduledTaskFailureDiscordNotifications; $this->settings->docker_cleanup_success_discord_notifications = $this->dockerCleanupSuccessDiscordNotifications; $this->settings->docker_cleanup_failure_discord_notifications = $this->dockerCleanupFailureDiscordNotifications; $this->settings->server_disk_usage_discord_notifications = $this->serverDiskUsageDiscordNotifications; $this->settings->server_reachable_discord_notifications = $this->serverReachableDiscordNotifications; $this->settings->server_unreachable_discord_notifications = $this->serverUnreachableDiscordNotifications; $this->settings->server_patch_discord_notifications = $this->serverPatchDiscordNotifications; $this->settings->traefik_outdated_discord_notifications = $this->traefikOutdatedDiscordNotifications; $this->settings->discord_ping_enabled = $this->discordPingEnabled; $this->settings->save(); refreshSession(); } else { $this->discordEnabled = $this->settings->discord_enabled; $this->discordWebhookUrl = $this->settings->discord_webhook_url; $this->deploymentSuccessDiscordNotifications = $this->settings->deployment_success_discord_notifications; $this->deploymentFailureDiscordNotifications = $this->settings->deployment_failure_discord_notifications; $this->statusChangeDiscordNotifications = $this->settings->status_change_discord_notifications; $this->backupSuccessDiscordNotifications = $this->settings->backup_success_discord_notifications; $this->backupFailureDiscordNotifications = $this->settings->backup_failure_discord_notifications; $this->scheduledTaskSuccessDiscordNotifications = $this->settings->scheduled_task_success_discord_notifications; $this->scheduledTaskFailureDiscordNotifications = $this->settings->scheduled_task_failure_discord_notifications; $this->dockerCleanupSuccessDiscordNotifications = $this->settings->docker_cleanup_success_discord_notifications; $this->dockerCleanupFailureDiscordNotifications = $this->settings->docker_cleanup_failure_discord_notifications; $this->serverDiskUsageDiscordNotifications = $this->settings->server_disk_usage_discord_notifications; $this->serverReachableDiscordNotifications = $this->settings->server_reachable_discord_notifications; $this->serverUnreachableDiscordNotifications = $this->settings->server_unreachable_discord_notifications; $this->serverPatchDiscordNotifications = $this->settings->server_patch_discord_notifications; $this->traefikOutdatedDiscordNotifications = $this->settings->traefik_outdated_discord_notifications; $this->discordPingEnabled = $this->settings->discord_ping_enabled; } } public function instantSaveDiscordPingEnabled() { try { $original = $this->discordPingEnabled; $this->validate([ 'discordPingEnabled' => 'required', ]); $this->saveModel(); } catch (\Throwable $e) { $this->discordPingEnabled = $original; return handleError($e, $this); } } public function instantSaveDiscordEnabled() { try { $original = $this->discordEnabled; $this->validate([ 'discordWebhookUrl' => 'required', ], [ 'discordWebhookUrl.required' => 'Discord Webhook URL is required.', ]); $this->saveModel(); } catch (\Throwable $e) { $this->discordEnabled = $original; return handleError($e, $this); } } public function instantSave() { try { $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->resetErrorBag(); $this->syncData(true); $this->saveModel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function saveModel() { $this->syncData(true); refreshSession(); $this->dispatch('success', 'Settings saved.'); } public function sendTestNotification() { try { $this->authorize('sendTest', $this->settings); $this->team->notify(new Test(channel: 'discord')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.notifications.discord'); } } ================================================ FILE: app/Livewire/Notifications/Email.php ================================================ '$refresh']; #[Locked] public Team $team; #[Locked] public EmailNotificationSettings $settings; #[Locked] public string $emails; #[Validate(['boolean'])] public bool $smtpEnabled = false; #[Validate(['nullable', 'email'])] public ?string $smtpFromAddress = null; #[Validate(['nullable', 'string'])] public ?string $smtpFromName = null; #[Validate(['nullable', 'string'])] public ?string $smtpRecipients = null; #[Validate(['nullable', 'string'])] public ?string $smtpHost = null; #[Validate(['nullable', 'numeric', 'min:1', 'max:65535'])] public ?int $smtpPort = null; #[Validate(['nullable', 'string', 'in:starttls,tls,none'])] public ?string $smtpEncryption = null; #[Validate(['nullable', 'string'])] public ?string $smtpUsername = null; #[Validate(['nullable', 'string'])] public ?string $smtpPassword = null; #[Validate(['nullable', 'numeric'])] public ?int $smtpTimeout = null; #[Validate(['boolean'])] public bool $resendEnabled = false; #[Validate(['nullable', 'string'])] public ?string $resendApiKey = null; #[Validate(['boolean'])] public bool $useInstanceEmailSettings = false; #[Validate(['boolean'])] public bool $deploymentSuccessEmailNotifications = false; #[Validate(['boolean'])] public bool $deploymentFailureEmailNotifications = true; #[Validate(['boolean'])] public bool $statusChangeEmailNotifications = false; #[Validate(['boolean'])] public bool $backupSuccessEmailNotifications = false; #[Validate(['boolean'])] public bool $backupFailureEmailNotifications = true; #[Validate(['boolean'])] public bool $scheduledTaskSuccessEmailNotifications = false; #[Validate(['boolean'])] public bool $scheduledTaskFailureEmailNotifications = true; #[Validate(['boolean'])] public bool $dockerCleanupSuccessEmailNotifications = false; #[Validate(['boolean'])] public bool $dockerCleanupFailureEmailNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsageEmailNotifications = true; #[Validate(['boolean'])] public bool $serverReachableEmailNotifications = false; #[Validate(['boolean'])] public bool $serverUnreachableEmailNotifications = true; #[Validate(['boolean'])] public bool $serverPatchEmailNotifications = false; #[Validate(['boolean'])] public bool $traefikOutdatedEmailNotifications = true; #[Validate(['nullable', 'email'])] public ?string $testEmailAddress = null; public function mount() { try { $this->team = auth()->user()->currentTeam(); $this->emails = auth()->user()->email; $this->settings = $this->team->emailNotificationSettings; $this->authorize('view', $this->settings); $this->syncData(); $this->testEmailAddress = auth()->user()->email; } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->authorize('update', $this->settings); $this->settings->smtp_enabled = $this->smtpEnabled; $this->settings->smtp_from_address = $this->smtpFromAddress; $this->settings->smtp_from_name = $this->smtpFromName; $this->settings->smtp_recipients = $this->smtpRecipients; $this->settings->smtp_host = $this->smtpHost; $this->settings->smtp_port = $this->smtpPort; $this->settings->smtp_encryption = $this->smtpEncryption; $this->settings->smtp_username = $this->smtpUsername; $this->settings->smtp_password = $this->smtpPassword; $this->settings->smtp_timeout = $this->smtpTimeout; $this->settings->resend_enabled = $this->resendEnabled; $this->settings->resend_api_key = $this->resendApiKey; $this->settings->use_instance_email_settings = $this->useInstanceEmailSettings; $this->settings->deployment_success_email_notifications = $this->deploymentSuccessEmailNotifications; $this->settings->deployment_failure_email_notifications = $this->deploymentFailureEmailNotifications; $this->settings->status_change_email_notifications = $this->statusChangeEmailNotifications; $this->settings->backup_success_email_notifications = $this->backupSuccessEmailNotifications; $this->settings->backup_failure_email_notifications = $this->backupFailureEmailNotifications; $this->settings->scheduled_task_success_email_notifications = $this->scheduledTaskSuccessEmailNotifications; $this->settings->scheduled_task_failure_email_notifications = $this->scheduledTaskFailureEmailNotifications; $this->settings->docker_cleanup_success_email_notifications = $this->dockerCleanupSuccessEmailNotifications; $this->settings->docker_cleanup_failure_email_notifications = $this->dockerCleanupFailureEmailNotifications; $this->settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications; $this->settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications; $this->settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications; $this->settings->server_patch_email_notifications = $this->serverPatchEmailNotifications; $this->settings->traefik_outdated_email_notifications = $this->traefikOutdatedEmailNotifications; $this->settings->save(); } else { $this->smtpEnabled = $this->settings->smtp_enabled; $this->smtpFromAddress = $this->settings->smtp_from_address; $this->smtpFromName = $this->settings->smtp_from_name; $this->smtpRecipients = $this->settings->smtp_recipients; $this->smtpHost = $this->settings->smtp_host; $this->smtpPort = $this->settings->smtp_port; $this->smtpEncryption = $this->settings->smtp_encryption; $this->smtpUsername = $this->settings->smtp_username; $this->smtpPassword = $this->settings->smtp_password; $this->smtpTimeout = $this->settings->smtp_timeout; $this->resendEnabled = $this->settings->resend_enabled; $this->resendApiKey = $this->settings->resend_api_key; $this->useInstanceEmailSettings = $this->settings->use_instance_email_settings; $this->deploymentSuccessEmailNotifications = $this->settings->deployment_success_email_notifications; $this->deploymentFailureEmailNotifications = $this->settings->deployment_failure_email_notifications; $this->statusChangeEmailNotifications = $this->settings->status_change_email_notifications; $this->backupSuccessEmailNotifications = $this->settings->backup_success_email_notifications; $this->backupFailureEmailNotifications = $this->settings->backup_failure_email_notifications; $this->scheduledTaskSuccessEmailNotifications = $this->settings->scheduled_task_success_email_notifications; $this->scheduledTaskFailureEmailNotifications = $this->settings->scheduled_task_failure_email_notifications; $this->dockerCleanupSuccessEmailNotifications = $this->settings->docker_cleanup_success_email_notifications; $this->dockerCleanupFailureEmailNotifications = $this->settings->docker_cleanup_failure_email_notifications; $this->serverDiskUsageEmailNotifications = $this->settings->server_disk_usage_email_notifications; $this->serverReachableEmailNotifications = $this->settings->server_reachable_email_notifications; $this->serverUnreachableEmailNotifications = $this->settings->server_unreachable_email_notifications; $this->serverPatchEmailNotifications = $this->settings->server_patch_email_notifications; $this->traefikOutdatedEmailNotifications = $this->settings->traefik_outdated_email_notifications; } } public function submit() { try { $this->resetErrorBag(); $this->saveModel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function saveModel() { $this->syncData(true); $this->dispatch('success', 'Email notifications settings updated.'); } public function instantSave(?string $type = null) { try { $this->resetErrorBag(); if ($type === 'SMTP') { $this->submitSmtp(); } elseif ($type === 'Resend') { $this->submitResend(); } else { $this->smtpEnabled = false; $this->resendEnabled = false; $this->saveModel(); return; } } catch (\Throwable $e) { if ($type === 'SMTP') { $this->smtpEnabled = false; } elseif ($type === 'Resend') { $this->resendEnabled = false; } return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function submitSmtp() { try { $this->resetErrorBag(); $this->validate([ 'smtpEnabled' => 'boolean', 'smtpFromAddress' => 'required|email', 'smtpFromName' => 'required|string', 'smtpHost' => 'required|string', 'smtpPort' => 'required|numeric', 'smtpEncryption' => 'required|string|in:starttls,tls,none', 'smtpUsername' => 'nullable|string', 'smtpPassword' => 'nullable|string', 'smtpTimeout' => 'nullable|numeric', ], [ 'smtpFromAddress.required' => 'From Address is required.', 'smtpFromAddress.email' => 'Please enter a valid email address.', 'smtpFromName.required' => 'From Name is required.', 'smtpHost.required' => 'SMTP Host is required.', 'smtpPort.required' => 'SMTP Port is required.', 'smtpPort.numeric' => 'SMTP Port must be a number.', 'smtpEncryption.required' => 'Encryption type is required.', ]); if ($this->smtpEnabled) { $this->settings->resend_enabled = $this->resendEnabled = false; } $this->settings->smtp_enabled = $this->smtpEnabled; $this->settings->smtp_from_address = $this->smtpFromAddress; $this->settings->smtp_from_name = $this->smtpFromName; $this->settings->smtp_host = $this->smtpHost; $this->settings->smtp_port = $this->smtpPort; $this->settings->smtp_encryption = $this->smtpEncryption; $this->settings->smtp_username = $this->smtpUsername; $this->settings->smtp_password = $this->smtpPassword; $this->settings->smtp_timeout = $this->smtpTimeout; $this->settings->save(); $this->dispatch('success', 'SMTP settings updated.'); } catch (\Throwable $e) { $this->smtpEnabled = false; return handleError($e, $this); } } public function submitResend() { try { $this->resetErrorBag(); $this->validate([ 'resendEnabled' => 'boolean', 'resendApiKey' => 'required|string', 'smtpFromAddress' => 'required|email', 'smtpFromName' => 'required|string', ], [ 'resendApiKey.required' => 'Resend API Key is required.', 'smtpFromAddress.required' => 'From Address is required.', 'smtpFromAddress.email' => 'Please enter a valid email address.', 'smtpFromName.required' => 'From Name is required.', ]); if ($this->resendEnabled) { $this->settings->smtp_enabled = $this->smtpEnabled = false; } $this->settings->resend_enabled = $this->resendEnabled; $this->settings->resend_api_key = $this->resendApiKey; $this->settings->smtp_from_address = $this->smtpFromAddress; $this->settings->smtp_from_name = $this->smtpFromName; $this->settings->save(); $this->dispatch('success', 'Resend settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function sendTestEmail() { try { $this->authorize('sendTest', $this->settings); $this->validate([ 'testEmailAddress' => 'required|email', ], [ 'testEmailAddress.required' => 'Test email address is required.', 'testEmailAddress.email' => 'Please enter a valid email address.', ]); $executed = RateLimiter::attempt( 'test-email:'.$this->team->id, $perMinute = 0, function () { $this->team?->notifyNow(new Test($this->testEmailAddress, 'email')); $this->dispatch('success', 'Test Email sent.'); }, $decaySeconds = 10, ); if (! $executed) { throw new \Exception('Too many messages sent!'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function copyFromInstanceSettings() { $this->authorize('update', $this->settings); $settings = instanceSettings(); $this->smtpFromAddress = $settings->smtp_from_address; $this->smtpFromName = $settings->smtp_from_name; if ($settings->smtp_enabled) { $this->smtpEnabled = true; $this->resendEnabled = false; } $this->smtpRecipients = $settings->smtp_recipients; $this->smtpHost = $settings->smtp_host; $this->smtpPort = $settings->smtp_port; $this->smtpEncryption = $settings->smtp_encryption; $this->smtpUsername = $settings->smtp_username; $this->smtpPassword = $settings->smtp_password; $this->smtpTimeout = $settings->smtp_timeout; if ($settings->resend_enabled) { $this->resendEnabled = true; $this->smtpEnabled = false; } $this->resendApiKey = $settings->resend_api_key; $this->saveModel(); } public function render() { return view('livewire.notifications.email'); } } ================================================ FILE: app/Livewire/Notifications/Pushover.php ================================================ '$refresh']; #[Locked] public Team $team; #[Locked] public PushoverNotificationSettings $settings; #[Validate(['boolean'])] public bool $pushoverEnabled = false; #[Validate(['nullable', 'string'])] public ?string $pushoverUserKey = null; #[Validate(['nullable', 'string'])] public ?string $pushoverApiToken = null; #[Validate(['boolean'])] public bool $deploymentSuccessPushoverNotifications = false; #[Validate(['boolean'])] public bool $deploymentFailurePushoverNotifications = true; #[Validate(['boolean'])] public bool $statusChangePushoverNotifications = false; #[Validate(['boolean'])] public bool $backupSuccessPushoverNotifications = false; #[Validate(['boolean'])] public bool $backupFailurePushoverNotifications = true; #[Validate(['boolean'])] public bool $scheduledTaskSuccessPushoverNotifications = false; #[Validate(['boolean'])] public bool $scheduledTaskFailurePushoverNotifications = true; #[Validate(['boolean'])] public bool $dockerCleanupSuccessPushoverNotifications = false; #[Validate(['boolean'])] public bool $dockerCleanupFailurePushoverNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsagePushoverNotifications = true; #[Validate(['boolean'])] public bool $serverReachablePushoverNotifications = false; #[Validate(['boolean'])] public bool $serverUnreachablePushoverNotifications = true; #[Validate(['boolean'])] public bool $serverPatchPushoverNotifications = false; #[Validate(['boolean'])] public bool $traefikOutdatedPushoverNotifications = true; public function mount() { try { $this->team = auth()->user()->currentTeam(); $this->settings = $this->team->pushoverNotificationSettings; $this->authorize('view', $this->settings); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->authorize('update', $this->settings); $this->settings->pushover_enabled = $this->pushoverEnabled; $this->settings->pushover_user_key = $this->pushoverUserKey; $this->settings->pushover_api_token = $this->pushoverApiToken; $this->settings->deployment_success_pushover_notifications = $this->deploymentSuccessPushoverNotifications; $this->settings->deployment_failure_pushover_notifications = $this->deploymentFailurePushoverNotifications; $this->settings->status_change_pushover_notifications = $this->statusChangePushoverNotifications; $this->settings->backup_success_pushover_notifications = $this->backupSuccessPushoverNotifications; $this->settings->backup_failure_pushover_notifications = $this->backupFailurePushoverNotifications; $this->settings->scheduled_task_success_pushover_notifications = $this->scheduledTaskSuccessPushoverNotifications; $this->settings->scheduled_task_failure_pushover_notifications = $this->scheduledTaskFailurePushoverNotifications; $this->settings->docker_cleanup_success_pushover_notifications = $this->dockerCleanupSuccessPushoverNotifications; $this->settings->docker_cleanup_failure_pushover_notifications = $this->dockerCleanupFailurePushoverNotifications; $this->settings->server_disk_usage_pushover_notifications = $this->serverDiskUsagePushoverNotifications; $this->settings->server_reachable_pushover_notifications = $this->serverReachablePushoverNotifications; $this->settings->server_unreachable_pushover_notifications = $this->serverUnreachablePushoverNotifications; $this->settings->server_patch_pushover_notifications = $this->serverPatchPushoverNotifications; $this->settings->traefik_outdated_pushover_notifications = $this->traefikOutdatedPushoverNotifications; $this->settings->save(); refreshSession(); } else { $this->pushoverEnabled = $this->settings->pushover_enabled; $this->pushoverUserKey = $this->settings->pushover_user_key; $this->pushoverApiToken = $this->settings->pushover_api_token; $this->deploymentSuccessPushoverNotifications = $this->settings->deployment_success_pushover_notifications; $this->deploymentFailurePushoverNotifications = $this->settings->deployment_failure_pushover_notifications; $this->statusChangePushoverNotifications = $this->settings->status_change_pushover_notifications; $this->backupSuccessPushoverNotifications = $this->settings->backup_success_pushover_notifications; $this->backupFailurePushoverNotifications = $this->settings->backup_failure_pushover_notifications; $this->scheduledTaskSuccessPushoverNotifications = $this->settings->scheduled_task_success_pushover_notifications; $this->scheduledTaskFailurePushoverNotifications = $this->settings->scheduled_task_failure_pushover_notifications; $this->dockerCleanupSuccessPushoverNotifications = $this->settings->docker_cleanup_success_pushover_notifications; $this->dockerCleanupFailurePushoverNotifications = $this->settings->docker_cleanup_failure_pushover_notifications; $this->serverDiskUsagePushoverNotifications = $this->settings->server_disk_usage_pushover_notifications; $this->serverReachablePushoverNotifications = $this->settings->server_reachable_pushover_notifications; $this->serverUnreachablePushoverNotifications = $this->settings->server_unreachable_pushover_notifications; $this->serverPatchPushoverNotifications = $this->settings->server_patch_pushover_notifications; $this->traefikOutdatedPushoverNotifications = $this->settings->traefik_outdated_pushover_notifications; } } public function instantSavePushoverEnabled() { try { $this->validate([ 'pushoverUserKey' => 'required', 'pushoverApiToken' => 'required', ], [ 'pushoverUserKey.required' => 'Pushover User Key is required.', 'pushoverApiToken.required' => 'Pushover API Token is required.', ]); $this->saveModel(); } catch (\Throwable $e) { $this->pushoverEnabled = false; return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function instantSave() { try { $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function submit() { try { $this->resetErrorBag(); $this->syncData(true); $this->saveModel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function saveModel() { $this->syncData(true); refreshSession(); $this->dispatch('success', 'Settings saved.'); } public function sendTestNotification() { try { $this->authorize('sendTest', $this->settings); $this->team->notify(new Test(channel: 'pushover')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.notifications.pushover'); } } ================================================ FILE: app/Livewire/Notifications/Slack.php ================================================ '$refresh']; #[Locked] public Team $team; #[Locked] public SlackNotificationSettings $settings; #[Validate(['boolean'])] public bool $slackEnabled = false; #[Validate(['url', 'nullable'])] public ?string $slackWebhookUrl = null; #[Validate(['boolean'])] public bool $deploymentSuccessSlackNotifications = false; #[Validate(['boolean'])] public bool $deploymentFailureSlackNotifications = true; #[Validate(['boolean'])] public bool $statusChangeSlackNotifications = false; #[Validate(['boolean'])] public bool $backupSuccessSlackNotifications = false; #[Validate(['boolean'])] public bool $backupFailureSlackNotifications = true; #[Validate(['boolean'])] public bool $scheduledTaskSuccessSlackNotifications = false; #[Validate(['boolean'])] public bool $scheduledTaskFailureSlackNotifications = true; #[Validate(['boolean'])] public bool $dockerCleanupSuccessSlackNotifications = false; #[Validate(['boolean'])] public bool $dockerCleanupFailureSlackNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsageSlackNotifications = true; #[Validate(['boolean'])] public bool $serverReachableSlackNotifications = false; #[Validate(['boolean'])] public bool $serverUnreachableSlackNotifications = true; #[Validate(['boolean'])] public bool $serverPatchSlackNotifications = false; #[Validate(['boolean'])] public bool $traefikOutdatedSlackNotifications = true; public function mount() { try { $this->team = auth()->user()->currentTeam(); $this->settings = $this->team->slackNotificationSettings; $this->authorize('view', $this->settings); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->authorize('update', $this->settings); $this->settings->slack_enabled = $this->slackEnabled; $this->settings->slack_webhook_url = $this->slackWebhookUrl; $this->settings->deployment_success_slack_notifications = $this->deploymentSuccessSlackNotifications; $this->settings->deployment_failure_slack_notifications = $this->deploymentFailureSlackNotifications; $this->settings->status_change_slack_notifications = $this->statusChangeSlackNotifications; $this->settings->backup_success_slack_notifications = $this->backupSuccessSlackNotifications; $this->settings->backup_failure_slack_notifications = $this->backupFailureSlackNotifications; $this->settings->scheduled_task_success_slack_notifications = $this->scheduledTaskSuccessSlackNotifications; $this->settings->scheduled_task_failure_slack_notifications = $this->scheduledTaskFailureSlackNotifications; $this->settings->docker_cleanup_success_slack_notifications = $this->dockerCleanupSuccessSlackNotifications; $this->settings->docker_cleanup_failure_slack_notifications = $this->dockerCleanupFailureSlackNotifications; $this->settings->server_disk_usage_slack_notifications = $this->serverDiskUsageSlackNotifications; $this->settings->server_reachable_slack_notifications = $this->serverReachableSlackNotifications; $this->settings->server_unreachable_slack_notifications = $this->serverUnreachableSlackNotifications; $this->settings->server_patch_slack_notifications = $this->serverPatchSlackNotifications; $this->settings->traefik_outdated_slack_notifications = $this->traefikOutdatedSlackNotifications; $this->settings->save(); refreshSession(); } else { $this->slackEnabled = $this->settings->slack_enabled; $this->slackWebhookUrl = $this->settings->slack_webhook_url; $this->deploymentSuccessSlackNotifications = $this->settings->deployment_success_slack_notifications; $this->deploymentFailureSlackNotifications = $this->settings->deployment_failure_slack_notifications; $this->statusChangeSlackNotifications = $this->settings->status_change_slack_notifications; $this->backupSuccessSlackNotifications = $this->settings->backup_success_slack_notifications; $this->backupFailureSlackNotifications = $this->settings->backup_failure_slack_notifications; $this->scheduledTaskSuccessSlackNotifications = $this->settings->scheduled_task_success_slack_notifications; $this->scheduledTaskFailureSlackNotifications = $this->settings->scheduled_task_failure_slack_notifications; $this->dockerCleanupSuccessSlackNotifications = $this->settings->docker_cleanup_success_slack_notifications; $this->dockerCleanupFailureSlackNotifications = $this->settings->docker_cleanup_failure_slack_notifications; $this->serverDiskUsageSlackNotifications = $this->settings->server_disk_usage_slack_notifications; $this->serverReachableSlackNotifications = $this->settings->server_reachable_slack_notifications; $this->serverUnreachableSlackNotifications = $this->settings->server_unreachable_slack_notifications; $this->serverPatchSlackNotifications = $this->settings->server_patch_slack_notifications; $this->traefikOutdatedSlackNotifications = $this->settings->traefik_outdated_slack_notifications; } } public function instantSaveSlackEnabled() { try { $this->validate([ 'slackWebhookUrl' => 'required', ], [ 'slackWebhookUrl.required' => 'Slack Webhook URL is required.', ]); $this->saveModel(); } catch (\Throwable $e) { $this->slackEnabled = false; return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function instantSave() { try { $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function submit() { try { $this->resetErrorBag(); $this->syncData(true); $this->saveModel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function saveModel() { $this->syncData(true); refreshSession(); $this->dispatch('success', 'Settings saved.'); } public function sendTestNotification() { try { $this->authorize('sendTest', $this->settings); $this->team->notify(new Test(channel: 'slack')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.notifications.slack'); } } ================================================ FILE: app/Livewire/Notifications/Telegram.php ================================================ '$refresh']; #[Locked] public Team $team; #[Locked] public TelegramNotificationSettings $settings; #[Validate(['boolean'])] public bool $telegramEnabled = false; #[Validate(['nullable', 'string'])] public ?string $telegramToken = null; #[Validate(['nullable', 'string'])] public ?string $telegramChatId = null; #[Validate(['boolean'])] public bool $deploymentSuccessTelegramNotifications = false; #[Validate(['boolean'])] public bool $deploymentFailureTelegramNotifications = true; #[Validate(['boolean'])] public bool $statusChangeTelegramNotifications = false; #[Validate(['boolean'])] public bool $backupSuccessTelegramNotifications = false; #[Validate(['boolean'])] public bool $backupFailureTelegramNotifications = true; #[Validate(['boolean'])] public bool $scheduledTaskSuccessTelegramNotifications = false; #[Validate(['boolean'])] public bool $scheduledTaskFailureTelegramNotifications = true; #[Validate(['boolean'])] public bool $dockerCleanupSuccessTelegramNotifications = false; #[Validate(['boolean'])] public bool $dockerCleanupFailureTelegramNotifications = true; #[Validate(['boolean'])] public bool $serverDiskUsageTelegramNotifications = true; #[Validate(['boolean'])] public bool $serverReachableTelegramNotifications = false; #[Validate(['boolean'])] public bool $serverUnreachableTelegramNotifications = true; #[Validate(['boolean'])] public bool $serverPatchTelegramNotifications = false; #[Validate(['boolean'])] public bool $traefikOutdatedTelegramNotifications = true; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsDeploymentSuccessThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsDeploymentFailureThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsStatusChangeThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsBackupSuccessThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsBackupFailureThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsScheduledTaskSuccessThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsScheduledTaskFailureThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsDockerCleanupSuccessThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsDockerCleanupFailureThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsServerDiskUsageThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsServerReachableThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsServerUnreachableThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsServerPatchThreadId = null; #[Validate(['nullable', 'string'])] public ?string $telegramNotificationsTraefikOutdatedThreadId = null; public function mount() { try { $this->team = auth()->user()->currentTeam(); $this->settings = $this->team->telegramNotificationSettings; $this->authorize('view', $this->settings); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->authorize('update', $this->settings); $this->settings->telegram_enabled = $this->telegramEnabled; $this->settings->telegram_token = $this->telegramToken; $this->settings->telegram_chat_id = $this->telegramChatId; $this->settings->deployment_success_telegram_notifications = $this->deploymentSuccessTelegramNotifications; $this->settings->deployment_failure_telegram_notifications = $this->deploymentFailureTelegramNotifications; $this->settings->status_change_telegram_notifications = $this->statusChangeTelegramNotifications; $this->settings->backup_success_telegram_notifications = $this->backupSuccessTelegramNotifications; $this->settings->backup_failure_telegram_notifications = $this->backupFailureTelegramNotifications; $this->settings->scheduled_task_success_telegram_notifications = $this->scheduledTaskSuccessTelegramNotifications; $this->settings->scheduled_task_failure_telegram_notifications = $this->scheduledTaskFailureTelegramNotifications; $this->settings->docker_cleanup_success_telegram_notifications = $this->dockerCleanupSuccessTelegramNotifications; $this->settings->docker_cleanup_failure_telegram_notifications = $this->dockerCleanupFailureTelegramNotifications; $this->settings->server_disk_usage_telegram_notifications = $this->serverDiskUsageTelegramNotifications; $this->settings->server_reachable_telegram_notifications = $this->serverReachableTelegramNotifications; $this->settings->server_unreachable_telegram_notifications = $this->serverUnreachableTelegramNotifications; $this->settings->server_patch_telegram_notifications = $this->serverPatchTelegramNotifications; $this->settings->traefik_outdated_telegram_notifications = $this->traefikOutdatedTelegramNotifications; $this->settings->telegram_notifications_deployment_success_thread_id = $this->telegramNotificationsDeploymentSuccessThreadId; $this->settings->telegram_notifications_deployment_failure_thread_id = $this->telegramNotificationsDeploymentFailureThreadId; $this->settings->telegram_notifications_status_change_thread_id = $this->telegramNotificationsStatusChangeThreadId; $this->settings->telegram_notifications_backup_success_thread_id = $this->telegramNotificationsBackupSuccessThreadId; $this->settings->telegram_notifications_backup_failure_thread_id = $this->telegramNotificationsBackupFailureThreadId; $this->settings->telegram_notifications_scheduled_task_success_thread_id = $this->telegramNotificationsScheduledTaskSuccessThreadId; $this->settings->telegram_notifications_scheduled_task_failure_thread_id = $this->telegramNotificationsScheduledTaskFailureThreadId; $this->settings->telegram_notifications_docker_cleanup_success_thread_id = $this->telegramNotificationsDockerCleanupSuccessThreadId; $this->settings->telegram_notifications_docker_cleanup_failure_thread_id = $this->telegramNotificationsDockerCleanupFailureThreadId; $this->settings->telegram_notifications_server_disk_usage_thread_id = $this->telegramNotificationsServerDiskUsageThreadId; $this->settings->telegram_notifications_server_reachable_thread_id = $this->telegramNotificationsServerReachableThreadId; $this->settings->telegram_notifications_server_unreachable_thread_id = $this->telegramNotificationsServerUnreachableThreadId; $this->settings->telegram_notifications_server_patch_thread_id = $this->telegramNotificationsServerPatchThreadId; $this->settings->telegram_notifications_traefik_outdated_thread_id = $this->telegramNotificationsTraefikOutdatedThreadId; $this->settings->save(); } else { $this->telegramEnabled = $this->settings->telegram_enabled; $this->telegramToken = $this->settings->telegram_token; $this->telegramChatId = $this->settings->telegram_chat_id; $this->deploymentSuccessTelegramNotifications = $this->settings->deployment_success_telegram_notifications; $this->deploymentFailureTelegramNotifications = $this->settings->deployment_failure_telegram_notifications; $this->statusChangeTelegramNotifications = $this->settings->status_change_telegram_notifications; $this->backupSuccessTelegramNotifications = $this->settings->backup_success_telegram_notifications; $this->backupFailureTelegramNotifications = $this->settings->backup_failure_telegram_notifications; $this->scheduledTaskSuccessTelegramNotifications = $this->settings->scheduled_task_success_telegram_notifications; $this->scheduledTaskFailureTelegramNotifications = $this->settings->scheduled_task_failure_telegram_notifications; $this->dockerCleanupSuccessTelegramNotifications = $this->settings->docker_cleanup_success_telegram_notifications; $this->dockerCleanupFailureTelegramNotifications = $this->settings->docker_cleanup_failure_telegram_notifications; $this->serverDiskUsageTelegramNotifications = $this->settings->server_disk_usage_telegram_notifications; $this->serverReachableTelegramNotifications = $this->settings->server_reachable_telegram_notifications; $this->serverUnreachableTelegramNotifications = $this->settings->server_unreachable_telegram_notifications; $this->serverPatchTelegramNotifications = $this->settings->server_patch_telegram_notifications; $this->traefikOutdatedTelegramNotifications = $this->settings->traefik_outdated_telegram_notifications; $this->telegramNotificationsDeploymentSuccessThreadId = $this->settings->telegram_notifications_deployment_success_thread_id; $this->telegramNotificationsDeploymentFailureThreadId = $this->settings->telegram_notifications_deployment_failure_thread_id; $this->telegramNotificationsStatusChangeThreadId = $this->settings->telegram_notifications_status_change_thread_id; $this->telegramNotificationsBackupSuccessThreadId = $this->settings->telegram_notifications_backup_success_thread_id; $this->telegramNotificationsBackupFailureThreadId = $this->settings->telegram_notifications_backup_failure_thread_id; $this->telegramNotificationsScheduledTaskSuccessThreadId = $this->settings->telegram_notifications_scheduled_task_success_thread_id; $this->telegramNotificationsScheduledTaskFailureThreadId = $this->settings->telegram_notifications_scheduled_task_failure_thread_id; $this->telegramNotificationsDockerCleanupSuccessThreadId = $this->settings->telegram_notifications_docker_cleanup_success_thread_id; $this->telegramNotificationsDockerCleanupFailureThreadId = $this->settings->telegram_notifications_docker_cleanup_failure_thread_id; $this->telegramNotificationsServerDiskUsageThreadId = $this->settings->telegram_notifications_server_disk_usage_thread_id; $this->telegramNotificationsServerReachableThreadId = $this->settings->telegram_notifications_server_reachable_thread_id; $this->telegramNotificationsServerUnreachableThreadId = $this->settings->telegram_notifications_server_unreachable_thread_id; $this->telegramNotificationsServerPatchThreadId = $this->settings->telegram_notifications_server_patch_thread_id; $this->telegramNotificationsTraefikOutdatedThreadId = $this->settings->telegram_notifications_traefik_outdated_thread_id; } } public function instantSave() { try { $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function submit() { try { $this->resetErrorBag(); $this->syncData(true); $this->saveModel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSaveTelegramEnabled() { try { $this->validate([ 'telegramToken' => 'required', 'telegramChatId' => 'required', ], [ 'telegramToken.required' => 'Telegram Token is required.', 'telegramChatId.required' => 'Telegram Chat ID is required.', ]); $this->saveModel(); } catch (\Throwable $e) { $this->telegramEnabled = false; return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function saveModel() { $this->syncData(true); refreshSession(); $this->dispatch('success', 'Settings saved.'); } public function sendTestNotification() { try { $this->authorize('sendTest', $this->settings); $this->team->notify(new Test(channel: 'telegram')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.notifications.telegram'); } } ================================================ FILE: app/Livewire/Notifications/Webhook.php ================================================ team = auth()->user()->currentTeam(); $this->settings = $this->team->webhookNotificationSettings; $this->authorize('view', $this->settings); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->authorize('update', $this->settings); $this->settings->webhook_enabled = $this->webhookEnabled; $this->settings->webhook_url = $this->webhookUrl; $this->settings->deployment_success_webhook_notifications = $this->deploymentSuccessWebhookNotifications; $this->settings->deployment_failure_webhook_notifications = $this->deploymentFailureWebhookNotifications; $this->settings->status_change_webhook_notifications = $this->statusChangeWebhookNotifications; $this->settings->backup_success_webhook_notifications = $this->backupSuccessWebhookNotifications; $this->settings->backup_failure_webhook_notifications = $this->backupFailureWebhookNotifications; $this->settings->scheduled_task_success_webhook_notifications = $this->scheduledTaskSuccessWebhookNotifications; $this->settings->scheduled_task_failure_webhook_notifications = $this->scheduledTaskFailureWebhookNotifications; $this->settings->docker_cleanup_success_webhook_notifications = $this->dockerCleanupSuccessWebhookNotifications; $this->settings->docker_cleanup_failure_webhook_notifications = $this->dockerCleanupFailureWebhookNotifications; $this->settings->server_disk_usage_webhook_notifications = $this->serverDiskUsageWebhookNotifications; $this->settings->server_reachable_webhook_notifications = $this->serverReachableWebhookNotifications; $this->settings->server_unreachable_webhook_notifications = $this->serverUnreachableWebhookNotifications; $this->settings->server_patch_webhook_notifications = $this->serverPatchWebhookNotifications; $this->settings->traefik_outdated_webhook_notifications = $this->traefikOutdatedWebhookNotifications; $this->settings->save(); refreshSession(); } else { $this->webhookEnabled = $this->settings->webhook_enabled; $this->webhookUrl = $this->settings->webhook_url; $this->deploymentSuccessWebhookNotifications = $this->settings->deployment_success_webhook_notifications; $this->deploymentFailureWebhookNotifications = $this->settings->deployment_failure_webhook_notifications; $this->statusChangeWebhookNotifications = $this->settings->status_change_webhook_notifications; $this->backupSuccessWebhookNotifications = $this->settings->backup_success_webhook_notifications; $this->backupFailureWebhookNotifications = $this->settings->backup_failure_webhook_notifications; $this->scheduledTaskSuccessWebhookNotifications = $this->settings->scheduled_task_success_webhook_notifications; $this->scheduledTaskFailureWebhookNotifications = $this->settings->scheduled_task_failure_webhook_notifications; $this->dockerCleanupSuccessWebhookNotifications = $this->settings->docker_cleanup_success_webhook_notifications; $this->dockerCleanupFailureWebhookNotifications = $this->settings->docker_cleanup_failure_webhook_notifications; $this->serverDiskUsageWebhookNotifications = $this->settings->server_disk_usage_webhook_notifications; $this->serverReachableWebhookNotifications = $this->settings->server_reachable_webhook_notifications; $this->serverUnreachableWebhookNotifications = $this->settings->server_unreachable_webhook_notifications; $this->serverPatchWebhookNotifications = $this->settings->server_patch_webhook_notifications; $this->traefikOutdatedWebhookNotifications = $this->settings->traefik_outdated_webhook_notifications; } } public function instantSaveWebhookEnabled() { try { $original = $this->webhookEnabled; $this->validate([ 'webhookUrl' => 'required', ], [ 'webhookUrl.required' => 'Webhook URL is required.', ]); $this->saveModel(); } catch (\Throwable $e) { $this->webhookEnabled = $original; return handleError($e, $this); } } public function instantSave() { try { $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->resetErrorBag(); $this->syncData(true); $this->saveModel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function saveModel() { $this->syncData(true); refreshSession(); if (isDev()) { ray('Webhook settings saved', [ 'webhook_enabled' => $this->settings->webhook_enabled, 'webhook_url' => $this->settings->webhook_url, ]); } $this->dispatch('success', 'Settings saved.'); } public function sendTestNotification() { try { $this->authorize('sendTest', $this->settings); if (isDev()) { ray('Sending test webhook notification', [ 'team_id' => $this->team->id, 'webhook_url' => $this->settings->webhook_url, ]); } $this->team->notify(new Test(channel: 'webhook')); $this->dispatch('success', 'Test notification sent.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.notifications.webhook'); } } ================================================ FILE: app/Livewire/Profile/Index.php ================================================ userId = Auth::id(); $this->name = Auth::user()->name; $this->email = Auth::user()->email; // Check if there's a pending email change if (Auth::user()->hasEmailChangeRequest()) { $this->new_email = Auth::user()->pending_email; $this->show_verification = true; } } public function submit() { try { $this->validate([ 'name' => 'required', ]); Auth::user()->update([ 'name' => $this->name, ]); $this->dispatch('success', 'Profile updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function requestEmailChange() { try { // For self-hosted, check if email is enabled if (! isCloud()) { $settings = instanceSettings(); if (! $settings->smtp_enabled && ! $settings->resend_enabled) { $this->dispatch('error', 'Email functionality is not configured. Please contact your administrator.'); return; } } $this->validate([ 'new_email' => ['required', 'email', 'unique:users,email'], ]); $this->new_email = strtolower($this->new_email); // Skip rate limiting in development mode if (! isDev()) { // Rate limit by current user's email (1 request per 2 minutes) $userEmailKey = 'email-change:user:'.Auth::id(); if (! RateLimiter::attempt($userEmailKey, 1, function () {}, 120)) { $seconds = RateLimiter::availableIn($userEmailKey); $this->dispatch('error', 'Too many requests. Please wait '.$seconds.' seconds before trying again.'); return; } // Rate limit by new email address (3 requests per hour per email) $newEmailKey = 'email-change:email:'.md5($this->new_email); if (! RateLimiter::attempt($newEmailKey, 3, function () {}, 3600)) { $this->dispatch('error', 'This email address has received too many verification requests. Please try again later.'); return; } // Additional rate limit by IP address (5 requests per hour) $ipKey = 'email-change:ip:'.request()->ip(); if (! RateLimiter::attempt($ipKey, 5, function () {}, 3600)) { $this->dispatch('error', 'Too many requests from your IP address. Please try again later.'); return; } } Auth::user()->requestEmailChange($this->new_email); $this->show_email_change = false; $this->show_verification = true; $this->dispatch('success', 'Verification code sent to '.$this->new_email); } catch (\Throwable $e) { return handleError($e, $this); } } public function verifyEmailChange() { try { $this->validate([ 'email_verification_code' => ['required', 'string', 'size:6'], ]); // Skip rate limiting in development mode if (! isDev()) { // Rate limit verification attempts (5 attempts per 10 minutes) $verifyKey = 'email-verify:user:'.Auth::id(); if (! RateLimiter::attempt($verifyKey, 5, function () {}, 600)) { $seconds = RateLimiter::availableIn($verifyKey); $minutes = ceil($seconds / 60); $this->dispatch('error', 'Too many verification attempts. Please wait '.$minutes.' minutes before trying again.'); // If too many failed attempts, clear the email change request for security if (RateLimiter::attempts($verifyKey) >= 10) { Auth::user()->clearEmailChangeRequest(); $this->new_email = ''; $this->email_verification_code = ''; $this->show_verification = false; $this->dispatch('error', 'Email change request cancelled due to too many failed attempts. Please start over.'); } return; } } if (! Auth::user()->isEmailChangeCodeValid($this->email_verification_code)) { $this->dispatch('error', 'Invalid or expired verification code.'); return; } if (Auth::user()->confirmEmailChange($this->email_verification_code)) { // Clear rate limiters on successful verification (only in production) if (! isDev()) { $verifyKey = 'email-verify:user:'.Auth::id(); RateLimiter::clear($verifyKey); } $this->email = Auth::user()->email; $this->new_email = ''; $this->email_verification_code = ''; $this->show_verification = false; $this->dispatch('success', 'Email address updated successfully.'); } else { $this->dispatch('error', 'Failed to update email address.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function resendVerificationCode() { try { // Check if there's a pending request if (! Auth::user()->hasEmailChangeRequest()) { $this->dispatch('error', 'No pending email change request.'); return; } // Check if enough time has passed (at least half of the expiry time) $expiryMinutes = config('constants.email_change.verification_code_expiry_minutes', 10); $halfExpiryMinutes = $expiryMinutes / 2; $codeExpiry = Auth::user()->email_change_code_expires_at; $timeSinceCreated = $codeExpiry->subMinutes($expiryMinutes)->diffInMinutes(now()); if ($timeSinceCreated < $halfExpiryMinutes) { $minutesToWait = ceil($halfExpiryMinutes - $timeSinceCreated); $this->dispatch('error', 'Please wait '.$minutesToWait.' more minutes before requesting a new code.'); return; } $pendingEmail = Auth::user()->pending_email; // Skip rate limiting in development mode if (! isDev()) { // Rate limit by email address $newEmailKey = 'email-change:email:'.md5(strtolower($pendingEmail)); if (! RateLimiter::attempt($newEmailKey, 3, function () {}, 3600)) { $this->dispatch('error', 'This email address has received too many verification requests. Please try again later.'); return; } } // Generate and send new code Auth::user()->requestEmailChange($pendingEmail); $this->dispatch('success', 'New verification code sent to '.$pendingEmail); } catch (\Throwable $e) { return handleError($e, $this); } } public function cancelEmailChange() { Auth::user()->clearEmailChangeRequest(); $this->new_email = ''; $this->email_verification_code = ''; $this->show_email_change = false; $this->show_verification = false; $this->dispatch('success', 'Email change request cancelled.'); } public function showEmailChangeForm() { $this->show_email_change = true; $this->new_email = ''; } public function resetPassword() { try { $this->validate([ 'current_password' => ['required'], 'new_password' => ['required', Password::defaults(), 'confirmed'], ]); if (! Hash::check($this->current_password, auth()->user()->password)) { $this->dispatch('error', 'Current password is incorrect.'); return; } if ($this->new_password !== $this->new_password_confirmation) { $this->dispatch('error', 'The two new passwords does not match.'); return; } auth()->user()->update([ 'password' => Hash::make($this->new_password), ]); $this->dispatch('success', 'Password updated.'); $this->current_password = ''; $this->new_password = ''; $this->new_password_confirmation = ''; $this->dispatch('reloadWindow'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.profile.index'); } } ================================================ FILE: app/Livewire/Project/AddEmpty.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), ]; } protected function messages(): array { return ValidationPatterns::combinedMessages(); } public function submit() { try { $this->validate(); $project = Project::create([ 'name' => $this->name, 'description' => $this->description, 'team_id' => currentTeam()->id, 'uuid' => (string) new Cuid2, ]); $productionEnvironment = $project->environments()->where('name', 'production')->first(); return redirect()->route('project.resource.index', [ 'project_uuid' => $project->uuid, 'environment_uuid' => $productionEnvironment->uuid, ]); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Application/Advanced.php ================================================ syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->application->settings->is_force_https_enabled = $this->isForceHttpsEnabled; $this->application->settings->is_git_submodules_enabled = $this->isGitSubmodulesEnabled; $this->application->settings->is_git_lfs_enabled = $this->isGitLfsEnabled; $this->application->settings->is_git_shallow_clone_enabled = $this->isGitShallowCloneEnabled; $this->application->settings->is_preview_deployments_enabled = $this->isPreviewDeploymentsEnabled; $this->application->settings->is_pr_deployments_public_enabled = $this->isPrDeploymentsPublicEnabled; $this->application->settings->is_auto_deploy_enabled = $this->isAutoDeployEnabled; $this->application->settings->is_log_drain_enabled = $this->isLogDrainEnabled; $this->application->settings->is_gpu_enabled = $this->isGpuEnabled; $this->application->settings->gpu_driver = $this->gpuDriver; $this->application->settings->gpu_count = $this->gpuCount; $this->application->settings->gpu_device_ids = $this->gpuDeviceIds; $this->application->settings->gpu_options = $this->gpuOptions; $this->application->settings->is_build_server_enabled = $this->isBuildServerEnabled; $this->application->settings->is_consistent_container_name_enabled = $this->isConsistentContainerNameEnabled; $this->application->settings->custom_internal_name = $this->customInternalName; $this->application->settings->is_gzip_enabled = $this->isGzipEnabled; $this->application->settings->is_stripprefix_enabled = $this->isStripprefixEnabled; $this->application->settings->is_raw_compose_deployment_enabled = $this->isRawComposeDeploymentEnabled; $this->application->settings->connect_to_docker_network = $this->isConnectToDockerNetworkEnabled; $this->application->settings->disable_build_cache = $this->disableBuildCache; $this->application->settings->inject_build_args_to_dockerfile = $this->injectBuildArgsToDockerfile; $this->application->settings->include_source_commit_in_build = $this->includeSourceCommitInBuild; $this->application->settings->save(); } else { $this->isForceHttpsEnabled = $this->application->isForceHttpsEnabled(); $this->isGzipEnabled = $this->application->isGzipEnabled(); $this->isStripprefixEnabled = $this->application->isStripprefixEnabled(); $this->isLogDrainEnabled = $this->application->isLogDrainEnabled(); $this->isGitSubmodulesEnabled = $this->application->settings->is_git_submodules_enabled; $this->isGitLfsEnabled = $this->application->settings->is_git_lfs_enabled; $this->isGitShallowCloneEnabled = $this->application->settings->is_git_shallow_clone_enabled ?? false; $this->isPreviewDeploymentsEnabled = $this->application->settings->is_preview_deployments_enabled; $this->isPrDeploymentsPublicEnabled = $this->application->settings->is_pr_deployments_public_enabled ?? false; $this->isAutoDeployEnabled = $this->application->settings->is_auto_deploy_enabled; $this->isGpuEnabled = $this->application->settings->is_gpu_enabled; $this->gpuDriver = $this->application->settings->gpu_driver; $this->gpuCount = $this->application->settings->gpu_count; $this->gpuDeviceIds = $this->application->settings->gpu_device_ids; $this->gpuOptions = $this->application->settings->gpu_options; $this->isBuildServerEnabled = $this->application->settings->is_build_server_enabled; $this->isConsistentContainerNameEnabled = $this->application->settings->is_consistent_container_name_enabled; $this->customInternalName = $this->application->settings->custom_internal_name; $this->isRawComposeDeploymentEnabled = $this->application->settings->is_raw_compose_deployment_enabled; $this->isConnectToDockerNetworkEnabled = $this->application->settings->connect_to_docker_network; $this->disableBuildCache = $this->application->settings->disable_build_cache; $this->injectBuildArgsToDockerfile = $this->application->settings->inject_build_args_to_dockerfile ?? true; $this->includeSourceCommitInBuild = $this->application->settings->include_source_commit_in_build ?? false; } } private function resetDefaultLabels() { if ($this->application->settings->is_container_label_readonly_enabled === false) { return; } $customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n"); $this->application->custom_labels = base64_encode($customLabels); $this->application->save(); } public function instantSave() { try { $this->authorize('update', $this->application); $reset = false; if ($this->isLogDrainEnabled) { if (! $this->application->destination->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->syncData(true); $this->dispatch('error', 'Log drain is not enabled on this server.'); return; } } if ($this->application->isForceHttpsEnabled() !== $this->isForceHttpsEnabled || $this->application->isGzipEnabled() !== $this->isGzipEnabled || $this->application->isStripprefixEnabled() !== $this->isStripprefixEnabled ) { $reset = true; } if ($this->application->settings->is_raw_compose_deployment_enabled) { $this->application->oldRawParser(); } else { $this->application->parse(); } $this->syncData(true); if ($reset) { $this->resetDefaultLabels(); } $this->dispatch('success', 'Settings saved.'); $this->dispatch('configurationChanged'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->application); if ($this->gpuCount && $this->gpuDeviceIds) { $this->dispatch('error', 'You cannot set both GPU count and GPU device IDs.'); $this->gpuCount = null; $this->gpuDeviceIds = null; $this->syncData(true); return; } $this->syncData(true); $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function saveCustomName() { try { $this->authorize('update', $this->application); if (str($this->customInternalName)->isNotEmpty()) { $this->customInternalName = str($this->customInternalName)->slug()->value(); } else { $this->customInternalName = null; } if (is_null($this->customInternalName)) { $this->syncData(true); $this->dispatch('success', 'Custom name saved.'); return; } $customInternalName = $this->customInternalName; $server = $this->application->destination->server; $allApplications = $server->applications(); $foundSameInternalName = $allApplications->filter(function ($application) { return $application->id !== $this->application->id && $application->settings->custom_internal_name === $this->customInternalName; }); if ($foundSameInternalName->isNotEmpty()) { $this->dispatch('error', 'This custom container name is already in use by another application on this server.'); $this->customInternalName = $customInternalName; $this->syncData(true); return; } $this->syncData(true); $this->dispatch('success', 'Custom name saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.application.advanced'); } } ================================================ FILE: app/Livewire/Project/Application/Configuration.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceChecked" => '$refresh', "echo-private:team.{$teamId},ServiceStatusChanged" => '$refresh', 'buildPackUpdated' => '$refresh', 'refresh' => '$refresh', ]; } public function mount() { $this->currentRoute = request()->route()->getName(); $project = currentTeam() ->projects() ->select('id', 'uuid', 'team_id') ->where('uuid', request()->route('project_uuid')) ->firstOrFail(); $environment = $project->environments() ->select('id', 'uuid', 'name', 'project_id') ->where('uuid', request()->route('environment_uuid')) ->firstOrFail(); $application = $environment->applications() ->with(['destination']) ->where('uuid', request()->route('application_uuid')) ->firstOrFail(); $this->project = $project; $this->environment = $environment; $this->application = $application; if ($this->application->build_pack === 'dockercompose' && $this->currentRoute === 'project.application.healthcheck') { return redirect()->route('project.application.configuration', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]); } } public function render() { return view('livewire.project.application.configuration'); } } ================================================ FILE: app/Livewire/Project/Application/Deployment/Index.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceChecked" => '$refresh', ]; } public function mount() { $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); if (! $project) { return redirect()->route('dashboard'); } $environment = $project->load(['environments'])->environments->where('uuid', request()->route('environment_uuid'))->first()->load(['applications']); if (! $environment) { return redirect()->route('dashboard'); } $application = $environment->applications->where('uuid', request()->route('application_uuid'))->first(); if (! $application) { return redirect()->route('dashboard'); } // Validate pull request ID from URL parameters if ($this->pull_request_id !== null && $this->pull_request_id !== '') { if (! is_numeric($this->pull_request_id) || (float) $this->pull_request_id <= 0 || (float) $this->pull_request_id != (int) $this->pull_request_id) { $this->pull_request_id = null; $this->dispatch('error', 'Invalid Pull Request ID in URL. Filter cleared.'); } else { // Ensure it's stored as a string representation of a positive integer $this->pull_request_id = (string) (int) $this->pull_request_id; } } ['deployments' => $deployments, 'count' => $count] = $application->deployments(0, $this->defaultTake, $this->pull_request_id); $this->application = $application; $this->deployments = $deployments; $this->deployments_count = $count; $this->current_url = url()->current(); $this->updateCurrentPage(); $this->showMore(); } private function showMore() { if ($this->deployments->count() !== 0) { $this->showNext = true; if ($this->deployments->count() < $this->defaultTake) { $this->showNext = false; } return; } } public function reloadDeployments() { $this->loadDeployments(); } public function previousPage(?int $take = null) { if ($take) { $this->skip = $this->skip - $take; } $this->skip = $this->skip - $this->defaultTake; if ($this->skip < 0) { $this->showPrev = false; $this->skip = 0; } $this->updateCurrentPage(); $this->loadDeployments(); } public function nextPage(?int $take = null) { if ($take) { $this->skip = $this->skip + $take; } $this->showPrev = true; $this->updateCurrentPage(); $this->loadDeployments(); } public function loadDeployments() { ['deployments' => $deployments, 'count' => $count] = $this->application->deployments($this->skip, $this->defaultTake, $this->pull_request_id); $this->deployments = $deployments; $this->deployments_count = $count; $this->showMore(); } public function updatedPullRequestId($value) { // Sanitize and validate the pull request ID if ($value !== null && $value !== '') { // Check if it's numeric and positive if (! is_numeric($value) || (float) $value <= 0 || (float) $value != (int) $value) { $this->pull_request_id = null; $this->dispatch('error', 'Invalid Pull Request ID. Please enter a valid positive number.'); return; } // Ensure it's stored as a string representation of a positive integer $this->pull_request_id = (string) (int) $value; } else { $this->pull_request_id = null; } // Reset pagination when filter changes $this->skip = 0; $this->showPrev = false; $this->updateCurrentPage(); $this->loadDeployments(); } public function clearFilter() { $this->pull_request_id = null; $this->skip = 0; $this->showPrev = false; $this->updateCurrentPage(); $this->loadDeployments(); } private function updateCurrentPage() { $this->currentPage = intval($this->skip / $this->defaultTake) + 1; } public function render() { return view('livewire.project.application.deployment.index'); } } ================================================ FILE: app/Livewire/Project/Application/Deployment/Show.php ================================================ route('deployment_uuid'); $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); if (! $project) { return redirect()->route('dashboard'); } $environment = $project->load(['environments'])->environments->where('uuid', request()->route('environment_uuid'))->first()->load(['applications']); if (! $environment) { return redirect()->route('dashboard'); } $application = $environment->applications->where('uuid', request()->route('application_uuid'))->first(); if (! $application) { return redirect()->route('dashboard'); } $application_deployment_queue = ApplicationDeploymentQueue::where('deployment_uuid', $deploymentUuid)->first(); if (! $application_deployment_queue) { return redirect()->route('project.application.deployment.index', [ 'project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid, ]); } $this->application = $application; $this->application_deployment_queue = $application_deployment_queue; $this->horizon_job_status = $this->application_deployment_queue->getHorizonJobStatus(); $this->deployment_uuid = $deploymentUuid; $this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->isKeepAliveOn(); } public function toggleDebug() { try { $this->authorize('update', $this->application); $this->application->settings->is_debug_enabled = ! $this->application->settings->is_debug_enabled; $this->application->settings->save(); $this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->application_deployment_queue->refresh(); } catch (\Throwable $e) { return handleError($e, $this); } } public function refreshQueue() { $this->application_deployment_queue->refresh(); } private function isKeepAliveOn() { if (data_get($this->application_deployment_queue, 'status') === 'finished' || data_get($this->application_deployment_queue, 'status') === 'failed') { $this->isKeepAliveOn = false; } else { $this->isKeepAliveOn = true; } } public function polling() { $this->application_deployment_queue->refresh(); $this->horizon_job_status = $this->application_deployment_queue->getHorizonJobStatus(); $this->isKeepAliveOn(); // Dispatch event when deployment finishes to stop auto-scroll (only once) if (! $this->isKeepAliveOn && ! $this->deploymentFinishedDispatched) { $this->deploymentFinishedDispatched = true; $this->dispatch('deploymentFinished'); } } public function getLogLinesProperty() { return decode_remote_command_output($this->application_deployment_queue); } public function copyLogs(): string { $logs = decode_remote_command_output($this->application_deployment_queue) ->map(function ($line) { return $line['timestamp'].' '. (isset($line['command']) && $line['command'] ? '[CMD]: ' : ''). trim($line['line']); }) ->join("\n"); return sanitizeLogsForExport($logs); } public function downloadAllLogs(): string { $logs = decode_remote_command_output($this->application_deployment_queue, includeAll: true) ->map(function ($line) { $prefix = ''; if ($line['hidden']) { $prefix = '[DEBUG] '; } if (isset($line['command']) && $line['command']) { $prefix .= '[CMD]: '; } return $line['timestamp'].' '.$prefix.trim($line['line']); }) ->join("\n"); return sanitizeLogsForExport($logs); } public function render() { return view('livewire.project.application.deployment.show'); } } ================================================ FILE: app/Livewire/Project/Application/DeploymentNavbar.php ================================================ application = Application::ownedByCurrentTeam()->find($this->application_deployment_queue->application_id); $this->server = $this->application->destination->server; $this->is_debug_enabled = $this->application->settings->is_debug_enabled; } public function deploymentFinished() { $this->application_deployment_queue->refresh(); } public function show_debug() { $this->application->settings->is_debug_enabled = ! $this->application->settings->is_debug_enabled; $this->application->settings->save(); $this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->dispatch('refreshQueue'); } public function force_start() { try { force_start_deployment($this->application_deployment_queue); } catch (\Throwable $e) { return handleError($e, $this); } } public function copyLogsToClipboard(): string { $logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR); if (! $logs) { return ''; } $markdown = "# Deployment Logs\n\n"; $markdown .= "```\n"; foreach ($logs as $log) { if (isset($log['output'])) { $markdown .= $log['output']."\n"; } } $markdown .= "```\n"; return $markdown; } public function cancel() { $deployment_uuid = $this->application_deployment_queue->deployment_uuid; $kill_command = "docker rm -f {$deployment_uuid}"; $build_server_id = $this->application_deployment_queue->build_server_id ?? $this->application->destination->server_id; $server_id = $this->application_deployment_queue->server_id ?? $this->application->destination->server_id; // First, mark the deployment as cancelled to prevent further processing $this->application_deployment_queue->update([ 'status' => ApplicationDeploymentStatus::CANCELLED_BY_USER->value, ]); try { if ($this->application->settings->is_build_server_enabled) { $server = Server::ownedByCurrentTeam()->find($build_server_id); } else { $server = Server::ownedByCurrentTeam()->find($server_id); } // Add cancellation log entry if ($this->application_deployment_queue->logs) { $previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR); $new_log_entry = [ 'command' => $kill_command, 'output' => 'Deployment cancelled by user.', 'type' => 'stderr', 'order' => count($previous_logs) + 1, 'timestamp' => Carbon::now('UTC'), 'hidden' => false, ]; $previous_logs[] = $new_log_entry; $this->application_deployment_queue->update([ 'logs' => json_encode($previous_logs, flags: JSON_THROW_ON_ERROR), ]); } // Try to stop the helper container if it exists // Check if container exists first $checkCommand = "docker ps -a --filter name={$deployment_uuid} --format '{{.Names}}'"; $containerExists = instant_remote_process([$checkCommand], $server); if ($containerExists && str($containerExists)->trim()->isNotEmpty()) { // Container exists, kill it instant_remote_process([$kill_command], $server); } else { // Container hasn't started yet $this->application_deployment_queue->addLogEntry('Helper container not yet started. Deployment will be cancelled when job checks status.'); } // Also try to kill any running process if we have a process ID if ($this->application_deployment_queue->current_process_id) { try { $processKillCommand = "kill -9 {$this->application_deployment_queue->current_process_id}"; instant_remote_process([$processKillCommand], $server); } catch (\Throwable $e) { // Process might already be gone, that's ok } } } catch (\Throwable $e) { // Still mark as cancelled even if cleanup fails return handleError($e, $this); } finally { $this->application_deployment_queue->update([ 'current_process_id' => null, ]); next_after_cancel($server); } } } ================================================ FILE: app/Livewire/Project/Application/General.php ================================================ '$refresh', 'confirmDomainUsage', ]; protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'fqdn' => 'nullable', 'gitRepository' => 'required', 'gitBranch' => 'required', 'gitCommitSha' => ['nullable', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9._\-\/]*$/'], 'installCommand' => 'nullable', 'buildCommand' => 'nullable', 'startCommand' => 'nullable', 'buildPack' => 'required', 'staticImage' => 'required', 'baseDirectory' => 'required', 'publishDirectory' => 'nullable', 'portsExposes' => 'required', 'portsMappings' => 'nullable', 'customNetworkAliases' => 'nullable', 'dockerfile' => 'nullable', 'dockerRegistryImageName' => 'nullable', 'dockerRegistryImageTag' => 'nullable', 'dockerfileLocation' => ['nullable', 'regex:'.ValidationPatterns::FILE_PATH_PATTERN], 'dockerComposeLocation' => ['nullable', 'regex:'.ValidationPatterns::FILE_PATH_PATTERN], 'dockerCompose' => 'nullable', 'dockerComposeRaw' => 'nullable', 'dockerfileTargetBuild' => 'nullable', 'dockerComposeCustomStartCommand' => 'nullable', 'dockerComposeCustomBuildCommand' => 'nullable', 'customLabels' => 'nullable', 'customDockerRunOptions' => 'nullable', 'preDeploymentCommand' => 'nullable', 'preDeploymentCommandContainer' => 'nullable', 'postDeploymentCommand' => 'nullable', 'postDeploymentCommandContainer' => 'nullable', 'customNginxConfiguration' => 'nullable', 'isStatic' => 'boolean|required', 'isSpa' => 'boolean|required', 'isBuildServerEnabled' => 'boolean|required', 'isContainerLabelEscapeEnabled' => 'boolean|required', 'isContainerLabelReadonlyEnabled' => 'boolean|required', 'isPreserveRepositoryEnabled' => 'boolean|required', 'isHttpBasicAuthEnabled' => 'boolean|required', 'httpBasicAuthUsername' => 'string|nullable', 'httpBasicAuthPassword' => 'string|nullable', 'watchPaths' => 'nullable', 'redirect' => 'string|required', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ ...ValidationPatterns::filePathMessages('dockerfileLocation', 'Dockerfile'), ...ValidationPatterns::filePathMessages('dockerComposeLocation', 'Docker Compose'), 'name.required' => 'The Name field is required.', 'gitRepository.required' => 'The Git Repository field is required.', 'gitBranch.required' => 'The Git Branch field is required.', 'buildPack.required' => 'The Build Pack field is required.', 'staticImage.required' => 'The Static Image field is required.', 'baseDirectory.required' => 'The Base Directory field is required.', 'portsExposes.required' => 'The Exposed Ports field is required.', 'isStatic.required' => 'The Static setting is required.', 'isStatic.boolean' => 'The Static setting must be true or false.', 'isSpa.required' => 'The SPA setting is required.', 'isSpa.boolean' => 'The SPA setting must be true or false.', 'isBuildServerEnabled.required' => 'The Build Server setting is required.', 'isBuildServerEnabled.boolean' => 'The Build Server setting must be true or false.', 'isContainerLabelEscapeEnabled.required' => 'The Container Label Escape setting is required.', 'isContainerLabelEscapeEnabled.boolean' => 'The Container Label Escape setting must be true or false.', 'isContainerLabelReadonlyEnabled.required' => 'The Container Label Readonly setting is required.', 'isContainerLabelReadonlyEnabled.boolean' => 'The Container Label Readonly setting must be true or false.', 'isPreserveRepositoryEnabled.required' => 'The Preserve Repository setting is required.', 'isPreserveRepositoryEnabled.boolean' => 'The Preserve Repository setting must be true or false.', 'isHttpBasicAuthEnabled.required' => 'The HTTP Basic Auth setting is required.', 'isHttpBasicAuthEnabled.boolean' => 'The HTTP Basic Auth setting must be true or false.', 'redirect.required' => 'The Redirect setting is required.', 'redirect.string' => 'The Redirect setting must be a string.', ] ); } protected $validationAttributes = [ 'name' => 'name', 'description' => 'description', 'fqdn' => 'FQDN', 'gitRepository' => 'Git repository', 'gitBranch' => 'Git branch', 'gitCommitSha' => 'Git commit SHA', 'installCommand' => 'Install command', 'buildCommand' => 'Build command', 'startCommand' => 'Start command', 'buildPack' => 'Build pack', 'staticImage' => 'Static image', 'baseDirectory' => 'Base directory', 'publishDirectory' => 'Publish directory', 'portsExposes' => 'Ports exposes', 'portsMappings' => 'Ports mappings', 'dockerfile' => 'Dockerfile', 'dockerRegistryImageName' => 'Docker registry image name', 'dockerRegistryImageTag' => 'Docker registry image tag', 'dockerfileLocation' => 'Dockerfile location', 'dockerComposeLocation' => 'Docker compose location', 'dockerCompose' => 'Docker compose', 'dockerComposeRaw' => 'Docker compose raw', 'customLabels' => 'Custom labels', 'dockerfileTargetBuild' => 'Dockerfile target build', 'customDockerRunOptions' => 'Custom docker run commands', 'customNetworkAliases' => 'Custom docker network aliases', 'dockerComposeCustomStartCommand' => 'Docker compose custom start command', 'dockerComposeCustomBuildCommand' => 'Docker compose custom build command', 'customNginxConfiguration' => 'Custom Nginx configuration', 'isStatic' => 'Is static', 'isSpa' => 'Is SPA', 'isBuildServerEnabled' => 'Is build server enabled', 'isContainerLabelEscapeEnabled' => 'Is container label escape enabled', 'isContainerLabelReadonlyEnabled' => 'Is container label readonly', 'isPreserveRepositoryEnabled' => 'Is preserve repository enabled', 'watchPaths' => 'Watch paths', 'redirect' => 'Redirect', ]; public function mount() { try { $this->parsedServices = $this->application->parse(); if (is_null($this->parsedServices) || empty($this->parsedServices)) { $this->dispatch('error', 'Failed to parse your docker-compose file. Please check the syntax and try again.'); // Still sync data even if parse fails, so form fields are populated $this->syncData(); return; } } catch (\Throwable $e) { $this->dispatch('error', $e->getMessage()); // Still sync data even on error, so form fields are populated $this->syncData(); } if ($this->application->build_pack === 'dockercompose') { // Only update if user has permission try { $this->authorize('update', $this->application); $this->application->fqdn = null; $this->application->settings->save(); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User doesn't have update permission, just continue without saving } } $this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : []; // Convert service names with dots and dashes to use underscores for HTML form binding $sanitizedDomains = []; foreach ($this->parsedServiceDomains as $serviceName => $domain) { $sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString(); $sanitizedDomains[$sanitizedKey] = $domain; } $this->parsedServiceDomains = $sanitizedDomains; $this->customLabels = $this->application->parseContainerLabels(); if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE' && $this->application->settings->is_container_label_readonly_enabled === true) { // Only update custom labels if user has permission try { $this->authorize('update', $this->application); $this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n"); $this->application->custom_labels = base64_encode($this->customLabels); $this->application->save(); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User doesn't have update permission, just use existing labels // $this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n"); } } $this->initialDockerComposeLocation = $this->application->docker_compose_location; if ($this->application->build_pack === 'dockercompose' && ! $this->application->docker_compose_raw) { // Only load compose file if user has update permission try { $this->authorize('update', $this->application); $this->initLoadingCompose = true; $this->dispatch('info', 'Loading docker compose file.'); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User doesn't have update permission, skip loading compose file } } if (str($this->application->status)->startsWith('running') && is_null($this->application->config_hash)) { $this->dispatch('configurationChanged'); } // Sync data from model to properties at the END, after all business logic // This ensures any modifications to $this->application during mount() are reflected in properties $this->syncData(); } public function syncData(bool $toModel = false): void { if ($toModel) { $this->validate(); // Application properties $this->application->name = $this->name; $this->application->description = $this->description; $this->application->fqdn = $this->fqdn; $this->application->git_repository = $this->gitRepository; $this->application->git_branch = $this->gitBranch; $this->application->git_commit_sha = $this->gitCommitSha; $this->application->install_command = $this->installCommand; $this->application->build_command = $this->buildCommand; $this->application->start_command = $this->startCommand; $this->application->build_pack = $this->buildPack; $this->application->static_image = $this->staticImage; $this->application->base_directory = $this->baseDirectory; $this->application->publish_directory = $this->publishDirectory; $this->application->ports_exposes = $this->portsExposes; $this->application->ports_mappings = $this->portsMappings; $this->application->custom_network_aliases = $this->customNetworkAliases; $this->application->dockerfile = $this->dockerfile; $this->application->dockerfile_location = $this->dockerfileLocation; $this->application->dockerfile_target_build = $this->dockerfileTargetBuild; $this->application->docker_registry_image_name = $this->dockerRegistryImageName; $this->application->docker_registry_image_tag = $this->dockerRegistryImageTag; $this->application->docker_compose_location = $this->dockerComposeLocation; $this->application->docker_compose = $this->dockerCompose; $this->application->docker_compose_raw = $this->dockerComposeRaw; $this->application->docker_compose_custom_start_command = $this->dockerComposeCustomStartCommand; $this->application->docker_compose_custom_build_command = $this->dockerComposeCustomBuildCommand; $this->application->custom_labels = is_null($this->customLabels) ? null : base64_encode($this->customLabels); $this->application->custom_docker_run_options = $this->customDockerRunOptions; $this->application->pre_deployment_command = $this->preDeploymentCommand; $this->application->pre_deployment_command_container = $this->preDeploymentCommandContainer; $this->application->post_deployment_command = $this->postDeploymentCommand; $this->application->post_deployment_command_container = $this->postDeploymentCommandContainer; $this->application->custom_nginx_configuration = $this->customNginxConfiguration; $this->application->is_http_basic_auth_enabled = $this->isHttpBasicAuthEnabled; $this->application->http_basic_auth_username = $this->httpBasicAuthUsername; $this->application->http_basic_auth_password = $this->httpBasicAuthPassword; $this->application->watch_paths = $this->watchPaths; $this->application->redirect = $this->redirect; // Application settings properties $this->application->settings->is_static = $this->isStatic; $this->application->settings->is_spa = $this->isSpa; $this->application->settings->is_build_server_enabled = $this->isBuildServerEnabled; $this->application->settings->is_preserve_repository_enabled = $this->isPreserveRepositoryEnabled; $this->application->settings->is_container_label_escape_enabled = $this->isContainerLabelEscapeEnabled; $this->application->settings->is_container_label_readonly_enabled = $this->isContainerLabelReadonlyEnabled; $this->application->settings->save(); } else { // From model to properties $this->name = $this->application->name; $this->description = $this->application->description; $this->fqdn = $this->application->fqdn; $this->gitRepository = $this->application->git_repository; $this->gitBranch = $this->application->git_branch; $this->gitCommitSha = $this->application->git_commit_sha; $this->installCommand = $this->application->install_command; $this->buildCommand = $this->application->build_command; $this->startCommand = $this->application->start_command; $this->buildPack = $this->application->build_pack; $this->staticImage = $this->application->static_image; $this->baseDirectory = $this->application->base_directory; $this->publishDirectory = $this->application->publish_directory; $this->portsExposes = $this->application->ports_exposes; $this->portsMappings = $this->application->ports_mappings; $this->customNetworkAliases = $this->application->custom_network_aliases; $this->dockerfile = $this->application->dockerfile; $this->dockerfileLocation = $this->application->dockerfile_location; $this->dockerfileTargetBuild = $this->application->dockerfile_target_build; $this->dockerRegistryImageName = $this->application->docker_registry_image_name; $this->dockerRegistryImageTag = $this->application->docker_registry_image_tag; $this->dockerComposeLocation = $this->application->docker_compose_location; $this->dockerCompose = $this->application->docker_compose; $this->dockerComposeRaw = $this->application->docker_compose_raw; $this->dockerComposeCustomStartCommand = $this->application->docker_compose_custom_start_command; $this->dockerComposeCustomBuildCommand = $this->application->docker_compose_custom_build_command; $this->customLabels = $this->application->parseContainerLabels(); $this->customDockerRunOptions = $this->application->custom_docker_run_options; $this->preDeploymentCommand = $this->application->pre_deployment_command; $this->preDeploymentCommandContainer = $this->application->pre_deployment_command_container; $this->postDeploymentCommand = $this->application->post_deployment_command; $this->postDeploymentCommandContainer = $this->application->post_deployment_command_container; $this->customNginxConfiguration = $this->application->custom_nginx_configuration; $this->isHttpBasicAuthEnabled = $this->application->is_http_basic_auth_enabled; $this->httpBasicAuthUsername = $this->application->http_basic_auth_username; $this->httpBasicAuthPassword = $this->application->http_basic_auth_password; $this->watchPaths = $this->application->watch_paths; $this->redirect = $this->application->redirect; // Application settings properties $this->isStatic = $this->application->settings->is_static; $this->isSpa = $this->application->settings->is_spa; $this->isBuildServerEnabled = $this->application->settings->is_build_server_enabled; $this->isPreserveRepositoryEnabled = $this->application->settings->is_preserve_repository_enabled; $this->isContainerLabelEscapeEnabled = $this->application->settings->is_container_label_escape_enabled; $this->isContainerLabelReadonlyEnabled = $this->application->settings->is_container_label_readonly_enabled; } } public function instantSave() { try { $this->authorize('update', $this->application); $oldPortsExposes = $this->application->ports_exposes; $oldIsContainerLabelEscapeEnabled = $this->application->settings->is_container_label_escape_enabled; $oldIsPreserveRepositoryEnabled = $this->application->settings->is_preserve_repository_enabled; $oldIsSpa = $this->application->settings->is_spa; $oldIsHttpBasicAuthEnabled = $this->application->is_http_basic_auth_enabled; $this->syncData(toModel: true); if ($oldIsSpa !== $this->isSpa) { $this->generateNginxConfiguration($this->isSpa ? 'spa' : 'static'); } if ($oldIsHttpBasicAuthEnabled !== $this->isHttpBasicAuthEnabled) { $this->application->save(); } $this->dispatch('success', 'Settings saved.'); $this->application->refresh(); $this->syncData(); // If port_exposes changed, reset default labels if ($oldPortsExposes !== $this->portsExposes || $oldIsContainerLabelEscapeEnabled !== $this->isContainerLabelEscapeEnabled) { $this->resetDefaultLabels(false); } if ($oldIsPreserveRepositoryEnabled !== $this->isPreserveRepositoryEnabled) { if ($this->isPreserveRepositoryEnabled === false) { $this->application->fileStorages->each(function ($storage) { $storage->is_based_on_git = $this->isPreserveRepositoryEnabled; $storage->save(); }); } } if ($this->isContainerLabelReadonlyEnabled) { $this->resetDefaultLabels(false); } } catch (\Throwable $e) { return handleError($e, $this); } } public function loadComposeFile($isInit = false, $showToast = true, ?string $restoreBaseDirectory = null, ?string $restoreDockerComposeLocation = null) { try { $this->authorize('update', $this->application); if ($isInit && $this->application->docker_compose_raw) { return; } ['parsedServices' => $this->parsedServices, 'initialDockerComposeLocation' => $this->initialDockerComposeLocation] = $this->application->loadComposeFile($isInit, $restoreBaseDirectory, $restoreDockerComposeLocation); if (is_null($this->parsedServices)) { $showToast && $this->dispatch('error', 'Failed to parse your docker-compose file. Please check the syntax and try again.'); return; } // Refresh parsedServiceDomains to reflect any changes in docker_compose_domains $this->application->refresh(); // Sync the docker_compose_raw from the model to the component property // This ensures the Monaco editor displays the loaded compose file $this->syncData(); $this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : []; // Convert service names with dots and dashes to use underscores for HTML form binding $sanitizedDomains = []; foreach ($this->parsedServiceDomains as $serviceName => $domain) { $sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString(); $sanitizedDomains[$sanitizedKey] = $domain; } $this->parsedServiceDomains = $sanitizedDomains; $showToast && $this->dispatch('success', 'Docker compose file loaded.'); $this->dispatch('compose_loaded'); $this->dispatch('refreshStorages'); $this->dispatch('refreshEnvs'); } catch (\Throwable $e) { // Refresh model to get restored values from Application::loadComposeFile $this->application->refresh(); // Sync restored values back to component properties for UI update $this->syncData(); return handleError($e, $this); } finally { $this->initLoadingCompose = false; } } public function generateDomain(string $serviceName) { try { $this->authorize('update', $this->application); $uuid = new Cuid2; $domain = generateUrl(server: $this->application->destination->server, random: $uuid); $sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString(); $this->parsedServiceDomains[$sanitizedKey]['domain'] = $domain; // Convert back to original service names for storage $originalDomains = []; foreach ($this->parsedServiceDomains as $key => $value) { // Find the original service name by checking parsed services $originalServiceName = $key; if (isset($this->parsedServices['services'])) { foreach ($this->parsedServices['services'] as $originalName => $service) { if (str($originalName)->replace('-', '_')->replace('.', '_')->toString() === $key) { $originalServiceName = $originalName; break; } } } $originalDomains[$originalServiceName] = $value; } $this->application->docker_compose_domains = json_encode($originalDomains); $this->application->save(); $this->dispatch('success', 'Domain generated.'); if ($this->application->build_pack === 'dockercompose') { $this->loadComposeFile(showToast: false); } return $domain; } catch (\Throwable $e) { return handleError($e, $this); } } public function updatedIsStatic($value) { if ($value) { $this->generateNginxConfiguration(); } } public function updatedBuildPack() { // Check if user has permission to update try { $this->authorize('update', $this->application); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User doesn't have permission, revert the change and return $this->application->refresh(); $this->syncData(); return; } // Sync property to model before checking/modifying $this->syncData(toModel: true); if ($this->buildPack !== 'nixpacks') { $this->isStatic = false; $this->application->settings->is_static = false; $this->application->settings->save(); } else { $this->resetDefaultLabels(false); } if ($this->buildPack === 'dockercompose') { // Only update if user has permission try { $this->authorize('update', $this->application); $this->fqdn = null; $this->application->fqdn = null; $this->application->settings->save(); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User doesn't have update permission, just continue without saving } } if ($this->buildPack === 'static') { $this->portsExposes = '80'; $this->application->ports_exposes = '80'; $this->resetDefaultLabels(false); $this->generateNginxConfiguration(); } $this->submit(); $this->dispatch('buildPackUpdated'); } public function getWildcardDomain() { try { $this->authorize('update', $this->application); $server = data_get($this->application, 'destination.server'); if ($server) { $fqdn = generateUrl(server: $server, random: $this->application->uuid); $this->fqdn = $fqdn; $this->syncData(toModel: true); $this->application->save(); $this->application->refresh(); $this->syncData(); $this->resetDefaultLabels(); $this->dispatch('success', 'Wildcard domain generated.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function generateNginxConfiguration($type = 'static') { try { $this->authorize('update', $this->application); $this->customNginxConfiguration = defaultNginxConfiguration($type); $this->syncData(toModel: true); $this->application->save(); $this->application->refresh(); $this->syncData(); $this->dispatch('success', 'Nginx configuration generated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function resetDefaultLabels($manualReset = false) { try { if (! $this->isContainerLabelReadonlyEnabled && ! $manualReset) { return; } $this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n"); $this->application->custom_labels = base64_encode($this->customLabels); $this->application->save(); $this->application->refresh(); $this->syncData(); if ($this->buildPack === 'dockercompose') { $this->loadComposeFile(showToast: false); } $this->dispatch('configurationChanged'); } catch (\Throwable $e) { return handleError($e, $this); } } public function checkFqdns($showToaster = true) { if ($this->fqdn) { $domains = str($this->fqdn)->trim()->explode(','); if ($this->application->additional_servers->count() === 0) { foreach ($domains as $domain) { if (! validateDNSEntry($domain, $this->application->destination->server)) { $showToaster && $this->dispatch('error', 'Validating DNS failed.', "Make sure you have added the DNS records correctly.

$domain->{$this->application->destination->server->ip}

Check this documentation for further help."); } } } // Check for domain conflicts if not forcing save if (! $this->forceSaveDomains) { $result = checkDomainUsage(resource: $this->application); if ($result['hasConflicts']) { $this->domainConflicts = $result['conflicts']; $this->showDomainConflictModal = true; return false; } } else { // Reset the force flag after using it $this->forceSaveDomains = false; } $this->fqdn = $domains->implode(','); $this->application->fqdn = $this->fqdn; $this->resetDefaultLabels(false); } return true; } public function confirmDomainUsage() { $this->forceSaveDomains = true; $this->showDomainConflictModal = false; $this->submit(); } public function setRedirect() { $this->authorize('update', $this->application); try { $has_www = collect($this->application->fqdns)->filter(fn ($fqdn) => str($fqdn)->contains('www.'))->count(); if ($has_www === 0 && $this->application->redirect === 'www') { $this->dispatch('error', 'You want to redirect to www, but you do not have a www domain set.

Please add www to your domain list and as an A DNS record (if applicable).'); return; } $this->application->save(); $this->resetDefaultLabels(); $this->dispatch('success', 'Redirect updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit($showToaster = true) { try { $this->authorize('update', $this->application); $this->resetErrorBag(); $this->validate(); $oldPortsExposes = $this->application->ports_exposes; $oldIsContainerLabelEscapeEnabled = $this->application->settings->is_container_label_escape_enabled; $oldDockerComposeLocation = $this->initialDockerComposeLocation; $oldBaseDirectory = $this->application->base_directory; // Process FQDN with intermediate variable to avoid Collection/string confusion $this->fqdn = str($this->fqdn)->replaceEnd(',', '')->trim()->toString(); $this->fqdn = str($this->fqdn)->replaceStart(',', '')->trim()->toString(); $domains = str($this->fqdn)->trim()->explode(',')->map(function ($domain) { $domain = trim($domain); Url::fromString($domain, ['http', 'https']); return str($domain)->lower(); }); $this->fqdn = $domains->unique()->implode(','); $warning = sslipDomainWarning($this->fqdn); if ($warning) { $this->dispatch('warning', __('warning.sslipdomain')); } $this->syncData(toModel: true); if ($this->application->isDirty('redirect')) { $this->setRedirect(); } if ($this->application->isDirty('dockerfile')) { $this->application->parseHealthcheckFromDockerfile($this->application->dockerfile); } if (! $this->checkFqdns()) { return; // Stop if there are conflicts and user hasn't confirmed } // Normalize paths BEFORE validation if ($this->baseDirectory && $this->baseDirectory !== '/') { $this->baseDirectory = rtrim($this->baseDirectory, '/'); $this->application->base_directory = $this->baseDirectory; } if ($this->publishDirectory && $this->publishDirectory !== '/') { $this->publishDirectory = rtrim($this->publishDirectory, '/'); $this->application->publish_directory = $this->publishDirectory; } // Validate docker compose file path BEFORE saving to database // This prevents invalid paths from being persisted when validation fails if ($this->buildPack === 'dockercompose' && ($oldDockerComposeLocation !== $this->dockerComposeLocation || $oldBaseDirectory !== $this->baseDirectory)) { // Pass original values to loadComposeFile so it can restore them on failure // The finally block in Application::loadComposeFile will save these original // values if validation fails, preventing invalid paths from being persisted $compose_return = $this->loadComposeFile( isInit: false, showToast: false, restoreBaseDirectory: $oldBaseDirectory, restoreDockerComposeLocation: $oldDockerComposeLocation ); if ($compose_return instanceof \Livewire\Features\SupportEvents\Event) { // Validation failed - restore original values to component properties $this->baseDirectory = $oldBaseDirectory; $this->dockerComposeLocation = $oldDockerComposeLocation; // The model was saved by loadComposeFile's finally block with original values // Refresh to sync component with database state $this->application->refresh(); return; } } $this->application->save(); if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE' && ! $this->application->settings->is_container_label_readonly_enabled) { $this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n"); $this->application->custom_labels = base64_encode($this->customLabels); $this->application->save(); } if ($oldPortsExposes !== $this->portsExposes || $oldIsContainerLabelEscapeEnabled !== $this->isContainerLabelEscapeEnabled) { $this->resetDefaultLabels(); } if ($this->buildPack === 'dockerimage') { $this->validate([ 'dockerRegistryImageName' => 'required', ]); } if ($this->customDockerRunOptions) { $this->customDockerRunOptions = str($this->customDockerRunOptions)->trim()->toString(); $this->application->custom_docker_run_options = $this->customDockerRunOptions; } if ($this->dockerfile) { $port = get_port_from_dockerfile($this->dockerfile); if ($port && ! $this->portsExposes) { $this->portsExposes = $port; $this->application->ports_exposes = $port; } } if ($this->buildPack === 'dockercompose') { $this->application->docker_compose_domains = json_encode($this->parsedServiceDomains); if ($this->application->isDirty('docker_compose_domains')) { foreach ($this->parsedServiceDomains as $service) { $domain = data_get($service, 'domain'); if ($domain) { if (! validateDNSEntry($domain, $this->application->destination->server)) { $showToaster && $this->dispatch('error', 'Validating DNS failed.', "Make sure you have added the DNS records correctly.

$domain->{$this->application->destination->server->ip}

Check this documentation for further help."); } } } // Check for domain conflicts if not forcing save if (! $this->forceSaveDomains) { $result = checkDomainUsage(resource: $this->application); if ($result['hasConflicts']) { $this->domainConflicts = $result['conflicts']; $this->showDomainConflictModal = true; return; } } else { // Reset the force flag after using it $this->forceSaveDomains = false; } $this->application->save(); $this->resetDefaultLabels(); } } $this->application->custom_labels = base64_encode($this->customLabels); $this->application->save(); $this->application->refresh(); $this->syncData(); $showToaster && ! $warning && $this->dispatch('success', 'Application settings updated!'); } catch (\Throwable $e) { $this->application->refresh(); $this->syncData(); return handleError($e, $this); } finally { $this->dispatch('configurationChanged'); } } public function downloadConfig() { $config = GenerateConfig::run($this->application, true); $fileName = str($this->application->name)->slug()->append('_config.json'); return response()->streamDownload(function () use ($config) { echo $config; }, $fileName, [ 'Content-Type' => 'application/json', 'Content-Disposition' => 'attachment; filename='.$fileName, ]); } public function getDetectedPortInfoProperty(): ?array { $detectedPort = $this->application->detectPortFromEnvironment(); if (! $detectedPort) { return null; } $portsExposesArray = $this->application->ports_exposes_array; $isMatch = in_array($detectedPort, $portsExposesArray); $isEmpty = empty($portsExposesArray); return [ 'port' => $detectedPort, 'matches' => $isMatch, 'isEmpty' => $isEmpty, ]; } public function getDockerComposeBuildCommandPreviewProperty(): string { if (! $this->dockerComposeCustomBuildCommand) { return ''; } // Normalize baseDirectory to prevent double slashes (e.g., when baseDirectory is '/') $normalizedBase = $this->baseDirectory === '/' ? '' : rtrim($this->baseDirectory, '/'); // Use relative path for clarity in preview (e.g., ./backend/docker-compose.yaml) // Actual deployment uses absolute path: /artifacts/{deployment_uuid}{base_directory}{docker_compose_location} // Build-time env path references ApplicationDeploymentJob::BUILD_TIME_ENV_PATH as source of truth $command = injectDockerComposeFlags( $this->dockerComposeCustomBuildCommand, ".{$normalizedBase}{$this->dockerComposeLocation}", \App\Jobs\ApplicationDeploymentJob::BUILD_TIME_ENV_PATH ); // Inject build args if not using build secrets if (! $this->application->settings->use_build_secrets) { $buildTimeEnvs = $this->application->environment_variables() ->where('is_buildtime', true) ->get(); if ($buildTimeEnvs->isNotEmpty()) { $buildArgs = generateDockerBuildArgs($buildTimeEnvs); $buildArgsString = $buildArgs->implode(' '); $command = injectDockerComposeBuildArgs($command, $buildArgsString); } } return $command; } public function getDockerComposeStartCommandPreviewProperty(): string { if (! $this->dockerComposeCustomStartCommand) { return ''; } // Normalize baseDirectory to prevent double slashes (e.g., when baseDirectory is '/') $normalizedBase = $this->baseDirectory === '/' ? '' : rtrim($this->baseDirectory, '/'); // Use relative path for clarity in preview (e.g., ./backend/docker-compose.yaml) // Placeholder {workdir}/.env shows it's the workdir .env file (runtime env, not build-time) return injectDockerComposeFlags( $this->dockerComposeCustomStartCommand, ".{$normalizedBase}{$this->dockerComposeLocation}", '{workdir}/.env' ); } } ================================================ FILE: app/Livewire/Project/Application/Heading.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceStatusChanged" => 'checkStatus', "echo-private:team.{$teamId},ServiceChecked" => '$refresh', 'compose_loaded' => '$refresh', 'update_links' => '$refresh', ]; } public function mount() { $this->parameters = [ 'project_uuid' => $this->application->project()->uuid, 'environment_uuid' => $this->application->environment->uuid, 'application_uuid' => $this->application->uuid, ]; $lastDeployment = $this->application->get_last_successful_deployment(); $this->lastDeploymentInfo = data_get_str($lastDeployment, 'commit')->limit(7).' '.data_get($lastDeployment, 'commit_message'); $this->lastDeploymentLink = $this->application->gitCommitLink(data_get($lastDeployment, 'commit')); } public function checkStatus() { if ($this->application->destination->server->isFunctional()) { GetContainersStatus::dispatch($this->application->destination->server); } else { $this->dispatch('error', 'Server is not functional.'); } } public function manualCheckStatus() { $this->checkStatus(); } public function force_deploy_without_cache() { $this->authorize('deploy', $this->application); $this->deploy(force_rebuild: true); } public function deploy(bool $force_rebuild = false) { $this->authorize('deploy', $this->application); if ($this->application->build_pack === 'dockercompose' && is_null($this->application->docker_compose_raw)) { $this->dispatch('error', 'Failed to deploy', 'Please load a Compose file first.'); return; } if ($this->application->destination->server->isSwarm() && str($this->application->docker_registry_image_name)->isEmpty()) { $this->dispatch('error', 'Failed to deploy.', 'To deploy to a Swarm cluster you must set a Docker image name first.'); return; } if (data_get($this->application, 'settings.is_build_server_enabled') && str($this->application->docker_registry_image_name)->isEmpty()) { $this->dispatch('error', 'Failed to deploy.', 'To use a build server, you must first set a Docker image.
More information here: documentation'); return; } if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) { $this->dispatch('error', 'Failed to deploy.', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.
More information here: documentation'); return; } $this->setDeploymentUuid(); $result = queue_application_deployment( application: $this->application, deployment_uuid: $this->deploymentUuid, force_rebuild: $force_rebuild, ); if ($result['status'] === 'queue_full') { $this->dispatch('error', 'Deployment queue full', $result['message']); return; } if ($result['status'] === 'skipped') { $this->dispatch('error', 'Deployment skipped', $result['message']); return; } return $this->redirectRoute('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deploymentUuid, 'environment_uuid' => $this->parameters['environment_uuid'], ], navigate: false); } protected function setDeploymentUuid() { $this->deploymentUuid = new Cuid2; $this->parameters['deployment_uuid'] = $this->deploymentUuid; } public function stop() { $this->authorize('deploy', $this->application); $this->dispatch('info', 'Gracefully stopping application.
It could take a while depending on the application.'); StopApplication::dispatch($this->application, false, $this->docker_cleanup); } public function restart() { $this->authorize('deploy', $this->application); if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) { $this->dispatch('error', 'Failed to deploy', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.
More information here: documentation'); return; } $this->setDeploymentUuid(); $result = queue_application_deployment( application: $this->application, deployment_uuid: $this->deploymentUuid, restart_only: true, ); if ($result['status'] === 'queue_full') { $this->dispatch('error', 'Deployment queue full', $result['message']); return; } if ($result['status'] === 'skipped') { $this->dispatch('success', 'Deployment skipped', $result['message']); return; } return $this->redirectRoute('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deploymentUuid, 'environment_uuid' => $this->parameters['environment_uuid'], ], navigate: false); } public function render() { return view('livewire.project.application.heading', [ 'checkboxes' => [ ['id' => 'docker_cleanup', 'label' => __('resource.docker_cleanup')], ], ]); } } ================================================ FILE: app/Livewire/Project/Application/Preview/Form.php ================================================ previewUrlTemplate = $this->application->preview_url_template; $this->generateRealUrl(); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->application); $this->resetErrorBag(); $this->validate(); $this->application->preview_url_template = str_replace(' ', '', $this->previewUrlTemplate); $this->application->save(); $this->dispatch('success', 'Preview url template updated.'); $this->generateRealUrl(); } catch (\Throwable $e) { return handleError($e, $this); } } public function resetToDefault() { try { $this->authorize('update', $this->application); $this->application->preview_url_template = '{{pr_id}}.{{domain}}'; $this->previewUrlTemplate = $this->application->preview_url_template; $this->application->save(); $this->generateRealUrl(); $this->dispatch('success', 'Preview url template updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function generateRealUrl() { if (data_get($this->application, 'fqdn')) { $firstFqdn = str($this->application->fqdn)->before(','); $url = Url::fromString($firstFqdn); $host = $url->getHost(); $this->previewUrlTemplate = str($this->application->preview_url_template)->replace('{{domain}}', $host); } } } ================================================ FILE: app/Livewire/Project/Application/Previews.php ================================================ 'string|nullable', ]; public function mount() { $this->pull_requests = collect(); $this->parameters = get_route_parameters(); $this->syncData(false); } private function syncData(bool $toModel = false): void { if ($toModel) { foreach ($this->previewFqdns as $key => $fqdn) { $preview = $this->application->previews->get($key); if ($preview) { $preview->fqdn = $fqdn; } } } else { $this->previewFqdns = []; foreach ($this->application->previews as $key => $preview) { $this->previewFqdns[$key] = $preview->fqdn; } } } public function load_prs() { try { $this->authorize('update', $this->application); ['rate_limit_remaining' => $rate_limit_remaining, 'data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/pulls"); $this->rate_limit_remaining = $rate_limit_remaining; $this->pull_requests = $data->sortBy('number')->values(); } catch (\Throwable $e) { $this->rate_limit_remaining = 0; return handleError($e, $this); } } public function confirmDomainUsage() { $this->forceSaveDomains = true; $this->showDomainConflictModal = false; if ($this->pendingPreviewId) { $this->save_preview($this->pendingPreviewId); $this->pendingPreviewId = null; } } public function save_preview($preview_id) { try { $this->authorize('update', $this->application); $success = true; $preview = $this->application->previews->find($preview_id); if (! $preview) { throw new \Exception('Preview not found'); } // Find the key for this preview in the collection $previewKey = $this->application->previews->search(function ($item) use ($preview_id) { return $item->id == $preview_id; }); if ($previewKey !== false && isset($this->previewFqdns[$previewKey])) { $fqdn = $this->previewFqdns[$previewKey]; if (! empty($fqdn)) { $fqdn = str($fqdn)->replaceEnd(',', '')->trim(); $fqdn = str($fqdn)->replaceStart(',', '')->trim(); $fqdn = str($fqdn)->trim()->lower(); $this->previewFqdns[$previewKey] = $fqdn; if (! validateDNSEntry($fqdn, $this->application->destination->server)) { $this->dispatch('error', 'Validating DNS failed.', "Make sure you have added the DNS records correctly.

$fqdn->{$this->application->destination->server->ip}

Check this documentation for further help."); $success = false; } // Check for domain conflicts if not forcing save if (! $this->forceSaveDomains) { $result = checkDomainUsage(resource: $this->application, domain: $fqdn); if ($result['hasConflicts']) { $this->domainConflicts = $result['conflicts']; $this->showDomainConflictModal = true; $this->pendingPreviewId = $preview_id; return; } } else { // Reset the force flag after using it $this->forceSaveDomains = false; } } } if ($success) { $this->syncData(true); $preview->save(); $this->dispatch('success', 'Preview saved.

Do not forget to redeploy the preview to apply the changes.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function generate_preview($preview_id) { try { $this->authorize('update', $this->application); $preview = $this->application->previews->find($preview_id); if (! $preview) { $this->dispatch('error', 'Preview not found.'); return; } if ($this->application->build_pack === 'dockercompose') { $preview->generate_preview_fqdn_compose(); $this->application->refresh(); $this->syncData(false); $this->dispatch('success', 'Domain generated.'); return; } $preview->generate_preview_fqdn(); $this->application->refresh(); $this->syncData(false); $this->dispatch('update_links'); $this->dispatch('success', 'Domain generated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function add(int $pull_request_id, ?string $pull_request_html_url = null) { try { $this->authorize('update', $this->application); if ($this->application->build_pack === 'dockercompose') { $this->setDeploymentUuid(); $found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first(); if (! $found && ! is_null($pull_request_html_url)) { $found = ApplicationPreview::create([ 'application_id' => $this->application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, 'docker_compose_domains' => $this->application->docker_compose_domains, ]); } $found->generate_preview_fqdn_compose(); $this->application->refresh(); $this->syncData(false); } else { $this->setDeploymentUuid(); $found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first(); if (! $found && ! is_null($pull_request_html_url)) { $found = ApplicationPreview::create([ 'application_id' => $this->application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, ]); } $found->generate_preview_fqdn(); $this->application->refresh(); $this->syncData(false); $this->dispatch('update_links'); $this->dispatch('success', 'Preview added.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function force_deploy_without_cache(int $pull_request_id, ?string $pull_request_html_url = null) { $this->authorize('deploy', $this->application); $this->deploy($pull_request_id, $pull_request_html_url, force_rebuild: true); } public function add_and_deploy(int $pull_request_id, ?string $pull_request_html_url = null) { $this->authorize('deploy', $this->application); $this->add($pull_request_id, $pull_request_html_url); $this->deploy($pull_request_id, $pull_request_html_url); } public function deploy(int $pull_request_id, ?string $pull_request_html_url = null, bool $force_rebuild = false) { $this->authorize('deploy', $this->application); try { $this->setDeploymentUuid(); $found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first(); if (! $found && ! is_null($pull_request_html_url)) { ApplicationPreview::create([ 'application_id' => $this->application->id, 'pull_request_id' => $pull_request_id, 'pull_request_html_url' => $pull_request_html_url, ]); } $result = queue_application_deployment( application: $this->application, deployment_uuid: $this->deployment_uuid, force_rebuild: $force_rebuild, pull_request_id: $pull_request_id, git_type: $found->git_type ?? null, ); if ($result['status'] === 'queue_full') { $this->dispatch('error', 'Deployment queue full', $result['message']); return; } if ($result['status'] === 'skipped') { $this->dispatch('success', 'Deployment skipped', $result['message']); return; } return redirect()->route('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deployment_uuid, 'environment_uuid' => $this->parameters['environment_uuid'], ]); } catch (\Throwable $e) { return handleError($e, $this); } } protected function setDeploymentUuid() { $this->deployment_uuid = new Cuid2; $this->parameters['deployment_uuid'] = $this->deployment_uuid; } private function stopContainers(array $containers, $server) { $containersToStop = collect($containers)->pluck('Names')->toArray(); foreach ($containersToStop as $containerName) { instant_remote_process(command: [ "docker stop -t 30 $containerName", "docker rm -f $containerName", ], server: $server, throwError: false); } } public function stop(int $pull_request_id) { $this->authorize('deploy', $this->application); try { $server = $this->application->destination->server; if ($this->application->destination->server->isSwarm()) { instant_remote_process(["docker stack rm {$this->application->uuid}-{$pull_request_id}"], $server); } else { $containers = getCurrentApplicationContainerStatus($server, $this->application->id, $pull_request_id)->toArray(); $this->stopContainers($containers, $server); } GetContainersStatus::run($server); $this->application->refresh(); $this->dispatch('containerStatusUpdated'); $this->dispatch('success', 'Preview Deployment stopped.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function delete(int $pull_request_id) { try { $this->authorize('delete', $this->application); $preview = ApplicationPreview::where('application_id', $this->application->id) ->where('pull_request_id', $pull_request_id) ->first(); if (! $preview) { $this->dispatch('error', 'Preview not found.'); return; } // Soft delete immediately for instant UI feedback $preview->delete(); // Dispatch the job for async cleanup (container stopping + force delete) DeleteResourceJob::dispatch($preview); // Refresh the application and its previews relationship to reflect the soft delete $this->application->load('previews'); $this->dispatch('update_links'); $this->dispatch('success', 'Preview deletion started. It may take a few moments to complete.'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Application/PreviewsCompose.php ================================================ domain = data_get($this->service, 'domain'); } public function render() { return view('livewire.project.application.previews-compose'); } public function save() { try { $this->authorize('update', $this->preview->application); $docker_compose_domains = data_get($this->preview, 'docker_compose_domains'); $docker_compose_domains = json_decode($docker_compose_domains, true) ?: []; $docker_compose_domains[$this->serviceName] = $docker_compose_domains[$this->serviceName] ?? []; $docker_compose_domains[$this->serviceName]['domain'] = $this->domain; $this->preview->docker_compose_domains = json_encode($docker_compose_domains); $this->preview->save(); $this->dispatch('update_links'); $this->dispatch('success', 'Domain saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function generate() { try { $this->authorize('update', $this->preview->application); $domains = collect(json_decode($this->preview->application->docker_compose_domains, true) ?: []); $domain = $domains->first(function ($_, $key) { return $key === $this->serviceName; }); $domain_string = data_get($domain, 'domain'); // If no domain is set in the main application, generate a default domain if (empty($domain_string)) { $server = $this->preview->application->destination->server; $template = $this->preview->application->preview_url_template; $random = new Cuid2; // Generate a unique domain like main app services do $generated_fqdn = generateUrl(server: $server, random: $random); $preview_fqdn = str_replace('{{random}}', $random, $template); $preview_fqdn = str_replace('{{domain}}', str($generated_fqdn)->after('://'), $preview_fqdn); $preview_fqdn = str_replace('{{pr_id}}', $this->preview->pull_request_id, $preview_fqdn); $preview_fqdn = str($generated_fqdn)->before('://').'://'.$preview_fqdn; } else { // Use the existing domain from the main application // Handle multiple domains separated by commas $domain_list = explode(',', $domain_string); $preview_fqdns = []; $template = $this->preview->application->preview_url_template; $random = new Cuid2; foreach ($domain_list as $single_domain) { $single_domain = trim($single_domain); if (empty($single_domain)) { continue; } $url = Url::fromString($single_domain); $host = $url->getHost(); $schema = $url->getScheme(); $portInt = $url->getPort(); $port = $portInt !== null ? ':'.$portInt : ''; $preview_fqdn = str_replace('{{random}}', $random, $template); $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); $preview_fqdn = str_replace('{{pr_id}}', $this->preview->pull_request_id, $preview_fqdn); $preview_fqdns[] = "$schema://$preview_fqdn{$port}"; } $preview_fqdn = implode(',', $preview_fqdns); } // Save the generated domain $this->domain = $preview_fqdn; $docker_compose_domains = data_get($this->preview, 'docker_compose_domains'); $docker_compose_domains = json_decode($docker_compose_domains, true) ?: []; $docker_compose_domains[$this->serviceName] = $docker_compose_domains[$this->serviceName] ?? []; $docker_compose_domains[$this->serviceName]['domain'] = $this->domain; $this->preview->docker_compose_domains = json_encode($docker_compose_domains); $this->preview->save(); $this->dispatch('update_links'); $this->dispatch('success', 'Domain generated.'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Application/Rollback.php ================================================ parameters = get_route_parameters(); $this->dockerImagesToKeep = $this->application->settings->docker_images_to_keep ?? 2; $server = $this->application->destination->server; $this->serverRetentionDisabled = $server->settings->disable_application_image_retention ?? false; } public function saveSettings() { try { $this->authorize('update', $this->application); $this->validate(); $this->application->settings->docker_images_to_keep = $this->dockerImagesToKeep; $this->application->settings->save(); $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function rollbackImage($commit) { $this->authorize('deploy', $this->application); $commit = validateGitRef($commit, 'rollback commit'); $deployment_uuid = new Cuid2; $result = queue_application_deployment( application: $this->application, deployment_uuid: $deployment_uuid, commit: $commit, rollback: true, force_rebuild: false, ); if ($result['status'] === 'queue_full') { $this->dispatch('error', 'Deployment queue full', $result['message']); return; } return redirectRoute($this, 'project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $deployment_uuid, 'environment_uuid' => $this->parameters['environment_uuid'], ]); } public function loadImages($showToast = false) { $this->authorize('view', $this->application); try { $image = $this->application->docker_registry_image_name ?? $this->application->uuid; if ($this->application->destination->server->isFunctional()) { $output = instant_remote_process([ "docker inspect --format='{{.Config.Image}}' {$this->application->uuid}", ], $this->application->destination->server, throwError: false); $current_tag = str($output)->trim()->explode(':'); $this->current = data_get($current_tag, 1); $output = instant_remote_process([ "docker images --format '{{.Repository}}#{{.Tag}}#{{.CreatedAt}}'", ], $this->application->destination->server); $this->images = str($output)->trim()->explode("\n")->filter(function ($item) use ($image) { return str($item)->contains($image); })->map(function ($item) { $item = str($item)->explode('#'); $is_current = $item[1] === $this->current; return [ 'tag' => $item[1], 'created_at' => $item[2], 'is_current' => $is_current, ]; })->toArray(); } $showToast && $this->dispatch('success', 'Images loaded.'); return []; } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Application/Source.php ================================================ syncData(); $this->getPrivateKeys(); $this->getSources(); } catch (\Throwable $e) { handleError($e, $this); } } public function updatedGitRepository() { $this->gitRepository = trim($this->gitRepository); } public function updatedGitBranch() { $this->gitBranch = trim($this->gitBranch); } public function updatedGitCommitSha() { $this->gitCommitSha = trim($this->gitCommitSha); } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->application->update([ 'git_repository' => $this->gitRepository, 'git_branch' => $this->gitBranch, 'git_commit_sha' => $this->gitCommitSha, 'private_key_id' => $this->privateKeyId, ]); // Refresh to get the trimmed values from the model $this->application->refresh(); $this->syncData(false); } else { $this->gitRepository = $this->application->git_repository; $this->gitBranch = $this->application->git_branch; $this->gitCommitSha = $this->application->git_commit_sha; $this->privateKeyId = $this->application->private_key_id; $this->privateKeyName = data_get($this->application, 'private_key.name'); } } private function getPrivateKeys() { $this->privateKeys = PrivateKey::whereTeamId(currentTeam()->id)->get()->reject(function ($key) { return $key->id == $this->privateKeyId; }); } private function getSources() { // filter the current source out $this->sources = currentTeam()->sources()->whereNotNull('app_id')->reject(function ($source) { return $source->id === $this->application->source_id; })->sortBy('name'); } public function setPrivateKey(int $privateKeyId) { try { $this->authorize('update', $this->application); $this->privateKeyId = $privateKeyId; $this->syncData(true); $this->getPrivateKeys(); $this->application->refresh(); $this->privateKeyName = $this->application->private_key->name; $this->dispatch('success', 'Private key updated!'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->application); if (str($this->gitCommitSha)->isEmpty()) { $this->gitCommitSha = 'HEAD'; } $this->syncData(true); $this->dispatch('success', 'Application source updated!'); } catch (\Throwable $e) { return handleError($e, $this); } } public function changeSource($sourceId, $sourceType) { try { $this->authorize('update', $this->application); $this->application->update([ 'source_id' => $sourceId, 'source_type' => $sourceType, ]); ['repository' => $customRepository] = $this->application->customRepository(); $repository = githubApi($this->application->source, "repos/{$customRepository}"); $data = data_get($repository, 'data'); $repository_project_id = data_get($data, 'id'); if (isset($repository_project_id)) { if ($this->application->repository_project_id !== $repository_project_id) { $this->application->repository_project_id = $repository_project_id; $this->application->save(); } } $this->application->refresh(); $this->getSources(); $this->dispatch('success', 'Source updated!'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Application/Swarm.php ================================================ syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->application->swarm_replicas = $this->swarmReplicas; $this->application->swarm_placement_constraints = $this->swarmPlacementConstraints ? base64_encode($this->swarmPlacementConstraints) : null; $this->application->settings->is_swarm_only_worker_nodes = $this->isSwarmOnlyWorkerNodes; $this->application->save(); $this->application->settings->save(); } else { $this->swarmReplicas = $this->application->swarm_replicas; if ($this->application->swarm_placement_constraints) { $this->swarmPlacementConstraints = base64_decode($this->application->swarm_placement_constraints); } else { $this->swarmPlacementConstraints = null; } $this->isSwarmOnlyWorkerNodes = $this->application->settings->is_swarm_only_worker_nodes; } } public function instantSave() { try { $this->syncData(true); $this->dispatch('success', 'Swarm settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->syncData(true); $this->dispatch('success', 'Swarm settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.application.swarm'); } } ================================================ FILE: app/Livewire/Project/CloneMe.php ================================================ 'Please select a server.', 'selectedDestination' => 'Please select a server & destination.', 'newName.required' => 'Please enter a name for the new project or environment.', ], ValidationPatterns::nameMessages()); } public function mount($project_uuid) { $this->project_uuid = $project_uuid; $this->project = Project::where('uuid', $project_uuid)->firstOrFail(); $this->environment = $this->project->environments->where('uuid', $this->environment_uuid)->first(); $this->project_id = $this->project->id; $this->servers = currentTeam() ->servers() ->get() ->reject(fn ($server) => $server->isBuildServer()); $this->newName = str($this->project->name.'-clone-'.(string) new Cuid2)->slug(); } public function toggleVolumeCloning(bool $value) { $this->cloneVolumeData = $value; } public function render() { return view('livewire.project.clone-me'); } public function selectServer($server_id, $destination_id) { if ($server_id == $this->selectedServer && $destination_id == $this->selectedDestination) { $this->selectedServer = null; $this->selectedDestination = null; $this->server = null; return; } $this->selectedServer = $server_id; $this->selectedDestination = $destination_id; $this->server = $this->servers->where('id', $server_id)->first(); } public function clone(string $type) { try { $this->validate([ 'selectedDestination' => 'required', 'newName' => ValidationPatterns::nameRules(), ]); if ($type === 'project') { $foundProject = Project::where('name', $this->newName)->first(); if ($foundProject) { throw new \Exception('Project with the same name already exists.'); } $project = Project::create([ 'name' => $this->newName, 'team_id' => currentTeam()->id, 'description' => $this->project->description.' (clone)', ]); if ($this->environment->name !== 'production') { $project->environments()->create([ 'name' => $this->environment->name, 'uuid' => (string) new Cuid2, ]); } $environment = $project->environments->where('name', $this->environment->name)->first(); } else { $foundEnv = $this->project->environments()->where('name', $this->newName)->first(); if ($foundEnv) { throw new \Exception('Environment with the same name already exists.'); } $project = $this->project; $environment = $this->project->environments()->create([ 'name' => $this->newName, 'uuid' => (string) new Cuid2, ]); } $applications = $this->environment->applications; $databases = $this->environment->databases(); $services = $this->environment->services; foreach ($applications as $application) { $selectedDestination = $this->servers->flatMap(fn ($server) => $server->destinations())->where('id', $this->selectedDestination)->first(); clone_application($application, $selectedDestination, [ 'environment_id' => $environment->id, ], $this->cloneVolumeData); } foreach ($databases as $database) { $uuid = (string) new Cuid2; $newDatabase = $database->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => $uuid, 'status' => 'exited', 'started_at' => null, 'environment_id' => $environment->id, 'destination_id' => $this->selectedDestination, ]); $newDatabase->save(); $tags = $database->tags; foreach ($tags as $tag) { $newDatabase->tags()->attach($tag->id); } $newDatabase->persistentStorages()->delete(); $persistentVolumes = $database->persistentStorages()->get(); foreach ($persistentVolumes as $volume) { $originalName = $volume->name; $newName = ''; if (str_starts_with($originalName, 'postgres-data-')) { $newName = 'postgres-data-'.$newDatabase->uuid; } elseif (str_starts_with($originalName, 'mysql-data-')) { $newName = 'mysql-data-'.$newDatabase->uuid; } elseif (str_starts_with($originalName, 'redis-data-')) { $newName = 'redis-data-'.$newDatabase->uuid; } elseif (str_starts_with($originalName, 'clickhouse-data-')) { $newName = 'clickhouse-data-'.$newDatabase->uuid; } elseif (str_starts_with($originalName, 'mariadb-data-')) { $newName = 'mariadb-data-'.$newDatabase->uuid; } elseif (str_starts_with($originalName, 'mongodb-data-')) { $newName = 'mongodb-data-'.$newDatabase->uuid; } elseif (str_starts_with($originalName, 'keydb-data-')) { $newName = 'keydb-data-'.$newDatabase->uuid; } elseif (str_starts_with($originalName, 'dragonfly-data-')) { $newName = 'dragonfly-data-'.$newDatabase->uuid; } else { if (str_starts_with($volume->name, $database->uuid)) { $newName = str($volume->name)->replace($database->uuid, $newDatabase->uuid); } else { $newName = $newDatabase->uuid.'-'.$volume->name; } } $newPersistentVolume = $volume->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'name' => $newName, 'resource_id' => $newDatabase->id, ]); $newPersistentVolume->save(); if ($this->cloneVolumeData) { try { StopDatabase::dispatch($database); $sourceVolume = $volume->name; $targetVolume = $newPersistentVolume->name; $sourceServer = $database->destination->server; $targetServer = $newDatabase->destination->server; VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume); StartDatabase::dispatch($database); } catch (\Exception $e) { \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage()); } } } $fileStorages = $database->fileStorages()->get(); foreach ($fileStorages as $storage) { $newStorage = $storage->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'resource_id' => $newDatabase->id, ]); $newStorage->save(); } $scheduledBackups = $database->scheduledBackups()->get(); foreach ($scheduledBackups as $backup) { $uuid = (string) new Cuid2; $newBackup = $backup->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => $uuid, 'database_id' => $newDatabase->id, 'database_type' => $newDatabase->getMorphClass(), 'team_id' => currentTeam()->id, ]); $newBackup->save(); } $environmentVaribles = $database->environment_variables()->get(); foreach ($environmentVaribles as $environmentVarible) { $payload = []; $payload['resourceable_id'] = $newDatabase->id; $payload['resourceable_type'] = $newDatabase->getMorphClass(); $newEnvironmentVariable = $environmentVarible->replicate([ 'id', 'created_at', 'updated_at', ])->fill($payload); $newEnvironmentVariable->save(); } } foreach ($services as $service) { $uuid = (string) new Cuid2; $newService = $service->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => $uuid, 'environment_id' => $environment->id, 'destination_id' => $this->selectedDestination, ]); $newService->save(); $tags = $service->tags; foreach ($tags as $tag) { $newService->tags()->attach($tag->id); } $scheduledTasks = $service->scheduled_tasks()->get(); foreach ($scheduledTasks as $task) { $newTask = $task->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => (string) new Cuid2, 'service_id' => $newService->id, 'team_id' => currentTeam()->id, ]); $newTask->save(); } $environmentVariables = $service->environment_variables()->get(); foreach ($environmentVariables as $environmentVariable) { $newEnvironmentVariable = $environmentVariable->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'resourceable_id' => $newService->id, 'resourceable_type' => $newService->getMorphClass(), ]); $newEnvironmentVariable->save(); } foreach ($newService->applications() as $application) { $application->update([ 'status' => 'exited', ]); $persistentVolumes = $application->persistentStorages()->get(); foreach ($persistentVolumes as $volume) { $newName = ''; if (str_starts_with($volume->name, $application->uuid)) { $newName = str($volume->name)->replace($application->uuid, $application->uuid); } else { $newName = $application->uuid.'-'.$volume->name; } $newPersistentVolume = $volume->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'name' => $newName, 'resource_id' => $application->id, ]); $newPersistentVolume->save(); if ($this->cloneVolumeData) { try { StopService::dispatch($application); $sourceVolume = $volume->name; $targetVolume = $newPersistentVolume->name; $sourceServer = $application->service->destination->server; $targetServer = $newService->destination->server; VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume); StartService::dispatch($application); } catch (\Exception $e) { \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage()); } } } $fileStorages = $application->fileStorages()->get(); foreach ($fileStorages as $storage) { $newStorage = $storage->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'resource_id' => $application->id, ]); $newStorage->save(); } } foreach ($newService->databases() as $database) { $database->update([ 'status' => 'exited', ]); $persistentVolumes = $database->persistentStorages()->get(); foreach ($persistentVolumes as $volume) { $newName = ''; if (str_starts_with($volume->name, $database->uuid)) { $newName = str($volume->name)->replace($database->uuid, $database->uuid); } else { $newName = $database->uuid.'-'.$volume->name; } $newPersistentVolume = $volume->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'name' => $newName, 'resource_id' => $database->id, ]); $newPersistentVolume->save(); if ($this->cloneVolumeData) { try { StopService::dispatch($database->service); $sourceVolume = $volume->name; $targetVolume = $newPersistentVolume->name; $sourceServer = $database->service->destination->server; $targetServer = $newService->destination->server; VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume); StartService::dispatch($database->service); } catch (\Exception $e) { \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage()); } } } $fileStorages = $database->fileStorages()->get(); foreach ($fileStorages as $storage) { $newStorage = $storage->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'resource_id' => $database->id, ]); $newStorage->save(); } $scheduledBackups = $database->scheduledBackups()->get(); foreach ($scheduledBackups as $backup) { $uuid = (string) new Cuid2; $newBackup = $backup->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => $uuid, 'database_id' => $database->id, 'database_type' => $database->getMorphClass(), 'team_id' => currentTeam()->id, ]); $newBackup->save(); } } $newService->parse(); } } catch (\Exception $e) { handleError($e, $this); return; } finally { if (! isset($e)) { return redirect()->route('project.resource.index', [ 'project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, ]); } } } } ================================================ FILE: app/Livewire/Project/Database/Backup/Execution.php ================================================ route('backup_uuid'); $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); if (! $project) { return redirect()->route('dashboard'); } $environment = $project->load(['environments'])->environments->where('uuid', request()->route('environment_uuid'))->first()->load(['applications']); if (! $environment) { return redirect()->route('dashboard'); } $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); if (! $database) { return redirect()->route('dashboard'); } $backup = $database->scheduledBackups->where('uuid', $backup_uuid)->first(); if (! $backup) { return redirect()->route('dashboard'); } $executions = collect($backup->executions)->sortByDesc('created_at'); $this->database = $database; $this->backup = $backup; $this->executions = $executions; $this->s3s = currentTeam()->s3s; } public function render() { return view('livewire.project.database.backup.execution'); } } ================================================ FILE: app/Livewire/Project/Database/Backup/Index.php ================================================ load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); if (! $project) { return redirect()->route('dashboard'); } $environment = $project->load(['environments'])->environments->where('uuid', request()->route('environment_uuid'))->first()->load(['applications']); if (! $environment) { return redirect()->route('dashboard'); } $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); if (! $database) { return redirect()->route('dashboard'); } // No backups if ( $database->getMorphClass() === \App\Models\StandaloneRedis::class || $database->getMorphClass() === \App\Models\StandaloneKeydb::class || $database->getMorphClass() === \App\Models\StandaloneDragonfly::class || $database->getMorphClass() === \App\Models\StandaloneClickhouse::class ) { return redirect()->route('project.database.configuration', [ 'project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid, ]); } $this->database = $database; } public function render() { return view('livewire.project.database.backup.index'); } } ================================================ FILE: app/Livewire/Project/Database/BackupEdit.php ================================================ authorize('view', $this->backup->database); $this->parameters = get_route_parameters(); $this->syncData(); } catch (Exception $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->backup->enabled = $this->backupEnabled; $this->backup->frequency = $this->frequency; $this->backup->database_backup_retention_amount_locally = $this->databaseBackupRetentionAmountLocally; $this->backup->database_backup_retention_days_locally = $this->databaseBackupRetentionDaysLocally; $this->backup->database_backup_retention_max_storage_locally = $this->databaseBackupRetentionMaxStorageLocally; $this->backup->database_backup_retention_amount_s3 = $this->databaseBackupRetentionAmountS3; $this->backup->database_backup_retention_days_s3 = $this->databaseBackupRetentionDaysS3; $this->backup->database_backup_retention_max_storage_s3 = $this->databaseBackupRetentionMaxStorageS3; $this->backup->save_s3 = $this->saveS3; $this->backup->disable_local_backup = $this->disableLocalBackup; $this->backup->s3_storage_id = $this->s3StorageId; // Validate databases_to_backup to prevent command injection if (filled($this->databasesToBackup)) { $databases = str($this->databasesToBackup)->explode(','); foreach ($databases as $index => $db) { $dbName = trim($db); try { validateShellSafePath($dbName, 'database name'); } catch (\Exception $e) { // Provide specific error message indicating which database failed validation $position = $index + 1; throw new \Exception( "Database #{$position} ('{$dbName}') validation failed: ". $e->getMessage() ); } } } $this->backup->databases_to_backup = $this->databasesToBackup; $this->backup->dump_all = $this->dumpAll; $this->backup->timeout = $this->timeout; $this->customValidate(); $this->backup->save(); } else { $this->backupEnabled = $this->backup->enabled; $this->frequency = $this->backup->frequency; $this->timezone = data_get($this->backup->server(), 'settings.server_timezone', 'Instance timezone'); $this->databaseBackupRetentionAmountLocally = $this->backup->database_backup_retention_amount_locally; $this->databaseBackupRetentionDaysLocally = $this->backup->database_backup_retention_days_locally; $this->databaseBackupRetentionMaxStorageLocally = $this->backup->database_backup_retention_max_storage_locally; $this->databaseBackupRetentionAmountS3 = $this->backup->database_backup_retention_amount_s3; $this->databaseBackupRetentionDaysS3 = $this->backup->database_backup_retention_days_s3; $this->databaseBackupRetentionMaxStorageS3 = $this->backup->database_backup_retention_max_storage_s3; $this->saveS3 = $this->backup->save_s3; $this->disableLocalBackup = $this->backup->disable_local_backup ?? false; $this->s3StorageId = $this->backup->s3_storage_id; $this->databasesToBackup = $this->backup->databases_to_backup; $this->dumpAll = $this->backup->dump_all; $this->timeout = $this->backup->timeout; } } public function delete($password, $selectedActions = []) { $this->authorize('manageBackups', $this->backup->database); if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } try { $server = null; if ($this->backup->database instanceof \App\Models\ServiceDatabase) { $server = $this->backup->database->service->destination->server; } elseif ($this->backup->database->destination && $this->backup->database->destination->server) { $server = $this->backup->database->destination->server; } $filenames = $this->backup->executions() ->whereNotNull('filename') ->where('filename', '!=', '') ->where('scheduled_database_backup_id', $this->backup->id) ->pluck('filename') ->filter() ->all(); if (! empty($filenames)) { if ($this->delete_associated_backups_locally && $server) { deleteBackupsLocally($filenames, $server); } if ($this->delete_associated_backups_s3 && $this->backup->s3) { deleteBackupsS3($filenames, $this->backup->s3); } } $this->backup->delete(); if ($this->backup->database->getMorphClass() === \App\Models\ServiceDatabase::class) { $serviceDatabase = $this->backup->database; return redirect()->route('project.service.database.backups', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_uuid' => $this->parameters['environment_uuid'], 'service_uuid' => $serviceDatabase->service->uuid, 'stack_service_uuid' => $serviceDatabase->uuid, ]); } else { return redirect()->route('project.database.backup.index', $this->parameters); } } catch (\Exception $e) { $this->dispatch('error', 'Failed to delete backup: '.$e->getMessage()); return handleError($e, $this); } } public function instantSave() { try { $this->authorize('manageBackups', $this->backup->database); $this->syncData(true); $this->dispatch('success', 'Backup updated successfully.'); } catch (\Throwable $e) { $this->dispatch('error', $e->getMessage()); } } private function customValidate() { if (! is_numeric($this->backup->s3_storage_id)) { $this->backup->s3_storage_id = null; } // Validate that disable_local_backup can only be true when S3 backup is enabled if ($this->backup->disable_local_backup && ! $this->backup->save_s3) { $this->backup->disable_local_backup = $this->disableLocalBackup = false; } $isValid = validate_cron_expression($this->backup->frequency); if (! $isValid) { throw new \Exception('Invalid Cron / Human expression'); } $this->validate(); } public function submit() { try { $this->authorize('manageBackups', $this->backup->database); $this->syncData(true); $this->dispatch('success', 'Backup updated successfully.'); } catch (\Throwable $e) { $this->dispatch('error', $e->getMessage()); } } public function render() { return view('livewire.project.database.backup-edit', [ 'checkboxes' => [ ['id' => 'delete_associated_backups_locally', 'label' => __('database.delete_backups_locally')], ['id' => 'delete_associated_backups_s3', 'label' => 'All backups will be permanently deleted (associated with this backup job) from the selected S3 Storage.'], // ['id' => 'delete_associated_backups_sftp', 'label' => 'All backups associated with this backup job from this database will be permanently deleted from the selected SFTP Storage.'] ], ]); } } ================================================ FILE: app/Livewire/Project/Database/BackupExecutions.php ================================================ 'refreshBackupExecutions', ]; } public function cleanupFailed() { if ($this->backup) { $this->backup->executions()->where('status', 'failed')->delete(); $this->refreshBackupExecutions(); $this->dispatch('success', 'Failed backups cleaned up.'); } } public function cleanupDeleted() { if ($this->backup) { $deletedCount = $this->backup->executions()->where('local_storage_deleted', true)->count(); if ($deletedCount > 0) { $this->backup->executions()->where('local_storage_deleted', true)->delete(); $this->refreshBackupExecutions(); $this->dispatch('success', "Cleaned up {$deletedCount} backup entries deleted from local storage."); } else { $this->dispatch('info', 'No backup entries found that are deleted from local storage.'); } } } public function deleteBackup($executionId, $password, $selectedActions = []) { if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } $execution = $this->backup->executions()->where('id', $executionId)->first(); if (is_null($execution)) { $this->dispatch('error', 'Backup execution not found.'); return; } $server = $execution->scheduledDatabaseBackup->database->getMorphClass() === \App\Models\ServiceDatabase::class ? $execution->scheduledDatabaseBackup->database->service->destination->server : $execution->scheduledDatabaseBackup->database->destination->server; try { if ($execution->filename) { deleteBackupsLocally($execution->filename, $server); if ($this->delete_backup_s3 && $execution->scheduledDatabaseBackup->s3) { deleteBackupsS3($execution->filename, $execution->scheduledDatabaseBackup->s3); } } $execution->delete(); $this->dispatch('success', 'Backup deleted.'); $this->refreshBackupExecutions(); } catch (\Exception $e) { $this->dispatch('error', 'Failed to delete backup: '.$e->getMessage()); return true; } return true; } public function download_file($exeuctionId) { return redirect()->route('download.backup', $exeuctionId); } public function refreshBackupExecutions(): void { $this->loadExecutions(); } public function reloadExecutions() { $this->loadExecutions(); } public function previousPage(?int $take = null) { if ($take) { $this->skip = $this->skip - $take; } $this->skip = $this->skip - $this->defaultTake; if ($this->skip < 0) { $this->showPrev = false; $this->skip = 0; } $this->updateCurrentPage(); $this->loadExecutions(); } public function nextPage(?int $take = null) { if ($take) { $this->skip = $this->skip + $take; } $this->showPrev = true; $this->updateCurrentPage(); $this->loadExecutions(); } private function loadExecutions() { if ($this->backup && $this->backup->exists) { ['executions' => $executions, 'count' => $count] = $this->backup->executionsPaginated($this->skip, $this->defaultTake); $this->executions = $executions; $this->executions_count = $count; } else { $this->executions = collect([]); $this->executions_count = 0; } $this->showMore(); } private function showMore() { if ($this->executions->count() !== 0) { $this->showNext = true; if ($this->executions->count() < $this->defaultTake) { $this->showNext = false; } return; } } private function updateCurrentPage() { $this->currentPage = intval($this->skip / $this->defaultTake) + 1; } public function mount(ScheduledDatabaseBackup $backup) { $this->backup = $backup; $this->database = $backup->database; $this->updateCurrentPage(); $this->loadExecutions(); } public function server() { if ($this->database) { $server = null; if ($this->database instanceof \App\Models\ServiceDatabase) { $server = $this->database->service->destination->server; } elseif ($this->database->destination && $this->database->destination->server) { $server = $this->database->destination->server; } if ($server) { return $server; } } return null; } public function render() { return view('livewire.project.database.backup-executions'); } } ================================================ FILE: app/Livewire/Project/Database/BackupNow.php ================================================ authorize('manageBackups', $this->backup->database); DatabaseBackupJob::dispatch($this->backup); $this->dispatch('success', 'Backup queued. It will be available in a few minutes.'); } } ================================================ FILE: app/Livewire/Project/Database/Clickhouse/General.php ================================================ currentTeam()->id; return [ "echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped', ]; } public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } } catch (\Throwable $e) { return handleError($e, $this); } } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'clickhouseAdminUser' => 'required|string', 'clickhouseAdminPassword' => 'required|string', 'image' => 'required|string', 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', 'isLogDrainEnabled' => 'nullable|boolean', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'clickhouseAdminUser.required' => 'The Admin User field is required.', 'clickhouseAdminUser.string' => 'The Admin User must be a string.', 'clickhouseAdminPassword.required' => 'The Admin Password field is required.', 'clickhouseAdminPassword.string' => 'The Admin Password must be a string.', 'image.required' => 'The Docker Image field is required.', 'image.string' => 'The Docker Image must be a string.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', ] ); } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->clickhouse_admin_user = $this->clickhouseAdminUser; $this->database->clickhouse_admin_password = $this->clickhouseAdminPassword; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->save(); $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->clickhouseAdminUser = $this->database->clickhouse_admin_user; $this->clickhouseAdminPassword = $this->database->clickhouse_admin_password; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function databaseProxyStopped() { $this->syncData(); } public function submit() { try { $this->authorize('update', $this->database); if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { if (is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } } ================================================ FILE: app/Livewire/Project/Database/Configuration.php ================================================ currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceChecked" => '$refresh', ]; } public function mount() { try { $this->currentRoute = request()->route()->getName(); $project = currentTeam() ->projects() ->select('id', 'uuid', 'team_id') ->where('uuid', request()->route('project_uuid')) ->firstOrFail(); $environment = $project->environments() ->select('id', 'name', 'project_id', 'uuid') ->where('uuid', request()->route('environment_uuid')) ->firstOrFail(); $database = $environment->databases() ->where('uuid', request()->route('database_uuid')) ->firstOrFail(); $this->authorize('view', $database); $this->database = $database; $this->project = $project; $this->environment = $environment; if (str($this->database->status)->startsWith('running') && is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); $this->dispatch('configurationChanged'); } } catch (\Throwable $e) { if ($e instanceof \Illuminate\Auth\Access\AuthorizationException) { return redirect()->route('dashboard'); } if ($e instanceof \Illuminate\Support\ItemNotFoundException) { return redirect()->route('dashboard'); } return handleError($e, $this); } } public function render() { return view('livewire.project.database.configuration'); } } ================================================ FILE: app/Livewire/Project/Database/CreateScheduledBackup.php ================================================ definedS3s = currentTeam()->s3s; if ($this->definedS3s->count() > 0) { $this->s3StorageId = $this->definedS3s->first()->id; } } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('manageBackups', $this->database); $this->validate(); $isValid = validate_cron_expression($this->frequency); if (! $isValid) { $this->dispatch('error', 'Invalid Cron / Human expression.'); return; } $payload = [ 'enabled' => true, 'frequency' => $this->frequency, 'save_s3' => $this->saveToS3, 's3_storage_id' => $this->s3StorageId, 'database_id' => $this->database->id, 'database_type' => $this->database->getMorphClass(), 'team_id' => currentTeam()->id, ]; if ($this->database->type() === 'standalone-postgresql') { $payload['databases_to_backup'] = $this->database->postgres_db; } elseif ($this->database->type() === 'standalone-mysql') { $payload['databases_to_backup'] = $this->database->mysql_database; } elseif ($this->database->type() === 'standalone-mariadb') { $payload['databases_to_backup'] = $this->database->mariadb_database; } $databaseBackup = ScheduledDatabaseBackup::create($payload); if ($this->database->getMorphClass() === \App\Models\ServiceDatabase::class) { $this->dispatch('refreshScheduledBackups', $databaseBackup->id); } else { $this->dispatch('refreshScheduledBackups'); } } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->frequency = ''; } } } ================================================ FILE: app/Livewire/Project/Database/Dragonfly/General.php ================================================ currentTeam()->id; return [ "echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped', "echo-private:user.{$userId},DatabaseStatusChanged" => '$refresh', ]; } public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } $existingCert = $this->database->sslCertificates()->first(); if ($existingCert) { $this->certificateValidUntil = $existingCert->valid_until; } } catch (\Throwable $e) { return handleError($e, $this); } } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'dragonflyPassword' => 'required|string', 'image' => 'required|string', 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', 'isLogDrainEnabled' => 'nullable|boolean', 'enable_ssl' => 'nullable|boolean', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'dragonflyPassword.required' => 'The Dragonfly Password field is required.', 'dragonflyPassword.string' => 'The Dragonfly Password must be a string.', 'image.required' => 'The Docker Image field is required.', 'image.string' => 'The Docker Image must be a string.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', ] ); } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->dragonfly_password = $this->dragonflyPassword; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->enable_ssl = $this->enable_ssl; $this->database->save(); $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->dragonflyPassword = $this->database->dragonfly_password; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->enable_ssl = $this->database->enable_ssl; $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function databaseProxyStopped() { $this->syncData(); } public function submit() { try { $this->authorize('update', $this->database); if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { if (is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } public function instantSaveSSL() { try { $this->authorize('update', $this->database); $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { return handleError($e, $this); } } public function regenerateSslCertificate() { try { $this->authorize('update', $this->database); $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { $this->dispatch('error', 'No existing SSL certificate found for this database.'); return; } $server = $this->database->destination->server; $caCert = $server->sslCertificates() ->where('is_ca_certificate', true) ->first(); if (! $caCert) { $server->generateCaCertificate(); $caCert = $server->sslCertificates()->where('is_ca_certificate', true)->first(); } if (! $caCert) { $this->dispatch('error', 'No CA certificate found for this database. Please generate a CA certificate for this server in the server/advanced page.'); return; } SslHelper::generateSslCertificate( commonName: $existingCert->commonName, subjectAlternativeNames: $existingCert->subjectAlternativeNames ?? [], resourceType: $existingCert->resource_type, resourceId: $existingCert->resource_id, serverId: $existingCert->server_id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $existingCert->configuration_dir, mountPath: $existingCert->mount_path, isPemKeyFileRequired: true, ); $this->dispatch('success', 'SSL certificates regenerated. Restart database to apply changes.'); } catch (Exception $e) { handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Database/Heading.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceStatusChanged" => 'checkStatus', "echo-private:team.{$teamId},ServiceChecked" => 'activityFinished', 'refresh' => '$refresh', 'compose_loaded' => '$refresh', 'update_links' => '$refresh', ]; } public function activityFinished() { try { // Only set started_at if database is actually running if ($this->database->isRunning()) { $this->database->started_at ??= now(); } $this->database->save(); if (is_null($this->database->config_hash) || $this->database->isConfigurationChanged()) { $this->database->isConfigurationChanged(true); } $this->dispatch('configurationChanged'); } catch (\Exception $e) { return handleError($e, $this); } finally { $this->dispatch('refresh'); } } public function checkStatus() { if ($this->database->destination->server->isFunctional()) { GetContainersStatus::dispatch($this->database->destination->server); } else { $this->dispatch('error', 'Server is not functional.'); } } public function manualCheckStatus() { $this->checkStatus(); } public function mount() { $this->parameters = [ 'project_uuid' => $this->database->environment->project->uuid, 'environment_uuid' => $this->database->environment->uuid, 'database_uuid' => $this->database->uuid, ]; } public function stop() { try { $this->authorize('manage', $this->database); $this->dispatch('info', 'Gracefully stopping database.'); StopDatabase::dispatch($this->database, false, $this->docker_cleanup); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } public function restart() { $this->authorize('manage', $this->database); $activity = RestartDatabase::run($this->database); $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function start() { $this->authorize('manage', $this->database); $activity = StartDatabase::run($this->database); $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function render() { return view('livewire.project.database.heading', [ 'checkboxes' => [ ['id' => 'docker_cleanup', 'label' => __('resource.docker_cleanup')], ], ]); } } ================================================ FILE: app/Livewire/Project/Database/Import.php ================================================ ', // Redirect '<', // Redirect "\n", // Newline "\r", // Carriage return "\0", // Null byte "'", // Single quote '"', // Double quote '\\', // Backslash ]; foreach ($dangerousPatterns as $pattern) { if (str_contains($path, $pattern)) { return false; } } // Allow alphanumerics, dots, dashes, underscores, slashes, spaces, plus, equals, at return preg_match('/^[a-zA-Z0-9.\-_\/\s+@=]+$/', $path) === 1; } /** * Validate that a string is safe for use as a file path on the server. */ private function validateServerPath(string $path): bool { // Must be an absolute path if (! str_starts_with($path, '/')) { return false; } // Must not contain dangerous shell metacharacters or command injection patterns $dangerousPatterns = [ '..', // Directory traversal '$(', // Command substitution '`', // Backtick command substitution '|', // Pipe ';', // Command separator '&', // Background/AND '>', // Redirect '<', // Redirect "\n", // Newline "\r", // Carriage return "\0", // Null byte "'", // Single quote '"', // Double quote '\\', // Backslash ]; foreach ($dangerousPatterns as $pattern) { if (str_contains($path, $pattern)) { return false; } } // Allow alphanumerics, dots, dashes, underscores, slashes, and spaces return preg_match('/^[a-zA-Z0-9.\-_\/\s]+$/', $path) === 1; } public bool $unsupported = false; // Store IDs instead of models for proper Livewire serialization public ?int $resourceId = null; public ?string $resourceType = null; public ?int $serverId = null; // View-friendly properties to avoid computed property access in Blade public string $resourceUuid = ''; public string $resourceStatus = ''; public string $resourceDbType = ''; public array $parameters = []; public array $containers = []; public bool $scpInProgress = false; public bool $importRunning = false; public ?string $filename = null; public ?string $filesize = null; public bool $isUploading = false; public int $progress = 0; public bool $error = false; public string $container; public array $importCommands = []; public bool $dumpAll = false; public string $restoreCommandText = ''; public string $customLocation = ''; public ?int $activityId = null; public string $postgresqlRestoreCommand = 'pg_restore -U $POSTGRES_USER -d ${POSTGRES_DB:-${POSTGRES_USER:-postgres}}'; public string $mysqlRestoreCommand = 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE'; public string $mariadbRestoreCommand = 'mariadb -u $MARIADB_USER -p$MARIADB_PASSWORD $MARIADB_DATABASE'; public string $mongodbRestoreCommand = 'mongorestore --authenticationDatabase=admin --username $MONGO_INITDB_ROOT_USERNAME --password $MONGO_INITDB_ROOT_PASSWORD --uri mongodb://localhost:27017 --gzip --archive='; // S3 Restore properties public array $availableS3Storages = []; public ?int $s3StorageId = null; public string $s3Path = ''; public ?int $s3FileSize = null; #[Computed] public function resource() { if ($this->resourceId === null || $this->resourceType === null) { return null; } return $this->resourceType::find($this->resourceId); } #[Computed] public function server() { if ($this->serverId === null) { return null; } return Server::find($this->serverId); } public function getListeners() { $userId = Auth::id(); return [ "echo-private:user.{$userId},DatabaseStatusChanged" => '$refresh', 'slideOverClosed' => 'resetActivityId', ]; } public function resetActivityId() { $this->activityId = null; } public function mount() { $this->parameters = get_route_parameters(); $this->getContainers(); $this->loadAvailableS3Storages(); } public function updatedDumpAll($value) { $morphClass = $this->resource->getMorphClass(); // Handle ServiceDatabase by checking the database type if ($morphClass === \App\Models\ServiceDatabase::class) { $dbType = $this->resource->databaseType(); if (str_contains($dbType, 'mysql')) { $morphClass = 'mysql'; } elseif (str_contains($dbType, 'mariadb')) { $morphClass = 'mariadb'; } elseif (str_contains($dbType, 'postgres')) { $morphClass = 'postgresql'; } } switch ($morphClass) { case \App\Models\StandaloneMariadb::class: case 'mariadb': if ($value === true) { $this->mariadbRestoreCommand = <<<'EOD' for pid in $(mariadb -u root -p$MARIADB_ROOT_PASSWORD -N -e "SELECT id FROM information_schema.processlist WHERE user != 'root';"); do mariadb -u root -p$MARIADB_ROOT_PASSWORD -e "KILL $pid" 2>/dev/null || true done && \ mariadb -u root -p$MARIADB_ROOT_PASSWORD -N -e "SELECT CONCAT('DROP DATABASE IF EXISTS \`',schema_name,'\`;') FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema','sys');" | mariadb -u root -p$MARIADB_ROOT_PASSWORD && \ mariadb -u root -p$MARIADB_ROOT_PASSWORD -e "CREATE DATABASE IF NOT EXISTS \`${MARIADB_DATABASE:-default}\`;" && \ (gunzip -cf $tmpPath 2>/dev/null || cat $tmpPath) | sed -e '/^CREATE DATABASE/d' -e '/^USE \`mysql\`/d' | mariadb -u root -p$MARIADB_ROOT_PASSWORD ${MARIADB_DATABASE:-default} EOD; $this->restoreCommandText = $this->mariadbRestoreCommand.' && (gunzip -cf 2>/dev/null || cat ) | mariadb -u root -p$MARIADB_ROOT_PASSWORD ${MARIADB_DATABASE:-default}'; } else { $this->mariadbRestoreCommand = 'mariadb -u $MARIADB_USER -p$MARIADB_PASSWORD $MARIADB_DATABASE'; } break; case \App\Models\StandaloneMysql::class: case 'mysql': if ($value === true) { $this->mysqlRestoreCommand = <<<'EOD' for pid in $(mysql -u root -p$MYSQL_ROOT_PASSWORD -N -e "SELECT id FROM information_schema.processlist WHERE user != 'root';"); do mysql -u root -p$MYSQL_ROOT_PASSWORD -e "KILL $pid" 2>/dev/null || true done && \ mysql -u root -p$MYSQL_ROOT_PASSWORD -N -e "SELECT CONCAT('DROP DATABASE IF EXISTS \`',schema_name,'\`;') FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema','sys');" | mysql -u root -p$MYSQL_ROOT_PASSWORD && \ mysql -u root -p$MYSQL_ROOT_PASSWORD -e "CREATE DATABASE IF NOT EXISTS \`${MYSQL_DATABASE:-default}\`;" && \ (gunzip -cf $tmpPath 2>/dev/null || cat $tmpPath) | sed -e '/^CREATE DATABASE/d' -e '/^USE \`mysql\`/d' | mysql -u root -p$MYSQL_ROOT_PASSWORD ${MYSQL_DATABASE:-default} EOD; $this->restoreCommandText = $this->mysqlRestoreCommand.' && (gunzip -cf 2>/dev/null || cat ) | mysql -u root -p$MYSQL_ROOT_PASSWORD ${MYSQL_DATABASE:-default}'; } else { $this->mysqlRestoreCommand = 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE'; } break; case \App\Models\StandalonePostgresql::class: case 'postgresql': if ($value === true) { $this->postgresqlRestoreCommand = <<<'EOD' psql -U ${POSTGRES_USER} -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname IS NOT NULL AND pid <> pg_backend_pid()" && \ psql -U ${POSTGRES_USER} -t -c "SELECT datname FROM pg_database WHERE NOT datistemplate" | xargs -I {} dropdb -U ${POSTGRES_USER} --if-exists {} && \ createdb -U ${POSTGRES_USER} ${POSTGRES_DB:-${POSTGRES_USER:-postgres}} EOD; $this->restoreCommandText = $this->postgresqlRestoreCommand.' && (gunzip -cf 2>/dev/null || cat ) | psql -U ${POSTGRES_USER} -d ${POSTGRES_DB:-${POSTGRES_USER:-postgres}}'; } else { $this->postgresqlRestoreCommand = 'pg_restore -U ${POSTGRES_USER} -d ${POSTGRES_DB:-${POSTGRES_USER:-postgres}}'; } break; } } public function getContainers() { $this->containers = []; $teamId = data_get(auth()->user()->currentTeam(), 'id'); // Try to find resource by route parameter $databaseUuid = data_get($this->parameters, 'database_uuid'); $stackServiceUuid = data_get($this->parameters, 'stack_service_uuid'); $resource = null; if ($databaseUuid) { // Standalone database route $resource = getResourceByUuid($databaseUuid, $teamId); if (is_null($resource)) { abort(404); } } elseif ($stackServiceUuid) { // ServiceDatabase route - look up the service database $serviceUuid = data_get($this->parameters, 'service_uuid'); $service = Service::whereUuid($serviceUuid)->first(); if (! $service) { abort(404); } $resource = $service->databases()->whereUuid($stackServiceUuid)->first(); if (is_null($resource)) { abort(404); } } else { abort(404); } $this->authorize('view', $resource); // Store IDs for Livewire serialization $this->resourceId = $resource->id; $this->resourceType = get_class($resource); // Store view-friendly properties $this->resourceStatus = $resource->status ?? ''; // Handle ServiceDatabase server access differently if ($resource->getMorphClass() === \App\Models\ServiceDatabase::class) { $server = $resource->service?->server; if (! $server) { abort(404, 'Server not found for this service database.'); } $this->serverId = $server->id; $this->container = $resource->name.'-'.$resource->service->uuid; $this->resourceUuid = $resource->uuid; // Use ServiceDatabase's own UUID // Determine database type for ServiceDatabase $dbType = $resource->databaseType(); if (str_contains($dbType, 'postgres')) { $this->resourceDbType = 'standalone-postgresql'; } elseif (str_contains($dbType, 'mysql')) { $this->resourceDbType = 'standalone-mysql'; } elseif (str_contains($dbType, 'mariadb')) { $this->resourceDbType = 'standalone-mariadb'; } elseif (str_contains($dbType, 'mongo')) { $this->resourceDbType = 'standalone-mongodb'; } else { $this->resourceDbType = $dbType; } } else { $server = $resource->destination?->server; if (! $server) { abort(404, 'Server not found for this database.'); } $this->serverId = $server->id; $this->container = $resource->uuid; $this->resourceUuid = $resource->uuid; $this->resourceDbType = $resource->type(); } if (str($resource->status)->startsWith('running')) { $this->containers[] = $this->container; } if ( $resource->getMorphClass() === \App\Models\StandaloneRedis::class || $resource->getMorphClass() === \App\Models\StandaloneKeydb::class || $resource->getMorphClass() === \App\Models\StandaloneDragonfly::class || $resource->getMorphClass() === \App\Models\StandaloneClickhouse::class ) { $this->unsupported = true; } // Mark unsupported ServiceDatabase types (Redis, KeyDB, etc.) if ($resource->getMorphClass() === \App\Models\ServiceDatabase::class) { $dbType = $resource->databaseType(); if (str_contains($dbType, 'redis') || str_contains($dbType, 'keydb') || str_contains($dbType, 'dragonfly') || str_contains($dbType, 'clickhouse')) { $this->unsupported = true; } } } public function checkFile() { if (filled($this->customLocation)) { // Validate the custom location to prevent command injection if (! $this->validateServerPath($this->customLocation)) { $this->dispatch('error', 'Invalid file path. Path must be absolute and contain only safe characters (alphanumerics, dots, dashes, underscores, slashes).'); return; } if (! $this->server) { $this->dispatch('error', 'Server not found. Please refresh the page.'); return; } try { $escapedPath = escapeshellarg($this->customLocation); $result = instant_remote_process(["ls -l {$escapedPath}"], $this->server, throwError: false); if (blank($result)) { $this->dispatch('error', 'The file does not exist or has been deleted.'); return; } $this->filename = $this->customLocation; $this->dispatch('success', 'The file exists.'); } catch (\Throwable $e) { return handleError($e, $this); } } } public function runImport(string $password = ''): bool|string { if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } $this->authorize('update', $this->resource); if ($this->filename === '') { $this->dispatch('error', 'Please select a file to import.'); return true; } if (! $this->server) { $this->dispatch('error', 'Server not found. Please refresh the page.'); return true; } try { $this->importRunning = true; $this->importCommands = []; $backupFileName = "upload/{$this->resourceUuid}/restore"; // Check if an uploaded file exists first (takes priority over custom location) if (Storage::exists($backupFileName)) { $path = Storage::path($backupFileName); $tmpPath = '/tmp/'.basename($backupFileName).'_'.$this->resourceUuid; instant_scp($path, $tmpPath, $this->server); Storage::delete($backupFileName); $this->importCommands[] = "docker cp {$tmpPath} {$this->container}:{$tmpPath}"; } elseif (filled($this->customLocation)) { // Validate the custom location to prevent command injection if (! $this->validateServerPath($this->customLocation)) { $this->dispatch('error', 'Invalid file path. Path must be absolute and contain only safe characters.'); return true; } $tmpPath = '/tmp/restore_'.$this->resourceUuid; $escapedCustomLocation = escapeshellarg($this->customLocation); $this->importCommands[] = "docker cp {$escapedCustomLocation} {$this->container}:{$tmpPath}"; } else { $this->dispatch('error', 'The file does not exist or has been deleted.'); return true; } // Copy the restore command to a script file $scriptPath = "/tmp/restore_{$this->resourceUuid}.sh"; $restoreCommand = $this->buildRestoreCommand($tmpPath); $restoreCommandBase64 = base64_encode($restoreCommand); $this->importCommands[] = "echo \"{$restoreCommandBase64}\" | base64 -d > {$scriptPath}"; $this->importCommands[] = "chmod +x {$scriptPath}"; $this->importCommands[] = "docker cp {$scriptPath} {$this->container}:{$scriptPath}"; $this->importCommands[] = "docker exec {$this->container} sh -c '{$scriptPath}'"; $this->importCommands[] = "docker exec {$this->container} sh -c 'echo \"Import finished with exit code $?\"'"; if (! empty($this->importCommands)) { $activity = remote_process($this->importCommands, $this->server, ignore_errors: true, callEventOnFinish: 'RestoreJobFinished', callEventData: [ 'scriptPath' => $scriptPath, 'tmpPath' => $tmpPath, 'container' => $this->container, 'serverId' => $this->server->id, ]); // Track the activity ID $this->activityId = $activity->id; // Dispatch activity to the monitor and open slide-over $this->dispatch('activityMonitor', $activity->id); $this->dispatch('databaserestore'); } } catch (\Throwable $e) { handleError($e, $this); return true; } finally { $this->filename = null; $this->importCommands = []; } return true; } public function loadAvailableS3Storages() { try { $this->availableS3Storages = S3Storage::ownedByCurrentTeam(['id', 'name', 'description']) ->where('is_usable', true) ->get() ->map(fn ($s) => ['id' => $s->id, 'name' => $s->name, 'description' => $s->description]) ->toArray(); } catch (\Throwable $e) { $this->availableS3Storages = []; } } public function updatedS3Path($value) { // Reset validation state when path changes $this->s3FileSize = null; // Ensure path starts with a slash if ($value !== null && $value !== '') { $this->s3Path = str($value)->trim()->start('/')->value(); } } public function updatedS3StorageId() { // Reset validation state when storage changes $this->s3FileSize = null; } public function checkS3File() { if (! $this->s3StorageId) { $this->dispatch('error', 'Please select an S3 storage.'); return; } if (blank($this->s3Path)) { $this->dispatch('error', 'Please provide an S3 path.'); return; } // Clean the path (remove leading slash if present) $cleanPath = ltrim($this->s3Path, '/'); // Validate the S3 path early to prevent command injection in subsequent operations if (! $this->validateS3Path($cleanPath)) { $this->dispatch('error', 'Invalid S3 path. Path must contain only safe characters (alphanumerics, dots, dashes, underscores, slashes).'); return; } try { $s3Storage = S3Storage::ownedByCurrentTeam()->findOrFail($this->s3StorageId); // Validate bucket name early if (! $this->validateBucketName($s3Storage->bucket)) { $this->dispatch('error', 'Invalid S3 bucket name. Bucket name must contain only alphanumerics, dots, dashes, and underscores.'); return; } // Test connection $s3Storage->testConnection(); // Build S3 disk configuration $disk = Storage::build([ 'driver' => 's3', 'region' => $s3Storage->region, 'key' => $s3Storage->key, 'secret' => $s3Storage->secret, 'bucket' => $s3Storage->bucket, 'endpoint' => $s3Storage->endpoint, 'use_path_style_endpoint' => true, ]); // Check if file exists if (! $disk->exists($cleanPath)) { $this->dispatch('error', 'File not found in S3. Please check the path.'); return; } // Get file size $this->s3FileSize = $disk->size($cleanPath); $this->dispatch('success', 'File found in S3. Size: '.formatBytes($this->s3FileSize)); } catch (\Throwable $e) { $this->s3FileSize = null; return handleError($e, $this); } } public function restoreFromS3(string $password = ''): bool|string { if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } $this->authorize('update', $this->resource); if (! $this->s3StorageId || blank($this->s3Path)) { $this->dispatch('error', 'Please select S3 storage and provide a path first.'); return true; } if (is_null($this->s3FileSize)) { $this->dispatch('error', 'Please check the file first by clicking "Check File".'); return true; } if (! $this->server) { $this->dispatch('error', 'Server not found. Please refresh the page.'); return true; } try { $this->importRunning = true; $s3Storage = S3Storage::ownedByCurrentTeam()->findOrFail($this->s3StorageId); $key = $s3Storage->key; $secret = $s3Storage->secret; $bucket = $s3Storage->bucket; $endpoint = $s3Storage->endpoint; // Validate bucket name to prevent command injection if (! $this->validateBucketName($bucket)) { $this->dispatch('error', 'Invalid S3 bucket name. Bucket name must contain only alphanumerics, dots, dashes, and underscores.'); return true; } // Clean the S3 path $cleanPath = ltrim($this->s3Path, '/'); // Validate the S3 path to prevent command injection if (! $this->validateS3Path($cleanPath)) { $this->dispatch('error', 'Invalid S3 path. Path must contain only safe characters (alphanumerics, dots, dashes, underscores, slashes).'); return true; } // Get helper image $helperImage = config('constants.coolify.helper_image'); $latestVersion = getHelperVersion(); $fullImageName = "{$helperImage}:{$latestVersion}"; // Get the database destination network if ($this->resource->getMorphClass() === \App\Models\ServiceDatabase::class) { $destinationNetwork = $this->resource->service->destination->network ?? 'coolify'; } else { $destinationNetwork = $this->resource->destination->network ?? 'coolify'; } // Generate unique names for this operation $containerName = "s3-restore-{$this->resourceUuid}"; $helperTmpPath = '/tmp/'.basename($cleanPath); $serverTmpPath = "/tmp/s3-restore-{$this->resourceUuid}-".basename($cleanPath); $containerTmpPath = "/tmp/restore_{$this->resourceUuid}-".basename($cleanPath); $scriptPath = "/tmp/restore_{$this->resourceUuid}.sh"; // Prepare all commands in sequence $commands = []; // 1. Clean up any existing helper container and temp files from previous runs $commands[] = "docker rm -f {$containerName} 2>/dev/null || true"; $commands[] = "rm -f {$serverTmpPath} 2>/dev/null || true"; $commands[] = "docker exec {$this->container} rm -f {$containerTmpPath} {$scriptPath} 2>/dev/null || true"; // 2. Start helper container on the database network $commands[] = "docker run -d --network {$destinationNetwork} --name {$containerName} {$fullImageName} sleep 3600"; // 3. Configure S3 access in helper container $escapedEndpoint = escapeshellarg($endpoint); $escapedKey = escapeshellarg($key); $escapedSecret = escapeshellarg($secret); $commands[] = "docker exec {$containerName} mc alias set s3temp {$escapedEndpoint} {$escapedKey} {$escapedSecret}"; // 4. Check file exists in S3 (bucket and path already validated above) $escapedBucket = escapeshellarg($bucket); $escapedCleanPath = escapeshellarg($cleanPath); $escapedS3Source = escapeshellarg("s3temp/{$bucket}/{$cleanPath}"); $commands[] = "docker exec {$containerName} mc stat {$escapedS3Source}"; // 5. Download from S3 to helper container (progress shown by default) $escapedHelperTmpPath = escapeshellarg($helperTmpPath); $commands[] = "docker exec {$containerName} mc cp {$escapedS3Source} {$escapedHelperTmpPath}"; // 6. Copy from helper to server, then immediately to database container $commands[] = "docker cp {$containerName}:{$helperTmpPath} {$serverTmpPath}"; $commands[] = "docker cp {$serverTmpPath} {$this->container}:{$containerTmpPath}"; // 7. Cleanup helper container and server temp file immediately (no longer needed) $commands[] = "docker rm -f {$containerName} 2>/dev/null || true"; $commands[] = "rm -f {$serverTmpPath} 2>/dev/null || true"; // 8. Build and execute restore command inside database container $restoreCommand = $this->buildRestoreCommand($containerTmpPath); $restoreCommandBase64 = base64_encode($restoreCommand); $commands[] = "echo \"{$restoreCommandBase64}\" | base64 -d > {$scriptPath}"; $commands[] = "chmod +x {$scriptPath}"; $commands[] = "docker cp {$scriptPath} {$this->container}:{$scriptPath}"; // 9. Execute restore and cleanup temp files immediately after completion $commands[] = "docker exec {$this->container} sh -c '{$scriptPath} && rm -f {$containerTmpPath} {$scriptPath}'"; $commands[] = "docker exec {$this->container} sh -c 'echo \"Import finished with exit code $?\"'"; // Execute all commands with cleanup event (as safety net for edge cases) $activity = remote_process($commands, $this->server, ignore_errors: true, callEventOnFinish: 'S3RestoreJobFinished', callEventData: [ 'containerName' => $containerName, 'serverTmpPath' => $serverTmpPath, 'scriptPath' => $scriptPath, 'containerTmpPath' => $containerTmpPath, 'container' => $this->container, 'serverId' => $this->server->id, ]); // Track the activity ID $this->activityId = $activity->id; // Dispatch activity to the monitor and open slide-over $this->dispatch('activityMonitor', $activity->id); $this->dispatch('databaserestore'); $this->dispatch('info', 'Restoring database from S3. Progress will be shown in the activity monitor...'); } catch (\Throwable $e) { $this->importRunning = false; handleError($e, $this); return true; } return true; } public function buildRestoreCommand(string $tmpPath): string { $morphClass = $this->resource->getMorphClass(); // Handle ServiceDatabase by checking the database type if ($morphClass === \App\Models\ServiceDatabase::class) { $dbType = $this->resource->databaseType(); if (str_contains($dbType, 'mysql')) { $morphClass = 'mysql'; } elseif (str_contains($dbType, 'mariadb')) { $morphClass = 'mariadb'; } elseif (str_contains($dbType, 'postgres')) { $morphClass = 'postgresql'; } elseif (str_contains($dbType, 'mongo')) { $morphClass = 'mongodb'; } } switch ($morphClass) { case \App\Models\StandaloneMariadb::class: case 'mariadb': $restoreCommand = $this->mariadbRestoreCommand; if ($this->dumpAll) { $restoreCommand .= " && (gunzip -cf {$tmpPath} 2>/dev/null || cat {$tmpPath}) | mariadb -u root -p\$MARIADB_ROOT_PASSWORD \${MARIADB_DATABASE:-default}"; } else { $restoreCommand .= " < {$tmpPath}"; } break; case \App\Models\StandaloneMysql::class: case 'mysql': $restoreCommand = $this->mysqlRestoreCommand; if ($this->dumpAll) { $restoreCommand .= " && (gunzip -cf {$tmpPath} 2>/dev/null || cat {$tmpPath}) | mysql -u root -p\$MYSQL_ROOT_PASSWORD \${MYSQL_DATABASE:-default}"; } else { $restoreCommand .= " < {$tmpPath}"; } break; case \App\Models\StandalonePostgresql::class: case 'postgresql': $restoreCommand = $this->postgresqlRestoreCommand; if ($this->dumpAll) { $restoreCommand .= " && (gunzip -cf {$tmpPath} 2>/dev/null || cat {$tmpPath}) | psql -U \${POSTGRES_USER} -d \${POSTGRES_DB:-\${POSTGRES_USER:-postgres}}"; } else { $restoreCommand .= " {$tmpPath}"; } break; case \App\Models\StandaloneMongodb::class: case 'mongodb': $restoreCommand = $this->mongodbRestoreCommand; if ($this->dumpAll === false) { $restoreCommand .= "{$tmpPath}"; } break; default: $restoreCommand = ''; } return $restoreCommand; } } ================================================ FILE: app/Livewire/Project/Database/InitScript.php ================================================ index = data_get($this->script, 'index'); $this->filename = data_get($this->script, 'filename'); $this->content = data_get($this->script, 'content'); } catch (Exception $e) { return handleError($e, $this); } } public function submit() { try { $this->validate(); $this->script['index'] = $this->index; $this->script['content'] = $this->content; $this->script['filename'] = $this->filename; $this->dispatch('save_init_script', $this->script); } catch (Exception $e) { return handleError($e, $this); } } public function delete() { try { $this->dispatch('delete_init_script', $this->script); } catch (Exception $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Database/Keydb/General.php ================================================ currentTeam()->id; return [ "echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped', "echo-private:user.{$userId},DatabaseStatusChanged" => '$refresh', ]; } public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } $existingCert = $this->database->sslCertificates()->first(); if ($existingCert) { $this->certificateValidUntil = $existingCert->valid_until; } } catch (\Throwable $e) { return handleError($e, $this); } } protected function rules(): array { $baseRules = [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'keydbConf' => 'nullable|string', 'keydbPassword' => 'required|string', 'image' => 'required|string', 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', 'isLogDrainEnabled' => 'nullable|boolean', 'enable_ssl' => 'boolean', ]; return $baseRules; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'keydbPassword.required' => 'The KeyDB Password field is required.', 'keydbPassword.string' => 'The KeyDB Password must be a string.', 'image.required' => 'The Docker Image field is required.', 'image.string' => 'The Docker Image must be a string.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', ] ); } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->keydb_conf = $this->keydbConf; $this->database->keydb_password = $this->keydbPassword; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->enable_ssl = $this->enable_ssl; $this->database->save(); $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->keydbConf = $this->database->keydb_conf; $this->keydbPassword = $this->database->keydb_password; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->enable_ssl = $this->database->enable_ssl; $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function databaseProxyStopped() { $this->syncData(); } public function submit() { try { $this->authorize('manageEnvironment', $this->database); if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { if (is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } public function instantSaveSSL() { try { $this->authorize('update', $this->database); $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { return handleError($e, $this); } } public function regenerateSslCertificate() { try { $this->authorize('update', $this->database); $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { $this->dispatch('error', 'No existing SSL certificate found for this database.'); return; } $caCert = $this->server->sslCertificates() ->where('is_ca_certificate', true) ->first(); SslHelper::generateSslCertificate( commonName: $existingCert->commonName, subjectAlternativeNames: $existingCert->subjectAlternativeNames ?? [], resourceType: $existingCert->resource_type, resourceId: $existingCert->resource_id, serverId: $existingCert->server_id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $existingCert->configuration_dir, mountPath: $existingCert->mount_path, isPemKeyFileRequired: true, ); $this->dispatch('success', 'SSL certificates regenerated. Restart database to apply changes.'); } catch (Exception $e) { handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Database/Mariadb/General.php ================================================ '$refresh', ]; } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'mariadbRootPassword' => 'required', 'mariadbUser' => 'required', 'mariadbPassword' => 'required', 'mariadbDatabase' => 'required', 'mariadbConf' => 'nullable', 'image' => 'required', 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', 'mariadbRootPassword.required' => 'The Root Password field is required.', 'mariadbUser.required' => 'The MariaDB User field is required.', 'mariadbPassword.required' => 'The MariaDB Password field is required.', 'mariadbDatabase.required' => 'The MariaDB Database field is required.', 'image.required' => 'The Docker Image field is required.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', ] ); } protected $validationAttributes = [ 'name' => 'Name', 'description' => 'Description', 'mariadbRootPassword' => 'Root Password', 'mariadbUser' => 'User', 'mariadbPassword' => 'Password', 'mariadbDatabase' => 'Database', 'mariadbConf' => 'MariaDB Configuration', 'image' => 'Image', 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', 'publicPortTimeout' => 'Public Port Timeout', 'customDockerRunOptions' => 'Custom Docker Options', 'enableSsl' => 'Enable SSL', ]; public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } $existingCert = $this->database->sslCertificates()->first(); if ($existingCert) { $this->certificateValidUntil = $existingCert->valid_until; } } catch (Exception $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->mariadb_root_password = $this->mariadbRootPassword; $this->database->mariadb_user = $this->mariadbUser; $this->database->mariadb_password = $this->mariadbPassword; $this->database->mariadb_database = $this->mariadbDatabase; $this->database->mariadb_conf = $this->mariadbConf; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; $this->database->save(); $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->mariadbRootPassword = $this->database->mariadb_root_password; $this->mariadbUser = $this->database->mariadb_user; $this->mariadbPassword = $this->database->mariadb_password; $this->mariadbDatabase = $this->database->mariadb_database; $this->mariadbConf = $this->database->mariadb_conf; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->database); if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { if (is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function instantSaveSSL() { try { $this->authorize('update', $this->database); $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { return handleError($e, $this); } } public function regenerateSslCertificate() { try { $this->authorize('update', $this->database); $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { $this->dispatch('error', 'No existing SSL certificate found for this database.'); return; } $caCert = $this->server->sslCertificates()->where('is_ca_certificate', true)->first(); SslHelper::generateSslCertificate( commonName: $existingCert->common_name, subjectAlternativeNames: $existingCert->subject_alternative_names ?? [], resourceType: $existingCert->resource_type, resourceId: $existingCert->resource_id, serverId: $existingCert->server_id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $existingCert->configuration_dir, mountPath: $existingCert->mount_path, isPemKeyFileRequired: true, ); $this->dispatch('success', 'SSL certificates have been regenerated. Please restart the database for changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function refresh(): void { $this->database->refresh(); $this->syncData(); } public function render() { return view('livewire.project.database.mariadb.general'); } } ================================================ FILE: app/Livewire/Project/Database/Mongodb/General.php ================================================ '$refresh', ]; } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'mongoConf' => 'nullable', 'mongoInitdbRootUsername' => 'required', 'mongoInitdbRootPassword' => 'required', 'mongoInitdbDatabase' => 'required', 'image' => 'required', 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', 'sslMode' => 'nullable|string|in:allow,prefer,require,verify-full', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', 'mongoInitdbRootUsername.required' => 'The Root Username field is required.', 'mongoInitdbRootPassword.required' => 'The Root Password field is required.', 'mongoInitdbDatabase.required' => 'The MongoDB Database field is required.', 'image.required' => 'The Docker Image field is required.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', 'sslMode.in' => 'The SSL Mode must be one of: allow, prefer, require, verify-full.', ] ); } protected $validationAttributes = [ 'name' => 'Name', 'description' => 'Description', 'mongoConf' => 'Mongo Configuration', 'mongoInitdbRootUsername' => 'Root Username', 'mongoInitdbRootPassword' => 'Root Password', 'mongoInitdbDatabase' => 'Database', 'image' => 'Image', 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', 'publicPortTimeout' => 'Public Port Timeout', 'customDockerRunOptions' => 'Custom Docker Run Options', 'enableSsl' => 'Enable SSL', 'sslMode' => 'SSL Mode', ]; public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } $existingCert = $this->database->sslCertificates()->first(); if ($existingCert) { $this->certificateValidUntil = $existingCert->valid_until; } } catch (Exception $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->mongo_conf = $this->mongoConf; $this->database->mongo_initdb_root_username = $this->mongoInitdbRootUsername; $this->database->mongo_initdb_root_password = $this->mongoInitdbRootPassword; $this->database->mongo_initdb_database = $this->mongoInitdbDatabase; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; $this->database->ssl_mode = $this->sslMode; $this->database->save(); $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->mongoConf = $this->database->mongo_conf; $this->mongoInitdbRootUsername = $this->database->mongo_initdb_root_username; $this->mongoInitdbRootPassword = $this->database->mongo_initdb_root_password; $this->mongoInitdbDatabase = $this->database->mongo_initdb_database; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; $this->sslMode = $this->database->ssl_mode; $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->database); if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } if (str($this->mongoConf)->isEmpty()) { $this->mongoConf = null; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { if (is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function updatedSslMode() { $this->instantSaveSSL(); } public function instantSaveSSL() { try { $this->authorize('update', $this->database); $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { return handleError($e, $this); } } public function regenerateSslCertificate() { try { $this->authorize('update', $this->database); $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { $this->dispatch('error', 'No existing SSL certificate found for this database.'); return; } $caCert = $this->server->sslCertificates()->where('is_ca_certificate', true)->first(); SslHelper::generateSslCertificate( commonName: $existingCert->common_name, subjectAlternativeNames: $existingCert->subject_alternative_names ?? [], resourceType: $existingCert->resource_type, resourceId: $existingCert->resource_id, serverId: $existingCert->server_id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $existingCert->configuration_dir, mountPath: $existingCert->mount_path, isPemKeyFileRequired: true, ); $this->dispatch('success', 'SSL certificates have been regenerated. Please restart the database for changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function refresh(): void { $this->database->refresh(); $this->syncData(); } public function render() { return view('livewire.project.database.mongodb.general'); } } ================================================ FILE: app/Livewire/Project/Database/Mysql/General.php ================================================ '$refresh', ]; } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'mysqlRootPassword' => 'required', 'mysqlUser' => 'required', 'mysqlPassword' => 'required', 'mysqlDatabase' => 'required', 'mysqlConf' => 'nullable', 'image' => 'required', 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', 'sslMode' => 'nullable|string|in:PREFERRED,REQUIRED,VERIFY_CA,VERIFY_IDENTITY', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', 'mysqlRootPassword.required' => 'The Root Password field is required.', 'mysqlUser.required' => 'The MySQL User field is required.', 'mysqlPassword.required' => 'The MySQL Password field is required.', 'mysqlDatabase.required' => 'The MySQL Database field is required.', 'image.required' => 'The Docker Image field is required.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', 'sslMode.in' => 'The SSL Mode must be one of: PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY.', ] ); } protected $validationAttributes = [ 'name' => 'Name', 'description' => 'Description', 'mysqlRootPassword' => 'Root Password', 'mysqlUser' => 'User', 'mysqlPassword' => 'Password', 'mysqlDatabase' => 'Database', 'mysqlConf' => 'MySQL Configuration', 'image' => 'Image', 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', 'publicPortTimeout' => 'Public Port Timeout', 'customDockerRunOptions' => 'Custom Docker Run Options', 'enableSsl' => 'Enable SSL', 'sslMode' => 'SSL Mode', ]; public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } $existingCert = $this->database->sslCertificates()->first(); if ($existingCert) { $this->certificateValidUntil = $existingCert->valid_until; } } catch (Exception $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->mysql_root_password = $this->mysqlRootPassword; $this->database->mysql_user = $this->mysqlUser; $this->database->mysql_password = $this->mysqlPassword; $this->database->mysql_database = $this->mysqlDatabase; $this->database->mysql_conf = $this->mysqlConf; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; $this->database->ssl_mode = $this->sslMode; $this->database->save(); $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->mysqlRootPassword = $this->database->mysql_root_password; $this->mysqlUser = $this->database->mysql_user; $this->mysqlPassword = $this->database->mysql_password; $this->mysqlDatabase = $this->database->mysql_database; $this->mysqlConf = $this->database->mysql_conf; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; $this->sslMode = $this->database->ssl_mode; $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->database); if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { if (is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function updatedSslMode() { $this->instantSaveSSL(); } public function instantSaveSSL() { try { $this->authorize('update', $this->database); $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { return handleError($e, $this); } } public function regenerateSslCertificate() { try { $this->authorize('update', $this->database); $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { $this->dispatch('error', 'No existing SSL certificate found for this database.'); return; } $caCert = $this->server->sslCertificates()->where('is_ca_certificate', true)->first(); SslHelper::generateSslCertificate( commonName: $existingCert->common_name, subjectAlternativeNames: $existingCert->subject_alternative_names ?? [], resourceType: $existingCert->resource_type, resourceId: $existingCert->resource_id, serverId: $existingCert->server_id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $existingCert->configuration_dir, mountPath: $existingCert->mount_path, isPemKeyFileRequired: true, ); $this->dispatch('success', 'SSL certificates have been regenerated. Please restart the database for changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function refresh(): void { $this->database->refresh(); $this->syncData(); } public function render() { return view('livewire.project.database.mysql.general'); } } ================================================ FILE: app/Livewire/Project/Database/Postgresql/General.php ================================================ '$refresh', 'save_init_script', 'delete_init_script', ]; } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'postgresUser' => 'required', 'postgresPassword' => 'required', 'postgresDb' => 'required', 'postgresInitdbArgs' => 'nullable', 'postgresHostAuthMethod' => 'nullable', 'postgresConf' => 'nullable', 'initScripts' => 'nullable', 'image' => 'required', 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', 'sslMode' => 'nullable|string|in:allow,prefer,require,verify-ca,verify-full', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', 'postgresUser.required' => 'The Postgres User field is required.', 'postgresPassword.required' => 'The Postgres Password field is required.', 'postgresDb.required' => 'The Postgres Database field is required.', 'image.required' => 'The Docker Image field is required.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', 'sslMode.in' => 'The SSL Mode must be one of: allow, prefer, require, verify-ca, verify-full.', ] ); } protected $validationAttributes = [ 'name' => 'Name', 'description' => 'Description', 'postgresUser' => 'Postgres User', 'postgresPassword' => 'Postgres Password', 'postgresDb' => 'Postgres DB', 'postgresInitdbArgs' => 'Postgres Initdb Args', 'postgresHostAuthMethod' => 'Postgres Host Auth Method', 'postgresConf' => 'Postgres Configuration', 'initScripts' => 'Init Scripts', 'image' => 'Image', 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', 'publicPortTimeout' => 'Public Port Timeout', 'customDockerRunOptions' => 'Custom Docker Run Options', 'enableSsl' => 'Enable SSL', 'sslMode' => 'SSL Mode', ]; public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } $existingCert = $this->database->sslCertificates()->first(); if ($existingCert) { $this->certificateValidUntil = $existingCert->valid_until; } } catch (Exception $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->postgres_user = $this->postgresUser; $this->database->postgres_password = $this->postgresPassword; $this->database->postgres_db = $this->postgresDb; $this->database->postgres_initdb_args = $this->postgresInitdbArgs; $this->database->postgres_host_auth_method = $this->postgresHostAuthMethod; $this->database->postgres_conf = $this->postgresConf; $this->database->init_scripts = $this->initScripts; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; $this->database->ssl_mode = $this->sslMode; $this->database->save(); $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->postgresUser = $this->database->postgres_user; $this->postgresPassword = $this->database->postgres_password; $this->postgresDb = $this->database->postgres_db; $this->postgresInitdbArgs = $this->database->postgres_initdb_args; $this->postgresHostAuthMethod = $this->database->postgres_host_auth_method; $this->postgresConf = $this->database->postgres_conf; $this->initScripts = $this->database->init_scripts; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; $this->sslMode = $this->database->ssl_mode; $this->db_url = $this->database->internal_db_url; $this->db_url_public = $this->database->external_db_url; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function updatedSslMode() { $this->instantSaveSSL(); } public function instantSaveSSL() { try { $this->authorize('update', $this->database); $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { return handleError($e, $this); } } public function regenerateSslCertificate() { try { $this->authorize('update', $this->database); $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { $this->dispatch('error', 'No existing SSL certificate found for this database.'); return; } $caCert = $this->server->sslCertificates()->where('is_ca_certificate', true)->first(); SslHelper::generateSslCertificate( commonName: $existingCert->common_name, subjectAlternativeNames: $existingCert->subject_alternative_names ?? [], resourceType: $existingCert->resource_type, resourceId: $existingCert->resource_id, serverId: $existingCert->server_id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $existingCert->configuration_dir, mountPath: $existingCert->mount_path, isPemKeyFileRequired: true, ); $this->dispatch('success', 'SSL certificates have been regenerated. Please restart the database for changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function save_init_script($script) { $this->authorize('update', $this->database); $initScripts = collect($this->initScripts ?? []); $existingScript = $initScripts->firstWhere('filename', $script['filename']); $oldScript = $initScripts->firstWhere('index', $script['index']); if ($existingScript && $existingScript['index'] !== $script['index']) { $this->dispatch('error', 'A script with this filename already exists.'); return; } $container_name = $this->database->uuid; $configuration_dir = database_configuration_dir().'/'.$container_name; if ($oldScript && $oldScript['filename'] !== $script['filename']) { try { // Validate and escape filename to prevent command injection validateShellSafePath($oldScript['filename'], 'init script filename'); $old_file_path = "$configuration_dir/docker-entrypoint-initdb.d/{$oldScript['filename']}"; $escapedOldPath = escapeshellarg($old_file_path); $delete_command = "rm -f {$escapedOldPath}"; instant_remote_process([$delete_command], $this->server); } catch (Exception $e) { $this->dispatch('error', $e->getMessage()); return; } } $index = $initScripts->search(function ($item) use ($script) { return $item['index'] === $script['index']; }); if ($index !== false) { $initScripts[$index] = $script; } else { $initScripts->push($script); } $this->initScripts = $initScripts->values() ->map(function ($item, $index) { $item['index'] = $index; return $item; }) ->all(); $this->syncData(true); $this->dispatch('success', 'Init script saved and updated.'); } public function delete_init_script($script) { $this->authorize('update', $this->database); $collection = collect($this->initScripts); $found = $collection->firstWhere('filename', $script['filename']); if ($found) { $container_name = $this->database->uuid; $configuration_dir = database_configuration_dir().'/'.$container_name; try { // Validate and escape filename to prevent command injection validateShellSafePath($script['filename'], 'init script filename'); $file_path = "$configuration_dir/docker-entrypoint-initdb.d/{$script['filename']}"; $escapedPath = escapeshellarg($file_path); $command = "rm -f {$escapedPath}"; instant_remote_process([$command], $this->server); } catch (Exception $e) { $this->dispatch('error', $e->getMessage()); return; } $updatedScripts = $collection->filter(fn ($s) => $s['filename'] !== $script['filename']) ->values() ->map(function ($item, $index) { $item['index'] = $index; return $item; }) ->all(); $this->initScripts = $updatedScripts; $this->syncData(true); $this->dispatch('refresh')->self(); $this->dispatch('success', 'Init script deleted from the database and the server.'); } } public function save_new_init_script() { $this->authorize('update', $this->database); $this->validate([ 'new_filename' => 'required|string', 'new_content' => 'required|string', ]); try { // Validate filename to prevent command injection validateShellSafePath($this->new_filename, 'init script filename'); } catch (Exception $e) { $this->dispatch('error', $e->getMessage()); return; } $found = collect($this->initScripts)->firstWhere('filename', $this->new_filename); if ($found) { $this->dispatch('error', 'Filename already exists.'); return; } if (! isset($this->initScripts)) { $this->initScripts = []; } $this->initScripts = array_merge($this->initScripts, [ [ 'index' => count($this->initScripts), 'filename' => $this->new_filename, 'content' => $this->new_content, ], ]); $this->syncData(true); $this->dispatch('success', 'Init script added.'); $this->new_content = ''; $this->new_filename = ''; } public function submit() { try { $this->authorize('update', $this->database); if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { if (is_null($this->database->config_hash)) { $this->database->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } } ================================================ FILE: app/Livewire/Project/Database/Redis/General.php ================================================ '$refresh', 'envsUpdated' => 'refresh', ]; } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'redisConf' => 'nullable', 'image' => 'required', 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'redisUsername' => 'required', 'redisPassword' => 'required', 'enableSsl' => 'boolean', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', 'image.required' => 'The Docker Image field is required.', 'publicPort.integer' => 'The Public Port must be an integer.', 'publicPortTimeout.integer' => 'The Public Port Timeout must be an integer.', 'publicPortTimeout.min' => 'The Public Port Timeout must be at least 1.', 'redisUsername.required' => 'The Redis Username field is required.', 'redisPassword.required' => 'The Redis Password field is required.', ] ); } protected $validationAttributes = [ 'name' => 'Name', 'description' => 'Description', 'redisConf' => 'Redis Configuration', 'image' => 'Image', 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', 'publicPortTimeout' => 'Public Port Timeout', 'customDockerRunOptions' => 'Custom Docker Options', 'redisUsername' => 'Redis Username', 'redisPassword' => 'Redis Password', 'enableSsl' => 'Enable SSL', ]; public function mount() { try { $this->authorize('view', $this->database); $this->syncData(); $this->server = data_get($this->database, 'destination.server'); if (! $this->server) { $this->dispatch('error', 'Database destination server is not configured.'); return; } $existingCert = $this->database->sslCertificates()->first(); if ($existingCert) { $this->certificateValidUntil = $existingCert->valid_until; } } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->database->name = $this->name; $this->database->description = $this->description; $this->database->redis_conf = $this->redisConf; $this->database->image = $this->image; $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; $this->database->public_port_timeout = $this->publicPortTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; $this->database->save(); $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; } else { $this->name = $this->database->name; $this->description = $this->database->description; $this->redisConf = $this->database->redis_conf; $this->image = $this->database->image; $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; $this->publicPortTimeout = $this->database->public_port_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; $this->dbUrl = $this->database->internal_db_url; $this->dbUrlPublic = $this->database->external_db_url; $this->redisVersion = $this->database->getRedisVersion(); $this->redisUsername = $this->database->redis_username; $this->redisPassword = $this->database->redis_password; } } public function instantSaveAdvanced() { try { $this->authorize('update', $this->database); if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncData(true); $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('manageEnvironment', $this->database); $this->syncData(true); if (version_compare($this->redisVersion, '6.0', '>=')) { $this->database->runtime_environment_variables()->updateOrCreate( ['key' => 'REDIS_USERNAME'], ['value' => $this->redisUsername, 'resourceable_id' => $this->database->id] ); } $this->database->runtime_environment_variables()->updateOrCreate( ['key' => 'REDIS_PASSWORD'], ['value' => $this->redisPassword, 'resourceable_id' => $this->database->id] ); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } finally { $this->dispatch('refreshEnvs'); } } public function instantSave() { try { $this->authorize('update', $this->database); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } if ($this->isPublic && ! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; return; } $this->syncData(true); if ($this->isPublic) { StartDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { $this->isPublic = ! $this->isPublic; $this->syncData(true); return handleError($e, $this); } } public function instantSaveSSL() { try { $this->authorize('update', $this->database); $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { return handleError($e, $this); } } public function regenerateSslCertificate() { try { $this->authorize('update', $this->database); $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { $this->dispatch('error', 'No existing SSL certificate found for this database.'); return; } $caCert = $this->server->sslCertificates()->where('is_ca_certificate', true)->first(); SslHelper::generateSslCertificate( commonName: $existingCert->commonName, subjectAlternativeNames: $existingCert->subjectAlternativeNames ?? [], resourceType: $existingCert->resource_type, resourceId: $existingCert->resource_id, serverId: $existingCert->server_id, caCert: $caCert->ssl_certificate, caKey: $caCert->ssl_private_key, configurationDir: $existingCert->configuration_dir, mountPath: $existingCert->mount_path, isPemKeyFileRequired: true, ); $this->dispatch('success', 'SSL certificates regenerated. Restart database to apply changes.'); } catch (Exception $e) { handleError($e, $this); } } public function refresh(): void { $this->database->refresh(); $this->syncData(); } public function render() { return view('livewire.project.database.redis.general'); } public function isSharedVariable($name) { return $this->database->runtime_environment_variables()->where('key', $name)->where('is_shared', true)->exists(); } } ================================================ FILE: app/Livewire/Project/Database/ScheduledBackups.php ================================================ selectedBackupId) { $this->setSelectedBackup($this->selectedBackupId, true); } $this->parameters = get_route_parameters(); if ($this->database->getMorphClass() === \App\Models\ServiceDatabase::class) { $this->type = 'service-database'; } else { $this->type = 'database'; } $this->s3s = currentTeam()->s3s; } public function setSelectedBackup($backupId, $force = false) { if ($this->selectedBackupId === $backupId && ! $force) { return; } $this->selectedBackupId = $backupId; $this->selectedBackup = $this->database->scheduledBackups->find($backupId); if (is_null($this->selectedBackup)) { $this->selectedBackupId = null; } } public function setCustomType() { $this->authorize('update', $this->database); $this->database->custom_type = $this->custom_type; $this->database->save(); $this->dispatch('success', 'Database type set.'); $this->refreshScheduledBackups(); } public function delete($scheduled_backup_id): void { $backup = $this->database->scheduledBackups->find($scheduled_backup_id); $this->authorize('manageBackups', $this->database); $backup->delete(); $this->dispatch('success', 'Scheduled backup deleted.'); $this->refreshScheduledBackups(); } public function refreshScheduledBackups(?int $id = null): void { $this->database->refresh(); if ($id) { $this->setSelectedBackup($id); } $this->dispatch('refreshScheduledBackups'); } } ================================================ FILE: app/Livewire/Project/DeleteEnvironment.php ================================================ environmentName = Environment::findOrFail($this->environment_id)->name; $this->parameters = get_route_parameters(); } catch (\Exception $e) { return handleError($e, $this); } } public function delete() { $this->validate([ 'environment_id' => 'required|int', ]); $environment = Environment::findOrFail($this->environment_id); $this->authorize('delete', $environment); if ($environment->isEmpty()) { $environment->delete(); return redirectRoute($this, 'project.show', ['project_uuid' => $this->parameters['project_uuid']]); } return $this->dispatch('error', "Environment {$environment->name} has defined resources, please delete them first."); } } ================================================ FILE: app/Livewire/Project/DeleteProject.php ================================================ parameters = get_route_parameters(); $this->projectName = Project::findOrFail($this->project_id)->name; } public function delete() { $this->validate([ 'project_id' => 'required|int', ]); $project = Project::findOrFail($this->project_id); $this->authorize('delete', $project); if ($project->isEmpty()) { $project->delete(); return redirectRoute($this, 'project.index'); } return $this->dispatch('error', "Project {$project->name} has resources defined, please delete them first."); } } ================================================ FILE: app/Livewire/Project/Edit.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), ]; } protected function messages(): array { return ValidationPatterns::combinedMessages(); } public function mount(string $project_uuid) { try { $this->project = Project::where('team_id', currentTeam()->id)->where('uuid', $project_uuid)->firstOrFail(); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->project->update([ 'name' => $this->name, 'description' => $this->description, ]); } else { $this->name = $this->project->name; $this->description = $this->project->description; } } public function submit() { try { $this->syncData(true); $this->dispatch('success', 'Project updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/EnvironmentEdit.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), ]; } protected function messages(): array { return ValidationPatterns::combinedMessages(); } public function mount(string $project_uuid, string $environment_uuid) { try { $this->project = Project::ownedByCurrentTeam()->where('uuid', $project_uuid)->firstOrFail(); $this->environment = $this->project->environments()->where('uuid', $environment_uuid)->firstOrFail(); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->environment->update([ 'name' => $this->name, 'description' => $this->description, ]); } else { $this->name = $this->environment->name; $this->description = $this->environment->description; } } public function submit() { try { $this->syncData(true); redirectRoute($this, 'project.environment.edit', [ 'environment_uuid' => $this->environment->uuid, 'project_uuid' => $this->project->uuid, ]); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.environment-edit'); } } ================================================ FILE: app/Livewire/Project/Index.php ================================================ private_keys = PrivateKey::ownedByCurrentTeamCached(); $this->projects = Project::ownedByCurrentTeamCached(); $this->servers = Server::ownedByCurrentTeamCached(); } public function render() { return view('livewire.project.index'); } } ================================================ FILE: app/Livewire/Project/New/DockerCompose.php ================================================ parameters = get_route_parameters(); $this->query = request()->query(); if (isDev()) { $this->dockerComposeRaw = file_get_contents(base_path('templates/test-database-detection.yaml')); } } public function submit() { $server_id = $this->query['server_id']; try { $this->validate([ 'dockerComposeRaw' => 'required', ]); $this->dockerComposeRaw = Yaml::dump(Yaml::parse($this->dockerComposeRaw), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); // Validate for command injection BEFORE saving to database validateDockerComposeForInjection($this->dockerComposeRaw); $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); $destination_uuid = $this->query['destination']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); if (! $destination) { $destination = SwarmDocker::where('uuid', $destination_uuid)->first(); } if (! $destination) { throw new \Exception('Destination not found. What?!'); } $destination_class = $destination->getMorphClass(); $service = Service::create([ 'docker_compose_raw' => $this->dockerComposeRaw, 'environment_id' => $environment->id, 'server_id' => (int) $server_id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, ]); $variables = parseEnvFormatToArray($this->envFile); foreach ($variables as $key => $data) { // Extract value and comment from parsed data // Handle both array format ['value' => ..., 'comment' => ...] and plain string values $value = is_array($data) ? ($data['value'] ?? '') : $data; $comment = is_array($data) ? ($data['comment'] ?? null) : null; EnvironmentVariable::create([ 'key' => $key, 'value' => $value, 'comment' => $comment, 'is_preview' => false, 'resourceable_id' => $service->id, 'resourceable_type' => $service->getMorphClass(), ]); } $service->parse(isNew: true); // Apply service-specific application prerequisites applyServiceApplicationPrerequisites($service); return redirect()->route('project.service.configuration', [ 'service_uuid' => $service->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/New/DockerImage.php ================================================ parameters = get_route_parameters(); $this->query = request()->query(); } /** * Auto-parse image name when user pastes a complete Docker image reference * Examples: * - nginx:stable-alpine3.21-perl@sha256:4e272eef... * - ghcr.io/user/app:v1.2.3 * - nginx@sha256:abc123... */ public function updatedImageName(): void { if (empty($this->imageName)) { return; } // Don't auto-parse if user has already manually filled tag or sha256 fields if (! empty($this->imageTag) || ! empty($this->imageSha256)) { return; } // Only auto-parse if the image name contains a tag (:) or digest (@) if (! str_contains($this->imageName, ':') && ! str_contains($this->imageName, '@')) { return; } try { $parser = new DockerImageParser; $parser->parse($this->imageName); // Extract the base image name (without tag/digest) $baseImageName = $parser->getFullImageNameWithoutTag(); // Only update if parsing resulted in different base name // This prevents unnecessary updates when user types just the name if ($baseImageName !== $this->imageName) { if ($parser->isImageHash()) { // It's a SHA256 digest (takes priority over tag) $this->imageSha256 = $parser->getTag(); $this->imageTag = ''; } elseif ($parser->getTag() !== 'latest' || str_contains($this->imageName, ':')) { // It's a regular tag (only set if not default 'latest' or explicitly specified) $this->imageTag = $parser->getTag(); $this->imageSha256 = ''; } // Update imageName to just the base name $this->imageName = $baseImageName; } } catch (\Exception $e) { // If parsing fails, leave the image name as-is // User will see validation error on submit } } public function submit() { $this->validate([ 'imageName' => ['required', 'string'], 'imageTag' => ['nullable', 'string', 'regex:/^[a-z0-9][a-z0-9._-]*$/i'], 'imageSha256' => ['nullable', 'string', 'regex:/^[a-f0-9]{64}$/i'], ]); // Validate that either tag or sha256 is provided, but not both if ($this->imageTag && $this->imageSha256) { $this->addError('imageTag', 'Provide either a tag or SHA256 digest, not both.'); $this->addError('imageSha256', 'Provide either a tag or SHA256 digest, not both.'); return; } // Build the full Docker image string if ($this->imageSha256) { // Strip 'sha256:' prefix if user pasted it $sha256Hash = preg_replace('/^sha256:/i', '', trim($this->imageSha256)); $dockerImage = $this->imageName.'@sha256:'.$sha256Hash; } elseif ($this->imageTag) { $dockerImage = $this->imageName.':'.$this->imageTag; } else { $dockerImage = $this->imageName.':latest'; } // Parse using DockerImageParser to normalize the image reference $parser = new DockerImageParser; $parser->parse($dockerImage); $destination_uuid = $this->query['destination']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); if (! $destination) { $destination = SwarmDocker::where('uuid', $destination_uuid)->first(); } if (! $destination) { throw new \Exception('Destination not found. What?!'); } $destination_class = $destination->getMorphClass(); $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); // Append @sha256 to image name if using digest and not already present $imageName = $parser->getFullImageNameWithoutTag(); if ($parser->isImageHash() && ! str_ends_with($imageName, '@sha256')) { $imageName .= '@sha256'; } // Determine the image tag based on whether it's a hash or regular tag $imageTag = $parser->isImageHash() ? 'sha256-'.$parser->getTag() : $parser->getTag(); $application = Application::create([ 'name' => 'docker-image-'.new Cuid2, 'repository_project_id' => 0, 'git_repository' => 'coollabsio/coolify', 'git_branch' => 'main', 'build_pack' => 'dockerimage', 'ports_exposes' => 80, 'docker_registry_image_name' => $imageName, 'docker_registry_image_tag' => $imageTag, 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'health_check_enabled' => false, ]); $fqdn = generateUrl(server: $destination->server, random: $application->uuid); $application->update([ 'name' => 'docker-image-'.$application->uuid, 'fqdn' => $fqdn, ]); return redirectRoute($this, 'project.application.configuration', [ 'application_uuid' => $application->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); } public function render() { return view('livewire.project.new.docker-image'); } } ================================================ FILE: app/Livewire/Project/New/EmptyProject.php ================================================ generate_random_name(), 'team_id' => currentTeam()->id, 'uuid' => (string) new Cuid2, ]); return redirectRoute($this, 'project.show', ['project_uuid' => $project->uuid, 'environment_uuid' => $project->environments->first()->uuid]); } } ================================================ FILE: app/Livewire/Project/New/GithubPrivateRepository.php ================================================ currentRoute = Route::currentRouteName(); $this->parameters = get_route_parameters(); $this->query = request()->query(); $this->repositories = $this->branches = collect(); $this->github_apps = GithubApp::private(); } public function updatedSelectedRepositoryId(): void { $this->loadBranches(); } public function updatedBuildPack() { if ($this->build_pack === 'nixpacks') { $this->show_is_static = true; $this->port = 3000; } elseif ($this->build_pack === 'static') { $this->show_is_static = false; $this->is_static = false; $this->port = 80; } else { $this->show_is_static = false; $this->is_static = false; } } public function loadRepositories($github_app_id) { $this->repositories = collect(); $this->page = 1; $this->selected_github_app_id = $github_app_id; $this->github_app = GithubApp::where('id', $github_app_id)->first(); $this->token = generateGithubInstallationToken($this->github_app); $repositories = loadRepositoryByPage($this->github_app, $this->token, $this->page); $this->total_repositories_count = $repositories['total_count']; $this->repositories = $this->repositories->concat(collect($repositories['repositories'])); if ($this->repositories->count() < $this->total_repositories_count) { while ($this->repositories->count() < $this->total_repositories_count) { $this->page++; $repositories = loadRepositoryByPage($this->github_app, $this->token, $this->page); $this->total_repositories_count = $repositories['total_count']; $this->repositories = $this->repositories->concat(collect($repositories['repositories'])); } } $this->repositories = $this->repositories->sortBy('name'); if ($this->repositories->count() > 0) { $this->selected_repository_id = data_get($this->repositories->first(), 'id'); } $this->current_step = 'repository'; } public function loadBranches() { $this->selected_repository_owner = $this->repositories->where('id', $this->selected_repository_id)->first()['owner']['login']; $this->selected_repository_repo = $this->repositories->where('id', $this->selected_repository_id)->first()['name']; $this->branches = collect(); $this->page = 1; $this->loadBranchByPage(); if ($this->total_branches_count === 100) { while ($this->total_branches_count === 100) { $this->page++; $this->loadBranchByPage(); } } $this->branches = sortBranchesByPriority($this->branches); $this->selected_branch_name = data_get($this->branches, '0.name', 'main'); } protected function loadBranchByPage() { $response = Http::GitHub($this->github_app->api_url, $this->token) ->timeout(20) ->retry(3, 200, throw: false) ->get("/repos/{$this->selected_repository_owner}/{$this->selected_repository_repo}/branches", [ 'per_page' => 100, 'page' => $this->page, ]); $json = $response->json(); if ($response->status() !== 200) { return $this->dispatch('error', $json['message']); } $this->total_branches_count = count($json); $this->branches = $this->branches->concat(collect($json)); } public function submit() { try { // Validate git repository parts and branch $validator = validator([ 'selected_repository_owner' => $this->selected_repository_owner, 'selected_repository_repo' => $this->selected_repository_repo, 'selected_branch_name' => $this->selected_branch_name, 'docker_compose_location' => $this->docker_compose_location, ], [ 'selected_repository_owner' => 'required|string|regex:/^[a-zA-Z0-9\-_]+$/', 'selected_repository_repo' => 'required|string|regex:/^[a-zA-Z0-9\-_\.]+$/', 'selected_branch_name' => ['required', 'string', new ValidGitBranch], 'docker_compose_location' => \App\Support\ValidationPatterns::filePathRules(), ]); if ($validator->fails()) { throw new \RuntimeException('Invalid repository data: '.$validator->errors()->first()); } $destination_uuid = $this->query['destination']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); if (! $destination) { $destination = SwarmDocker::where('uuid', $destination_uuid)->first(); } if (! $destination) { throw new \Exception('Destination not found. What?!'); } $destination_class = $destination->getMorphClass(); $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); $application = Application::create([ 'name' => generate_application_name($this->selected_repository_owner.'/'.$this->selected_repository_repo, $this->selected_branch_name), 'repository_project_id' => $this->selected_repository_id, 'git_repository' => str($this->selected_repository_owner)->trim()->toString().'/'.str($this->selected_repository_repo)->trim()->toString(), 'git_branch' => str($this->selected_branch_name)->trim()->toString(), 'build_pack' => $this->build_pack, 'ports_exposes' => $this->port, 'publish_directory' => $this->publish_directory, 'base_directory' => $this->base_directory, 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'source_id' => $this->github_app->id, 'source_type' => $this->github_app->getMorphClass(), ]); $application->settings->is_static = $this->is_static; $application->settings->save(); if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') { $application->health_check_enabled = false; } if ($this->build_pack === 'dockercompose') { $application['docker_compose_location'] = $this->docker_compose_location; } $fqdn = generateUrl(server: $destination->server, random: $application->uuid); $application->fqdn = $fqdn; $application->name = generate_application_name($this->selected_repository_owner.'/'.$this->selected_repository_repo, $this->selected_branch_name, $application->uuid); $application->save(); return redirect()->route('project.application.configuration', [ 'application_uuid' => $application->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSave() { if ($this->is_static) { $this->port = 80; $this->publish_directory = '/dist'; } else { $this->port = 3000; $this->publish_directory = null; } $this->dispatch('success', 'Application settings updated!'); } } ================================================ FILE: app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php ================================================ ['required', 'string', new ValidGitRepositoryUrl], 'branch' => ['required', 'string', new ValidGitBranch], 'port' => 'required|numeric', 'is_static' => 'required|boolean', 'publish_directory' => 'nullable|string', 'build_pack' => 'required|string', 'docker_compose_location' => \App\Support\ValidationPatterns::filePathRules(), ]; } protected $validationAttributes = [ 'repository_url' => 'Repository', 'branch' => 'Branch', 'port' => 'Port', 'is_static' => 'Is static', 'publish_directory' => 'Publish directory', 'build_pack' => 'Build pack', ]; public function mount() { if (isDev()) { $this->repository_url = 'https://github.com/coollabsio/coolify-examples/tree/v4.x'; } $this->parameters = get_route_parameters(); $this->query = request()->query(); if (isDev()) { $this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->get(); } else { $this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->where('id', '!=', 0)->get(); } } public function updatedBuildPack() { if ($this->build_pack === 'nixpacks') { $this->show_is_static = true; $this->port = 3000; } elseif ($this->build_pack === 'static') { $this->show_is_static = false; $this->is_static = false; $this->port = 80; } else { $this->show_is_static = false; $this->is_static = false; } } public function instantSave() { if ($this->is_static) { $this->port = 80; $this->publish_directory = '/dist'; } else { $this->port = 3000; $this->publish_directory = null; } } public function setPrivateKey($private_key_id) { $this->private_key_id = $private_key_id; $this->current_step = 'repository'; } public function submit() { $this->validate(); try { $destination_uuid = $this->query['destination']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); if (! $destination) { $destination = SwarmDocker::where('uuid', $destination_uuid)->first(); } if (! $destination) { throw new \Exception('Destination not found. What?!'); } $destination_class = $destination->getMorphClass(); $this->get_git_source(); // Note: git_repository has already been validated and transformed in get_git_source() // It may now be in SSH format (git@host:repo.git) which is valid for deploy keys $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); if ($this->git_source === 'other') { $application_init = [ 'name' => generate_random_name(), 'git_repository' => $this->git_repository, 'git_branch' => $this->branch, 'build_pack' => $this->build_pack, 'ports_exposes' => $this->port, 'publish_directory' => $this->publish_directory, 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'private_key_id' => $this->private_key_id, ]; } else { $application_init = [ 'name' => generate_random_name(), 'git_repository' => $this->git_repository, 'git_branch' => $this->branch, 'build_pack' => $this->build_pack, 'ports_exposes' => $this->port, 'publish_directory' => $this->publish_directory, 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'private_key_id' => $this->private_key_id, 'source_id' => $this->git_source->id, 'source_type' => $this->git_source->getMorphClass(), ]; } if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') { $application_init['health_check_enabled'] = false; } if ($this->build_pack === 'dockercompose') { $application_init['docker_compose_location'] = $this->docker_compose_location; $application_init['base_directory'] = $this->base_directory; } $application = Application::create($application_init); $application->settings->is_static = $this->is_static; $application->settings->save(); $fqdn = generateUrl(server: $destination->server, random: $application->uuid); $application->fqdn = $fqdn; $application->name = generate_random_name($application->uuid); $application->save(); return redirect()->route('project.application.configuration', [ 'application_uuid' => $application->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); } catch (\Throwable $e) { return handleError($e, $this); } } private function get_git_source() { // Validate repository URL before parsing $validator = validator(['repository_url' => $this->repository_url], [ 'repository_url' => ['required', 'string', new ValidGitRepositoryUrl], ]); if ($validator->fails()) { throw new \RuntimeException('Invalid repository URL: '.$validator->errors()->first('repository_url')); } $this->repository_url_parsed = Url::fromString($this->repository_url); $this->git_host = $this->repository_url_parsed->getHost(); $this->git_repository = $this->repository_url_parsed->getSegment(1).'/'.$this->repository_url_parsed->getSegment(2); if ($this->git_host === 'github.com') { $this->git_source = GithubApp::where('name', 'Public GitHub')->first(); return; } if (str($this->repository_url)->startsWith('http')) { $this->git_host = $this->repository_url_parsed->getHost(); $this->git_repository = $this->repository_url_parsed->getSegment(1).'/'.$this->repository_url_parsed->getSegment(2); // Convert to SSH format for deploy key usage $this->git_repository = Str::finish("git@$this->git_host:$this->git_repository", '.git'); } else { // If it's already in SSH format, just use it as-is $this->git_repository = $this->repository_url; } $this->git_source = 'other'; } } ================================================ FILE: app/Livewire/Project/New/PublicGitRepository.php ================================================ ['required', 'string', new ValidGitRepositoryUrl], 'port' => 'required|numeric', 'isStatic' => 'required|boolean', 'publish_directory' => 'nullable|string', 'build_pack' => 'required|string', 'base_directory' => 'nullable|string', 'docker_compose_location' => \App\Support\ValidationPatterns::filePathRules(), 'git_branch' => ['required', 'string', new ValidGitBranch], ]; } protected $validationAttributes = [ 'repository_url' => 'repository', 'port' => 'port', 'isStatic' => 'static', 'publish_directory' => 'publish directory', 'build_pack' => 'build pack', 'base_directory' => 'base directory', 'docker_compose_location' => 'docker compose location', ]; public function mount() { if (isDev()) { $this->repository_url = 'https://github.com/coollabsio/coolify-examples/tree/v4.x'; $this->port = 3000; } $this->parameters = get_route_parameters(); $this->query = request()->query(); } public function updatedBuildPack() { if ($this->build_pack === 'nixpacks') { $this->show_is_static = true; $this->port = 3000; } elseif ($this->build_pack === 'static') { $this->show_is_static = false; $this->isStatic = false; $this->port = 80; } else { $this->show_is_static = false; $this->isStatic = false; } } public function instantSave() { if ($this->isStatic) { $this->port = 80; $this->publish_directory = '/dist'; } else { $this->port = 3000; $this->publish_directory = null; } $this->dispatch('success', 'Application settings updated!'); } public function loadBranch() { try { // Validate repository URL $validator = validator(['repository_url' => $this->repository_url], [ 'repository_url' => ['required', 'string', new ValidGitRepositoryUrl], ]); if ($validator->fails()) { throw new \RuntimeException('Invalid repository URL: '.$validator->errors()->first('repository_url')); } if (str($this->repository_url)->startsWith('git@')) { $github_instance = str($this->repository_url)->after('git@')->before(':'); $repository = str($this->repository_url)->after(':')->before('.git'); $this->repository_url = 'https://'.str($github_instance).'/'.$repository; } if ( (str($this->repository_url)->startsWith('https://') || str($this->repository_url)->startsWith('http://')) && ! str($this->repository_url)->endsWith('.git') && (! str($this->repository_url)->contains('github.com') || ! str($this->repository_url)->contains('git.sr.ht')) && ! str($this->repository_url)->contains('tangled') ) { $this->repository_url = $this->repository_url.'.git'; } if (str($this->repository_url)->contains('github.com') && str($this->repository_url)->endsWith('.git')) { $this->repository_url = str($this->repository_url)->beforeLast('.git')->value(); } } catch (\Throwable $e) { return handleError($e, $this); } try { $this->branchFound = false; $this->getGitSource(); $this->getBranch(); if (str($this->repository_url)->contains('tangled')) { $this->git_branch = 'master'; } $this->selectedBranch = $this->git_branch; } catch (\Throwable $e) { if ($this->rate_limit_remaining == 0) { $this->selectedBranch = $this->git_branch; $this->branchFound = true; return; } if (! $this->branchFound && $this->git_branch === 'main') { try { $this->git_branch = 'master'; $this->getBranch(); } catch (\Throwable $e) { return handleError($e, $this); } } else { return handleError($e, $this); } } } private function getGitSource() { $this->git_branch = 'main'; $this->base_directory = '/'; // Validate repository URL before parsing $validator = validator(['repository_url' => $this->repository_url], [ 'repository_url' => ['required', 'string', new ValidGitRepositoryUrl], ]); if ($validator->fails()) { throw new \RuntimeException('Invalid repository URL: '.$validator->errors()->first('repository_url')); } $this->repository_url_parsed = Url::fromString($this->repository_url); $this->git_host = $this->repository_url_parsed->getHost(); $this->git_repository = $this->repository_url_parsed->getSegment(1).'/'.$this->repository_url_parsed->getSegment(2); if ($this->repository_url_parsed->getSegment(3) === 'tree') { $path = str($this->repository_url_parsed->getPath())->trim('/'); $this->git_branch = str($path)->after('tree/')->before('/')->value(); $this->base_directory = str($path)->after($this->git_branch)->after('/')->value(); if (filled($this->base_directory)) { $this->base_directory = '/'.$this->base_directory; } else { $this->base_directory = '/'; } } else { $this->git_branch = 'main'; } if ($this->git_host === 'github.com') { $this->git_source = GithubApp::where('name', 'Public GitHub')->first(); return; } $this->git_repository = $this->repository_url; $this->git_source = 'other'; } private function getBranch() { if ($this->git_source === 'other') { $this->branchFound = true; return; } if ($this->git_source->getMorphClass() === \App\Models\GithubApp::class) { ['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = githubApi(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}"); $this->rate_limit_reset = Carbon::parse((int) $this->rate_limit_reset)->format('Y-M-d H:i:s'); $this->branchFound = true; } } public function submit() { try { $this->validate(); // Additional validation for git repository and branch if ($this->git_source === 'other') { // For 'other' sources, git_repository contains the full URL $validator = validator(['git_repository' => $this->git_repository], [ 'git_repository' => ['required', 'string', new ValidGitRepositoryUrl], ]); if ($validator->fails()) { throw new \RuntimeException('Invalid repository URL: '.$validator->errors()->first('git_repository')); } } $branchValidator = validator(['git_branch' => $this->git_branch], [ 'git_branch' => ['required', 'string', new ValidGitBranch], ]); if ($branchValidator->fails()) { throw new \RuntimeException('Invalid branch: '.$branchValidator->errors()->first('git_branch')); } $destination_uuid = $this->query['destination']; $project_uuid = $this->parameters['project_uuid']; $environment_uuid = $this->parameters['environment_uuid']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); if (! $destination) { $destination = SwarmDocker::where('uuid', $destination_uuid)->first(); } if (! $destination) { throw new \Exception('Destination not found. What?!'); } $destination_class = $destination->getMorphClass(); $project = Project::where('uuid', $project_uuid)->first(); $environment = $project->load(['environments'])->environments->where('uuid', $environment_uuid)->first(); if ($this->build_pack === 'dockercompose' && isDev() && $this->new_compose_services) { $server = $destination->server; $new_service = [ 'name' => 'service'.str()->random(10), 'docker_compose_raw' => 'coolify', 'environment_id' => $environment->id, 'server_id' => $server->id, ]; if ($this->git_source === 'other') { $new_service['git_repository'] = $this->git_repository; $new_service['git_branch'] = $this->git_branch; } else { $new_service['git_repository'] = $this->git_repository; $new_service['git_branch'] = $this->git_branch; $new_service['source_id'] = $this->git_source->id; $new_service['source_type'] = $this->git_source->getMorphClass(); } $service = Service::create($new_service); return redirect()->route('project.service.configuration', [ 'service_uuid' => $service->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); return; } if ($this->git_source === 'other') { $application_init = [ 'name' => generate_random_name(), 'git_repository' => $this->git_repository, 'git_branch' => $this->git_branch, 'ports_exposes' => $this->port, 'publish_directory' => $this->publish_directory, 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'build_pack' => $this->build_pack, 'base_directory' => $this->base_directory, ]; } else { $application_init = [ 'name' => generate_application_name($this->git_repository, $this->git_branch), 'git_repository' => $this->git_repository, 'git_branch' => $this->git_branch, 'ports_exposes' => $this->port, 'publish_directory' => $this->publish_directory, 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'source_id' => $this->git_source->id, 'source_type' => $this->git_source->getMorphClass(), 'build_pack' => $this->build_pack, 'base_directory' => $this->base_directory, ]; } if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') { $application_init['health_check_enabled'] = false; } if ($this->build_pack === 'dockercompose') { $application_init['docker_compose_location'] = $this->docker_compose_location; $application_init['base_directory'] = $this->base_directory; } $application = Application::create($application_init); $application->settings->is_static = $this->isStatic; $application->settings->save(); $fqdn = generateUrl(server: $destination->server, random: $application->uuid); $application->fqdn = $fqdn; $application->save(); if ($this->checkCoolifyConfig) { // $config = loadConfigFromGit($this->repository_url, $this->git_branch, $this->base_directory, $this->query['server_id'], auth()->user()->currentTeam()->id); // if ($config) { // $application->setConfig($config); // } } return redirect()->route('project.application.configuration', [ 'application_uuid' => $application->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/New/Select.php ================================================ ['except' => ''], 'destination_uuid' => ['except' => '', 'as' => 'destination'], ]; public function mount() { try { $this->parameters = get_route_parameters(); if (isDev()) { $this->existingPostgresqlUrl = 'postgres://coolify:password@coolify-db:5432'; } $projectUuid = data_get($this->parameters, 'project_uuid'); $project = Project::whereUuid($projectUuid)->firstOrFail(); $this->environments = $project->environments; $this->selectedEnvironment = $this->environments->where('uuid', data_get($this->parameters, 'environment_uuid'))->firstOrFail()->name; // Check if we have all required params for PostgreSQL type selection // This handles navigation from global search $queryType = request()->query('type'); $queryServerId = request()->query('server_id'); $queryDestination = request()->query('destination'); if ($queryType === 'postgresql' && $queryServerId !== null && $queryDestination) { $this->type = $queryType; $this->server_id = $queryServerId; $this->destination_uuid = $queryDestination; $this->server = Server::find($queryServerId); $this->current_step = 'select-postgresql-type'; } } catch (\Exception $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.new.select'); } public function updatedSelectedEnvironment() { $environmentUuid = $this->environments->where('name', $this->selectedEnvironment)->first()->uuid; return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_uuid' => $environmentUuid, ]); } public function loadServices() { $services = get_service_templates(); $services = collect($services)->map(function ($service, $key) { $default_logo = 'images/default.webp'; $logo = data_get($service, 'logo', $default_logo); $local_logo_path = public_path($logo); return [ 'name' => str($key)->headline(), 'logo' => asset($logo), 'logo_github_url' => file_exists($local_logo_path) ? 'https://raw.githubusercontent.com/coollabsio/coolify/refs/heads/main/public/'.$logo : asset($default_logo), ] + (array) $service; })->all(); // Extract unique categories from services $categories = collect($services) ->pluck('category') ->filter() ->unique() ->map(function ($category) { // Handle multiple categories separated by comma if (str_contains($category, ',')) { return collect(explode(',', $category))->map(fn ($cat) => trim($cat)); } return [$category]; }) ->flatten() ->unique() ->map(function ($category) { // Format common acronyms to uppercase $acronyms = ['ai', 'api', 'ci', 'cd', 'cms', 'crm', 'erp', 'iot', 'vpn', 'vps', 'dns', 'ssl', 'tls', 'ssh', 'ftp', 'http', 'https', 'smtp', 'imap', 'pop3', 'sql', 'nosql', 'json', 'xml', 'yaml', 'csv', 'pdf', 'sms', 'mfa', '2fa', 'oauth', 'saml', 'jwt', 'rest', 'soap', 'grpc', 'graphql', 'websocket', 'webrtc', 'p2p', 'b2b', 'b2c', 'seo', 'sem', 'ppc', 'roi', 'kpi', 'ui', 'ux', 'ide', 'sdk', 'api', 'cli', 'gui', 'cdn', 'ddos', 'dos', 'xss', 'csrf', 'sqli', 'rce', 'lfi', 'rfi', 'ssrf', 'xxe', 'idor', 'owasp', 'gdpr', 'hipaa', 'pci', 'dss', 'iso', 'nist', 'cve', 'cwe', 'cvss']; $lower = strtolower($category); if (in_array($lower, $acronyms)) { return strtoupper($category); } return $category; }) ->sort(SORT_NATURAL | SORT_FLAG_CASE) ->values() ->all(); $gitBasedApplications = [ [ 'id' => 'public', 'name' => 'Public Repository', 'description' => 'You can deploy any kind of public repositories from the supported git providers.', 'logo' => asset('svgs/git.svg'), ], [ 'id' => 'private-gh-app', 'name' => 'Private Repository (with GitHub App)', 'description' => 'You can deploy public & private repositories through your GitHub Apps.', 'logo' => asset('svgs/github.svg'), ], [ 'id' => 'private-deploy-key', 'name' => 'Private Repository (with Deploy Key)', 'description' => 'You can deploy private repositories with a deploy key.', 'logo' => asset('svgs/git.svg'), ], ]; $dockerBasedApplications = [ [ 'id' => 'dockerfile', 'name' => 'Dockerfile', 'description' => 'You can deploy a simple Dockerfile, without Git.', 'logo' => asset('svgs/docker.svg'), ], [ 'id' => 'docker-compose-empty', 'name' => 'Docker Compose Empty', 'description' => 'You can deploy complex application easily with Docker Compose, without Git.', 'logo' => asset('svgs/docker.svg'), ], [ 'id' => 'docker-image', 'name' => 'Docker Image', 'description' => 'You can deploy an existing Docker Image from any Registry, without Git.', 'logo' => asset('svgs/docker.svg'), ], ]; $databases = [ [ 'id' => 'postgresql', 'name' => 'PostgreSQL', 'description' => 'PostgreSQL is an object-relational database known for its robustness, advanced features, and strong standards compliance.', 'logo' => ' ', ], [ 'id' => 'mysql', 'name' => 'MySQL', 'description' => 'MySQL is an open-source relational database management system. ', 'logo' => ' ', ], [ 'id' => 'mariadb', 'name' => 'MariaDB', 'description' => 'MariaDB is a community-developed, commercially supported fork of the MySQL relational database management system, intended to remain free and open-source.', 'logo' => '', ], [ 'id' => 'redis', 'name' => 'Redis', 'description' => 'Redis is a source-available, in-memory storage, used as a distributed, in-memory key–value database, cache and message broker, with optional durability.', 'logo' => '', ], [ 'id' => 'keydb', 'name' => 'KeyDB', 'description' => 'KeyDB is a database that offers high performance, low latency, and scalability for various data structures and workloads.', 'logo' => '
', ], [ 'id' => 'dragonfly', 'name' => 'Dragonfly', 'description' => 'Dragonfly DB is a drop-in Redis replacement that delivers 25x more throughput and 12x faster snapshotting than Redis.', 'logo' => '
', ], [ 'id' => 'mongodb', 'name' => 'MongoDB', 'description' => 'MongoDB is a source-available, cross-platform, document-oriented database program.', 'logo' => '', ], [ 'id' => 'clickhouse', 'name' => 'ClickHouse', 'description' => 'ClickHouse is a column-oriented database that supports real-time analytics, business intelligence, observability, ML and GenAI, and more.', 'logo' => '
', ], ]; return [ 'services' => $services, 'categories' => $categories, 'gitBasedApplications' => $gitBasedApplications, 'dockerBasedApplications' => $dockerBasedApplications, 'databases' => $databases, ]; } public function instantSave() { if ($this->includeSwarm) { $this->servers = $this->allServers; } else { if ($this->allServers instanceof Collection) { $this->servers = $this->allServers->where('settings.is_swarm_worker', false)->where('settings.is_swarm_manager', false)->where('settings.is_build_server', false); } else { $this->servers = $this->allServers; } } } public function setType(string $type) { $type = str($type)->lower()->slug()->value(); if ($this->loading) { return; } $this->loading = true; $this->type = $type; switch ($type) { case 'postgresql': case 'mysql': case 'mariadb': case 'redis': case 'keydb': case 'dragonfly': case 'clickhouse': case 'mongodb': $this->isDatabase = true; $this->includeSwarm = false; if ($this->allServers instanceof Collection) { $this->servers = $this->allServers->where('settings.is_swarm_worker', false)->where('settings.is_swarm_manager', false)->where('settings.is_build_server', false); } else { $this->servers = $this->allServers; } break; } if (str($type)->startsWith('one-click-service') || str($type)->startsWith('docker-compose-empty')) { $this->isDatabase = true; $this->includeSwarm = false; if ($this->allServers instanceof Collection) { $this->servers = $this->allServers->where('settings.is_swarm_worker', false)->where('settings.is_swarm_manager', false)->where('settings.is_build_server', false); } else { $this->servers = $this->allServers; } } if ($type === 'existing-postgresql') { $this->current_step = $type; return; } if (count($this->servers) === 1) { $server = $this->servers->first(); if ($server instanceof Server) { $this->setServer($server); } } if (! is_null($this->server)) { $foundServer = $this->servers->where('id', $this->server->id)->first(); if ($foundServer) { return $this->setServer($foundServer); } } $this->current_step = 'servers'; } public function setServer(Server $server) { $this->server_id = $server->id; $this->server = $server; $this->standaloneDockers = $server->standaloneDockers; $this->swarmDockers = $server->swarmDockers; $count = count($this->standaloneDockers) + count($this->swarmDockers); if ($count === 1) { $docker = $this->standaloneDockers->first() ?? $this->swarmDockers->first(); if ($docker) { $this->setDestination($docker->uuid); return $this->whatToDoNext(); } } $this->current_step = 'destinations'; } public function setDestination(string $destination_uuid) { $this->destination_uuid = $destination_uuid; return $this->whatToDoNext(); } public function setPostgresqlType(string $type) { $this->postgresql_type = $type; return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_uuid' => $this->parameters['environment_uuid'], 'type' => $this->type, 'destination' => $this->destination_uuid, 'server_id' => $this->server_id, 'database_image' => $this->postgresql_type, ]); } public function whatToDoNext() { if ($this->type === 'postgresql') { $this->current_step = 'select-postgresql-type'; } else { return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_uuid' => $this->parameters['environment_uuid'], 'type' => $this->type, 'destination' => $this->destination_uuid, 'server_id' => $this->server_id, ]); } } public function loadServers() { $this->servers = Server::isUsable()->get()->sortBy('name'); $this->allServers = $this->servers; if ($this->allServers && $this->allServers->isNotEmpty()) { $this->onlyBuildServerAvailable = $this->allServers->every(function ($server) { return $server->isBuildServer(); }); } } } ================================================ FILE: app/Livewire/Project/New/SimpleDockerfile.php ================================================ parameters = get_route_parameters(); $this->query = request()->query(); if (isDev()) { $this->dockerfile = 'FROM nginx EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] '; } } public function submit() { $this->validate([ 'dockerfile' => 'required', ]); $destination_uuid = $this->query['destination']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); if (! $destination) { $destination = SwarmDocker::where('uuid', $destination_uuid)->first(); } if (! $destination) { throw new \Exception('Destination not found. What?!'); } $destination_class = $destination->getMorphClass(); $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); $port = get_port_from_dockerfile($this->dockerfile); if (! $port) { $port = 80; } $application = Application::create([ 'name' => 'dockerfile-'.new Cuid2, 'repository_project_id' => 0, 'git_repository' => 'coollabsio/coolify', 'git_branch' => 'main', 'build_pack' => 'dockerfile', 'dockerfile' => $this->dockerfile, 'ports_exposes' => $port, 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, 'health_check_enabled' => false, 'source_id' => 0, 'source_type' => GithubApp::class, ]); $fqdn = generateUrl(server: $destination->server, random: $application->uuid); $application->update([ 'name' => 'dockerfile-'.$application->uuid, 'fqdn' => $fqdn, ]); $application->parseHealthcheckFromDockerfile(dockerfile: $this->dockerfile, isInit: true); return redirect()->route('project.application.configuration', [ 'application_uuid' => $application->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); } } ================================================ FILE: app/Livewire/Project/Resource/Create.php ================================================ query('type')); $destination_uuid = request()->query('destination'); $server_id = request()->query('server_id'); $database_image = request()->query('database_image'); $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); if (! $project) { return redirect()->route('dashboard'); } $this->project = $project; $environment = $project->load(['environments'])->environments->where('uuid', request()->route('environment_uuid'))->first(); if (! $environment) { return redirect()->route('dashboard'); } if (isset($type) && isset($destination_uuid) && isset($server_id)) { $services = get_service_templates(); if (in_array($type, DATABASE_TYPES)) { if ($type->value() === 'postgresql') { // PostgreSQL requires database_image to be explicitly set // If not provided, fall through to Select component for version selection if (! $database_image) { $this->type = $type->value(); return; } $database = create_standalone_postgresql( environmentId: $environment->id, destinationUuid: $destination_uuid, databaseImage: $database_image ); } elseif ($type->value() === 'redis') { $database = create_standalone_redis($environment->id, $destination_uuid); } elseif ($type->value() === 'mongodb') { $database = create_standalone_mongodb($environment->id, $destination_uuid); } elseif ($type->value() === 'mysql') { $database = create_standalone_mysql($environment->id, $destination_uuid); } elseif ($type->value() === 'mariadb') { $database = create_standalone_mariadb($environment->id, $destination_uuid); } elseif ($type->value() === 'keydb') { $database = create_standalone_keydb($environment->id, $destination_uuid); } elseif ($type->value() === 'dragonfly') { $database = create_standalone_dragonfly($environment->id, $destination_uuid); } elseif ($type->value() === 'clickhouse') { $database = create_standalone_clickhouse($environment->id, $destination_uuid); } return redirect()->route('project.database.configuration', [ 'project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid, ]); } if ($type->startsWith('one-click-service-') && ! is_null((int) $server_id)) { $oneClickServiceName = $type->after('one-click-service-')->value(); $oneClickService = data_get($services, "$oneClickServiceName.compose"); $oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null); if ($oneClickDotEnvs) { $oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) { return ! empty($value); }); } if ($oneClickService) { $destination = StandaloneDocker::whereUuid($destination_uuid)->first(); $service_payload = [ 'docker_compose_raw' => base64_decode($oneClickService), 'environment_id' => $environment->id, 'service_type' => $oneClickServiceName, 'server_id' => (int) $server_id, 'destination_id' => $destination->id, 'destination_type' => $destination->getMorphClass(), ]; if (in_array($oneClickServiceName, NEEDS_TO_CONNECT_TO_PREDEFINED_NETWORK)) { data_set($service_payload, 'connect_to_docker_network', true); } $service = Service::create($service_payload); $service->name = "$oneClickServiceName-".$service->uuid; $service->save(); if ($oneClickDotEnvs?->count() > 0) { $oneClickDotEnvs->each(function ($value) use ($service) { $key = str()->before($value, '='); $value = str(str()->after($value, '=')); if ($value) { EnvironmentVariable::create([ 'key' => $key, 'value' => $value, 'resourceable_id' => $service->id, 'resourceable_type' => $service->getMorphClass(), 'is_preview' => false, ]); } }); } $service->parse(isNew: true); // Apply service-specific application prerequisites applyServiceApplicationPrerequisites($service); return redirect()->route('project.service.configuration', [ 'service_uuid' => $service->uuid, 'environment_uuid' => $environment->uuid, 'project_uuid' => $project->uuid, ]); } } $this->type = $type->value(); } } public function render() { return view('livewire.project.resource.create'); } } ================================================ FILE: app/Livewire/Project/Resource/Index.php ================================================ applications = $this->postgresqls = $this->redis = $this->mongodbs = $this->mysqls = $this->mariadbs = $this->keydbs = $this->dragonflies = $this->clickhouses = $this->services = collect(); $this->parameters = get_route_parameters(); $project = currentTeam() ->projects() ->select('id', 'uuid', 'team_id', 'name') ->where('uuid', request()->route('project_uuid')) ->firstOrFail(); $environment = $project->environments() ->select('id', 'uuid', 'name', 'project_id') ->where('uuid', request()->route('environment_uuid')) ->firstOrFail(); $this->project = $project; // Load projects and environments for breadcrumb navigation (avoids inline queries in view) $this->allProjects = Project::ownedByCurrentTeamCached(); $this->allEnvironments = $project->environments() ->with([ 'applications.additional_servers', 'applications.destination.server', 'services', 'services.destination.server', 'postgresqls', 'postgresqls.destination.server', 'redis', 'redis.destination.server', 'mongodbs', 'mongodbs.destination.server', 'mysqls', 'mysqls.destination.server', 'mariadbs', 'mariadbs.destination.server', 'keydbs', 'keydbs.destination.server', 'dragonflies', 'dragonflies.destination.server', 'clickhouses', 'clickhouses.destination.server', ])->get(); $this->environment = $environment->loadCount([ 'applications', 'redis', 'postgresqls', 'mysqls', 'keydbs', 'dragonflies', 'clickhouses', 'mariadbs', 'mongodbs', 'services', ]); // Eager load all relationships for applications including nested ones $this->applications = $this->environment->applications()->with([ 'tags', 'additional_servers.settings', 'additional_networks', 'destination.server.settings', 'settings', ])->get()->sortBy('name'); $projectUuid = $this->project->uuid; $environmentUuid = $this->environment->uuid; $this->applications = $this->applications->map(function ($application) use ($projectUuid, $environmentUuid) { $application->hrefLink = route('project.application.configuration', [ 'project_uuid' => $projectUuid, 'environment_uuid' => $environmentUuid, 'application_uuid' => $application->uuid, ]); return $application; }); // Load all database resources in a single query per type $databaseTypes = [ 'postgresqls' => 'postgresqls', 'redis' => 'redis', 'mongodbs' => 'mongodbs', 'mysqls' => 'mysqls', 'mariadbs' => 'mariadbs', 'keydbs' => 'keydbs', 'dragonflies' => 'dragonflies', 'clickhouses' => 'clickhouses', ]; foreach ($databaseTypes as $property => $relation) { $this->{$property} = $this->environment->{$relation}()->with([ 'tags', 'destination.server.settings', ])->get()->sortBy('name'); $this->{$property} = $this->{$property}->map(function ($db) use ($projectUuid, $environmentUuid) { $db->hrefLink = route('project.database.configuration', [ 'project_uuid' => $projectUuid, 'database_uuid' => $db->uuid, 'environment_uuid' => $environmentUuid, ]); return $db; }); } // Load services with their tags and server $this->services = $this->environment->services()->with([ 'tags', 'destination.server.settings', ])->get()->sortBy('name'); $this->services = $this->services->map(function ($service) use ($projectUuid, $environmentUuid) { $service->hrefLink = route('project.service.configuration', [ 'project_uuid' => $projectUuid, 'environment_uuid' => $environmentUuid, 'service_uuid' => $service->uuid, ]); return $service; }); } public function render() { return view('livewire.project.resource.index'); } } ================================================ FILE: app/Livewire/Project/Service/Configuration.php ================================================ currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceChecked" => 'serviceChecked', 'refreshServices' => 'refreshServices', 'refresh' => 'refreshServices', ]; } public function render() { return view('livewire.project.service.configuration'); } public function mount() { try { $this->parameters = get_route_parameters(); $this->currentRoute = request()->route()->getName(); $this->query = request()->query(); $project = currentTeam() ->projects() ->select('id', 'uuid', 'team_id') ->where('uuid', request()->route('project_uuid')) ->firstOrFail(); $environment = $project->environments() ->select('id', 'uuid', 'name', 'project_id') ->where('uuid', request()->route('environment_uuid')) ->firstOrFail(); $this->service = $environment->services()->whereUuid(request()->route('service_uuid'))->firstOrFail(); $this->authorize('view', $this->service); $this->project = $project; $this->environment = $environment; $this->applications = $this->service->applications->sort(); $this->databases = $this->service->databases->sort(); } catch (\Throwable $e) { return handleError($e, $this); } } public function refreshServices() { $this->service->refresh(); $this->applications = $this->service->applications->sort(); $this->databases = $this->service->databases->sort(); } public function restartApplication($id) { try { $this->authorize('update', $this->service); $application = $this->service->applications->find($id); if ($application) { $application->restart(); $this->dispatch('success', 'Service application restarted successfully.'); } } catch (\Exception $e) { return handleError($e, $this); } } public function restartDatabase($id) { try { $this->authorize('update', $this->service); $database = $this->service->databases->find($id); if ($database) { $database->restart(); $this->dispatch('success', 'Service database restarted successfully.'); } } catch (\Exception $e) { return handleError($e, $this); } } public function serviceChecked() { try { $this->service->applications->each(function ($application) { $application->refresh(); }); $this->service->databases->each(function ($database) { $database->refresh(); }); } catch (\Exception $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Service/DatabaseBackups.php ================================================ '$refresh']; public function mount() { try { $this->parameters = get_route_parameters(); $this->query = request()->query(); $this->service = Service::whereUuid($this->parameters['service_uuid'])->first(); if (! $this->service) { return redirect()->route('dashboard'); } $this->authorize('view', $this->service); $this->serviceDatabase = $this->service->databases()->whereUuid($this->parameters['stack_service_uuid'])->first(); if (! $this->serviceDatabase) { return redirect()->route('project.service.configuration', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_uuid' => $this->parameters['environment_uuid'], 'service_uuid' => $this->parameters['service_uuid'], ]); } // Check if backups are supported for this database if (! $this->serviceDatabase->isBackupSolutionAvailable() && ! $this->serviceDatabase->is_migrated) { return redirect()->route('project.service.index', $this->parameters); } // Check if import is supported for this database type $dbType = $this->serviceDatabase->databaseType(); $supportedTypes = ['mysql', 'mariadb', 'postgres', 'mongo']; $this->isImportSupported = collect($supportedTypes)->contains(fn ($type) => str_contains($dbType, $type)); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.service.database-backups'); } } ================================================ FILE: app/Livewire/Project/Service/EditCompose.php ================================================ 'envsUpdated', ]; protected $rules = [ 'dockerComposeRaw' => 'required', 'dockerCompose' => 'required', 'isContainerLabelEscapeEnabled' => 'required', ]; public function envsUpdated() { $this->dispatch('saveCompose', $this->dockerComposeRaw); $this->refreshEnvs(); } public function refreshEnvs() { $this->service = Service::ownedByCurrentTeam()->find($this->serviceId); $this->syncData(false); } public function mount() { $this->service = Service::ownedByCurrentTeam()->find($this->serviceId); $this->syncData(false); } private function syncData(bool $toModel = false): void { if ($toModel) { $this->service->docker_compose_raw = $this->dockerComposeRaw; $this->service->docker_compose = $this->dockerCompose; $this->service->is_container_label_escape_enabled = $this->isContainerLabelEscapeEnabled; } else { $this->dockerComposeRaw = $this->service->docker_compose_raw; $this->dockerCompose = $this->service->docker_compose; $this->isContainerLabelEscapeEnabled = $this->service->is_container_label_escape_enabled ?? false; } } public function validateCompose() { $isValid = validateComposeFile($this->dockerComposeRaw, $this->service->server_id); if ($isValid !== 'OK') { $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); } else { $this->dispatch('success', 'Docker compose is valid.'); } } public function saveEditedCompose() { $this->dispatch('info', 'Saving new docker compose...'); $this->dispatch('saveCompose', $this->dockerComposeRaw); $this->dispatch('refreshStorages'); } public function instantSave() { $this->validate([ 'isContainerLabelEscapeEnabled' => 'required', ]); $this->syncData(true); $this->service->save(['is_container_label_escape_enabled' => $this->isContainerLabelEscapeEnabled]); $this->dispatch('success', 'Service updated successfully'); } public function render() { return view('livewire.project.service.edit-compose'); } } ================================================ FILE: app/Livewire/Project/Service/EditDomain.php ================================================ 'nullable', ]; public function mount() { $this->application = ServiceApplication::ownedByCurrentTeam()->findOrFail($this->applicationId); $this->authorize('view', $this->application); $this->requiredPort = $this->application->getRequiredPort(); $this->syncData(); } public function syncData(bool $toModel = false): void { if ($toModel) { $this->validate(); // Sync to model $this->application->fqdn = $this->fqdn; $this->application->save(); } else { // Sync from model $this->fqdn = $this->application->fqdn; } } public function confirmDomainUsage() { $this->forceSaveDomains = true; $this->showDomainConflictModal = false; $this->submit(); } public function confirmRemovePort() { $this->forceRemovePort = true; $this->showPortWarningModal = false; $this->submit(); } public function cancelRemovePort() { $this->showPortWarningModal = false; $this->syncData(); // Reset to original FQDN } public function submit() { try { $this->authorize('update', $this->application); $this->fqdn = str($this->fqdn)->replaceEnd(',', '')->trim()->toString(); $this->fqdn = str($this->fqdn)->replaceStart(',', '')->trim()->toString(); $domains = str($this->fqdn)->trim()->explode(',')->map(function ($domain) { $domain = trim($domain); Url::fromString($domain, ['http', 'https']); return str($domain)->lower(); }); $this->fqdn = $domains->unique()->implode(','); $warning = sslipDomainWarning($this->fqdn); if ($warning) { $this->dispatch('warning', __('warning.sslipdomain')); } // Sync to model for domain conflict check (without validation) $this->application->fqdn = $this->fqdn; // Check for domain conflicts if not forcing save if (! $this->forceSaveDomains) { $result = checkDomainUsage(resource: $this->application); if ($result['hasConflicts']) { $this->domainConflicts = $result['conflicts']; $this->showDomainConflictModal = true; return; } } else { // Reset the force flag after using it $this->forceSaveDomains = false; } // Check for required port if (! $this->forceRemovePort) { $requiredPort = $this->application->getRequiredPort(); if ($requiredPort !== null) { // Check if all FQDNs have a port $fqdns = str($this->fqdn)->trim()->explode(','); $missingPort = false; foreach ($fqdns as $fqdn) { $fqdn = trim($fqdn); if (empty($fqdn)) { continue; } $port = ServiceApplication::extractPortFromUrl($fqdn); if ($port === null) { $missingPort = true; break; } } if ($missingPort) { $this->requiredPort = $requiredPort; $this->showPortWarningModal = true; return; } } } else { // Reset the force flag after using it $this->forceRemovePort = false; } $this->validate(); $this->application->save(); $this->application->refresh(); $this->syncData(); updateCompose($this->application); if (str($this->application->fqdn)->contains(',')) { $this->dispatch('warning', 'Some services do not support multiple domains, which can lead to problems and is NOT RECOMMENDED.

Only use multiple domains if you know what you are doing.'); } $this->application->service->parse(); $this->dispatch('refresh'); $this->dispatch('refreshServices'); $this->dispatch('configurationChanged'); } catch (\Throwable $e) { $originalFqdn = $this->application->getOriginal('fqdn'); if ($originalFqdn !== $this->application->fqdn) { $this->application->fqdn = $originalFqdn; $this->syncData(); } return handleError($e, $this); } } public function render() { return view('livewire.project.service.edit-domain'); } } ================================================ FILE: app/Livewire/Project/Service/FileStorage.php ================================================ 'required', 'fileStorage.fs_path' => 'required', 'fileStorage.mount_path' => 'required', 'content' => 'nullable', 'isBasedOnGit' => 'required|boolean', ]; public function mount() { $this->resource = $this->fileStorage->service; if (str($this->fileStorage->fs_path)->startsWith('.')) { $this->workdir = $this->resource->service?->workdir(); $this->fs_path = str($this->fileStorage->fs_path)->after('.'); } else { $this->workdir = null; $this->fs_path = $this->fileStorage->fs_path; } $this->isReadOnly = $this->fileStorage->shouldBeReadOnlyInUI(); $this->syncData(); } public function syncData(bool $toModel = false): void { if ($toModel) { $this->validate(); // Sync to model $this->fileStorage->content = $this->content; $this->fileStorage->is_based_on_git = $this->isBasedOnGit; $this->fileStorage->save(); } else { // Sync from model $this->content = $this->fileStorage->content; $this->isBasedOnGit = $this->fileStorage->is_based_on_git; } } public function convertToDirectory() { try { $this->authorize('update', $this->resource); $this->fileStorage->deleteStorageOnServer(); $this->fileStorage->is_directory = true; $this->fileStorage->content = null; $this->fileStorage->is_based_on_git = false; $this->fileStorage->save(); $this->fileStorage->saveStorageOnServer(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('refreshStorages'); } } public function loadStorageOnServer() { try { // Loading content is a read operation, so we use 'view' permission $this->authorize('view', $this->resource); $this->fileStorage->loadStorageOnServer(); $this->syncData(); $this->dispatch('success', 'File storage loaded from server.'); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('refreshStorages'); } } public function convertToFile() { try { $this->authorize('update', $this->resource); $this->fileStorage->deleteStorageOnServer(); $this->fileStorage->is_directory = false; $this->fileStorage->content = null; if (data_get($this->resource, 'settings.is_preserve_repository_enabled')) { $this->fileStorage->is_based_on_git = true; } $this->fileStorage->save(); $this->fileStorage->saveStorageOnServer(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('refreshStorages'); } } public function delete($password, $selectedActions = []) { $this->authorize('update', $this->resource); if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } try { $message = 'File deleted.'; if ($this->fileStorage->is_directory) { $message = 'Directory deleted.'; } if ($this->permanently_delete) { $message = 'Directory deleted from the server.'; $this->fileStorage->deleteStorageOnServer(); } $this->fileStorage->delete(); $this->dispatch('success', $message); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('refreshStorages'); } return true; } public function submit() { $this->authorize('update', $this->resource); $original = $this->fileStorage->getOriginal(); try { $this->validate(); if ($this->fileStorage->is_directory) { $this->content = null; } // Sync component properties to model $this->fileStorage->content = $this->content; $this->fileStorage->is_based_on_git = $this->isBasedOnGit; $this->fileStorage->save(); $this->fileStorage->saveStorageOnServer(); $this->dispatch('success', 'File updated.'); } catch (\Throwable $e) { $this->fileStorage->setRawAttributes($original); $this->fileStorage->save(); $this->syncData(); return handleError($e, $this); } } public function instantSave() { $this->submit(); } public function render() { return view('livewire.project.service.file-storage', [ 'directoryDeletionCheckboxes' => [ ['id' => 'permanently_delete', 'label' => 'The selected directory and all its contents will be permantely deleted form the server.'], ], 'fileDeletionCheckboxes' => [ ['id' => 'permanently_delete', 'label' => 'The selected file will be permanently deleted form the server.'], ], ]); } } ================================================ FILE: app/Livewire/Project/Service/Heading.php ================================================ service->status)->contains('running') && is_null($this->service->config_hash)) { $this->service->isConfigurationChanged(true); $this->dispatch('configurationChanged'); } } public function getListeners() { $teamId = Auth::user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceStatusChanged" => 'checkStatus', "echo-private:team.{$teamId},ServiceChecked" => 'serviceChecked', 'refresh' => '$refresh', 'envsUpdated' => '$refresh', ]; } public function checkStatus() { if ($this->service->server->isFunctional()) { GetContainersStatus::dispatch($this->service->server); } else { $this->dispatch('error', 'Server is not functional.'); } } public function manualCheckStatus() { $this->checkStatus(); } public function serviceChecked() { try { $this->service->applications->each(function ($application) { $application->refresh(); }); $this->service->databases->each(function ($database) { $database->refresh(); }); if (is_null($this->service->config_hash)) { $this->service->isConfigurationChanged(true); } $this->dispatch('configurationChanged'); } catch (\Exception $e) { return handleError($e, $this); } finally { $this->dispatch('refresh')->self(); } } public function checkDeployments() { try { $activity = Activity::where('properties->type_uuid', $this->service->uuid)->latest()->first(); $status = data_get($activity, 'properties.status'); if ($status === ProcessStatus::QUEUED->value || $status === ProcessStatus::IN_PROGRESS->value) { $this->isDeploymentProgress = true; } else { $this->isDeploymentProgress = false; } } catch (\Throwable) { $this->isDeploymentProgress = false; } return $this->isDeploymentProgress; } public function start() { $activity = StartService::run($this->service, pullLatestImages: true); $this->dispatch('activityMonitor', $activity->id); } public function forceDeploy() { try { $activities = Activity::where('properties->type_uuid', $this->service->uuid) ->where(function ($q) { $q->where('properties->status', ProcessStatus::IN_PROGRESS->value) ->orWhere('properties->status', ProcessStatus::QUEUED->value); })->get(); foreach ($activities as $activity) { $activity->properties->status = ProcessStatus::ERROR->value; $activity->save(); } $activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true); $this->dispatch('activityMonitor', $activity->id); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } public function stop() { try { StopService::dispatch($this->service, false, $this->docker_cleanup); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } public function restart() { $this->checkDeployments(); if ($this->isDeploymentProgress) { $this->dispatch('error', 'There is a deployment in progress.'); return; } $activity = StartService::run($this->service, stopBeforeStart: true); $this->dispatch('activityMonitor', $activity->id); } public function pullAndRestartEvent() { $this->checkDeployments(); if ($this->isDeploymentProgress) { $this->dispatch('error', 'There is a deployment in progress.'); return; } $activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true); $this->dispatch('activityMonitor', $activity->id); } public function render() { return view('livewire.project.service.heading', [ 'checkboxes' => [ ['id' => 'docker_cleanup', 'label' => __('resource.docker_cleanup')], ], ]); } } ================================================ FILE: app/Livewire/Project/Service/Index.php ================================================ '$refresh', 'refreshFileStorages']; protected $rules = [ 'humanName' => 'nullable', 'description' => 'nullable', 'image' => 'required', 'excludeFromStatus' => 'required|boolean', 'publicPort' => 'nullable|integer', 'publicPortTimeout' => 'nullable|integer|min:1', 'isPublic' => 'required|boolean', 'isLogDrainEnabled' => 'required|boolean', // Application-specific rules 'fqdn' => 'nullable', 'isGzipEnabled' => 'nullable|boolean', 'isStripprefixEnabled' => 'nullable|boolean', ]; public function mount() { try { $this->services = collect([]); $this->parameters = get_route_parameters(); $this->query = request()->query(); $this->currentRoute = request()->route()->getName(); $this->service = Service::whereUuid($this->parameters['service_uuid'])->first(); if (! $this->service) { return redirect()->route('dashboard'); } $this->authorize('view', $this->service); $service = $this->service->applications()->whereUuid($this->parameters['stack_service_uuid'])->first(); if ($service) { $this->serviceApplication = $service; $this->resourceType = 'application'; $this->serviceApplication->getFilesFromServer(); $this->initializeApplicationProperties(); } else { $this->serviceDatabase = $this->service->databases()->whereUuid($this->parameters['stack_service_uuid'])->first(); if (! $this->serviceDatabase) { return redirect()->route('project.service.configuration', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_uuid' => $this->parameters['environment_uuid'], 'service_uuid' => $this->parameters['service_uuid'], ]); } $this->resourceType = 'database'; $this->serviceDatabase->getFilesFromServer(); $this->initializeDatabaseProperties(); } $this->s3s = currentTeam()->s3s; } catch (\Throwable $e) { return handleError($e, $this); } } private function initializeDatabaseProperties(): void { $this->server = $this->serviceDatabase->service->destination->server; if ($this->serviceDatabase->is_public) { $this->db_url_public = $this->serviceDatabase->getServiceDatabaseUrl(); } $this->refreshFileStorages(); $this->syncDatabaseData(false); // Check if import is supported for this database type $dbType = $this->serviceDatabase->databaseType(); $supportedTypes = ['mysql', 'mariadb', 'postgres', 'mongo']; $this->isImportSupported = collect($supportedTypes)->contains(fn ($type) => str_contains($dbType, $type)); } private function syncDatabaseData(bool $toModel = false): void { if ($toModel) { $this->serviceDatabase->human_name = $this->humanName; $this->serviceDatabase->description = $this->description; $this->serviceDatabase->image = $this->image; $this->serviceDatabase->exclude_from_status = $this->excludeFromStatus; $this->serviceDatabase->public_port = $this->publicPort; $this->serviceDatabase->public_port_timeout = $this->publicPortTimeout; $this->serviceDatabase->is_public = $this->isPublic; $this->serviceDatabase->is_log_drain_enabled = $this->isLogDrainEnabled; } else { $this->humanName = $this->serviceDatabase->human_name; $this->description = $this->serviceDatabase->description; $this->image = $this->serviceDatabase->image; $this->excludeFromStatus = $this->serviceDatabase->exclude_from_status ?? false; $this->publicPort = $this->serviceDatabase->public_port; $this->publicPortTimeout = $this->serviceDatabase->public_port_timeout; $this->isPublic = $this->serviceDatabase->is_public ?? false; $this->isLogDrainEnabled = $this->serviceDatabase->is_log_drain_enabled ?? false; } } public function generateDockerCompose() { try { $this->authorize('update', $this->service); $this->service->parse(); } catch (\Throwable $e) { return handleError($e, $this); } } // Database-specific methods public function refreshFileStorages() { if ($this->serviceDatabase) { $this->fileStorages = $this->serviceDatabase->fileStorages()->get(); } } public function deleteDatabase($password, $selectedActions = []) { try { $this->authorize('delete', $this->serviceDatabase); if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } $this->serviceDatabase->delete(); $this->dispatch('success', 'Database deleted.'); return redirectRoute($this, 'project.service.configuration', $this->parameters); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSaveExclude() { try { $this->authorize('update', $this->serviceDatabase); $this->submitDatabase(); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSaveLogDrain() { try { $this->authorize('update', $this->serviceDatabase); if (! $this->serviceDatabase->service->destination->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->submitDatabase(); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function convertToApplication() { try { $this->authorize('update', $this->serviceDatabase); $service = $this->serviceDatabase->service; $serviceDatabase = $this->serviceDatabase; // Check if application with same name already exists if ($service->applications()->where('name', $serviceDatabase->name)->exists()) { throw new \Exception('An application with this name already exists.'); } // Create new parameters removing database_uuid $redirectParams = collect($this->parameters) ->except('database_uuid') ->all(); DB::transaction(function () use ($service, $serviceDatabase) { $service->applications()->create([ 'name' => $serviceDatabase->name, 'human_name' => $serviceDatabase->human_name, 'description' => $serviceDatabase->description, 'exclude_from_status' => $serviceDatabase->exclude_from_status, 'is_log_drain_enabled' => $serviceDatabase->is_log_drain_enabled, 'image' => $serviceDatabase->image, 'service_id' => $service->id, 'is_migrated' => true, ]); $serviceDatabase->delete(); }); return redirectRoute($this, 'project.service.configuration', $redirectParams); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSave() { try { $this->authorize('update', $this->serviceDatabase); if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; return; } $this->syncDatabaseData(true); if ($this->serviceDatabase->is_public) { if (! str($this->serviceDatabase->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->isPublic = false; $this->serviceDatabase->is_public = false; return; } StartDatabaseProxy::run($this->serviceDatabase); $this->db_url_public = $this->serviceDatabase->getServiceDatabaseUrl(); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->serviceDatabase); $this->db_url_public = null; $this->dispatch('success', 'Database is no longer publicly accessible.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function submitDatabase() { try { $this->authorize('update', $this->serviceDatabase); $this->validate(); $this->syncDatabaseData(true); $this->serviceDatabase->save(); $this->serviceDatabase->refresh(); $this->syncDatabaseData(false); updateCompose($this->serviceDatabase); $this->dispatch('success', 'Database saved.'); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->dispatch('generateDockerCompose'); } } // Application-specific methods private function initializeApplicationProperties(): void { $this->requiredPort = $this->serviceApplication->getRequiredPort(); $this->syncApplicationData(false); } private function syncApplicationData(bool $toModel = false): void { if ($toModel) { $this->serviceApplication->human_name = $this->humanName; $this->serviceApplication->description = $this->description; $this->serviceApplication->fqdn = $this->fqdn; $this->serviceApplication->image = $this->image; $this->serviceApplication->exclude_from_status = $this->excludeFromStatus; $this->serviceApplication->is_log_drain_enabled = $this->isLogDrainEnabled; $this->serviceApplication->is_gzip_enabled = $this->isGzipEnabled; $this->serviceApplication->is_stripprefix_enabled = $this->isStripprefixEnabled; } else { $this->humanName = $this->serviceApplication->human_name; $this->description = $this->serviceApplication->description; $this->fqdn = $this->serviceApplication->fqdn; $this->image = $this->serviceApplication->image; $this->excludeFromStatus = data_get($this->serviceApplication, 'exclude_from_status', false); $this->isLogDrainEnabled = data_get($this->serviceApplication, 'is_log_drain_enabled', false); $this->isGzipEnabled = data_get($this->serviceApplication, 'is_gzip_enabled', true); $this->isStripprefixEnabled = data_get($this->serviceApplication, 'is_stripprefix_enabled', true); } } public function instantSaveApplication() { try { $this->authorize('update', $this->serviceApplication); $this->submitApplication(); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSaveApplicationSettings() { try { $this->authorize('update', $this->serviceApplication); $this->serviceApplication->is_gzip_enabled = $this->isGzipEnabled; $this->serviceApplication->is_stripprefix_enabled = $this->isStripprefixEnabled; $this->serviceApplication->exclude_from_status = $this->excludeFromStatus; $this->serviceApplication->save(); $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSaveApplicationAdvanced() { try { $this->authorize('update', $this->serviceApplication); if (! $this->serviceApplication->service->destination->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } $this->syncApplicationData(true); $this->serviceApplication->save(); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function deleteApplication($password, $selectedActions = []) { try { $this->authorize('delete', $this->serviceApplication); if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } $this->serviceApplication->delete(); $this->dispatch('success', 'Application deleted.'); return redirect()->route('project.service.configuration', $this->parameters); } catch (\Throwable $e) { return handleError($e, $this); } } public function convertToDatabase() { try { $this->authorize('update', $this->serviceApplication); $service = $this->serviceApplication->service; $serviceApplication = $this->serviceApplication; if ($service->databases()->where('name', $serviceApplication->name)->exists()) { throw new \Exception('A database with this name already exists.'); } $redirectParams = collect($this->parameters) ->except('database_uuid') ->all(); DB::transaction(function () use ($service, $serviceApplication) { $service->databases()->create([ 'name' => $serviceApplication->name, 'human_name' => $serviceApplication->human_name, 'description' => $serviceApplication->description, 'exclude_from_status' => $serviceApplication->exclude_from_status, 'is_log_drain_enabled' => $serviceApplication->is_log_drain_enabled, 'image' => $serviceApplication->image, 'service_id' => $service->id, 'is_migrated' => true, ]); $serviceApplication->delete(); }); return redirect()->route('project.service.configuration', $redirectParams); } catch (\Throwable $e) { return handleError($e, $this); } } public function confirmDomainUsage() { $this->forceSaveDomains = true; $this->showDomainConflictModal = false; $this->submitApplication(); } public function confirmRemovePort() { $this->forceRemovePort = true; $this->showPortWarningModal = false; $this->submitApplication(); } public function cancelRemovePort() { $this->showPortWarningModal = false; $this->syncApplicationData(false); } public function submitApplication() { try { $this->authorize('update', $this->serviceApplication); $this->fqdn = str($this->fqdn)->replaceEnd(',', '')->trim()->toString(); $this->fqdn = str($this->fqdn)->replaceStart(',', '')->trim()->toString(); $domains = str($this->fqdn)->trim()->explode(',')->map(function ($domain) { $domain = trim($domain); Url::fromString($domain, ['http', 'https']); return str($domain)->lower(); }); $this->fqdn = $domains->unique()->implode(','); $warning = sslipDomainWarning($this->fqdn); if ($warning) { $this->dispatch('warning', __('warning.sslipdomain')); } $this->syncApplicationData(true); if (! $this->forceSaveDomains) { $result = checkDomainUsage(resource: $this->serviceApplication); if ($result['hasConflicts']) { $this->domainConflicts = $result['conflicts']; $this->showDomainConflictModal = true; return; } } else { $this->forceSaveDomains = false; } if (! $this->forceRemovePort) { $requiredPort = $this->serviceApplication->getRequiredPort(); if ($requiredPort !== null) { $fqdns = str($this->fqdn)->trim()->explode(','); $missingPort = false; foreach ($fqdns as $fqdn) { $fqdn = trim($fqdn); if (empty($fqdn)) { continue; } $port = ServiceApplication::extractPortFromUrl($fqdn); if ($port === null) { $missingPort = true; break; } } if ($missingPort) { $this->requiredPort = $requiredPort; $this->showPortWarningModal = true; return; } } } else { $this->forceRemovePort = false; } $this->validate(); $this->serviceApplication->save(); $this->serviceApplication->refresh(); $this->syncApplicationData(false); updateCompose($this->serviceApplication); if (str($this->serviceApplication->fqdn)->contains(',')) { $this->dispatch('warning', 'Some services do not support multiple domains, which can lead to problems and is NOT RECOMMENDED.

Only use multiple domains if you know what you are doing.'); } else { ! $warning && $this->dispatch('success', 'Service saved.'); } $this->dispatch('generateDockerCompose'); } catch (\Throwable $e) { $originalFqdn = $this->serviceApplication->getOriginal('fqdn'); if ($originalFqdn !== $this->serviceApplication->fqdn) { $this->serviceApplication->fqdn = $originalFqdn; $this->syncApplicationData(false); } return handleError($e, $this); } } public function render() { return view('livewire.project.service.index'); } } ================================================ FILE: app/Livewire/Project/Service/StackForm.php ================================================ 'required', 'dockerCompose' => 'nullable', 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'connectToDockerNetwork' => 'nullable', ]; // Add dynamic field rules foreach ($this->fields ?? collect() as $key => $field) { $rules = data_get($field, 'rules', 'nullable'); $baseRules["fields.$key.value"] = $rules; } return $baseRules; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', 'dockerComposeRaw.required' => 'The Docker Compose Raw field is required.', 'dockerCompose.required' => 'The Docker Compose field is required.', ] ); } public $validationAttributes = []; /** * Sync data between component properties and model * * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties. */ private function syncData(bool $toModel = false): void { if ($toModel) { // Sync TO model (before save) $this->service->name = $this->name; $this->service->description = $this->description; $this->service->docker_compose_raw = $this->dockerComposeRaw; $this->service->docker_compose = $this->dockerCompose; $this->service->connect_to_docker_network = $this->connectToDockerNetwork; } else { // Sync FROM model (on load/refresh) $this->name = $this->service->name; $this->description = $this->service->description; $this->dockerComposeRaw = $this->service->docker_compose_raw; $this->dockerCompose = $this->service->docker_compose; $this->connectToDockerNetwork = $this->service->connect_to_docker_network; } } public function mount() { $this->syncData(false); $this->fields = collect([]); $extraFields = $this->service->extraFields(); foreach ($extraFields as $serviceName => $fields) { foreach ($fields as $fieldKey => $field) { $key = data_get($field, 'key'); $value = data_get($field, 'value'); $rules = data_get($field, 'rules', 'nullable'); $isPassword = data_get($field, 'isPassword', false); $customHelper = data_get($field, 'customHelper', false); $this->fields->put($key, [ 'serviceName' => $serviceName, 'key' => $key, 'name' => $fieldKey, 'value' => $value, 'isPassword' => $isPassword, 'rules' => $rules, 'customHelper' => $customHelper, ]); $this->validationAttributes["fields.$key.value"] = $fieldKey; } } $this->fields = $this->fields->groupBy('serviceName')->map(function ($group) { return $group->sortBy(function ($field) { return data_get($field, 'isPassword') ? 1 : 0; })->mapWithKeys(function ($field) { return [$field['key'] => $field]; }); })->flatMap(function ($group) { return $group; }); } public function saveCompose($raw) { $this->dockerComposeRaw = $raw; $this->submit(notify: true); } public function instantSave() { $this->syncData(true); $this->service->save(); $this->dispatch('success', 'Service settings saved.'); } public function submit($notify = true) { try { $this->validate(); $this->syncData(true); // Validate for command injection BEFORE any database operations validateDockerComposeForInjection($this->service->docker_compose_raw); // Use transaction to ensure atomicity - if parse fails, save is rolled back DB::transaction(function () { $this->service->save(); $this->service->saveExtraFields($this->fields); $this->service->parse(); }); // Refresh and write files after a successful commit $this->service->refresh(); $this->service->saveComposeConfigs(); $this->dispatch('refreshEnvs'); $this->dispatch('refreshServices'); $notify && $this->dispatch('success', 'Service saved.'); } catch (\Throwable $e) { // On error, refresh from database to restore clean state $this->service->refresh(); $this->syncData(false); return handleError($e, $this); } finally { if (is_null($this->service->config_hash)) { $this->service->isConfigurationChanged(true); } else { $this->dispatch('configurationChanged'); } } } public function render() { return view('livewire.project.service.stack-form'); } } ================================================ FILE: app/Livewire/Project/Service/Storage.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},FileStorageChanged" => 'refreshStoragesFromEvent', 'refreshStorages', 'addNewVolume', ]; } public function mount() { if (str($this->resource->getMorphClass())->contains('Standalone')) { $this->file_storage_directory_source = database_configuration_dir()."/{$this->resource->uuid}"; } else { $this->file_storage_directory_source = application_configuration_dir()."/{$this->resource->uuid}"; } if ($this->resource->getMorphClass() === \App\Models\Application::class) { if ($this->resource->destination->server->isSwarm()) { $this->isSwarm = true; } } $this->refreshStorages(); } public function refreshStoragesFromEvent() { $this->refreshStorages(); $this->dispatch('warning', 'File storage changed. Usually it means that the file / directory is already defined on the server, so Coolify set it up for you properly on the UI.'); } public function refreshStorages() { $this->fileStorage = $this->resource->fileStorages()->get(); $this->resource->load('persistentStorages.resource'); } public function getFilesProperty() { return $this->fileStorage->where('is_directory', false); } public function getDirectoriesProperty() { return $this->fileStorage->where('is_directory', true); } public function getVolumeCountProperty() { return $this->resource->persistentStorages()->count(); } public function getFileCountProperty() { return $this->files->count(); } public function getDirectoryCountProperty() { return $this->directories->count(); } public function submitPersistentVolume() { try { $this->authorize('update', $this->resource); $this->validate([ 'name' => 'required|string', 'mount_path' => 'required|string', 'host_path' => $this->isSwarm ? 'required|string' : 'string|nullable', ]); $name = $this->resource->uuid.'-'.$this->name; LocalPersistentVolume::create([ 'name' => $name, 'mount_path' => $this->mount_path, 'host_path' => $this->host_path, 'resource_id' => $this->resource->id, 'resource_type' => $this->resource->getMorphClass(), ]); $this->resource->refresh(); $this->dispatch('success', 'Volume added successfully'); $this->dispatch('closeStorageModal', 'volume'); $this->clearForm(); $this->refreshStorages(); } catch (\Throwable $e) { return handleError($e, $this); } } public function submitFileStorage() { try { $this->authorize('update', $this->resource); $this->validate([ 'file_storage_path' => 'required|string', 'file_storage_content' => 'nullable|string', ]); $this->file_storage_path = trim($this->file_storage_path); $this->file_storage_path = str($this->file_storage_path)->start('/')->value(); if ($this->resource->getMorphClass() === \App\Models\Application::class) { $fs_path = application_configuration_dir().'/'.$this->resource->uuid.$this->file_storage_path; } elseif (str($this->resource->getMorphClass())->contains('Standalone')) { $fs_path = database_configuration_dir().'/'.$this->resource->uuid.$this->file_storage_path; } else { throw new \Exception('No valid resource type for file mount storage type!'); } \App\Models\LocalFileVolume::create([ 'fs_path' => $fs_path, 'mount_path' => $this->file_storage_path, 'content' => $this->file_storage_content, 'is_directory' => false, 'resource_id' => $this->resource->id, 'resource_type' => get_class($this->resource), ]); $this->dispatch('success', 'File mount added successfully'); $this->dispatch('closeStorageModal', 'file'); $this->clearForm(); $this->refreshStorages(); } catch (\Throwable $e) { return handleError($e, $this); } } public function submitFileStorageDirectory() { try { $this->authorize('update', $this->resource); $this->validate([ 'file_storage_directory_source' => 'required|string', 'file_storage_directory_destination' => 'required|string', ]); $this->file_storage_directory_source = trim($this->file_storage_directory_source); $this->file_storage_directory_source = str($this->file_storage_directory_source)->start('/')->value(); $this->file_storage_directory_destination = trim($this->file_storage_directory_destination); $this->file_storage_directory_destination = str($this->file_storage_directory_destination)->start('/')->value(); // Validate paths to prevent command injection validateShellSafePath($this->file_storage_directory_source, 'storage source path'); validateShellSafePath($this->file_storage_directory_destination, 'storage destination path'); \App\Models\LocalFileVolume::create([ 'fs_path' => $this->file_storage_directory_source, 'mount_path' => $this->file_storage_directory_destination, 'is_directory' => true, 'resource_id' => $this->resource->id, 'resource_type' => get_class($this->resource), ]); $this->dispatch('success', 'Directory mount added successfully'); $this->dispatch('closeStorageModal', 'directory'); $this->clearForm(); $this->refreshStorages(); } catch (\Throwable $e) { return handleError($e, $this); } } public function clearForm() { $this->name = ''; $this->mount_path = ''; $this->host_path = null; $this->file_storage_path = ''; $this->file_storage_content = null; $this->file_storage_directory_destination = ''; if (str($this->resource->getMorphClass())->contains('Standalone')) { $this->file_storage_directory_source = database_configuration_dir()."/{$this->resource->uuid}"; } else { $this->file_storage_directory_source = application_configuration_dir()."/{$this->resource->uuid}"; } } public function render() { return view('livewire.project.service.storage'); } } ================================================ FILE: app/Livewire/Project/Shared/ConfigurationChecker.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ApplicationConfigurationChanged" => 'configurationChanged', 'configurationChanged' => 'configurationChanged', ]; } public function mount() { $this->configurationChanged(); } public function render() { return view('livewire.project.shared.configuration-checker'); } public function configurationChanged() { $this->isConfigurationChanged = $this->resource->isConfigurationChanged(); } } ================================================ FILE: app/Livewire/Project/Shared/Danger.php ================================================ modalId = new Cuid2; $this->projectUuid = data_get($parameters, 'project_uuid'); $this->environmentUuid = data_get($parameters, 'environment_uuid'); if ($this->resource === null) { if (isset($parameters['service_uuid'])) { $this->resource = Service::ownedByCurrentTeam()->where('uuid', $parameters['service_uuid'])->first(); } elseif (isset($parameters['stack_service_uuid'])) { $this->resource = ServiceApplication::ownedByCurrentTeam()->where('uuid', $parameters['stack_service_uuid'])->first() ?? ServiceDatabase::ownedByCurrentTeam()->where('uuid', $parameters['stack_service_uuid'])->first(); } } if ($this->resource === null) { $this->resourceName = 'Unknown Resource'; return; } if (! method_exists($this->resource, 'type')) { $this->resourceName = 'Unknown Resource'; return; } $this->resourceName = match ($this->resource->type()) { 'application' => $this->resource->name ?? 'Application', 'standalone-postgresql', 'standalone-redis', 'standalone-mongodb', 'standalone-mysql', 'standalone-mariadb', 'standalone-keydb', 'standalone-dragonfly', 'standalone-clickhouse' => $this->resource->name ?? 'Database', 'service' => $this->resource->name ?? 'Service', 'service-application' => $this->resource->name ?? 'Service Application', 'service-database' => $this->resource->name ?? 'Service Database', default => 'Unknown Resource', }; // Check if user can delete this resource try { $this->canDelete = auth()->user()->can('delete', $this->resource); } catch (\Exception $e) { $this->canDelete = false; } } public function delete($password, $selectedActions = []) { if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } if (! $this->resource) { return 'Resource not found.'; } if (! empty($selectedActions)) { $this->delete_volumes = in_array('delete_volumes', $selectedActions); $this->delete_connected_networks = in_array('delete_connected_networks', $selectedActions); $this->delete_configurations = in_array('delete_configurations', $selectedActions); $this->docker_cleanup = in_array('docker_cleanup', $selectedActions); } try { $this->authorize('delete', $this->resource); $this->resource->delete(); DeleteResourceJob::dispatch( $this->resource, $this->delete_volumes, $this->delete_connected_networks, $this->delete_configurations, $this->docker_cleanup ); return redirectRoute($this, 'project.resource.index', [ 'project_uuid' => $this->projectUuid, 'environment_uuid' => $this->environmentUuid, ]); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.shared.danger', [ 'checkboxes' => [ ['id' => 'delete_volumes', 'label' => __('resource.delete_volumes')], ['id' => 'delete_connected_networks', 'label' => __('resource.delete_connected_networks')], ['id' => 'delete_configurations', 'label' => __('resource.delete_configurations')], ['id' => 'docker_cleanup', 'label' => __('resource.docker_cleanup')], // ['id' => 'delete_associated_backups_locally', 'label' => 'All backups associated with this Ressource will be permanently deleted from local storage.'], // ['id' => 'delete_associated_backups_s3', 'label' => 'All backups associated with this Ressource will be permanently deleted from the selected S3 Storage.'], // ['id' => 'delete_associated_backups_sftp', 'label' => 'All backups associated with this Ressource will be permanently deleted from the selected SFTP Storage.'] ], ]); } } ================================================ FILE: app/Livewire/Project/Shared/Destination.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ApplicationStatusChanged" => 'loadData', "echo-private:team.{$teamId},ServiceStatusChanged" => 'mount', 'refresh' => 'mount', ]; } public function mount() { $this->networks = collect([]); $this->loadData(); } public function loadData() { $all_networks = collect([]); $all_networks = $all_networks->push($this->resource->destination); $all_networks = $all_networks->merge($this->resource->additional_networks); $this->networks = Server::isUsable()->get()->map(function ($server) { return $server->standaloneDockers; })->flatten(); $this->networks = $this->networks->reject(function ($network) use ($all_networks) { return $all_networks->pluck('id')->contains($network->id); }); $this->networks = $this->networks->reject(function ($network) { return $this->resource->destination->server->id == $network->server->id; }); if ($this->resource?->additional_servers?->count() > 0) { $this->networks = $this->networks->reject(function ($network) { return $this->resource->additional_servers->pluck('id')->contains($network->server->id); }); } } public function stop($serverId) { try { $server = Server::ownedByCurrentTeam()->findOrFail($serverId); StopApplicationOneServer::run($this->resource, $server); $this->refreshServers(); } catch (\Exception $e) { return handleError($e, $this); } } public function redeploy(int $network_id, int $server_id) { try { if ($this->resource->additional_servers->count() > 0 && str($this->resource->docker_registry_image_name)->isEmpty()) { $this->dispatch('error', 'Failed to deploy.', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.
More information here: documentation'); return; } $deployment_uuid = new Cuid2; $server = Server::ownedByCurrentTeam()->findOrFail($server_id); $destination = $server->standaloneDockers->where('id', $network_id)->firstOrFail(); $result = queue_application_deployment( deployment_uuid: $deployment_uuid, application: $this->resource, server: $server, destination: $destination, only_this_server: true, no_questions_asked: true, ); if ($result['status'] === 'queue_full') { $this->dispatch('error', 'Deployment queue full', $result['message']); return; } if ($result['status'] === 'skipped') { $this->dispatch('success', 'Deployment skipped', $result['message']); return; } return redirectRoute($this, 'project.application.deployment.show', [ 'project_uuid' => data_get($this->resource, 'environment.project.uuid'), 'application_uuid' => data_get($this->resource, 'uuid'), 'deployment_uuid' => $deployment_uuid, 'environment_uuid' => data_get($this->resource, 'environment.uuid'), ]); } catch (\Exception $e) { return handleError($e, $this); } } public function promote(int $network_id, int $server_id) { $main_destination = $this->resource->destination; $this->resource->update([ 'destination_id' => $network_id, 'destination_type' => StandaloneDocker::class, ]); $this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]); $this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]); $this->refreshServers(); $this->resource->refresh(); } public function refreshServers() { GetContainersStatus::run($this->resource->destination->server); $this->loadData(); $this->dispatch('refresh'); } public function addServer(int $network_id, int $server_id) { $this->resource->additional_networks()->attach($network_id, ['server_id' => $server_id]); $this->dispatch('refresh'); } public function removeServer(int $network_id, int $server_id, $password, $selectedActions = []) { try { if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } if ($this->resource->destination->server->id == $server_id && $this->resource->destination->id == $network_id) { $this->dispatch('error', 'You are trying to remove the main server.'); return; } $server = Server::ownedByCurrentTeam()->findOrFail($server_id); StopApplicationOneServer::run($this->resource, $server); $this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]); $this->loadData(); $this->dispatch('refresh'); ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id')); return true; } catch (\Exception $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Shared/EnvironmentVariable/Add.php ================================================ 'clear']; protected $rules = [ 'key' => 'required|string', 'value' => 'nullable', 'is_multiline' => 'required|boolean', 'is_literal' => 'required|boolean', 'is_runtime' => 'required|boolean', 'is_buildtime' => 'required|boolean', 'comment' => 'nullable|string|max:256', ]; protected $validationAttributes = [ 'key' => 'key', 'value' => 'value', 'is_multiline' => 'multiline', 'is_literal' => 'literal', 'is_runtime' => 'runtime', 'is_buildtime' => 'buildtime', 'comment' => 'comment', ]; public function mount() { $this->parameters = get_route_parameters(); $this->problematicVariables = self::getProblematicVariablesForFrontend(); } #[Computed] public function availableSharedVariables(): array { $team = currentTeam(); $result = [ 'team' => [], 'project' => [], 'environment' => [], ]; // Early return if no team if (! $team) { return $result; } // Check if user can view team variables try { $this->authorize('view', $team); $result['team'] = $team->environment_variables() ->pluck('key') ->toArray(); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User not authorized to view team variables } // Get project variables if we have a project_uuid in route $projectUuid = data_get($this->parameters, 'project_uuid'); if ($projectUuid) { $project = Project::where('team_id', $team->id) ->where('uuid', $projectUuid) ->first(); if ($project) { try { $this->authorize('view', $project); $result['project'] = $project->environment_variables() ->pluck('key') ->toArray(); // Get environment variables if we have an environment_uuid in route $environmentUuid = data_get($this->parameters, 'environment_uuid'); if ($environmentUuid) { $environment = $project->environments() ->where('uuid', $environmentUuid) ->first(); if ($environment) { try { $this->authorize('view', $environment); $result['environment'] = $environment->environment_variables() ->pluck('key') ->toArray(); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User not authorized to view environment variables } } } } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User not authorized to view project variables } } } return $result; } public function submit() { $this->validate(); $this->dispatch('saveKey', [ 'key' => $this->key, 'value' => $this->value, 'is_multiline' => $this->is_multiline, 'is_literal' => $this->is_literal, 'is_runtime' => $this->is_runtime, 'is_buildtime' => $this->is_buildtime, 'is_preview' => $this->is_preview, 'comment' => $this->comment, ]); $this->clear(); } public function clear() { $this->key = ''; $this->value = ''; $this->is_multiline = false; $this->is_literal = false; $this->is_runtime = true; $this->is_buildtime = true; $this->comment = null; } } ================================================ FILE: app/Livewire/Project/Shared/EnvironmentVariable/All.php ================================================ 'submit', 'refreshEnvs', 'environmentVariableDeleted' => 'refreshEnvs', ]; public function mount() { $this->is_env_sorting_enabled = data_get($this->resource, 'settings.is_env_sorting_enabled', false); $this->use_build_secrets = data_get($this->resource, 'settings.use_build_secrets', false); $this->resourceClass = get_class($this->resource); $resourceWithPreviews = [\App\Models\Application::class]; $simpleDockerfile = filled(data_get($this->resource, 'dockerfile')); if (str($this->resourceClass)->contains($resourceWithPreviews) && ! $simpleDockerfile) { $this->showPreview = true; } $this->getDevView(); } public function instantSave() { try { $this->authorize('manageEnvironment', $this->resource); $this->resource->settings->is_env_sorting_enabled = $this->is_env_sorting_enabled; $this->resource->settings->use_build_secrets = $this->use_build_secrets; $this->resource->settings->save(); $this->getDevView(); $this->dispatch('success', 'Environment variable settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function getEnvironmentVariablesProperty() { $query = $this->resource->environment_variables() ->orderByRaw("CASE WHEN is_required = true AND (value IS NULL OR value = '') THEN 0 ELSE 1 END"); if ($this->is_env_sorting_enabled) { $query->orderBy('key'); } else { $query->orderBy('order'); } return $query->get(); } public function getEnvironmentVariablesPreviewProperty() { $query = $this->resource->environment_variables_preview() ->orderByRaw("CASE WHEN is_required = true AND (value IS NULL OR value = '') THEN 0 ELSE 1 END"); if ($this->is_env_sorting_enabled) { $query->orderBy('key'); } else { $query->orderBy('order'); } return $query->get(); } public function getHardcodedEnvironmentVariablesProperty() { return $this->getHardcodedVariables(false); } public function getHardcodedEnvironmentVariablesPreviewProperty() { return $this->getHardcodedVariables(true); } protected function getHardcodedVariables(bool $isPreview) { // Only for services and docker-compose applications if ($this->resource->type() !== 'service' && ($this->resourceClass !== 'App\Models\Application' || ($this->resourceClass === 'App\Models\Application' && $this->resource->build_pack !== 'dockercompose'))) { return collect([]); } $dockerComposeRaw = $this->resource->docker_compose_raw ?? $this->resource->docker_compose; if (blank($dockerComposeRaw)) { return collect([]); } // Extract all hard-coded variables $hardcodedVars = extractHardcodedEnvironmentVariables($dockerComposeRaw); // Filter out magic variables (SERVICE_FQDN_*, SERVICE_URL_*, SERVICE_NAME_*) $hardcodedVars = $hardcodedVars->filter(function ($var) { $key = $var['key']; return ! str($key)->startsWith(['SERVICE_FQDN_', 'SERVICE_URL_', 'SERVICE_NAME_']); }); // Filter out variables that exist in database (user has overridden/managed them) // For preview, check against preview variables; for production, check against production variables if ($isPreview) { $managedKeys = $this->resource->environment_variables_preview()->pluck('key')->toArray(); } else { $managedKeys = $this->resource->environment_variables()->where('is_preview', false)->pluck('key')->toArray(); } $hardcodedVars = $hardcodedVars->filter(function ($var) use ($managedKeys) { return ! in_array($var['key'], $managedKeys); }); // Apply sorting based on is_env_sorting_enabled if ($this->is_env_sorting_enabled) { $hardcodedVars = $hardcodedVars->sortBy('key')->values(); } // Otherwise keep order from docker-compose file return $hardcodedVars; } public function getDevView() { $this->variables = $this->formatEnvironmentVariables($this->environmentVariables); if ($this->showPreview) { $this->variablesPreview = $this->formatEnvironmentVariables($this->environmentVariablesPreview); } } private function formatEnvironmentVariables($variables) { return $variables->map(function ($item) { if ($item->is_shown_once) { return "$item->key=(Locked Secret, delete and add again to change)"; } if ($item->is_multiline) { return "$item->key=(Multiline environment variable, edit in normal view)"; } return "$item->key=$item->value"; })->join("\n"); } public function switch() { $this->view = $this->view === 'normal' ? 'dev' : 'normal'; $this->getDevView(); } public function submit($data = null) { try { $this->authorize('manageEnvironment', $this->resource); if ($data === null) { $this->handleBulkSubmit(); } else { $this->handleSingleSubmit($data); } $this->updateOrder(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->refreshEnvs(); } } private function updateOrder() { $variables = parseEnvFormatToArray($this->variables); $order = 1; foreach ($variables as $key => $value) { $env = $this->resource->environment_variables()->where('key', $key)->first(); if ($env) { $env->order = $order; $env->save(); } $order++; } if ($this->showPreview) { $previewVariables = parseEnvFormatToArray($this->variablesPreview); $order = 1; foreach ($previewVariables as $key => $value) { $env = $this->resource->environment_variables_preview()->where('key', $key)->first(); if ($env) { $env->order = $order; $env->save(); } $order++; } } } private function handleBulkSubmit() { $variables = parseEnvFormatToArray($this->variables); $changesMade = false; $errorOccurred = false; // Try to delete removed variables $deletedCount = $this->deleteRemovedVariables(false, $variables); if ($deletedCount > 0) { $changesMade = true; } elseif ($deletedCount === 0 && $this->resource->environment_variables()->whereNotIn('key', array_keys($variables))->exists()) { // If we tried to delete but couldn't (due to Docker Compose), mark as error $errorOccurred = true; } // Update or create variables $updatedCount = $this->updateOrCreateVariables(false, $variables); if ($updatedCount > 0) { $changesMade = true; } if ($this->showPreview) { $previewVariables = parseEnvFormatToArray($this->variablesPreview); // Try to delete removed preview variables $deletedPreviewCount = $this->deleteRemovedVariables(true, $previewVariables); if ($deletedPreviewCount > 0) { $changesMade = true; } elseif ($deletedPreviewCount === 0 && $this->resource->environment_variables_preview()->whereNotIn('key', array_keys($previewVariables))->exists()) { // If we tried to delete but couldn't (due to Docker Compose), mark as error $errorOccurred = true; } // Update or create preview variables $updatedPreviewCount = $this->updateOrCreateVariables(true, $previewVariables); if ($updatedPreviewCount > 0) { $changesMade = true; } } // Only show success message if changes were actually made and no errors occurred if ($changesMade && ! $errorOccurred) { $this->dispatch('success', 'Environment variables updated.'); } } private function handleSingleSubmit($data) { $found = $this->resource->environment_variables()->where('key', $data['key'])->first(); if ($found) { $this->dispatch('error', 'Environment variable already exists.'); return; } $maxOrder = $this->resource->environment_variables()->max('order') ?? 0; $environment = $this->createEnvironmentVariable($data); $environment->order = $maxOrder + 1; $environment->save(); // Clear computed property cache to force refresh unset($this->environmentVariables); unset($this->environmentVariablesPreview); $this->dispatch('success', 'Environment variable added.'); } private function createEnvironmentVariable($data) { $environment = new EnvironmentVariable; $environment->key = $data['key']; $environment->value = $data['value']; $environment->is_multiline = $data['is_multiline'] ?? false; $environment->is_literal = $data['is_literal'] ?? false; $environment->is_runtime = $data['is_runtime'] ?? true; $environment->is_buildtime = $data['is_buildtime'] ?? true; $environment->is_preview = $data['is_preview'] ?? false; $environment->comment = $data['comment'] ?? null; $environment->resourceable_id = $this->resource->id; $environment->resourceable_type = $this->resource->getMorphClass(); return $environment; } private function deleteRemovedVariables($isPreview, $variables) { $method = $isPreview ? 'environment_variables_preview' : 'environment_variables'; // Get all environment variables that will be deleted $variablesToDelete = $this->resource->$method()->whereNotIn('key', array_keys($variables))->get(); // If there are no variables to delete, return 0 if ($variablesToDelete->isEmpty()) { return 0; } // Check if any of these variables are used in Docker Compose if ($this->resource->type() === 'service' || $this->resource->build_pack === 'dockercompose') { foreach ($variablesToDelete as $envVar) { [$isUsed, $reason] = $this->isEnvironmentVariableUsedInDockerCompose($envVar->key, $this->resource->docker_compose); if ($isUsed) { $this->dispatch('error', "Cannot delete environment variable '{$envVar->key}'

Please remove it from the Docker Compose file first."); return 0; } } } // If we get here, no variables are used in Docker Compose, so we can delete them $this->resource->$method()->whereNotIn('key', array_keys($variables))->delete(); return $variablesToDelete->count(); } private function updateOrCreateVariables($isPreview, $variables) { $count = 0; foreach ($variables as $key => $data) { if (str($key)->startsWith('SERVICE_FQDN') || str($key)->startsWith('SERVICE_URL') || str($key)->startsWith('SERVICE_NAME')) { continue; } // Extract value and comment from parsed data // Handle both array format ['value' => ..., 'comment' => ...] and plain string values $value = is_array($data) ? ($data['value'] ?? '') : $data; $comment = is_array($data) ? ($data['comment'] ?? null) : null; $method = $isPreview ? 'environment_variables_preview' : 'environment_variables'; $found = $this->resource->$method()->where('key', $key)->first(); if ($found) { if (! $found->is_shown_once && ! $found->is_multiline) { $changed = false; // Update value if it changed if ($found->value !== $value) { $found->value = $value; $changed = true; } // Only update comment from inline comment if one is provided (overwrites existing) // If $comment is null, don't touch existing comment field to preserve it if ($comment !== null && $found->comment !== $comment) { $found->comment = $comment; $changed = true; } if ($changed) { $found->save(); $count++; } } } else { $environment = new EnvironmentVariable; $environment->key = $key; $environment->value = $value; $environment->comment = $comment; // Set comment from inline comment $environment->is_multiline = false; $environment->is_preview = $isPreview; $environment->resourceable_id = $this->resource->id; $environment->resourceable_type = $this->resource->getMorphClass(); $environment->save(); $count++; } } return $count; } public function refreshEnvs() { $this->resource->refresh(); // Clear computed property cache to force refresh unset($this->environmentVariables); unset($this->environmentVariablesPreview); $this->getDevView(); } } ================================================ FILE: app/Livewire/Project/Shared/EnvironmentVariable/Show.php ================================================ 'refresh', 'refresh', 'compose_loaded' => '$refresh', ]; protected $rules = [ 'key' => 'required|string', 'value' => 'nullable', 'comment' => 'nullable|string|max:256', 'is_multiline' => 'required|boolean', 'is_literal' => 'required|boolean', 'is_shown_once' => 'required|boolean', 'is_runtime' => 'required|boolean', 'is_buildtime' => 'required|boolean', 'real_value' => 'nullable', 'is_required' => 'required|boolean', ]; public function mount() { $this->syncData(); if ($this->env->getMorphClass() === \App\Models\SharedEnvironmentVariable::class) { $this->isSharedVariable = true; } $this->parameters = get_route_parameters(); $this->checkEnvs(); if ($this->type === 'standalone-redis' && ($this->env->key === 'REDIS_PASSWORD' || $this->env->key === 'REDIS_USERNAME')) { $this->is_redis_credential = true; } $this->problematicVariables = self::getProblematicVariablesForFrontend(); } public function getResourceProperty() { return $this->env->resourceable ?? $this->env; } public function refresh() { $this->syncData(); $this->checkEnvs(); } public function syncData(bool $toModel = false) { if ($toModel) { if ($this->isSharedVariable) { $this->validate([ 'key' => 'required|string', 'value' => 'nullable', 'comment' => 'nullable|string|max:256', 'is_multiline' => 'required|boolean', 'is_literal' => 'required|boolean', 'is_shown_once' => 'required|boolean', 'real_value' => 'nullable', ]); } else { $this->validate(); $this->env->is_required = $this->is_required; $this->env->is_runtime = $this->is_runtime; $this->env->is_buildtime = $this->is_buildtime; $this->env->is_shared = $this->is_shared; } $this->env->key = $this->key; $this->env->value = $this->value; $this->env->comment = $this->comment; $this->env->is_multiline = $this->is_multiline; $this->env->is_literal = $this->is_literal; $this->env->is_shown_once = $this->is_shown_once; $this->env->save(); } else { $this->key = $this->env->key; $this->value = $this->env->value; $this->comment = $this->env->comment; $this->is_multiline = $this->env->is_multiline; $this->is_literal = $this->env->is_literal; $this->is_shown_once = $this->env->is_shown_once; $this->is_runtime = $this->env->is_runtime ?? true; $this->is_buildtime = $this->env->is_buildtime ?? true; $this->is_required = $this->env->is_required ?? false; $this->is_really_required = $this->env->is_really_required ?? false; $this->is_shared = $this->env->is_shared ?? false; $this->real_value = $this->env->real_value; } } public function checkEnvs() { $this->isDisabled = false; $this->isMagicVariable = false; if (str($this->env->key)->startsWith('SERVICE_FQDN') || str($this->env->key)->startsWith('SERVICE_URL') || str($this->env->key)->startsWith('SERVICE_NAME')) { $this->isDisabled = true; $this->isMagicVariable = true; } if ($this->env->is_shown_once) { $this->isLocked = true; } } public function serialize() { data_forget($this->env, 'real_value'); } public function lock() { $this->authorize('update', $this->env); $this->env->is_shown_once = true; if ($this->isSharedVariable) { unset($this->env->is_required); } $this->serialize(); $this->env->save(); $this->checkEnvs(); $this->dispatch('refreshEnvs'); } public function instantSave() { $this->submit(); } public function submit() { try { $this->authorize('update', $this->env); if (! $this->isSharedVariable && $this->is_required && str($this->value)->isEmpty()) { $oldValue = $this->env->getOriginal('value'); $this->value = $oldValue; $this->dispatch('error', 'Required environment variables cannot be empty.'); return; } $this->serialize(); $this->syncData(true); $this->syncData(false); $this->dispatch('success', 'Environment variable updated.'); $this->dispatch('envsUpdated'); $this->dispatch('configurationChanged'); } catch (\Exception $e) { return handleError($e); } } #[Computed] public function availableSharedVariables(): array { $team = currentTeam(); $result = [ 'team' => [], 'project' => [], 'environment' => [], ]; // Early return if no team if (! $team) { return $result; } // Check if user can view team variables try { $this->authorize('view', $team); $result['team'] = $team->environment_variables() ->pluck('key') ->toArray(); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User not authorized to view team variables } // Get project variables if we have a project_uuid in route $projectUuid = data_get($this->parameters, 'project_uuid'); if ($projectUuid) { $project = Project::where('team_id', $team->id) ->where('uuid', $projectUuid) ->first(); if ($project) { try { $this->authorize('view', $project); $result['project'] = $project->environment_variables() ->pluck('key') ->toArray(); // Get environment variables if we have an environment_uuid in route $environmentUuid = data_get($this->parameters, 'environment_uuid'); if ($environmentUuid) { $environment = $project->environments() ->where('uuid', $environmentUuid) ->first(); if ($environment) { try { $this->authorize('view', $environment); $result['environment'] = $environment->environment_variables() ->pluck('key') ->toArray(); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User not authorized to view environment variables } } } } catch (\Illuminate\Auth\Access\AuthorizationException $e) { // User not authorized to view project variables } } } return $result; } public function delete() { try { $this->authorize('delete', $this->env); // Check if the variable is used in Docker Compose if ($this->type === 'service' || $this->type === 'application' && $this->env->resourceable?->docker_compose) { [$isUsed, $reason] = $this->isEnvironmentVariableUsedInDockerCompose($this->env->key, $this->env->resourceable?->docker_compose); if ($isUsed) { $this->dispatch('error', "Cannot delete environment variable '{$this->env->key}'

Please remove it from the Docker Compose file first."); return; } } $this->env->delete(); $this->dispatch('environmentVariableDeleted'); $this->dispatch('success', 'Environment variable deleted successfully.'); } catch (\Exception $e) { return handleError($e); } } } ================================================ FILE: app/Livewire/Project/Shared/EnvironmentVariable/ShowHardcoded.php ================================================ key = $this->env['key']; $this->value = $this->env['value'] ?? null; $this->comment = $this->env['comment'] ?? null; $this->serviceName = $this->env['service_name'] ?? null; } public function render() { return view('livewire.project.shared.environment-variable.show-hardcoded'); } } ================================================ FILE: app/Livewire/Project/Shared/ExecuteContainerCommand.php ================================================ 'required', 'container' => 'required', 'command' => 'required', ]; public function mount() { $this->parameters = get_route_parameters(); $this->containers = collect(); $this->servers = collect(); if (data_get($this->parameters, 'application_uuid')) { $this->type = 'application'; $this->resource = Application::ownedByCurrentTeam()->where('uuid', $this->parameters['application_uuid'])->firstOrFail(); if ($this->resource->destination->server->isFunctional()) { $this->servers = $this->servers->push($this->resource->destination->server); } foreach ($this->resource->additional_servers as $server) { if ($server->isFunctional()) { $this->servers = $this->servers->push($server); } } $this->loadContainers(); } elseif (data_get($this->parameters, 'database_uuid')) { $this->type = 'database'; $resource = getResourceByUuid($this->parameters['database_uuid'], data_get(auth()->user()->currentTeam(), 'id')); if (is_null($resource)) { abort(404); } $this->resource = $resource; if ($this->resource->destination->server->isFunctional()) { $this->servers = $this->servers->push($this->resource->destination->server); } $this->loadContainers(); } elseif (data_get($this->parameters, 'service_uuid')) { $this->type = 'service'; $this->resource = Service::ownedByCurrentTeam()->where('uuid', $this->parameters['service_uuid'])->firstOrFail(); if ($this->resource->server->isFunctional()) { $this->servers = $this->servers->push($this->resource->server); } $this->loadContainers(); } elseif (data_get($this->parameters, 'server_uuid')) { $this->type = 'server'; $this->resource = Server::ownedByCurrentTeam()->where('uuid', $this->parameters['server_uuid'])->firstOrFail(); $this->servers = $this->servers->push($this->resource); } $this->servers = $this->servers->sortByDesc(fn ($server) => $server->isTerminalEnabled()); } public function loadContainers() { foreach ($this->servers as $server) { if (data_get($this->parameters, 'application_uuid')) { if ($server->isSwarm()) { $containers = collect([ [ 'Names' => $this->resource->uuid.'_'.$this->resource->uuid, ], ]); } else { $containers = getCurrentApplicationContainerStatus($server, $this->resource->id, includePullrequests: true); } foreach ($containers as $container) { // if container state is running if (data_get($container, 'State') === 'running' && $server->isTerminalEnabled()) { $payload = [ 'server' => $server, 'container' => $container, ]; $this->containers = $this->containers->push($payload); } } } elseif (data_get($this->parameters, 'database_uuid')) { if ($this->resource->isRunning() && $server->isTerminalEnabled()) { $this->containers = $this->containers->push([ 'server' => $server, 'container' => [ 'Names' => $this->resource->uuid, ], ]); } } elseif (data_get($this->parameters, 'service_uuid')) { $this->resource->applications()->get()->each(function ($application) { if ($application->isRunning() && $this->resource->server->isTerminalEnabled()) { $this->containers->push([ 'server' => $this->resource->server, 'container' => [ 'Names' => data_get($application, 'name').'-'.data_get($this->resource, 'uuid'), ], ]); } }); $this->resource->databases()->get()->each(function ($database) { if ($database->isRunning()) { $this->containers->push([ 'server' => $this->resource->server, 'container' => [ 'Names' => data_get($database, 'name').'-'.data_get($this->resource, 'uuid'), ], ]); } }); } } // Sort containers alphabetically by name $this->containers = $this->containers->sortBy(function ($container) { return data_get($container, 'container.Names'); }); if ($this->containers->count() === 1) { $this->selected_container = data_get($this->containers->first(), 'container.Names'); } } public function updatedSelectedContainer() { if ($this->selected_container !== 'default') { $this->connectToContainer(); } } #[On('connectToServer')] public function connectToServer() { try { $server = $this->servers->first(); if ($server->isForceDisabled()) { throw new \RuntimeException('Server is disabled.'); } $this->dispatch( 'send-terminal-command', false, data_get($server, 'name'), data_get($server, 'uuid') ); // Dispatch a frontend event to ensure terminal gets focus after connection $this->dispatch('terminal-should-focus'); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->isConnecting = false; } } #[On('connectToContainer')] public function connectToContainer() { if ($this->selected_container === 'default') { $this->dispatch('error', 'Please select a container.'); return; } try { // Validate container name format if (! preg_match('/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/', $this->selected_container)) { throw new \InvalidArgumentException('Invalid container name format'); } // Verify container exists in our allowed list $container = collect($this->containers)->firstWhere('container.Names', $this->selected_container); if (is_null($container)) { throw new \RuntimeException('Container not found.'); } // Verify server ownership and status $server = data_get($container, 'server'); if (! $server || ! $server instanceof Server) { throw new \RuntimeException('Invalid server configuration.'); } if ($server->isForceDisabled()) { throw new \RuntimeException('Server is disabled.'); } // Additional ownership verification based on resource type $resourceServer = match ($this->type) { 'application' => $this->resource->destination->server, 'database' => $this->resource->destination->server, 'service' => $this->resource->server, default => throw new \RuntimeException('Invalid resource type.') }; if ($server->id !== $resourceServer->id && ! $this->resource->additional_servers->contains('id', $server->id)) { throw new \RuntimeException('Server ownership verification failed.'); } $this->dispatch( 'send-terminal-command', true, data_get($container, 'container.Names'), data_get($container, 'server.uuid') ); // Dispatch a frontend event to ensure terminal gets focus after connection $this->dispatch('terminal-should-focus'); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->isConnecting = false; } } public function render() { return view('livewire.project.shared.execute-container-command'); } } ================================================ FILE: app/Livewire/Project/Shared/GetLogs.php ================================================ resource)) { if ($this->resource->getMorphClass() === \App\Models\Application::class) { $this->showTimeStamps = $this->resource->settings->is_include_timestamps; } else { if ($this->servicesubtype) { $this->showTimeStamps = $this->servicesubtype->is_include_timestamps; } else { $this->showTimeStamps = $this->resource->is_include_timestamps; } } if ($this->resource?->getMorphClass() === \App\Models\Application::class) { if (str($this->container)->contains('-pr-')) { $this->pull_request = 'Pull Request: '.str($this->container)->afterLast('-pr-')->beforeLast('_')->value(); } } } } public function instantSave() { if (! is_null($this->resource)) { if ($this->resource->getMorphClass() === \App\Models\Application::class) { $this->resource->settings->is_include_timestamps = $this->showTimeStamps; $this->resource->settings->save(); } if ($this->resource->getMorphClass() === \App\Models\Service::class) { $serviceName = str($this->container)->beforeLast('-')->value(); $subType = $this->resource->applications()->where('name', $serviceName)->first(); if ($subType) { $subType->is_include_timestamps = $this->showTimeStamps; $subType->save(); } else { $subType = $this->resource->databases()->where('name', $serviceName)->first(); if ($subType) { $subType->is_include_timestamps = $this->showTimeStamps; $subType->save(); } } } } } public function toggleTimestamps() { $previousValue = $this->showTimeStamps; $this->showTimeStamps = ! $this->showTimeStamps; try { $this->instantSave(); $this->getLogs(true); } catch (\Throwable $e) { // Revert the flag to its previous value on failure $this->showTimeStamps = $previousValue; return handleError($e, $this); } } public function toggleStreamLogs() { $this->streamLogs = ! $this->streamLogs; } public function getLogs($refresh = false) { if (! $this->server->isFunctional()) { return; } if (! $refresh && ! $this->expandByDefault && ($this->resource?->getMorphClass() === \App\Models\Service::class || str($this->container)->contains('-pr-'))) { return; } if ($this->numberOfLines <= 0 || is_null($this->numberOfLines)) { $this->numberOfLines = 1000; } if ($this->numberOfLines > self::MAX_LOG_LINES) { $this->numberOfLines = self::MAX_LOG_LINES; } if ($this->container) { if ($this->showTimeStamps) { if ($this->server->isSwarm()) { $command = "docker service logs -n {$this->numberOfLines} -t {$this->container}"; if ($this->server->isNonRoot()) { $command = parseCommandsByLineForSudo(collect($command), $this->server); $command = $command[0]; } $sshCommand = SshMultiplexingHelper::generateSshCommand($this->server, $command); } else { $command = "docker logs -n {$this->numberOfLines} -t {$this->container}"; if ($this->server->isNonRoot()) { $command = parseCommandsByLineForSudo(collect($command), $this->server); $command = $command[0]; } $sshCommand = SshMultiplexingHelper::generateSshCommand($this->server, $command); } } else { if ($this->server->isSwarm()) { $command = "docker service logs -n {$this->numberOfLines} {$this->container}"; if ($this->server->isNonRoot()) { $command = parseCommandsByLineForSudo(collect($command), $this->server); $command = $command[0]; } $sshCommand = SshMultiplexingHelper::generateSshCommand($this->server, $command); } else { $command = "docker logs -n {$this->numberOfLines} {$this->container}"; if ($this->server->isNonRoot()) { $command = parseCommandsByLineForSudo(collect($command), $this->server); $command = $command[0]; } $sshCommand = SshMultiplexingHelper::generateSshCommand($this->server, $command); } } // Collect new logs into temporary variable first to prevent flickering // (avoids clearing output before new data is ready) // Use array accumulation + implode for O(n) instead of O(n²) string concatenation $logChunks = []; Process::timeout(config('constants.ssh.command_timeout'))->run($sshCommand, function (string $type, string $output) use (&$logChunks) { $logChunks[] = removeAnsiColors($output); }); $newOutputs = implode('', $logChunks); if ($this->showTimeStamps) { $newOutputs = str($newOutputs)->split('/\n/')->sort(function ($a, $b) { $a = explode(' ', $a); $b = explode(' ', $b); return $a[0] <=> $b[0]; })->join("\n"); } // Only update outputs after new data is ready (atomic update prevents flicker) $this->outputs = $newOutputs; } } public function copyLogs(): string { return sanitizeLogsForExport($this->outputs); } public function downloadAllLogs(): string { if (! $this->server->isFunctional() || ! $this->container) { return ''; } if ($this->showTimeStamps) { if ($this->server->isSwarm()) { $command = "docker service logs -t {$this->container}"; } else { $command = "docker logs -t {$this->container}"; } } else { if ($this->server->isSwarm()) { $command = "docker service logs {$this->container}"; } else { $command = "docker logs {$this->container}"; } } if ($this->server->isNonRoot()) { $command = parseCommandsByLineForSudo(collect($command), $this->server); $command = $command[0]; } $sshCommand = SshMultiplexingHelper::generateSshCommand($this->server, $command); // Use array accumulation + implode for O(n) instead of O(n²) string concatenation // Enforce 50MB size limit to prevent memory exhaustion from large logs $logChunks = []; $accumulatedBytes = 0; $truncated = false; Process::timeout(config('constants.ssh.command_timeout'))->run($sshCommand, function (string $type, string $output) use (&$logChunks, &$accumulatedBytes, &$truncated) { if ($truncated) { return; } $output = removeAnsiColors($output); $outputBytes = strlen($output); if ($accumulatedBytes + $outputBytes > self::MAX_DOWNLOAD_SIZE_BYTES) { $remaining = self::MAX_DOWNLOAD_SIZE_BYTES - $accumulatedBytes; if ($remaining > 0) { $logChunks[] = substr($output, 0, $remaining); } $truncated = true; return; } $logChunks[] = $output; $accumulatedBytes += $outputBytes; }); $allLogs = implode('', $logChunks); if ($truncated) { $allLogs .= "\n\n[... Output truncated at 50MB limit ...]"; } if ($this->showTimeStamps) { $allLogs = str($allLogs)->split('/\n/')->sort(function ($a, $b) { $a = explode(' ', $a); $b = explode(' ', $b); return $a[0] <=> $b[0]; })->join("\n"); } return sanitizeLogsForExport($allLogs); } public function render() { return view('livewire.project.shared.get-logs'); } } ================================================ FILE: app/Livewire/Project/Shared/HealthChecks.php ================================================ 'boolean', 'healthCheckType' => 'string|in:http,cmd', 'healthCheckCommand' => ['nullable', 'string', 'max:1000', 'regex:/^[a-zA-Z0-9 \-_.\/:=@,+]+$/'], 'healthCheckPath' => ['required', 'string', 'regex:#^[a-zA-Z0-9/\-_.~%]+$#'], 'healthCheckPort' => 'nullable|integer|min:1|max:65535', 'healthCheckHost' => ['required', 'string', 'regex:/^[a-zA-Z0-9.\-_]+$/'], 'healthCheckMethod' => 'required|string|in:GET,HEAD,POST,OPTIONS', 'healthCheckReturnCode' => 'integer', 'healthCheckScheme' => 'required|string|in:http,https', 'healthCheckResponseText' => 'nullable|string', 'healthCheckInterval' => 'integer|min:1', 'healthCheckTimeout' => 'integer|min:1', 'healthCheckRetries' => 'integer|min:1', 'healthCheckStartPeriod' => 'integer', 'customHealthcheckFound' => 'boolean', ]; public function mount() { $this->authorize('view', $this->resource); $this->syncData(); } public function syncData(bool $toModel = false): void { if ($toModel) { $this->validate(); // Sync to model $this->resource->health_check_enabled = $this->healthCheckEnabled; $this->resource->health_check_type = $this->healthCheckType; $this->resource->health_check_command = $this->healthCheckCommand; $this->resource->health_check_method = $this->healthCheckMethod; $this->resource->health_check_scheme = $this->healthCheckScheme; $this->resource->health_check_host = $this->healthCheckHost; $this->resource->health_check_port = $this->healthCheckPort; $this->resource->health_check_path = $this->healthCheckPath; $this->resource->health_check_return_code = $this->healthCheckReturnCode; $this->resource->health_check_response_text = $this->healthCheckResponseText; $this->resource->health_check_interval = $this->healthCheckInterval; $this->resource->health_check_timeout = $this->healthCheckTimeout; $this->resource->health_check_retries = $this->healthCheckRetries; $this->resource->health_check_start_period = $this->healthCheckStartPeriod; $this->resource->custom_healthcheck_found = $this->customHealthcheckFound; $this->resource->save(); } else { // Sync from model $this->healthCheckEnabled = $this->resource->health_check_enabled; $this->healthCheckType = $this->resource->health_check_type ?? 'http'; $this->healthCheckCommand = $this->resource->health_check_command; $this->healthCheckMethod = $this->resource->health_check_method; $this->healthCheckScheme = $this->resource->health_check_scheme; $this->healthCheckHost = $this->resource->health_check_host; $this->healthCheckPort = $this->resource->health_check_port; $this->healthCheckPath = $this->resource->health_check_path; $this->healthCheckReturnCode = $this->resource->health_check_return_code; $this->healthCheckResponseText = $this->resource->health_check_response_text; $this->healthCheckInterval = $this->resource->health_check_interval; $this->healthCheckTimeout = $this->resource->health_check_timeout; $this->healthCheckRetries = $this->resource->health_check_retries; $this->healthCheckStartPeriod = $this->resource->health_check_start_period; $this->customHealthcheckFound = $this->resource->custom_healthcheck_found; } } public function instantSave() { $this->authorize('update', $this->resource); $this->validate(); // Sync component properties to model $this->resource->health_check_enabled = $this->healthCheckEnabled; $this->resource->health_check_type = $this->healthCheckType; $this->resource->health_check_command = $this->healthCheckCommand; $this->resource->health_check_method = $this->healthCheckMethod; $this->resource->health_check_scheme = $this->healthCheckScheme; $this->resource->health_check_host = $this->healthCheckHost; $this->resource->health_check_port = $this->healthCheckPort; $this->resource->health_check_path = $this->healthCheckPath; $this->resource->health_check_return_code = $this->healthCheckReturnCode; $this->resource->health_check_response_text = $this->healthCheckResponseText; $this->resource->health_check_interval = $this->healthCheckInterval; $this->resource->health_check_timeout = $this->healthCheckTimeout; $this->resource->health_check_retries = $this->healthCheckRetries; $this->resource->health_check_start_period = $this->healthCheckStartPeriod; $this->resource->custom_healthcheck_found = $this->customHealthcheckFound; $this->resource->save(); $this->dispatch('success', 'Health check updated.'); } public function submit() { try { $this->authorize('update', $this->resource); $this->validate(); // Sync component properties to model $this->resource->health_check_enabled = $this->healthCheckEnabled; $this->resource->health_check_type = $this->healthCheckType; $this->resource->health_check_command = $this->healthCheckCommand; $this->resource->health_check_method = $this->healthCheckMethod; $this->resource->health_check_scheme = $this->healthCheckScheme; $this->resource->health_check_host = $this->healthCheckHost; $this->resource->health_check_port = $this->healthCheckPort; $this->resource->health_check_path = $this->healthCheckPath; $this->resource->health_check_return_code = $this->healthCheckReturnCode; $this->resource->health_check_response_text = $this->healthCheckResponseText; $this->resource->health_check_interval = $this->healthCheckInterval; $this->resource->health_check_timeout = $this->healthCheckTimeout; $this->resource->health_check_retries = $this->healthCheckRetries; $this->resource->health_check_start_period = $this->healthCheckStartPeriod; $this->resource->custom_healthcheck_found = $this->customHealthcheckFound; $this->resource->save(); $this->dispatch('success', 'Health check updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function toggleHealthcheck() { try { $this->authorize('update', $this->resource); $wasEnabled = $this->healthCheckEnabled; $this->healthCheckEnabled = ! $this->healthCheckEnabled; // Sync component properties to model $this->resource->health_check_enabled = $this->healthCheckEnabled; $this->resource->health_check_type = $this->healthCheckType; $this->resource->health_check_command = $this->healthCheckCommand; $this->resource->health_check_method = $this->healthCheckMethod; $this->resource->health_check_scheme = $this->healthCheckScheme; $this->resource->health_check_host = $this->healthCheckHost; $this->resource->health_check_port = $this->healthCheckPort; $this->resource->health_check_path = $this->healthCheckPath; $this->resource->health_check_return_code = $this->healthCheckReturnCode; $this->resource->health_check_response_text = $this->healthCheckResponseText; $this->resource->health_check_interval = $this->healthCheckInterval; $this->resource->health_check_timeout = $this->healthCheckTimeout; $this->resource->health_check_retries = $this->healthCheckRetries; $this->resource->health_check_start_period = $this->healthCheckStartPeriod; $this->resource->custom_healthcheck_found = $this->customHealthcheckFound; $this->resource->save(); if ($this->healthCheckEnabled && ! $wasEnabled && $this->resource->isRunning()) { $this->dispatch('info', 'Health check has been enabled. A restart is required to apply the new settings.'); } else { $this->dispatch('success', 'Health check '.($this->healthCheckEnabled ? 'enabled' : 'disabled').'.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.shared.health-checks'); } } ================================================ FILE: app/Livewire/Project/Shared/Logs.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ServiceChecked" => '$refresh', ]; } public function loadAllContainers() { try { foreach ($this->servers as $server) { $this->serverContainers[$server->id] = $this->getContainersForServer($server); } $this->containersLoaded = true; } catch (\Exception $e) { $this->containersLoaded = true; // Set to true to stop loading spinner return handleError($e, $this); } } private function getContainersForServer($server) { if (! $server->isFunctional()) { return []; } try { if ($server->isSwarm()) { $containers = collect([ [ 'ID' => $this->resource->uuid, 'Names' => $this->resource->uuid.'_'.$this->resource->uuid, ], ]); return $containers->toArray(); } else { $containers = getCurrentApplicationContainerStatus($server, $this->resource->id, includePullrequests: true); if ($containers && $containers->count() > 0) { return $containers->sort()->toArray(); } return []; } } catch (\Exception $e) { // Log error but don't fail the entire operation ray("Error loading containers for server {$server->name}: ".$e->getMessage()); return []; } } public function mount() { try { $this->containers = collect(); $this->servers = collect(); $this->serverContainers = []; $this->parameters = get_route_parameters(); $this->query = request()->query(); if (data_get($this->parameters, 'application_uuid')) { $this->type = 'application'; $this->resource = Application::ownedByCurrentTeam()->where('uuid', $this->parameters['application_uuid'])->firstOrFail(); $this->status = $this->resource->status; if ($this->resource->destination->server->isFunctional()) { $server = $this->resource->destination->server; $this->servers = $this->servers->push($server); } foreach ($this->resource->additional_servers as $server) { if ($server->isFunctional()) { $this->servers = $this->servers->push($server); } } } elseif (data_get($this->parameters, 'database_uuid')) { $this->type = 'database'; $resource = getResourceByUuid($this->parameters['database_uuid'], data_get(auth()->user()->currentTeam(), 'id')); if (is_null($resource)) { abort(404); } $this->resource = $resource; $this->status = $this->resource->status; if ($this->resource->destination->server->isFunctional()) { $server = $this->resource->destination->server; $this->servers = $this->servers->push($server); } $this->container = $this->resource->uuid; $this->containers->push($this->container); } elseif (data_get($this->parameters, 'service_uuid')) { $this->type = 'service'; $this->resource = Service::ownedByCurrentTeam()->where('uuid', $this->parameters['service_uuid'])->firstOrFail(); $this->resource->applications()->get()->each(function ($application) { $this->containers->push(data_get($application, 'name').'-'.data_get($this->resource, 'uuid')); }); $this->resource->databases()->get()->each(function ($database) { $this->containers->push(data_get($database, 'name').'-'.data_get($this->resource, 'uuid')); }); if ($this->resource->server->isFunctional()) { $server = $this->resource->server; $this->servers = $this->servers->push($server); } } $this->containers = $this->containers->sort(); if (data_get($this->query, 'pull_request_id')) { $this->containers = $this->containers->filter(function ($container) { return str_contains($container, $this->query['pull_request_id']); }); } } catch (\Exception $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.shared.logs'); } } ================================================ FILE: app/Livewire/Project/Shared/Metrics.php ================================================ poll || $this->interval <= 10) { $this->loadData(); if ($this->interval > 10) { $this->poll = false; } } } public function loadData() { try { $cpuMetrics = $this->resource->getCpuMetrics($this->interval); $memoryMetrics = $this->resource->getMemoryMetrics($this->interval); $this->dispatch("refreshChartData-{$this->chartId}-cpu", [ 'seriesData' => $cpuMetrics, ]); $this->dispatch("refreshChartData-{$this->chartId}-memory", [ 'seriesData' => $memoryMetrics, ]); } catch (\Throwable $e) { return handleError($e, $this); } } public function setInterval() { if ($this->interval <= 10) { $this->poll = true; } $this->loadData(); } public function render() { return view('livewire.project.shared.metrics'); } } ================================================ FILE: app/Livewire/Project/Shared/ResourceLimits.php ================================================ 'required|string', 'limitsMemorySwap' => 'required|string', 'limitsMemorySwappiness' => 'required|integer|min:0|max:100', 'limitsMemoryReservation' => 'required|string', 'limitsCpus' => 'nullable', 'limitsCpuset' => 'nullable', 'limitsCpuShares' => 'nullable', ]; protected $validationAttributes = [ 'limitsMemory' => 'memory', 'limitsMemorySwap' => 'swap', 'limitsMemorySwappiness' => 'swappiness', 'limitsMemoryReservation' => 'reservation', 'limitsCpus' => 'cpus', 'limitsCpuset' => 'cpuset', 'limitsCpuShares' => 'cpu shares', ]; /** * Sync data between component properties and model * * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties. */ private function syncData(bool $toModel = false): void { if ($toModel) { // Sync TO model (before save) $this->resource->limits_cpus = $this->limitsCpus; $this->resource->limits_cpuset = $this->limitsCpuset; $this->resource->limits_cpu_shares = $this->limitsCpuShares; $this->resource->limits_memory = $this->limitsMemory; $this->resource->limits_memory_swap = $this->limitsMemorySwap; $this->resource->limits_memory_swappiness = $this->limitsMemorySwappiness; $this->resource->limits_memory_reservation = $this->limitsMemoryReservation; } else { // Sync FROM model (on load/refresh) $this->limitsCpus = $this->resource->limits_cpus; $this->limitsCpuset = $this->resource->limits_cpuset; $this->limitsCpuShares = $this->resource->limits_cpu_shares; $this->limitsMemory = $this->resource->limits_memory; $this->limitsMemorySwap = $this->resource->limits_memory_swap; $this->limitsMemorySwappiness = $this->resource->limits_memory_swappiness; $this->limitsMemoryReservation = $this->resource->limits_memory_reservation; } } public function mount() { $this->syncData(false); } public function submit() { try { $this->authorize('update', $this->resource); // Apply default values to properties if (! $this->limitsMemory) { $this->limitsMemory = '0'; } if (! $this->limitsMemorySwap) { $this->limitsMemorySwap = '0'; } if (is_null($this->limitsMemorySwappiness)) { $this->limitsMemorySwappiness = 60; } if (! $this->limitsMemoryReservation) { $this->limitsMemoryReservation = '0'; } if (! $this->limitsCpus) { $this->limitsCpus = '0'; } if ($this->limitsCpuset === '') { $this->limitsCpuset = null; } if (is_null($this->limitsCpuShares)) { $this->limitsCpuShares = 1024; } $this->validate(); $this->syncData(true); $this->resource->save(); $this->dispatch('success', 'Resource limits updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Shared/ResourceOperations.php ================================================ projectUuid = data_get($parameters, 'project_uuid'); $this->environmentUuid = data_get($parameters, 'environment_uuid'); $this->projects = Project::ownedByCurrentTeamCached(); $this->servers = currentTeam()->servers->filter(fn ($server) => ! $server->isBuildServer()); } public function toggleVolumeCloning(bool $value) { $this->cloneVolumeData = $value; } public function cloneTo($destination_id) { $this->authorize('update', $this->resource); $teamScope = fn ($q) => $q->where('team_id', currentTeam()->id); $new_destination = StandaloneDocker::whereHas('server', $teamScope)->find($destination_id); if (! $new_destination) { $new_destination = SwarmDocker::whereHas('server', $teamScope)->find($destination_id); } if (! $new_destination) { return $this->addError('destination_id', 'Destination not found.'); } $uuid = (string) new Cuid2; $server = $new_destination->server; if ($this->resource->getMorphClass() === \App\Models\Application::class) { $new_resource = clone_application($this->resource, $new_destination, ['uuid' => $uuid], $this->cloneVolumeData); $route = route('project.application.configuration', [ 'project_uuid' => $this->projectUuid, 'environment_uuid' => $this->environmentUuid, 'application_uuid' => $new_resource->uuid, ]).'#resource-operations'; return redirect()->to($route); } elseif ( $this->resource->getMorphClass() === \App\Models\StandalonePostgresql::class || $this->resource->getMorphClass() === \App\Models\StandaloneMongodb::class || $this->resource->getMorphClass() === \App\Models\StandaloneMysql::class || $this->resource->getMorphClass() === \App\Models\StandaloneMariadb::class || $this->resource->getMorphClass() === \App\Models\StandaloneRedis::class || $this->resource->getMorphClass() === \App\Models\StandaloneKeydb::class || $this->resource->getMorphClass() === \App\Models\StandaloneDragonfly::class || $this->resource->getMorphClass() === \App\Models\StandaloneClickhouse::class ) { $uuid = (string) new Cuid2; $new_resource = $this->resource->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => $uuid, 'name' => $this->resource->name.'-clone-'.$uuid, 'status' => 'exited', 'started_at' => null, 'destination_id' => $new_destination->id, ]); $new_resource->save(); $tags = $this->resource->tags; foreach ($tags as $tag) { $new_resource->tags()->attach($tag->id); } $new_resource->persistentStorages()->delete(); $persistentVolumes = $this->resource->persistentStorages()->get(); foreach ($persistentVolumes as $volume) { $originalName = $volume->name; $newName = ''; if (str_starts_with($originalName, 'postgres-data-')) { $newName = 'postgres-data-'.$new_resource->uuid; } elseif (str_starts_with($originalName, 'mysql-data-')) { $newName = 'mysql-data-'.$new_resource->uuid; } elseif (str_starts_with($originalName, 'redis-data-')) { $newName = 'redis-data-'.$new_resource->uuid; } elseif (str_starts_with($originalName, 'clickhouse-data-')) { $newName = 'clickhouse-data-'.$new_resource->uuid; } elseif (str_starts_with($originalName, 'mariadb-data-')) { $newName = 'mariadb-data-'.$new_resource->uuid; } elseif (str_starts_with($originalName, 'mongodb-data-')) { $newName = 'mongodb-data-'.$new_resource->uuid; } elseif (str_starts_with($originalName, 'keydb-data-')) { $newName = 'keydb-data-'.$new_resource->uuid; } elseif (str_starts_with($originalName, 'dragonfly-data-')) { $newName = 'dragonfly-data-'.$new_resource->uuid; } else { if (str_starts_with($volume->name, $this->resource->uuid)) { $newName = str($volume->name)->replace($this->resource->uuid, $new_resource->uuid); } else { $newName = $new_resource->uuid.'-'.$volume->name; } } $newPersistentVolume = $volume->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'name' => $newName, 'resource_id' => $new_resource->id, ]); $newPersistentVolume->save(); if ($this->cloneVolumeData) { try { StopDatabase::dispatch($this->resource); $sourceVolume = $volume->name; $targetVolume = $newPersistentVolume->name; $sourceServer = $this->resource->destination->server; $targetServer = $new_resource->destination->server; VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume); StartDatabase::dispatch($this->resource); } catch (\Exception $e) { \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage()); } } } $fileStorages = $this->resource->fileStorages()->get(); foreach ($fileStorages as $storage) { $newStorage = $storage->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'resource_id' => $new_resource->id, ]); $newStorage->save(); } $scheduledBackups = $this->resource->scheduledBackups()->get(); foreach ($scheduledBackups as $backup) { $uuid = (string) new Cuid2; $newBackup = $backup->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => $uuid, 'database_id' => $new_resource->id, 'database_type' => $new_resource->getMorphClass(), 'team_id' => currentTeam()->id, ]); $newBackup->save(); } $environmentVaribles = $this->resource->environment_variables()->get(); foreach ($environmentVaribles as $environmentVarible) { $payload = [ 'resourceable_id' => $new_resource->id, 'resourceable_type' => $new_resource->getMorphClass(), ]; $newEnvironmentVariable = $environmentVarible->replicate([ 'id', 'created_at', 'updated_at', ])->fill($payload); $newEnvironmentVariable->save(); } $route = route('project.database.configuration', [ 'project_uuid' => $this->projectUuid, 'environment_uuid' => $this->environmentUuid, 'database_uuid' => $new_resource->uuid, ]).'#resource-operations'; return redirect()->to($route); } elseif ($this->resource->type() === 'service') { $uuid = (string) new Cuid2; $new_resource = $this->resource->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => $uuid, 'name' => $this->resource->name.'-clone-'.$uuid, 'destination_id' => $new_destination->id, 'destination_type' => $new_destination->getMorphClass(), 'server_id' => $new_destination->server_id, // server_id is probably not needed anymore because of the new polymorphic relationships (here it is needed for clone to a different server to work - but maybe we can drop the column) ]); $new_resource->save(); $tags = $this->resource->tags; foreach ($tags as $tag) { $new_resource->tags()->attach($tag->id); } $scheduledTasks = $this->resource->scheduled_tasks()->get(); foreach ($scheduledTasks as $task) { $newTask = $task->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'uuid' => (string) new Cuid2, 'service_id' => $new_resource->id, 'team_id' => currentTeam()->id, ]); $newTask->save(); } $environmentVariables = $this->resource->environment_variables()->get(); foreach ($environmentVariables as $environmentVariable) { $newEnvironmentVariable = $environmentVariable->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'resourceable_id' => $new_resource->id, 'resourceable_type' => $new_resource->getMorphClass(), ]); $newEnvironmentVariable->save(); } foreach ($new_resource->applications() as $application) { $application->update([ 'status' => 'exited', ]); $persistentVolumes = $application->persistentStorages()->get(); foreach ($persistentVolumes as $volume) { $newName = ''; if (str_starts_with($volume->name, $volume->resource->uuid)) { $newName = str($volume->name)->replace($volume->resource->uuid, $application->uuid); } else { $newName = $application->uuid.'-'.str($volume->name)->afterLast('-'); } $newPersistentVolume = $volume->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'name' => $newName, 'resource_id' => $application->id, ]); $newPersistentVolume->save(); if ($this->cloneVolumeData) { try { StopService::dispatch($application); $sourceVolume = $volume->name; $targetVolume = $newPersistentVolume->name; $sourceServer = $application->service->destination->server; $targetServer = $new_resource->destination->server; VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume); StartService::dispatch($application); } catch (\Exception $e) { \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage()); } } } } foreach ($new_resource->databases() as $database) { $database->update([ 'status' => 'exited', ]); $persistentVolumes = $database->persistentStorages()->get(); foreach ($persistentVolumes as $volume) { $newName = ''; if (str_starts_with($volume->name, $volume->resource->uuid)) { $newName = str($volume->name)->replace($volume->resource->uuid, $database->uuid); } else { $newName = $database->uuid.'-'.str($volume->name)->afterLast('-'); } $newPersistentVolume = $volume->replicate([ 'id', 'created_at', 'updated_at', ])->fill([ 'name' => $newName, 'resource_id' => $database->id, ]); $newPersistentVolume->save(); if ($this->cloneVolumeData) { try { StopService::dispatch($database->service); $sourceVolume = $volume->name; $targetVolume = $newPersistentVolume->name; $sourceServer = $database->service->destination->server; $targetServer = $new_resource->destination->server; VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume); StartService::dispatch($database->service); } catch (\Exception $e) { \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage()); } } } } $new_resource->parse(); $route = route('project.service.configuration', [ 'project_uuid' => $this->projectUuid, 'environment_uuid' => $this->environmentUuid, 'service_uuid' => $new_resource->uuid, ]).'#resource-operations'; return redirect()->to($route); } } public function moveTo($environment_id) { try { $this->authorize('update', $this->resource); $new_environment = Environment::ownedByCurrentTeam()->findOrFail($environment_id); $this->resource->update([ 'environment_id' => $environment_id, ]); if ($this->resource->type() === 'application') { $route = route('project.application.configuration', [ 'project_uuid' => $new_environment->project->uuid, 'environment_uuid' => $new_environment->uuid, 'application_uuid' => $this->resource->uuid, ]).'#resource-operations'; return redirect()->to($route); } elseif (str($this->resource->type())->startsWith('standalone-')) { $route = route('project.database.configuration', [ 'project_uuid' => $new_environment->project->uuid, 'environment_uuid' => $new_environment->uuid, 'database_uuid' => $this->resource->uuid, ]).'#resource-operations'; return redirect()->to($route); } elseif ($this->resource->type() === 'service') { $route = route('project.service.configuration', [ 'project_uuid' => $new_environment->project->uuid, 'environment_uuid' => $new_environment->uuid, 'service_uuid' => $this->resource->uuid, ]).'#resource-operations'; return redirect()->to($route); } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.project.shared.resource-operations'); } } ================================================ FILE: app/Livewire/Project/Shared/ScheduledTask/Add.php ================================================ 'required|string', 'command' => 'required|string', 'frequency' => 'required|string', 'container' => 'nullable|string', 'timeout' => 'required|integer|min:60|max:36000', ]; protected $validationAttributes = [ 'name' => 'name', 'command' => 'command', 'frequency' => 'frequency', 'container' => 'container', 'timeout' => 'timeout', ]; public function mount() { $this->parameters = get_route_parameters(); // Get the resource based on type and id switch ($this->type) { case 'application': $this->resource = \App\Models\Application::findOrFail($this->id); break; case 'service': $this->resource = \App\Models\Service::findOrFail($this->id); break; case 'standalone-postgresql': $this->resource = \App\Models\StandalonePostgresql::findOrFail($this->id); break; default: throw new \Exception('Invalid resource type'); } if ($this->containerNames->count() > 0) { $this->container = $this->containerNames->first(); } } public function submit() { try { $this->authorize('update', $this->resource); $this->validate(); $isValid = validate_cron_expression($this->frequency); if (! $isValid) { $this->dispatch('error', 'Invalid Cron / Human expression.'); return; } if (empty($this->container) || $this->container === 'null') { if ($this->type === 'service') { $this->container = $this->subServiceName; } } $this->saveScheduledTask(); $this->clear(); } catch (\Exception $e) { return handleError($e, $this); } } public function saveScheduledTask() { try { $task = new ScheduledTask; $task->name = $this->name; $task->command = $this->command; $task->frequency = $this->frequency; $task->container = $this->container; $task->timeout = $this->timeout; $task->team_id = currentTeam()->id; switch ($this->type) { case 'application': $task->application_id = $this->id; break; case 'standalone-postgresql': $task->standalone_postgresql_id = $this->id; break; case 'service': $task->service_id = $this->id; break; } $task->save(); $this->dispatch('refreshTasks'); $this->dispatch('success', 'Scheduled task added.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function clear() { $this->name = ''; $this->command = ''; $this->frequency = ''; $this->container = ''; $this->timeout = 300; } } ================================================ FILE: app/Livewire/Project/Shared/ScheduledTask/All.php ================================================ parameters = get_route_parameters(); if ($this->resource->type() === 'service') { $this->containerNames = $this->resource->applications()->pluck('name'); $this->containerNames = $this->containerNames->merge($this->resource->databases()->pluck('name')); } elseif ($this->resource->type() === 'application') { if ($this->resource->build_pack === 'dockercompose') { $parsed = $this->resource->parse(); $containers = collect(data_get($parsed, 'services'))->keys(); $this->containerNames = $containers; } else { $this->containerNames = collect([]); } } } #[On('refreshTasks')] public function refreshTasks() { $this->resource->refresh(); } } ================================================ FILE: app/Livewire/Project/Shared/ScheduledTask/Executions.php ================================================ currentTeam()->id; return [ "echo-private:team.{$teamId},ScheduledTaskDone" => 'refreshExecutions', ]; } public function mount($taskId) { try { $this->taskId = $taskId; $this->task = ScheduledTask::findOrFail($taskId); $this->executions = $this->task->executions()->take(20)->get(); $this->serverTimezone = data_get($this->task, 'application.destination.server.settings.server_timezone'); if (! $this->serverTimezone) { $this->serverTimezone = data_get($this->task, 'service.destination.server.settings.server_timezone'); } if (! $this->serverTimezone) { $this->serverTimezone = 'UTC'; } } catch (\Exception $e) { return handleError($e); } } public function refreshExecutions(): void { $this->executions = $this->task->executions()->take(20)->get(); if ($this->selectedKey) { $this->selectedExecution = $this->task->executions()->find($this->selectedKey); if ($this->selectedExecution && $this->selectedExecution->status !== 'running') { $this->isPollingActive = false; } } } public function selectTask($key): void { if ($key == $this->selectedKey) { $this->selectedKey = null; $this->selectedExecution = null; $this->currentPage = 1; $this->isPollingActive = false; return; } $this->selectedKey = $key; $this->selectedExecution = $this->task->executions()->find($key); $this->currentPage = 1; // Start polling if task is running if ($this->selectedExecution && $this->selectedExecution->status === 'running') { $this->isPollingActive = true; } } public function polling() { if ($this->selectedExecution && $this->isPollingActive) { $this->selectedExecution->refresh(); if ($this->selectedExecution->status !== 'running') { $this->isPollingActive = false; } } } public function loadMoreLogs() { $this->currentPage++; } public function loadAllLogs() { if (! $this->selectedExecution || ! $this->selectedExecution->message) { return; } $lines = collect(explode("\n", $this->selectedExecution->message)); $totalLines = $lines->count(); $totalPages = ceil($totalLines / $this->logsPerPage); $this->currentPage = $totalPages; } public function getLogLinesProperty() { if (! $this->selectedExecution) { return collect(); } if (! $this->selectedExecution->message) { return collect(['Waiting for task output...']); } $lines = collect(explode("\n", $this->selectedExecution->message)); return $lines->take($this->currentPage * $this->logsPerPage); } public function downloadLogs(int $executionId) { $execution = $this->executions->firstWhere('id', $executionId); if (! $execution) { return; } return response()->streamDownload(function () use ($execution) { echo $execution->message; }, 'task-execution-'.$execution->id.'.log'); } public function hasMoreLogs() { if (! $this->selectedExecution || ! $this->selectedExecution->message) { return false; } $lines = collect(explode("\n", $this->selectedExecution->message)); return $lines->count() > ($this->currentPage * $this->logsPerPage); } } ================================================ FILE: app/Livewire/Project/Shared/ScheduledTask/Show.php ================================================ task_uuid = $task_uuid; if ($application_uuid) { $this->type = 'application'; $this->application_uuid = $application_uuid; $this->resource = Application::ownedByCurrentTeam()->where('uuid', $application_uuid)->firstOrFail(); } elseif ($service_uuid) { $this->type = 'service'; $this->service_uuid = $service_uuid; $this->resource = Service::ownedByCurrentTeamCached()->where('uuid', $service_uuid)->firstOrFail(); } $this->parameters = [ 'environment_uuid' => $environment_uuid, 'project_uuid' => $project_uuid, 'application_uuid' => $application_uuid, 'service_uuid' => $service_uuid, ]; $this->task = $this->resource->scheduled_tasks()->where('uuid', $task_uuid)->firstOrFail(); $this->syncData(); } catch (\Exception $e) { return handleError($e); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $isValid = validate_cron_expression($this->frequency); if (! $isValid) { $this->frequency = $this->task->frequency; throw new \Exception('Invalid Cron / Human expression.'); } $this->task->enabled = $this->isEnabled; $this->task->name = str($this->name)->trim()->value(); $this->task->command = str($this->command)->trim()->value(); $this->task->frequency = str($this->frequency)->trim()->value(); $this->task->container = str($this->container)->trim()->value(); $this->task->timeout = (int) $this->timeout; $this->task->save(); } else { $this->isEnabled = $this->task->enabled; $this->name = $this->task->name; $this->command = $this->task->command; $this->frequency = $this->task->frequency; $this->container = $this->task->container; $this->timeout = $this->task->timeout ?? 300; } } public function instantSave() { try { $this->authorize('update', $this->resource); $this->syncData(true); $this->dispatch('success', 'Scheduled task updated.'); $this->refreshTasks(); } catch (\Exception $e) { return handleError($e); } } public function submit() { try { $this->authorize('update', $this->resource); $this->syncData(true); $this->dispatch('success', 'Scheduled task updated.'); } catch (\Exception $e) { return handleError($e, $this); } } public function refreshTasks() { try { $this->task->refresh(); } catch (\Exception $e) { return handleError($e); } } public function delete() { try { $this->authorize('update', $this->resource); $this->task->delete(); if ($this->type === 'application') { return redirect()->route('project.application.scheduled-tasks.show', $this->parameters); } else { return redirect()->route('project.service.scheduled-tasks.show', $this->parameters); } } catch (\Exception $e) { return handleError($e); } } public function executeNow() { try { $this->authorize('update', $this->resource); ScheduledTaskJob::dispatch($this->task); $this->dispatch('success', 'Scheduled task executed.'); } catch (\Exception $e) { return handleError($e); } } } ================================================ FILE: app/Livewire/Project/Shared/Storages/All.php ================================================ '$refresh']; public function getFirstStorageIdProperty() { if ($this->resource->persistentStorages->isEmpty()) { return null; } // Use the storage with the smallest ID as the "first" one // This ensures stability even when storages are deleted return $this->resource->persistentStorages->sortBy('id')->first()->id; } } ================================================ FILE: app/Livewire/Project/Shared/Storages/Show.php ================================================ 'required|string', 'mountPath' => 'required|string', 'hostPath' => 'string|nullable', ]; protected $validationAttributes = [ 'name' => 'name', 'mountPath' => 'mount', 'hostPath' => 'host', ]; /** * Sync data between component properties and model * * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties. */ private function syncData(bool $toModel = false): void { if ($toModel) { // Sync TO model (before save) $this->storage->name = $this->name; $this->storage->mount_path = $this->mountPath; $this->storage->host_path = $this->hostPath; } else { // Sync FROM model (on load/refresh) $this->name = $this->storage->name; $this->mountPath = $this->storage->mount_path; $this->hostPath = $this->storage->host_path; } } public function mount() { $this->syncData(false); $this->isReadOnly = $this->storage->shouldBeReadOnlyInUI(); } public function submit() { $this->authorize('update', $this->resource); $this->validate(); $this->syncData(true); $this->storage->save(); $this->dispatch('success', 'Storage updated successfully'); } public function delete($password, $selectedActions = []) { $this->authorize('update', $this->resource); if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } $this->storage->delete(); $this->dispatch('refreshStorages'); return true; } } ================================================ FILE: app/Livewire/Project/Shared/Tags.php ================================================ loadTags(); } public function loadTags() { $this->tags = Tag::ownedByCurrentTeam()->get(); $this->filteredTags = $this->tags->filter(function ($tag) { return ! $this->resource->tags->contains($tag); }); } public function submit() { try { $this->authorize('update', $this->resource); $this->validate(); $tags = str($this->newTags)->trim()->explode(' '); foreach ($tags as $tag) { $tag = strip_tags($tag); if (strlen($tag) < 2) { $this->dispatch('error', 'Invalid tag.', "Tag $tag is invalid. Min length is 2."); continue; } if ($this->resource->tags()->where('name', $tag)->exists()) { $this->dispatch('error', 'Duplicate tags.', "Tag $tag already added."); continue; } $found = Tag::ownedByCurrentTeam()->where(['name' => $tag])->exists(); if (! $found) { $found = Tag::create([ 'name' => $tag, 'team_id' => currentTeam()->id, ]); } $this->resource->tags()->attach($found->id); } $this->refresh(); } catch (\Exception $e) { return handleError($e, $this); } } public function addTag(string $id, string $name) { try { $this->authorize('update', $this->resource); $name = strip_tags($name); if ($this->resource->tags()->where('id', $id)->exists()) { $this->dispatch('error', 'Duplicate tags.', "Tag $name already added."); return; } $this->resource->tags()->attach($id); $this->refresh(); $this->dispatch('success', 'Tag added.'); } catch (\Exception $e) { return handleError($e, $this); } } public function deleteTag(string $id) { try { $this->authorize('update', $this->resource); $this->resource->tags()->detach($id); $found_more_tags = Tag::ownedByCurrentTeam()->find($id); if ($found_more_tags && $found_more_tags->applications()->count() == 0 && $found_more_tags->services()->count() == 0) { $found_more_tags->delete(); } $this->refresh(); $this->dispatch('success', 'Tag deleted.'); } catch (\Exception $e) { return handleError($e, $this); } } public function refresh() { $this->resource->refresh(); // Remove this when legacy_model_binding is false $this->loadTags(); $this->reset('newTags'); } } ================================================ FILE: app/Livewire/Project/Shared/Terminal.php ================================================ /dev/null || ". "docker exec {$escapedContainer} sh -c 'exit 0' 2>/dev/null", ], $server); return true; } catch (\Throwable) { return false; } } #[On('send-terminal-command')] public function sendTerminalCommand($isContainer, $identifier, $serverUuid) { $server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->firstOrFail(); if (! $server->isTerminalEnabled() || $server->isForceDisabled()) { abort(403, 'Terminal access is disabled on this server.'); } if ($isContainer) { // Validate container identifier format (alphanumeric, dashes, and underscores only) if (! preg_match('/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/', $identifier)) { throw new \InvalidArgumentException('Invalid container identifier format'); } // Verify container exists and belongs to the user's team $status = getContainerStatus($server, $identifier); if ($status !== 'running') { return; } // Check shell availability $this->hasShell = $this->checkShellAvailability($server, $identifier); if (! $this->hasShell) { return; } // Escape the identifier for shell usage $escapedIdentifier = escapeshellarg($identifier); $shellCommand = 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '. 'if [ -f ~/.profile ]; then . ~/.profile; fi && '. 'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi'; // Add sudo for non-root users to access Docker socket $dockerCommand = "docker exec -it {$escapedIdentifier} sh -c '{$shellCommand}'"; if ($server->isNonRoot()) { $dockerCommand = "sudo {$dockerCommand}"; } $command = SshMultiplexingHelper::generateSshCommand($server, $dockerCommand); } else { $shellCommand = 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '. 'if [ -f ~/.profile ]; then . ~/.profile; fi && '. 'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi'; $command = SshMultiplexingHelper::generateSshCommand($server, $shellCommand); } // ssh command is sent back to frontend then to websocket // this is done because the websocket connection is not available here // a better solution would be to remove websocket on NodeJS and work with something like // 1. Laravel Pusher/Echo connection (not possible without a sdk) // 2. Ratchet / Revolt / ReactPHP / Event Loop (possible but hard to implement and huge dependencies) // 3. Just found out about this https://github.com/sirn-se/websocket-php, perhaps it can be used // 4. Follow-up discussions here: // - https://github.com/coollabsio/coolify/issues/2298 // - https://github.com/coollabsio/coolify/discussions/3362 $this->dispatch('send-back-command', $command); } public function render() { return view('livewire.project.shared.terminal'); } } ================================================ FILE: app/Livewire/Project/Shared/UploadConfig.php ================================================ config = '{ "build_pack": "nixpacks", "base_directory": "/nodejs", "publish_directory": "/", "ports_exposes": "3000", "settings": { "is_static": false } }'; } } public function uploadConfig() { try { $application = Application::findOrFail($this->applicationId); $application->setConfig($this->config); $this->dispatch('success', 'Application settings updated'); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); return; } } public function render() { return view('livewire.project.shared.upload-config'); } } ================================================ FILE: app/Livewire/Project/Shared/Webhooks.php ================================================ deploywebhook = generateDeployWebhook($this->resource); $this->githubManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_github'); $this->githubManualWebhook = generateGitManualWebhook($this->resource, 'github'); $this->gitlabManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_gitlab'); $this->gitlabManualWebhook = generateGitManualWebhook($this->resource, 'gitlab'); $this->bitbucketManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_bitbucket'); $this->bitbucketManualWebhook = generateGitManualWebhook($this->resource, 'bitbucket'); $this->giteaManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_gitea'); $this->giteaManualWebhook = generateGitManualWebhook($this->resource, 'gitea'); } public function submit() { try { $this->authorize('update', $this->resource); $this->resource->update([ 'manual_webhook_secret_github' => $this->githubManualWebhookSecret, 'manual_webhook_secret_gitlab' => $this->gitlabManualWebhookSecret, 'manual_webhook_secret_bitbucket' => $this->bitbucketManualWebhookSecret, 'manual_webhook_secret_gitea' => $this->giteaManualWebhookSecret, ]); $this->dispatch('success', 'Secret Saved.'); } catch (\Exception $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Project/Show.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), ]; } protected function messages(): array { return ValidationPatterns::combinedMessages(); } public function mount(string $project_uuid) { try { $this->project = Project::where('team_id', currentTeam()->id)->where('uuid', $project_uuid)->firstOrFail(); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->validate(); $environment = Environment::create([ 'name' => $this->name, 'project_id' => $this->project->id, 'uuid' => (string) new Cuid2, ]); return redirectRoute($this, 'project.resource.index', [ 'project_uuid' => $this->project->uuid, 'environment_uuid' => $environment->uuid, ]); } catch (\Throwable $e) { handleError($e, $this); } } public function navigateToEnvironment($projectUuid, $environmentUuid) { return redirectRoute($this, 'project.resource.index', [ 'project_uuid' => $projectUuid, 'environment_uuid' => $environmentUuid, ]); } public function render() { return view('livewire.project.show'); } } ================================================ FILE: app/Livewire/Security/ApiTokens.php ================================================ isApiEnabled = InstanceSettings::get()->is_api_enabled; $this->canUseRootPermissions = auth()->user()->can('useRootPermissions', PersonalAccessToken::class); $this->canUseWritePermissions = auth()->user()->can('useWritePermissions', PersonalAccessToken::class); $this->getTokens(); } private function getTokens() { $this->tokens = auth()->user()->tokens->sortByDesc('created_at'); } public function updatedPermissions($permissionToUpdate) { // Check if user is trying to use restricted permissions if ($permissionToUpdate == 'root' && ! $this->canUseRootPermissions) { $this->dispatch('error', 'You do not have permission to use root permissions.'); // Remove root from permissions if it was somehow added $this->permissions = array_diff($this->permissions, ['root']); return; } if (in_array($permissionToUpdate, ['write', 'write:sensitive']) && ! $this->canUseWritePermissions) { $this->dispatch('error', 'You do not have permission to use write permissions.'); // Remove write permissions if they were somehow added $this->permissions = array_diff($this->permissions, ['write', 'write:sensitive']); return; } if ($permissionToUpdate == 'root') { $this->permissions = ['root']; } elseif ($permissionToUpdate == 'read:sensitive' && ! in_array('read', $this->permissions)) { $this->permissions[] = 'read'; } elseif ($permissionToUpdate == 'deploy') { $this->permissions = ['deploy']; } else { if (count($this->permissions) == 0) { $this->permissions = ['read']; } } sort($this->permissions); } public function addNewToken() { try { $this->authorize('create', PersonalAccessToken::class); // Validate permissions based on user role if (in_array('root', $this->permissions) && ! $this->canUseRootPermissions) { throw new \Exception('You do not have permission to create tokens with root permissions.'); } if (array_intersect(['write', 'write:sensitive'], $this->permissions) && ! $this->canUseWritePermissions) { throw new \Exception('You do not have permission to create tokens with write permissions.'); } $this->validate([ 'description' => 'required|min:3|max:255', ]); $token = auth()->user()->createToken($this->description, array_values($this->permissions)); $this->getTokens(); session()->flash('token', $token->plainTextToken); } catch (\Exception $e) { return handleError($e, $this); } } public function revoke(int $id) { try { $token = auth()->user()->tokens()->where('id', $id)->firstOrFail(); $this->authorize('delete', $token); $token->delete(); $this->getTokens(); } catch (\Exception $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Security/CloudInitScriptForm.php ================================================ scriptId = $scriptId; $cloudInitScript = CloudInitScript::ownedByCurrentTeam()->findOrFail($scriptId); $this->authorize('update', $cloudInitScript); $this->name = $cloudInitScript->name; $this->script = $cloudInitScript->script; } else { $this->authorize('create', CloudInitScript::class); } } protected function rules(): array { return [ 'name' => 'required|string|max:255', 'script' => ['required', 'string', new \App\Rules\ValidCloudInitYaml], ]; } protected function messages(): array { return [ 'name.required' => 'Script name is required.', 'name.max' => 'Script name cannot exceed 255 characters.', 'script.required' => 'Cloud-init script content is required.', ]; } public function save() { $this->validate(); try { if ($this->scriptId) { // Update existing script $cloudInitScript = CloudInitScript::ownedByCurrentTeam()->findOrFail($this->scriptId); $this->authorize('update', $cloudInitScript); $cloudInitScript->update([ 'name' => $this->name, 'script' => $this->script, ]); $message = 'Cloud-init script updated successfully.'; } else { // Create new script $this->authorize('create', CloudInitScript::class); CloudInitScript::create([ 'team_id' => currentTeam()->id, 'name' => $this->name, 'script' => $this->script, ]); $message = 'Cloud-init script created successfully.'; } // Only reset fields if creating (not editing) if (! $this->scriptId) { $this->reset(['name', 'script']); } $this->dispatch('scriptSaved'); $this->dispatch('success', $message); if ($this->modal_mode) { $this->dispatch('closeModal'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.security.cloud-init-script-form'); } } ================================================ FILE: app/Livewire/Security/CloudInitScripts.php ================================================ authorize('viewAny', CloudInitScript::class); $this->loadScripts(); } public function getListeners() { return [ 'scriptSaved' => 'loadScripts', ]; } public function loadScripts() { $this->scripts = CloudInitScript::ownedByCurrentTeam()->orderBy('created_at', 'desc')->get(); } public function deleteScript(int $scriptId) { try { $script = CloudInitScript::ownedByCurrentTeam()->findOrFail($scriptId); $this->authorize('delete', $script); $script->delete(); $this->loadScripts(); $this->dispatch('success', 'Cloud-init script deleted successfully.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.security.cloud-init-scripts'); } } ================================================ FILE: app/Livewire/Security/CloudProviderTokenForm.php ================================================ authorize('create', CloudProviderToken::class); } protected function rules(): array { return [ 'provider' => 'required|string|in:hetzner,digitalocean', 'token' => 'required|string', 'name' => 'required|string|max:255', ]; } protected function messages(): array { return [ 'provider.required' => 'Please select a cloud provider.', 'provider.in' => 'Invalid cloud provider selected.', 'token.required' => 'API token is required.', 'name.required' => 'Token name is required.', ]; } private function validateToken(string $provider, string $token): bool { try { if ($provider === 'hetzner') { $response = Http::withHeaders([ 'Authorization' => 'Bearer '.$token, ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); ray($response); return $response->successful(); } // Add other providers here in the future // if ($provider === 'digitalocean') { ... } return false; } catch (\Throwable $e) { return false; } } public function addToken() { $this->validate(); try { // Validate the token with the provider's API if (! $this->validateToken($this->provider, $this->token)) { return $this->dispatch('error', 'Invalid API token. Please check your token and try again.'); } $savedToken = CloudProviderToken::create([ 'team_id' => currentTeam()->id, 'provider' => $this->provider, 'token' => $this->token, 'name' => $this->name, ]); $this->reset(['token', 'name']); // Dispatch event with token ID so parent components can react $this->dispatch('tokenAdded', tokenId: $savedToken->id); $this->dispatch('success', 'Cloud provider token added successfully.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.security.cloud-provider-token-form'); } } ================================================ FILE: app/Livewire/Security/CloudProviderTokens.php ================================================ authorize('viewAny', CloudProviderToken::class); $this->loadTokens(); } public function getListeners() { return [ 'tokenAdded' => 'loadTokens', ]; } public function loadTokens() { $this->tokens = CloudProviderToken::ownedByCurrentTeam()->get(); } public function validateToken(int $tokenId) { try { $token = CloudProviderToken::ownedByCurrentTeam()->findOrFail($tokenId); $this->authorize('view', $token); if ($token->provider === 'hetzner') { $isValid = $this->validateHetznerToken($token->token); if ($isValid) { $this->dispatch('success', 'Hetzner token is valid.'); } else { $this->dispatch('error', 'Hetzner token validation failed. Please check the token.'); } } elseif ($token->provider === 'digitalocean') { $isValid = $this->validateDigitalOceanToken($token->token); if ($isValid) { $this->dispatch('success', 'DigitalOcean token is valid.'); } else { $this->dispatch('error', 'DigitalOcean token validation failed. Please check the token.'); } } else { $this->dispatch('error', 'Unknown provider.'); } } catch (\Throwable $e) { return handleError($e, $this); } } private function validateHetznerToken(string $token): bool { try { $response = \Illuminate\Support\Facades\Http::withToken($token) ->timeout(10) ->get('https://api.hetzner.cloud/v1/servers?per_page=1'); return $response->successful(); } catch (\Throwable $e) { return false; } } private function validateDigitalOceanToken(string $token): bool { try { $response = \Illuminate\Support\Facades\Http::withToken($token) ->timeout(10) ->get('https://api.digitalocean.com/v2/account'); return $response->successful(); } catch (\Throwable $e) { return false; } } public function deleteToken(int $tokenId) { try { $token = CloudProviderToken::ownedByCurrentTeam()->findOrFail($tokenId); $this->authorize('delete', $token); // Check if any servers are using this token if ($token->hasServers()) { $serverCount = $token->servers()->count(); $this->dispatch('error', "Cannot delete this token. It is currently used by {$serverCount} server(s). Please reassign those servers to a different token first."); return; } $token->delete(); $this->loadTokens(); $this->dispatch('success', 'Cloud provider token deleted successfully.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.security.cloud-provider-tokens'); } } ================================================ FILE: app/Livewire/Security/CloudTokens.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'value' => 'required|string', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'value.required' => 'The Private Key field is required.', 'value.string' => 'The Private Key must be a valid string.', ] ); } public function generateNewRSAKey() { $this->generateNewKey('rsa'); } public function generateNewEDKey() { $this->generateNewKey('ed25519'); } private function generateNewKey($type) { $keyData = PrivateKey::generateNewKeyPair($type); $this->setKeyData($keyData); } public function updated($property) { if ($property === 'value') { $this->validatePrivateKey(); } } public function createPrivateKey() { $this->validate(); try { $this->authorize('create', PrivateKey::class); $privateKey = PrivateKey::createAndStore([ 'name' => $this->name, 'description' => $this->description, 'private_key' => trim($this->value)."\n", 'team_id' => currentTeam()->id, ]); // If in modal mode, dispatch event and don't redirect if ($this->modal_mode) { $this->dispatch('privateKeyCreated', keyId: $privateKey->id); $this->dispatch('success', 'Private key created successfully.'); return; } return $this->redirectAfterCreation($privateKey); } catch (\Throwable $e) { return handleError($e, $this); } } private function setKeyData(array $keyData) { $this->name = $keyData['name']; $this->description = $keyData['description']; $this->value = $keyData['private_key']; $this->publicKey = $keyData['public_key']; } private function validatePrivateKey() { $validationResult = PrivateKey::validateAndExtractPublicKey($this->value); $this->publicKey = $validationResult['publicKey']; if (! $validationResult['isValid']) { $this->addError('value', 'Invalid private key'); } } private function redirectAfterCreation(PrivateKey $privateKey) { return $this->from === 'server' ? redirectRoute($this, 'dashboard') : redirectRoute($this, 'security.private-key.show', ['private_key_uuid' => $privateKey->uuid]); } } ================================================ FILE: app/Livewire/Security/PrivateKey/Index.php ================================================ get(); return view('livewire.security.private-key.index', [ 'privateKeys' => $privateKeys, ])->layout('components.layout'); } public function cleanupUnusedKeys() { $this->authorize('create', PrivateKey::class); PrivateKey::cleanupUnusedKeys(); $this->dispatch('success', 'Unused keys have been cleaned up.'); } } ================================================ FILE: app/Livewire/Security/PrivateKey/Show.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'privateKeyValue' => 'required|string', 'isGitRelated' => 'nullable|boolean', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', 'privateKeyValue.required' => 'The Private Key field is required.', 'privateKeyValue.string' => 'The Private Key must be a valid string.', ] ); } protected $validationAttributes = [ 'name' => 'name', 'description' => 'description', 'privateKeyValue' => 'private key', ]; /** * Sync data between component properties and model * * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties. */ private function syncData(bool $toModel = false): void { if ($toModel) { // Sync TO model (before save) $this->private_key->name = $this->name; $this->private_key->description = $this->description; $this->private_key->private_key = $this->privateKeyValue; $this->private_key->is_git_related = $this->isGitRelated; } else { // Sync FROM model (on load/refresh) $this->name = $this->private_key->name; $this->description = $this->private_key->description; $this->privateKeyValue = $this->private_key->private_key; $this->isGitRelated = $this->private_key->is_git_related; } } public function mount() { try { $this->private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related', 'team_id'])->whereUuid(request()->private_key_uuid)->firstOrFail(); // Explicit authorization check - will throw 403 if not authorized $this->authorize('view', $this->private_key); $this->syncData(false); } catch (\Illuminate\Auth\Access\AuthorizationException $e) { abort(403, 'You do not have permission to view this private key.'); } catch (\Throwable) { abort(404); } } public function loadPublicKey() { $this->public_key = $this->private_key->getPublicKey(); if ($this->public_key === 'Error loading private key') { $this->dispatch('error', 'Failed to load public key. The private key may be invalid.'); } } public function delete() { try { $this->authorize('delete', $this->private_key); $this->private_key->safeDelete(); currentTeam()->privateKeys = PrivateKey::where('team_id', currentTeam()->id)->get(); return redirectRoute($this, 'security.private-key.index'); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } catch (\Throwable $e) { return handleError($e, $this); } } public function changePrivateKey() { try { $this->authorize('update', $this->private_key); $this->validate(); $this->syncData(true); $this->private_key->updatePrivateKey([ 'private_key' => formatPrivateKey($this->private_key->private_key), ]); refresh_server_connection($this->private_key); $this->dispatch('success', 'Private key updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Server/Advanced.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->parameters = get_route_parameters(); $this->syncData(); } catch (\Throwable) { return redirect()->route('server.index'); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->authorize('update', $this->server); $this->validate(); $this->server->settings->concurrent_builds = $this->concurrentBuilds; $this->server->settings->dynamic_timeout = $this->dynamicTimeout; $this->server->settings->deployment_queue_limit = $this->deploymentQueueLimit; $this->server->settings->server_disk_usage_notification_threshold = $this->serverDiskUsageNotificationThreshold; $this->server->settings->server_disk_usage_check_frequency = $this->serverDiskUsageCheckFrequency; $this->server->settings->save(); } else { $this->concurrentBuilds = $this->server->settings->concurrent_builds; $this->dynamicTimeout = $this->server->settings->dynamic_timeout; $this->deploymentQueueLimit = $this->server->settings->deployment_queue_limit; $this->serverDiskUsageNotificationThreshold = $this->server->settings->server_disk_usage_notification_threshold; $this->serverDiskUsageCheckFrequency = $this->server->settings->server_disk_usage_check_frequency; } } public function instantSave() { try { $this->syncData(true); $this->dispatch('success', 'Server updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { if (! validate_cron_expression($this->serverDiskUsageCheckFrequency)) { $this->serverDiskUsageCheckFrequency = $this->server->settings->getOriginal('server_disk_usage_check_frequency'); throw new \Exception('Invalid Cron / Human expression for Disk Usage Check Frequency.'); } $this->syncData(true); $this->dispatch('success', 'Server updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.advanced'); } } ================================================ FILE: app/Livewire/Server/CaCertificate/Show.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->loadCaCertificate(); } catch (\Throwable $e) { return redirect()->route('server.index'); } } public function loadCaCertificate() { $this->caCertificate = $this->server->sslCertificates()->where('is_ca_certificate', true)->first(); if ($this->caCertificate) { $this->certificateContent = $this->caCertificate->ssl_certificate; $this->certificateValidUntil = $this->caCertificate->valid_until; } } public function toggleCertificate() { $this->showCertificate = ! $this->showCertificate; } public function saveCaCertificate() { try { $this->authorize('manageCaCertificate', $this->server); if (! $this->certificateContent) { throw new \Exception('Certificate content cannot be empty.'); } $parsedCert = openssl_x509_read($this->certificateContent); if (! $parsedCert) { throw new \Exception('Invalid certificate format.'); } if (! openssl_x509_export($parsedCert, $cleanedCertificate)) { throw new \Exception('Failed to process certificate.'); } $this->certificateContent = $cleanedCertificate; if ($this->caCertificate) { $this->caCertificate->ssl_certificate = $this->certificateContent; $this->caCertificate->save(); $this->loadCaCertificate(); $this->writeCertificateToServer(); dispatch(new RegenerateSslCertJob( server_id: $this->server->id, force_regeneration: true )); } $this->dispatch('success', 'CA Certificate saved successfully.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function regenerateCaCertificate() { try { $this->authorize('manageCaCertificate', $this->server); SslHelper::generateSslCertificate( commonName: 'Coolify CA Certificate', serverId: $this->server->id, isCaCertificate: true, validityDays: 10 * 365 ); $this->loadCaCertificate(); $this->writeCertificateToServer(); dispatch(new RegenerateSslCertJob( server_id: $this->server->id, force_regeneration: true )); $this->loadCaCertificate(); $this->dispatch('success', 'CA Certificate regenerated successfully.'); } catch (\Throwable $e) { return handleError($e, $this); } } private function writeCertificateToServer() { $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; $base64Cert = base64_encode($this->certificateContent); $commands = collect([ "mkdir -p $caCertPath", "chown -R 9999:root $caCertPath", "chmod -R 700 $caCertPath", "rm -rf $caCertPath/coolify-ca.crt", "echo '{$base64Cert}' | base64 -d | tee $caCertPath/coolify-ca.crt > /dev/null", "chmod 644 $caCertPath/coolify-ca.crt", ]); remote_process($commands, $this->server); } public function render() { return view('livewire.server.ca-certificate.show'); } } ================================================ FILE: app/Livewire/Server/Charts.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); } catch (\Throwable $e) { return handleError($e, $this); } } public function pollData() { if ($this->poll || $this->interval <= 10) { $this->loadData(); if ($this->interval > 10) { $this->poll = false; } } } public function loadData() { try { $cpuMetrics = $this->server->getCpuMetrics($this->interval); $memoryMetrics = $this->server->getMemoryMetrics($this->interval); $this->dispatch("refreshChartData-{$this->chartId}-cpu", [ 'seriesData' => $cpuMetrics, ]); $this->dispatch("refreshChartData-{$this->chartId}-memory", [ 'seriesData' => $memoryMetrics, ]); } catch (\Throwable $e) { return handleError($e, $this); } } public function setInterval() { if ($this->interval <= 10) { $this->poll = true; } $this->loadData(); } } ================================================ FILE: app/Livewire/Server/CloudProviderToken/Show.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->loadTokens(); } catch (\Throwable $e) { return handleError($e, $this); } } public function getListeners() { return [ 'tokenAdded' => 'handleTokenAdded', ]; } public function loadTokens() { $this->cloudProviderTokens = CloudProviderToken::ownedByCurrentTeam() ->where('provider', 'hetzner') ->get(); } public function handleTokenAdded($tokenId) { $this->loadTokens(); } public function setCloudProviderToken($tokenId) { $ownedToken = CloudProviderToken::ownedByCurrentTeam()->find($tokenId); if (is_null($ownedToken)) { $this->dispatch('error', 'You are not allowed to use this token.'); return; } try { $this->authorize('update', $this->server); // Validate the token works and can access this specific server $validationResult = $this->validateTokenForServer($ownedToken); if (! $validationResult['valid']) { $this->dispatch('error', $validationResult['error']); return; } $this->server->cloudProviderToken()->associate($ownedToken); $this->server->save(); $this->dispatch('success', 'Hetzner token updated successfully.'); $this->dispatch('refreshServerShow'); } catch (\Exception $e) { $this->server->refresh(); $this->dispatch('error', $e->getMessage()); } } private function validateTokenForServer(CloudProviderToken $token): array { try { // First, validate the token itself $response = \Illuminate\Support\Facades\Http::withHeaders([ 'Authorization' => 'Bearer '.$token->token, ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); if (! $response->successful()) { return [ 'valid' => false, 'error' => 'This token is invalid or has insufficient permissions.', ]; } // Check if this token can access the specific Hetzner server if ($this->server->hetzner_server_id) { $serverResponse = \Illuminate\Support\Facades\Http::withHeaders([ 'Authorization' => 'Bearer '.$token->token, ])->timeout(10)->get("https://api.hetzner.cloud/v1/servers/{$this->server->hetzner_server_id}"); if (! $serverResponse->successful()) { return [ 'valid' => false, 'error' => 'This token cannot access this server. It may belong to a different Hetzner project.', ]; } } return ['valid' => true]; } catch (\Throwable $e) { return [ 'valid' => false, 'error' => 'Failed to validate token: '.$e->getMessage(), ]; } } public function validateToken() { try { $token = $this->server->cloudProviderToken; if (! $token) { $this->dispatch('error', 'No Hetzner token is associated with this server.'); return; } $response = \Illuminate\Support\Facades\Http::withHeaders([ 'Authorization' => 'Bearer '.$token->token, ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); if ($response->successful()) { $this->dispatch('success', 'Hetzner token is valid and working.'); } else { $this->dispatch('error', 'Hetzner token is invalid or has insufficient permissions.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.cloud-provider-token.show'); } } ================================================ FILE: app/Livewire/Server/CloudflareTunnel.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},CloudflareTunnelConfigured" => 'refresh', ]; } public function refresh() { $this->server->refresh(); $this->isCloudflareTunnelsEnabled = $this->server->settings->is_cloudflare_tunnel; } public function mount(string $server_uuid) { try { $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); if ($this->server->isLocalhost()) { return redirect()->route('server.show', ['server_uuid' => $server_uuid]); } $this->isCloudflareTunnelsEnabled = $this->server->settings->is_cloudflare_tunnel; } catch (\Throwable $e) { return handleError($e, $this); } } public function toggleCloudflareTunnels() { try { $this->authorize('update', $this->server); remote_process(['docker rm -f coolify-cloudflared'], $this->server, false, 10); $this->isCloudflareTunnelsEnabled = false; $this->server->settings->is_cloudflare_tunnel = false; $this->server->settings->save(); if ($this->server->ip_previous) { $this->server->update(['ip' => $this->server->ip_previous]); $this->dispatch('success', 'Cloudflare Tunnel disabled.

Manually updated the server IP address to its previous IP address.'); } else { $this->dispatch('warning', 'Cloudflare Tunnel disabled. Action required: Update the server IP address to its real IP address in the Advanced settings.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function manualCloudflareConfig() { $this->authorize('update', $this->server); $this->isCloudflareTunnelsEnabled = true; $this->server->settings->is_cloudflare_tunnel = true; $this->server->settings->save(); $this->server->refresh(); $this->dispatch('success', 'Cloudflare Tunnel enabled.'); } public function automatedCloudflareConfig() { try { $this->authorize('update', $this->server); if (str($this->ssh_domain)->contains('https://')) { $this->ssh_domain = str($this->ssh_domain)->replace('https://', '')->replace('http://', '')->trim(); $this->ssh_domain = str($this->ssh_domain)->replace('/', ''); } $activity = ConfigureCloudflared::run($this->server, $this->cloudflare_token, $this->ssh_domain); $this->dispatch('activityMonitor', $activity->id); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.cloudflare-tunnel'); } } ================================================ FILE: app/Livewire/Server/Create.php ================================================ private_keys = PrivateKey::ownedByCurrentTeamCached(); if (! isCloud()) { $this->limit_reached = false; return; } $this->limit_reached = Team::serverLimitReached(); // Check if user has Hetzner tokens $this->has_hetzner_tokens = CloudProviderToken::ownedByCurrentTeam() ->where('provider', 'hetzner') ->exists(); } public function render() { return view('livewire.server.create'); } } ================================================ FILE: app/Livewire/Server/Delete.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); } catch (\Throwable $e) { return handleError($e, $this); } } public function delete($password, $selectedActions = []) { if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } if (! empty($selectedActions)) { $this->delete_from_hetzner = in_array('delete_from_hetzner', $selectedActions); } try { $this->authorize('delete', $this->server); if ($this->server->hasDefinedResources()) { $this->dispatch('error', 'Server has defined resources. Please delete them first.'); return; } $this->server->delete(); DeleteServer::dispatch( $this->server->id, $this->delete_from_hetzner, $this->server->hetzner_server_id, $this->server->cloud_provider_token_id, $this->server->team_id ); return redirectRoute($this, 'server.index'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { $checkboxes = []; if ($this->server->hetzner_server_id) { $checkboxes[] = [ 'id' => 'delete_from_hetzner', 'label' => 'Also delete server from Hetzner Cloud', 'default_warning' => 'The actual server on Hetzner Cloud will NOT be deleted.', ]; } return view('livewire.server.delete', [ 'checkboxes' => $checkboxes, ]); } } ================================================ FILE: app/Livewire/Server/Destinations.php ================================================ networks = collect(); $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); } catch (\Throwable $e) { return handleError($e, $this); } } private function createNetworkAndAttachToProxy() { ConnectProxyToNetworksJob::dispatchSync($this->server); } public function add($name) { if ($this->server->isSwarm()) { $this->authorize('create', SwarmDocker::class); $found = $this->server->swarmDockers()->where('network', $name)->first(); if ($found) { $this->dispatch('error', 'Network already added to this server.'); return; } else { SwarmDocker::create([ 'name' => $this->server->name.'-'.$name, 'network' => $this->name, 'server_id' => $this->server->id, ]); } } else { $this->authorize('create', StandaloneDocker::class); $found = $this->server->standaloneDockers()->where('network', $name)->first(); if ($found) { $this->dispatch('error', 'Network already added to this server.'); return; } else { StandaloneDocker::create([ 'name' => $this->server->name.'-'.$name, 'network' => $name, 'server_id' => $this->server->id, ]); } $this->createNetworkAndAttachToProxy(); } } public function scan() { if ($this->server->isSwarm()) { $alreadyAddedNetworks = $this->server->swarmDockers; } else { $alreadyAddedNetworks = $this->server->standaloneDockers; } $networks = instant_remote_process(['docker network ls --format "{{json .}}"'], $this->server, false); $this->networks = format_docker_command_output_to_json($networks)->filter(function ($network) { return $network['Name'] !== 'bridge' && $network['Name'] !== 'host' && $network['Name'] !== 'none'; })->filter(function ($network) use ($alreadyAddedNetworks) { return ! $alreadyAddedNetworks->contains('network', $network['Name']); }); if ($this->networks->count() === 0) { $this->dispatch('success', 'No new destinations found on this server.'); return; } $this->dispatch('success', 'Scan done.'); } public function render() { return view('livewire.server.destinations'); } } ================================================ FILE: app/Livewire/Server/DockerCleanup.php ================================================ server->id) ->orderBy('created_at', 'desc') ->first(); if (! $lastExecution) { return false; } $frequency = $this->server->settings->docker_cleanup_frequency ?? '0 0 * * *'; if (isset(VALID_CRON_STRINGS[$frequency])) { $frequency = VALID_CRON_STRINGS[$frequency]; } $cron = new CronExpression($frequency); $now = Carbon::now(); $nextRun = Carbon::parse($cron->getNextRunDate($now)); $afterThat = Carbon::parse($cron->getNextRunDate($nextRun)); $intervalMinutes = $nextRun->diffInMinutes($afterThat); $threshold = max($intervalMinutes * 2, 10); return Carbon::parse($lastExecution->created_at)->diffInMinutes($now) > $threshold; } catch (\Throwable) { return false; } } #[Computed] public function lastExecutionTime(): ?string { return DockerCleanupExecution::where('server_id', $this->server->id) ->orderBy('created_at', 'desc') ->first() ?->created_at ?->diffForHumans(); } #[Computed] public function isSchedulerHealthy(): bool { return Cache::get('scheduled-job-manager:heartbeat') !== null; } public function mount(string $server_uuid) { try { $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->parameters = get_route_parameters(); $this->syncData(); } catch (\Throwable) { return redirect()->route('server.index'); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->authorize('update', $this->server); $this->validate(); $this->server->settings->force_docker_cleanup = $this->forceDockerCleanup; $this->server->settings->docker_cleanup_frequency = $this->dockerCleanupFrequency; $this->server->settings->docker_cleanup_threshold = $this->dockerCleanupThreshold; $this->server->settings->delete_unused_volumes = $this->deleteUnusedVolumes; $this->server->settings->delete_unused_networks = $this->deleteUnusedNetworks; $this->server->settings->disable_application_image_retention = $this->disableApplicationImageRetention; $this->server->settings->save(); } else { $this->forceDockerCleanup = $this->server->settings->force_docker_cleanup; $this->dockerCleanupFrequency = $this->server->settings->docker_cleanup_frequency; $this->dockerCleanupThreshold = $this->server->settings->docker_cleanup_threshold; $this->deleteUnusedVolumes = $this->server->settings->delete_unused_volumes; $this->deleteUnusedNetworks = $this->server->settings->delete_unused_networks; $this->disableApplicationImageRetention = $this->server->settings->disable_application_image_retention; } } public function instantSave() { try { $this->syncData(true); $this->dispatch('success', 'Server updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function manualCleanup() { try { $this->authorize('update', $this->server); DockerCleanupJob::dispatch($this->server, true, $this->deleteUnusedVolumes, $this->deleteUnusedNetworks); $this->dispatch('success', 'Manual cleanup job started. Depending on the amount of data, this might take a while.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { if (! validate_cron_expression($this->dockerCleanupFrequency)) { $this->dockerCleanupFrequency = $this->server->settings->getOriginal('docker_cleanup_frequency'); throw new \Exception('Invalid Cron / Human expression for Docker Cleanup Frequency.'); } $this->syncData(true); $this->dispatch('success', 'Server updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.docker-cleanup'); } } ================================================ FILE: app/Livewire/Server/DockerCleanupExecutions.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},DockerCleanupDone" => 'refreshExecutions', ]; } public function mount(Server $server) { $this->server = $server; $this->refreshExecutions(); } public function refreshExecutions(): void { $this->executions = $this->server->dockerCleanupExecutions() ->orderBy('created_at', 'desc') ->take(20) ->get(); if ($this->selectedKey) { $this->selectedExecution = DockerCleanupExecution::find($this->selectedKey); if ($this->selectedExecution && $this->selectedExecution->status !== 'running') { $this->isPollingActive = false; } } } public function selectExecution($key): void { if ($key == $this->selectedKey) { $this->selectedKey = null; $this->selectedExecution = null; $this->currentPage = 1; $this->isPollingActive = false; return; } $this->selectedKey = $key; $this->selectedExecution = DockerCleanupExecution::find($key); $this->currentPage = 1; if ($this->selectedExecution && $this->selectedExecution->status === 'running') { $this->isPollingActive = true; } } public function polling() { if ($this->selectedExecution && $this->isPollingActive) { $this->selectedExecution->refresh(); if ($this->selectedExecution->status !== 'running') { $this->isPollingActive = false; } } $this->refreshExecutions(); } public function loadMoreLogs() { $this->currentPage++; } public function getLogLinesProperty() { if (! $this->selectedExecution) { return collect(); } if (! $this->selectedExecution->message) { return collect(['Waiting for execution output...']); } $lines = collect(explode("\n", $this->selectedExecution->message)); return $lines->take($this->currentPage * $this->logsPerPage); } public function downloadLogs(int $executionId) { $execution = $this->executions->firstWhere('id', $executionId); if (! $execution) { return; } return response()->streamDownload(function () use ($execution) { echo $execution->message; }, "docker-cleanup-{$execution->uuid}.log"); } public function hasMoreLogs() { if (! $this->selectedExecution || ! $this->selectedExecution->message) { return false; } $lines = collect(explode("\n", $this->selectedExecution->message)); return $lines->count() > ($this->currentPage * $this->logsPerPage); } public function render() { return view('livewire.server.docker-cleanup-executions'); } } ================================================ FILE: app/Livewire/Server/Index.php ================================================ servers = Server::ownedByCurrentTeamCached(); } public function render() { return view('livewire.server.index'); } } ================================================ FILE: app/Livewire/Server/LogDrains.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } public function syncDataNewRelic(bool $toModel = false) { if ($toModel) { $this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled; $this->server->settings->logdrain_newrelic_license_key = $this->logDrainNewRelicLicenseKey; $this->server->settings->logdrain_newrelic_base_uri = $this->logDrainNewRelicBaseUri; } else { $this->isLogDrainNewRelicEnabled = $this->server->settings->is_logdrain_newrelic_enabled; $this->logDrainNewRelicLicenseKey = $this->server->settings->logdrain_newrelic_license_key; $this->logDrainNewRelicBaseUri = $this->server->settings->logdrain_newrelic_base_uri; } } public function syncDataAxiom(bool $toModel = false) { if ($toModel) { $this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled; $this->server->settings->logdrain_axiom_dataset_name = $this->logDrainAxiomDatasetName; $this->server->settings->logdrain_axiom_api_key = $this->logDrainAxiomApiKey; } else { $this->isLogDrainAxiomEnabled = $this->server->settings->is_logdrain_axiom_enabled; $this->logDrainAxiomDatasetName = $this->server->settings->logdrain_axiom_dataset_name; $this->logDrainAxiomApiKey = $this->server->settings->logdrain_axiom_api_key; } } public function syncDataCustom(bool $toModel = false) { if ($toModel) { $this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled; $this->server->settings->logdrain_custom_config = $this->logDrainCustomConfig; $this->server->settings->logdrain_custom_config_parser = $this->logDrainCustomConfigParser; } else { $this->isLogDrainCustomEnabled = $this->server->settings->is_logdrain_custom_enabled; $this->logDrainCustomConfig = $this->server->settings->logdrain_custom_config; $this->logDrainCustomConfigParser = $this->server->settings->logdrain_custom_config_parser; } } public function syncData(bool $toModel = false, ?string $type = null) { if ($toModel) { $this->customValidation(); if ($type === 'newrelic') { $this->syncDataNewRelic($toModel); } elseif ($type === 'axiom') { $this->syncDataAxiom($toModel); } elseif ($type === 'custom') { $this->syncDataCustom($toModel); } else { $this->syncDataNewRelic($toModel); $this->syncDataAxiom($toModel); $this->syncDataCustom($toModel); } $this->server->settings->save(); } else { if ($type === 'newrelic') { $this->syncDataNewRelic($toModel); } elseif ($type === 'axiom') { $this->syncDataAxiom($toModel); } elseif ($type === 'custom') { $this->syncDataCustom($toModel); } else { $this->syncDataNewRelic($toModel); $this->syncDataAxiom($toModel); $this->syncDataCustom($toModel); } } } public function customValidation() { if ($this->isLogDrainNewRelicEnabled) { try { $this->validate([ 'logDrainNewRelicLicenseKey' => ['required', 'regex:/^[a-zA-Z0-9_\-\.]+$/'], 'logDrainNewRelicBaseUri' => ['required', 'url'], ]); } catch (\Throwable $e) { $this->isLogDrainNewRelicEnabled = false; throw $e; } } elseif ($this->isLogDrainAxiomEnabled) { try { $this->validate([ 'logDrainAxiomDatasetName' => ['required', 'regex:/^[a-zA-Z0-9_\-\.]+$/'], 'logDrainAxiomApiKey' => ['required', 'regex:/^[a-zA-Z0-9_\-\.]+$/'], ]); } catch (\Throwable $e) { $this->isLogDrainAxiomEnabled = false; throw $e; } } elseif ($this->isLogDrainCustomEnabled) { try { $this->validate([ 'logDrainCustomConfig' => ['required'], 'logDrainCustomConfigParser' => ['string', 'nullable'], ]); } catch (\Throwable $e) { $this->isLogDrainCustomEnabled = false; throw $e; } } } public function instantSave() { try { $this->authorize('update', $this->server); $this->syncData(true); if ($this->server->isLogDrainEnabled()) { StartLogDrain::run($this->server); $this->dispatch('success', 'Log drain service started.'); } else { StopLogDrain::run($this->server); $this->dispatch('success', 'Log drain service stopped.'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function submit(string $type) { try { $this->authorize('update', $this->server); $this->syncData(true, $type); $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.log-drains'); } } ================================================ FILE: app/Livewire/Server/Navbar.php ================================================ user()->currentTeam()->id; return [ 'refreshServerShow' => 'refreshServer', "echo-private:team.{$teamId},ProxyStatusChangedUI" => 'showNotification', ]; } public function mount(Server $server) { $this->server = $server; $this->currentRoute = request()->route()->getName(); $this->serverIp = $this->server->id === 0 ? base_ip() : $this->server->ip; $this->proxyStatus = $this->server->proxy->status ?? 'unknown'; $this->loadProxyConfiguration(); } public function loadProxyConfiguration() { try { if ($this->proxyStatus === 'running') { $this->traefikDashboardAvailable = ProxyDashboardCacheService::isTraefikDashboardAvailableFromCache($this->server); } } catch (\Throwable $e) { return handleError($e, $this); } } public function restart() { try { $this->authorize('manageProxy', $this->server); // Prevent duplicate restart calls if ($this->restartInitiated) { return; } $this->restartInitiated = true; // Always use background job for all servers RestartProxyJob::dispatch($this->server); } catch (\Throwable $e) { $this->restartInitiated = false; return handleError($e, $this); } } public function checkProxy() { try { $this->authorize('manageProxy', $this->server); CheckProxy::run($this->server, true); $this->dispatch('startProxy')->self(); } catch (\Throwable $e) { return handleError($e, $this); } } public function startProxy() { try { $this->authorize('manageProxy', $this->server); $activity = StartProxy::run($this->server, force: true); $this->dispatch('activityMonitor', $activity->id); } catch (\Throwable $e) { return handleError($e, $this); } } public function stop(bool $forceStop = true) { try { $this->authorize('manageProxy', $this->server); StopProxy::dispatch($this->server, $forceStop); } catch (\Throwable $e) { return handleError($e, $this); } } public function checkProxyStatus() { if ($this->isChecking) { return; } try { $this->isChecking = true; CheckProxy::run($this->server, true); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->isChecking = false; $this->showNotification(); } } public function showNotification($event = null) { $previousStatus = $this->proxyStatus; $this->server->refresh(); $this->proxyStatus = $this->server->proxy->status ?? 'unknown'; // If event contains activityId, open activity monitor if ($event && isset($event['activityId'])) { $this->dispatch('activityMonitor', $event['activityId']); } // Reset restart flag when proxy reaches a stable state if (in_array($this->proxyStatus, ['running', 'exited', 'error'])) { $this->restartInitiated = false; } // Skip notification if we already notified about this status (prevents duplicates) if ($this->lastNotifiedStatus === $this->proxyStatus) { return; } switch ($this->proxyStatus) { case 'running': $this->loadProxyConfiguration(); // Only show "Proxy is running" notification when transitioning from a stopped/error state // Don't show during normal start/restart flows (starting, restarting, stopping) if (in_array($previousStatus, ['exited', 'stopped', 'unknown', null])) { $this->dispatch('success', 'Proxy is running.'); $this->lastNotifiedStatus = $this->proxyStatus; } break; case 'exited': // Only show "Proxy has exited" notification when transitioning from running state // Don't show during normal stop/restart flows (stopping, restarting) if (in_array($previousStatus, ['running'])) { $this->dispatch('info', 'Proxy has exited.'); $this->lastNotifiedStatus = $this->proxyStatus; } break; case 'stopping': // $this->dispatch('info', 'Proxy is stopping.'); $this->lastNotifiedStatus = $this->proxyStatus; break; case 'starting': // $this->dispatch('info', 'Proxy is starting.'); $this->lastNotifiedStatus = $this->proxyStatus; break; case 'restarting': // $this->dispatch('info', 'Proxy is restarting.'); $this->lastNotifiedStatus = $this->proxyStatus; break; case 'error': $this->dispatch('error', 'Proxy restart failed. Check logs.'); $this->lastNotifiedStatus = $this->proxyStatus; break; case 'unknown': // Don't notify for unknown status - too noisy break; default: // Don't notify for other statuses break; } } public function refreshServer() { $this->server->refresh(); $this->server->load('settings'); } /** * Check if Traefik has any outdated version info (patch or minor upgrade). * This shows a warning indicator in the navbar. */ public function getHasTraefikOutdatedProperty(): bool { if ($this->server->proxyType() !== ProxyTypes::TRAEFIK->value) { return false; } // Check if server has outdated info stored $outdatedInfo = $this->server->traefik_outdated_info; return ! empty($outdatedInfo) && isset($outdatedInfo['type']); } public function render() { return view('livewire.server.navbar'); } } ================================================ FILE: app/Livewire/Server/New/ByHetzner.php ================================================ authorize('viewAny', CloudProviderToken::class); $this->loadTokens(); $this->loadSavedCloudInitScripts(); $this->server_name = generate_random_name(); $this->private_keys = PrivateKey::ownedAndOnlySShKeys()->where('id', '!=', 0)->get(); if ($this->private_keys->count() > 0) { $this->private_key_id = $this->private_keys->first()->id; } } public function loadSavedCloudInitScripts() { $this->saved_cloud_init_scripts = CloudInitScript::ownedByCurrentTeam()->get(); } public function getListeners() { return [ 'tokenAdded' => 'handleTokenAdded', 'privateKeyCreated' => 'handlePrivateKeyCreated', 'modalClosed' => 'resetSelection', ]; } public function resetSelection() { $this->selected_token_id = null; $this->current_step = 1; $this->cloud_init_script = null; $this->save_cloud_init_script = false; $this->cloud_init_script_name = null; $this->selected_cloud_init_script_id = null; } public function loadTokens() { $this->available_tokens = CloudProviderToken::ownedByCurrentTeam() ->where('provider', 'hetzner') ->get(); } public function handleTokenAdded($tokenId) { // Refresh token list $this->loadTokens(); // Auto-select the new token $this->selected_token_id = $tokenId; // Automatically proceed to next step $this->nextStep(); } public function handlePrivateKeyCreated($keyId) { // Refresh private keys list $this->private_keys = PrivateKey::ownedAndOnlySShKeys()->where('id', '!=', 0)->get(); // Auto-select the new key $this->private_key_id = $keyId; // Clear validation errors for private_key_id $this->resetErrorBag('private_key_id'); } protected function rules(): array { $rules = [ 'selected_token_id' => 'required|integer|exists:cloud_provider_tokens,id', ]; if ($this->current_step === 2) { $rules = array_merge($rules, [ 'server_name' => ['required', 'string', 'max:253', new ValidHostname], 'selected_location' => 'required|string', 'selected_image' => 'required|integer', 'selected_server_type' => 'required|string', 'private_key_id' => 'required|integer|exists:private_keys,id,team_id,'.currentTeam()->id, 'selectedHetznerSshKeyIds' => 'nullable|array', 'selectedHetznerSshKeyIds.*' => 'integer', 'enable_ipv4' => 'required|boolean', 'enable_ipv6' => 'required|boolean', 'cloud_init_script' => ['nullable', 'string', new \App\Rules\ValidCloudInitYaml], 'save_cloud_init_script' => 'boolean', 'cloud_init_script_name' => 'nullable|string|max:255', 'selected_cloud_init_script_id' => 'nullable|integer|exists:cloud_init_scripts,id', ]); } return $rules; } protected function messages(): array { return [ 'selected_token_id.required' => 'Please select a Hetzner token.', 'selected_token_id.exists' => 'Selected token not found.', ]; } public function selectToken(int $tokenId) { $this->selected_token_id = $tokenId; } private function validateHetznerToken(string $token): bool { try { $response = Http::withHeaders([ 'Authorization' => 'Bearer '.$token, ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); return $response->successful(); } catch (\Throwable $e) { return false; } } private function getHetznerToken(): string { if ($this->selected_token_id) { $token = $this->available_tokens->firstWhere('id', $this->selected_token_id); return $token ? $token->token : ''; } return ''; } public function nextStep() { // Validate step 1 - just need a token selected $this->validate([ 'selected_token_id' => 'required|integer|exists:cloud_provider_tokens,id', ]); try { $hetznerToken = $this->getHetznerToken(); if (! $hetznerToken) { return $this->dispatch('error', 'Please select a valid Hetzner token.'); } // Load Hetzner data $this->loadHetznerData($hetznerToken); // Move to step 2 $this->current_step = 2; } catch (\Throwable $e) { return handleError($e, $this); } } public function previousStep() { $this->current_step = 1; } private function loadHetznerData(string $token) { $this->loading_data = true; try { $hetznerService = new HetznerService($token); $this->locations = $hetznerService->getLocations(); $this->serverTypes = $hetznerService->getServerTypes(); // Get images and sort by name $images = $hetznerService->getImages(); $this->images = collect($images) ->filter(function ($image) { // Only system images if (! isset($image['type']) || $image['type'] !== 'system') { return false; } // Filter out deprecated images if (isset($image['deprecated']) && $image['deprecated'] === true) { return false; } return true; }) ->sortBy('name') ->values() ->toArray(); // Load SSH keys from Hetzner $this->hetznerSshKeys = $hetznerService->getSshKeys(); $this->loading_data = false; } catch (\Throwable $e) { $this->loading_data = false; throw $e; } } private function getCpuVendorInfo(array $serverType): ?string { $name = strtolower($serverType['name'] ?? ''); if (str_starts_with($name, 'ccx')) { return 'AMD Milan EPYC™'; } elseif (str_starts_with($name, 'cpx')) { return 'AMD EPYC™'; } elseif (str_starts_with($name, 'cx')) { return 'Intel®/AMD'; } elseif (str_starts_with($name, 'cax')) { return 'Ampere®'; } return null; } public function getAvailableServerTypesProperty() { ray('Getting available server types', [ 'selected_location' => $this->selected_location, 'total_server_types' => count($this->serverTypes), ]); if (! $this->selected_location) { return $this->serverTypes; } $filtered = collect($this->serverTypes) ->filter(function ($type) { if (! isset($type['locations'])) { return false; } $locationNames = collect($type['locations'])->pluck('name')->toArray(); return in_array($this->selected_location, $locationNames); }) ->map(function ($serverType) { $serverType['cpu_vendor_info'] = $this->getCpuVendorInfo($serverType); return $serverType; }) ->values() ->toArray(); ray('Filtered server types', [ 'selected_location' => $this->selected_location, 'filtered_count' => count($filtered), ]); return $filtered; } public function getAvailableImagesProperty() { ray('Getting available images', [ 'selected_server_type' => $this->selected_server_type, 'total_images' => count($this->images), 'images' => $this->images, ]); if (! $this->selected_server_type) { return $this->images; } $serverType = collect($this->serverTypes)->firstWhere('name', $this->selected_server_type); ray('Server type data', $serverType); if (! $serverType || ! isset($serverType['architecture'])) { ray('No architecture in server type, returning all'); return $this->images; } $architecture = $serverType['architecture']; $filtered = collect($this->images) ->filter(fn ($image) => ($image['architecture'] ?? null) === $architecture) ->values() ->toArray(); ray('Filtered images', [ 'architecture' => $architecture, 'filtered_count' => count($filtered), ]); return $filtered; } public function getSelectedServerPriceProperty(): ?string { if (! $this->selected_server_type) { return null; } $serverType = collect($this->serverTypes)->firstWhere('name', $this->selected_server_type); if (! $serverType || ! isset($serverType['prices'][0]['price_monthly']['gross'])) { return null; } $price = $serverType['prices'][0]['price_monthly']['gross']; return '€'.number_format($price, 2); } public function updatedSelectedLocation($value) { ray('Location selected', $value); // Reset server type and image when location changes $this->selected_server_type = null; $this->selected_image = null; } public function updatedSelectedServerType($value) { ray('Server type selected', $value); // Reset image when server type changes $this->selected_image = null; } public function updatedSelectedImage($value) { ray('Image selected', $value); } public function updatedSelectedCloudInitScriptId($value) { if ($value) { $script = CloudInitScript::ownedByCurrentTeam()->findOrFail($value); $this->cloud_init_script = $script->script; $this->cloud_init_script_name = $script->name; } } public function clearCloudInitScript() { $this->selected_cloud_init_script_id = null; $this->cloud_init_script = ''; $this->cloud_init_script_name = ''; $this->save_cloud_init_script = false; } private function createHetznerServer(string $token): array { $hetznerService = new HetznerService($token); // Get the private key and extract public key $privateKey = PrivateKey::ownedByCurrentTeam()->findOrFail($this->private_key_id); $publicKey = $privateKey->getPublicKey(); $md5Fingerprint = PrivateKey::generateMd5Fingerprint($privateKey->private_key); ray('Private Key Info', [ 'private_key_id' => $this->private_key_id, 'sha256_fingerprint' => $privateKey->fingerprint, 'md5_fingerprint' => $md5Fingerprint, ]); // Check if SSH key already exists on Hetzner by comparing MD5 fingerprints $existingSshKeys = $hetznerService->getSshKeys(); $existingKey = null; ray('Existing SSH Keys on Hetzner', $existingSshKeys); foreach ($existingSshKeys as $key) { if ($key['fingerprint'] === $md5Fingerprint) { $existingKey = $key; break; } } // Upload SSH key if it doesn't exist if ($existingKey) { $sshKeyId = $existingKey['id']; ray('Using existing SSH key', ['ssh_key_id' => $sshKeyId]); } else { $sshKeyName = $privateKey->name; $uploadedKey = $hetznerService->uploadSshKey($sshKeyName, $publicKey); $sshKeyId = $uploadedKey['id']; ray('Uploaded new SSH key', ['ssh_key_id' => $sshKeyId, 'name' => $sshKeyName]); } // Normalize server name to lowercase for RFC 1123 compliance $normalizedServerName = strtolower(trim($this->server_name)); // Prepare SSH keys array: Coolify key + user-selected Hetzner keys $sshKeys = array_merge( [$sshKeyId], // Coolify key (always included) $this->selectedHetznerSshKeyIds // User-selected Hetzner keys ); // Remove duplicates in case the Coolify key was also selected $sshKeys = array_unique($sshKeys); $sshKeys = array_values($sshKeys); // Re-index array // Prepare server creation parameters $params = [ 'name' => $normalizedServerName, 'server_type' => $this->selected_server_type, 'image' => $this->selected_image, 'location' => $this->selected_location, 'start_after_create' => true, 'ssh_keys' => $sshKeys, 'public_net' => [ 'enable_ipv4' => $this->enable_ipv4, 'enable_ipv6' => $this->enable_ipv6, ], ]; // Add cloud-init script if provided if (! empty($this->cloud_init_script)) { $params['user_data'] = $this->cloud_init_script; } ray('Server creation parameters', $params); // Create server on Hetzner $hetznerServer = $hetznerService->createServer($params); ray('Hetzner server created', $hetznerServer); return $hetznerServer; } public function submit() { $this->validate(); try { $this->authorize('create', Server::class); if (Team::serverLimitReached()) { return $this->dispatch('error', 'You have reached the server limit for your subscription.'); } // Save cloud-init script if requested if ($this->save_cloud_init_script && ! empty($this->cloud_init_script) && ! empty($this->cloud_init_script_name)) { $this->authorize('create', CloudInitScript::class); CloudInitScript::create([ 'team_id' => currentTeam()->id, 'name' => $this->cloud_init_script_name, 'script' => $this->cloud_init_script, ]); } $hetznerToken = $this->getHetznerToken(); // Create server on Hetzner $hetznerServer = $this->createHetznerServer($hetznerToken); // Determine IP address to use (prefer IPv4, fallback to IPv6) $ipAddress = null; if ($this->enable_ipv4 && isset($hetznerServer['public_net']['ipv4']['ip'])) { $ipAddress = $hetznerServer['public_net']['ipv4']['ip']; } elseif ($this->enable_ipv6 && isset($hetznerServer['public_net']['ipv6']['ip'])) { $ipAddress = $hetznerServer['public_net']['ipv6']['ip']; } if (! $ipAddress) { throw new \Exception('No public IP address available. Enable at least one of IPv4 or IPv6.'); } // Create server in Coolify database $server = Server::create([ 'name' => $this->server_name, 'ip' => $ipAddress, 'user' => 'root', 'port' => 22, 'team_id' => currentTeam()->id, 'private_key_id' => $this->private_key_id, 'cloud_provider_token_id' => $this->selected_token_id, 'hetzner_server_id' => $hetznerServer['id'], ]); $server->proxy->set('status', 'exited'); $server->proxy->set('type', ProxyTypes::TRAEFIK->value); $server->save(); if ($this->from_onboarding) { // Complete the boarding when server is successfully created via Hetzner currentTeam()->update([ 'show_boarding' => false, ]); refreshSession(); return redirectRoute($this, 'server.show', [$server->uuid]); } return redirectRoute($this, 'server.show', [$server->uuid]); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.new.by-hetzner'); } } ================================================ FILE: app/Livewire/Server/New/ByIp.php ================================================ name = generate_random_name(); $this->private_key_id = $this->private_keys->first()?->id; } protected function rules(): array { return [ 'private_key_id' => 'nullable|integer', 'new_private_key_name' => 'nullable|string', 'new_private_key_description' => 'nullable|string', 'new_private_key_value' => 'nullable|string', 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'ip' => ['required', 'string', new ValidServerIp], 'user' => ['required', 'string', 'regex:/^[a-zA-Z0-9_-]+$/'], 'port' => 'required|integer|between:1,65535', 'is_build_server' => 'required|boolean', ]; } protected function messages(): array { return array_merge(ValidationPatterns::combinedMessages(), [ 'private_key_id.integer' => 'The Private Key field must be an integer.', 'private_key_id.nullable' => 'The Private Key field is optional.', 'new_private_key_name.string' => 'The Private Key Name must be a string.', 'new_private_key_description.string' => 'The Private Key Description must be a string.', 'new_private_key_value.string' => 'The Private Key Value must be a string.', 'ip.required' => 'The IP Address/Domain is required.', 'ip.string' => 'The IP Address/Domain must be a string.', 'user.required' => 'The User field is required.', 'user.string' => 'The User field must be a string.', 'port.required' => 'The Port field is required.', 'port.integer' => 'The Port field must be an integer.', 'port.between' => 'The Port field must be between 1 and 65535.', 'is_build_server.required' => 'The Build Server field is required.', 'is_build_server.boolean' => 'The Build Server field must be true or false.', ]); } public function setPrivateKey(string $private_key_id) { $this->private_key_id = $private_key_id; } public function instantSave() { // $this->dispatch('success', 'Application settings updated!'); } public function submit() { $this->validate(); try { $this->authorize('create', Server::class); $foundServer = Server::whereIp($this->ip)->first(); if ($foundServer) { if ($foundServer->team_id === currentTeam()->id) { return $this->dispatch('error', 'A server with this IP/Domain already exists in your team.'); } return $this->dispatch('error', 'A server with this IP/Domain is already in use by another team.'); } if (is_null($this->private_key_id)) { return $this->dispatch('error', 'You must select a private key'); } if (Team::serverLimitReached()) { return $this->dispatch('error', 'You have reached the server limit for your subscription.'); } $payload = [ 'name' => $this->name, 'description' => $this->description, 'ip' => $this->ip, 'user' => $this->user, 'port' => $this->port, 'team_id' => currentTeam()->id, 'private_key_id' => $this->private_key_id, ]; if ($this->is_build_server) { data_forget($payload, 'proxy'); } $server = Server::create($payload); $server->proxy->set('status', 'exited'); $server->proxy->set('type', ProxyTypes::TRAEFIK->value); $server->save(); $server->settings->is_build_server = $this->is_build_server; $server->settings->save(); return redirectRoute($this, 'server.show', [$server->uuid]); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Server/PrivateKey/Show.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->privateKeys = PrivateKey::ownedByCurrentTeam()->get()->where('is_git_related', false); } catch (\Throwable $e) { return handleError($e, $this); } } public function setPrivateKey($privateKeyId) { $ownedPrivateKey = PrivateKey::ownedByCurrentTeam()->find($privateKeyId); if (is_null($ownedPrivateKey)) { $this->dispatch('error', 'You are not allowed to use this private key.'); return; } try { $this->authorize('update', $this->server); DB::transaction(function () use ($ownedPrivateKey) { $this->server->privateKey()->associate($ownedPrivateKey); $this->server->save(); ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(justCheckingNewKey: true); if (! $uptime) { throw new \Exception($error); } }); $this->dispatch('success', 'Private key updated successfully.'); $this->dispatch('refreshServerShow'); } catch (\Exception $e) { $this->server->refresh(); $this->server->validateConnection(); $this->dispatch('error', $e->getMessage()); } } public function checkConnection() { try { ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); if ($uptime) { $this->dispatch('success', 'Server is reachable.'); $this->dispatch('refreshServerShow'); } else { $this->dispatch('error', 'Server is not reachable.

Check this documentation for further help.

Error: '.$error); return; } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.private-key.show'); } } ================================================ FILE: app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php ================================================ authorize('update', $this->server); $proxy_path = $this->server->proxyPath(); $proxy_type = $this->server->proxyType(); // Decode filename: pipes are used to encode dots for Livewire property binding // (e.g., 'my|service.yaml' -> 'my.service.yaml') // This must happen BEFORE validation because validateShellSafePath() correctly // rejects pipe characters as dangerous shell metacharacters $file = str_replace('|', '.', $fileName); // Validate filename to prevent command injection validateShellSafePath($file, 'proxy configuration filename'); if ($proxy_type === 'CADDY' && $file === 'Caddyfile') { $this->dispatch('error', 'Cannot delete Caddyfile.'); return; } $fullPath = "{$proxy_path}/dynamic/{$file}"; $escapedPath = escapeshellarg($fullPath); instant_remote_process(["rm -f {$escapedPath}"], $this->server); if ($proxy_type === 'CADDY') { $this->server->reloadCaddy(); } $this->dispatch('success', 'File deleted.'); $this->dispatch('loadDynamicConfigurations'); $this->dispatch('refresh'); } public function render() { return view('livewire.server.proxy.dynamic-configuration-navbar'); } } ================================================ FILE: app/Livewire/Server/Proxy/DynamicConfigurations.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ProxyStatusChangedUI" => 'loadDynamicConfigurations', 'loadDynamicConfigurations', ]; } protected $rules = [ 'contents.*' => 'nullable|string', ]; public function initLoadDynamicConfigurations() { $this->loadDynamicConfigurations(); } public function loadDynamicConfigurations() { $proxy_path = $this->server->proxyPath(); $files = instant_remote_process(["mkdir -p $proxy_path/dynamic && ls -1 {$proxy_path}/dynamic"], $this->server); $files = collect(explode("\n", $files))->filter(fn ($file) => ! empty($file)); $files = $files->map(fn ($file) => trim($file)); $files = $files->sort(); $contents = collect([]); foreach ($files as $file) { $without_extension = str_replace('.', '|', $file); $content = instant_remote_process(["cat {$proxy_path}/dynamic/{$file}"], $this->server); $contents[$without_extension] = $content ?? ''; } $this->contents = $contents; $this->dispatch('$refresh'); $this->dispatch('success', 'Dynamic configurations loaded.'); } public function mount() { $this->parameters = get_route_parameters(); try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { return redirect()->route('server.index'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.proxy.dynamic-configurations'); } } ================================================ FILE: app/Livewire/Server/Proxy/Logs.php ================================================ parameters = get_route_parameters(); try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { return redirect()->route('server.index'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.proxy.logs'); } } ================================================ FILE: app/Livewire/Server/Proxy/NewDynamicConfiguration.php ================================================ server = Server::ownedByCurrentTeam()->whereId($this->server_id)->first(); $this->parameters = get_route_parameters(); if ($this->fileName !== '') { $this->fileName = str_replace('|', '.', $this->fileName); } } public function addDynamicConfiguration() { try { $this->authorize('update', $this->server); $this->validate([ 'fileName' => ['required', new ValidProxyConfigFilename], 'value' => 'required', ]); // Additional security validation to prevent command injection validateShellSafePath($this->fileName, 'proxy configuration filename'); if (data_get($this->parameters, 'server_uuid')) { $this->server = Server::ownedByCurrentTeam()->whereUuid(data_get($this->parameters, 'server_uuid'))->first(); } if (is_null($this->server)) { return redirect()->route('server.index'); } $proxy_type = $this->server->proxyType(); if ($proxy_type === ProxyTypes::TRAEFIK->value) { if (! str($this->fileName)->endsWith('.yaml') && ! str($this->fileName)->endsWith('.yml')) { $this->fileName = "{$this->fileName}.yaml"; } if ($this->fileName === 'coolify.yaml') { $this->dispatch('error', 'File name is reserved.'); return; } } elseif ($proxy_type === 'CADDY') { if (! str($this->fileName)->endsWith('.caddy')) { $this->fileName = "{$this->fileName}.caddy"; } } $proxy_path = $this->server->proxyPath(); $file = "{$proxy_path}/dynamic/{$this->fileName}"; $escapedFile = escapeshellarg($file); if ($this->newFile) { $exists = instant_remote_process(["test -f {$escapedFile} && echo 1 || echo 0"], $this->server); if ($exists == 1) { $this->dispatch('error', 'File already exists'); return; } } if ($proxy_type === ProxyTypes::TRAEFIK->value) { $yaml = Yaml::parse($this->value); $yaml = Yaml::dump($yaml, 10, 2); $this->value = $yaml; } $base64_value = base64_encode($this->value); instant_remote_process([ "echo '{$base64_value}' | base64 -d | tee {$escapedFile} > /dev/null", ], $this->server); if ($proxy_type === 'CADDY') { $this->server->reloadCaddy(); } $this->dispatch('loadDynamicConfigurations'); $this->dispatch('dynamic-configuration-added'); $this->dispatch('success', 'Dynamic configuration saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.proxy.new-dynamic-configuration'); } } ================================================ FILE: app/Livewire/Server/Proxy/Show.php ================================================ parameters = get_route_parameters(); try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail(); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.proxy.show'); } } ================================================ FILE: app/Livewire/Server/Proxy.php ================================================ user()->currentTeam()->id; return [ 'saveConfiguration' => 'submit', "echo-private:team.{$teamId},ProxyStatusChangedUI" => '$refresh', ]; } protected $rules = [ 'generateExactLabels' => 'required|boolean', ]; public function mount() { $this->selectedProxy = $this->server->proxyType(); $this->redirectEnabled = data_get($this->server, 'proxy.redirect_enabled', true); $this->redirectUrl = data_get($this->server, 'proxy.redirect_url'); $this->syncData(false); $this->loadProxyConfiguration(); } private function syncData(bool $toModel = false): void { if ($toModel) { $this->server->settings->generate_exact_labels = $this->generateExactLabels; } else { $this->generateExactLabels = $this->server->settings->generate_exact_labels ?? false; } } /** * Get Traefik versions from cached data with in-memory optimization. * Returns array like: ['v3.5' => '3.5.6', 'v3.6' => '3.6.2'] * * This method adds an in-memory cache layer on top of the global * get_traefik_versions() helper to avoid multiple calls during * a single component lifecycle/render. */ protected function getTraefikVersions(): ?array { // In-memory cache for this component instance (per-request) if ($this->cachedVersionsFile !== null) { return data_get($this->cachedVersionsFile, 'traefik'); } // Load from global cached helper (Redis + filesystem) $versionsData = get_versions_data(); if (! $versionsData) { return null; } $this->cachedVersionsFile = $versionsData; $traefikVersions = data_get($versionsData, 'traefik'); return is_array($traefikVersions) ? $traefikVersions : null; } public function getConfigurationFilePathProperty(): string { return rtrim($this->server->proxyPath(), '/').'/docker-compose.yml'; } public function changeProxy() { $this->authorize('update', $this->server); $this->server->proxy = null; $this->server->save(); $this->dispatch('reloadWindow'); } public function selectProxy($proxy_type) { try { $this->authorize('update', $this->server); $this->server->changeProxy($proxy_type, async: false); $this->selectedProxy = $this->server->proxy->type; $this->dispatch('reloadWindow'); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSave() { try { $this->authorize('update', $this->server); $this->validate(); $this->syncData(true); $this->server->settings->save(); $this->dispatch('success', 'Settings saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSaveRedirect() { try { $this->authorize('update', $this->server); $this->server->proxy->redirect_enabled = $this->redirectEnabled; $this->server->save(); $this->server->setupDefaultRedirect(); $this->dispatch('success', 'Proxy configuration saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->server); SaveProxyConfiguration::run($this->server, $this->proxySettings); $this->server->proxy->redirect_url = $this->redirectUrl; $this->server->save(); $this->server->setupDefaultRedirect(); $this->dispatch('success', 'Proxy configuration saved.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function resetProxyConfiguration() { try { $this->authorize('update', $this->server); // Explicitly regenerate default configuration $this->proxySettings = GetProxyConfiguration::run($this->server, forceRegenerate: true); SaveProxyConfiguration::run($this->server, $this->proxySettings); $this->server->save(); $this->dispatch('success', 'Proxy configuration reset to default.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function loadProxyConfiguration() { try { $this->proxySettings = GetProxyConfiguration::run($this->server); } catch (\Throwable $e) { return handleError($e, $this); } } /** * Get the latest Traefik version for this server's current branch. * * This compares the server's detected version against available versions * in versions.json to determine the latest patch for the current branch, * or the newest available version if no current version is detected. */ public function getLatestTraefikVersionProperty(): ?string { try { $traefikVersions = $this->getTraefikVersions(); if (! $traefikVersions) { return null; } // Get this server's current version $currentVersion = $this->server->detected_traefik_version; // If we have a current version, try to find matching branch if ($currentVersion && $currentVersion !== 'latest') { $current = ltrim($currentVersion, 'v'); if (preg_match('/^(\d+\.\d+)/', $current, $matches)) { $branch = "v{$matches[1]}"; if (isset($traefikVersions[$branch])) { $version = $traefikVersions[$branch]; return str_starts_with($version, 'v') ? $version : "v{$version}"; } } } // Return the newest available version $newestVersion = collect($traefikVersions) ->map(fn ($v) => ltrim($v, 'v')) ->sortBy(fn ($v) => $v, SORT_NATURAL) ->last(); return $newestVersion ? "v{$newestVersion}" : null; } catch (\Throwable $e) { return null; } } public function getIsTraefikOutdatedProperty(): bool { if ($this->server->proxyType() !== ProxyTypes::TRAEFIK->value) { return false; } $currentVersion = $this->server->detected_traefik_version; if (! $currentVersion || $currentVersion === 'latest') { return false; } $latestVersion = $this->latestTraefikVersion; if (! $latestVersion) { return false; } // Compare versions (strip 'v' prefix) $current = ltrim($currentVersion, 'v'); $latest = ltrim($latestVersion, 'v'); return version_compare($current, $latest, '<'); } /** * Check if a newer Traefik branch (minor version) is available for this server. * Returns the branch identifier (e.g., "v3.6") if a newer branch exists. */ public function getNewerTraefikBranchAvailableProperty(): ?string { try { if ($this->server->proxyType() !== ProxyTypes::TRAEFIK->value) { return null; } // Get this server's current version $currentVersion = $this->server->detected_traefik_version; if (! $currentVersion || $currentVersion === 'latest') { return null; } // Check if we have outdated info stored for this server (faster than computing) $outdatedInfo = $this->server->traefik_outdated_info; if ($outdatedInfo && isset($outdatedInfo['type']) && $outdatedInfo['type'] === 'minor_upgrade') { // Use the upgrade_target field if available (e.g., "v3.6") if (isset($outdatedInfo['upgrade_target'])) { return str_starts_with($outdatedInfo['upgrade_target'], 'v') ? $outdatedInfo['upgrade_target'] : "v{$outdatedInfo['upgrade_target']}"; } } // Fallback: compute from cached versions data $traefikVersions = $this->getTraefikVersions(); if (! $traefikVersions) { return null; } // Extract current branch (e.g., "3.5" from "3.5.6") $current = ltrim($currentVersion, 'v'); if (! preg_match('/^(\d+\.\d+)/', $current, $matches)) { return null; } $currentBranch = $matches[1]; // Find the newest branch that's greater than current $newestBranch = null; foreach ($traefikVersions as $branch => $version) { $branchNum = ltrim($branch, 'v'); if (version_compare($branchNum, $currentBranch, '>')) { if (! $newestBranch || version_compare($branchNum, $newestBranch, '>')) { $newestBranch = $branchNum; } } } return $newestBranch ? "v{$newestBranch}" : null; } catch (\Throwable $e) { return null; } } } ================================================ FILE: app/Livewire/Server/Resources.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ApplicationStatusChanged" => 'refreshStatus', ]; } public function startUnmanaged($id) { $this->server->startUnmanaged($id); $this->dispatch('success', 'Container started.'); $this->loadUnmanagedContainers(); } public function restartUnmanaged($id) { $this->server->restartUnmanaged($id); $this->dispatch('success', 'Container restarted.'); $this->loadUnmanagedContainers(); } public function stopUnmanaged($id) { $this->server->stopUnmanaged($id); $this->dispatch('success', 'Container stopped.'); $this->loadUnmanagedContainers(); } public function refreshStatus() { $this->server->refresh(); if ($this->activeTab === 'managed') { $this->loadManagedContainers(); } else { $this->loadUnmanagedContainers(); } $this->dispatch('success', 'Resource statuses refreshed.'); } public function loadManagedContainers() { try { $this->activeTab = 'managed'; $this->server->refresh(); } catch (\Throwable $e) { return handleError($e, $this); } } public function loadUnmanagedContainers() { $this->activeTab = 'unmanaged'; try { $this->unmanagedContainers = $this->server->loadUnmanagedContainers()->toArray(); } catch (\Throwable $e) { return handleError($e, $this); } } public function mount() { $this->parameters = get_route_parameters(); try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { return redirect()->route('server.index'); } } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.resources'); } } ================================================ FILE: app/Livewire/Server/Security/Patches.php ================================================ user()->currentTeam()->id; return [ "echo-private:team.{$teamId},ServerPackageUpdated" => 'checkForUpdatesDispatch', ]; } public function mount() { $this->parameters = get_route_parameters(); $this->server = Server::ownedByCurrentTeam()->whereUuid($this->parameters['server_uuid'])->firstOrFail(); $this->authorize('viewSecurity', $this->server); } public function checkForUpdatesDispatch() { $this->totalUpdates = null; $this->updates = null; $this->error = null; $this->osId = null; $this->packageManager = null; $this->dispatch('checkForUpdatesDispatch'); } public function checkForUpdates() { $job = CheckUpdates::run($this->server); if (isset($job['error'])) { $this->error = data_get($job, 'error', 'Something went wrong.'); } else { $this->totalUpdates = data_get($job, 'total_updates', 0); $this->updates = data_get($job, 'updates', []); $this->osId = data_get($job, 'osId', null); $this->packageManager = data_get($job, 'package_manager', null); } } public function updateAllPackages() { $this->authorize('update', $this->server); if (! $this->packageManager || ! $this->osId) { $this->dispatch('error', message: 'Run "Check for updates" first.'); return; } try { $activity = UpdatePackage::run( server: $this->server, packageManager: $this->packageManager, osId: $this->osId, all: true ); $this->dispatch('activityMonitor', $activity->id, ServerPackageUpdated::class); } catch (\Exception $e) { $this->dispatch('error', message: $e->getMessage()); } } public function updatePackage($package) { try { $this->authorize('update', $this->server); $activity = UpdatePackage::run(server: $this->server, packageManager: $this->packageManager, osId: $this->osId, package: $package); $this->dispatch('activityMonitor', $activity->id, ServerPackageUpdated::class); } catch (\Exception $e) { $this->dispatch('error', message: $e->getMessage()); } } public function sendTestEmail() { if (! isDev()) { $this->dispatch('error', message: 'Test email functionality is only available in development mode.'); return; } try { // Get current patch data or create test data if none exists $testPatchData = $this->createTestPatchData(); // Send test notification $this->server->team->notify(new ServerPatchCheck($this->server, $testPatchData)); $this->dispatch('success', 'Test email sent successfully! Check your email inbox.'); } catch (\Exception $e) { $this->dispatch('error', message: 'Failed to send test email: '.$e->getMessage()); } } private function createTestPatchData(): array { // If we have real patch data, use it if (isset($this->updates) && is_array($this->updates) && count($this->updates) > 0) { return [ 'total_updates' => $this->totalUpdates, 'updates' => $this->updates, 'osId' => $this->osId, 'package_manager' => $this->packageManager, ]; } // Otherwise create realistic test data return [ 'total_updates' => 8, 'updates' => [ [ 'package' => 'docker-ce', 'current_version' => '24.0.7-1', 'new_version' => '25.0.1-1', ], [ 'package' => 'nginx', 'current_version' => '1.20.2-1', 'new_version' => '1.22.1-1', ], [ 'package' => 'kernel-generic', 'current_version' => '5.15.0-89', 'new_version' => '5.15.0-91', ], [ 'package' => 'openssh-server', 'current_version' => '8.9p1-3', 'new_version' => '9.0p1-1', ], [ 'package' => 'curl', 'current_version' => '7.81.0-1', 'new_version' => '7.85.0-1', ], [ 'package' => 'git', 'current_version' => '2.34.1-1', 'new_version' => '2.39.1-1', ], [ 'package' => 'python3', 'current_version' => '3.10.6-1', 'new_version' => '3.11.0-1', ], [ 'package' => 'htop', 'current_version' => '3.2.1-1', 'new_version' => '3.2.2-1', ], ], 'osId' => $this->osId ?? 'ubuntu', 'package_manager' => $this->packageManager ?? 'apt', ]; } public function render() { return view('livewire.server.security.patches'); } } ================================================ FILE: app/Livewire/Server/Security/TerminalAccess.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->authorize('update', $this->server); $this->parameters = get_route_parameters(); $this->syncData(); } catch (\Throwable) { return redirect()->route('server.index'); } } public function toggleTerminal($password, $selectedActions = []) { try { $this->authorize('update', $this->server); // Check if user is admin or owner if (! auth()->user()->isAdmin()) { throw new \Exception('Only team administrators and owners can modify terminal access.'); } // Verify password if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } // Toggle the terminal setting $this->server->settings->is_terminal_enabled = ! $this->server->settings->is_terminal_enabled; $this->server->settings->save(); // Update the local property $this->isTerminalEnabled = $this->server->settings->is_terminal_enabled; $status = $this->isTerminalEnabled ? 'enabled' : 'disabled'; $this->dispatch('success', "Terminal access has been {$status}."); return true; } catch (\Throwable $e) { return handleError($e, $this); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->authorize('update', $this->server); $this->validate(); // No other fields to sync for terminal access } else { $this->isTerminalEnabled = $this->server->settings->is_terminal_enabled; } } public function render() { return view('livewire.server.security.terminal-access'); } } ================================================ FILE: app/Livewire/Server/Sentinel.php ================================================ server->team_id ?? auth()->user()->currentTeam()->id; return [ "echo-private:team.{$teamId},SentinelRestarted" => 'handleSentinelRestarted', ]; } public function mount(string $server_uuid) { try { $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->parameters = get_route_parameters(); $this->syncData(); } catch (\Throwable) { return redirect()->route('server.index'); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->authorize('update', $this->server); $this->validate(); $this->server->settings->is_metrics_enabled = $this->isMetricsEnabled; $this->server->settings->sentinel_token = $this->sentinelToken; $this->server->settings->sentinel_metrics_refresh_rate_seconds = $this->sentinelMetricsRefreshRateSeconds; $this->server->settings->sentinel_metrics_history_days = $this->sentinelMetricsHistoryDays; $this->server->settings->sentinel_push_interval_seconds = $this->sentinelPushIntervalSeconds; $this->server->settings->sentinel_custom_url = $this->sentinelCustomUrl; $this->server->settings->is_sentinel_enabled = $this->isSentinelEnabled; $this->server->settings->is_sentinel_debug_enabled = $this->isSentinelDebugEnabled; $this->server->settings->save(); } else { $this->isMetricsEnabled = $this->server->settings->is_metrics_enabled; $this->sentinelToken = $this->server->settings->sentinel_token; $this->sentinelMetricsRefreshRateSeconds = $this->server->settings->sentinel_metrics_refresh_rate_seconds; $this->sentinelMetricsHistoryDays = $this->server->settings->sentinel_metrics_history_days; $this->sentinelPushIntervalSeconds = $this->server->settings->sentinel_push_interval_seconds; $this->sentinelCustomUrl = $this->server->settings->sentinel_custom_url; $this->isSentinelEnabled = $this->server->settings->is_sentinel_enabled; $this->isSentinelDebugEnabled = $this->server->settings->is_sentinel_debug_enabled; $this->sentinelUpdatedAt = $this->server->sentinel_updated_at; } } public function handleSentinelRestarted($event) { if ($event['serverUuid'] === $this->server->uuid) { $this->server->refresh(); $this->syncData(); $this->dispatch('success', 'Sentinel has been restarted successfully.'); } } public function restartSentinel() { try { $this->authorize('manageSentinel', $this->server); $customImage = isDev() ? $this->sentinelCustomDockerImage : null; $this->server->restartSentinel($customImage); $this->dispatch('info', 'Restarting Sentinel.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function updatedIsSentinelEnabled($value) { try { $this->authorize('manageSentinel', $this->server); if ($value === true) { if ($this->server->isBuildServer()) { $this->isSentinelEnabled = false; $this->dispatch('error', 'Sentinel cannot be enabled on build servers.'); return; } $customImage = isDev() ? $this->sentinelCustomDockerImage : null; StartSentinel::run($this->server, true, null, $customImage); } else { $this->isMetricsEnabled = false; $this->isSentinelDebugEnabled = false; StopSentinel::dispatch($this->server); } $this->submit(); } catch (\Throwable $e) { return handleError($e, $this); } } public function regenerateSentinelToken() { try { $this->authorize('manageSentinel', $this->server); $this->server->settings->generateSentinelToken(); $this->dispatch('success', 'Token regenerated. Restarting Sentinel.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->syncData(true); $this->dispatch('success', 'Sentinel settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSave() { try { $this->syncData(true); $this->restartSentinel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.sentinel'); } } ================================================ FILE: app/Livewire/Server/Show.php ================================================ server->team_id ?? auth()->user()->currentTeam()->id; return [ 'refreshServerShow' => 'refresh', 'refreshServer' => '$refresh', "echo-private:team.{$teamId},SentinelRestarted" => 'handleSentinelRestarted', "echo-private:team.{$teamId},ServerValidated" => 'handleServerValidated', ]; } protected function rules(): array { return [ 'name' => ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'ip' => ['required', new ValidServerIp], 'user' => ['required', 'regex:/^[a-zA-Z0-9_-]+$/'], 'port' => 'required|integer|between:1,65535', 'validationLogs' => 'nullable', 'wildcardDomain' => 'nullable|url', 'isReachable' => 'required', 'isUsable' => 'required', 'isSwarmManager' => 'required', 'isSwarmWorker' => 'required', 'isBuildServer' => 'required', 'isMetricsEnabled' => 'required', 'sentinelToken' => 'required', 'sentinelUpdatedAt' => 'nullable', 'sentinelMetricsRefreshRateSeconds' => 'required|integer|min:1', 'sentinelMetricsHistoryDays' => 'required|integer|min:1', 'sentinelPushIntervalSeconds' => 'required|integer|min:10', 'sentinelCustomUrl' => 'nullable|url', 'isSentinelEnabled' => 'required', 'isSentinelDebugEnabled' => 'required', 'serverTimezone' => 'required', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'ip.required' => 'The IP Address field is required.', 'user.required' => 'The User field is required.', 'port.required' => 'The Port field is required.', 'wildcardDomain.url' => 'The Wildcard Domain must be a valid URL.', 'sentinelToken.required' => 'The Sentinel Token field is required.', 'sentinelMetricsRefreshRateSeconds.required' => 'The Metrics Refresh Rate field is required.', 'sentinelMetricsRefreshRateSeconds.integer' => 'The Metrics Refresh Rate must be an integer.', 'sentinelMetricsRefreshRateSeconds.min' => 'The Metrics Refresh Rate must be at least 1 second.', 'sentinelMetricsHistoryDays.required' => 'The Metrics History Days field is required.', 'sentinelMetricsHistoryDays.integer' => 'The Metrics History Days must be an integer.', 'sentinelMetricsHistoryDays.min' => 'The Metrics History Days must be at least 1 day.', 'sentinelPushIntervalSeconds.required' => 'The Push Interval field is required.', 'sentinelPushIntervalSeconds.integer' => 'The Push Interval must be an integer.', 'sentinelPushIntervalSeconds.min' => 'The Push Interval must be at least 10 seconds.', 'sentinelCustomUrl.url' => 'The Custom Sentinel URL must be a valid URL.', 'serverTimezone.required' => 'The Server Timezone field is required.', ] ); } public function mount(string $server_uuid) { try { $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->syncData(); if (! $this->server->isEmpty()) { $this->isBuildServerLocked = true; } // Load saved Hetzner status and validation state $this->hetznerServerStatus = $this->server->hetzner_server_status; $this->isValidating = $this->server->is_validating ?? false; // Load Hetzner tokens for linking $this->loadHetznerTokens(); } catch (\Throwable $e) { return handleError($e, $this); } } #[Computed] public function timezones(): array { return collect(timezone_identifiers_list()) ->sort() ->values() ->toArray(); } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->authorize('update', $this->server); $foundServer = Server::where('ip', $this->ip) ->where('id', '!=', $this->server->id) ->first(); if ($foundServer) { $this->ip = $this->server->ip; if ($foundServer->team_id === currentTeam()->id) { throw new \Exception('A server with this IP/Domain already exists in your team.'); } throw new \Exception('A server with this IP/Domain is already in use by another team.'); } $this->server->name = $this->name; $this->server->description = $this->description; $this->server->ip = $this->ip; $this->server->user = $this->user; $this->server->port = $this->port; $this->server->validation_logs = $this->validationLogs; $this->server->save(); $this->server->settings->is_swarm_manager = $this->isSwarmManager; $this->server->settings->wildcard_domain = $this->wildcardDomain; $this->server->settings->is_swarm_worker = $this->isSwarmWorker; $this->server->settings->is_build_server = $this->isBuildServer; $this->server->settings->is_metrics_enabled = $this->isMetricsEnabled; $this->server->settings->sentinel_token = $this->sentinelToken; $this->server->settings->sentinel_metrics_refresh_rate_seconds = $this->sentinelMetricsRefreshRateSeconds; $this->server->settings->sentinel_metrics_history_days = $this->sentinelMetricsHistoryDays; $this->server->settings->sentinel_push_interval_seconds = $this->sentinelPushIntervalSeconds; $this->server->settings->sentinel_custom_url = $this->sentinelCustomUrl; $this->server->settings->is_sentinel_enabled = $this->isSentinelEnabled; $this->server->settings->is_sentinel_debug_enabled = $this->isSentinelDebugEnabled; if (! validate_timezone($this->serverTimezone)) { $this->serverTimezone = config('app.timezone'); throw new \Exception('Invalid timezone.'); } else { $this->server->settings->server_timezone = $this->serverTimezone; } $this->server->settings->save(); } else { $this->name = $this->server->name; $this->description = $this->server->description; $this->ip = $this->server->ip; $this->user = $this->server->user; $this->port = $this->server->port; $this->wildcardDomain = $this->server->settings->wildcard_domain; $this->isReachable = $this->server->settings->is_reachable; $this->isUsable = $this->server->settings->is_usable; $this->isSwarmManager = $this->server->settings->is_swarm_manager; $this->isSwarmWorker = $this->server->settings->is_swarm_worker; $this->isBuildServer = $this->server->settings->is_build_server; $this->isMetricsEnabled = $this->server->settings->is_metrics_enabled; $this->sentinelToken = $this->server->settings->sentinel_token; $this->sentinelMetricsRefreshRateSeconds = $this->server->settings->sentinel_metrics_refresh_rate_seconds; $this->sentinelMetricsHistoryDays = $this->server->settings->sentinel_metrics_history_days; $this->sentinelPushIntervalSeconds = $this->server->settings->sentinel_push_interval_seconds; $this->sentinelCustomUrl = $this->server->settings->sentinel_custom_url; $this->isSentinelEnabled = $this->server->settings->is_sentinel_enabled; $this->isSentinelDebugEnabled = $this->server->settings->is_sentinel_debug_enabled; $this->sentinelUpdatedAt = $this->server->sentinel_updated_at; $this->serverTimezone = $this->server->settings->server_timezone; $this->isValidating = $this->server->is_validating ?? false; } } public function refresh() { $this->syncData(); } public function handleSentinelRestarted($event) { // Only refresh if the event is for this server if (isset($event['serverUuid']) && $event['serverUuid'] === $this->server->uuid) { $this->server->refresh(); $this->syncData(); $this->dispatch('success', 'Sentinel has been restarted successfully.'); } } public function validateServer($install = true) { try { $this->authorize('update', $this->server); $this->validationLogs = $this->server->validation_logs = null; $this->server->save(); $this->dispatch('init', $install); } catch (\Throwable $e) { return handleError($e, $this); } } public function checkLocalhostConnection() { $this->syncData(true); ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); if ($uptime) { $this->dispatch('success', 'Server is reachable.'); $this->server->settings->is_reachable = $this->isReachable = true; $this->server->settings->is_usable = $this->isUsable = true; $this->server->settings->save(); ServerReachabilityChanged::dispatch($this->server); } else { $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.

Check this documentation for further help.

Error: '.$error); return; } } public function restartSentinel() { try { $this->authorize('manageSentinel', $this->server); $customImage = isDev() ? $this->sentinelCustomDockerImage : null; $this->server->restartSentinel($customImage); $this->dispatch('info', 'Restarting Sentinel.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function updatedIsSentinelDebugEnabled($value) { try { $this->submit(); $this->restartSentinel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function updatedIsMetricsEnabled($value) { try { $this->submit(); $this->restartSentinel(); } catch (\Throwable $e) { return handleError($e, $this); } } public function updatedIsBuildServer($value) { try { $this->authorize('update', $this->server); if ($value === true && $this->isSentinelEnabled) { $this->isSentinelEnabled = false; $this->isMetricsEnabled = false; $this->isSentinelDebugEnabled = false; StopSentinel::dispatch($this->server); $this->dispatch('info', 'Sentinel has been disabled as build servers cannot run Sentinel.'); } $this->submit(); // Dispatch event to refresh the navbar $this->dispatch('refreshServerShow'); } catch (\Throwable $e) { return handleError($e, $this); } } public function updatedIsSentinelEnabled($value) { try { $this->authorize('manageSentinel', $this->server); if ($value === true) { if ($this->isBuildServer) { $this->isSentinelEnabled = false; $this->dispatch('error', 'Sentinel cannot be enabled on build servers.'); return; } $customImage = isDev() ? $this->sentinelCustomDockerImage : null; StartSentinel::run($this->server, true, null, $customImage); } else { $this->isMetricsEnabled = false; $this->isSentinelDebugEnabled = false; StopSentinel::dispatch($this->server); } $this->submit(); } catch (\Throwable $e) { return handleError($e, $this); } } public function regenerateSentinelToken() { try { $this->authorize('manageSentinel', $this->server); $this->server->settings->generateSentinelToken(); $this->dispatch('success', 'Token regenerated. Restarting Sentinel.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSave() { try { $this->syncData(true); } catch (\Throwable $e) { return handleError($e, $this); } } public function checkHetznerServerStatus(bool $manual = false) { try { if (! $this->server->hetzner_server_id || ! $this->server->cloudProviderToken) { $this->dispatch('error', 'This server is not associated with a Hetzner Cloud server or token.'); return; } $hetznerService = new \App\Services\HetznerService($this->server->cloudProviderToken->token); $serverData = $hetznerService->getServer($this->server->hetzner_server_id); $this->hetznerServerStatus = $serverData['status'] ?? null; // Save status to database without triggering model events if ($this->server->hetzner_server_status !== $this->hetznerServerStatus) { $this->server->hetzner_server_status = $this->hetznerServerStatus; $this->server->update(['hetzner_server_status' => $this->hetznerServerStatus]); } if ($manual) { $this->dispatch('success', 'Server status refreshed: '.ucfirst($this->hetznerServerStatus ?? 'unknown')); } // If Hetzner server is off but Coolify thinks it's still reachable, update Coolify's state if ($this->hetznerServerStatus === 'off' && $this->server->settings->is_reachable) { ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); if ($uptime) { $this->dispatch('success', 'Server is reachable.'); $this->server->settings->is_reachable = $this->isReachable = true; $this->server->settings->is_usable = $this->isUsable = true; $this->server->settings->save(); ServerReachabilityChanged::dispatch($this->server); } else { $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.

Check this documentation for further help.

Error: '.$error); return; } } } catch (\Throwable $e) { return handleError($e, $this); } } public function handleServerValidated($event = null) { // Check if event is for this server if ($event && isset($event['serverUuid']) && $event['serverUuid'] !== $this->server->uuid) { return; } // Refresh server data $this->server->refresh(); $this->syncData(); // Update validation state $this->isValidating = $this->server->is_validating ?? false; // Reload Hetzner tokens in case the linking section should now be shown $this->loadHetznerTokens(); $this->dispatch('refreshServerShow'); $this->dispatch('refreshServer'); } public function startHetznerServer() { try { if (! $this->server->hetzner_server_id || ! $this->server->cloudProviderToken) { $this->dispatch('error', 'This server is not associated with a Hetzner Cloud server or token.'); return; } $hetznerService = new \App\Services\HetznerService($this->server->cloudProviderToken->token); $hetznerService->powerOnServer($this->server->hetzner_server_id); $this->hetznerServerStatus = 'starting'; $this->server->update(['hetzner_server_status' => 'starting']); $this->hetznerServerManuallyStarted = true; // Set flag to trigger auto-validation when running $this->dispatch('success', 'Hetzner server is starting...'); } catch (\Throwable $e) { return handleError($e, $this); } } public function refreshServerMetadata(): void { try { $this->authorize('update', $this->server); $result = $this->server->gatherServerMetadata(); if ($result) { $this->server->refresh(); $this->dispatch('success', 'Server details refreshed.'); } else { $this->dispatch('error', 'Could not fetch server details. Is the server reachable?'); } } catch (\Throwable $e) { handleError($e, $this); } } public function submit() { try { $this->syncData(true); $this->dispatch('success', 'Server settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function loadHetznerTokens(): void { $this->availableHetznerTokens = CloudProviderToken::ownedByCurrentTeam() ->where('provider', 'hetzner') ->get(); } public function searchHetznerServer(): void { $this->hetznerSearchError = null; $this->hetznerNoMatchFound = false; $this->matchedHetznerServer = null; if (! $this->selectedHetznerTokenId) { $this->hetznerSearchError = 'Please select a Hetzner token.'; return; } try { $this->authorize('update', $this->server); $token = $this->availableHetznerTokens->firstWhere('id', $this->selectedHetznerTokenId); if (! $token) { $this->hetznerSearchError = 'Invalid token selected.'; return; } $hetznerService = new HetznerService($token->token); $matched = $hetznerService->findServerByIp($this->server->ip); if ($matched) { $this->matchedHetznerServer = $matched; } else { $this->hetznerNoMatchFound = true; } } catch (\Throwable $e) { $this->hetznerSearchError = 'Failed to search Hetzner servers: '.$e->getMessage(); } } public function searchHetznerServerById(): void { $this->hetznerSearchError = null; $this->hetznerNoMatchFound = false; $this->matchedHetznerServer = null; if (! $this->selectedHetznerTokenId) { $this->hetznerSearchError = 'Please select a Hetzner token first.'; return; } if (! $this->manualHetznerServerId) { $this->hetznerSearchError = 'Please enter a Hetzner Server ID.'; return; } try { $this->authorize('update', $this->server); $token = $this->availableHetznerTokens->firstWhere('id', $this->selectedHetznerTokenId); if (! $token) { $this->hetznerSearchError = 'Invalid token selected.'; return; } $hetznerService = new HetznerService($token->token); $serverData = $hetznerService->getServer((int) $this->manualHetznerServerId); if (! empty($serverData)) { $this->matchedHetznerServer = $serverData; } else { $this->hetznerNoMatchFound = true; } } catch (\Throwable $e) { $this->hetznerSearchError = 'Failed to fetch Hetzner server: '.$e->getMessage(); } } public function linkToHetzner() { if (! $this->matchedHetznerServer) { $this->dispatch('error', 'No Hetzner server selected.'); return; } try { $this->authorize('update', $this->server); $token = $this->availableHetznerTokens->firstWhere('id', $this->selectedHetznerTokenId); if (! $token) { $this->dispatch('error', 'Invalid token selected.'); return; } // Verify the server exists and is accessible with the token $hetznerService = new HetznerService($token->token); $serverData = $hetznerService->getServer($this->matchedHetznerServer['id']); if (empty($serverData)) { $this->dispatch('error', 'Could not find Hetzner server with ID: '.$this->matchedHetznerServer['id']); return; } // Update the server with Hetzner details $this->server->update([ 'cloud_provider_token_id' => $this->selectedHetznerTokenId, 'hetzner_server_id' => $this->matchedHetznerServer['id'], 'hetzner_server_status' => $serverData['status'] ?? null, ]); $this->hetznerServerStatus = $serverData['status'] ?? null; // Clear the linking state $this->matchedHetznerServer = null; $this->selectedHetznerTokenId = null; $this->manualHetznerServerId = null; $this->hetznerNoMatchFound = false; $this->hetznerSearchError = null; $this->dispatch('success', 'Server successfully linked to Hetzner Cloud!'); $this->dispatch('refreshServerShow'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.show'); } } ================================================ FILE: app/Livewire/Server/Swarm.php ================================================ server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->parameters = get_route_parameters(); $this->syncData(); } catch (\Throwable) { return redirect()->route('server.index'); } } public function syncData(bool $toModel = false) { if ($toModel) { $this->authorize('update', $this->server); $this->server->settings->is_swarm_manager = $this->isSwarmManager; $this->server->settings->is_swarm_worker = $this->isSwarmWorker; $this->server->settings->save(); } else { $this->isSwarmManager = $this->server->settings->is_swarm_manager; $this->isSwarmWorker = $this->server->settings->is_swarm_worker; } } public function instantSave() { try { $this->syncData(true); $this->dispatch('success', 'Swarm settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function render() { return view('livewire.server.swarm'); } } ================================================ FILE: app/Livewire/Server/ValidateAndInstall.php ================================================ '$refresh', ]; public function init(int $data = 0) { $this->uptime = null; $this->supported_os_type = null; $this->prerequisites_installed = null; $this->docker_installed = null; $this->docker_version = null; $this->docker_compose_installed = null; $this->error = null; $this->number_of_tries = $data; if (! $this->ask) { $this->dispatch('validateConnection'); } } public function startValidatingAfterAsking() { $this->ask = false; $this->init(); } public function retry() { $this->authorize('update', $this->server); $this->uptime = null; $this->supported_os_type = null; $this->prerequisites_installed = null; $this->docker_installed = null; $this->docker_compose_installed = null; $this->docker_version = null; $this->error = null; $this->number_of_tries = 0; $this->init(); } public function validateConnection() { $this->authorize('update', $this->server); ['uptime' => $this->uptime, 'error' => $error] = $this->server->validateConnection(); if (! $this->uptime) { $this->error = 'Server is not reachable. Please validate your configuration and connection.
Check this documentation for further help.

Error: '.$error.'
'; $this->server->update([ 'validation_logs' => $this->error, ]); return; } $this->dispatch('validateOS'); } public function validateOS() { $this->supported_os_type = $this->server->validateOS(); if (! $this->supported_os_type) { $this->error = 'Server OS type is not supported. Please install Docker manually before continuing: documentation.'; $this->server->update([ 'validation_logs' => $this->error, ]); return; } $this->dispatch('validatePrerequisites'); } public function validatePrerequisites() { $validationResult = $this->server->validatePrerequisites(); $this->prerequisites_installed = $validationResult['success']; if (! $validationResult['success']) { if ($this->install) { if ($this->number_of_tries == $this->max_tries) { $missingCommands = implode(', ', $validationResult['missing']); $this->error = "Prerequisites ({$missingCommands}) could not be installed. Please install them manually before continuing."; $this->server->update([ 'validation_logs' => $this->error, ]); return; } else { if ($this->number_of_tries <= $this->max_tries) { $this->installationStep = 'Prerequisites'; $activity = $this->server->installPrerequisites(); $this->number_of_tries++; $this->dispatch('activityMonitor', $activity->id, 'init', $this->number_of_tries, "{$this->installationStep} Installation Logs"); } return; } } else { $missingCommands = implode(', ', $validationResult['missing']); $this->error = "Prerequisites ({$missingCommands}) are not installed. Please install them before continuing."; $this->server->update([ 'validation_logs' => $this->error, ]); return; } } $this->dispatch('validateDockerEngine'); } public function validateDockerEngine() { $this->docker_installed = $this->server->validateDockerEngine(); $this->docker_compose_installed = $this->server->validateDockerCompose(); if (! $this->docker_installed || ! $this->docker_compose_installed) { if ($this->install) { if ($this->number_of_tries == $this->max_tries) { $this->error = 'Docker Engine could not be installed. Please install Docker manually before continuing: documentation.'; $this->server->update([ 'validation_logs' => $this->error, ]); return; } else { if ($this->number_of_tries <= $this->max_tries) { $this->installationStep = 'Docker'; $activity = $this->server->installDocker(); $this->number_of_tries++; $this->dispatch('activityMonitor', $activity->id, 'init', $this->number_of_tries, "{$this->installationStep} Installation Logs"); } return; } } else { $this->error = 'Docker Engine is not installed. Please install Docker manually before continuing: documentation.'; $this->server->update([ 'validation_logs' => $this->error, ]); return; } } $this->dispatch('validateDockerVersion'); } public function validateDockerVersion() { if ($this->server->isSwarm()) { $swarmInstalled = $this->server->validateDockerSwarm(); if ($swarmInstalled) { $this->dispatch('success', 'Docker Swarm is initiated.'); } } else { $this->docker_version = $this->server->validateDockerEngineVersion(); if ($this->docker_version) { // Mark validation as complete $this->server->update(['is_validating' => false]); $this->dispatch('refreshServerShow'); $this->dispatch('refreshBoardingIndex'); ServerValidated::dispatch($this->server->team_id, $this->server->uuid); $this->dispatch('success', 'Server validated, proxy is starting in a moment.'); $proxyShouldRun = CheckProxy::run($this->server, true); if (! $proxyShouldRun) { return; } // Ensure networks exist BEFORE dispatching async proxy startup // This prevents race condition where proxy tries to start before networks are created instant_remote_process(ensureProxyNetworksExist($this->server)->toArray(), $this->server, false); StartProxy::dispatch($this->server); } else { $requiredDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.'); $this->error = 'Minimum Docker Engine version '.$requiredDockerVersion.' is not installed. Please install Docker manually before continuing: documentation.'; $this->server->update([ 'validation_logs' => $this->error, ]); return; } } if ($this->server->isBuildServer()) { return; } } public function render() { return view('livewire.server.validate-and-install'); } } ================================================ FILE: app/Livewire/Settings/Advanced.php ================================================ 'boolean', 'do_not_track' => 'boolean', 'is_dns_validation_enabled' => 'boolean', 'custom_dns_servers' => 'nullable|string', 'is_api_enabled' => 'boolean', 'allowed_ips' => ['nullable', 'string', new ValidIpOrCidr], 'is_sponsorship_popup_enabled' => 'boolean', 'disable_two_step_confirmation' => 'boolean', 'is_wire_navigate_enabled' => 'boolean', ]; } public function mount() { if (! isInstanceAdmin()) { return redirect()->route('dashboard'); } $this->settings = instanceSettings(); $this->custom_dns_servers = $this->settings->custom_dns_servers; $this->allowed_ips = $this->settings->allowed_ips; $this->do_not_track = $this->settings->do_not_track; $this->is_registration_enabled = $this->settings->is_registration_enabled; $this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled; $this->is_api_enabled = $this->settings->is_api_enabled; $this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation; $this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled; $this->is_wire_navigate_enabled = $this->settings->is_wire_navigate_enabled ?? true; } public function submit() { try { $this->validate(); $this->custom_dns_servers = str($this->custom_dns_servers)->replaceEnd(',', '')->trim(); $this->custom_dns_servers = str($this->custom_dns_servers)->trim()->explode(',')->map(function ($dns) { return str($dns)->trim()->lower(); })->unique()->implode(','); // Handle allowed IPs with subnet support and 0.0.0.0 special case $this->allowed_ips = str($this->allowed_ips)->replaceEnd(',', '')->trim(); // Only validate and clean up if we have IPs and it's not 0.0.0.0 (allow all) if (! empty($this->allowed_ips) && ! in_array('0.0.0.0', array_map('trim', explode(',', $this->allowed_ips)))) { $invalidEntries = []; $validEntries = str($this->allowed_ips)->trim()->explode(',')->map(function ($entry) use (&$invalidEntries) { $entry = str($entry)->trim()->toString(); if (empty($entry)) { return null; } // Check if it's valid CIDR notation if (str_contains($entry, '/')) { [$ip, $mask] = explode('/', $entry); $isIpv6 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false; $maxMask = $isIpv6 ? 128 : 32; if (filter_var($ip, FILTER_VALIDATE_IP) && is_numeric($mask) && $mask >= 0 && $mask <= $maxMask) { return $entry; } $invalidEntries[] = $entry; return null; } // Check if it's a valid IP address if (filter_var($entry, FILTER_VALIDATE_IP)) { return $entry; } $invalidEntries[] = $entry; return null; })->filter()->values()->all(); if (! empty($invalidEntries)) { $this->dispatch('error', 'Invalid IP addresses or subnets: '.implode(', ', $invalidEntries)); return; } if (empty($validEntries)) { $this->dispatch('error', 'No valid IP addresses or subnets provided'); return; } $validEntries = deduplicateAllowlist($validEntries); $this->allowed_ips = implode(',', $validEntries); } $this->instantSave(); } catch (\Exception $e) { return handleError($e, $this); } } public function instantSave() { try { $this->settings->is_registration_enabled = $this->is_registration_enabled; $this->settings->do_not_track = $this->do_not_track; $this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled; $this->settings->custom_dns_servers = $this->custom_dns_servers; $this->settings->is_api_enabled = $this->is_api_enabled; $this->settings->allowed_ips = $this->allowed_ips; $this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled; $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation; $this->settings->is_wire_navigate_enabled = $this->is_wire_navigate_enabled; $this->settings->save(); $this->dispatch('success', 'Settings updated!'); } catch (\Exception $e) { return handleError($e, $this); } } public function toggleTwoStepConfirmation($password): bool { if (! verifyPasswordConfirmation($password, $this)) { return false; } $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation = true; $this->settings->save(); $this->dispatch('success', 'Two step confirmation has been disabled.'); return true; } public function render() { return view('livewire.settings.advanced'); } } ================================================ FILE: app/Livewire/Settings/Index.php ================================================ 'Invalid instance URL.', 'fqdn.max' => 'URL must not exceed 255 characters.', ]; public function render() { return view('livewire.settings.index'); } public function mount() { if (! isInstanceAdmin()) { return redirect()->route('dashboard'); } $this->settings = instanceSettings(); if (! isCloud()) { $this->server = Server::findOrFail(0); } $this->fqdn = $this->settings->fqdn; $this->public_port_min = $this->settings->public_port_min; $this->public_port_max = $this->settings->public_port_max; $this->instance_name = $this->settings->instance_name; $this->public_ipv4 = $this->settings->public_ipv4; $this->public_ipv6 = $this->settings->public_ipv6; $this->instance_timezone = $this->settings->instance_timezone; $this->dev_helper_version = $this->settings->dev_helper_version; } #[Computed] public function timezones(): array { return collect(timezone_identifiers_list()) ->sort() ->values() ->toArray(); } public function instantSave($isSave = true) { $this->validate(); $this->settings->fqdn = $this->fqdn ? trim($this->fqdn) : $this->fqdn; $this->settings->public_port_min = $this->public_port_min; $this->settings->public_port_max = $this->public_port_max; $this->settings->instance_name = $this->instance_name; $this->settings->public_ipv4 = $this->public_ipv4; $this->settings->public_ipv6 = $this->public_ipv6; $this->settings->instance_timezone = $this->instance_timezone; $this->settings->dev_helper_version = $this->dev_helper_version; if ($isSave) { $this->settings->save(); $this->dispatch('success', 'Settings updated!'); } } public function confirmDomainUsage() { $this->forceSaveDomains = true; $this->showDomainConflictModal = false; $this->submit(); } public function submit() { try { $error_show = false; $this->resetErrorBag(); if (! validate_timezone($this->instance_timezone)) { $this->instance_timezone = config('app.timezone'); throw new \Exception('Invalid timezone.'); } else { $this->settings->instance_timezone = $this->instance_timezone; } if ($this->settings->public_port_min > $this->settings->public_port_max) { $this->addError('settings.public_port_min', 'The minimum port must be lower than the maximum port.'); return; } // Trim FQDN to remove leading/trailing whitespace before validation if ($this->fqdn) { $this->fqdn = trim($this->fqdn); } $this->validate(); if ($this->settings->is_dns_validation_enabled && $this->fqdn && $this->server) { if (! validateDNSEntry($this->fqdn, $this->server)) { $this->dispatch('error', "Validating DNS failed.

Make sure you have added the DNS records correctly.

{$this->fqdn}->{$this->server->ip}

Check this documentation for further help."); $error_show = true; } } if ($this->fqdn) { if (! $this->forceSaveDomains) { $result = checkDomainUsage(domain: $this->fqdn); if ($result['hasConflicts']) { $this->domainConflicts = $result['conflicts']; $this->showDomainConflictModal = true; return; } } else { // Reset the force flag after using it $this->forceSaveDomains = false; } } $this->instantSave(isSave: false); $this->settings->save(); if ($this->server) { $this->server->setupDynamicProxyConfiguration(); } if (! $error_show) { $this->dispatch('success', 'Instance settings updated successfully!'); } } catch (\Exception $e) { return handleError($e, $this); } } public function buildHelperImage() { try { if (! isDev()) { $this->dispatch('error', 'Building helper image is only available in development mode.'); return; } if (! $this->server) { $this->dispatch('error', 'Server not available.'); return; } $version = $this->dev_helper_version ?: config('constants.coolify.helper_version'); if (empty($version)) { $this->dispatch('error', 'Please specify a version to build.'); return; } $buildCommand = "docker build -t ghcr.io/coollabsio/coolify-helper:{$version} -f docker/coolify-helper/Dockerfile ."; $activity = remote_process( command: [$buildCommand], server: $this->server, type: 'build-helper-image' ); $this->buildActivityId = $activity->id; $this->dispatch('activityMonitor', $activity->id); $this->dispatch('success', "Building coolify-helper:{$version}..."); } catch (\Exception $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Settings/ScheduledJobs.php ================================================ executions = collect(); $this->skipLogs = collect(); $this->managerRuns = collect(); } public function mount(): void { if (! isInstanceAdmin()) { redirect()->route('dashboard'); return; } $this->loadData(); } public function updatedFilterType(): void { $this->skipPage = 0; $this->loadData(); } public function updatedFilterDate(): void { $this->skipPage = 0; $this->loadData(); } public function skipNextPage(): void { $this->skipPage += $this->skipDefaultTake; $this->showSkipPrev = true; $this->loadData(); } public function skipPreviousPage(): void { $this->skipPage -= $this->skipDefaultTake; if ($this->skipPage < 0) { $this->skipPage = 0; } $this->showSkipPrev = $this->skipPage > 0; $this->loadData(); } public function refresh(): void { $this->loadData(); } public function render() { return view('livewire.settings.scheduled-jobs', [ 'executions' => $this->executions, 'skipLogs' => $this->skipLogs, 'managerRuns' => $this->managerRuns, ]); } private function loadData(?int $teamId = null): void { $this->executions = $this->getExecutions($teamId); $parser = new SchedulerLogParser; $allSkips = $parser->getRecentSkips(500, $teamId); $this->skipTotalCount = $allSkips->count(); $this->skipLogs = $this->enrichSkipLogsWithLinks( $allSkips->slice($this->skipPage, $this->skipDefaultTake)->values() ); $this->showSkipPrev = $this->skipPage > 0; $this->showSkipNext = ($this->skipPage + $this->skipDefaultTake) < $this->skipTotalCount; $this->skipCurrentPage = intval($this->skipPage / $this->skipDefaultTake) + 1; $this->managerRuns = $parser->getRecentRuns(30, $teamId); } private function enrichSkipLogsWithLinks(Collection $skipLogs): Collection { $taskIds = $skipLogs->where('type', 'task')->pluck('context.task_id')->filter()->unique()->values(); $backupIds = $skipLogs->where('type', 'backup')->pluck('context.backup_id')->filter()->unique()->values(); $serverIds = $skipLogs->where('type', 'docker_cleanup')->pluck('context.server_id')->filter()->unique()->values(); $tasks = $taskIds->isNotEmpty() ? ScheduledTask::with(['application.environment.project', 'service.environment.project'])->whereIn('id', $taskIds)->get()->keyBy('id') : collect(); $backups = $backupIds->isNotEmpty() ? ScheduledDatabaseBackup::with(['database.environment.project'])->whereIn('id', $backupIds)->get()->keyBy('id') : collect(); $servers = $serverIds->isNotEmpty() ? Server::whereIn('id', $serverIds)->get()->keyBy('id') : collect(); return $skipLogs->map(function (array $skip) use ($tasks, $backups, $servers): array { $skip['link'] = null; $skip['resource_name'] = null; if ($skip['type'] === 'task') { $task = $tasks->get($skip['context']['task_id'] ?? null); if ($task) { $skip['resource_name'] = $skip['context']['task_name'] ?? $task->name; $resource = $task->application ?? $task->service; $environment = $resource?->environment; $project = $environment?->project; if ($project && $environment && $resource) { $routeName = $task->application_id ? 'project.application.scheduled-tasks' : 'project.service.scheduled-tasks'; $routeKey = $task->application_id ? 'application_uuid' : 'service_uuid'; $skip['link'] = route($routeName, [ 'project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, $routeKey => $resource->uuid, 'task_uuid' => $task->uuid, ]); } } } elseif ($skip['type'] === 'backup') { $backup = $backups->get($skip['context']['backup_id'] ?? null); if ($backup) { $database = $backup->database; $skip['resource_name'] = $database?->name ?? 'Database backup'; $environment = $database?->environment; $project = $environment?->project; if ($project && $environment && $database) { $skip['link'] = route('project.database.backup.index', [ 'project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid, ]); } } } elseif ($skip['type'] === 'docker_cleanup') { $server = $servers->get($skip['context']['server_id'] ?? null); if ($server) { $skip['resource_name'] = $server->name; $skip['link'] = route('server.show', ['server_uuid' => $server->uuid]); } } return $skip; }); } private function getExecutions(?int $teamId = null): Collection { $dateFrom = $this->getDateFrom(); $backups = collect(); $tasks = collect(); $cleanups = collect(); if ($this->filterType === 'all' || $this->filterType === 'backup') { $backups = $this->getBackupExecutions($dateFrom, $teamId); } if ($this->filterType === 'all' || $this->filterType === 'task') { $tasks = $this->getTaskExecutions($dateFrom, $teamId); } if ($this->filterType === 'all' || $this->filterType === 'cleanup') { $cleanups = $this->getCleanupExecutions($dateFrom, $teamId); } return $backups->concat($tasks)->concat($cleanups) ->sortByDesc('created_at') ->values() ->take(100); } private function getBackupExecutions(?Carbon $dateFrom, ?int $teamId): Collection { $query = ScheduledDatabaseBackupExecution::with(['scheduledDatabaseBackup.database', 'scheduledDatabaseBackup.team']) ->where('status', 'failed') ->when($dateFrom, fn ($q) => $q->where('created_at', '>=', $dateFrom)) ->when($teamId, fn ($q) => $q->whereRelation('scheduledDatabaseBackup.team', 'id', $teamId)) ->orderBy('created_at', 'desc') ->limit(100) ->get(); return $query->map(function ($execution) { $backup = $execution->scheduledDatabaseBackup; $database = $backup?->database; $server = $backup?->server(); return [ 'id' => $execution->id, 'type' => 'backup', 'status' => $execution->status ?? 'unknown', 'resource_name' => $database?->name ?? 'Deleted database', 'resource_type' => $database ? class_basename($database) : null, 'server_name' => $server?->name ?? 'Unknown', 'server_id' => $server?->id, 'team_id' => $backup?->team_id, 'created_at' => $execution->created_at, 'finished_at' => $execution->updated_at, 'message' => $execution->message, 'size' => $execution->size ?? null, ]; }); } private function getTaskExecutions(?Carbon $dateFrom, ?int $teamId): Collection { $query = ScheduledTaskExecution::with(['scheduledTask.application', 'scheduledTask.service']) ->where('status', 'failed') ->when($dateFrom, fn ($q) => $q->where('created_at', '>=', $dateFrom)) ->when($teamId, function ($q) use ($teamId) { $q->where(function ($sub) use ($teamId) { $sub->whereRelation('scheduledTask.application.environment.project.team', 'id', $teamId) ->orWhereRelation('scheduledTask.service.environment.project.team', 'id', $teamId); }); }) ->orderBy('created_at', 'desc') ->limit(100) ->get(); return $query->map(function ($execution) { $task = $execution->scheduledTask; $resource = $task?->application ?? $task?->service; $server = $task?->server(); $teamId = $server?->team_id; return [ 'id' => $execution->id, 'type' => 'task', 'status' => $execution->status ?? 'unknown', 'resource_name' => $task?->name ?? 'Deleted task', 'resource_type' => $resource ? class_basename($resource) : null, 'server_name' => $server?->name ?? 'Unknown', 'server_id' => $server?->id, 'team_id' => $teamId, 'created_at' => $execution->created_at, 'finished_at' => $execution->finished_at, 'message' => $execution->message, 'size' => null, ]; }); } private function getCleanupExecutions(?Carbon $dateFrom, ?int $teamId): Collection { $query = DockerCleanupExecution::with(['server']) ->where('status', 'failed') ->when($dateFrom, fn ($q) => $q->where('created_at', '>=', $dateFrom)) ->when($teamId, fn ($q) => $q->whereRelation('server', 'team_id', $teamId)) ->orderBy('created_at', 'desc') ->limit(100) ->get(); return $query->map(function ($execution) { $server = $execution->server; return [ 'id' => $execution->id, 'type' => 'cleanup', 'status' => $execution->status ?? 'unknown', 'resource_name' => $server?->name ?? 'Deleted server', 'resource_type' => 'Server', 'server_name' => $server?->name ?? 'Unknown', 'server_id' => $server?->id, 'team_id' => $server?->team_id, 'created_at' => $execution->created_at, 'finished_at' => $execution->finished_at ?? $execution->updated_at, 'message' => $execution->message, 'size' => null, ]; }); } private function getDateFrom(): ?Carbon { return match ($this->filterDate) { 'last_24h' => now()->subDay(), 'last_7d' => now()->subWeek(), 'last_30d' => now()->subMonth(), default => null, }; } } ================================================ FILE: app/Livewire/Settings/Updates.php ================================================ server = Server::findOrFail(0); } $this->settings = instanceSettings(); $this->auto_update_frequency = $this->settings->auto_update_frequency; $this->update_check_frequency = $this->settings->update_check_frequency; $this->is_auto_update_enabled = $this->settings->is_auto_update_enabled; } public function instantSave() { try { if ($this->settings->is_auto_update_enabled === true) { $this->validate([ 'auto_update_frequency' => ['required', 'string'], ]); } $this->settings->auto_update_frequency = $this->auto_update_frequency; $this->settings->update_check_frequency = $this->update_check_frequency; $this->settings->is_auto_update_enabled = $this->is_auto_update_enabled; $this->settings->save(); $this->dispatch('success', 'Settings updated!'); } catch (\Exception $e) { return handleError($e, $this); } } public function submit() { try { $this->resetErrorBag(); $this->validate(); if ($this->is_auto_update_enabled && ! validate_cron_expression($this->auto_update_frequency)) { $this->dispatch('error', 'Invalid Cron / Human expression for Auto Update Frequency.'); if (empty($this->auto_update_frequency)) { $this->auto_update_frequency = '0 0 * * *'; } return; } if (! validate_cron_expression($this->update_check_frequency)) { $this->dispatch('error', 'Invalid Cron / Human expression for Update Check Frequency.'); if (empty($this->update_check_frequency)) { $this->update_check_frequency = '0 * * * *'; } return; } $this->instantSave(); if ($this->server) { $this->server->setupDynamicProxyConfiguration(); } } catch (\Exception $e) { return handleError($e, $this); } } public function checkManually() { CheckForUpdatesJob::dispatchSync(); $this->dispatch('updateAvailable'); $settings = instanceSettings(); if ($settings->new_version_available) { $this->dispatch('success', 'New version available!'); } else { $this->dispatch('success', 'No new version available.'); } } public function render() { return view('livewire.settings.updates'); } } ================================================ FILE: app/Livewire/SettingsBackup.php ================================================ route('dashboard'); } $settings = instanceSettings(); $this->server = Server::findOrFail(0); $this->database = StandalonePostgresql::whereName('coolify-db')->first(); $s3s = S3Storage::whereTeamId(0)->get() ?? []; if ($this->database) { $this->uuid = $this->database->uuid; $this->name = $this->database->name; $this->description = $this->database->description; $this->postgres_user = $this->database->postgres_user; $this->postgres_password = $this->database->postgres_password; if ($this->database->status !== 'running') { $this->database->status = 'running'; $this->database->save(); } $this->backup = $this->database->scheduledBackups->first(); if ($this->backup && ! $this->server->isFunctional()) { $this->backup->enabled = false; $this->backup->save(); } $this->executions = $this->backup->executions; } $this->settings = $settings; $this->s3s = $s3s; } public function addCoolifyDatabase() { try { $server = Server::findOrFail(0); $out = instant_remote_process(['docker inspect coolify-db'], $server); $envs = format_docker_envs_to_json($out); $postgres_password = $envs['POSTGRES_PASSWORD']; $postgres_user = $envs['POSTGRES_USER']; $postgres_db = $envs['POSTGRES_DB']; $this->database = StandalonePostgresql::create([ 'id' => 0, 'name' => 'coolify-db', 'description' => 'Coolify database', 'postgres_user' => $postgres_user, 'postgres_password' => $postgres_password, 'postgres_db' => $postgres_db, 'status' => 'running', 'destination_type' => \App\Models\StandaloneDocker::class, 'destination_id' => 0, ]); $this->backup = ScheduledDatabaseBackup::create([ 'id' => 0, 'enabled' => true, 'save_s3' => false, 'frequency' => '0 0 * * *', 'database_id' => $this->database->id, 'database_type' => \App\Models\StandalonePostgresql::class, 'team_id' => currentTeam()->id, ]); $this->database->refresh(); $this->backup->refresh(); $this->s3s = S3Storage::whereTeamId(0)->get(); $this->uuid = $this->database->uuid; $this->name = $this->database->name; $this->description = $this->database->description; $this->postgres_user = $this->database->postgres_user; $this->postgres_password = $this->database->postgres_password; $this->executions = $this->backup->executions; } catch (\Exception $e) { return handleError($e, $this); } } public function submit() { $this->validate(); $this->database->update([ 'name' => $this->name, 'description' => $this->description, 'postgres_user' => $this->postgres_user, 'postgres_password' => $this->postgres_password, ]); $this->dispatch('success', 'Backup updated.'); } } ================================================ FILE: app/Livewire/SettingsDropdown.php ================================================ getUnreadChangelogCount(); } public function getEntriesProperty() { $user = Auth::user(); return app(ChangelogService::class)->getEntriesForUser($user); } public function getCurrentVersionProperty() { return 'v'.config('constants.coolify.version'); } public function openWhatsNewModal() { $this->showWhatsNewModal = true; } public function closeWhatsNewModal() { $this->showWhatsNewModal = false; } public function markAsRead($identifier) { app(ChangelogService::class)->markAsReadForUser($identifier, Auth::user()); } public function markAllAsRead() { app(ChangelogService::class)->markAllAsReadForUser(Auth::user()); } public function manualFetchChangelog() { if (! isDev()) { return; } try { PullChangelog::dispatch(); $this->dispatch('success', 'Changelog fetch initiated! Check back in a few moments.'); } catch (\Throwable $e) { $this->dispatch('error', 'Failed to fetch changelog: '.$e->getMessage()); } } public function render() { return view('livewire.settings-dropdown', [ 'entries' => $this->entries, 'unreadCount' => $this->unreadCount, 'currentVersion' => $this->currentVersion, ]); } } ================================================ FILE: app/Livewire/SettingsEmail.php ================================================ route('dashboard'); } $this->settings = instanceSettings(); $this->syncData(); $this->team = auth()->user()->currentTeam(); $this->testEmailAddress = auth()->user()->email; } public function syncData(bool $toModel = false) { if ($toModel) { $this->validate(); $this->settings->smtp_enabled = $this->smtpEnabled; $this->settings->smtp_host = $this->smtpHost; $this->settings->smtp_port = $this->smtpPort; $this->settings->smtp_encryption = $this->smtpEncryption; $this->settings->smtp_username = $this->smtpUsername; $this->settings->smtp_password = $this->smtpPassword; $this->settings->smtp_timeout = $this->smtpTimeout; $this->settings->smtp_from_address = $this->smtpFromAddress; $this->settings->smtp_from_name = $this->smtpFromName; $this->settings->resend_enabled = $this->resendEnabled; $this->settings->resend_api_key = $this->resendApiKey; $this->settings->save(); } else { $this->smtpEnabled = $this->settings->smtp_enabled; $this->smtpHost = $this->settings->smtp_host; $this->smtpPort = $this->settings->smtp_port; $this->smtpEncryption = $this->settings->smtp_encryption; $this->smtpUsername = $this->settings->smtp_username; $this->smtpPassword = $this->settings->smtp_password; $this->smtpTimeout = $this->settings->smtp_timeout; $this->smtpFromAddress = $this->settings->smtp_from_address; $this->smtpFromName = $this->settings->smtp_from_name; $this->resendEnabled = $this->settings->resend_enabled; $this->resendApiKey = $this->settings->resend_api_key; } } public function submit() { try { $this->resetErrorBag(); $this->syncData(true); $this->dispatch('success', 'Transactional email settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function instantSave(string $type) { try { $currentSmtpEnabled = $this->settings->smtp_enabled; $currentResendEnabled = $this->settings->resend_enabled; $this->resetErrorBag(); if ($type === 'SMTP') { $this->submitSmtp(); $this->resendEnabled = $this->settings->resend_enabled = false; } elseif ($type === 'Resend') { $this->submitResend(); $this->smtpEnabled = $this->settings->smtp_enabled = false; } $this->settings->save(); } catch (\Throwable $e) { if ($type === 'SMTP') { $this->smtpEnabled = $currentSmtpEnabled; } elseif ($type === 'Resend') { $this->resendEnabled = $currentResendEnabled; } return handleError($e, $this); } } public function submitSmtp() { try { $this->validate([ 'smtpEnabled' => 'boolean', 'smtpFromAddress' => 'required|email', 'smtpFromName' => 'required|string', 'smtpHost' => 'required|string', 'smtpPort' => 'required|numeric', 'smtpEncryption' => 'required|string|in:starttls,tls,none', 'smtpUsername' => 'nullable|string', 'smtpPassword' => 'nullable|string', 'smtpTimeout' => 'nullable|numeric', ], [ 'smtpFromAddress.required' => 'From Address is required.', 'smtpFromAddress.email' => 'Please enter a valid email address.', 'smtpFromName.required' => 'From Name is required.', 'smtpHost.required' => 'SMTP Host is required.', 'smtpPort.required' => 'SMTP Port is required.', 'smtpPort.numeric' => 'SMTP Port must be a number.', 'smtpEncryption.required' => 'Encryption type is required.', ]); $this->settings->smtp_enabled = $this->smtpEnabled; $this->settings->smtp_host = $this->smtpHost; $this->settings->smtp_port = $this->smtpPort; $this->settings->smtp_encryption = $this->smtpEncryption; $this->settings->smtp_username = $this->smtpUsername; $this->settings->smtp_password = $this->smtpPassword; $this->settings->smtp_timeout = $this->smtpTimeout; $this->settings->smtp_from_address = $this->smtpFromAddress; $this->settings->smtp_from_name = $this->smtpFromName; $this->settings->save(); $this->dispatch('success', 'SMTP settings updated.'); } catch (\Throwable $e) { $this->smtpEnabled = false; return handleError($e, $this); } } public function submitResend() { try { $this->validate([ 'resendEnabled' => 'boolean', 'resendApiKey' => 'required|string', 'smtpFromAddress' => 'required|email', 'smtpFromName' => 'required|string', ], [ 'resendApiKey.required' => 'Resend API Key is required.', 'smtpFromAddress.required' => 'From Address is required.', 'smtpFromAddress.email' => 'Please enter a valid email address.', 'smtpFromName.required' => 'From Name is required.', ]); $this->settings->resend_enabled = $this->resendEnabled; $this->settings->resend_api_key = $this->resendApiKey; $this->settings->smtp_from_address = $this->smtpFromAddress; $this->settings->smtp_from_name = $this->smtpFromName; $this->settings->save(); $this->dispatch('success', 'Resend settings updated.'); } catch (\Throwable $e) { $this->resendEnabled = false; return handleError($e, $this); } } public function sendTestEmail() { try { $this->validate([ 'testEmailAddress' => 'required|email', ], [ 'testEmailAddress.required' => 'Test email address is required.', 'testEmailAddress.email' => 'Please enter a valid email address.', ]); $executed = RateLimiter::attempt( 'test-email:'.$this->team->id, $perMinute = 0, function () { $this->team?->notifyNow(new Test($this->testEmailAddress)); $this->dispatch('success', 'Test Email sent.'); }, $decaySeconds = 10, ); if (! $executed) { throw new \Exception('Too many messages sent!'); } } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/SettingsOauth.php ================================================ reduce(function ($carry, $setting) { $carry["oauth_settings_map.$setting->provider.enabled"] = 'required'; $carry["oauth_settings_map.$setting->provider.client_id"] = 'nullable'; $carry["oauth_settings_map.$setting->provider.client_secret"] = 'nullable'; $carry["oauth_settings_map.$setting->provider.redirect_uri"] = 'nullable'; $carry["oauth_settings_map.$setting->provider.tenant"] = 'nullable'; $carry["oauth_settings_map.$setting->provider.base_url"] = 'nullable'; return $carry; }, []); } public function mount() { if (! isInstanceAdmin()) { return redirect()->route('home'); } $this->oauth_settings_map = OauthSetting::all()->sortBy('provider')->reduce(function ($carry, $setting) { $carry[$setting->provider] = [ 'id' => $setting->id, 'provider' => $setting->provider, 'enabled' => $setting->enabled, 'client_id' => $setting->client_id, 'client_secret' => $setting->client_secret, 'redirect_uri' => $setting->redirect_uri, 'tenant' => $setting->tenant, 'base_url' => $setting->base_url, ]; return $carry; }, []); } private function updateOauthSettings(?string $provider = null) { if ($provider) { $oauthData = $this->oauth_settings_map[$provider]; $oauth = OauthSetting::find($oauthData['id']); if (! $oauth) { throw new \Exception('OAuth setting for '.$provider.' not found. It may have been deleted.'); } $oauth->fill([ 'enabled' => $oauthData['enabled'], 'client_id' => $oauthData['client_id'], 'client_secret' => $oauthData['client_secret'], 'redirect_uri' => $oauthData['redirect_uri'], 'tenant' => $oauthData['tenant'], 'base_url' => $oauthData['base_url'], ]); if (! $oauth->couldBeEnabled()) { $oauth->update(['enabled' => false]); throw new \Exception('OAuth settings are not complete for '.$oauth->provider.'.
Please fill in all required fields.'); } $oauth->save(); // Update the array with fresh data $this->oauth_settings_map[$provider] = [ 'id' => $oauth->id, 'provider' => $oauth->provider, 'enabled' => $oauth->enabled, 'client_id' => $oauth->client_id, 'client_secret' => $oauth->client_secret, 'redirect_uri' => $oauth->redirect_uri, 'tenant' => $oauth->tenant, 'base_url' => $oauth->base_url, ]; $this->dispatch('success', 'OAuth settings for '.$oauth->provider.' updated successfully!'); } else { $errors = []; foreach (array_values($this->oauth_settings_map) as $settingData) { $oauth = OauthSetting::find($settingData['id']); if (! $oauth) { $errors[] = "OAuth setting for provider '{$settingData['provider']}' not found. It may have been deleted."; continue; } $oauth->fill([ 'enabled' => $settingData['enabled'], 'client_id' => $settingData['client_id'], 'client_secret' => $settingData['client_secret'], 'redirect_uri' => $settingData['redirect_uri'], 'tenant' => $settingData['tenant'], 'base_url' => $settingData['base_url'], ]); if ($settingData['enabled'] && ! $oauth->couldBeEnabled()) { $oauth->enabled = false; $errors[] = "OAuth settings are incomplete for '{$oauth->provider}'. Required fields are missing. The provider has been disabled."; } $oauth->save(); // Update the array with fresh data $this->oauth_settings_map[$oauth->provider] = [ 'id' => $oauth->id, 'provider' => $oauth->provider, 'enabled' => $oauth->enabled, 'client_id' => $oauth->client_id, 'client_secret' => $oauth->client_secret, 'redirect_uri' => $oauth->redirect_uri, 'tenant' => $oauth->tenant, 'base_url' => $oauth->base_url, ]; } if (! empty($errors)) { $this->dispatch('error', implode('
', $errors)); } } } public function instantSave(string $provider) { try { $this->updateOauthSettings($provider); } catch (\Exception $e) { return handleError($e, $this); } } public function submit() { $this->updateOauthSettings(); $this->dispatch('success', 'Instance settings updated successfully!'); } } ================================================ FILE: app/Livewire/SharedVariables/Environment/Index.php ================================================ projects = Project::ownedByCurrentTeamCached(); } public function render() { return view('livewire.shared-variables.environment.index'); } } ================================================ FILE: app/Livewire/SharedVariables/Environment/Show.php ================================================ 'refreshEnvs', 'saveKey', 'environmentVariableDeleted' => 'refreshEnvs']; public function saveKey($data) { try { $this->authorize('update', $this->environment); $found = $this->environment->environment_variables()->where('key', $data['key'])->first(); if ($found) { throw new \Exception('Variable already exists.'); } $this->environment->environment_variables()->create([ 'key' => $data['key'], 'value' => $data['value'], 'is_multiline' => $data['is_multiline'], 'is_literal' => $data['is_literal'], 'comment' => $data['comment'] ?? null, 'type' => 'environment', 'team_id' => currentTeam()->id, ]); $this->environment->refresh(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } } public function mount() { $this->parameters = get_route_parameters(); $this->project = Project::ownedByCurrentTeam()->where('uuid', request()->route('project_uuid'))->firstOrFail(); $this->environment = $this->project->environments()->where('uuid', request()->route('environment_uuid'))->firstOrFail(); $this->getDevView(); } public function switch() { $this->authorize('view', $this->environment); $this->view = $this->view === 'normal' ? 'dev' : 'normal'; $this->getDevView(); } public function getDevView() { $this->variables = $this->formatEnvironmentVariables($this->environment->environment_variables->sortBy('key')); } private function formatEnvironmentVariables($variables) { return $variables->map(function ($item) { if ($item->is_shown_once) { return "$item->key=(Locked Secret, delete and add again to change)"; } if ($item->is_multiline) { return "$item->key=(Multiline environment variable, edit in normal view)"; } return "$item->key=$item->value"; })->join("\n"); } public function submit() { try { $this->authorize('update', $this->environment); $this->handleBulkSubmit(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->refreshEnvs(); } } private function handleBulkSubmit() { $variables = parseEnvFormatToArray($this->variables); $changesMade = false; DB::transaction(function () use ($variables, &$changesMade) { // Delete removed variables $deletedCount = $this->deleteRemovedVariables($variables); if ($deletedCount > 0) { $changesMade = true; } // Update or create variables $updatedCount = $this->updateOrCreateVariables($variables); if ($updatedCount > 0) { $changesMade = true; } }); // Only dispatch success after transaction has committed if ($changesMade) { $this->dispatch('success', 'Environment variables updated.'); } } private function deleteRemovedVariables($variables) { $variablesToDelete = $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->get(); if ($variablesToDelete->isEmpty()) { return 0; } $this->environment->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); return $variablesToDelete->count(); } private function updateOrCreateVariables($variables) { $count = 0; foreach ($variables as $key => $data) { $value = is_array($data) ? ($data['value'] ?? '') : $data; $found = $this->environment->environment_variables()->where('key', $key)->first(); if ($found) { if (! $found->is_shown_once && ! $found->is_multiline) { if ($found->value !== $value) { $found->value = $value; $found->save(); $count++; } } } else { $this->environment->environment_variables()->create([ 'key' => $key, 'value' => $value, 'is_multiline' => false, 'is_literal' => false, 'type' => 'environment', 'team_id' => currentTeam()->id, ]); $count++; } } return $count; } public function refreshEnvs() { $this->environment->refresh(); $this->getDevView(); } public function render() { return view('livewire.shared-variables.environment.show'); } } ================================================ FILE: app/Livewire/SharedVariables/Index.php ================================================ projects = Project::ownedByCurrentTeamCached(); } public function render() { return view('livewire.shared-variables.project.index'); } } ================================================ FILE: app/Livewire/SharedVariables/Project/Show.php ================================================ 'refreshEnvs', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => 'refreshEnvs']; public function saveKey($data) { try { $this->authorize('update', $this->project); $found = $this->project->environment_variables()->where('key', $data['key'])->first(); if ($found) { throw new \Exception('Variable already exists.'); } $this->project->environment_variables()->create([ 'key' => $data['key'], 'value' => $data['value'], 'is_multiline' => $data['is_multiline'], 'is_literal' => $data['is_literal'], 'comment' => $data['comment'] ?? null, 'type' => 'project', 'team_id' => currentTeam()->id, ]); $this->project->refresh(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } } public function mount() { $projectUuid = request()->route('project_uuid'); $teamId = currentTeam()->id; $project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first(); if (! $project) { return redirect()->route('dashboard'); } $this->project = $project; $this->getDevView(); } public function switch() { $this->authorize('view', $this->project); $this->view = $this->view === 'normal' ? 'dev' : 'normal'; $this->getDevView(); } public function getDevView() { $this->variables = $this->formatEnvironmentVariables($this->project->environment_variables->sortBy('key')); } private function formatEnvironmentVariables($variables) { return $variables->map(function ($item) { if ($item->is_shown_once) { return "$item->key=(Locked Secret, delete and add again to change)"; } if ($item->is_multiline) { return "$item->key=(Multiline environment variable, edit in normal view)"; } return "$item->key=$item->value"; })->join("\n"); } public function submit() { try { $this->authorize('update', $this->project); $this->handleBulkSubmit(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->refreshEnvs(); } } private function handleBulkSubmit() { $variables = parseEnvFormatToArray($this->variables); $changesMade = DB::transaction(function () use ($variables) { // Delete removed variables $deletedCount = $this->deleteRemovedVariables($variables); // Update or create variables $updatedCount = $this->updateOrCreateVariables($variables); return $deletedCount > 0 || $updatedCount > 0; }); if ($changesMade) { $this->dispatch('success', 'Environment variables updated.'); } } private function deleteRemovedVariables($variables) { $variablesToDelete = $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->get(); if ($variablesToDelete->isEmpty()) { return 0; } $this->project->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); return $variablesToDelete->count(); } private function updateOrCreateVariables($variables) { $count = 0; foreach ($variables as $key => $data) { $value = is_array($data) ? ($data['value'] ?? '') : $data; $found = $this->project->environment_variables()->where('key', $key)->first(); if ($found) { if (! $found->is_shown_once && ! $found->is_multiline) { if ($found->value !== $value) { $found->value = $value; $found->save(); $count++; } } } else { $this->project->environment_variables()->create([ 'key' => $key, 'value' => $value, 'is_multiline' => false, 'is_literal' => false, 'type' => 'project', 'team_id' => currentTeam()->id, ]); $count++; } } return $count; } public function refreshEnvs() { $this->project->refresh(); $this->getDevView(); } public function render() { return view('livewire.shared-variables.project.show'); } } ================================================ FILE: app/Livewire/SharedVariables/Team/Index.php ================================================ 'refreshEnvs', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => 'refreshEnvs']; public function saveKey($data) { try { $this->authorize('update', $this->team); $found = $this->team->environment_variables()->where('key', $data['key'])->first(); if ($found) { throw new \Exception('Variable already exists.'); } $this->team->environment_variables()->create([ 'key' => $data['key'], 'value' => $data['value'], 'is_multiline' => $data['is_multiline'], 'is_literal' => $data['is_literal'], 'comment' => $data['comment'] ?? null, 'type' => 'team', 'team_id' => currentTeam()->id, ]); $this->team->refresh(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } } public function mount() { $this->team = currentTeam(); $this->getDevView(); } public function switch() { $this->authorize('view', $this->team); $this->view = $this->view === 'normal' ? 'dev' : 'normal'; $this->getDevView(); } public function getDevView() { $this->variables = $this->formatEnvironmentVariables($this->team->environment_variables->sortBy('key')); } private function formatEnvironmentVariables($variables) { return $variables->map(function ($item) { if ($item->is_shown_once) { return "$item->key=(Locked Secret, delete and add again to change)"; } if ($item->is_multiline) { return "$item->key=(Multiline environment variable, edit in normal view)"; } return "$item->key=$item->value"; })->join("\n"); } public function submit() { try { $this->authorize('update', $this->team); $this->handleBulkSubmit(); $this->getDevView(); } catch (\Throwable $e) { return handleError($e, $this); } finally { $this->refreshEnvs(); } } private function handleBulkSubmit() { $variables = parseEnvFormatToArray($this->variables); $changesMade = false; DB::transaction(function () use ($variables, &$changesMade) { // Delete removed variables $deletedCount = $this->deleteRemovedVariables($variables); if ($deletedCount > 0) { $changesMade = true; } // Update or create variables $updatedCount = $this->updateOrCreateVariables($variables); if ($updatedCount > 0) { $changesMade = true; } }); if ($changesMade) { $this->dispatch('success', 'Environment variables updated.'); } } private function deleteRemovedVariables($variables) { $variablesToDelete = $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->get(); if ($variablesToDelete->isEmpty()) { return 0; } $this->team->environment_variables()->whereNotIn('key', array_keys($variables))->delete(); return $variablesToDelete->count(); } private function updateOrCreateVariables($variables) { $count = 0; foreach ($variables as $key => $data) { $value = is_array($data) ? ($data['value'] ?? '') : $data; $found = $this->team->environment_variables()->where('key', $key)->first(); if ($found) { if (! $found->is_shown_once && ! $found->is_multiline) { if ($found->value !== $value) { $found->value = $value; $found->save(); $count++; } } } else { $this->team->environment_variables()->create([ 'key' => $key, 'value' => $value, 'is_multiline' => false, 'is_literal' => false, 'type' => 'team', 'team_id' => currentTeam()->id, ]); $count++; } } return $count; } public function refreshEnvs() { $this->team->refresh(); $this->getDevView(); } public function render() { return view('livewire.shared-variables.team.index'); } } ================================================ FILE: app/Livewire/Source/Github/Change.php ================================================ 'required|string', 'organization' => 'nullable|string', 'apiUrl' => 'required|string', 'htmlUrl' => 'required|string', 'customUser' => 'required|string', 'customPort' => 'required|int', 'appId' => 'nullable|int', 'installationId' => 'nullable|int', 'clientId' => 'nullable|string', 'clientSecret' => 'nullable|string', 'webhookSecret' => 'nullable|string', 'isSystemWide' => 'required|bool', 'contents' => 'nullable|string', 'metadata' => 'nullable|string', 'pullRequests' => 'nullable|string', 'privateKeyId' => 'nullable|int', ]; public function boot() { if ($this->github_app) { $this->github_app->makeVisible(['client_secret', 'webhook_secret']); } } /** * Sync data between component properties and model * * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties. */ private function syncData(bool $toModel = false): void { if ($toModel) { // Sync TO model (before save) $this->github_app->name = $this->name; $this->github_app->organization = $this->organization; $this->github_app->api_url = $this->apiUrl; $this->github_app->html_url = $this->htmlUrl; $this->github_app->custom_user = $this->customUser; $this->github_app->custom_port = $this->customPort; $this->github_app->app_id = $this->appId; $this->github_app->installation_id = $this->installationId; $this->github_app->client_id = $this->clientId; $this->github_app->client_secret = $this->clientSecret; $this->github_app->webhook_secret = $this->webhookSecret; $this->github_app->is_system_wide = $this->isSystemWide; $this->github_app->private_key_id = $this->privateKeyId; $this->github_app->contents = $this->contents; $this->github_app->metadata = $this->metadata; $this->github_app->pull_requests = $this->pullRequests; } else { // Sync FROM model (on load/refresh) $this->name = $this->github_app->name; $this->organization = $this->github_app->organization; $this->apiUrl = $this->github_app->api_url; $this->htmlUrl = $this->github_app->html_url; $this->customUser = $this->github_app->custom_user; $this->customPort = $this->github_app->custom_port; $this->appId = $this->github_app->app_id; $this->installationId = $this->github_app->installation_id; $this->clientId = $this->github_app->client_id; $this->clientSecret = $this->github_app->client_secret; $this->webhookSecret = $this->github_app->webhook_secret; $this->isSystemWide = $this->github_app->is_system_wide; $this->privateKeyId = $this->github_app->private_key_id; $this->contents = $this->github_app->contents; $this->metadata = $this->github_app->metadata; $this->pullRequests = $this->github_app->pull_requests; } } public function checkPermissions() { try { $this->authorize('view', $this->github_app); // Validate required fields before attempting to fetch permissions $missingFields = []; if (! $this->github_app->app_id) { $missingFields[] = 'App ID'; } if (! $this->github_app->private_key_id) { $missingFields[] = 'Private Key'; } if (! empty($missingFields)) { $fieldsList = implode(', ', $missingFields); $this->dispatch('error', "Cannot fetch permissions. Please set the following required fields first: {$fieldsList}"); return; } // Verify the private key exists and is accessible if (! $this->github_app->privateKey) { $this->dispatch('error', 'Private Key not found. Please select a valid private key.'); return; } GithubAppPermissionJob::dispatchSync($this->github_app); $this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret'); $this->dispatch('success', 'Github App permissions updated.'); } catch (\Throwable $e) { // Provide better error message for unsupported key formats $errorMessage = $e->getMessage(); if (str_contains($errorMessage, 'DECODER routines::unsupported') || str_contains($errorMessage, 'parse your key')) { $this->dispatch('error', 'The selected private key format is not supported for GitHub Apps.

Please use an RSA private key in PEM format (BEGIN RSA PRIVATE KEY).

OpenSSH format keys (BEGIN OPENSSH PRIVATE KEY) are not supported.'); return; } return handleError($e, $this); } } public function mount() { try { $github_app_uuid = request()->github_app_uuid; $this->github_app = GithubApp::ownedByCurrentTeam()->whereUuid($github_app_uuid)->firstOrFail(); $this->github_app->makeVisible(['client_secret', 'webhook_secret']); $this->privateKeys = PrivateKey::ownedByCurrentTeamCached(); $this->applications = $this->github_app->applications; $settings = instanceSettings(); // Sync data from model to properties $this->syncData(false); // Override name with kebab case for display $this->name = str($this->github_app->name)->kebab(); $this->fqdn = $settings->fqdn; if ($settings->public_ipv4) { $this->ipv4 = 'http://'.$settings->public_ipv4.':'.config('app.port'); } if ($settings->public_ipv6) { $this->ipv6 = 'http://'.$settings->public_ipv6.':'.config('app.port'); } if ($this->github_app->installation_id && session('from')) { $source_id = data_get(session('from'), 'source_id'); if (! $source_id || $this->github_app->id !== $source_id) { session()->forget('from'); } else { $parameters = data_get(session('from'), 'parameters'); $back = data_get(session('from'), 'back'); $environment_uuid = data_get($parameters, 'environment_uuid'); $project_uuid = data_get($parameters, 'project_uuid'); $type = data_get($parameters, 'type'); $destination = data_get($parameters, 'destination'); session()->forget('from'); return redirect()->route($back, [ 'environment_uuid' => $environment_uuid, 'project_uuid' => $project_uuid, 'type' => $type, 'destination' => $destination, ]); } } $this->parameters = get_route_parameters(); if (isCloud() && ! isDev()) { $this->webhook_endpoint = config('app.url'); } else { $this->webhook_endpoint = $this->ipv4 ?? ''; $this->is_system_wide = $this->github_app->is_system_wide; } } catch (\Throwable $e) { return handleError($e, $this); } } public function getGithubAppNameUpdatePath() { if (str($this->github_app->organization)->isNotEmpty()) { return "{$this->github_app->html_url}/organizations/{$this->github_app->organization}/settings/apps/{$this->github_app->name}"; } return "{$this->github_app->html_url}/settings/apps/{$this->github_app->name}"; } private function generateGithubJwt($private_key, $app_id): string { $configuration = Configuration::forAsymmetricSigner( new Sha256, InMemory::plainText($private_key), InMemory::plainText($private_key) ); $now = time(); return $configuration->builder() ->issuedBy((string) $app_id) ->permittedFor('https://api.github.com') ->identifiedBy((string) $now) ->issuedAt(new \DateTimeImmutable("@{$now}")) ->expiresAt(new \DateTimeImmutable('@'.($now + 600))) ->getToken($configuration->signer(), $configuration->signingKey()) ->toString(); } public function updateGithubAppName() { try { $this->authorize('update', $this->github_app); $privateKey = PrivateKey::ownedByCurrentTeam()->find($this->github_app->private_key_id); if (! $privateKey) { $this->dispatch('error', 'No private key found for this GitHub App.'); return; } $jwt = $this->generateGithubJwt($privateKey->private_key, $this->github_app->app_id); $response = Http::withHeaders([ 'Accept' => 'application/vnd.github+json', 'X-GitHub-Api-Version' => '2022-11-28', 'Authorization' => "Bearer {$jwt}", ])->get("{$this->github_app->api_url}/app"); if ($response->successful()) { $app_data = $response->json(); $app_slug = $app_data['slug'] ?? null; if ($app_slug) { $this->github_app->name = $app_slug; $this->name = str($app_slug)->kebab(); $privateKey->name = "github-app-{$app_slug}"; $privateKey->save(); $this->github_app->save(); $this->dispatch('success', 'GitHub App name and SSH key name synchronized successfully.'); } else { $this->dispatch('info', 'Could not find App Name (slug) in GitHub response.'); } } else { $error_message = $response->json()['message'] ?? 'Unknown error'; $this->dispatch('error', "Failed to fetch GitHub App information: {$error_message}"); } } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->github_app); $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); $this->validate(); $this->syncData(true); $this->github_app->save(); $this->dispatch('success', 'Github App updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function createGithubAppManually() { $this->authorize('update', $this->github_app); $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); $this->github_app->app_id = 1234567890; $this->github_app->installation_id = 1234567890; $this->github_app->save(); // Redirect to avoid Livewire morphing issues when view structure changes return redirect()->route('source.github.show', ['github_app_uuid' => $this->github_app->uuid]) ->with('success', 'Github App updated. You can now configure the details.'); } public function instantSave() { try { $this->authorize('update', $this->github_app); $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); $this->syncData(true); $this->github_app->save(); $this->dispatch('success', 'Github App updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function delete() { try { $this->authorize('delete', $this->github_app); if ($this->github_app->applications->isNotEmpty()) { $this->dispatch('error', 'This source is being used by an application. Please delete all applications first.'); $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); return; } $this->github_app->delete(); return redirect()->route('source.all'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Source/Github/Create.php ================================================ name = substr(generate_random_name(), 0, 30); } public function createGitHubApp() { try { $this->authorize('createAnyResource'); $this->validate([ 'name' => 'required|string', 'organization' => 'nullable|string', 'api_url' => 'required|string', 'html_url' => 'required|string', 'custom_user' => 'required|string', 'custom_port' => 'required|int', 'is_system_wide' => 'required|bool', ]); $payload = [ 'name' => $this->name, 'organization' => $this->organization, 'api_url' => $this->api_url, 'html_url' => $this->html_url, 'custom_user' => $this->custom_user, 'custom_port' => $this->custom_port, 'is_system_wide' => $this->is_system_wide, 'team_id' => currentTeam()->id, ]; $github_app = GithubApp::create($payload); if (session('from')) { session(['from' => session('from') + ['source_id' => $github_app->id]]); } return redirectRoute($this, 'source.github.show', ['github_app_uuid' => $github_app->uuid]); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Storage/Create.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), 'region' => 'required|max:255', 'key' => 'required|max:255', 'secret' => 'required|max:255', 'bucket' => 'required|max:255', 'endpoint' => 'required|url|max:255', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'region.required' => 'The Region field is required.', 'region.max' => 'The Region may not be greater than 255 characters.', 'key.required' => 'The Access Key field is required.', 'key.max' => 'The Access Key may not be greater than 255 characters.', 'secret.required' => 'The Secret Key field is required.', 'secret.max' => 'The Secret Key may not be greater than 255 characters.', 'bucket.required' => 'The Bucket field is required.', 'bucket.max' => 'The Bucket may not be greater than 255 characters.', 'endpoint.required' => 'The Endpoint field is required.', 'endpoint.url' => 'The Endpoint must be a valid URL.', 'endpoint.max' => 'The Endpoint may not be greater than 255 characters.', ] ); } protected $validationAttributes = [ 'name' => 'Name', 'description' => 'Description', 'region' => 'Region', 'key' => 'Key', 'secret' => 'Secret', 'bucket' => 'Bucket', 'endpoint' => 'Endpoint', ]; public function updatedEndpoint($value) { try { if (empty($value)) { return; } if (str($value)->contains('digitaloceanspaces.com')) { $uri = Uri::of($value); $host = $uri->host(); if (preg_match('/^(.+)\.([^.]+\.digitaloceanspaces\.com)$/', $host, $matches)) { $host = $matches[2]; $value = "https://{$host}"; } } } finally { if (! str($value)->startsWith('https://') && ! str($value)->startsWith('http://')) { $value = 'https://'.$value; } $this->endpoint = $value; } } public function submit() { try { $this->authorize('create', S3Storage::class); $this->validate(); $this->storage = new S3Storage; $this->storage->name = $this->name; $this->storage->description = $this->description ?? null; $this->storage->region = $this->region; $this->storage->key = $this->key; $this->storage->secret = $this->secret; $this->storage->bucket = $this->bucket; if (empty($this->endpoint)) { $this->storage->endpoint = "https://s3.{$this->region}.amazonaws.com"; } else { $this->storage->endpoint = $this->endpoint; } $this->storage->team_id = currentTeam()->id; $this->storage->testConnection(); $this->storage->save(); return redirectRoute($this, 'storage.show', [$this->storage->uuid]); } catch (\Throwable $e) { $this->dispatch('error', 'Failed to create storage.', $e->getMessage()); // return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Storage/Form.php ================================================ 'nullable|boolean', 'name' => ValidationPatterns::nameRules(required: false), 'description' => ValidationPatterns::descriptionRules(), 'region' => 'required|max:255', 'key' => 'required|max:255', 'secret' => 'required|max:255', 'bucket' => 'required|max:255', 'endpoint' => 'required|url|max:255', ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'region.required' => 'The Region field is required.', 'region.max' => 'The Region may not be greater than 255 characters.', 'key.required' => 'The Access Key field is required.', 'key.max' => 'The Access Key may not be greater than 255 characters.', 'secret.required' => 'The Secret Key field is required.', 'secret.max' => 'The Secret Key may not be greater than 255 characters.', 'bucket.required' => 'The Bucket field is required.', 'bucket.max' => 'The Bucket may not be greater than 255 characters.', 'endpoint.required' => 'The Endpoint field is required.', 'endpoint.url' => 'The Endpoint must be a valid URL.', 'endpoint.max' => 'The Endpoint may not be greater than 255 characters.', ] ); } protected $validationAttributes = [ 'isUsable' => 'Is Usable', 'name' => 'Name', 'description' => 'Description', 'region' => 'Region', 'key' => 'Key', 'secret' => 'Secret', 'bucket' => 'Bucket', 'endpoint' => 'Endpoint', ]; /** * Sync data between component properties and model * * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties. */ private function syncData(bool $toModel = false): void { if ($toModel) { // Sync TO model (before save) $this->storage->name = $this->name; $this->storage->description = $this->description; $this->storage->endpoint = $this->endpoint; $this->storage->bucket = $this->bucket; $this->storage->region = $this->region; $this->storage->key = $this->key; $this->storage->secret = $this->secret; $this->storage->is_usable = $this->isUsable; } else { // Sync FROM model (on load/refresh) $this->name = $this->storage->name; $this->description = $this->storage->description; $this->endpoint = $this->storage->endpoint; $this->bucket = $this->storage->bucket; $this->region = $this->storage->region; $this->key = $this->storage->key; $this->secret = $this->storage->secret; $this->isUsable = $this->storage->is_usable; } } public function mount() { $this->syncData(false); } public function testConnection() { try { $this->authorize('validateConnection', $this->storage); $this->storage->testConnection(shouldSave: true); // Update component property to reflect the new validation status $this->isUsable = $this->storage->is_usable; return $this->dispatch('success', 'Connection is working.', 'Tested with "ListObjectsV2" action.'); } catch (\Throwable $e) { // Refresh model and sync to get the latest state $this->storage->refresh(); $this->isUsable = $this->storage->is_usable; $this->dispatch('error', 'Failed to test connection.', $e->getMessage()); } } public function delete() { try { $this->authorize('delete', $this->storage); $this->storage->delete(); return redirect()->route('storage.index'); } catch (\Throwable $e) { return handleError($e, $this); } } public function submit() { try { $this->authorize('update', $this->storage); DB::transaction(function () { $this->validate(); // Sync properties to model before saving $this->syncData(true); $this->storage->save(); // Test connection with new values - if this fails, transaction will rollback $this->storage->testConnection(shouldSave: false); // If we get here, the connection test succeeded $this->storage->is_usable = true; $this->storage->unusable_email_sent = false; $this->storage->save(); // Update local property to reflect success $this->isUsable = true; }); $this->dispatch('success', 'Storage settings updated and connection verified.'); } catch (\Throwable $e) { // Refresh the model to revert UI to database values after rollback $this->storage->refresh(); $this->syncData(false); return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Storage/Index.php ================================================ s3 = S3Storage::ownedByCurrentTeam()->get(); } public function render() { return view('livewire.storage.index'); } } ================================================ FILE: app/Livewire/Storage/Show.php ================================================ storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->first(); if (! $this->storage) { abort(404); } $this->authorize('view', $this->storage); } public function render() { return view('livewire.storage.show'); } } ================================================ FILE: app/Livewire/Subscription/Actions.php ================================================ server_limits = Team::serverLimit(); $this->quantity = (int) $this->server_limits; } public function loadPricePreview(int $quantity): void { $this->quantity = $quantity; $result = (new UpdateSubscriptionQuantity)->fetchPricePreview(currentTeam(), $quantity); $this->pricePreview = $result['success'] ? $result['preview'] : null; } // Password validation is intentionally skipped for quantity updates. // Unlike refunds/cancellations, changing the server limit is a // non-destructive, reversible billing adjustment (prorated by Stripe). public function updateQuantity(string $password = ''): bool { if ($this->quantity < UpdateSubscriptionQuantity::MIN_SERVER_LIMIT) { $this->dispatch('error', 'Minimum server limit is '.UpdateSubscriptionQuantity::MIN_SERVER_LIMIT.'.'); $this->quantity = UpdateSubscriptionQuantity::MIN_SERVER_LIMIT; return true; } if ($this->quantity === (int) $this->server_limits) { return true; } $result = (new UpdateSubscriptionQuantity)->execute(currentTeam(), $this->quantity); if ($result['success']) { $this->server_limits = $this->quantity; $this->pricePreview = null; $this->dispatch('success', 'Server limit updated to '.$this->quantity.'.'); return true; } $this->dispatch('error', $result['error'] ?? 'Failed to update server limit.'); $this->quantity = (int) $this->server_limits; return true; } public function loadRefundEligibility(): void { $this->checkRefundEligibility(); $this->refundCheckLoading = false; } public function stripeCustomerPortal(): void { $session = getStripeCustomerPortalSession(currentTeam()); redirect($session->url); } public function refundSubscription(string $password): bool|string { if (! shouldSkipPasswordConfirmation() && ! Hash::check($password, auth()->user()->password)) { return 'Invalid password.'; } $result = (new RefundSubscription)->execute(currentTeam()); if ($result['success']) { $this->dispatch('success', 'Subscription refunded successfully.'); $this->redirect(route('subscription.index'), navigate: true); return true; } $this->dispatch('error', 'Something went wrong with the refund. Please contact us.'); return true; } public function cancelImmediately(string $password): bool|string { if (! shouldSkipPasswordConfirmation() && ! Hash::check($password, auth()->user()->password)) { return 'Invalid password.'; } $team = currentTeam(); $subscription = $team->subscription; if (! $subscription?->stripe_subscription_id) { $this->dispatch('error', 'Something went wrong with the cancellation. Please contact us.'); return true; } try { $stripe = new StripeClient(config('subscription.stripe_api_key')); $stripe->subscriptions->cancel($subscription->stripe_subscription_id); $subscription->update([ 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, 'stripe_trial_already_ended' => false, 'stripe_past_due' => false, 'stripe_feedback' => 'Cancelled immediately by user', 'stripe_comment' => 'Subscription cancelled immediately by user at '.now()->toDateTimeString(), ]); $team->subscriptionEnded(); \Log::info("Subscription {$subscription->stripe_subscription_id} cancelled immediately for team {$team->name}"); $this->dispatch('success', 'Subscription cancelled successfully.'); $this->redirect(route('subscription.index'), navigate: true); return true; } catch (\Exception $e) { \Log::error("Immediate cancellation error for team {$team->id}: ".$e->getMessage()); $this->dispatch('error', 'Something went wrong with the cancellation. Please contact us.'); return true; } } public function cancelAtPeriodEnd(string $password): bool|string { if (! shouldSkipPasswordConfirmation() && ! Hash::check($password, auth()->user()->password)) { return 'Invalid password.'; } $result = (new CancelSubscriptionAtPeriodEnd)->execute(currentTeam()); if ($result['success']) { $this->dispatch('success', 'Subscription will be cancelled at the end of the billing period.'); return true; } $this->dispatch('error', 'Something went wrong with the cancellation. Please contact us.'); return true; } public function resumeSubscription(): bool { $result = (new ResumeSubscription)->execute(currentTeam()); if ($result['success']) { $this->dispatch('success', 'Subscription resumed successfully.'); return true; } $this->dispatch('error', 'Something went wrong resuming the subscription. Please contact us.'); return true; } private function checkRefundEligibility(): void { if (! isCloud() || ! currentTeam()->subscription?->stripe_subscription_id) { return; } try { $this->refundAlreadyUsed = currentTeam()->subscription?->stripe_refunded_at !== null; $result = (new RefundSubscription)->checkEligibility(currentTeam()); $this->isRefundEligible = $result['eligible']; $this->refundDaysRemaining = $result['days_remaining']; } catch (\Exception $e) { \Log::warning('Refund eligibility check failed: '.$e->getMessage()); } } } ================================================ FILE: app/Livewire/Subscription/Index.php ================================================ user()?->isMember()) { $this->isMember = true; } if (data_get(currentTeam(), 'subscription') && isSubscriptionActive()) { return redirect()->route('subscription.show'); } $this->settings = instanceSettings(); $this->alreadySubscribed = currentTeam()->subscription()->exists(); if (! $this->alreadySubscribed) { $this->loading = false; } } public function stripeCustomerPortal() { $session = getStripeCustomerPortalSession(currentTeam()); if (is_null($session)) { return; } return redirect($session->url); } public function getStripeStatus() { try { $subscription = currentTeam()->subscription; $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); $customer = $stripe->customers->retrieve(currentTeam()->subscription->stripe_customer_id); if ($customer) { $subscriptions = $stripe->subscriptions->all(['customer' => $customer->id]); $currentTeam = currentTeam()->id ?? null; if (count($subscriptions->data) > 0 && $currentTeam) { $foundSubscription = collect($subscriptions->data)->firstWhere('metadata.team_id', $currentTeam); if ($foundSubscription) { $status = data_get($foundSubscription, 'status'); $subscription->update([ 'stripe_subscription_id' => $foundSubscription->id, ]); if ($status === 'unpaid') { $this->isUnpaid = true; } } } if (count($subscriptions->data) === 0) { $this->isCancelled = true; } } } catch (\Exception $e) { // Log the error logger()->error('Stripe API error: '.$e->getMessage()); // Set a flag to show an error message to the user $this->addError('stripe', 'Could not retrieve subscription information. Please try again later.'); } finally { $this->loading = false; } } public function render() { return view('livewire.subscription.index'); } } ================================================ FILE: app/Livewire/Subscription/PricingPlans.php ================================================ config('subscription.stripe_price_id_dynamic_monthly'), 'dynamic-yearly' => config('subscription.stripe_price_id_dynamic_yearly'), default => config('subscription.stripe_price_id_dynamic_monthly'), }; if (! $priceId) { $this->dispatch('error', 'Price ID not found! Please contact the administrator.'); return; } $payload = [ 'allow_promotion_codes' => true, 'billing_address_collection' => 'required', 'client_reference_id' => Auth::id().':'.currentTeam()->id, 'line_items' => [[ 'price' => $priceId, 'adjustable_quantity' => [ 'enabled' => true, 'minimum' => 2, ], 'quantity' => 2, ]], 'tax_id_collection' => [ 'enabled' => true, ], 'automatic_tax' => [ 'enabled' => true, ], 'subscription_data' => [ 'metadata' => [ 'user_id' => Auth::id(), 'team_id' => currentTeam()->id, ], ], 'payment_method_collection' => 'if_required', 'mode' => 'subscription', 'success_url' => route('dashboard', ['success' => true]), 'cancel_url' => route('subscription.index', ['cancelled' => true]), ]; $customer = currentTeam()->subscription?->stripe_customer_id ?? null; if ($customer) { $payload['customer'] = $customer; $payload['customer_update'] = [ 'name' => 'auto', ]; } else { $payload['customer_email'] = Auth::user()->email; } $session = Session::create($payload); return redirect($session->url, 303); } } ================================================ FILE: app/Livewire/Subscription/Show.php ================================================ route('dashboard'); } if (auth()->user()?->isMember()) { return redirect()->route('dashboard'); } if (! data_get(currentTeam(), 'subscription')) { return redirect()->route('subscription.index'); } } public function render() { return view('livewire.subscription.show'); } } ================================================ FILE: app/Livewire/SwitchTeam.php ================================================ selectedTeamId = auth()->user()->currentTeam()->id; } public function updatedSelectedTeamId() { $this->switch_to($this->selectedTeamId); } public function switch_to($team_id) { if (! auth()->user()->teams->contains($team_id)) { return; } $team_to_switch_to = Team::find($team_id); if (! $team_to_switch_to) { return; } refreshSession($team_to_switch_to); return redirect('dashboard'); } } ================================================ FILE: app/Livewire/Tags/Deployments.php ================================================ deploymentsPerTagPerServer = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->whereIn('application_id', $this->resourceIds)->get([ 'id', 'application_id', 'application_name', 'deployment_url', 'pull_request_id', 'server_name', 'server_id', 'status', ])->sortBy('id')->groupBy('server_name')->toArray(); $this->dispatch('deployments', $this->deploymentsPerTagPerServer); } catch (\Exception $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Tags/Show.php ================================================ tags = Tag::ownedByCurrentTeam()->get()->unique('name')->sortBy('name'); if (str($this->tagName)->isNotEmpty()) { $tag = $this->tags->where('name', $this->tagName)->first(); $this->webhook = generateTagDeployWebhook($tag->name); $this->applications = $tag->applications()->get(); $this->services = $tag->services()->get(); $this->tag = $tag; $this->getDeployments(); } } catch (\Exception $e) { return handleError($e, $this); } } public function getDeployments() { try { $resource_ids = $this->applications->pluck('id'); $this->deploymentsPerTagPerServer = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->whereIn('application_id', $resource_ids)->get([ 'id', 'application_id', 'application_name', 'deployment_url', 'pull_request_id', 'server_name', 'server_id', 'status', ])->sortBy('id')->groupBy('server_name')->toArray(); } catch (\Exception $e) { return handleError($e, $this); } } public function redeployAll() { try { $message = collect([]); $this->applications->each(function ($resource) use ($message) { $deploy = new DeployController; $message->push($deploy->deploy_resource($resource)); }); $this->services->each(function ($resource) use ($message) { $deploy = new DeployController; $message->push($deploy->deploy_resource($resource)); }); $this->dispatch('success', 'Mass deployment started.'); } catch (\Exception $e) { return handleError($e, $this); } } public function render() { return view('livewire.tags.show'); } } ================================================ FILE: app/Livewire/Team/AdminView.php ================================================ route('dashboard'); } $this->getUsers(); } public function submitSearch() { if ($this->search !== '') { $this->users = User::where(function ($query) { $query->where('name', 'like', "%{$this->search}%") ->orWhere('email', 'like', "%{$this->search}%"); })->get()->filter(function ($user) { return $user->id !== auth()->id(); }); } else { $this->getUsers(); } } public function getUsers() { $users = User::where('id', '!=', auth()->id())->get(); if ($users->count() > $this->number_of_users_to_show) { $this->lots_of_users = true; $this->users = $users->take($this->number_of_users_to_show); } else { $this->lots_of_users = false; $this->users = $users; } } public function delete($id, $password, $selectedActions = []) { if (! isInstanceAdmin()) { return redirect()->route('dashboard'); } if (! verifyPasswordConfirmation($password, $this)) { return 'The provided password is incorrect.'; } if (! auth()->user()->isInstanceAdmin()) { return $this->dispatch('error', 'You are not authorized to delete users'); } $user = User::find($id); if (! $user) { return $this->dispatch('error', 'User not found'); } try { $user->delete(); $this->getUsers(); return true; } catch (\Exception $e) { return $this->dispatch('error', $e->getMessage()); } } public function render() { return view('livewire.team.admin-view'); } } ================================================ FILE: app/Livewire/Team/Create.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), ]; } protected function messages(): array { return ValidationPatterns::combinedMessages(); } public function submit() { try { $this->validate(); $team = Team::create([ 'name' => $this->name, 'description' => $this->description, 'personal_team' => false, ]); auth()->user()->teams()->attach($team, ['role' => 'admin']); refreshSession($team); return redirectRoute($this, 'team.index'); } catch (\Throwable $e) { return handleError($e, $this); } } } ================================================ FILE: app/Livewire/Team/Index.php ================================================ ValidationPatterns::nameRules(), 'description' => ValidationPatterns::descriptionRules(), ]; } protected function messages(): array { return array_merge( ValidationPatterns::combinedMessages(), [ 'name.required' => 'The Name field is required.', ] ); } protected $validationAttributes = [ 'name' => 'name', 'description' => 'description', ]; /** * Sync data between component properties and model * * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties. */ private function syncData(bool $toModel = false): void { if ($toModel) { // Sync TO model (before save) $this->team->name = $this->name; $this->team->description = $this->description; } else { // Sync FROM model (on load/refresh) $this->name = $this->team->name; $this->description = $this->team->description; } } public function mount() { $this->team = currentTeam(); $this->syncData(false); if (auth()->user()->isAdminFromSession()) { $this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get(); } } public function render() { return view('livewire.team.index'); } public function submit() { $this->validate(); try { $this->authorize('update', $this->team); $this->syncData(true); $this->team->save(); refreshSession(); $this->dispatch('success', 'Team updated.'); } catch (\Throwable $e) { return handleError($e, $this); } } public function delete() { $currentTeam = currentTeam(); $this->authorize('delete', $currentTeam); $currentTeam->delete(); $currentTeam->members->each(function ($user) use ($currentTeam) { if ($user->id === Auth::id()) { return; } $user->teams()->detach($currentTeam); $session = DB::table('sessions')->where('user_id', $user->id)->first(); if ($session) { DB::table('sessions')->where('id', $session->id)->delete(); } }); refreshSession(); return redirect()->route('team.index'); } } ================================================ FILE: app/Livewire/Team/Invitations.php ================================================ authorize('manageInvitations', currentTeam()); $invitation = TeamInvitation::ownedByCurrentTeam()->findOrFail($invitation_id); $user = User::whereEmail($invitation->email)->first(); if (filled($user)) { $user->deleteIfNotVerifiedAndForcePasswordReset(); } $invitation->delete(); $this->refreshInvitations(); $this->dispatch('success', 'Invitation revoked.'); } catch (\Exception) { return $this->dispatch('error', 'Invitation not found.'); } } public function refreshInvitations() { $this->invitations = TeamInvitation::ownedByCurrentTeam()->get(); } } ================================================ FILE: app/Livewire/Team/InviteLink.php ================================================ 'required|email', 'role' => 'required|string', ]; public function mount() { $this->email = isDev() ? 'test3@example.com' : ''; } public function viaEmail() { $this->generateInviteLink(sendEmail: true); } public function viaLink() { $this->generateInviteLink(sendEmail: false); } private function generateInviteLink(bool $sendEmail = false) { try { $this->authorize('manageInvitations', currentTeam()); $this->validate(); // Prevent privilege escalation: users cannot invite someone with higher privileges $userRole = auth()->user()->role(); if (is_null($userRole) || ($userRole === 'member' && in_array($this->role, ['admin', 'owner']))) { throw new \Exception('Members cannot invite admins or owners.'); } if ($userRole === 'admin' && $this->role === 'owner') { throw new \Exception('Admins cannot invite owners.'); } $this->email = strtolower($this->email); $member_emails = currentTeam()->members()->get()->pluck('email'); if ($member_emails->contains($this->email)) { return handleError(livewire: $this, customErrorMessage: "$this->email is already a member of ".currentTeam()->name.'.'); } $uuid = new Cuid2(32); $link = url('/').config('constants.invitation.link.base_url').$uuid; $user = User::whereEmail($this->email)->first(); if (is_null($user)) { $password = Str::password(); $user = User::create([ 'name' => str($this->email)->before('@'), 'email' => $this->email, 'password' => Hash::make($password), 'force_password_reset' => true, ]); $token = Crypt::encryptString("{$user->email}@@@$password"); $link = route('auth.link', ['token' => $token]); } $invitation = TeamInvitation::whereEmail($this->email)->first(); if (! is_null($invitation)) { $invitationValid = $invitation->isValid(); if ($invitationValid) { return handleError(livewire: $this, customErrorMessage: "Pending invitation already exists for $this->email."); } else { $invitation->delete(); } } $invitation = TeamInvitation::firstOrCreate([ 'team_id' => currentTeam()->id, 'uuid' => $uuid, 'email' => $this->email, 'role' => $this->role, 'link' => $link, 'via' => $sendEmail ? 'email' : 'link', ]); if ($sendEmail) { $mail = new MailMessage; $mail->view('emails.invitation-link', [ 'team' => currentTeam()->name, 'invitation_link' => $link, ]); $mail->subject('You have been invited to '.currentTeam()->name.' on '.config('app.name').'.'); send_user_an_email($mail, $this->email); $this->dispatch('success', 'Invitation sent via email.'); $this->dispatch('refreshInvitations'); return; } else { $this->dispatch('success', 'Invitation link generated.'); $this->dispatch('refreshInvitations'); } } catch (\Throwable $e) { $error_message = $e->getMessage(); if ($e->getCode() === '23505') { $error_message = 'Invitation already sent.'; } return handleError(error: $e, livewire: $this, customErrorMessage: $error_message); } } } ================================================ FILE: app/Livewire/Team/Member/Index.php ================================================ user()->can('manageInvitations', currentTeam())) { $this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get(); } } public function render() { return view('livewire.team.member.index'); } } ================================================ FILE: app/Livewire/Team/Member.php ================================================ authorize('manageMembers', currentTeam()); if (Role::from(auth()->user()->role())->lt(Role::ADMIN) || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { throw new \Exception('You are not authorized to perform this action.'); } $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => Role::ADMIN->value]); $this->dispatch('reloadWindow'); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } public function makeOwner() { try { $this->authorize('manageMembers', currentTeam()); if (Role::from(auth()->user()->role())->lt(Role::OWNER) || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { throw new \Exception('You are not authorized to perform this action.'); } $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => Role::OWNER->value]); $this->dispatch('reloadWindow'); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } public function makeReadonly() { try { $this->authorize('manageMembers', currentTeam()); if (Role::from(auth()->user()->role())->lt(Role::ADMIN) || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { throw new \Exception('You are not authorized to perform this action.'); } $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => Role::MEMBER->value]); $this->dispatch('reloadWindow'); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } public function remove() { try { $this->authorize('manageMembers', currentTeam()); if (Role::from(auth()->user()->role())->lt(Role::ADMIN) || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { throw new \Exception('You are not authorized to perform this action.'); } $teamId = currentTeam()->id; $this->member->teams()->detach(currentTeam()); // Clear cache for the removed user - both old and new key formats Cache::forget("team:{$this->member->id}"); Cache::forget("user:{$this->member->id}:team:{$teamId}"); $this->dispatch('reloadWindow'); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } } private function getMemberRole() { return $this->member->teams()->where('teams.id', currentTeam()->id)->first()?->pivot?->role; } } ================================================ FILE: app/Livewire/Team/Storage/Show.php ================================================ storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->first(); if (! $this->storage) { abort(404); } } public function render() { return view('livewire.storage.show'); } } ================================================ FILE: app/Livewire/Terminal/Index.php ================================================ servers = Server::isReachable()->get()->filter(function ($server) { return $server->isTerminalEnabled(); }); } public function loadContainers() { try { $this->containers = $this->getAllActiveContainers(); } catch (\Exception $e) { return handleError($e, $this); } finally { $this->isLoadingContainers = false; } } private function getAllActiveContainers() { return collect($this->servers)->flatMap(function ($server) { if (! $server->isFunctional()) { return []; } return $server->loadAllContainers()->map(function ($container) use ($server) { $state = data_get_str($container, 'State')->lower(); if ($state->contains('running')) { return [ 'name' => data_get($container, 'Names'), 'connection_name' => data_get($container, 'Names'), 'uuid' => data_get($container, 'Names'), 'status' => data_get_str($container, 'State')->lower(), 'server' => $server, 'server_uuid' => $server->uuid, ]; } return null; })->filter(); })->sortBy('name'); } public function updatedSelectedUuid() { if ($this->selected_uuid === 'default') { // When cleared to default, do nothing (no error message) return; } $this->connectToContainer(); } #[On('connectToContainer')] public function connectToContainer() { if ($this->selected_uuid === 'default') { $this->dispatch('error', 'Please select a server or a container.'); return; } $container = collect($this->containers)->firstWhere('uuid', $this->selected_uuid); $this->dispatch('send-terminal-command', isset($container), $container['connection_name'] ?? $this->selected_uuid, $container['server_uuid'] ?? $this->selected_uuid ); } public function render() { return view('livewire.terminal.index'); } } ================================================ FILE: app/Livewire/Upgrade.php ================================================ 'checkUpdate']; public function mount() { $this->currentVersion = config('constants.coolify.version'); $this->devMode = isDev(); } public function checkUpdate() { try { $this->latestVersion = get_latest_version_of_coolify(); $this->currentVersion = config('constants.coolify.version'); $this->isUpgradeAvailable = data_get(InstanceSettings::get(), 'new_version_available', false); if (isDev()) { $this->isUpgradeAvailable = true; } } catch (\Throwable $e) { return handleError($e, $this); } } public function upgrade() { try { if ($this->updateInProgress) { return; } $this->updateInProgress = true; UpdateCoolify::run(manual_update: true); } catch (\Throwable $e) { return handleError($e, $this); } } public function getUpgradeStatus(): array { // Only root team members can view upgrade status if (auth()->user()?->currentTeam()?->id !== 0) { return ['status' => 'none']; } $server = Server::find(0); if (! $server) { return ['status' => 'none']; } $statusFile = '/data/coolify/source/.upgrade-status'; try { $content = instant_remote_process( ["cat {$statusFile} 2>/dev/null || echo ''"], $server, false ); $content = trim($content ?? ''); } catch (\Throwable $e) { return ['status' => 'none']; } if (empty($content)) { return ['status' => 'none']; } $parts = explode('|', $content); if (count($parts) < 3) { return ['status' => 'none']; } [$step, $message, $timestamp] = $parts; // Check if status is stale (older than 10 minutes) try { $statusTime = new \DateTime($timestamp); $now = new \DateTime; $diffMinutes = ($now->getTimestamp() - $statusTime->getTimestamp()) / 60; if ($diffMinutes > 10) { return ['status' => 'none']; } } catch (\Throwable $e) { return ['status' => 'none']; } if ($step === 'error') { return [ 'status' => 'error', 'step' => 0, 'message' => $message, ]; } $stepInt = (int) $step; $status = $stepInt >= 6 ? 'complete' : 'in_progress'; return [ 'status' => $status, 'step' => $stepInt, 'message' => $message, ]; } } ================================================ FILE: app/Livewire/VerifyEmail.php ================================================ rateLimit(1, 300); auth()->user()->sendVerificationEmail(); $this->dispatch('success', 'Email verification link sent!'); } catch (\Exception $e) { return handleError($e, $this); } } public function render() { return view('livewire.verify-email'); } } ================================================ FILE: app/Models/Application.php ================================================ ['type' => 'integer', 'description' => 'The application identifier in the database.'], 'description' => ['type' => 'string', 'nullable' => true, 'description' => 'The application description.'], 'repository_project_id' => ['type' => 'integer', 'nullable' => true, 'description' => 'The repository project identifier.'], 'uuid' => ['type' => 'string', 'description' => 'The application UUID.'], 'name' => ['type' => 'string', 'description' => 'The application name.'], 'fqdn' => ['type' => 'string', 'nullable' => true, 'description' => 'The application domains.'], 'config_hash' => ['type' => 'string', 'description' => 'Configuration hash.'], 'git_repository' => ['type' => 'string', 'description' => 'Git repository URL.'], 'git_branch' => ['type' => 'string', 'description' => 'Git branch.'], 'git_commit_sha' => ['type' => 'string', 'description' => 'Git commit SHA.'], 'git_full_url' => ['type' => 'string', 'nullable' => true, 'description' => 'Git full URL.'], 'docker_registry_image_name' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker registry image name.'], 'docker_registry_image_tag' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker registry image tag.'], 'build_pack' => ['type' => 'string', 'description' => 'Build pack.', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose']], 'static_image' => ['type' => 'string', 'description' => 'Static image used when static site is deployed.'], 'install_command' => ['type' => 'string', 'description' => 'Install command.'], 'build_command' => ['type' => 'string', 'description' => 'Build command.'], 'start_command' => ['type' => 'string', 'description' => 'Start command.'], 'ports_exposes' => ['type' => 'string', 'description' => 'Ports exposes.'], 'ports_mappings' => ['type' => 'string', 'nullable' => true, 'description' => 'Ports mappings.'], 'custom_network_aliases' => ['type' => 'string', 'nullable' => true, 'description' => 'Network aliases for Docker container.'], 'base_directory' => ['type' => 'string', 'description' => 'Base directory for all commands.'], 'publish_directory' => ['type' => 'string', 'description' => 'Publish directory.'], 'health_check_enabled' => ['type' => 'boolean', 'description' => 'Health check enabled.'], 'health_check_path' => ['type' => 'string', 'description' => 'Health check path.'], 'health_check_port' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check port.'], 'health_check_host' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check host.'], 'health_check_method' => ['type' => 'string', 'description' => 'Health check method.'], 'health_check_return_code' => ['type' => 'integer', 'description' => 'Health check return code.'], 'health_check_scheme' => ['type' => 'string', 'description' => 'Health check scheme.'], 'health_check_response_text' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check response text.'], 'health_check_interval' => ['type' => 'integer', 'description' => 'Health check interval in seconds.'], 'health_check_timeout' => ['type' => 'integer', 'description' => 'Health check timeout in seconds.'], 'health_check_retries' => ['type' => 'integer', 'description' => 'Health check retries count.'], 'health_check_start_period' => ['type' => 'integer', 'description' => 'Health check start period in seconds.'], 'health_check_type' => ['type' => 'string', 'description' => 'Health check type: http or cmd.', 'enum' => ['http', 'cmd']], 'health_check_command' => ['type' => 'string', 'nullable' => true, 'description' => 'Health check command for CMD type.'], 'limits_memory' => ['type' => 'string', 'description' => 'Memory limit.'], 'limits_memory_swap' => ['type' => 'string', 'description' => 'Memory swap limit.'], 'limits_memory_swappiness' => ['type' => 'integer', 'description' => 'Memory swappiness.'], 'limits_memory_reservation' => ['type' => 'string', 'description' => 'Memory reservation.'], 'limits_cpus' => ['type' => 'string', 'description' => 'CPU limit.'], 'limits_cpuset' => ['type' => 'string', 'nullable' => true, 'description' => 'CPU set.'], 'limits_cpu_shares' => ['type' => 'integer', 'description' => 'CPU shares.'], 'status' => ['type' => 'string', 'description' => 'Application status.'], 'preview_url_template' => ['type' => 'string', 'description' => 'Preview URL template.'], 'destination_type' => ['type' => 'string', 'description' => 'Destination type.'], 'destination_id' => ['type' => 'integer', 'description' => 'Destination identifier.'], 'source_id' => ['type' => 'integer', 'nullable' => true, 'description' => 'Source identifier.'], 'private_key_id' => ['type' => 'integer', 'nullable' => true, 'description' => 'Private key identifier.'], 'environment_id' => ['type' => 'integer', 'description' => 'Environment identifier.'], 'dockerfile' => ['type' => 'string', 'nullable' => true, 'description' => 'Dockerfile content. Used for dockerfile build pack.'], 'dockerfile_location' => ['type' => 'string', 'description' => 'Dockerfile location.'], 'custom_labels' => ['type' => 'string', 'nullable' => true, 'description' => 'Custom labels.'], 'dockerfile_target_build' => ['type' => 'string', 'nullable' => true, 'description' => 'Dockerfile target build.'], 'manual_webhook_secret_github' => ['type' => 'string', 'nullable' => true, 'description' => 'Manual webhook secret for GitHub.'], 'manual_webhook_secret_gitlab' => ['type' => 'string', 'nullable' => true, 'description' => 'Manual webhook secret for GitLab.'], 'manual_webhook_secret_bitbucket' => ['type' => 'string', 'nullable' => true, 'description' => 'Manual webhook secret for Bitbucket.'], 'manual_webhook_secret_gitea' => ['type' => 'string', 'nullable' => true, 'description' => 'Manual webhook secret for Gitea.'], 'docker_compose_location' => ['type' => 'string', 'description' => 'Docker compose location.'], 'docker_compose' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker compose content. Used for docker compose build pack.'], 'docker_compose_raw' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker compose raw content.'], 'docker_compose_domains' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker compose domains.'], 'docker_compose_custom_start_command' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker compose custom start command.'], 'docker_compose_custom_build_command' => ['type' => 'string', 'nullable' => true, 'description' => 'Docker compose custom build command.'], 'swarm_replicas' => ['type' => 'integer', 'nullable' => true, 'description' => 'Swarm replicas. Only used for swarm deployments.'], 'swarm_placement_constraints' => ['type' => 'string', 'nullable' => true, 'description' => 'Swarm placement constraints. Only used for swarm deployments.'], 'custom_docker_run_options' => ['type' => 'string', 'nullable' => true, 'description' => 'Custom docker run options.'], 'post_deployment_command' => ['type' => 'string', 'nullable' => true, 'description' => 'Post deployment command.'], 'post_deployment_command_container' => ['type' => 'string', 'nullable' => true, 'description' => 'Post deployment command container.'], 'pre_deployment_command' => ['type' => 'string', 'nullable' => true, 'description' => 'Pre deployment command.'], 'pre_deployment_command_container' => ['type' => 'string', 'nullable' => true, 'description' => 'Pre deployment command container.'], 'watch_paths' => ['type' => 'string', 'nullable' => true, 'description' => 'Watch paths.'], 'custom_healthcheck_found' => ['type' => 'boolean', 'description' => 'Custom healthcheck found.'], 'redirect' => ['type' => 'string', 'nullable' => true, 'description' => 'How to set redirect with Traefik / Caddy. www<->non-www.', 'enum' => ['www', 'non-www', 'both']], 'created_at' => ['type' => 'string', 'format' => 'date-time', 'description' => 'The date and time when the application was created.'], 'updated_at' => ['type' => 'string', 'format' => 'date-time', 'description' => 'The date and time when the application was last updated.'], 'deleted_at' => ['type' => 'string', 'format' => 'date-time', 'nullable' => true, 'description' => 'The date and time when the application was deleted.'], 'compose_parsing_version' => ['type' => 'string', 'description' => 'How Coolify parse the compose file.'], 'custom_nginx_configuration' => ['type' => 'string', 'nullable' => true, 'description' => 'Custom Nginx configuration base64 encoded.'], 'is_http_basic_auth_enabled' => ['type' => 'boolean', 'description' => 'HTTP Basic Authentication enabled.'], 'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'], 'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'], ] )] class Application extends BaseModel { use ClearsGlobalSearchCache, HasConfiguration, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes; private static $parserVersion = '5'; protected $guarded = []; protected $appends = ['server_status']; protected $casts = [ 'http_basic_auth_password' => 'encrypted', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', ]; protected static function booted() { static::addGlobalScope('withRelations', function ($builder) { $builder->withCount([ 'additional_servers', 'additional_networks', ]); }); static::saving(function ($application) { $payload = []; if ($application->isDirty('fqdn')) { if ($application->fqdn === '') { $application->fqdn = null; } $payload['fqdn'] = $application->fqdn; } if ($application->isDirty('install_command')) { $payload['install_command'] = str($application->install_command)->trim(); } if ($application->isDirty('build_command')) { $payload['build_command'] = str($application->build_command)->trim(); } if ($application->isDirty('start_command')) { $payload['start_command'] = str($application->start_command)->trim(); } if ($application->isDirty('base_directory')) { $payload['base_directory'] = str($application->base_directory)->trim(); } if ($application->isDirty('publish_directory')) { $payload['publish_directory'] = str($application->publish_directory)->trim(); } if ($application->isDirty('git_repository')) { $payload['git_repository'] = str($application->git_repository)->trim(); } if ($application->isDirty('git_branch')) { $payload['git_branch'] = str($application->git_branch)->trim(); } if ($application->isDirty('git_commit_sha')) { $payload['git_commit_sha'] = str($application->git_commit_sha)->trim(); } if ($application->isDirty('status')) { $payload['last_online_at'] = now(); } if ($application->isDirty('custom_nginx_configuration')) { if ($application->custom_nginx_configuration === '') { $payload['custom_nginx_configuration'] = null; } } if (count($payload) > 0) { $application->forceFill($payload); } // Buildpack switching cleanup logic if ($application->isDirty('build_pack')) { $originalBuildPack = $application->getOriginal('build_pack'); // Clear Docker Compose specific data when switching away from dockercompose if ($originalBuildPack === 'dockercompose') { $application->docker_compose_domains = null; $application->docker_compose_raw = null; // Remove SERVICE_FQDN_* and SERVICE_URL_* environment variables $application->environment_variables() ->where(function ($q) { $q->where('key', 'LIKE', 'SERVICE_FQDN_%') ->orWhere('key', 'LIKE', 'SERVICE_URL_%'); }) ->delete(); $application->environment_variables_preview() ->where(function ($q) { $q->where('key', 'LIKE', 'SERVICE_FQDN_%') ->orWhere('key', 'LIKE', 'SERVICE_URL_%'); }) ->delete(); } // Clear Dockerfile specific data when switching away from dockerfile if ($originalBuildPack === 'dockerfile') { $application->dockerfile = null; $application->dockerfile_location = null; $application->dockerfile_target_build = null; $application->custom_healthcheck_found = false; } } }); static::created(function ($application) { ApplicationSetting::create([ 'application_id' => $application->id, ]); $application->compose_parsing_version = self::$parserVersion; $application->save(); // Add default NIXPACKS_NODE_VERSION environment variable for Nixpacks applications if ($application->build_pack === 'nixpacks') { EnvironmentVariable::create([ 'key' => 'NIXPACKS_NODE_VERSION', 'value' => '22', 'is_multiline' => false, 'is_literal' => false, 'is_buildtime' => true, 'is_runtime' => false, 'is_preview' => false, 'resourceable_type' => Application::class, 'resourceable_id' => $application->id, ]); } }); static::forceDeleting(function ($application) { $application->update(['fqdn' => null]); $application->settings()->delete(); $application->persistentStorages()->delete(); $application->environment_variables()->delete(); $application->environment_variables_preview()->delete(); foreach ($application->scheduled_tasks as $task) { $task->delete(); } $application->tags()->detach(); $application->previews()->delete(); foreach ($application->deployment_queue as $deployment) { $deployment->delete(); } }); } public function customNetworkAliases(): Attribute { return Attribute::make( set: function ($value) { if (is_null($value) || $value === '') { return null; } // If it's already a JSON string, decode it if (is_string($value) && $this->isJson($value)) { $value = json_decode($value, true); } // If it's a string but not JSON, treat it as a comma-separated list if (is_string($value) && ! is_array($value)) { $value = explode(',', $value); } $value = collect($value) ->map(function ($alias) { if (is_string($alias)) { return str_replace(' ', '-', trim($alias)); } return null; }) ->filter() ->unique() // Remove duplicate values ->values() ->toArray(); return empty($value) ? null : json_encode($value); }, get: function ($value) { if (is_null($value)) { return null; } if (is_string($value) && $this->isJson($value)) { $decoded = json_decode($value, true); // Return as comma-separated string, not array return is_array($decoded) ? implode(',', $decoded) : $value; } return $value; } ); } /** * Get custom_network_aliases as an array */ public function customNetworkAliasesArray(): Attribute { return Attribute::make( get: function () { $value = $this->getRawOriginal('custom_network_aliases'); if (is_null($value)) { return null; } if (is_string($value) && $this->isJson($value)) { return json_decode($value, true); } return is_array($value) ? $value : []; } ); } /** * Check if a string is a valid JSON */ private function isJson($string) { if (! is_string($string)) { return false; } json_decode($string); return json_last_error() === JSON_ERROR_NONE; } public static function ownedByCurrentTeamAPI(int $teamId) { return Application::whereRelation('environment.project.team', 'id', $teamId)->orderBy('name'); } /** * Get query builder for applications owned by current team. * If you need all applications without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return Application::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all applications owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return Application::ownedByCurrentTeam()->get(); }); } public function getContainersToStop(Server $server, bool $previewDeployments = false): array { $containers = $previewDeployments ? getCurrentApplicationContainerStatus($server, $this->id, includePullrequests: true) : getCurrentApplicationContainerStatus($server, $this->id, 0); return $containers->pluck('Names')->toArray(); } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($this->build_pack === 'dockercompose') { $server = data_get($this, 'destination.server'); instant_remote_process(["cd {$this->dirOnServer()} && docker compose down -v"], $server, false); } else { if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } } public function deleteConnectedNetworks() { $uuid = $this->uuid; $server = data_get($this, 'destination.server'); instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); instant_remote_process(["docker network rm {$uuid}"], $server, false); } public function additional_servers() { return $this->belongsToMany(Server::class, 'additional_destinations') ->withPivot('standalone_docker_id', 'status'); } public function additional_networks() { return $this->belongsToMany(StandaloneDocker::class, 'additional_destinations') ->withPivot('server_id', 'status'); } public function is_public_repository(): bool { if (data_get($this, 'source.is_public')) { return true; } return false; } public function is_github_based(): bool { if (data_get($this, 'source')) { return true; } return false; } public function isForceHttpsEnabled() { return data_get($this, 'settings.is_force_https_enabled', false); } public function isStripprefixEnabled() { return data_get($this, 'settings.is_stripprefix_enabled', true); } public function isGzipEnabled() { return data_get($this, 'settings.is_gzip_enabled', true); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.application.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'application_uuid' => data_get($this, 'uuid'), ]); } return null; } public function taskLink($task_uuid) { if (data_get($this, 'environment.project.uuid')) { $route = route('project.application.scheduled-tasks', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'application_uuid' => data_get($this, 'uuid'), 'task_uuid' => $task_uuid, ]); $settings = instanceSettings(); if (data_get($settings, 'fqdn')) { $url = Url::fromString($route); $url = $url->withPort(null); $fqdn = data_get($settings, 'fqdn'); $fqdn = str_replace(['http://', 'https://'], '', $fqdn); $url = $url->withHost($fqdn); return $url->__toString(); } return $route; } return null; } public function settings() { return $this->hasOne(ApplicationSetting::class); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function type() { return 'application'; } public function publishDirectory(): Attribute { return Attribute::make( set: fn ($value) => $value ? '/'.ltrim($value, '/') : null, ); } public function gitBranchLocation(): Attribute { return Attribute::make( get: function () { $base_dir = $this->base_directory ?? '/'; if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) { if (str($this->git_repository)->contains('bitbucket')) { return "{$this->source->html_url}/{$this->git_repository}/src/{$this->git_branch}{$base_dir}"; } return "{$this->source->html_url}/{$this->git_repository}/tree/{$this->git_branch}{$base_dir}"; } // Convert the SSH URL to HTTPS URL if (strpos($this->git_repository, 'git@') === 0) { $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository); if (str($this->git_repository)->contains('bitbucket')) { return "https://{$git_repository}/src/{$this->git_branch}{$base_dir}"; } return "https://{$git_repository}/tree/{$this->git_branch}{$base_dir}"; } return $this->git_repository; } ); } public function gitWebhook(): Attribute { return Attribute::make( get: function () { if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) { return "{$this->source->html_url}/{$this->git_repository}/settings/hooks"; } // Convert the SSH URL to HTTPS URL if (strpos($this->git_repository, 'git@') === 0) { $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository); return "https://{$git_repository}/settings/hooks"; } return $this->git_repository; } ); } public function gitCommits(): Attribute { return Attribute::make( get: function () { if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) { return "{$this->source->html_url}/{$this->git_repository}/commits/{$this->git_branch}"; } // Convert the SSH URL to HTTPS URL if (strpos($this->git_repository, 'git@') === 0) { $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository); return "https://{$git_repository}/commits/{$this->git_branch}"; } return $this->git_repository; } ); } public function gitCommitLink($link): string { if (! is_null(data_get($this, 'source.html_url')) && ! is_null(data_get($this, 'git_repository')) && ! is_null(data_get($this, 'git_branch'))) { if (str($this->source->html_url)->contains('bitbucket')) { return "{$this->source->html_url}/{$this->git_repository}/commits/{$link}"; } return "{$this->source->html_url}/{$this->git_repository}/commit/{$link}"; } if (str($this->git_repository)->contains('bitbucket')) { $git_repository = str_replace('.git', '', $this->git_repository); $url = Url::fromString($git_repository); $url = $url->withUserInfo(''); $url = $url->withPath($url->getPath().'/commits/'.$link); return $url->__toString(); } if (strpos($this->git_repository, 'git@') === 0) { $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository); if (data_get($this, 'source.html_url')) { return "{$this->source->html_url}/{$git_repository}/commit/{$link}"; } return "{$git_repository}/commit/{$link}"; } return $this->git_repository; } public function dockerfileLocation(): Attribute { return Attribute::make( set: function ($value) { if (is_null($value) || $value === '') { return '/Dockerfile'; } else { if ($value !== '/') { return Str::start(Str::replaceEnd('/', '', $value), '/'); } return Str::start($value, '/'); } } ); } public function dockerComposeLocation(): Attribute { return Attribute::make( set: function ($value) { if (is_null($value) || $value === '') { return '/docker-compose.yaml'; } else { if ($value !== '/') { return Str::start(Str::replaceEnd('/', '', $value), '/'); } return Str::start($value, '/'); } } ); } public function baseDirectory(): Attribute { return Attribute::make( set: fn ($value) => '/'.ltrim($value, '/'), ); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } public function isRunning() { return (bool) str($this->status)->startsWith('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function realStatus() { return $this->getRawOriginal('status'); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { // Check main server infrastructure health $main_server_functional = $this->destination?->server?->isFunctional() ?? false; if (! $main_server_functional) { return false; } // Check additional servers infrastructure health (not container status!) if ($this->relationLoaded('additional_servers') && $this->additional_servers->count() > 0) { foreach ($this->additional_servers as $server) { if (! $server->isFunctional()) { return false; // Real server infrastructure problem } } } return true; } ); } public function status(): Attribute { return Attribute::make( set: function ($value) { if ($this->additional_servers->count() === 0) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; } else { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; } }, get: function ($value) { if ($this->additional_servers->count() === 0) { // running (healthy) if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; } else { $complex_status = null; $complex_health = null; $complex_status = $main_server_status = str($value)->before(':')->value(); $complex_health = $main_server_health = str($value)->after(':')->value() ?? 'unhealthy'; $additional_servers_status = $this->additional_servers->pluck('pivot.status'); foreach ($additional_servers_status as $status) { $server_status = str($status)->before(':')->value(); $server_health = str($status)->after(':')->value() ?? 'unhealthy'; if ($main_server_status !== $server_status) { $complex_status = 'degraded'; } if ($main_server_health !== $server_health) { $complex_health = 'unhealthy'; } } return "$complex_status:$complex_health"; } }, ); } public function customNginxConfiguration(): Attribute { return Attribute::make( set: fn ($value) => base64_encode($value), get: fn ($value) => base64_decode($value), ); } public function portsExposesArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_exposes) ? [] : explode(',', $this->ports_exposes) ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function serviceType() { $found = str(collect(SPECIFIC_SERVICES)->filter(function ($service) { return str($this->image)->before(':')->value() === $service; })->first()); if ($found->isNotEmpty()) { return $found; } return null; } public function main_port() { return $this->settings->is_static ? [80] : $this->ports_exposes_array; } public function detectPortFromEnvironment(?bool $isPreview = false): ?int { $envVars = $isPreview ? $this->environment_variables_preview : $this->environment_variables; $portVar = $envVars->firstWhere('key', 'PORT'); if ($portVar && $portVar->real_value) { $portValue = trim($portVar->real_value); if (is_numeric($portValue)) { return (int) $portValue; } } return null; } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', false); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', false) ->where('key', 'not like', 'NIXPACKS_%'); } public function nixpacks_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', false) ->where('key', 'like', 'NIXPACKS_%'); } public function environment_variables_preview() { return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', true) ->orderByRaw(" CASE WHEN is_required = true THEN 1 WHEN LOWER(key) LIKE 'service_%' THEN 2 ELSE 3 END, LOWER(key) ASC "); } public function runtime_environment_variables_preview() { return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', true) ->where('key', 'not like', 'NIXPACKS_%'); } public function nixpacks_environment_variables_preview() { return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', true) ->where('key', 'like', 'NIXPACKS_%'); } public function scheduled_tasks(): HasMany { return $this->hasMany(ScheduledTask::class)->orderBy('name', 'asc'); } public function private_key() { return $this->belongsTo(PrivateKey::class); } public function environment() { return $this->belongsTo(Environment::class); } public function previews() { return $this->hasMany(ApplicationPreview::class)->orderBy('pull_request_id', 'desc'); } public function deployment_queue() { return $this->hasMany(ApplicationDeploymentQueue::class); } public function destination() { return $this->morphTo(); } public function source() { return $this->morphTo(); } public function isDeploymentInprogress() { $deployments = ApplicationDeploymentQueue::where('application_id', $this->id)->whereIn('status', [ApplicationDeploymentStatus::IN_PROGRESS, ApplicationDeploymentStatus::QUEUED])->count(); if ($deployments > 0) { return true; } return false; } public function get_last_successful_deployment() { return ApplicationDeploymentQueue::where('application_id', $this->id)->where('status', ApplicationDeploymentStatus::FINISHED)->where('pull_request_id', 0)->orderBy('created_at', 'desc')->first(); } public function get_last_days_deployments() { return ApplicationDeploymentQueue::where('application_id', $this->id)->where('created_at', '>=', now()->subDays(7))->orderBy('created_at', 'desc')->get(); } public function deployments(int $skip = 0, int $take = 10, ?string $pullRequestId = null) { $deployments = ApplicationDeploymentQueue::where('application_id', $this->id)->orderBy('created_at', 'desc'); if ($pullRequestId) { $deployments = $deployments->where('pull_request_id', $pullRequestId); } $count = $deployments->count(); $deployments = $deployments->skip($skip)->take($take)->get(); return [ 'count' => $count, 'deployments' => $deployments, ]; } public function get_deployment(string $deployment_uuid) { return Activity::where('subject_id', $this->id)->where('properties->type_uuid', '=', $deployment_uuid)->first(); } public function isDeployable(): bool { if ($this->settings->is_auto_deploy_enabled) { return true; } return false; } public function isPRDeployable(): bool { if ($this->settings->is_preview_deployments_enabled) { return true; } return false; } public function deploymentType() { $privateKeyId = data_get($this, 'private_key_id'); // Real private key (id > 0) always takes precedence if ($privateKeyId !== null && $privateKeyId > 0) { return 'deploy_key'; } // GitHub/GitLab App source if (data_get($this, 'source')) { return 'source'; } // Localhost key (id = 0) when no source is configured if ($privateKeyId === 0) { return 'deploy_key'; } return 'other'; } public function could_set_build_commands(): bool { if ($this->build_pack === 'nixpacks') { return true; } return false; } public function git_based(): bool { if ($this->dockerfile) { return false; } if ($this->build_pack === 'dockerimage') { return false; } return true; } public function isHealthcheckDisabled(): bool { if (data_get($this, 'health_check_enabled') === false) { return true; } return false; } public function workdir() { return application_configuration_dir()."/{$this->uuid}"; } public function isLogDrainEnabled() { return data_get($this, 'settings.is_log_drain_enabled', false); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = base64_encode($this->fqdn.$this->git_repository.$this->git_branch.$this->git_commit_sha.$this->build_pack.$this->static_image.$this->install_command.$this->build_command.$this->start_command.$this->ports_exposes.$this->ports_mappings.$this->custom_network_aliases.$this->base_directory.$this->publish_directory.$this->dockerfile.$this->dockerfile_location.$this->custom_labels.$this->custom_docker_run_options.$this->dockerfile_target_build.$this->redirect.$this->custom_nginx_configuration.$this->settings->use_build_secrets.$this->settings->inject_build_args_to_dockerfile.$this->settings->include_source_commit_in_build); if ($this->pull_request_id === 0 || $this->pull_request_id === null) { $newConfigHash .= json_encode($this->environment_variables()->get(['value', 'is_multiline', 'is_literal', 'is_buildtime', 'is_runtime'])->sort()); } else { $newConfigHash .= json_encode($this->environment_variables_preview->get(['value', 'is_multiline', 'is_literal', 'is_buildtime', 'is_runtime'])->sort()); } $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function customRepository() { return convertGitUrl($this->git_repository, $this->deploymentType(), $this->source); } public function generateBaseDir(string $uuid) { return "/artifacts/{$uuid}"; } public function dirOnServer() { return application_configuration_dir()."/{$this->uuid}"; } public function setGitImportSettings(string $deployment_uuid, string $git_clone_command, bool $public = false, ?string $commit = null, ?string $git_ssh_command = null) { $baseDir = $this->generateBaseDir($deployment_uuid); $escapedBaseDir = escapeshellarg($baseDir); $isShallowCloneEnabled = $this->settings?->is_git_shallow_clone_enabled ?? false; // Use the full GIT_SSH_COMMAND (including -i for SSH key and port options) when provided, // so that git fetch, submodule update, and lfs pull can authenticate the same way as git clone. $sshCommand = $git_ssh_command ?? 'GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"'; // Use the explicitly passed commit (e.g. from rollback), falling back to the application's git_commit_sha. // Invalid refs will cause the git checkout/fetch command to fail on the remote server. $commitToUse = $commit ?? $this->git_commit_sha; if ($commitToUse !== 'HEAD') { $escapedCommit = escapeshellarg($commitToUse); // If shallow clone is enabled and we need a specific commit, // we need to fetch that specific commit with depth=1 if ($isShallowCloneEnabled) { $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$sshCommand} git fetch --depth=1 origin {$escapedCommit} && git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1"; } else { $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$sshCommand} git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1"; } } if ($this->settings->is_git_submodules_enabled) { // Check if .gitmodules file exists before running submodule commands $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && if [ -f .gitmodules ]; then"; if ($public) { $git_clone_command = "{$git_clone_command} sed -i \"s#git@\(.*\):#https://\\1/#g\" {$escapedBaseDir}/.gitmodules || true &&"; } // Add shallow submodules flag if shallow clone is enabled $submoduleFlags = $isShallowCloneEnabled ? '--depth=1' : ''; $git_clone_command = "{$git_clone_command} git submodule sync && {$sshCommand} git submodule update --init --recursive {$submoduleFlags}; fi"; } if ($this->settings->is_git_lfs_enabled) { $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$sshCommand} git lfs pull"; } return $git_clone_command; } public function getGitRemoteStatus(string $deployment_uuid) { try { ['commands' => $lsRemoteCommand] = $this->generateGitLsRemoteCommands(deployment_uuid: $deployment_uuid, exec_in_docker: false); instant_remote_process([$lsRemoteCommand], $this->destination->server, true); return [ 'is_accessible' => true, 'error' => null, ]; } catch (\RuntimeException $ex) { return [ 'is_accessible' => false, 'error' => $ex->getMessage(), ]; } } public function generateGitLsRemoteCommands(string $deployment_uuid, bool $exec_in_docker = true) { $branch = $this->git_branch; ['repository' => $customRepository, 'port' => $customPort] = $this->customRepository(); $commands = collect([]); $base_command = 'git ls-remote'; if ($this->deploymentType() === 'source') { $source_html_url = data_get($this, 'source.html_url'); $url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL)); $source_html_url_host = $url['host']; $source_html_url_scheme = $url['scheme']; if ($this->source->getMorphClass() == 'App\Models\GithubApp') { $escapedCustomRepository = escapeshellarg($customRepository); if ($this->source->is_public) { $escapedRepoUrl = escapeshellarg("{$this->source->html_url}/{$customRepository}"); $fullRepoUrl = "{$this->source->html_url}/{$customRepository}"; $base_command = "{$base_command} {$escapedRepoUrl}"; } else { $github_access_token = generateGithubInstallationToken($this->source); $encodedToken = rawurlencode($github_access_token); if ($exec_in_docker) { $repoUrl = "$source_html_url_scheme://x-access-token:$encodedToken@$source_html_url_host/{$customRepository}.git"; $escapedRepoUrl = escapeshellarg($repoUrl); $base_command = "{$base_command} {$escapedRepoUrl}"; $fullRepoUrl = $repoUrl; } else { $repoUrl = "$source_html_url_scheme://x-access-token:$encodedToken@$source_html_url_host/{$customRepository}"; $escapedRepoUrl = escapeshellarg($repoUrl); $base_command = "{$base_command} {$escapedRepoUrl}"; $fullRepoUrl = $repoUrl; } } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $base_command)); } else { $commands->push($base_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } if ($this->source->getMorphClass() === \App\Models\GitlabApp::class) { $gitlabSource = $this->source; $private_key = data_get($gitlabSource, 'privateKey.private_key'); if ($private_key) { $fullRepoUrl = $customRepository; $private_key = base64_encode($private_key); $gitlabPort = $gitlabSource->custom_port ?? 22; $escapedCustomRepository = str_replace("'", "'\\''", $customRepository); $base_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$gitlabPort} -o Port={$gitlabPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$base_command} '{$escapedCustomRepository}'"; if ($exec_in_docker) { $commands = collect([ executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'), executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"), executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'), ]); } else { $commands = collect([ 'mkdir -p /root/.ssh', "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null", 'chmod 600 /root/.ssh/id_rsa', ]); } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $base_command)); } else { $commands->push($base_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } // GitLab source without private key — use URL as-is (supports user-embedded basic auth) $fullRepoUrl = $customRepository; $escapedCustomRepository = escapeshellarg($customRepository); $base_command = "{$base_command} {$escapedCustomRepository}"; if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $base_command)); } else { $commands->push($base_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } } if ($this->deploymentType() === 'deploy_key') { $fullRepoUrl = $customRepository; $private_key = data_get($this, 'private_key.private_key'); if (is_null($private_key)) { throw new RuntimeException('Private key not found. Please add a private key to the application and try again.'); } $private_key = base64_encode($private_key); // When used with executeInDocker (which uses bash -c '...'), we need to escape for bash context // Replace ' with '\'' to safely escape within single-quoted bash strings $escapedCustomRepository = str_replace("'", "'\\''", $customRepository); $base_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$base_command} '{$escapedCustomRepository}'"; if ($exec_in_docker) { $commands = collect([ executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'), executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"), executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'), ]); } else { $commands = collect([ 'mkdir -p /root/.ssh', "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null", 'chmod 600 /root/.ssh/id_rsa', ]); } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $base_command)); } else { $commands->push($base_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } if ($this->deploymentType() === 'other') { $fullRepoUrl = $customRepository; $escapedCustomRepository = escapeshellarg($customRepository); $base_command = "{$base_command} {$escapedCustomRepository}"; if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $base_command)); } else { $commands->push($base_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } } public function generateGitImportCommands(string $deployment_uuid, int $pull_request_id = 0, ?string $git_type = null, bool $exec_in_docker = true, bool $only_checkout = false, ?string $custom_base_dir = null, ?string $commit = null) { $branch = $this->git_branch; ['repository' => $customRepository, 'port' => $customPort] = $this->customRepository(); $baseDir = $custom_base_dir ?? $this->generateBaseDir($deployment_uuid); // Escape shell arguments for safety to prevent command injection $escapedBranch = escapeshellarg($branch); $escapedBaseDir = escapeshellarg($baseDir); $commands = collect([]); // Check if shallow clone is enabled $isShallowCloneEnabled = $this->settings?->is_git_shallow_clone_enabled ?? false; $depthFlag = $isShallowCloneEnabled ? ' --depth=1' : ''; $submoduleFlags = ''; if ($this->settings->is_git_submodules_enabled) { $submoduleFlags = ' --recurse-submodules'; if ($isShallowCloneEnabled) { $submoduleFlags .= ' --shallow-submodules'; } } $git_clone_command = "git clone{$depthFlag}{$submoduleFlags} -b {$escapedBranch}"; if ($only_checkout) { $git_clone_command = "git clone{$depthFlag}{$submoduleFlags} --no-checkout -b {$escapedBranch}"; } if ($pull_request_id !== 0) { $pr_branch_name = "pr-{$pull_request_id}-coolify"; } if ($this->deploymentType() === 'source') { $source_html_url = data_get($this, 'source.html_url'); $url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL)); $source_html_url_host = $url['host']; $source_html_url_scheme = $url['scheme']; if ($this->source->getMorphClass() === \App\Models\GithubApp::class) { if ($this->source->is_public) { $fullRepoUrl = "{$this->source->html_url}/{$customRepository}"; $escapedRepoUrl = escapeshellarg("{$this->source->html_url}/{$customRepository}"); $git_clone_command = "{$git_clone_command} {$escapedRepoUrl} {$escapedBaseDir}"; if (! $only_checkout) { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true, commit: $commit); } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $git_clone_command)); } else { $commands->push($git_clone_command); } } else { $github_access_token = generateGithubInstallationToken($this->source); $encodedToken = rawurlencode($github_access_token); if ($exec_in_docker) { $repoUrl = "$source_html_url_scheme://x-access-token:$encodedToken@$source_html_url_host/{$customRepository}.git"; $escapedRepoUrl = escapeshellarg($repoUrl); $git_clone_command = "{$git_clone_command} {$escapedRepoUrl} {$escapedBaseDir}"; $fullRepoUrl = $repoUrl; } else { $repoUrl = "$source_html_url_scheme://x-access-token:$encodedToken@$source_html_url_host/{$customRepository}"; $escapedRepoUrl = escapeshellarg($repoUrl); $git_clone_command = "{$git_clone_command} {$escapedRepoUrl} {$escapedBaseDir}"; $fullRepoUrl = $repoUrl; } if (! $only_checkout) { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: false, commit: $commit); } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $git_clone_command)); } else { $commands->push($git_clone_command); } } if ($pull_request_id !== 0) { $branch = "pull/{$pull_request_id}/head:$pr_branch_name"; $git_checkout_command = $this->buildGitCheckoutCommand($pr_branch_name); $escapedPrBranch = escapeshellarg($branch); if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "cd {$escapedBaseDir} && git fetch origin {$escapedPrBranch} && $git_checkout_command")); } else { $commands->push("cd {$escapedBaseDir} && git fetch origin {$escapedPrBranch} && $git_checkout_command"); } } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } if ($this->source->getMorphClass() === \App\Models\GitlabApp::class) { $gitlabSource = $this->source; $private_key = data_get($gitlabSource, 'privateKey.private_key'); if ($private_key) { $fullRepoUrl = $customRepository; $private_key = base64_encode($private_key); $gitlabPort = $gitlabSource->custom_port ?? 22; $escapedCustomRepository = escapeshellarg($customRepository); $gitlabSshCommand = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$gitlabPort} -o Port={$gitlabPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\""; $git_clone_command_base = "{$gitlabSshCommand} {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}"; if ($only_checkout) { $git_clone_command = $git_clone_command_base; } else { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit, git_ssh_command: $gitlabSshCommand); } if ($exec_in_docker) { $commands = collect([ executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'), executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"), executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'), ]); } else { $commands = collect([ 'mkdir -p /root/.ssh', "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null", 'chmod 600 /root/.ssh/id_rsa', ]); } if ($pull_request_id !== 0) { $branch = "merge-requests/{$pull_request_id}/head:$pr_branch_name"; if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$gitlabPort} -o Port={$gitlabPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $git_clone_command)); } else { $commands->push($git_clone_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } // GitLab source without private key — use URL as-is (supports user-embedded basic auth) $fullRepoUrl = $customRepository; $escapedCustomRepository = escapeshellarg($customRepository); $git_clone_command = "{$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}"; $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true, commit: $commit); if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $git_clone_command)); } else { $commands->push($git_clone_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } } if ($this->deploymentType() === 'deploy_key') { $fullRepoUrl = $customRepository; $private_key = data_get($this, 'private_key.private_key'); if (is_null($private_key)) { throw new RuntimeException('Private key not found. Please add a private key to the application and try again.'); } $private_key = base64_encode($private_key); $escapedCustomRepository = escapeshellarg($customRepository); $deployKeySshCommand = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\""; $git_clone_command_base = "{$deployKeySshCommand} {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}"; if ($only_checkout) { $git_clone_command = $git_clone_command_base; } else { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit, git_ssh_command: $deployKeySshCommand); } if ($exec_in_docker) { $commands = collect([ executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'), executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"), executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'), ]); } else { $commands = collect([ 'mkdir -p /root/.ssh', "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null", 'chmod 600 /root/.ssh/id_rsa', ]); } if ($pull_request_id !== 0) { if ($git_type === 'gitlab') { $branch = "merge-requests/{$pull_request_id}/head:$pr_branch_name"; if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'github' || $git_type === 'gitea') { $branch = "pull/{$pull_request_id}/head:$pr_branch_name"; if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'bitbucket') { if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" ".$this->buildGitCheckoutCommand($commit); } } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $git_clone_command)); } else { $commands->push($git_clone_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } if ($this->deploymentType() === 'other') { $fullRepoUrl = $customRepository; $escapedCustomRepository = escapeshellarg($customRepository); $git_clone_command = "{$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}"; $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true, commit: $commit); if ($pull_request_id !== 0) { if ($git_type === 'gitlab') { $branch = "merge-requests/{$pull_request_id}/head:$pr_branch_name"; if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'github' || $git_type === 'gitea') { $branch = "pull/{$pull_request_id}/head:$pr_branch_name"; if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'bitbucket') { if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } $git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" ".$this->buildGitCheckoutCommand($commit); } } if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, $git_clone_command)); } else { $commands->push($git_clone_command); } return [ 'commands' => $commands->implode(' && '), 'branch' => $branch, 'fullRepoUrl' => $fullRepoUrl, ]; } } public function oldRawParser() { try { $yaml = Yaml::parse($this->docker_compose_raw); } catch (\Exception $e) { throw new \RuntimeException($e->getMessage()); } $services = data_get($yaml, 'services'); $commands = collect([]); $services = collect($services)->map(function ($service) use ($commands) { $serviceVolumes = collect(data_get($service, 'volumes', [])); if ($serviceVolumes->count() > 0) { foreach ($serviceVolumes as $volume) { $workdir = $this->workdir(); $type = null; $source = null; if (is_string($volume)) { $source = str($volume)->before(':'); if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) { $type = str('bind'); } } elseif (is_array($volume)) { $type = data_get_str($volume, 'type'); $source = data_get_str($volume, 'source'); } if ($type?->value() === 'bind') { if ($source->value() === '/var/run/docker.sock') { continue; } if ($source->value() === '/tmp' || $source->value() === '/tmp/') { continue; } if ($source->startsWith('.')) { $source = $source->after('.'); $source = $workdir.$source; } $commands->push("mkdir -p $source > /dev/null 2>&1 || true"); } } } $labels = collect(data_get($service, 'labels', [])); if (! $labels->contains('coolify.managed')) { $labels->push('coolify.managed=true'); } if (! $labels->contains('coolify.applicationId')) { $labels->push('coolify.applicationId='.$this->id); } if (! $labels->contains('coolify.type')) { $labels->push('coolify.type=application'); } data_set($service, 'labels', $labels->toArray()); return $service; }); data_set($yaml, 'services', $services->toArray()); $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); instant_remote_process($commands, $this->destination->server, false); } public function parse(int $pull_request_id = 0, ?int $preview_id = null, ?string $commit = null) { if ((int) $this->compose_parsing_version >= 3) { return applicationParser($this, $pull_request_id, $preview_id, $commit); } elseif ($this->docker_compose_raw) { return parseDockerComposeFile(resource: $this, isNew: false, pull_request_id: $pull_request_id, preview_id: $preview_id); } else { return collect([]); } } public function loadComposeFile($isInit = false, ?string $restoreBaseDirectory = null, ?string $restoreDockerComposeLocation = null) { // Use provided restore values or capture current values as fallback $initialDockerComposeLocation = $restoreDockerComposeLocation ?? $this->docker_compose_location; $initialBaseDirectory = $restoreBaseDirectory ?? $this->base_directory; if ($isInit && $this->docker_compose_raw) { return; } $uuid = new Cuid2; ['commands' => $cloneCommand] = $this->generateGitImportCommands(deployment_uuid: $uuid, only_checkout: true, exec_in_docker: false, custom_base_dir: '.'); $workdir = rtrim($this->base_directory, '/'); $composeFile = $this->docker_compose_location; $fileList = collect([".$workdir$composeFile"]); $gitRemoteStatus = $this->getGitRemoteStatus(deployment_uuid: $uuid); if (! $gitRemoteStatus['is_accessible']) { throw new \RuntimeException("Failed to read Git source:\n\n{$gitRemoteStatus['error']}"); } $getGitVersion = instant_remote_process(['git --version'], $this->destination->server, false); $gitVersion = str($getGitVersion)->explode(' ')->last(); if (version_compare($gitVersion, '2.35.1', '<')) { $fileList = $fileList->map(function ($file) { $parts = explode('/', trim($file, '.')); $paths = collect(); $currentPath = ''; foreach ($parts as $part) { $currentPath .= ($currentPath ? '/' : '').$part; if (str($currentPath)->isNotEmpty()) { $paths->push($currentPath); } } return $paths; })->flatten()->unique()->values(); $commands = collect([ "rm -rf /tmp/{$uuid}", "mkdir -p /tmp/{$uuid}", "cd /tmp/{$uuid}", $cloneCommand, 'git sparse-checkout init', "git sparse-checkout set {$fileList->implode(' ')}", 'git read-tree -mu HEAD', "cat .$workdir$composeFile", ]); } else { $commands = collect([ "rm -rf /tmp/{$uuid}", "mkdir -p /tmp/{$uuid}", "cd /tmp/{$uuid}", $cloneCommand, 'git sparse-checkout init --cone', "git sparse-checkout set {$fileList->implode(' ')}", 'git read-tree -mu HEAD', "cat .$workdir$composeFile", ]); } try { $composeFileContent = instant_remote_process($commands, $this->destination->server); } catch (\Exception $e) { // Restore original values on failure only $this->docker_compose_location = $initialDockerComposeLocation; $this->base_directory = $initialBaseDirectory; $this->save(); if (str($e->getMessage())->contains('No such file')) { throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile

Check if you used the right extension (.yaml or .yml) in the compose file name."); } if (str($e->getMessage())->contains('fatal: repository') && str($e->getMessage())->contains('does not exist')) { if ($this->deploymentType() === 'deploy_key') { throw new \RuntimeException('Your deploy key does not have access to the repository. Please check your deploy key and try again.'); } throw new \RuntimeException('Repository does not exist. Please check your repository URL and try again.'); } throw new \RuntimeException($e->getMessage()); } finally { // Cleanup only - restoration happens in catch block $commands = collect([ "rm -rf /tmp/{$uuid}", ]); instant_remote_process($commands, $this->destination->server, false); } if ($composeFileContent) { $this->docker_compose_raw = $composeFileContent; $this->save(); $parsedServices = $this->parse(); if ($this->docker_compose_domains) { $decoded = json_decode($this->docker_compose_domains, true); $json = collect(is_array($decoded) ? $decoded : []); $normalized = collect(); foreach ($json as $key => $value) { $normalizedKey = (string) str($key)->replace('-', '_')->replace('.', '_'); $normalized->put($normalizedKey, $value); } $json = $normalized; $services = collect(data_get($parsedServices, 'services', [])); foreach ($services as $name => $service) { if (str($name)->contains('-') || str($name)->contains('.')) { $replacedName = str($name)->replace('-', '_')->replace('.', '_'); $services->put((string) $replacedName, $service); $services->forget((string) $name); } } $names = collect($services)->keys()->toArray(); $jsonNames = $json->keys()->toArray(); $diff = array_diff($jsonNames, $names); $json = $json->filter(function ($value, $key) use ($diff) { return ! in_array($key, $diff); }); if ($json) { $this->docker_compose_domains = json_encode($json); } else { $this->docker_compose_domains = null; } $this->save(); } return [ 'parsedServices' => $parsedServices, 'initialDockerComposeLocation' => $this->docker_compose_location, ]; } else { // Restore original values before throwing $this->docker_compose_location = $initialDockerComposeLocation; $this->base_directory = $initialBaseDirectory; $this->save(); throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile

Check if you used the right extension (.yaml or .yml) in the compose file name."); } } public function parseContainerLabels(?ApplicationPreview $preview = null) { $customLabels = data_get($this, 'custom_labels'); if (! $customLabels) { return; } if (base64_encode(base64_decode($customLabels, true)) !== $customLabels) { $this->custom_labels = str($customLabels)->replace(',', "\n"); $this->custom_labels = base64_encode($customLabels); } $customLabels = base64_decode($this->custom_labels); if (mb_detect_encoding($customLabels, 'UTF-8', true) === false) { $customLabels = str(implode('|coolify|', generateLabelsApplication($this, $preview)))->replace('|coolify|', "\n"); } $this->custom_labels = base64_encode($customLabels); $this->save(); return $customLabels; } public function fqdns(): Attribute { return Attribute::make( get: fn () => is_null($this->fqdn) ? [] : explode(',', $this->fqdn), ); } protected function buildGitCheckoutCommand($target): string { $escapedTarget = escapeshellarg($target); $command = "git checkout {$escapedTarget}"; if ($this->settings->is_git_submodules_enabled) { $command .= ' && git submodule update --init --recursive'; } return $command; } private function parseWatchPaths($value) { if ($value) { $watch_paths = collect(explode("\n", $value)) ->map(function (string $path): string { // Trim whitespace $path = trim($path); if (str_starts_with($path, '!')) { $negation = '!'; $pathWithoutNegation = substr($path, 1); $pathWithoutNegation = ltrim(trim($pathWithoutNegation), '/'); return $negation.$pathWithoutNegation; } return ltrim($path, '/'); }) ->filter(function (string $path): bool { return strlen($path) > 0; }); return trim($watch_paths->implode("\n")); } } public function watchPaths(): Attribute { return Attribute::make( set: function ($value) { if ($value) { return $this->parseWatchPaths($value); } } ); } public function matchWatchPaths(Collection $modified_files, ?Collection $watch_paths): Collection { return self::matchPaths($modified_files, $watch_paths); } /** * Static method to match paths against watch patterns with negation support * Uses order-based matching: last matching pattern wins */ public static function matchPaths(Collection $modified_files, ?Collection $watch_paths): Collection { if (is_null($watch_paths) || $watch_paths->isEmpty()) { return collect([]); } return $modified_files->filter(function ($file) use ($watch_paths) { $shouldInclude = null; // null means no patterns matched // Process patterns in order - last match wins foreach ($watch_paths as $pattern) { $pattern = trim($pattern); if (empty($pattern)) { continue; } $isExclusion = str_starts_with($pattern, '!'); $matchPattern = $isExclusion ? substr($pattern, 1) : $pattern; if (self::globMatch($matchPattern, $file)) { // This pattern matches - it determines the current state $shouldInclude = ! $isExclusion; } } // If no patterns matched and we only have exclusion patterns, include by default if ($shouldInclude === null) { // Check if we only have exclusion patterns $hasInclusionPatterns = $watch_paths->contains(fn ($p) => ! str_starts_with(trim($p), '!')); return ! $hasInclusionPatterns; } return $shouldInclude; })->values(); } /** * Check if a path matches a glob pattern * Supports: *, **, ?, [abc], [!abc] */ public static function globMatch(string $pattern, string $path): bool { $regex = self::globToRegex($pattern); return preg_match($regex, $path) === 1; } /** * Convert a glob pattern to a regular expression */ public static function globToRegex(string $pattern): string { $regex = ''; $inGroup = false; $chars = str_split($pattern); $len = count($chars); for ($i = 0; $i < $len; $i++) { $c = $chars[$i]; switch ($c) { case '*': // Check for ** if ($i + 1 < $len && $chars[$i + 1] === '*') { // ** matches any number of directories $regex .= '.*'; $i++; // Skip next * // Skip optional / if ($i + 1 < $len && $chars[$i + 1] === '/') { $i++; } } else { // * matches anything except / $regex .= '[^/]*'; } break; case '?': // ? matches any single character except / $regex .= '[^/]'; break; case '[': // Character class $inGroup = true; $regex .= '['; // Check for negation if ($i + 1 < $len && ($chars[$i + 1] === '!' || $chars[$i + 1] === '^')) { $regex .= '^'; $i++; } break; case ']': if ($inGroup) { $inGroup = false; $regex .= ']'; } else { $regex .= preg_quote($c, '#'); } break; case '.': case '(': case ')': case '+': case '{': case '}': case '$': case '^': case '|': case '\\': // Escape regex special characters $regex .= '\\'.$c; break; default: $regex .= $c; break; } } // Wrap in delimiters and anchors return '#^'.$regex.'$#'; } public function normalizeWatchPaths(): void { if (is_null($this->watch_paths)) { return; } $normalized = $this->parseWatchPaths($this->watch_paths); if ($normalized !== $this->watch_paths) { $this->watch_paths = $normalized; $this->save(); } } public function isWatchPathsTriggered(Collection $modified_files): bool { if (is_null($this->watch_paths)) { return false; } $this->normalizeWatchPaths(); $watch_paths = collect(explode("\n", $this->watch_paths)); if ($watch_paths->isEmpty()) { return false; } $matches = $this->matchWatchPaths($modified_files, $watch_paths); return $matches->count() > 0; } public function getFilesFromServer(bool $isInit = false) { getFilesystemVolumesFromServer($this, $isInit); } public function parseHealthcheckFromDockerfile($dockerfile, bool $isInit = false) { $dockerfile = str($dockerfile)->trim()->explode("\n"); $hasHealthcheck = str($dockerfile)->contains('HEALTHCHECK'); // Always check if healthcheck was removed, regardless of health_check_enabled setting if (! $hasHealthcheck && $this->custom_healthcheck_found) { // HEALTHCHECK was removed from Dockerfile, reset to defaults $this->custom_healthcheck_found = false; $this->health_check_interval = 5; $this->health_check_timeout = 5; $this->health_check_retries = 10; $this->health_check_start_period = 5; $this->save(); return; } if ($hasHealthcheck && ($this->isHealthcheckDisabled() || $isInit)) { $healthcheckCommand = null; $lines = $dockerfile->toArray(); foreach ($lines as $line) { $trimmedLine = trim($line); if (str_starts_with($trimmedLine, 'HEALTHCHECK')) { $healthcheckCommand .= trim($trimmedLine, '\\ '); continue; } if (isset($healthcheckCommand) && str_contains($trimmedLine, '\\')) { $healthcheckCommand .= ' '.trim($trimmedLine, '\\ '); } if (isset($healthcheckCommand) && ! str_contains($trimmedLine, '\\') && ! empty($healthcheckCommand)) { $healthcheckCommand .= ' '.$trimmedLine; break; } } if (str($healthcheckCommand)->isNotEmpty()) { $interval = str($healthcheckCommand)->match('/--interval=([0-9]+[a-zµ]*)/'); $timeout = str($healthcheckCommand)->match('/--timeout=([0-9]+[a-zµ]*)/'); $start_period = str($healthcheckCommand)->match('/--start-period=([0-9]+[a-zµ]*)/'); $retries = str($healthcheckCommand)->match('/--retries=(\d+)/'); if ($interval->isNotEmpty()) { $this->health_check_interval = parseDockerfileInterval($interval); } if ($timeout->isNotEmpty()) { $this->health_check_timeout = parseDockerfileInterval($timeout); } if ($start_period->isNotEmpty()) { $this->health_check_start_period = parseDockerfileInterval($start_period); } if ($retries->isNotEmpty()) { $this->health_check_retries = $retries->toInteger(); } if ($interval || $timeout || $start_period || $retries) { $this->custom_healthcheck_found = true; $this->save(); } } } } public function getLimits(): array { return [ 'limits_memory' => $this->limits_memory, 'limits_memory_swap' => $this->limits_memory_swap, 'limits_memory_swappiness' => $this->limits_memory_swappiness, 'limits_memory_reservation' => $this->limits_memory_reservation, 'limits_cpus' => $this->limits_cpus, 'limits_cpuset' => $this->limits_cpuset, 'limits_cpu_shares' => $this->limits_cpu_shares, ]; } public function generateConfig($is_json = false) { $generator = new ConfigurationGenerator($this); if ($is_json) { return $generator->toJson(); } return $generator->toArray(); } public function setConfig($config) { $validator = Validator::make(['config' => $config], [ 'config' => 'required|json', ]); if ($validator->fails()) { throw new \Exception('Invalid JSON format'); } $config = json_decode($config, true); $deepValidator = Validator::make(['config' => $config], [ 'config.build_pack' => 'required|string', 'config.base_directory' => 'required|string', 'config.publish_directory' => 'required|string', 'config.ports_exposes' => 'required|string', 'config.settings.is_static' => 'required|boolean', ]); if ($deepValidator->fails()) { throw new \Exception('Invalid data'); } $config = $deepValidator->validated()['config']; try { $settings = data_get($config, 'settings', []); data_forget($config, 'settings'); $this->update($config); $this->settings()->update($settings); } catch (\Exception $e) { throw new \Exception('Failed to update application settings'); } } } ================================================ FILE: app/Models/ApplicationDeploymentQueue.php ================================================ ['type' => 'integer'], 'application_id' => ['type' => 'string'], 'deployment_uuid' => ['type' => 'string'], 'pull_request_id' => ['type' => 'integer'], 'force_rebuild' => ['type' => 'boolean'], 'commit' => ['type' => 'string'], 'status' => ['type' => 'string'], 'is_webhook' => ['type' => 'boolean'], 'is_api' => ['type' => 'boolean'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], 'logs' => ['type' => 'string'], 'current_process_id' => ['type' => 'string'], 'restart_only' => ['type' => 'boolean'], 'git_type' => ['type' => 'string'], 'server_id' => ['type' => 'integer'], 'application_name' => ['type' => 'string'], 'server_name' => ['type' => 'string'], 'deployment_url' => ['type' => 'string'], 'destination_id' => ['type' => 'string'], 'only_this_server' => ['type' => 'boolean'], 'rollback' => ['type' => 'boolean'], 'commit_message' => ['type' => 'string'], ], )] class ApplicationDeploymentQueue extends Model { protected $guarded = []; protected $casts = [ 'finished_at' => 'datetime', ]; public function application() { return $this->belongsTo(Application::class); } public function server(): Attribute { return Attribute::make( get: fn () => Server::find($this->server_id), ); } public function setStatus(string $status) { $this->update([ 'status' => $status, ]); } public function getOutput($name) { if (! $this->logs) { return null; } return collect(json_decode($this->logs))->where('name', $name)->first()?->output ?? null; } public function getHorizonJobStatus() { return getJobStatus($this->horizon_job_id); } public function commitMessage() { if (empty($this->commit_message) || is_null($this->commit_message)) { return null; } return str($this->commit_message)->value(); } private function redactSensitiveInfo($text) { $text = remove_iip($text); $app = $this->application; if (! $app) { return $text; } $lockedVars = collect([]); if ($app->environment_variables) { $lockedVars = $lockedVars->merge( $app->environment_variables ->where('is_shown_once', true) ->pluck('real_value', 'key') ->filter() ); } if ($this->pull_request_id !== 0 && $app->environment_variables_preview) { $lockedVars = $lockedVars->merge( $app->environment_variables_preview ->where('is_shown_once', true) ->pluck('real_value', 'key') ->filter() ); } foreach ($lockedVars as $key => $value) { $escapedValue = preg_quote($value, '/'); $text = preg_replace( '/'.$escapedValue.'/', REDACTED, $text ); } return $text; } public function addLogEntry(string $message, string $type = 'stdout', bool $hidden = false) { if ($type === 'error') { $type = 'stderr'; } $message = str($message)->trim(); if ($message->startsWith('╔')) { $message = "\n".$message; } $newLogEntry = [ 'command' => null, 'output' => $this->redactSensitiveInfo($message), 'type' => $type, 'timestamp' => Carbon::now('UTC'), 'hidden' => $hidden, 'batch' => 1, ]; // Use a transaction to ensure atomicity DB::transaction(function () use ($newLogEntry) { // Reload the model to get the latest logs $this->refresh(); if ($this->logs) { $previousLogs = json_decode($this->logs, associative: true, flags: JSON_THROW_ON_ERROR); $newLogEntry['order'] = count($previousLogs) + 1; $previousLogs[] = $newLogEntry; $this->logs = json_encode($previousLogs, flags: JSON_THROW_ON_ERROR); } else { $this->logs = json_encode([$newLogEntry], flags: JSON_THROW_ON_ERROR); } // Save without triggering events to prevent potential race conditions $this->saveQuietly(); }); } } ================================================ FILE: app/Models/ApplicationPreview.php ================================================ application->destination->server; $application = $preview->application; if (data_get($preview, 'application.build_pack') === 'dockercompose') { // Docker Compose volume and network cleanup $composeFile = $application->parse(pull_request_id: $preview->pull_request_id); $volumes = data_get($composeFile, 'volumes'); $networks = data_get($composeFile, 'networks'); $networkKeys = collect($networks)->keys(); $volumeKeys = collect($volumes)->keys(); $volumeKeys->each(function ($key) use ($server) { instant_remote_process(["docker volume rm -f $key"], $server, false); }); $networkKeys->each(function ($key) use ($server) { instant_remote_process(["docker network disconnect $key coolify-proxy"], $server, false); instant_remote_process(["docker network rm $key"], $server, false); }); } else { // Regular application volume cleanup $persistentStorages = $preview->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() > 0) { foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } } // Clean up persistent storage records $preview->persistentStorages()->delete(); }); static::saving(function ($preview) { if ($preview->isDirty('status')) { $preview->forceFill(['last_online_at' => now()]); } }); } public static function findPreviewByApplicationAndPullId(int $application_id, int $pull_request_id) { return self::where('application_id', $application_id)->where('pull_request_id', $pull_request_id)->firstOrFail(); } public function isRunning() { return (bool) str($this->status)->startsWith('running'); } public function application() { return $this->belongsTo(Application::class); } public function persistentStorages() { return $this->morphMany(\App\Models\LocalPersistentVolume::class, 'resource'); } public function generate_preview_fqdn() { if ($this->application->fqdn) { if (str($this->application->fqdn)->contains(',')) { $url = Url::fromString(str($this->application->fqdn)->explode(',')[0]); } else { $url = Url::fromString($this->application->fqdn); } $template = $this->application->preview_url_template; $host = $url->getHost(); $schema = $url->getScheme(); $portInt = $url->getPort(); $port = $portInt !== null ? ':'.$portInt : ''; $urlPath = $url->getPath(); $path = ($urlPath !== '' && $urlPath !== '/') ? $urlPath : ''; $random = new Cuid2; $preview_fqdn = str_replace('{{random}}', $random, $template); $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); $preview_fqdn = str_replace('{{pr_id}}', $this->pull_request_id, $preview_fqdn); $preview_fqdn = "$schema://$preview_fqdn{$port}{$path}"; $this->fqdn = $preview_fqdn; $this->save(); } return $this; } public function generate_preview_fqdn_compose() { $services = collect(json_decode($this->application->docker_compose_domains)) ?? collect(); $docker_compose_domains = data_get($this, 'docker_compose_domains'); $docker_compose_domains = json_decode($docker_compose_domains, true) ?? []; // Get all services from the parsed compose file to ensure all services have entries $parsedServices = $this->application->parse(pull_request_id: $this->pull_request_id); if (isset($parsedServices['services'])) { foreach ($parsedServices['services'] as $serviceName => $service) { if (! isDatabaseImage(data_get($service, 'image'))) { // Remove PR suffix from service name to get original service name $originalServiceName = str($serviceName)->replaceLast('-pr-'.$this->pull_request_id, '')->toString(); // Ensure all services have an entry, even if empty if (! $services->has($originalServiceName)) { $services->put($originalServiceName, ['domain' => '']); } } } } foreach ($services as $service_name => $service_config) { $domain_string = data_get($service_config, 'domain'); // If domain string is empty or null, don't auto-generate domain // Only generate domains when main app already has domains set if (empty($domain_string)) { // Ensure service has an empty domain entry for form binding $docker_compose_domains[$service_name]['domain'] = ''; continue; } $service_domains = str($domain_string)->explode(',')->map(fn ($d) => trim($d)); $preview_domains = []; foreach ($service_domains as $domain) { if (empty($domain)) { continue; } $url = Url::fromString($domain); $template = $this->application->preview_url_template; $host = $url->getHost(); $schema = $url->getScheme(); $portInt = $url->getPort(); $port = $portInt !== null ? ':'.$portInt : ''; $urlPath = $url->getPath(); $path = ($urlPath !== '' && $urlPath !== '/') ? $urlPath : ''; $random = new Cuid2; $preview_fqdn = str_replace('{{random}}', $random, $template); $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); $preview_fqdn = str_replace('{{pr_id}}', $this->pull_request_id, $preview_fqdn); $preview_fqdn = "$schema://$preview_fqdn{$port}{$path}"; $preview_domains[] = $preview_fqdn; } if (! empty($preview_domains)) { $docker_compose_domains[$service_name]['domain'] = implode(',', $preview_domains); } else { // Ensure service has an empty domain entry for form binding $docker_compose_domains[$service_name]['domain'] = ''; } } $this->docker_compose_domains = json_encode($docker_compose_domains); $this->save(); } } ================================================ FILE: app/Models/ApplicationSetting.php ================================================ 'boolean', 'is_spa' => 'boolean', 'is_build_server_enabled' => 'boolean', 'is_preserve_repository_enabled' => 'boolean', 'is_container_label_escape_enabled' => 'boolean', 'is_container_label_readonly_enabled' => 'boolean', 'use_build_secrets' => 'boolean', 'inject_build_args_to_dockerfile' => 'boolean', 'include_source_commit_in_build' => 'boolean', 'is_auto_deploy_enabled' => 'boolean', 'is_force_https_enabled' => 'boolean', 'is_debug_enabled' => 'boolean', 'is_preview_deployments_enabled' => 'boolean', 'is_pr_deployments_public_enabled' => 'boolean', 'is_git_submodules_enabled' => 'boolean', 'is_git_lfs_enabled' => 'boolean', 'is_git_shallow_clone_enabled' => 'boolean', 'docker_images_to_keep' => 'integer', ]; protected $guarded = []; public function isStatic(): Attribute { return Attribute::make( set: function ($value) { if ($value) { $this->application->ports_exposes = 80; } $this->application->save(); return $value; } ); } public function application() { return $this->belongsTo(Application::class); } } ================================================ FILE: app/Models/BaseModel.php ================================================ uuid) { $model->uuid = (string) new Cuid2; } }); } public function sanitizedName(): Attribute { return new Attribute( get: fn () => sanitize_string($this->getRawOriginal('name')), ); } public function image(): Attribute { return new Attribute( get: fn () => sanitize_string($this->getRawOriginal('image')), ); } } ================================================ FILE: app/Models/CloudInitScript.php ================================================ 'encrypted', ]; } public function team() { return $this->belongsTo(Team::class); } public static function ownedByCurrentTeam(array $select = ['*']) { $selectArray = collect($select)->concat(['id']); return self::whereTeamId(currentTeam()->id)->select($selectArray->all()); } } ================================================ FILE: app/Models/CloudProviderToken.php ================================================ 'encrypted', ]; public function team() { return $this->belongsTo(Team::class); } public function servers() { return $this->hasMany(Server::class); } public function hasServers(): bool { return $this->servers()->exists(); } public static function ownedByCurrentTeam(array $select = ['*']) { $selectArray = collect($select)->concat(['id']); return self::whereTeamId(currentTeam()->id)->select($selectArray->all()); } public function scopeForProvider($query, string $provider) { return $query->where('provider', $provider); } } ================================================ FILE: app/Models/DiscordNotificationSettings.php ================================================ 'boolean', 'discord_webhook_url' => 'encrypted', 'deployment_success_discord_notifications' => 'boolean', 'deployment_failure_discord_notifications' => 'boolean', 'status_change_discord_notifications' => 'boolean', 'backup_success_discord_notifications' => 'boolean', 'backup_failure_discord_notifications' => 'boolean', 'scheduled_task_success_discord_notifications' => 'boolean', 'scheduled_task_failure_discord_notifications' => 'boolean', 'docker_cleanup_discord_notifications' => 'boolean', 'server_disk_usage_discord_notifications' => 'boolean', 'server_reachable_discord_notifications' => 'boolean', 'server_unreachable_discord_notifications' => 'boolean', 'server_patch_discord_notifications' => 'boolean', 'traefik_outdated_discord_notifications' => 'boolean', 'discord_ping_enabled' => 'boolean', ]; public function team() { return $this->belongsTo(Team::class); } public function isEnabled() { return $this->discord_enabled; } public function isPingEnabled() { return $this->discord_ping_enabled; } } ================================================ FILE: app/Models/DockerCleanupExecution.php ================================================ belongsTo(Server::class); } } ================================================ FILE: app/Models/EmailNotificationSettings.php ================================================ 'boolean', 'smtp_from_address' => 'encrypted', 'smtp_from_name' => 'encrypted', 'smtp_recipients' => 'encrypted', 'smtp_host' => 'encrypted', 'smtp_port' => 'integer', 'smtp_username' => 'encrypted', 'smtp_password' => 'encrypted', 'smtp_timeout' => 'integer', 'resend_enabled' => 'boolean', 'resend_api_key' => 'encrypted', 'use_instance_email_settings' => 'boolean', 'deployment_success_email_notifications' => 'boolean', 'deployment_failure_email_notifications' => 'boolean', 'status_change_email_notifications' => 'boolean', 'backup_success_email_notifications' => 'boolean', 'backup_failure_email_notifications' => 'boolean', 'scheduled_task_success_email_notifications' => 'boolean', 'scheduled_task_failure_email_notifications' => 'boolean', 'server_disk_usage_email_notifications' => 'boolean', 'server_patch_email_notifications' => 'boolean', 'traefik_outdated_email_notifications' => 'boolean', ]; public function team() { return $this->belongsTo(Team::class); } public function isEnabled() { return $this->smtp_enabled || $this->resend_enabled || $this->use_instance_email_settings; } } ================================================ FILE: app/Models/Environment.php ================================================ ['type' => 'integer'], 'name' => ['type' => 'string'], 'project_id' => ['type' => 'integer'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], 'description' => ['type' => 'string'], ] )] class Environment extends BaseModel { use ClearsGlobalSearchCache; use HasFactory; use HasSafeStringAttribute; protected $guarded = []; protected static function booted() { static::deleting(function ($environment) { $shared_variables = $environment->environment_variables(); foreach ($shared_variables as $shared_variable) { $shared_variable->delete(); } }); } public static function ownedByCurrentTeam() { return Environment::whereRelation('project.team', 'id', currentTeam()->id)->orderBy('name'); } public function isEmpty() { return $this->applications()->count() == 0 && $this->redis()->count() == 0 && $this->postgresqls()->count() == 0 && $this->mysqls()->count() == 0 && $this->keydbs()->count() == 0 && $this->dragonflies()->count() == 0 && $this->clickhouses()->count() == 0 && $this->mariadbs()->count() == 0 && $this->mongodbs()->count() == 0 && $this->services()->count() == 0; } public function environment_variables() { return $this->hasMany(SharedEnvironmentVariable::class); } public function applications() { return $this->hasMany(Application::class); } public function postgresqls() { return $this->hasMany(StandalonePostgresql::class); } public function redis() { return $this->hasMany(StandaloneRedis::class); } public function mongodbs() { return $this->hasMany(StandaloneMongodb::class); } public function mysqls() { return $this->hasMany(StandaloneMysql::class); } public function mariadbs() { return $this->hasMany(StandaloneMariadb::class); } public function keydbs() { return $this->hasMany(StandaloneKeydb::class); } public function dragonflies() { return $this->hasMany(StandaloneDragonfly::class); } public function clickhouses() { return $this->hasMany(StandaloneClickhouse::class); } public function databases() { $postgresqls = $this->postgresqls; $redis = $this->redis; $mongodbs = $this->mongodbs; $mysqls = $this->mysqls; $mariadbs = $this->mariadbs; $keydbs = $this->keydbs; $dragonflies = $this->dragonflies; $clickhouses = $this->clickhouses; return $postgresqls->concat($redis)->concat($mongodbs)->concat($mysqls)->concat($mariadbs)->concat($keydbs)->concat($dragonflies)->concat($clickhouses); } public function project() { return $this->belongsTo(Project::class); } public function services() { return $this->hasMany(Service::class); } protected function customizeName($value) { return str($value)->lower()->trim()->replace('/', '-')->toString(); } } ================================================ FILE: app/Models/EnvironmentVariable.php ================================================ ['type' => 'integer'], 'uuid' => ['type' => 'string'], 'resourceable_type' => ['type' => 'string'], 'resourceable_id' => ['type' => 'integer'], 'is_literal' => ['type' => 'boolean'], 'is_multiline' => ['type' => 'boolean'], 'is_preview' => ['type' => 'boolean'], 'is_runtime' => ['type' => 'boolean'], 'is_buildtime' => ['type' => 'boolean'], 'is_shared' => ['type' => 'boolean'], 'is_shown_once' => ['type' => 'boolean'], 'key' => ['type' => 'string'], 'value' => ['type' => 'string'], 'real_value' => ['type' => 'string'], 'comment' => ['type' => 'string', 'nullable' => true], 'version' => ['type' => 'string'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], ] )] class EnvironmentVariable extends BaseModel { protected $fillable = [ // Core identification 'key', 'value', 'comment', // Polymorphic relationship 'resourceable_type', 'resourceable_id', // Boolean flags 'is_preview', 'is_multiline', 'is_literal', 'is_runtime', 'is_buildtime', 'is_shown_once', 'is_shared', 'is_required', // Metadata 'version', 'order', ]; protected $casts = [ 'key' => 'string', 'value' => 'encrypted', 'is_multiline' => 'boolean', 'is_preview' => 'boolean', 'is_runtime' => 'boolean', 'is_buildtime' => 'boolean', 'version' => 'string', 'resourceable_type' => 'string', 'resourceable_id' => 'integer', ]; protected $appends = ['real_value', 'is_shared', 'is_really_required', 'is_nixpacks', 'is_coolify']; protected static function booted() { static::created(function (EnvironmentVariable $environment_variable) { if ($environment_variable->resourceable_type === Application::class && ! $environment_variable->is_preview) { $found = ModelsEnvironmentVariable::where('key', $environment_variable->key) ->where('resourceable_type', Application::class) ->where('resourceable_id', $environment_variable->resourceable_id) ->where('is_preview', true) ->first(); if (! $found) { $application = Application::find($environment_variable->resourceable_id); if ($application) { ModelsEnvironmentVariable::create([ 'key' => $environment_variable->key, 'value' => $environment_variable->value, 'is_multiline' => $environment_variable->is_multiline ?? false, 'is_literal' => $environment_variable->is_literal ?? false, 'is_runtime' => $environment_variable->is_runtime ?? false, 'is_buildtime' => $environment_variable->is_buildtime ?? false, 'comment' => $environment_variable->comment, 'resourceable_type' => Application::class, 'resourceable_id' => $environment_variable->resourceable_id, 'is_preview' => true, ]); } } } $environment_variable->update([ 'version' => config('constants.coolify.version'), ]); }); static::saving(function (EnvironmentVariable $environmentVariable) { $environmentVariable->updateIsShared(); }); } public function service() { return $this->belongsTo(Service::class); } protected function value(): Attribute { return Attribute::make( get: fn (?string $value = null) => $this->get_environment_variables($value), set: fn (?string $value = null) => $this->set_environment_variables($value), ); } /** * Get the parent resourceable model. */ public function resourceable() { return $this->morphTo(); } public function resource() { return $this->resourceable; } public function realValue(): Attribute { return Attribute::make( get: function () { if (! $this->relationLoaded('resourceable')) { $this->load('resourceable'); } $resource = $this->resourceable; if (! $resource) { return null; } $real_value = $this->get_real_environment_variables($this->value, $resource); // Skip escaping for valid JSON objects/arrays to prevent quote corruption (see #6160) if (json_validate($real_value) && (str_starts_with($real_value, '{') || str_starts_with($real_value, '['))) { return $real_value; } if ($this->is_literal || $this->is_multiline) { $real_value = '\''.$real_value.'\''; } else { $real_value = escapeEnvVariables($real_value); } return $real_value; } ); } protected function isReallyRequired(): Attribute { return Attribute::make( get: fn () => $this->is_required && str($this->real_value)->isEmpty(), ); } protected function isNixpacks(): Attribute { return Attribute::make( get: function () { if (str($this->key)->startsWith('NIXPACKS_')) { return true; } return false; } ); } protected function isCoolify(): Attribute { return Attribute::make( get: function () { if (str($this->key)->startsWith('SERVICE_')) { return true; } return false; } ); } protected function isShared(): Attribute { return Attribute::make( get: function () { $type = str($this->value)->after('{{')->before('.')->value; if (str($this->value)->startsWith('{{'.$type) && str($this->value)->endsWith('}}')) { return true; } return false; } ); } private function get_real_environment_variables(?string $environment_variable = null, $resource = null) { return resolveSharedEnvironmentVariables($environment_variable, $resource); } private function get_environment_variables(?string $environment_variable = null): ?string { if (! $environment_variable) { return null; } return trim(decrypt($environment_variable)); } private function set_environment_variables(?string $environment_variable = null): ?string { if (is_null($environment_variable) && $environment_variable === '') { return null; } $environment_variable = trim($environment_variable); $type = str($environment_variable)->after('{{')->before('.')->value; if (str($environment_variable)->startsWith('{{'.$type) && str($environment_variable)->endsWith('}}')) { return encrypt($environment_variable); } return encrypt($environment_variable); } protected function key(): Attribute { return Attribute::make( set: fn (string $value) => str($value)->trim()->replace(' ', '_')->value, ); } protected function updateIsShared(): void { $type = str($this->value)->after('{{')->before('.')->value; $isShared = str($this->value)->startsWith('{{'.$type) && str($this->value)->endsWith('}}'); $this->is_shared = $isShared; } } ================================================ FILE: app/Models/GithubApp.php ================================================ 'boolean', 'is_system_wide' => 'boolean', 'type' => 'string', ]; protected $hidden = [ 'client_secret', 'webhook_secret', ]; protected static function booted(): void { static::deleting(function (GithubApp $github_app) { $applications_count = Application::where('source_id', $github_app->id)->count(); if ($applications_count > 0) { throw new \Exception('You cannot delete this GitHub App because it is in use by '.$applications_count.' application(s). Delete them first.'); } $privateKey = $github_app->privateKey; if ($privateKey) { // Check if key is used by anything EXCEPT this GitHub app $isUsedElsewhere = $privateKey->servers()->exists() || $privateKey->applications()->exists() || $privateKey->githubApps()->where('id', '!=', $github_app->id)->exists() || $privateKey->gitlabApps()->exists(); if (! $isUsedElsewhere) { $privateKey->delete(); } else { } } }); } public static function ownedByCurrentTeam() { return GithubApp::where(function ($query) { $query->where('team_id', currentTeam()->id) ->orWhere('is_system_wide', true); }); } public static function public() { return GithubApp::where(function ($query) { $query->where(function ($q) { $q->where('team_id', currentTeam()->id) ->orWhere('is_system_wide', true); })->where('is_public', true); })->whereNotNull('app_id')->get(); } public static function private() { return GithubApp::where(function ($query) { $query->where(function ($q) { $q->where('team_id', currentTeam()->id) ->orWhere('is_system_wide', true); })->where('is_public', false); })->whereNotNull('app_id')->get(); } public function team() { return $this->belongsTo(Team::class); } public function applications() { return $this->morphMany(Application::class, 'source'); } public function privateKey() { return $this->belongsTo(PrivateKey::class); } public function type(): Attribute { return Attribute::make( get: function () { if ($this->getMorphClass() === \App\Models\GithubApp::class) { return 'github'; } }, ); } } ================================================ FILE: app/Models/GitlabApp.php ================================================ id); } public function applications() { return $this->morphMany(Application::class, 'source'); } public function privateKey() { return $this->belongsTo(PrivateKey::class); } } ================================================ FILE: app/Models/InstanceSettings.php ================================================ 'boolean', 'smtp_from_address' => 'encrypted', 'smtp_from_name' => 'encrypted', 'smtp_recipients' => 'encrypted', 'smtp_host' => 'encrypted', 'smtp_port' => 'integer', 'smtp_username' => 'encrypted', 'smtp_password' => 'encrypted', 'smtp_timeout' => 'integer', 'resend_enabled' => 'boolean', 'resend_api_key' => 'encrypted', 'allowed_ip_ranges' => 'array', 'is_auto_update_enabled' => 'boolean', 'auto_update_frequency' => 'string', 'update_check_frequency' => 'string', 'sentinel_token' => 'encrypted', 'is_wire_navigate_enabled' => 'boolean', ]; protected static function booted(): void { static::updated(function ($settings) { // Clear once() cache so subsequent calls get fresh data Once::flush(); // Clear trusted hosts cache when FQDN changes if ($settings->wasChanged('fqdn')) { \Cache::forget('instance_settings_fqdn_host'); } }); } public function fqdn(): Attribute { return Attribute::make( set: function ($value) { if ($value) { $url = Url::fromString($value); $host = $url->getHost(); return $url->getScheme().'://'.$host; } } ); } public function updateCheckFrequency(): Attribute { return Attribute::make( set: function ($value) { return translate_cron_expression($value); }, get: function ($value) { return translate_cron_expression($value); } ); } public function autoUpdateFrequency(): Attribute { return Attribute::make( set: function ($value) { return translate_cron_expression($value); }, get: function ($value) { return translate_cron_expression($value); } ); } public static function get() { return once(fn () => InstanceSettings::findOrFail(0)); } // public function getRecipients($notification) // { // $recipients = data_get($notification, 'emails', null); // if (is_null($recipients) || $recipients === '') { // return []; // } // return explode(',', $recipients); // } public function getTitleDisplayName(): string { $instanceName = $this->instance_name; if (! $instanceName) { return ''; } return "[{$instanceName}]"; } // public function helperVersion(): Attribute // { // return Attribute::make( // get: function ($value) { // if (isDev()) { // return 'latest'; // } // return $value; // } // ); // } } ================================================ FILE: app/Models/LocalFileVolume.php ================================================ 'encrypted', // 'mount_path' => 'encrypted', 'content' => 'encrypted', 'is_directory' => 'boolean', ]; use HasFactory; protected $guarded = []; public $appends = ['is_binary']; protected static function booted() { static::created(function (LocalFileVolume $fileVolume) { $fileVolume->load(['service']); dispatch(new \App\Jobs\ServerStorageSaveJob($fileVolume)); }); } protected function isBinary(): Attribute { return Attribute::make( get: function () { return $this->content === '[binary file]'; } ); } public function service() { return $this->morphTo('resource'); } public function loadStorageOnServer() { $this->load(['service']); $isService = data_get($this->resource, 'service'); if ($isService) { $workdir = $this->resource->service->workdir(); $server = $this->resource->service->server; } else { $workdir = $this->resource->workdir(); $server = $this->resource->destination->server; } $commands = collect([]); $path = data_get_str($this, 'fs_path'); if ($path->startsWith('.')) { $path = $path->after('.'); $path = $workdir.$path; } // Validate and escape path to prevent command injection validateShellSafePath($path, 'storage path'); $escapedPath = escapeshellarg($path); $isFile = instant_remote_process(["test -f {$escapedPath} && echo OK || echo NOK"], $server); if ($isFile === 'OK') { $content = instant_remote_process(["cat {$escapedPath}"], $server, false); // Check if content contains binary data by looking for null bytes or non-printable characters if (str_contains($content, "\0") || preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', $content)) { $content = '[binary file]'; } $this->content = $content; $this->is_directory = false; $this->save(); } } public function deleteStorageOnServer() { $this->load(['service']); $isService = data_get($this->resource, 'service'); if ($isService) { $workdir = $this->resource->service->workdir(); $server = $this->resource->service->server; } else { $workdir = $this->resource->workdir(); $server = $this->resource->destination->server; } $commands = collect([]); $path = data_get_str($this, 'fs_path'); if ($path->startsWith('.')) { $path = $path->after('.'); $path = $workdir.$path; } // Validate and escape path to prevent command injection validateShellSafePath($path, 'storage path'); $escapedPath = escapeshellarg($path); $isFile = instant_remote_process(["test -f {$escapedPath} && echo OK || echo NOK"], $server); $isDir = instant_remote_process(["test -d {$escapedPath} && echo OK || echo NOK"], $server); if ($path && $path != '/' && $path != '.' && $path != '..') { if ($isFile === 'OK') { $commands->push("rm -rf {$escapedPath} > /dev/null 2>&1 || true"); } elseif ($isDir === 'OK') { $commands->push("rm -rf {$escapedPath} > /dev/null 2>&1 || true"); $commands->push("rmdir {$escapedPath} > /dev/null 2>&1 || true"); } } if ($commands->count() > 0) { return instant_remote_process($commands, $server); } } public function saveStorageOnServer() { $this->load(['service']); $isService = data_get($this->resource, 'service'); if ($isService) { $workdir = $this->resource->service->workdir(); $server = $this->resource->service->server; } else { $workdir = $this->resource->workdir(); $server = $this->resource->destination->server; } $commands = collect([]); if ($this->is_directory) { $commands->push("mkdir -p $this->fs_path > /dev/null 2>&1 || true"); $commands->push("mkdir -p $workdir > /dev/null 2>&1 || true"); $commands->push("cd $workdir"); } if (str($this->fs_path)->startsWith('.') || str($this->fs_path)->startsWith('/') || str($this->fs_path)->startsWith('~')) { $parent_dir = str($this->fs_path)->beforeLast('/'); if ($parent_dir != '') { $commands->push("mkdir -p $parent_dir > /dev/null 2>&1 || true"); } } $path = data_get_str($this, 'fs_path'); $content = data_get($this, 'content'); if ($path->startsWith('.')) { $path = $path->after('.'); $path = $workdir.$path; } // Validate and escape path to prevent command injection validateShellSafePath($path, 'storage path'); $escapedPath = escapeshellarg($path); $isFile = instant_remote_process(["test -f {$escapedPath} && echo OK || echo NOK"], $server); $isDir = instant_remote_process(["test -d {$escapedPath} && echo OK || echo NOK"], $server); if ($isFile === 'OK' && $this->is_directory) { $content = instant_remote_process(["cat {$escapedPath}"], $server, false); $this->is_directory = false; $this->content = $content; $this->save(); FileStorageChanged::dispatch(data_get($server, 'team_id')); throw new \Exception('The following file is a file on the server, but you are trying to mark it as a directory. Please delete the file on the server or mark it as directory.'); } elseif ($isDir === 'OK' && ! $this->is_directory) { if ($path === '/' || $path === '.' || $path === '..' || $path === '' || str($path)->isEmpty() || is_null($path)) { $this->is_directory = true; $this->save(); throw new \Exception('The following file is a directory on the server, but you are trying to mark it as a file.

Please delete the directory on the server or mark it as directory.'); } instant_remote_process([ "rm -fr {$escapedPath}", "touch {$escapedPath}", ], $server, false); FileStorageChanged::dispatch(data_get($server, 'team_id')); } if ($isDir === 'NOK' && ! $this->is_directory) { $chmod = data_get($this, 'chmod'); $chown = data_get($this, 'chown'); if ($content) { $content = base64_encode($content); $commands->push("echo '$content' | base64 -d | tee {$escapedPath} > /dev/null"); } else { $commands->push("touch {$escapedPath}"); } $commands->push("chmod +x {$escapedPath}"); if ($chown) { $commands->push("chown $chown {$escapedPath}"); } if ($chmod) { $commands->push("chmod $chmod {$escapedPath}"); } } elseif ($isDir === 'NOK' && $this->is_directory) { $commands->push("mkdir -p {$escapedPath} > /dev/null 2>&1 || true"); } return instant_remote_process($commands, $server); } // Accessor for convenient access protected function plainMountPath(): Attribute { return Attribute::make( get: fn () => $this->mount_path, set: fn ($value) => $this->mount_path = $value ); } // Scope for searching public function scopeWherePlainMountPath($query, $path) { return $query->get()->where('plain_mount_path', $path); } // Check if this volume belongs to a service resource public function isServiceResource(): bool { return in_array($this->resource_type, [ 'App\Models\ServiceApplication', 'App\Models\ServiceDatabase', ]); } // Determine if this volume should be read-only in the UI // File/directory mounts can be edited even for services public function shouldBeReadOnlyInUI(): bool { // Check for explicit :ro flag in compose (existing logic) return $this->isReadOnlyVolume(); } // Check if this volume is read-only by parsing the docker-compose content public function isReadOnlyVolume(): bool { try { // Only check for services $service = $this->service; if (! $service || ! method_exists($service, 'service')) { return false; } $actualService = $service->service; if (! $actualService || ! $actualService->docker_compose_raw) { return false; } // Parse the docker-compose content $compose = Yaml::parse($actualService->docker_compose_raw); if (! isset($compose['services'])) { return false; } // Find the service that this volume belongs to $serviceName = $service->name; if (! isset($compose['services'][$serviceName]['volumes'])) { return false; } $volumes = $compose['services'][$serviceName]['volumes']; // Check each volume to find a match // Note: We match on mount_path (container path) only, since fs_path gets transformed // from relative (./file) to absolute (/data/coolify/services/uuid/file) during parsing foreach ($volumes as $volume) { // Volume can be string like "host:container:ro" or "host:container" if (is_string($volume)) { $parts = explode(':', $volume); // Check if this volume matches our mount_path if (count($parts) >= 2) { $containerPath = $parts[1]; $options = $parts[2] ?? null; // Match based on mount_path // Remove leading slash from mount_path if present for comparison $mountPath = str($this->mount_path)->ltrim('/')->toString(); $containerPathClean = str($containerPath)->ltrim('/')->toString(); if ($mountPath === $containerPathClean || $this->mount_path === $containerPath) { return $options === 'ro'; } } } elseif (is_array($volume)) { // Long-form syntax: { type: bind, source: ..., target: ..., read_only: true } $containerPath = data_get($volume, 'target'); $readOnly = data_get($volume, 'read_only', false); // Match based on mount_path // Remove leading slash from mount_path if present for comparison $mountPath = str($this->mount_path)->ltrim('/')->toString(); $containerPathClean = str($containerPath)->ltrim('/')->toString(); if ($mountPath === $containerPathClean || $this->mount_path === $containerPath) { return $readOnly === true; } } } return false; } catch (\Throwable $e) { ray($e->getMessage(), 'Error checking read-only volume'); return false; } } } ================================================ FILE: app/Models/LocalPersistentVolume.php ================================================ morphTo('resource'); } public function application() { return $this->morphTo('resource'); } public function service() { return $this->morphTo('resource'); } public function database() { return $this->morphTo('resource'); } protected function customizeName($value) { return str($value)->trim()->value; } protected function mountPath(): Attribute { return Attribute::make( set: fn (string $value) => str($value)->trim()->start('/')->value ); } protected function hostPath(): Attribute { return Attribute::make( set: function (?string $value) { if ($value) { return str($value)->trim()->start('/')->value; } else { return $value; } } ); } // Check if this volume belongs to a service resource public function isServiceResource(): bool { return in_array($this->resource_type, [ 'App\Models\ServiceApplication', 'App\Models\ServiceDatabase', ]); } // Check if this volume belongs to a dockercompose application public function isDockerComposeResource(): bool { if ($this->resource_type !== 'App\Models\Application') { return false; } // Only access relationship if already eager loaded to avoid N+1 if (! $this->relationLoaded('resource')) { return false; } $application = $this->resource; if (! $application) { return false; } return data_get($application, 'build_pack') === 'dockercompose'; } // Determine if this volume should be read-only in the UI // Service volumes and dockercompose application volumes are read-only // (users should edit compose file directly) public function shouldBeReadOnlyInUI(): bool { // All service volumes should be read-only in UI if ($this->isServiceResource()) { return true; } // All dockercompose application volumes should be read-only in UI if ($this->isDockerComposeResource()) { return true; } // Check for explicit :ro flag in compose (existing logic) return $this->isReadOnlyVolume(); } // Check if this volume is read-only by parsing the docker-compose content public function isReadOnlyVolume(): bool { try { // Get the resource (can be application, service, or database) $resource = $this->resource; if (! $resource) { return false; } // Only check for services if (! method_exists($resource, 'service')) { return false; } $actualService = $resource->service; if (! $actualService || ! $actualService->docker_compose_raw) { return false; } // Parse the docker-compose content $compose = Yaml::parse($actualService->docker_compose_raw); if (! isset($compose['services'])) { return false; } // Find the service that this volume belongs to $serviceName = $resource->name; if (! isset($compose['services'][$serviceName]['volumes'])) { return false; } $volumes = $compose['services'][$serviceName]['volumes']; // Check each volume to find a match // Note: We match on mount_path (container path) only, since host paths get transformed foreach ($volumes as $volume) { // Volume can be string like "host:container:ro" or "host:container" if (is_string($volume)) { $parts = explode(':', $volume); // Check if this volume matches our mount_path if (count($parts) >= 2) { $containerPath = $parts[1]; $options = $parts[2] ?? null; // Match based on mount_path // Remove leading slash from mount_path if present for comparison $mountPath = str($this->mount_path)->ltrim('/')->toString(); $containerPathClean = str($containerPath)->ltrim('/')->toString(); if ($mountPath === $containerPathClean || $this->mount_path === $containerPath) { return $options === 'ro'; } } } elseif (is_array($volume)) { // Long-form syntax: { type: bind/volume, source: ..., target: ..., read_only: true } $containerPath = data_get($volume, 'target'); $readOnly = data_get($volume, 'read_only', false); // Match based on mount_path // Remove leading slash from mount_path if present for comparison $mountPath = str($this->mount_path)->ltrim('/')->toString(); $containerPathClean = str($containerPath)->ltrim('/')->toString(); if ($mountPath === $containerPathClean || $this->mount_path === $containerPath) { return $readOnly === true; } } } return false; } catch (\Throwable $e) { ray($e->getMessage(), 'Error checking read-only persistent volume'); return false; } } } ================================================ FILE: app/Models/OauthSetting.php ================================================ empty($value) ? null : Crypt::decryptString($value), set: fn (?string $value) => empty($value) ? null : Crypt::encryptString($value), ); } public function couldBeEnabled(): bool { switch ($this->provider) { case 'azure': return filled($this->client_id) && filled($this->client_secret) && filled($this->tenant); case 'authentik': case 'clerk': return filled($this->client_id) && filled($this->client_secret) && filled($this->base_url); default: return filled($this->client_id) && filled($this->client_secret); } } } ================================================ FILE: app/Models/PersonalAccessToken.php ================================================ ['type' => 'integer'], 'uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], 'private_key' => ['type' => 'string', 'format' => 'private-key'], 'public_key' => ['type' => 'string', 'description' => 'The public key of the private key.'], 'fingerprint' => ['type' => 'string', 'description' => 'The fingerprint of the private key.'], 'is_git_related' => ['type' => 'boolean'], 'team_id' => ['type' => 'integer'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], ], )] class PrivateKey extends BaseModel { use HasSafeStringAttribute, WithRateLimiting; protected $fillable = [ 'name', 'description', 'private_key', 'is_git_related', 'team_id', 'fingerprint', ]; protected $casts = [ 'private_key' => 'encrypted', ]; protected $appends = ['public_key']; protected static function booted() { static::saving(function ($key) { $key->private_key = formatPrivateKey($key->private_key); if (! self::validatePrivateKey($key->private_key)) { throw ValidationException::withMessages([ 'private_key' => ['The private key is invalid.'], ]); } $key->fingerprint = self::generateFingerprint($key->private_key); if (self::fingerprintExists($key->fingerprint, $key->id)) { throw ValidationException::withMessages([ 'private_key' => ['This private key already exists.'], ]); } }); static::deleted(function ($key) { self::deleteFromStorage($key); }); } public function getPublicKeyAttribute() { return self::extractPublicKeyFromPrivate($this->private_key) ?? 'Error loading private key'; } public function getPublicKey() { return self::extractPublicKeyFromPrivate($this->private_key) ?? 'Error loading private key'; } /** * Get query builder for private keys owned by current team. * If you need all private keys without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam(array $select = ['*']) { $teamId = currentTeam()->id; $selectArray = collect($select)->concat(['id']); return self::whereTeamId($teamId)->select($selectArray->all()); } /** * Get all private keys owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return PrivateKey::ownedByCurrentTeam()->get(); }); } public static function ownedAndOnlySShKeys(array $select = ['*']) { $teamId = currentTeam()->id; $selectArray = collect($select)->concat(['id']); return self::whereTeamId($teamId) ->where('is_git_related', false) ->select($selectArray->all()); } public static function validatePrivateKey($privateKey) { try { PublicKeyLoader::load($privateKey); return true; } catch (\Throwable $e) { return false; } } public static function createAndStore(array $data) { return DB::transaction(function () use ($data) { $privateKey = new self($data); $privateKey->save(); try { $privateKey->storeInFileSystem(); } catch (\Exception $e) { throw new \Exception('Failed to store SSH key: '.$e->getMessage()); } return $privateKey; }); } public static function generateNewKeyPair($type = 'rsa') { try { $instance = new self; $instance->rateLimit(10); $name = generate_random_name(); $description = 'Created by Coolify'; $keyPair = generateSSHKey($type === 'ed25519' ? 'ed25519' : 'rsa'); return [ 'name' => $name, 'description' => $description, 'private_key' => $keyPair['private'], 'public_key' => $keyPair['public'], ]; } catch (\Throwable $e) { throw new \Exception("Failed to generate new {$type} key: ".$e->getMessage()); } } public static function extractPublicKeyFromPrivate($privateKey) { try { $key = PublicKeyLoader::load($privateKey); return $key->getPublicKey()->toString('OpenSSH', ['comment' => '']); } catch (\Throwable $e) { return null; } } public static function validateAndExtractPublicKey($privateKey) { $isValid = self::validatePrivateKey($privateKey); $publicKey = $isValid ? self::extractPublicKeyFromPrivate($privateKey) : ''; return [ 'isValid' => $isValid, 'publicKey' => $publicKey, ]; } public function storeInFileSystem() { $filename = "ssh_key@{$this->uuid}"; $disk = Storage::disk('ssh-keys'); // Ensure the storage directory exists and is writable $this->ensureStorageDirectoryExists(); // Attempt to store the private key $success = $disk->put($filename, $this->private_key); if (! $success) { throw new \Exception("Failed to write SSH key to filesystem. Check disk space and permissions for: {$this->getKeyLocation()}"); } // Verify the file was actually created and has content if (! $disk->exists($filename)) { throw new \Exception("SSH key file was not created: {$this->getKeyLocation()}"); } $storedContent = $disk->get($filename); if (empty($storedContent) || $storedContent !== $this->private_key) { $disk->delete($filename); // Clean up the bad file throw new \Exception("SSH key file content verification failed: {$this->getKeyLocation()}"); } return $this->getKeyLocation(); } public static function deleteFromStorage(self $privateKey) { $filename = "ssh_key@{$privateKey->uuid}"; $disk = Storage::disk('ssh-keys'); if ($disk->exists($filename)) { $disk->delete($filename); } } protected function ensureStorageDirectoryExists() { $disk = Storage::disk('ssh-keys'); $directoryPath = ''; if (! $disk->exists($directoryPath)) { $success = $disk->makeDirectory($directoryPath); if (! $success) { throw new \Exception('Failed to create SSH keys storage directory'); } } // Check if directory is writable by attempting a test file $testFilename = '.test_write_'.uniqid(); $testSuccess = $disk->put($testFilename, 'test'); if (! $testSuccess) { throw new \Exception('SSH keys storage directory is not writable. Run on the host: sudo chown -R 9999 /data/coolify/ssh && sudo chmod -R 700 /data/coolify/ssh && docker restart coolify'); } // Clean up test file $disk->delete($testFilename); } public function getKeyLocation() { return "/var/www/html/storage/app/ssh/keys/ssh_key@{$this->uuid}"; } public function updatePrivateKey(array $data) { return DB::transaction(function () use ($data) { $this->update($data); try { $this->storeInFileSystem(); } catch (\Exception $e) { throw new \Exception('Failed to update SSH key: '.$e->getMessage()); } return $this; }); } public function servers() { return $this->hasMany(Server::class); } public function applications() { return $this->hasMany(Application::class); } public function githubApps() { return $this->hasMany(GithubApp::class); } public function gitlabApps() { return $this->hasMany(GitlabApp::class); } public function isInUse() { return $this->servers()->exists() || $this->applications()->exists() || $this->githubApps()->exists() || $this->gitlabApps()->exists(); } public function safeDelete() { if (! $this->isInUse()) { $this->delete(); return true; } return false; } public static function generateFingerprint($privateKey) { try { $key = PublicKeyLoader::load($privateKey); return $key->getPublicKey()->getFingerprint('sha256'); } catch (\Throwable $e) { return null; } } public static function generateMd5Fingerprint($privateKey) { try { $key = PublicKeyLoader::load($privateKey); return $key->getPublicKey()->getFingerprint('md5'); } catch (\Throwable $e) { return null; } } public static function fingerprintExists($fingerprint, $excludeId = null) { $query = self::query() ->where('fingerprint', $fingerprint) ->where('id', '!=', $excludeId); if (currentTeam()) { $query->where('team_id', currentTeam()->id); } return $query->exists(); } public static function cleanupUnusedKeys() { self::ownedByCurrentTeam()->each(function ($privateKey) { $privateKey->safeDelete(); }); } } ================================================ FILE: app/Models/Project.php ================================================ ['type' => 'integer'], 'uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], ] )] class Project extends BaseModel { use ClearsGlobalSearchCache; use HasFactory; use HasSafeStringAttribute; protected $guarded = []; /** * Get query builder for projects owned by current team. * If you need all projects without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return Project::whereTeamId(currentTeam()->id)->orderByRaw('LOWER(name)'); } /** * Get all projects owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return Project::ownedByCurrentTeam()->get(); }); } protected static function booted() { static::created(function ($project) { ProjectSetting::create([ 'project_id' => $project->id, ]); Environment::create([ 'name' => 'production', 'project_id' => $project->id, 'uuid' => (string) new Cuid2, ]); }); static::deleting(function ($project) { $project->environments()->delete(); $project->settings()->delete(); $shared_variables = $project->environment_variables(); foreach ($shared_variables as $shared_variable) { $shared_variable->delete(); } }); } public function environment_variables() { return $this->hasMany(SharedEnvironmentVariable::class); } public function environments() { return $this->hasMany(Environment::class); } public function settings() { return $this->hasOne(ProjectSetting::class); } public function team() { return $this->belongsTo(Team::class); } public function services() { return $this->hasManyThrough(Service::class, Environment::class); } public function applications() { return $this->hasManyThrough(Application::class, Environment::class); } public function postgresqls() { return $this->hasManyThrough(StandalonePostgresql::class, Environment::class); } public function redis() { return $this->hasManyThrough(StandaloneRedis::class, Environment::class); } public function keydbs() { return $this->hasManyThrough(StandaloneKeydb::class, Environment::class); } public function dragonflies() { return $this->hasManyThrough(StandaloneDragonfly::class, Environment::class); } public function clickhouses() { return $this->hasManyThrough(StandaloneClickhouse::class, Environment::class); } public function mongodbs() { return $this->hasManyThrough(StandaloneMongodb::class, Environment::class); } public function mysqls() { return $this->hasManyThrough(StandaloneMysql::class, Environment::class); } public function mariadbs() { return $this->hasManyThrough(StandaloneMariadb::class, Environment::class); } public function isEmpty() { return $this->applications()->count() == 0 && $this->redis()->count() == 0 && $this->postgresqls()->count() == 0 && $this->mysqls()->count() == 0 && $this->keydbs()->count() == 0 && $this->dragonflies()->count() == 0 && $this->clickhouses()->count() == 0 && $this->mariadbs()->count() == 0 && $this->mongodbs()->count() == 0 && $this->services()->count() == 0; } public function databases() { return $this->postgresqls()->get()->merge($this->redis()->get())->merge($this->mongodbs()->get())->merge($this->mysqls()->get())->merge($this->mariadbs()->get())->merge($this->keydbs()->get())->merge($this->dragonflies()->get())->merge($this->clickhouses()->get()); } public function navigateTo() { if ($this->environments->count() === 1) { return route('project.resource.index', [ 'project_uuid' => $this->uuid, 'environment_uuid' => $this->environments->first()->uuid, ]); } return route('project.show', ['project_uuid' => $this->uuid]); } } ================================================ FILE: app/Models/ProjectSetting.php ================================================ belongsTo(Project::class); } } ================================================ FILE: app/Models/PushoverNotificationSettings.php ================================================ 'boolean', 'pushover_user_key' => 'encrypted', 'pushover_api_token' => 'encrypted', 'deployment_success_pushover_notifications' => 'boolean', 'deployment_failure_pushover_notifications' => 'boolean', 'status_change_pushover_notifications' => 'boolean', 'backup_success_pushover_notifications' => 'boolean', 'backup_failure_pushover_notifications' => 'boolean', 'scheduled_task_success_pushover_notifications' => 'boolean', 'scheduled_task_failure_pushover_notifications' => 'boolean', 'docker_cleanup_pushover_notifications' => 'boolean', 'server_disk_usage_pushover_notifications' => 'boolean', 'server_reachable_pushover_notifications' => 'boolean', 'server_unreachable_pushover_notifications' => 'boolean', 'server_patch_pushover_notifications' => 'boolean', 'traefik_outdated_pushover_notifications' => 'boolean', ]; public function team() { return $this->belongsTo(Team::class); } public function isEnabled() { return $this->pushover_enabled; } } ================================================ FILE: app/Models/S3Storage.php ================================================ 'boolean', 'key' => 'encrypted', 'secret' => 'encrypted', ]; /** * Boot the model and register event listeners. */ protected static function boot(): void { parent::boot(); // Trim whitespace from credentials before saving to prevent // "Malformed Access Key Id" errors from accidental whitespace in pasted values. // Note: We use the saving event instead of Attribute mutators because key/secret // use Laravel's 'encrypted' cast. Attribute mutators fire before casts, which // would cause issues with the encryption/decryption cycle. static::saving(function (S3Storage $storage) { if ($storage->key !== null) { $storage->key = trim($storage->key); } if ($storage->secret !== null) { $storage->secret = trim($storage->secret); } }); } public static function ownedByCurrentTeam(array $select = ['*']) { $selectArray = collect($select)->concat(['id']); return S3Storage::whereTeamId(currentTeam()->id)->select($selectArray->all())->orderBy('name'); } public function isUsable() { return $this->is_usable; } public function team() { return $this->belongsTo(Team::class); } public function awsUrl() { return "{$this->endpoint}/{$this->bucket}"; } protected function path(): Attribute { return Attribute::make( set: function (?string $value) { if ($value === null || $value === '') { return null; } return str($value)->trim()->start('/')->value(); } ); } /** * Trim whitespace from endpoint to prevent malformed URLs. */ protected function endpoint(): Attribute { return Attribute::make( set: fn (?string $value) => $value ? trim($value) : null, ); } /** * Trim whitespace from bucket name to prevent connection errors. */ protected function bucket(): Attribute { return Attribute::make( set: fn (?string $value) => $value ? trim($value) : null, ); } /** * Trim whitespace from region to prevent connection errors. */ protected function region(): Attribute { return Attribute::make( set: fn (?string $value) => $value ? trim($value) : null, ); } public function testConnection(bool $shouldSave = false) { try { $disk = Storage::build([ 'driver' => 's3', 'region' => $this['region'], 'key' => $this['key'], 'secret' => $this['secret'], 'bucket' => $this['bucket'], 'endpoint' => $this['endpoint'], 'use_path_style_endpoint' => true, ]); // Test the connection by listing files with ListObjectsV2 (S3) $disk->files(); $this->unusable_email_sent = false; $this->is_usable = true; } catch (\Throwable $e) { $this->is_usable = false; if ($this->unusable_email_sent === false && is_transactional_emails_enabled()) { $mail = new MailMessage; $mail->subject('Coolify: S3 Storage Connection Error'); $mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('storage.show', ['storage_uuid' => $this->uuid])]); // Load the team with its members and their roles explicitly $team = $this->team()->with(['members' => function ($query) { $query->withPivot('role'); }])->first(); // Get admins directly from the pivot relationship for this specific team $users = $team->members()->wherePivotIn('role', ['admin', 'owner'])->get(['users.id', 'users.email']); foreach ($users as $user) { send_user_an_email($mail, $user->email); } $this->unusable_email_sent = true; } throw $e; } finally { if ($shouldSave) { $this->save(); } } } } ================================================ FILE: app/Models/ScheduledDatabaseBackup.php ================================================ id)->orderBy('created_at', 'desc'); } public static function ownedByCurrentTeamAPI(int $teamId) { return ScheduledDatabaseBackup::whereRelation('team', 'id', $teamId)->orderBy('created_at', 'desc'); } public function team() { return $this->belongsTo(Team::class); } public function database(): MorphTo { return $this->morphTo(); } public function latest_log(): HasOne { return $this->hasOne(ScheduledDatabaseBackupExecution::class)->latest(); } public function executions(): HasMany { // Last execution first return $this->hasMany(ScheduledDatabaseBackupExecution::class)->orderBy('created_at', 'desc'); } public function s3() { return $this->belongsTo(S3Storage::class, 's3_storage_id'); } public function get_last_days_backup_status($days = 7) { return $this->hasMany(ScheduledDatabaseBackupExecution::class)->where('created_at', '>=', now()->subDays($days))->get(); } public function executionsPaginated(int $skip = 0, int $take = 10) { $executions = $this->hasMany(ScheduledDatabaseBackupExecution::class)->orderBy('created_at', 'desc'); $count = $executions->count(); $executions = $executions->skip($skip)->take($take)->get(); return [ 'count' => $count, 'executions' => $executions, ]; } public function server() { if ($this->database) { if ($this->database instanceof ServiceDatabase) { $destination = data_get($this->database->service, 'destination'); $server = data_get($destination, 'server'); } else { $destination = data_get($this->database, 'destination'); $server = data_get($destination, 'server'); } if ($server) { return $server; } } return null; } } ================================================ FILE: app/Models/ScheduledDatabaseBackupExecution.php ================================================ 'boolean', 'local_storage_deleted' => 'boolean', 's3_storage_deleted' => 'boolean', ]; } public function scheduledDatabaseBackup(): BelongsTo { return $this->belongsTo(ScheduledDatabaseBackup::class); } } ================================================ FILE: app/Models/ScheduledTask.php ================================================ ['type' => 'integer', 'description' => 'The unique identifier of the scheduled task in the database.'], 'uuid' => ['type' => 'string', 'description' => 'The unique identifier of the scheduled task.'], 'enabled' => ['type' => 'boolean', 'description' => 'The flag to indicate if the scheduled task is enabled.'], 'name' => ['type' => 'string', 'description' => 'The name of the scheduled task.'], 'command' => ['type' => 'string', 'description' => 'The command to execute.'], 'frequency' => ['type' => 'string', 'description' => 'The frequency of the scheduled task.'], 'container' => ['type' => 'string', 'nullable' => true, 'description' => 'The container where the command should be executed.'], 'timeout' => ['type' => 'integer', 'description' => 'The timeout of the scheduled task in seconds.'], 'created_at' => ['type' => 'string', 'format' => 'date-time', 'description' => 'The date and time when the scheduled task was created.'], 'updated_at' => ['type' => 'string', 'format' => 'date-time', 'description' => 'The date and time when the scheduled task was last updated.'], ], )] class ScheduledTask extends BaseModel { use HasFactory; use HasSafeStringAttribute; protected $guarded = []; public static function ownedByCurrentTeamAPI(int $teamId) { return static::where('team_id', $teamId)->orderBy('created_at', 'desc'); } protected function casts(): array { return [ 'enabled' => 'boolean', 'timeout' => 'integer', ]; } public function service() { return $this->belongsTo(Service::class); } public function application() { return $this->belongsTo(Application::class); } public function latest_log(): HasOne { return $this->hasOne(ScheduledTaskExecution::class)->latest(); } public function executions(): HasMany { // Last execution first return $this->hasMany(ScheduledTaskExecution::class)->orderBy('created_at', 'desc'); } public function server() { if ($this->application) { if ($this->application->destination && $this->application->destination->server) { return $this->application->destination->server; } } elseif ($this->service) { if ($this->service->destination && $this->service->destination->server) { return $this->service->destination->server; } } elseif ($this->database) { if ($this->database->destination && $this->database->destination->server) { return $this->database->destination->server; } } return null; } } ================================================ FILE: app/Models/ScheduledTaskExecution.php ================================================ ['type' => 'string', 'description' => 'The unique identifier of the execution.'], 'status' => ['type' => 'string', 'enum' => ['success', 'failed', 'running'], 'description' => 'The status of the execution.'], 'message' => ['type' => 'string', 'nullable' => true, 'description' => 'The output message of the execution.'], 'retry_count' => ['type' => 'integer', 'description' => 'The number of retries.'], 'duration' => ['type' => 'number', 'nullable' => true, 'description' => 'Duration in seconds.'], 'started_at' => ['type' => 'string', 'format' => 'date-time', 'nullable' => true, 'description' => 'When the execution started.'], 'finished_at' => ['type' => 'string', 'format' => 'date-time', 'nullable' => true, 'description' => 'When the execution finished.'], 'created_at' => ['type' => 'string', 'format' => 'date-time', 'description' => 'When the record was created.'], 'updated_at' => ['type' => 'string', 'format' => 'date-time', 'description' => 'When the record was last updated.'], ], )] class ScheduledTaskExecution extends BaseModel { protected $guarded = []; protected function casts(): array { return [ 'started_at' => 'datetime', 'finished_at' => 'datetime', 'retry_count' => 'integer', 'duration' => 'decimal:2', ]; } public function scheduledTask(): BelongsTo { return $this->belongsTo(ScheduledTask::class); } } ================================================ FILE: app/Models/Server.php ================================================ '3.5.0', // Current version (without 'v' prefix) * 'latest' => '3.5.2', // Latest patch version available * 'type' => 'patch_update', // Update type identifier * 'checked_at' => '2025-11-14T10:00:00Z', // ISO8601 timestamp * 'newer_branch_target' => 'v3.6', // (Optional) Available major/minor version * 'newer_branch_latest' => '3.6.2' // (Optional) Latest version in that branch * ] * ``` * * **For minor/major upgrades** (e.g., 3.5.6 → 3.6.2): * ```php * [ * 'current' => '3.5.6', // Current version * 'latest' => '3.6.2', // Latest version in target branch * 'type' => 'minor_upgrade', // Update type identifier * 'upgrade_target' => 'v3.6', // Target branch (with 'v' prefix) * 'checked_at' => '2025-11-14T10:00:00Z' // ISO8601 timestamp * ] * ``` * * **Null value**: Set to null when: * - Server is fully up-to-date with the latest version * - Traefik image uses the 'latest' tag (no fixed version tracking) * - No Traefik version detected on the server * * @see \App\Jobs\CheckTraefikVersionForServerJob Where this data is populated * @see \App\Livewire\Server\Proxy Where this data is read and displayed */ #[OA\Schema( description: 'Server model', type: 'object', properties: [ 'id' => ['type' => 'integer', 'description' => 'The server ID.'], 'uuid' => ['type' => 'string', 'description' => 'The server UUID.'], 'name' => ['type' => 'string', 'description' => 'The server name.'], 'description' => ['type' => 'string', 'description' => 'The server description.'], 'ip' => ['type' => 'string', 'description' => 'The IP address.'], 'user' => ['type' => 'string', 'description' => 'The user.'], 'port' => ['type' => 'integer', 'description' => 'The port number.'], 'proxy' => ['type' => 'object', 'description' => 'The proxy configuration.'], 'proxy_type' => ['type' => 'string', 'enum' => ['traefik', 'caddy', 'none'], 'description' => 'The proxy type.'], 'high_disk_usage_notification_sent' => ['type' => 'boolean', 'description' => 'The flag to indicate if the high disk usage notification has been sent.'], 'unreachable_notification_sent' => ['type' => 'boolean', 'description' => 'The flag to indicate if the unreachable notification has been sent.'], 'unreachable_count' => ['type' => 'integer', 'description' => 'The unreachable count for your server.'], 'validation_logs' => ['type' => 'string', 'description' => 'The validation logs.'], 'log_drain_notification_sent' => ['type' => 'boolean', 'description' => 'The flag to indicate if the log drain notification has been sent.'], 'swarm_cluster' => ['type' => 'string', 'description' => 'The swarm cluster configuration.'], 'settings' => ['$ref' => '#/components/schemas/ServerSetting'], ] )] class Server extends BaseModel { use ClearsGlobalSearchCache, HasFactory, HasMetrics, SchemalessAttributesTrait, SoftDeletes; public static $batch_counter = 0; /** * Identity map cache for request-scoped Server lookups. * Prevents N+1 queries when the same Server is accessed multiple times. */ private static ?array $identityMapCache = null; protected $appends = ['is_coolify_host']; protected static function booted() { static::saving(function ($server) { $payload = []; if ($server->user) { $payload['user'] = str($server->user)->trim(); } if ($server->ip) { $payload['ip'] = str($server->ip)->trim(); // Update ip_previous when ip is being changed if ($server->isDirty('ip') && $server->getOriginal('ip')) { $payload['ip_previous'] = $server->getOriginal('ip'); } } $server->forceFill($payload); }); static::saved(function ($server) { if ($server->privateKey?->isDirty()) { refresh_server_connection($server->privateKey); } }); static::created(function ($server) { ServerSetting::create([ 'server_id' => $server->id, ]); if ($server->id === 0) { if ($server->isSwarm()) { SwarmDocker::create([ 'id' => 0, 'name' => 'coolify', 'network' => 'coolify-overlay', 'server_id' => $server->id, ]); } else { StandaloneDocker::create([ 'id' => 0, 'name' => 'coolify', 'network' => 'coolify', 'server_id' => $server->id, ]); } } else { if ($server->isSwarm()) { SwarmDocker::create([ 'name' => 'coolify-overlay', 'network' => 'coolify-overlay', 'server_id' => $server->id, ]); } else { $standaloneDocker = new StandaloneDocker([ 'name' => 'coolify', 'uuid' => (string) new Cuid2, 'network' => 'coolify', 'server_id' => $server->id, ]); $standaloneDocker->saveQuietly(); } } if (! isset($server->proxy->redirect_enabled)) { $server->proxy->redirect_enabled = true; } }); static::retrieved(function ($server) { if (! isset($server->proxy->redirect_enabled)) { $server->proxy->redirect_enabled = true; } }); static::forceDeleting(function ($server) { $server->destinations()->each(function ($destination) { $destination->delete(); }); $server->settings()->delete(); $server->sslCertificates()->delete(); }); static::updated(function () { static::flushIdentityMap(); }); } /** * Find a Server by ID using the identity map cache. * This prevents N+1 queries when the same Server is accessed multiple times. */ public static function findCached($id): ?static { if ($id === null) { return null; } if (static::$identityMapCache === null) { static::$identityMapCache = []; } if (! isset(static::$identityMapCache[$id])) { static::$identityMapCache[$id] = static::query()->find($id); } return static::$identityMapCache[$id]; } /** * Flush the identity map cache. * Called automatically on update, and should be called in tests. */ public static function flushIdentityMap(): void { static::$identityMapCache = null; } protected $casts = [ 'proxy' => SchemalessAttributes::class, 'traefik_outdated_info' => 'array', 'server_metadata' => 'array', 'logdrain_axiom_api_key' => 'encrypted', 'logdrain_newrelic_license_key' => 'encrypted', 'delete_unused_volumes' => 'boolean', 'delete_unused_networks' => 'boolean', 'unreachable_notification_sent' => 'boolean', 'is_build_server' => 'boolean', 'force_disabled' => 'boolean', ]; protected $schemalessAttributes = [ 'proxy', ]; protected $fillable = [ 'name', 'ip', 'port', 'user', 'description', 'private_key_id', 'cloud_provider_token_id', 'team_id', 'hetzner_server_id', 'hetzner_server_status', 'is_validating', 'detected_traefik_version', 'traefik_outdated_info', 'server_metadata', ]; protected $guarded = []; use HasSafeStringAttribute; public function type() { return 'server'; } protected function isCoolifyHost(): Attribute { return Attribute::make( get: function () { return $this->id === 0; } ); } public static function isReachable() { return Server::ownedByCurrentTeam()->whereRelation('settings', 'is_reachable', true); } /** * Get query builder for servers owned by current team. * If you need all servers without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam(array $select = ['*']) { $teamId = currentTeam()->id; $selectArray = collect($select)->concat(['id']); return Server::whereTeamId($teamId)->with('settings', 'swarmDockers', 'standaloneDockers')->select($selectArray->all())->orderBy('name'); } /** * Get all servers owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return Server::ownedByCurrentTeam()->get(); }); } public static function isUsable() { return Server::ownedByCurrentTeam()->whereRelation('settings', 'is_reachable', true)->whereRelation('settings', 'is_usable', true)->whereRelation('settings', 'is_swarm_worker', false)->whereRelation('settings', 'is_build_server', false)->whereRelation('settings', 'force_disabled', false); } public function settings() { return $this->hasOne(ServerSetting::class); } public function dockerCleanupExecutions() { return $this->hasMany(DockerCleanupExecution::class); } public function proxySet() { return $this->proxyType() && $this->proxyType() !== 'NONE' && $this->isFunctional() && ! $this->isSwarmWorker() && ! $this->settings->is_build_server; } public function setupDefaultRedirect() { $banner = "# This file is generated by Coolify, do not edit it manually.\n". "# Disable the default redirect to customize (only if you know what are you doing).\n\n"; $dynamic_conf_path = $this->proxyPath().'/dynamic'; $proxy_type = $this->proxyType(); $redirect_enabled = $this->proxy->redirect_enabled ?? true; $redirect_url = $this->proxy->redirect_url; if (isDev()) { if ($proxy_type === ProxyTypes::CADDY->value) { $dynamic_conf_path = '/data/coolify/proxy/caddy/dynamic'; } } if ($proxy_type === ProxyTypes::TRAEFIK->value) { $default_redirect_file = "$dynamic_conf_path/default_redirect_503.yaml"; } elseif ($proxy_type === ProxyTypes::CADDY->value) { $default_redirect_file = "$dynamic_conf_path/default_redirect_503.caddy"; } instant_remote_process([ "mkdir -p $dynamic_conf_path", "rm -f $dynamic_conf_path/default_redirect_404.yaml", "rm -f $dynamic_conf_path/default_redirect_404.caddy", ], $this); if ($redirect_enabled === false) { instant_remote_process(["rm -f $default_redirect_file"], $this); } else { if ($proxy_type === ProxyTypes::CADDY->value) { if (filled($redirect_url)) { $conf = ":80, :443 { redir $redirect_url }"; } else { $conf = ':80, :443 { respond 503 }'; } } elseif ($proxy_type === ProxyTypes::TRAEFIK->value) { $dynamic_conf = [ 'http' => [ 'routers' => [ 'catchall' => [ 'entryPoints' => [ 0 => 'http', 1 => 'https', ], 'service' => 'noop', 'rule' => 'PathPrefix(`/`)', 'tls' => [ 'certResolver' => 'letsencrypt', ], 'priority' => -1000, ], ], 'services' => [ 'noop' => [ 'loadBalancer' => [ 'servers' => [], ], ], ], ], ]; if (filled($redirect_url)) { $dynamic_conf['http']['routers']['catchall']['middlewares'] = [ 0 => 'redirect-regexp', ]; $dynamic_conf['http']['services']['noop']['loadBalancer']['servers'][0] = [ 'url' => '', ]; $dynamic_conf['http']['middlewares'] = [ 'redirect-regexp' => [ 'redirectRegex' => [ 'regex' => '(.*)', 'replacement' => $redirect_url, 'permanent' => false, ], ], ]; } $conf = Yaml::dump($dynamic_conf, 12, 2); } $conf = $banner.$conf; $base64 = base64_encode($conf); instant_remote_process([ "echo '$base64' | base64 -d | tee $default_redirect_file > /dev/null", ], $this); } if ($proxy_type === 'CADDY') { $this->reloadCaddy(); } } public function setupDynamicProxyConfiguration() { $settings = instanceSettings(); $dynamic_config_path = $this->proxyPath().'/dynamic'; if ($this->proxyType() === ProxyTypes::TRAEFIK->value) { $file = "$dynamic_config_path/coolify.yaml"; if (empty($settings->fqdn) || (isCloud() && $this->id !== 0) || ! $this->isLocalhost()) { instant_remote_process([ "rm -f $file", ], $this); } else { $url = Url::fromString($settings->fqdn); $host = $url->getHost(); $schema = $url->getScheme(); $traefik_dynamic_conf = [ 'http' => [ 'middlewares' => [ 'redirect-to-https' => [ 'redirectscheme' => [ 'scheme' => 'https', ], ], 'gzip' => [ 'compress' => true, ], ], 'routers' => [ 'coolify-http' => [ 'middlewares' => [ 0 => 'gzip', ], 'entryPoints' => [ 0 => 'http', ], 'service' => 'coolify', 'rule' => "Host(`{$host}`)", ], 'coolify-realtime-ws' => [ 'entryPoints' => [ 0 => 'http', ], 'service' => 'coolify-realtime', 'rule' => "Host(`{$host}`) && PathPrefix(`/app`)", ], 'coolify-terminal-ws' => [ 'entryPoints' => [ 0 => 'http', ], 'service' => 'coolify-terminal', 'rule' => "Host(`{$host}`) && PathPrefix(`/terminal/ws`)", ], ], 'services' => [ 'coolify' => [ 'loadBalancer' => [ 'servers' => [ 0 => [ 'url' => 'http://coolify:8080', ], ], ], ], 'coolify-realtime' => [ 'loadBalancer' => [ 'servers' => [ 0 => [ 'url' => 'http://coolify-realtime:6001', ], ], ], ], 'coolify-terminal' => [ 'loadBalancer' => [ 'servers' => [ 0 => [ 'url' => 'http://coolify-realtime:6002', ], ], ], ], ], ], ]; if ($schema === 'https') { $traefik_dynamic_conf['http']['routers']['coolify-http']['middlewares'] = [ 0 => 'redirect-to-https', ]; $traefik_dynamic_conf['http']['routers']['coolify-https'] = [ 'entryPoints' => [ 0 => 'https', ], 'service' => 'coolify', 'rule' => "Host(`{$host}`)", 'tls' => [ 'certresolver' => 'letsencrypt', ], ]; $traefik_dynamic_conf['http']['routers']['coolify-realtime-wss'] = [ 'entryPoints' => [ 0 => 'https', ], 'service' => 'coolify-realtime', 'rule' => "Host(`{$host}`) && PathPrefix(`/app`)", 'tls' => [ 'certresolver' => 'letsencrypt', ], ]; $traefik_dynamic_conf['http']['routers']['coolify-terminal-wss'] = [ 'entryPoints' => [ 0 => 'https', ], 'service' => 'coolify-terminal', 'rule' => "Host(`{$host}`) && PathPrefix(`/terminal/ws`)", 'tls' => [ 'certresolver' => 'letsencrypt', ], ]; } $yaml = Yaml::dump($traefik_dynamic_conf, 12, 2); $yaml = "# This file is automatically generated by Coolify.\n". "# Do not edit it manually (only if you know what are you doing).\n\n". $yaml; $base64 = base64_encode($yaml); instant_remote_process([ "mkdir -p $dynamic_config_path", "echo '$base64' | base64 -d | tee $file > /dev/null", ], $this); } } elseif ($this->proxyType() === 'CADDY') { $file = "$dynamic_config_path/coolify.caddy"; if (empty($settings->fqdn) || (isCloud() && $this->id !== 0) || ! $this->isLocalhost()) { instant_remote_process([ "rm -f $file", ], $this); $this->reloadCaddy(); } else { $url = Url::fromString($settings->fqdn); $host = $url->getHost(); $schema = $url->getScheme(); $caddy_file = " $schema://$host { handle /app/* { reverse_proxy coolify-realtime:6001 } handle /terminal/ws { reverse_proxy coolify-realtime:6002 } reverse_proxy coolify:8080 }"; $base64 = base64_encode($caddy_file); instant_remote_process([ "echo '$base64' | base64 -d | tee $file > /dev/null", ], $this); $this->reloadCaddy(); } } } public function reloadCaddy() { return instant_remote_process([ 'docker exec coolify-proxy caddy reload --config /config/caddy/Caddyfile.autosave', ], $this); } public function proxyPath() { $base_path = config('constants.coolify.base_config_path'); $proxyType = $this->proxyType(); $proxy_path = "$base_path/proxy"; if ($proxyType === ProxyTypes::TRAEFIK->value) { $proxy_path = $proxy_path.'/'; } elseif ($proxyType === ProxyTypes::CADDY->value) { $proxy_path = $proxy_path.'/caddy'; } elseif ($proxyType === ProxyTypes::NGINX->value) { $proxy_path = $proxy_path.'/nginx'; } return $proxy_path; } public function proxyType() { return data_get($this->proxy, 'type'); } public function scopeWithProxy(): Builder { return $this->proxy->modelScope(); } public function scopeWhereProxyType(Builder $query, string $proxyType): Builder { return $query->where('proxy->type', $proxyType); } public function isLocalhost() { return $this->ip === 'host.docker.internal' || $this->id === 0; } public static function buildServers($teamId) { return Server::whereTeamId($teamId)->whereRelation('settings', 'is_reachable', true)->whereRelation('settings', 'is_build_server', true); } public function isForceDisabled() { return $this->settings->force_disabled; } public function forceEnableServer() { $this->settings->force_disabled = false; $this->settings->save(); } public function forceDisableServer() { $this->settings->force_disabled = true; $this->settings->save(); $sshKeyFileLocation = "id.root@{$this->uuid}"; Storage::disk('ssh-keys')->delete($sshKeyFileLocation); $this->disableSshMux(); } public function sentinelHeartbeat(bool $isReset = false) { $this->sentinel_updated_at = $isReset ? now()->subMinutes(6000) : now(); $this->save(); } /** * Get the wait time for Sentinel to push before performing an SSH check. * * @return int The wait time in seconds. */ public function waitBeforeDoingSshCheck(): int { $wait = $this->settings->sentinel_push_interval_seconds * 3; if ($wait < 120) { $wait = 120; } return $wait; } public function isSentinelLive() { return Carbon::parse($this->sentinel_updated_at)->isAfter(now()->subSeconds($this->waitBeforeDoingSshCheck())); } public function isSentinelEnabled() { return ($this->isMetricsEnabled() || $this->isServerApiEnabled()) && ! $this->isBuildServer(); } public function isMetricsEnabled() { return $this->settings->is_metrics_enabled; } public function isServerApiEnabled() { return $this->settings->is_sentinel_enabled; } public function checkSentinel() { CheckAndStartSentinelJob::dispatch($this); } public function getDiskUsage(): ?string { return instant_remote_process(['df / --output=pcent | tr -cd 0-9'], $this, false); // return instant_remote_process(["df /| tail -1 | awk '{ print $5}' | sed 's/%//g'"], $this, false); } public function definedResources() { $applications = $this->applications(); $databases = $this->databases(); $services = $this->services(); return $applications->concat($databases)->concat($services->get()); } public function stopUnmanaged($id) { return instant_remote_process(["docker stop -t 0 $id"], $this); } public function restartUnmanaged($id) { return instant_remote_process(["docker restart $id"], $this); } public function startUnmanaged($id) { return instant_remote_process(["docker start $id"], $this); } public function getContainers() { $containers = collect([]); $containerReplicates = collect([]); if ($this->isSwarm()) { $containers = instant_remote_process_with_timeout(["docker service inspect $(docker service ls -q) --format '{{json .}}'"], $this, false); $containers = format_docker_command_output_to_json($containers); $containerReplicates = instant_remote_process_with_timeout(["docker service ls --format '{{json .}}'"], $this, false); if ($containerReplicates) { $containerReplicates = format_docker_command_output_to_json($containerReplicates); foreach ($containerReplicates as $containerReplica) { $name = data_get($containerReplica, 'Name'); $containers = $containers->map(function ($container) use ($name, $containerReplica) { if (data_get($container, 'Spec.Name') === $name) { $replicas = data_get($containerReplica, 'Replicas'); $running = str($replicas)->explode('/')[0]; $total = str($replicas)->explode('/')[1]; if ($running === $total) { data_set($container, 'State.Status', 'running'); data_set($container, 'State.Health.Status', 'healthy'); } else { data_set($container, 'State.Status', 'starting'); data_set($container, 'State.Health.Status', 'unhealthy'); } } return $container; }); } } } else { $containers = instant_remote_process_with_timeout(["docker container inspect $(docker container ls -aq) --format '{{json .}}'"], $this, false); $containers = format_docker_command_output_to_json($containers); $containerReplicates = collect([]); } return [ 'containers' => collect($containers) ?? collect([]), 'containerReplicates' => collect($containerReplicates) ?? collect([]), ]; } public function loadAllContainers(): Collection { if ($this->isFunctional()) { $containers = instant_remote_process(["docker ps -a --format '{{json .}}'"], $this); $containers = format_docker_command_output_to_json($containers); return collect($containers); } return collect([]); } public function loadUnmanagedContainers(): Collection { if ($this->isFunctional()) { $containers = instant_remote_process(["docker ps -a --format '{{json .}}'"], $this); $containers = format_docker_command_output_to_json($containers); $containers = $containers->map(function ($container) { $labels = data_get($container, 'Labels'); if (! str($labels)->contains('coolify.managed')) { return $container; } return null; }); $containers = $containers->filter(); return collect($containers); } else { return collect([]); } } public function hasDefinedResources() { $applications = $this->applications()->count() > 0; $databases = $this->databases()->count() > 0; $services = $this->services()->count() > 0; if ($applications || $databases || $services) { return true; } return false; } public function databases() { // Get destination IDs for this server in two efficient queries $standaloneDockerIds = StandaloneDocker::where('server_id', $this->id)->pluck('id'); $swarmDockerIds = SwarmDocker::where('server_id', $this->id)->pluck('id'); $destinationCondition = function ($query) use ($standaloneDockerIds, $swarmDockerIds) { $query->where(function ($q) use ($standaloneDockerIds) { $q->where('destination_type', StandaloneDocker::class) ->whereIn('destination_id', $standaloneDockerIds); })->orWhere(function ($q) use ($swarmDockerIds) { $q->where('destination_type', SwarmDocker::class) ->whereIn('destination_id', $swarmDockerIds); }); }; // Query each database type with the destination condition $postgresqls = StandalonePostgresql::where($destinationCondition)->get(); $redis = StandaloneRedis::where($destinationCondition)->get(); $mongodbs = StandaloneMongodb::where($destinationCondition)->get(); $mysqls = StandaloneMysql::where($destinationCondition)->get(); $mariadbs = StandaloneMariadb::where($destinationCondition)->get(); $keydbs = StandaloneKeydb::where($destinationCondition)->get(); $dragonflies = StandaloneDragonfly::where($destinationCondition)->get(); $clickhouses = StandaloneClickhouse::where($destinationCondition)->get(); return $postgresqls ->concat($redis) ->concat($mongodbs) ->concat($mysqls) ->concat($mariadbs) ->concat($keydbs) ->concat($dragonflies) ->concat($clickhouses) ->filter(fn ($item) => data_get($item, 'name') !== 'coolify-db'); } public function applications() { // Get destination IDs for this server in two efficient queries $standaloneDockerIds = StandaloneDocker::where('server_id', $this->id)->pluck('id'); $swarmDockerIds = SwarmDocker::where('server_id', $this->id)->pluck('id'); // Query all applications in a single query using polymorphic conditions $applications = Application::where(function ($query) use ($standaloneDockerIds, $swarmDockerIds) { $query->where(function ($q) use ($standaloneDockerIds) { $q->where('destination_type', StandaloneDocker::class) ->whereIn('destination_id', $standaloneDockerIds); })->orWhere(function ($q) use ($swarmDockerIds) { $q->where('destination_type', SwarmDocker::class) ->whereIn('destination_id', $swarmDockerIds); }); })->get(); // Get additional server applications $additionalApplicationIds = DB::table('additional_destinations') ->where('server_id', $this->id) ->pluck('application_id'); if ($additionalApplicationIds->isNotEmpty()) { $additionalApps = Application::whereIn('id', $additionalApplicationIds)->get(); $applications = $applications->concat($additionalApps); } return $applications; } public function dockerComposeBasedApplications() { return $this->applications()->filter(function ($application) { return data_get($application, 'build_pack') === 'dockercompose'; }); } public function dockerComposeBasedPreviewDeployments() { return $this->previews()->filter(function ($preview) { $applicationId = data_get($preview, 'application_id'); $application = Application::find($applicationId); if (! $application) { return false; } return data_get($application, 'build_pack') === 'dockercompose'; }); } public function services() { return $this->hasMany(Service::class); } public function port(): Attribute { return Attribute::make( get: function ($value) { return (int) preg_replace('/[^0-9]/', '', $value); }, set: function ($value) { return (int) preg_replace('/[^0-9]/', '', (string) $value); } ); } public function user(): Attribute { return Attribute::make( get: function ($value) { return preg_replace('/[^A-Za-z0-9\-_]/', '', $value); }, set: function ($value) { return preg_replace('/[^A-Za-z0-9\-_]/', '', $value); } ); } public function ip(): Attribute { return Attribute::make( get: function ($value) { return preg_replace('/[^0-9a-zA-Z.:%-]/', '', $value); }, set: function ($value) { return preg_replace('/[^0-9a-zA-Z.:%-]/', '', $value); } ); } public function getIp(): Attribute { return Attribute::make( get: function () { if (isDev()) { return '127.0.0.1'; } if ($this->isLocalhost()) { return base_ip(); } return $this->ip; } ); } public function previews() { return $this->destinations()->map(function ($standaloneDocker) { return $standaloneDocker->applications->map(function ($application) { return $application->previews; })->flatten(); })->flatten(); } public function destinations() { $standalone_docker = $this->hasMany(StandaloneDocker::class)->get(); $swarm_docker = $this->hasMany(SwarmDocker::class)->get(); return $standalone_docker->concat($swarm_docker); } public function standaloneDockers() { return $this->hasMany(StandaloneDocker::class); } public function swarmDockers() { return $this->hasMany(SwarmDocker::class); } public function privateKey() { return $this->belongsTo(PrivateKey::class); } public function cloudProviderToken() { return $this->belongsTo(CloudProviderToken::class); } public function sslCertificates() { return $this->hasMany(SslCertificate::class); } public function muxFilename() { return 'mux_'.$this->uuid; } public function team() { return $this->belongsTo(Team::class); } public function isProxyShouldRun() { // TODO: Do we need "|| $this->proxy->force_stop" here? if ($this->proxyType() === ProxyTypes::NONE->value || $this->isBuildServer()) { return false; } return true; } public function skipServer() { if ($this->ip === '1.2.3.4') { return true; } if ($this->settings->force_disabled === true) { return true; } return false; } public function isFunctional() { $isFunctional = data_get($this->settings, 'is_reachable') && data_get($this->settings, 'is_usable') && data_get($this->settings, 'force_disabled') === false && $this->ip !== '1.2.3.4'; if ($isFunctional === false) { Storage::disk('ssh-mux')->delete($this->muxFilename()); } return $isFunctional; } public function isLogDrainEnabled() { return $this->settings->is_logdrain_newrelic_enabled || $this->settings->is_logdrain_highlight_enabled || $this->settings->is_logdrain_axiom_enabled || $this->settings->is_logdrain_custom_enabled; } public function validateOS(): bool|Stringable { $os_release = instant_remote_process(['cat /etc/os-release'], $this); $releaseLines = collect(explode("\n", $os_release)); $collectedData = collect([]); foreach ($releaseLines as $line) { $item = str($line)->trim(); $collectedData->put($item->before('=')->value(), $item->after('=')->lower()->replace('"', '')->value()); } $ID = data_get($collectedData, 'ID'); // $ID_LIKE = data_get($collectedData, 'ID_LIKE'); // $VERSION_ID = data_get($collectedData, 'VERSION_ID'); $supported = collect(SUPPORTED_OS)->filter(function ($supportedOs) use ($ID) { if (str($supportedOs)->contains($ID)) { return str($ID); } }); if ($supported->count() === 1) { return str($supported->first()); } else { return false; } } public function gatherServerMetadata(): ?array { if (! $this->isFunctional()) { return null; } try { $output = instant_remote_process([ 'echo "---PRETTY_NAME---" && grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d \'"\' && echo "---ARCH---" && uname -m && echo "---KERNEL---" && uname -r && echo "---CPUS---" && nproc && echo "---MEMORY---" && free -b | awk \'/Mem:/{print $2}\' && echo "---UPTIME_SINCE---" && uptime -s', ], $this, false); if (! $output) { return null; } $sections = []; $currentKey = null; foreach (explode("\n", trim($output)) as $line) { $line = trim($line); if (preg_match('/^---(\w+)---$/', $line, $m)) { $currentKey = $m[1]; } elseif ($currentKey) { $sections[$currentKey] = $line; } } $metadata = [ 'os' => $sections['PRETTY_NAME'] ?? 'Unknown', 'arch' => $sections['ARCH'] ?? 'Unknown', 'kernel' => $sections['KERNEL'] ?? 'Unknown', 'cpus' => (int) ($sections['CPUS'] ?? 0), 'memory_bytes' => (int) ($sections['MEMORY'] ?? 0), 'uptime_since' => $sections['UPTIME_SINCE'] ?? null, 'collected_at' => now()->toIso8601String(), ]; $this->update(['server_metadata' => $metadata]); return $metadata; } catch (\Throwable $e) { Log::debug('Failed to gather server metadata', [ 'server_id' => $this->id, 'error' => $e->getMessage(), ]); return null; } } public function isTerminalEnabled() { return $this->settings->is_terminal_enabled ?? false; } public function isSwarm() { return data_get($this, 'settings.is_swarm_manager') || data_get($this, 'settings.is_swarm_worker'); } public function isSwarmManager() { return data_get($this, 'settings.is_swarm_manager'); } public function isSwarmWorker() { return data_get($this, 'settings.is_swarm_worker'); } public function serverStatus(): bool { if ($this->status() === false) { return false; } if ($this->isFunctional() === false) { return false; } return true; } public function status(): bool { ['uptime' => $uptime] = $this->validateConnection(); if ($uptime === false) { foreach ($this->applications() as $application) { $application->status = 'exited'; $application->save(); } foreach ($this->databases() as $database) { $database->status = 'exited'; $database->save(); } foreach ($this->services() as $service) { $apps = $service->applications()->get(); $dbs = $service->databases()->get(); foreach ($apps as $app) { $app->status = 'exited'; $app->save(); } foreach ($dbs as $db) { $db->status = 'exited'; $db->save(); } } return false; } return true; } public function isReachableChanged() { $this->refresh(); $unreachableNotificationSent = (bool) $this->unreachable_notification_sent; $isReachable = (bool) $this->settings->is_reachable; if ($isReachable === true) { $this->unreachable_count = 0; $this->save(); if ($unreachableNotificationSent === true) { $this->sendReachableNotification(); } return; } $this->increment('unreachable_count'); if ($this->unreachable_count === 1) { $this->settings->is_reachable = true; $this->settings->save(); return; } if ($this->unreachable_count >= 2 && ! $unreachableNotificationSent) { $failedChecks = 0; for ($i = 0; $i < 3; $i++) { $status = $this->serverStatus(); sleep(5); if (! $status) { $failedChecks++; } } if ($failedChecks === 3 && ! $unreachableNotificationSent) { $this->sendUnreachableNotification(); } } } public function sendReachableNotification() { $this->unreachable_notification_sent = false; $this->save(); $this->refresh(); $this->team->notify(new Reachable($this)); } public function sendUnreachableNotification() { $this->unreachable_notification_sent = true; $this->save(); $this->refresh(); $this->team->notify(new Unreachable($this)); } public function validateConnection(bool $justCheckingNewKey = false) { $this->disableSshMux(); if ($this->skipServer()) { return ['uptime' => false, 'error' => 'Server skipped.']; } try { instant_remote_process(['ls /'], $this); if ($this->settings->is_reachable === false) { $this->settings->is_reachable = true; $this->settings->save(); ServerReachabilityChanged::dispatch($this); } return ['uptime' => true, 'error' => null]; } catch (\Throwable $e) { if ($justCheckingNewKey) { return ['uptime' => false, 'error' => 'This key is not valid for this server.']; } if ($this->settings->is_reachable === true) { $this->settings->is_reachable = false; $this->settings->save(); ServerReachabilityChanged::dispatch($this); } return ['uptime' => false, 'error' => $e->getMessage()]; } } public function installDocker() { return InstallDocker::run($this); } /** * Validate that required commands are available on the server. * * @return array{success: bool, missing: array, found: array} */ public function validatePrerequisites(): array { return ValidatePrerequisites::run($this); } public function installPrerequisites() { return InstallPrerequisites::run($this); } public function validateDockerEngine($throwError = false) { $dockerBinary = instant_remote_process(['command -v docker'], $this, false, no_sudo: true); if (is_null($dockerBinary)) { $this->settings->is_usable = false; $this->settings->save(); if ($throwError) { throw new \Exception('Server is not usable. Docker Engine is not installed.'); } return false; } try { instant_remote_process(['docker version'], $this); } catch (\Throwable $e) { $this->settings->is_usable = false; $this->settings->save(); if ($throwError) { throw new \Exception('Server is not usable. Docker Engine is not running.'); } return false; } $this->settings->is_usable = true; $this->settings->save(); $this->validateCoolifyNetwork(isSwarm: false, isBuildServer: $this->settings->is_build_server); return true; } public function validateDockerCompose($throwError = false) { $dockerCompose = instant_remote_process(['docker compose version'], $this, false); if (is_null($dockerCompose)) { $this->settings->is_usable = false; $this->settings->save(); if ($throwError) { throw new \Exception('Server is not usable. Docker Compose is not installed.'); } return false; } $this->settings->is_usable = true; $this->settings->save(); return true; } public function validateDockerSwarm() { $swarmStatus = instant_remote_process(['docker info|grep -i swarm'], $this, false); $swarmStatus = str($swarmStatus)->trim()->after(':')->trim(); if ($swarmStatus === 'inactive') { throw new \Exception('Docker Swarm is not initiated. Please join the server to a swarm before continuing.'); return false; } $this->settings->is_usable = true; $this->settings->save(); $this->validateCoolifyNetwork(isSwarm: true); return true; } public function validateDockerEngineVersion() { $dockerVersionRaw = instant_remote_process(['docker version --format json'], $this, false); $dockerVersionJson = json_decode($dockerVersionRaw, true); $dockerVersion = data_get($dockerVersionJson, 'Server.Version', '0.0.0'); $dockerVersion = checkMinimumDockerEngineVersion($dockerVersion); if (is_null($dockerVersion)) { $this->settings->is_usable = false; $this->settings->save(); return false; } $this->settings->is_reachable = true; $this->settings->is_usable = true; $this->settings->save(); ServerReachabilityChanged::dispatch($this); return true; } public function validateCoolifyNetwork($isSwarm = false, $isBuildServer = false) { if ($isBuildServer) { return; } if ($isSwarm) { return instant_remote_process(['docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true'], $this, false); } else { return instant_remote_process(['docker network create coolify --attachable >/dev/null 2>&1 || true'], $this, false); } } public function isNonRoot() { if ($this->user instanceof Stringable) { return $this->user->value() !== 'root'; } return $this->user !== 'root'; } public function isBuildServer() { return $this->settings->is_build_server; } public static function createWithPrivateKey(array $data, PrivateKey $privateKey) { $server = new self($data); $server->privateKey()->associate($privateKey); $server->save(); return $server; } public function updateWithPrivateKey(array $data, ?PrivateKey $privateKey = null) { $this->update($data); if ($privateKey) { $this->privateKey()->associate($privateKey); $this->save(); } return $this; } public function storageCheck(): ?string { $commands = [ 'df / --output=pcent | tr -cd 0-9', ]; return instant_remote_process($commands, $this, false); } public function isIpv6(): bool { return str($this->ip)->contains(':'); } public function restartSentinel(?string $customImage = null, bool $async = true) { try { if ($async) { StartSentinel::dispatch($this, true, null, $customImage); } else { StartSentinel::run($this, true, null, $customImage); } } catch (\Throwable $e) { return handleError($e); } } public function url() { return base_url().'/server/'.$this->uuid; } public function restartContainer(string $containerName) { return instant_remote_process(['docker restart '.$containerName], $this, false); } public function changeProxy(string $proxyType, bool $async = true) { $validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) { return str($proxyType->value)->lower(); }); if ($validProxyTypes->contains(str($proxyType)->lower())) { $this->proxy->set('type', str($proxyType)->upper()); $this->proxy->set('status', 'exited'); $this->save(); if ($this->proxySet()) { if ($async) { StartProxy::dispatch($this); } else { StartProxy::run($this); } } } else { throw new \Exception('Invalid proxy type.'); } } public function isEmpty() { return $this->applications()->count() == 0 && $this->databases()->count() == 0 && $this->services()->count() == 0; } private function disableSshMux(): void { $configRepository = app(ConfigurationRepository::class); $configRepository->disableSshMux(); } public function generateCaCertificate() { try { ray('Generating CA certificate for server', $this->id); SslHelper::generateSslCertificate( commonName: 'Coolify CA Certificate', serverId: $this->id, isCaCertificate: true, validityDays: 10 * 365 ); $caCertificate = $this->sslCertificates()->where('is_ca_certificate', true)->first(); ray('CA certificate generated', $caCertificate); if ($caCertificate) { $certificateContent = $caCertificate->ssl_certificate; $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; $base64Cert = base64_encode($certificateContent); $commands = collect([ "mkdir -p $caCertPath", "chown -R 9999:root $caCertPath", "chmod -R 700 $caCertPath", "rm -rf $caCertPath/coolify-ca.crt", "echo '{$base64Cert}' | base64 -d | tee $caCertPath/coolify-ca.crt > /dev/null", "chmod 644 $caCertPath/coolify-ca.crt", ]); instant_remote_process($commands, $this, false); dispatch(new RegenerateSslCertJob( server_id: $this->id, force_regeneration: true )); } } catch (\Throwable $e) { return handleError($e); } } } ================================================ FILE: app/Models/ServerSetting.php ================================================ ['type' => 'integer'], 'concurrent_builds' => ['type' => 'integer'], 'deployment_queue_limit' => ['type' => 'integer'], 'dynamic_timeout' => ['type' => 'integer'], 'force_disabled' => ['type' => 'boolean'], 'force_server_cleanup' => ['type' => 'boolean'], 'is_build_server' => ['type' => 'boolean'], 'is_cloudflare_tunnel' => ['type' => 'boolean'], 'is_jump_server' => ['type' => 'boolean'], 'is_logdrain_axiom_enabled' => ['type' => 'boolean'], 'is_logdrain_custom_enabled' => ['type' => 'boolean'], 'is_logdrain_highlight_enabled' => ['type' => 'boolean'], 'is_logdrain_newrelic_enabled' => ['type' => 'boolean'], 'is_metrics_enabled' => ['type' => 'boolean'], 'is_reachable' => ['type' => 'boolean'], 'is_sentinel_enabled' => ['type' => 'boolean'], 'is_swarm_manager' => ['type' => 'boolean'], 'is_swarm_worker' => ['type' => 'boolean'], 'is_terminal_enabled' => ['type' => 'boolean'], 'is_usable' => ['type' => 'boolean'], 'logdrain_axiom_api_key' => ['type' => 'string'], 'logdrain_axiom_dataset_name' => ['type' => 'string'], 'logdrain_custom_config' => ['type' => 'string'], 'logdrain_custom_config_parser' => ['type' => 'string'], 'logdrain_highlight_project_id' => ['type' => 'string'], 'logdrain_newrelic_base_uri' => ['type' => 'string'], 'logdrain_newrelic_license_key' => ['type' => 'string'], 'sentinel_metrics_history_days' => ['type' => 'integer'], 'sentinel_metrics_refresh_rate_seconds' => ['type' => 'integer'], 'sentinel_token' => ['type' => 'string'], 'docker_cleanup_frequency' => ['type' => 'string'], 'docker_cleanup_threshold' => ['type' => 'integer'], 'server_id' => ['type' => 'integer'], 'wildcard_domain' => ['type' => 'string'], 'created_at' => ['type' => 'string'], 'updated_at' => ['type' => 'string'], 'delete_unused_volumes' => ['type' => 'boolean', 'description' => 'The flag to indicate if the unused volumes should be deleted.'], 'delete_unused_networks' => ['type' => 'boolean', 'description' => 'The flag to indicate if the unused networks should be deleted.'], ] )] class ServerSetting extends Model { protected $guarded = []; protected $casts = [ 'force_docker_cleanup' => 'boolean', 'docker_cleanup_threshold' => 'integer', 'sentinel_token' => 'encrypted', 'is_reachable' => 'boolean', 'is_usable' => 'boolean', 'is_terminal_enabled' => 'boolean', 'disable_application_image_retention' => 'boolean', ]; protected static function booted() { static::creating(function ($setting) { try { if (str($setting->sentinel_token)->isEmpty()) { $setting->generateSentinelToken(save: false, ignoreEvent: true); } if (str($setting->sentinel_custom_url)->isEmpty()) { $setting->generateSentinelUrl(save: false, ignoreEvent: true); } } catch (\Throwable $e) { Log::error('Error creating server setting: '.$e->getMessage()); } }); static::updated(function ($settings) { if ( $settings->wasChanged('sentinel_token') || $settings->wasChanged('sentinel_custom_url') || $settings->wasChanged('sentinel_metrics_refresh_rate_seconds') || $settings->wasChanged('sentinel_metrics_history_days') || $settings->wasChanged('sentinel_push_interval_seconds') ) { $settings->server->restartSentinel(); } }); } /** * Validate that a sentinel token contains only safe characters. * Prevents OS command injection when the token is interpolated into shell commands. */ public static function isValidSentinelToken(string $token): bool { return (bool) preg_match('/\A[a-zA-Z0-9._\-+=\/]+\z/', $token); } public function generateSentinelToken(bool $save = true, bool $ignoreEvent = false) { $data = [ 'server_uuid' => $this->server->uuid, ]; $token = json_encode($data); $encrypted = encrypt($token); $this->sentinel_token = $encrypted; if ($save) { if ($ignoreEvent) { $this->saveQuietly(); } else { $this->save(); } } return $token; } public function generateSentinelUrl(bool $save = true, bool $ignoreEvent = false) { $domain = null; $settings = InstanceSettings::get(); if ($this->server->isLocalhost()) { $domain = 'http://host.docker.internal:8000'; } elseif ($settings->fqdn) { $domain = $settings->fqdn; } elseif ($settings->public_ipv4) { $domain = 'http://'.$settings->public_ipv4.':8000'; } elseif ($settings->public_ipv6) { $domain = 'http://'.$settings->public_ipv6.':8000'; } $this->sentinel_custom_url = $domain; if ($save) { if ($ignoreEvent) { $this->saveQuietly(); } else { $this->save(); } } return $domain; } public function server() { return $this->belongsTo(Server::class); } public function dockerCleanupFrequency(): Attribute { return Attribute::make( set: function ($value) { return translate_cron_expression($value); }, get: function ($value) { return translate_cron_expression($value); } ); } } ================================================ FILE: app/Models/Service.php ================================================ ['type' => 'integer', 'description' => 'The unique identifier of the service. Only used for database identification.'], 'uuid' => ['type' => 'string', 'description' => 'The unique identifier of the service.'], 'name' => ['type' => 'string', 'description' => 'The name of the service.'], 'environment_id' => ['type' => 'integer', 'description' => 'The unique identifier of the environment where the service is attached to.'], 'server_id' => ['type' => 'integer', 'description' => 'The unique identifier of the server where the service is running.'], 'description' => ['type' => 'string', 'description' => 'The description of the service.'], 'docker_compose_raw' => ['type' => 'string', 'description' => 'The raw docker-compose.yml file of the service.'], 'docker_compose' => ['type' => 'string', 'description' => 'The docker-compose.yml file that is parsed and modified by Coolify.'], 'destination_type' => ['type' => 'string', 'description' => 'Destination type.'], 'destination_id' => ['type' => 'integer', 'description' => 'The unique identifier of the destination where the service is running.'], 'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'description' => 'The flag to enable the container label escape.'], 'is_container_label_readonly_enabled' => ['type' => 'boolean', 'description' => 'The flag to enable the container label readonly.'], 'config_hash' => ['type' => 'string', 'description' => 'The hash of the service configuration.'], 'service_type' => ['type' => 'string', 'description' => 'The type of the service.'], 'created_at' => ['type' => 'string', 'description' => 'The date and time when the service was created.'], 'updated_at' => ['type' => 'string', 'description' => 'The date and time when the service was last updated.'], 'deleted_at' => ['type' => 'string', 'description' => 'The date and time when the service was deleted.'], ], )] class Service extends BaseModel { use ClearsGlobalSearchCache, HasFactory, HasSafeStringAttribute, SoftDeletes; private static $parserVersion = '5'; protected $guarded = []; protected $appends = ['server_status', 'status']; protected static function booted() { static::creating(function ($service) { if (blank($service->name)) { $service->name = 'service-'.(new Cuid2); } }); static::created(function ($service) { $service->compose_parsing_version = self::$parserVersion; $service->save(); }); } public function isConfigurationChanged(bool $save = false) { $domains = $this->applications()->get()->pluck('fqdn')->sort()->toArray(); $domains = implode(',', $domains); $applicationImages = $this->applications()->get()->pluck('image')->sort(); $databaseImages = $this->databases()->get()->pluck('image')->sort(); $images = $applicationImages->merge($databaseImages); $images = implode(',', $images->toArray()); $applicationStorages = $this->applications()->get()->pluck('persistentStorages')->flatten()->sortBy('id'); $databaseStorages = $this->databases()->get()->pluck('persistentStorages')->flatten()->sortBy('id'); $storages = $applicationStorages->merge($databaseStorages)->implode('updated_at'); $newConfigHash = $images.$domains.$images.$storages; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->server->isFunctional(); } ); } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->contains('exited'); } public function isStarting(): bool { try { $activity = Activity::where('properties->type_uuid', $this->uuid)->latest()->first(); $status = data_get($activity, 'properties.status'); return $status === ProcessStatus::QUEUED->value || $status === ProcessStatus::IN_PROGRESS->value; } catch (\Throwable) { return false; } } public function type() { return 'service'; } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } /** * Get query builder for services owned by current team. * If you need all services without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return Service::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all services owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return Service::ownedByCurrentTeam()->get(); }); } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteConnectedNetworks() { $server = data_get($this, 'destination.server'); instant_remote_process(["docker network disconnect {$this->uuid} coolify-proxy"], $server, false); instant_remote_process(["docker network rm {$this->uuid}"], $server, false); } /** * Calculate the service's aggregate status from its applications and databases. * * This method aggregates status from Eloquent model relationships (not Docker containers). * It differs from the CalculatesExcludedStatus trait which works with Docker container objects * during container inspection. This accessor runs on-demand for UI display and works with * already-stored status strings from the database. * * Status format: "{status}:{health}" or "{status}:{health}:excluded" * - Status values: running, exited, degraded, starting, paused, restarting * - Health values: healthy, unhealthy, unknown * - :excluded suffix: Indicates all containers are excluded from health monitoring * * @return string The aggregate status in format "status:health" or "status:health:excluded" */ public function getStatusAttribute() { if ($this->isStarting()) { return 'starting:unhealthy'; } $applications = $this->applications; $databases = $this->databases; [$complexStatus, $complexHealth, $hasNonExcluded] = $this->aggregateResourceStatuses( $applications, $databases, excludedOnly: false ); // If all services are excluded from status checks, calculate status from excluded containers // but mark it with :excluded to indicate monitoring is disabled if (! $hasNonExcluded && ($complexStatus === null && $complexHealth === null)) { [$excludedStatus, $excludedHealth] = $this->aggregateResourceStatuses( $applications, $databases, excludedOnly: true ); // Return status with :excluded suffix to indicate monitoring is disabled if ($excludedStatus && $excludedHealth) { return "{$excludedStatus}:{$excludedHealth}:excluded"; } // If no status was calculated at all (no containers exist), return unknown if ($excludedStatus === null && $excludedHealth === null) { return 'unknown:unknown:excluded'; } return 'exited'; } // If health is null/empty, return just the status without trailing colon if ($complexHealth === null || $complexHealth === '') { return $complexStatus; } return "{$complexStatus}:{$complexHealth}"; } /** * Aggregate status and health from collections of applications and databases. * * This helper method consolidates status aggregation logic using ContainerStatusAggregator. * It processes container status strings stored in the database (not live Docker data). * * @param \Illuminate\Database\Eloquent\Collection $applications Collection of Application models * @param \Illuminate\Database\Eloquent\Collection $databases Collection of Database models * @param bool $excludedOnly If true, only process excluded containers; if false, only process non-excluded * @return array{0: string|null, 1: string|null, 2?: bool} [status, health, hasNonExcluded (only when excludedOnly=false)] */ private function aggregateResourceStatuses($applications, $databases, bool $excludedOnly = false): array { $hasNonExcluded = false; $statusStrings = collect(); // Process both applications and databases using the same logic $resources = $applications->concat($databases); foreach ($resources as $resource) { $isExcluded = $resource->exclude_from_status || str($resource->status)->contains(':excluded'); // Filter based on excludedOnly flag if ($excludedOnly && ! $isExcluded) { continue; } if (! $excludedOnly && $isExcluded) { continue; } if (! $excludedOnly) { $hasNonExcluded = true; } // Strip :excluded suffix before aggregation (it's in the 3rd part of "status:health:excluded") $status = str($resource->status)->before(':excluded')->toString(); $statusStrings->push($status); } // If no status strings collected, return nulls if ($statusStrings->isEmpty()) { return $excludedOnly ? [null, null] : [null, null, $hasNonExcluded]; } // Use ContainerStatusAggregator service for state machine logic $aggregator = new ContainerStatusAggregator; $aggregatedStatus = $aggregator->aggregateFromStrings($statusStrings); // Parse the aggregated "status:health" string $parts = explode(':', $aggregatedStatus); $status = $parts[0] ?? null; $health = $parts[1] ?? null; if ($excludedOnly) { return [$status, $health]; } return [$status, $health, $hasNonExcluded]; } public function extraFields() { $fields = collect([]); $applications = $this->applications()->get(); foreach ($applications as $application) { $image = str($application->image)->before(':'); if ($image->isEmpty()) { continue; } switch ($image) { case $image->contains('drizzle-team/gateway'): $data = collect([]); $masterpass = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_DRIZZLE')->first(); $data = $data->merge([ 'Master Password' => [ 'key' => data_get($masterpass, 'key'), 'value' => data_get($masterpass, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); $fields->put('Drizzle', $data->toArray()); break; case $image->contains('castopod'): $data = collect([]); $disable_https = $this->environment_variables()->where('key', 'CP_DISABLE_HTTPS')->first(); if ($disable_https) { $data = $data->merge([ 'Disable HTTPS' => [ 'key' => 'CP_DISABLE_HTTPS', 'value' => data_get($disable_https, 'value'), 'rules' => 'required', 'customHelper' => 'If you want to use https, set this to 0. Variable name: CP_DISABLE_HTTPS', ], ]); } $fields->put('Castopod', $data->toArray()); break; case $image->contains('label-studio'): $data = collect([]); $username = $this->environment_variables()->where('key', 'LABEL_STUDIO_USERNAME')->first(); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LABELSTUDIO')->first(); if ($username) { $data = $data->merge([ 'Username' => [ 'key' => 'LABEL_STUDIO_USERNAME', 'value' => data_get($username, 'value'), 'rules' => 'required', ], ]); } if ($password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Label Studio', $data->toArray()); break; case $image->contains('litellm'): $data = collect([]); $username = $this->environment_variables()->where('key', 'SERVICE_USER_UI')->first(); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_UI')->first(); if ($username) { $data = $data->merge([ 'Username' => [ 'key' => data_get($username, 'key'), 'value' => data_get($username, 'value'), 'rules' => 'required', ], ]); } if ($password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Litellm', $data->toArray()); break; case $image->contains('langfuse'): $data = collect([]); $email = $this->environment_variables()->where('key', 'LANGFUSE_INIT_USER_EMAIL')->first(); if ($email) { $data = $data->merge([ 'Admin Email' => [ 'key' => data_get($email, 'key'), 'value' => data_get($email, 'value'), 'rules' => 'required|email', ], ]); } $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LANGFUSE')->first(); if ($password) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Langfuse', $data->toArray()); break; case $image->contains('invoiceninja'): $data = collect([]); $email = $this->environment_variables()->where('key', 'IN_USER_EMAIL')->first(); $data = $data->merge([ 'Email' => [ 'key' => data_get($email, 'key'), 'value' => data_get($email, 'value'), 'rules' => 'required|email', ], ]); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_INVOICENINJAUSER')->first(); $data = $data->merge([ 'Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); $fields->put('Invoice Ninja', $data->toArray()); break; case $image->contains('argilla'): $data = collect([]); $api_key = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_APIKEY')->first(); $data = $data->merge([ 'API Key' => [ 'key' => data_get($api_key, 'key'), 'value' => data_get($api_key, 'value'), 'isPassword' => true, 'rules' => 'required', ], ]); $data = $data->merge([ 'API Key' => [ 'key' => data_get($api_key, 'key'), 'value' => data_get($api_key, 'value'), 'isPassword' => true, 'rules' => 'required', ], ]); $username = $this->environment_variables()->where('key', 'ARGILLA_USERNAME')->first(); $data = $data->merge([ 'Username' => [ 'key' => data_get($username, 'key'), 'value' => data_get($username, 'value'), 'rules' => 'required', ], ]); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ARGILLA')->first(); $data = $data->merge([ 'Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); $fields->put('Argilla', $data->toArray()); break; case $image->contains('rabbitmq'): $data = collect([]); $host_port = $this->environment_variables()->where('key', 'PORT')->first(); $username = $this->environment_variables()->where('key', 'SERVICE_USER_RABBITMQ')->first(); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_RABBITMQ')->first(); if ($host_port) { $data = $data->merge([ 'Host Port Binding' => [ 'key' => data_get($host_port, 'key'), 'value' => data_get($host_port, 'value'), 'rules' => 'required', ], ]); } if ($username) { $data = $data->merge([ 'Username' => [ 'key' => data_get($username, 'key'), 'value' => data_get($username, 'value'), 'rules' => 'required', ], ]); } if ($password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('RabbitMQ', $data->toArray()); break; case $image->is('registry'): $data = collect([]); $registry_user = $this->environment_variables()->where('key', 'SERVICE_USER_REGISTRY')->first(); $registry_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_REGISTRY')->first(); if ($registry_user) { $data = $data->merge([ 'Registry User' => [ 'key' => data_get($registry_user, 'key'), 'value' => data_get($registry_user, 'value'), 'rules' => 'required', ], ]); } if ($registry_password) { $data = $data->merge([ 'Registry Password' => [ 'key' => data_get($registry_password, 'key'), 'value' => data_get($registry_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Docker Registry', $data->toArray()); break; case $image->contains('tolgee'): $data = collect([]); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_TOLGEE')->first(); $data = $data->merge([ 'Admin User' => [ 'key' => 'TOLGEE_AUTHENTICATION_INITIAL_USERNAME', 'value' => 'admin', 'readonly' => true, 'rules' => 'required', ], ]); if ($admin_password) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($admin_password, 'key'), 'value' => data_get($admin_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Tolgee', $data->toArray()); break; case $image->contains('logto'): $data = collect([]); $logto_endpoint = $this->environment_variables()->where('key', 'LOGTO_ENDPOINT')->first(); $logto_admin_endpoint = $this->environment_variables()->where('key', 'LOGTO_ADMIN_ENDPOINT')->first(); if ($logto_endpoint) { $data = $data->merge([ 'Endpoint' => [ 'key' => data_get($logto_endpoint, 'key'), 'value' => data_get($logto_endpoint, 'value'), 'rules' => 'required|url', ], ]); } if ($logto_admin_endpoint) { $data = $data->merge([ 'Admin Endpoint' => [ 'key' => data_get($logto_admin_endpoint, 'key'), 'value' => data_get($logto_admin_endpoint, 'value'), 'rules' => 'required|url', ], ]); } $fields->put('Logto', $data->toArray()); break; case $image->contains('unleash-server'): $data = collect([]); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_UNLEASH')->first(); $data = $data->merge([ 'Admin User' => [ 'key' => 'SERVICE_USER_UNLEASH', 'value' => 'admin', 'readonly' => true, 'rules' => 'required', ], ]); if ($admin_password) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($admin_password, 'key'), 'value' => data_get($admin_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Unleash', $data->toArray()); break; case $image->contains('grafana'): $data = collect([]); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GRAFANA')->first(); $data = $data->merge([ 'Admin User' => [ 'key' => 'GF_SECURITY_ADMIN_USER', 'value' => 'admin', 'readonly' => true, 'rules' => 'required', ], ]); if ($admin_password) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($admin_password, 'key'), 'value' => data_get($admin_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Grafana', $data->toArray()); break; case $image->contains('elasticsearch'): $data = collect([]); $elastic_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ELASTICSEARCH')->first(); if ($elastic_password) { $data = $data->merge([ 'Password (default user: elastic)' => [ 'key' => data_get($elastic_password, 'key'), 'value' => data_get($elastic_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Elasticsearch', $data->toArray()); break; case $image->contains('directus'): $data = collect([]); $admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first(); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); if ($admin_email) { $data = $data->merge([ 'Admin Email' => [ 'key' => data_get($admin_email, 'key'), 'value' => data_get($admin_email, 'value'), 'rules' => 'required|email', ], ]); } if ($admin_password) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($admin_password, 'key'), 'value' => data_get($admin_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Directus', $data->toArray()); break; case $image->contains('kong'): $data = collect([]); $dashboard_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first(); $dashboard_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); if ($dashboard_user) { $data = $data->merge([ 'Dashboard User' => [ 'key' => data_get($dashboard_user, 'key'), 'value' => data_get($dashboard_user, 'value'), 'rules' => 'required', ], ]); } if ($dashboard_password) { $data = $data->merge([ 'Dashboard Password' => [ 'key' => data_get($dashboard_password, 'key'), 'value' => data_get($dashboard_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Supabase', $data->toArray()); case $image->contains('minio'): $data = collect([]); $console_url = $this->environment_variables()->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first(); $s3_api_url = $this->environment_variables()->where('key', 'MINIO_SERVER_URL')->first(); $admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_MINIO')->first(); if (is_null($admin_user)) { $admin_user = $this->environment_variables()->where('key', 'MINIO_ROOT_USER')->first(); } $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_MINIO')->first(); if (is_null($admin_password)) { $admin_password = $this->environment_variables()->where('key', 'MINIO_ROOT_PASSWORD')->first(); } if ($console_url) { $data = $data->merge([ 'Console URL' => [ 'key' => data_get($console_url, 'key'), 'value' => data_get($console_url, 'value'), 'rules' => 'required|url', ], ]); } if ($s3_api_url) { $data = $data->merge([ 'S3 API URL' => [ 'key' => data_get($s3_api_url, 'key'), 'value' => data_get($s3_api_url, 'value'), 'rules' => 'required|url', ], ]); } if ($admin_user) { $data = $data->merge([ 'Admin User' => [ 'key' => data_get($admin_user, 'key'), 'value' => data_get($admin_user, 'value'), 'rules' => 'required', ], ]); } if ($admin_password) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($admin_password, 'key'), 'value' => data_get($admin_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('MinIO', $data->toArray()); break; case $image->contains('garage'): $data = collect([]); $s3_api_url = $this->environment_variables()->where('key', 'GARAGE_S3_API_URL')->first(); $web_url = $this->environment_variables()->where('key', 'GARAGE_WEB_URL')->first(); $admin_url = $this->environment_variables()->where('key', 'GARAGE_ADMIN_URL')->first(); $admin_token = $this->environment_variables()->where('key', 'GARAGE_ADMIN_TOKEN')->first(); if (is_null($admin_token)) { $admin_token = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GARAGE')->first(); } $rpc_secret = $this->environment_variables()->where('key', 'GARAGE_RPC_SECRET')->first(); if (is_null($rpc_secret)) { $rpc_secret = $this->environment_variables()->where('key', 'SERVICE_HEX_32_RPCSECRET')->first(); } $metrics_token = $this->environment_variables()->where('key', 'GARAGE_METRICS_TOKEN')->first(); if (is_null($metrics_token)) { $metrics_token = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GARAGEMETRICS')->first(); } if ($s3_api_url) { $data = $data->merge([ 'S3 API URL' => [ 'key' => data_get($s3_api_url, 'key'), 'value' => data_get($s3_api_url, 'value'), 'rules' => 'required|url', ], ]); } if ($web_url) { $data = $data->merge([ 'Web URL' => [ 'key' => data_get($web_url, 'key'), 'value' => data_get($web_url, 'value'), 'rules' => 'required|url', ], ]); } if ($admin_url) { $data = $data->merge([ 'Admin URL' => [ 'key' => data_get($admin_url, 'key'), 'value' => data_get($admin_url, 'value'), 'rules' => 'required|url', ], ]); } if ($admin_token) { $data = $data->merge([ 'Admin Token' => [ 'key' => data_get($admin_token, 'key'), 'value' => data_get($admin_token, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($rpc_secret) { $data = $data->merge([ 'RPC Secret' => [ 'key' => data_get($rpc_secret, 'key'), 'value' => data_get($rpc_secret, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($metrics_token) { $data = $data->merge([ 'Metrics Token' => [ 'key' => data_get($metrics_token, 'key'), 'value' => data_get($metrics_token, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Garage', $data->toArray()); break; case $image->contains('weblate'): $data = collect([]); $admin_email = $this->environment_variables()->where('key', 'WEBLATE_ADMIN_EMAIL')->first(); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_WEBLATE')->first(); if ($admin_email) { $data = $data->merge([ 'Admin Email' => [ 'key' => data_get($admin_email, 'key'), 'value' => data_get($admin_email, 'value'), 'rules' => 'required|email', ], ]); } if ($admin_password) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($admin_password, 'key'), 'value' => data_get($admin_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Weblate', $data->toArray()); break; case $image->contains('meilisearch'): $data = collect([]); $SERVICE_PASSWORD_MEILISEARCH = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_MEILISEARCH')->first(); if ($SERVICE_PASSWORD_MEILISEARCH) { $data = $data->merge([ 'API Key' => [ 'key' => data_get($SERVICE_PASSWORD_MEILISEARCH, 'key'), 'value' => data_get($SERVICE_PASSWORD_MEILISEARCH, 'value'), 'isPassword' => true, ], ]); } $fields->put('Meilisearch', $data->toArray()); break; case $image->contains('linkding'): $data = collect([]); $SERVICE_USER_LINKDING = $this->environment_variables()->where('key', 'SERVICE_USER_LINKDING')->first(); $SERVICE_PASSWORD_LINKDING = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LINKDING')->first(); if ($SERVICE_USER_LINKDING) { $data = $data->merge([ 'Superuser Name' => [ 'key' => data_get($SERVICE_USER_LINKDING, 'key'), 'value' => data_get($SERVICE_USER_LINKDING, 'value'), ], ]); } if ($SERVICE_PASSWORD_LINKDING) { $data = $data->merge([ 'Superuser Password' => [ 'key' => data_get($SERVICE_PASSWORD_LINKDING, 'key'), 'value' => data_get($SERVICE_PASSWORD_LINKDING, 'value'), 'isPassword' => true, ], ]); } $fields->put('Linkding', $data->toArray()); break; case $image->contains('ghost'): $data = collect([]); $MAIL_OPTIONS_AUTH_PASS = $this->environment_variables()->where('key', 'MAIL_OPTIONS_AUTH_PASS')->first(); $MAIL_OPTIONS_AUTH_USER = $this->environment_variables()->where('key', 'MAIL_OPTIONS_AUTH_USER')->first(); $MAIL_OPTIONS_SECURE = $this->environment_variables()->where('key', 'MAIL_OPTIONS_SECURE')->first(); $MAIL_OPTIONS_PORT = $this->environment_variables()->where('key', 'MAIL_OPTIONS_PORT')->first(); $MAIL_OPTIONS_SERVICE = $this->environment_variables()->where('key', 'MAIL_OPTIONS_SERVICE')->first(); $MAIL_OPTIONS_HOST = $this->environment_variables()->where('key', 'MAIL_OPTIONS_HOST')->first(); if ($MAIL_OPTIONS_AUTH_PASS) { $data = $data->merge([ 'Mail Password' => [ 'key' => data_get($MAIL_OPTIONS_AUTH_PASS, 'key'), 'value' => data_get($MAIL_OPTIONS_AUTH_PASS, 'value'), 'isPassword' => true, ], ]); } if ($MAIL_OPTIONS_AUTH_USER) { $data = $data->merge([ 'Mail User' => [ 'key' => data_get($MAIL_OPTIONS_AUTH_USER, 'key'), 'value' => data_get($MAIL_OPTIONS_AUTH_USER, 'value'), ], ]); } if ($MAIL_OPTIONS_SECURE) { $data = $data->merge([ 'Mail Secure' => [ 'key' => data_get($MAIL_OPTIONS_SECURE, 'key'), 'value' => data_get($MAIL_OPTIONS_SECURE, 'value'), ], ]); } if ($MAIL_OPTIONS_PORT) { $data = $data->merge([ 'Mail Port' => [ 'key' => data_get($MAIL_OPTIONS_PORT, 'key'), 'value' => data_get($MAIL_OPTIONS_PORT, 'value'), ], ]); } if ($MAIL_OPTIONS_SERVICE) { $data = $data->merge([ 'Mail Service' => [ 'key' => data_get($MAIL_OPTIONS_SERVICE, 'key'), 'value' => data_get($MAIL_OPTIONS_SERVICE, 'value'), ], ]); } if ($MAIL_OPTIONS_HOST) { $data = $data->merge([ 'Mail Host' => [ 'key' => data_get($MAIL_OPTIONS_HOST, 'key'), 'value' => data_get($MAIL_OPTIONS_HOST, 'value'), ], ]); } $fields->put('Ghost', $data->toArray()); break; case $image->contains('vaultwarden'): $data = collect([]); $DATABASE_URL = $this->environment_variables()->where('key', 'DATABASE_URL')->first(); $ADMIN_TOKEN = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_64_ADMIN')->first(); $SIGNUP_ALLOWED = $this->environment_variables()->where('key', 'SIGNUP_ALLOWED')->first(); $PUSH_ENABLED = $this->environment_variables()->where('key', 'PUSH_ENABLED')->first(); $PUSH_INSTALLATION_ID = $this->environment_variables()->where('key', 'PUSH_SERVICE_ID')->first(); $PUSH_INSTALLATION_KEY = $this->environment_variables()->where('key', 'PUSH_SERVICE_KEY')->first(); if ($DATABASE_URL) { $data = $data->merge([ 'Database URL' => [ 'key' => data_get($DATABASE_URL, 'key'), 'value' => data_get($DATABASE_URL, 'value'), ], ]); } if ($ADMIN_TOKEN) { $data = $data->merge([ 'Admin Password' => [ 'key' => data_get($ADMIN_TOKEN, 'key'), 'value' => data_get($ADMIN_TOKEN, 'value'), 'isPassword' => true, ], ]); } if ($SIGNUP_ALLOWED) { $data = $data->merge([ 'Signup Allowed' => [ 'key' => data_get($SIGNUP_ALLOWED, 'key'), 'value' => data_get($SIGNUP_ALLOWED, 'value'), 'rules' => 'required|string|in:true,false', ], ]); } if ($PUSH_ENABLED) { $data = $data->merge([ 'Push Enabled' => [ 'key' => data_get($PUSH_ENABLED, 'key'), 'value' => data_get($PUSH_ENABLED, 'value'), 'rules' => 'required|string|in:true,false', ], ]); } if ($PUSH_INSTALLATION_ID) { $data = $data->merge([ 'Push Installation ID' => [ 'key' => data_get($PUSH_INSTALLATION_ID, 'key'), 'value' => data_get($PUSH_INSTALLATION_ID, 'value'), ], ]); } if ($PUSH_INSTALLATION_KEY) { $data = $data->merge([ 'Push Installation Key' => [ 'key' => data_get($PUSH_INSTALLATION_KEY, 'key'), 'value' => data_get($PUSH_INSTALLATION_KEY, 'value'), 'isPassword' => true, ], ]); } $fields->put('Vaultwarden', $data); break; case $image->contains('gitlab/gitlab'): $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GITLAB')->first(); $data = collect([]); if ($password) { $data = $data->merge([ 'Root Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $data = $data->merge([ 'Root User' => [ 'key' => 'GITLAB_ROOT_USER', 'value' => 'root', 'rules' => 'required', 'isPassword' => true, ], ]); $fields->put('GitLab', $data->toArray()); break; case $image->contains('code-server'): $data = collect([]); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_64_PASSWORDCODESERVER')->first(); if ($password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $sudoPassword = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_SUDOCODESERVER')->first(); if ($sudoPassword) { $data = $data->merge([ 'Sudo Password' => [ 'key' => data_get($sudoPassword, 'key'), 'value' => data_get($sudoPassword, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Code Server', $data->toArray()); break; case $image->contains('elestio/strapi'): $data = collect([]); $license = $this->environment_variables()->where('key', 'STRAPI_LICENSE')->first(); if ($license) { $data = $data->merge([ 'License' => [ 'key' => data_get($license, 'key'), 'value' => data_get($license, 'value'), ], ]); } $nodeEnv = $this->environment_variables()->where('key', 'NODE_ENV')->first(); if ($nodeEnv) { $data = $data->merge([ 'Node Environment' => [ 'key' => data_get($nodeEnv, 'key'), 'value' => data_get($nodeEnv, 'value'), ], ]); } $fields->put('Strapi', $data->toArray()); break; case $image->contains('marckohlbrugge/sessy'): $data = collect([]); $username = $this->environment_variables()->where('key', 'SERVICE_USER_SESSY')->first(); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_SESSY')->first(); if ($username) { $data = $data->merge([ 'HTTP Auth Username' => [ 'key' => data_get($username, 'key'), 'value' => data_get($username, 'value'), 'rules' => 'required', ], ]); } if ($password) { $data = $data->merge([ 'HTTP Auth Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } $fields->put('Sessy', $data->toArray()); break; case $image->contains('coollabsio/openclaw'): $data = collect([]); $username = $this->environment_variables()->where('key', 'AUTH_USERNAME')->first(); $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_OPENCLAW')->first(); $gateway_token = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_64_GATEWAYTOKEN')->first(); if ($username) { $data = $data->merge([ 'Username' => [ 'key' => data_get($username, 'key'), 'value' => data_get($username, 'value'), 'readonly' => true, ], ]); } if ($password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($password, 'key'), 'value' => data_get($password, 'value'), 'isPassword' => true, ], ]); } if ($gateway_token) { $data = $data->merge([ 'Gateway Token' => [ 'key' => data_get($gateway_token, 'key'), 'value' => data_get($gateway_token, 'value'), 'isPassword' => true, ], ]); } $fields->put('Openclaw', $data->toArray()); break; default: $data = collect([]); $admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first(); // Chaskiq $admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first(); $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); if ($admin_user) { $data = $data->merge([ 'User' => [ 'key' => data_get($admin_user, 'key'), 'value' => data_get($admin_user, 'value', 'admin'), 'readonly' => true, 'rules' => 'required', ], ]); } if ($admin_password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($admin_password, 'key'), 'value' => data_get($admin_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($admin_email) { $data = $data->merge([ 'Email' => [ 'key' => data_get($admin_email, 'key'), 'value' => data_get($admin_email, 'value'), 'rules' => 'required|email', ], ]); } $fields->put('Admin', $data->toArray()); break; } } $databases = $this->databases()->get(); foreach ($databases as $database) { $image = str($database->image)->before(':'); if ($image->isEmpty()) { continue; } switch ($image) { case $image->contains('postgres'): $userVariables = ['SERVICE_USER_POSTGRES', 'SERVICE_USER_POSTGRESQL']; $passwordVariables = ['SERVICE_PASSWORD_POSTGRES', 'SERVICE_PASSWORD_POSTGRESQL']; $dbNameVariables = ['POSTGRESQL_DATABASE', 'POSTGRES_DB']; $postgres_user = $this->environment_variables()->whereIn('key', $userVariables)->first(); $postgres_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first(); $postgres_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first(); $data = collect([]); if ($postgres_user) { $data = $data->merge([ 'User' => [ 'key' => data_get($postgres_user, 'key'), 'value' => data_get($postgres_user, 'value'), 'rules' => 'required', ], ]); } if ($postgres_password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($postgres_password, 'key'), 'value' => data_get($postgres_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($postgres_db_name) { $data = $data->merge([ 'Database Name' => [ 'key' => data_get($postgres_db_name, 'key'), 'value' => data_get($postgres_db_name, 'value'), 'rules' => 'required', ], ]); } $fields->put('PostgreSQL', $data->toArray()); break; case $image->contains('mysql'): $userVariables = ['SERVICE_USER_MYSQL', 'SERVICE_USER_WORDPRESS', 'MYSQL_USER']; $passwordVariables = ['SERVICE_PASSWORD_MYSQL', 'SERVICE_PASSWORD_WORDPRESS', 'MYSQL_PASSWORD', 'SERVICE_PASSWORD_64_MYSQL']; $rootPasswordVariables = ['SERVICE_PASSWORD_MYSQLROOT', 'SERVICE_PASSWORD_ROOT', 'SERVICE_PASSWORD_64_MYSQLROOT']; $dbNameVariables = ['MYSQL_DATABASE']; $mysql_user = $this->environment_variables()->whereIn('key', $userVariables)->first(); $mysql_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first(); $mysql_root_password = $this->environment_variables()->whereIn('key', $rootPasswordVariables)->first(); $mysql_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first(); $data = collect([]); if ($mysql_user) { $data = $data->merge([ 'User' => [ 'key' => data_get($mysql_user, 'key'), 'value' => data_get($mysql_user, 'value'), 'rules' => 'required', ], ]); } if ($mysql_password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($mysql_password, 'key'), 'value' => data_get($mysql_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($mysql_root_password) { $data = $data->merge([ 'Root Password' => [ 'key' => data_get($mysql_root_password, 'key'), 'value' => data_get($mysql_root_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($mysql_db_name) { $data = $data->merge([ 'Database Name' => [ 'key' => data_get($mysql_db_name, 'key'), 'value' => data_get($mysql_db_name, 'value'), 'rules' => 'required', ], ]); } $fields->put('MySQL', $data->toArray()); break; case $image->contains('mariadb'): $userVariables = ['SERVICE_USER_MARIADB', 'SERVICE_USER_WORDPRESS', 'SERVICE_USER_MYSQL', 'MYSQL_USER']; $passwordVariables = ['SERVICE_PASSWORD_MARIADB', 'SERVICE_PASSWORD_WORDPRESS', '_APP_DB_PASS', 'MYSQL_PASSWORD']; $rootPasswordVariables = ['SERVICE_PASSWORD_MARIADBROOT', 'SERVICE_PASSWORD_ROOT', '_APP_DB_ROOT_PASS', 'MYSQL_ROOT_PASSWORD']; $dbNameVariables = ['SERVICE_DATABASE_MARIADB', 'SERVICE_DATABASE_WORDPRESS', '_APP_DB_SCHEMA', 'MYSQL_DATABASE']; $mariadb_user = $this->environment_variables()->whereIn('key', $userVariables)->first(); $mariadb_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first(); $mariadb_root_password = $this->environment_variables()->whereIn('key', $rootPasswordVariables)->first(); $mariadb_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first(); $data = collect([]); if ($mariadb_user) { $data = $data->merge([ 'User' => [ 'key' => data_get($mariadb_user, 'key'), 'value' => data_get($mariadb_user, 'value'), 'rules' => 'required', ], ]); } if ($mariadb_password) { $data = $data->merge([ 'Password' => [ 'key' => data_get($mariadb_password, 'key'), 'value' => data_get($mariadb_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($mariadb_root_password) { $data = $data->merge([ 'Root Password' => [ 'key' => data_get($mariadb_root_password, 'key'), 'value' => data_get($mariadb_root_password, 'value'), 'rules' => 'required', 'isPassword' => true, ], ]); } if ($mariadb_db_name) { $data = $data->merge([ 'Database Name' => [ 'key' => data_get($mariadb_db_name, 'key'), 'value' => data_get($mariadb_db_name, 'value'), 'rules' => 'required', ], ]); } $fields->put('MariaDB', $data->toArray()); break; } } $fields = collect($fields)->map(function ($extraFields) { if (is_array($extraFields)) { $extraFields = collect($extraFields)->map(function ($field) { if (filled($field['value']) && str($field['value'])->startsWith('$SERVICE_')) { $searchValue = str($field['value'])->after('$')->value; $newValue = $this->environment_variables()->where('key', $searchValue)->first(); if ($newValue) { $field['value'] = $newValue->value; } } return $field; }); } return $extraFields; }); return $fields; } public function saveExtraFields($fields) { foreach ($fields as $field) { $key = data_get($field, 'key'); $value = data_get($field, 'value'); $found = $this->environment_variables()->where('key', $key)->first(); if ($found) { $found->value = $value; $found->save(); } else { $this->environment_variables()->create([ 'key' => $key, 'value' => $value, 'resourceable_id' => $this->id, 'resourceable_type' => $this->getMorphClass(), 'is_preview' => false, ]); } } } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.service.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'service_uuid' => data_get($this, 'uuid'), ]); } return null; } public function taskLink($task_uuid) { if (data_get($this, 'environment.project.uuid')) { $route = route('project.service.scheduled-tasks', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'service_uuid' => data_get($this, 'uuid'), 'task_uuid' => $task_uuid, ]); $settings = InstanceSettings::get(); if (data_get($settings, 'fqdn')) { $url = Url::fromString($route); $url = $url->withPort(null); $fqdn = data_get($settings, 'fqdn'); $fqdn = str_replace(['http://', 'https://'], '', $fqdn); $url = $url->withHost($fqdn); return $url->__toString(); } return $route; } return null; } public function documentation() { $services = get_service_templates(); $service = data_get($services, str($this->name)->beforeLast('-')->value, []); return data_get($service, 'documentation', config('constants.urls.docs')); } /** * Get the required port for this service from the template definition. */ public function getRequiredPort(): ?int { try { $services = get_service_templates(); $serviceName = str($this->name)->beforeLast('-')->value(); $service = data_get($services, $serviceName, []); $port = data_get($service, 'port'); return $port ? (int) $port : null; } catch (\Throwable) { return null; } } /** * Check if this service requires a port to function correctly. */ public function requiresPort(): bool { return $this->getRequiredPort() !== null; } public function applications() { return $this->hasMany(ServiceApplication::class); } public function databases() { return $this->hasMany(ServiceDatabase::class); } public function destination() { return $this->morphTo(); } public function environment() { return $this->belongsTo(Environment::class); } public function server() { return $this->belongsTo(Server::class); } public function byUuid(string $uuid) { $app = $this->applications()->whereUuid($uuid)->first(); if ($app) { return $app; } $db = $this->databases()->whereUuid($uuid)->first(); if ($db) { return $db; } return null; } public function byName(string $name) { $app = $this->applications()->whereName($name)->first(); if ($app) { return $app; } $db = $this->databases()->whereName($name)->first(); if ($db) { return $db; } return null; } public function scheduled_tasks(): HasMany { return $this->hasMany(ScheduledTask::class)->orderBy('name', 'asc'); } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function workdir() { return service_configuration_dir()."/{$this->uuid}"; } public function saveComposeConfigs() { // Guard against null or empty docker_compose if (! $this->docker_compose) { return; } $workdir = $this->workdir(); instant_remote_process([ "mkdir -p $workdir", "cd $workdir", ], $this->server); $filename = new Cuid2.'-docker-compose.yml'; Storage::disk('local')->put("tmp/{$filename}", $this->docker_compose); $path = Storage::path("tmp/{$filename}"); instant_scp($path, "{$workdir}/docker-compose.yml", $this->server); Storage::disk('local')->delete("tmp/{$filename}"); $commands[] = "cd $workdir"; $commands[] = 'rm -f .env || true'; $envs = collect([]); // Generate SERVICE_NAME_* environment variables from docker-compose services if ($this->docker_compose) { try { $dockerCompose = \Symfony\Component\Yaml\Yaml::parse($this->docker_compose); $services = data_get($dockerCompose, 'services', []); foreach ($services as $serviceName => $_) { $envs->push('SERVICE_NAME_'.str($serviceName)->replace('-', '_')->replace('.', '_')->upper().'='.$serviceName); } } catch (\Exception $e) { ray($e->getMessage()); } } $envs_from_coolify = $this->environment_variables()->get(); $sorted = $envs_from_coolify->sortBy(function ($env) { if (str($env->key)->startsWith('SERVICE_')) { return 1; } if (str($env->value)->startsWith('$SERVICE_') || str($env->value)->startsWith('${SERVICE_')) { return 2; } return 3; }); foreach ($sorted as $env) { $envs->push("{$env->key}={$env->real_value}"); } if ($envs->count() === 0) { $commands[] = 'touch .env'; } else { $envs_base64 = base64_encode($envs->implode("\n")); $commands[] = "echo '$envs_base64' | base64 -d | tee .env > /dev/null"; } instant_remote_process($commands, $this->server); } public function parse(bool $isNew = false): Collection { if ((int) $this->compose_parsing_version >= 3) { return serviceParser($this); } elseif ($this->docker_compose_raw) { return parseDockerComposeFile($this, $isNew); } else { return collect([]); } } public function networks() { return getTopLevelNetworks($this); } protected function isDeployable(): Attribute { return Attribute::make( get: function () { $envs = $this->environment_variables()->where('is_required', true)->get(); foreach ($envs as $env) { if ($env->is_really_required) { return false; } } return true; } ); } } ================================================ FILE: app/Models/ServiceApplication.php ================================================ update(['fqdn' => null]); $service->persistentStorages()->delete(); $service->fileStorages()->delete(); }); static::saving(function ($service) { if ($service->isDirty('status')) { $service->forceFill(['last_online_at' => now()]); } }); } public function restart() { $container_id = $this->name.'-'.$this->service->uuid; instant_remote_process(["docker restart {$container_id}"], $this->service->server); } public static function ownedByCurrentTeamAPI(int $teamId) { return ServiceApplication::whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name'); } /** * Get query builder for service applications owned by current team. * If you need all service applications without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return ServiceApplication::whereRelation('service.environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all service applications owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return ServiceApplication::ownedByCurrentTeam()->get(); }); } public function isRunning() { return str($this->status)->contains('running'); } public function isExited() { return str($this->status)->contains('exited'); } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function isStripprefixEnabled() { return data_get($this, 'is_stripprefix_enabled', true); } public function isGzipEnabled() { return data_get($this, 'is_gzip_enabled', true); } public function type() { return 'service'; } public function team() { return data_get($this, 'service.environment.project.team'); } public function workdir() { return service_configuration_dir()."/{$this->service->uuid}"; } public function serviceType() { $found = str(collect(SPECIFIC_SERVICES)->filter(function ($service) { return str($this->image)->before(':')->value() === $service; })->first()); if ($found->isNotEmpty()) { return $found; } return null; } public function service() { return $this->belongsTo(Service::class); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function fqdns(): Attribute { return Attribute::make( get: fn () => is_null($this->fqdn) ? [] : explode(',', $this->fqdn), ); } /** * Extract port number from a given FQDN URL. * Returns null if no port is specified. */ public static function extractPortFromUrl(string $url): ?int { try { // Ensure URL has a scheme for proper parsing if (! str_starts_with($url, 'http://') && ! str_starts_with($url, 'https://')) { $url = 'http://'.$url; } $parsed = parse_url($url); $port = $parsed['port'] ?? null; return $port ? (int) $port : null; } catch (\Throwable) { return null; } } /** * Check if all FQDNs have a port specified. */ public function allFqdnsHavePort(): bool { if (is_null($this->fqdn) || $this->fqdn === '') { return false; } $fqdns = explode(',', $this->fqdn); foreach ($fqdns as $fqdn) { $fqdn = trim($fqdn); if (empty($fqdn)) { continue; } $port = self::extractPortFromUrl($fqdn); if ($port === null) { return false; } } return true; } public function getFilesFromServer(bool $isInit = false) { getFilesystemVolumesFromServer($this, $isInit); } public function isBackupSolutionAvailable() { return false; } /** * Get the required port for this service application. * Extracts port from SERVICE_URL_* or SERVICE_FQDN_* environment variables * stored at the Service level, filtering by normalized container name. * Falls back to service-level port if no port-specific variable is found. */ public function getRequiredPort(): ?int { try { // Parse the Docker Compose to find SERVICE_URL/SERVICE_FQDN variables DIRECTLY DECLARED // for this specific service container (not just referenced from other containers) $dockerComposeRaw = data_get($this->service, 'docker_compose_raw'); if (! $dockerComposeRaw) { // Fall back to service-level port if no compose file return $this->service->getRequiredPort(); } $dockerCompose = \Symfony\Component\Yaml\Yaml::parse($dockerComposeRaw); $serviceConfig = data_get($dockerCompose, "services.{$this->name}"); if (! $serviceConfig) { return $this->service->getRequiredPort(); } $environment = data_get($serviceConfig, 'environment', []); // Extract SERVICE_URL and SERVICE_FQDN variables DIRECTLY DECLARED in this service's environment // (not variables that are merely referenced with ${VAR} syntax) $portFound = null; foreach ($environment as $key => $value) { if (is_int($key) && is_string($value)) { // List-style: "- SERVICE_URL_APP_3000" or "- SERVICE_URL_APP_3000=value" // Extract variable name (before '=' if present) $envVarName = str($value)->before('=')->trim(); // Only process direct declarations if ($envVarName->startsWith('SERVICE_FQDN_') || $envVarName->startsWith('SERVICE_URL_')) { // Parse to check if it has a port suffix $parsed = parseServiceEnvironmentVariable($envVarName->value()); if ($parsed['has_port'] && $parsed['port']) { // Found a port-specific variable for this service $portFound = (int) $parsed['port']; break; } } } elseif (is_string($key)) { // Map-style: "SERVICE_URL_APP_3000: value" or "SERVICE_FQDN_DB: localhost" $envVarName = str($key); // Only process direct declarations if ($envVarName->startsWith('SERVICE_FQDN_') || $envVarName->startsWith('SERVICE_URL_')) { // Parse to check if it has a port suffix $parsed = parseServiceEnvironmentVariable($envVarName->value()); if ($parsed['has_port'] && $parsed['port']) { // Found a port-specific variable for this service $portFound = (int) $parsed['port']; break; } } } } // If a port was found in the template, return it if ($portFound !== null) { return $portFound; } // No port-specific variables found for this service, return null // (DO NOT fall back to service-level port, as that applies to all services) return null; } catch (\Throwable $e) { return null; } } } ================================================ FILE: app/Models/ServiceDatabase.php ================================================ 'integer', ]; protected static function booted() { static::deleting(function ($service) { $service->persistentStorages()->delete(); $service->fileStorages()->delete(); $service->scheduledBackups()->delete(); }); static::saving(function ($service) { if ($service->isDirty('status')) { $service->forceFill(['last_online_at' => now()]); } }); } public static function ownedByCurrentTeamAPI(int $teamId) { return ServiceDatabase::whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name'); } /** * Get query builder for service databases owned by current team. * If you need all service databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return ServiceDatabase::whereRelation('service.environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all service databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return ServiceDatabase::ownedByCurrentTeam()->get(); }); } public function restart() { $container_id = $this->name.'-'.$this->service->uuid; remote_process(["docker restart {$container_id}"], $this->service->server); } public function isRunning() { return str($this->status)->contains('running'); } public function isExited() { return str($this->status)->contains('exited'); } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function isStripprefixEnabled() { return data_get($this, 'is_stripprefix_enabled', true); } public function isGzipEnabled() { return data_get($this, 'is_gzip_enabled', true); } public function type() { return 'service'; } public function serviceType() { return null; } public function databaseType() { if (filled($this->custom_type)) { return 'standalone-'.$this->custom_type; } $image = str($this->image)->before(':'); if ($image->contains('supabase/postgres')) { $finalImage = 'supabase/postgres'; } elseif ($image->contains('timescale')) { $finalImage = 'postgresql'; } elseif ($image->contains('pgvector')) { $finalImage = 'postgresql'; } elseif ($image->contains('postgres') || $image->contains('postgis')) { $finalImage = 'postgresql'; } else { $finalImage = $image; } return "standalone-$finalImage"; } public function getServiceDatabaseUrl() { $port = $this->public_port; $realIp = $this->service->server->ip; if ($this->service->server->isLocalhost() || isDev()) { $realIp = base_ip(); } return "{$realIp}:{$port}"; } public function team() { return data_get($this, 'service.environment.project.team'); } public function workdir() { return service_configuration_dir()."/{$this->service->uuid}"; } public function service() { return $this->belongsTo(Service::class); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function getFilesFromServer(bool $isInit = false) { getFilesystemVolumesFromServer($this, $isInit); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function isBackupSolutionAvailable() { return str($this->databaseType())->contains('mysql') || str($this->databaseType())->contains('postgres') || str($this->databaseType())->contains('postgis') || str($this->databaseType())->contains('mariadb') || str($this->databaseType())->contains('mongo') || filled($this->custom_type); } } ================================================ FILE: app/Models/SharedEnvironmentVariable.php ================================================ 'string', 'value' => 'encrypted', ]; public function team() { return $this->belongsTo(Team::class); } public function project() { return $this->belongsTo(Project::class); } public function environment() { return $this->belongsTo(Environment::class); } } ================================================ FILE: app/Models/SlackNotificationSettings.php ================================================ 'boolean', 'slack_webhook_url' => 'encrypted', 'deployment_success_slack_notifications' => 'boolean', 'deployment_failure_slack_notifications' => 'boolean', 'status_change_slack_notifications' => 'boolean', 'backup_success_slack_notifications' => 'boolean', 'backup_failure_slack_notifications' => 'boolean', 'scheduled_task_success_slack_notifications' => 'boolean', 'scheduled_task_failure_slack_notifications' => 'boolean', 'docker_cleanup_slack_notifications' => 'boolean', 'server_disk_usage_slack_notifications' => 'boolean', 'server_reachable_slack_notifications' => 'boolean', 'server_unreachable_slack_notifications' => 'boolean', 'server_patch_slack_notifications' => 'boolean', 'traefik_outdated_slack_notifications' => 'boolean', ]; public function team() { return $this->belongsTo(Team::class); } public function isEnabled() { return $this->slack_enabled; } } ================================================ FILE: app/Models/SslCertificate.php ================================================ 'encrypted', 'ssl_private_key' => 'encrypted', 'subject_alternative_names' => 'array', 'valid_until' => 'datetime', ]; public function application() { return $this->morphTo('resource'); } public function service() { return $this->morphTo('resource'); } public function database() { return $this->morphTo('resource'); } public function server() { return $this->belongsTo(Server::class); } } ================================================ FILE: app/Models/StandaloneClickhouse.php ================================================ 'encrypted', 'public_port_timeout' => 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'clickhouse-data-'.$database->uuid, 'mount_path' => '/var/lib/clickhouse', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); } /** * Get query builder for ClickHouse databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandaloneClickhouse::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all ClickHouse databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandaloneClickhouse::ownedByCurrentTeam()->get(); }); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } public function team() { return data_get($this, 'environment.project.team'); } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } public function type(): string { return 'standalone-clickhouse'; } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $encodedUser = rawurlencode($this->clickhouse_admin_user); $encodedPass = rawurlencode($this->clickhouse_admin_password); $database = $this->clickhouse_db ?? 'default'; return "clickhouse://{$encodedUser}:{$encodedPass}@{$this->uuid}:9000/{$database}"; }, ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $encodedUser = rawurlencode($this->clickhouse_admin_user); $encodedPass = rawurlencode($this->clickhouse_admin_password); $database = $this->clickhouse_db ?? 'default'; return "clickhouse://{$encodedUser}:{$encodedPass}@{$serverIp}:{$this->public_port}/{$database}"; } return null; } ); } public function environment() { return $this->belongsTo(Environment::class); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function destination() { return $this->morphTo(); } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function isBackupSolutionAvailable() { return false; } } ================================================ FILE: app/Models/StandaloneDocker.php ================================================ server; instant_remote_process([ "docker network inspect $newStandaloneDocker->network >/dev/null 2>&1 || docker network create --driver overlay --attachable $newStandaloneDocker->network >/dev/null", ], $server, false); ConnectProxyToNetworksJob::dispatchSync($server); }); } public function applications() { return $this->morphMany(Application::class, 'destination'); } public function postgresqls() { return $this->morphMany(StandalonePostgresql::class, 'destination'); } public function redis() { return $this->morphMany(StandaloneRedis::class, 'destination'); } public function mongodbs() { return $this->morphMany(StandaloneMongodb::class, 'destination'); } public function mysqls() { return $this->morphMany(StandaloneMysql::class, 'destination'); } public function mariadbs() { return $this->morphMany(StandaloneMariadb::class, 'destination'); } public function keydbs() { return $this->morphMany(StandaloneKeydb::class, 'destination'); } public function dragonflies() { return $this->morphMany(StandaloneDragonfly::class, 'destination'); } public function clickhouses() { return $this->morphMany(StandaloneClickhouse::class, 'destination'); } public function server() { return $this->belongsTo(Server::class); } /** * Get the server attribute using identity map caching. * This intercepts lazy-loading to use cached Server lookups. */ public function getServerAttribute(): ?Server { // Use eager loaded data if available if ($this->relationLoaded('server')) { return $this->getRelation('server'); } // Use identity map for lazy loading $server = Server::findCached($this->server_id); // Cache in relation for future access on this instance if ($server) { $this->setRelation('server', $server); } return $server; } public function services() { return $this->morphMany(Service::class, 'destination'); } public function databases() { $postgresqls = $this->postgresqls; $redis = $this->redis; $mongodbs = $this->mongodbs; $mysqls = $this->mysqls; $mariadbs = $this->mariadbs; return $postgresqls->concat($redis)->concat($mongodbs)->concat($mysqls)->concat($mariadbs); } public function attachedTo() { return $this->applications?->count() > 0 || $this->databases()->count() > 0; } } ================================================ FILE: app/Models/StandaloneDragonfly.php ================================================ 'encrypted', 'public_port_timeout' => 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'dragonfly-data-'.$database->uuid, 'mount_path' => '/data', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); } /** * Get query builder for Dragonfly databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandaloneDragonfly::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all Dragonfly databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandaloneDragonfly::ownedByCurrentTeam()->get(); }); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } public function type(): string { return 'standalone-dragonfly'; } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $scheme = $this->enable_ssl ? 'rediss' : 'redis'; $port = $this->enable_ssl ? 6380 : 6379; $encodedPass = rawurlencode($this->dragonfly_password); $url = "{$scheme}://:{$encodedPass}@{$this->uuid}:{$port}/0"; if ($this->enable_ssl && $this->ssl_mode === 'verify-ca') { $url .= '?cacert=/etc/ssl/certs/coolify-ca.crt'; } return $url; } ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $scheme = $this->enable_ssl ? 'rediss' : 'redis'; $encodedPass = rawurlencode($this->dragonfly_password); $url = "{$scheme}://:{$encodedPass}@{$serverIp}:{$this->public_port}/0"; if ($this->enable_ssl && $this->ssl_mode === 'verify-ca') { $url .= '?cacert=/etc/ssl/certs/coolify-ca.crt'; } return $url; } return null; } ); } public function environment() { return $this->belongsTo(Environment::class); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function destination() { return $this->morphTo(); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function isBackupSolutionAvailable() { return false; } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } } ================================================ FILE: app/Models/StandaloneKeydb.php ================================================ 'encrypted', 'public_port_timeout' => 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'keydb-data-'.$database->uuid, 'mount_path' => '/data', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); } /** * Get query builder for KeyDB databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandaloneKeydb::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all KeyDB databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandaloneKeydb::ownedByCurrentTeam()->get(); }); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->keydb_conf; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } public function type(): string { return 'standalone-keydb'; } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $scheme = $this->enable_ssl ? 'rediss' : 'redis'; $port = $this->enable_ssl ? 6380 : 6379; $encodedPass = rawurlencode($this->keydb_password); $url = "{$scheme}://:{$encodedPass}@{$this->uuid}:{$port}/0"; if ($this->enable_ssl && $this->ssl_mode === 'verify-ca') { $url .= '?cacert=/etc/ssl/certs/coolify-ca.crt'; } return $url; } ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $scheme = $this->enable_ssl ? 'rediss' : 'redis'; $encodedPass = rawurlencode($this->keydb_password); $url = "{$scheme}://:{$encodedPass}@{$serverIp}:{$this->public_port}/0"; if ($this->enable_ssl && $this->ssl_mode === 'verify-ca') { $url .= '?cacert=/etc/ssl/certs/coolify-ca.crt'; } return $url; } return null; } ); } public function environment() { return $this->belongsTo(Environment::class); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function destination() { return $this->morphTo(); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function isBackupSolutionAvailable() { return false; } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } } ================================================ FILE: app/Models/StandaloneMariadb.php ================================================ 'encrypted', 'public_port_timeout' => 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'mariadb-data-'.$database->uuid, 'mount_path' => '/var/lib/mysql', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); } /** * Get query builder for MariaDB databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandaloneMariadb::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all MariaDB databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandaloneMariadb::ownedByCurrentTeam()->get(); }); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->mariadb_conf; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } public function type(): string { return 'standalone-mariadb'; } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $encodedUser = rawurlencode($this->mariadb_user); $encodedPass = rawurlencode($this->mariadb_password); return "mysql://{$encodedUser}:{$encodedPass}@{$this->uuid}:3306/{$this->mariadb_database}"; }, ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $encodedUser = rawurlencode($this->mariadb_user); $encodedPass = rawurlencode($this->mariadb_password); return "mysql://{$encodedUser}:{$encodedPass}@{$serverIp}:{$this->public_port}/{$this->mariadb_database}"; } return null; } ); } public function environment() { return $this->belongsTo(Environment::class); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function destination(): MorphTo { return $this->morphTo(); } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function isBackupSolutionAvailable() { return true; } } ================================================ FILE: app/Models/StandaloneMongodb.php ================================================ 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'mongodb-configdb-'.$database->uuid, 'mount_path' => '/data/configdb', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); LocalPersistentVolume::create([ 'name' => 'mongodb-db-'.$database->uuid, 'mount_path' => '/data/db', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); } /** * Get query builder for MongoDB databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandaloneMongodb::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all MongoDB databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandaloneMongodb::ownedByCurrentTeam()->get(); }); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->mongo_conf; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function mongoInitdbRootPassword(): Attribute { return Attribute::make( get: function ($value) { try { return decrypt($value); } catch (\Throwable $th) { $this->mongo_initdb_root_password = encrypt($value); $this->save(); return $value; } } ); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } public function type(): string { return 'standalone-mongodb'; } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $encodedUser = rawurlencode($this->mongo_initdb_root_username); $encodedPass = rawurlencode($this->mongo_initdb_root_password); $url = "mongodb://{$encodedUser}:{$encodedPass}@{$this->uuid}:27017/?directConnection=true"; if ($this->enable_ssl) { $url .= '&tls=true&tlsCAFile=/etc/mongo/certs/ca.pem'; if (in_array($this->ssl_mode, ['verify-full'])) { $url .= '&tlsCertificateKeyFile=/etc/mongo/certs/server.pem'; } } return $url; }, ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $encodedUser = rawurlencode($this->mongo_initdb_root_username); $encodedPass = rawurlencode($this->mongo_initdb_root_password); $url = "mongodb://{$encodedUser}:{$encodedPass}@{$serverIp}:{$this->public_port}/?directConnection=true"; if ($this->enable_ssl) { $url .= '&tls=true&tlsCAFile=/etc/mongo/certs/ca.pem'; if (in_array($this->ssl_mode, ['verify-full'])) { $url .= '&tlsCertificateKeyFile=/etc/mongo/certs/server.pem'; } } return $url; } return null; } ); } public function environment() { return $this->belongsTo(Environment::class); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function destination() { return $this->morphTo(); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function isBackupSolutionAvailable() { return true; } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } } ================================================ FILE: app/Models/StandaloneMysql.php ================================================ 'encrypted', 'mysql_root_password' => 'encrypted', 'public_port_timeout' => 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'mysql-data-'.$database->uuid, 'mount_path' => '/var/lib/mysql', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); } /** * Get query builder for MySQL databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandaloneMysql::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all MySQL databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandaloneMysql::ownedByCurrentTeam()->get(); }); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->mysql_conf; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } public function type(): string { return 'standalone-mysql'; } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $encodedUser = rawurlencode($this->mysql_user); $encodedPass = rawurlencode($this->mysql_password); $url = "mysql://{$encodedUser}:{$encodedPass}@{$this->uuid}:3306/{$this->mysql_database}"; if ($this->enable_ssl) { $url .= "?ssl-mode={$this->ssl_mode}"; if (in_array($this->ssl_mode, ['VERIFY_CA', 'VERIFY_IDENTITY'])) { $url .= '&ssl-ca=/etc/ssl/certs/coolify-ca.crt'; } } return $url; }, ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $encodedUser = rawurlencode($this->mysql_user); $encodedPass = rawurlencode($this->mysql_password); $url = "mysql://{$encodedUser}:{$encodedPass}@{$serverIp}:{$this->public_port}/{$this->mysql_database}"; if ($this->enable_ssl) { $url .= "?ssl-mode={$this->ssl_mode}"; if (in_array($this->ssl_mode, ['VERIFY_CA', 'VERIFY_IDENTITY'])) { $url .= '&ssl-ca=/etc/ssl/certs/coolify-ca.crt'; } } return $url; } return null; } ); } public function environment() { return $this->belongsTo(Environment::class); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function destination() { return $this->morphTo(); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function isBackupSolutionAvailable() { return true; } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } } ================================================ FILE: app/Models/StandalonePostgresql.php ================================================ 'array', 'postgres_password' => 'encrypted', 'public_port_timeout' => 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { // This is really stupid and it took me 1h to figure out why the image was not loading properly. This is exactly the reason why we need to use the action pattern because Model events and Accessors are a fragile mess! $image = (string) ($database->getAttributes()['image'] ?? ''); $majorVersion = 0; if (preg_match('/:(?:pg)?(\d+)/i', $image, $matches)) { $majorVersion = (int) $matches[1]; } // PostgreSQL 18+ uses /var/lib/postgresql as mount path // Older versions use /var/lib/postgresql/data $mountPath = $majorVersion >= 18 ? '/var/lib/postgresql' : '/var/lib/postgresql/data'; LocalPersistentVolume::create([ 'name' => 'postgres-data-'.$database->uuid, 'mount_path' => $mountPath, 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); } /** * Get query builder for PostgreSQL databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandalonePostgresql::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all PostgreSQL databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandalonePostgresql::ownedByCurrentTeam()->get(); }); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->postgres_initdb_args.$this->postgres_host_auth_method; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } public function team() { return data_get($this, 'environment.project.team'); } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } public function type(): string { return 'standalone-postgresql'; } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $encodedUser = rawurlencode($this->postgres_user); $encodedPass = rawurlencode($this->postgres_password); $url = "postgres://{$encodedUser}:{$encodedPass}@{$this->uuid}:5432/{$this->postgres_db}"; if ($this->enable_ssl) { $url .= "?sslmode={$this->ssl_mode}"; if (in_array($this->ssl_mode, ['verify-ca', 'verify-full'])) { $url .= '&sslrootcert=/etc/ssl/certs/coolify-ca.crt'; } } return $url; }, ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $encodedUser = rawurlencode($this->postgres_user); $encodedPass = rawurlencode($this->postgres_password); $url = "postgres://{$encodedUser}:{$encodedPass}@{$serverIp}:{$this->public_port}/{$this->postgres_db}"; if ($this->enable_ssl) { $url .= "?sslmode={$this->ssl_mode}"; if (in_array($this->ssl_mode, ['verify-ca', 'verify-full'])) { $url .= '&sslrootcert=/etc/ssl/certs/coolify-ca.crt'; } } return $url; } return null; } ); } public function environment() { return $this->belongsTo(Environment::class); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function destination() { return $this->morphTo(); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function isBackupSolutionAvailable() { return true; } } ================================================ FILE: app/Models/StandaloneRedis.php ================================================ 'integer', 'restart_count' => 'integer', 'last_restart_at' => 'datetime', 'last_restart_type' => 'string', ]; protected static function booted() { static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'redis-data-'.$database->uuid, 'mount_path' => '/data', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), ]); }); static::forceDeleting(function ($database) { $database->persistentStorages()->delete(); $database->scheduledBackups()->delete(); $database->environment_variables()->delete(); $database->tags()->detach(); }); static::saving(function ($database) { if ($database->isDirty('status')) { $database->forceFill(['last_online_at' => now()]); } }); static::retrieved(function ($database) { if (! $database->redis_username) { $database->redis_username = 'default'; } }); } /** * Get query builder for Redis databases owned by current team. * If you need all databases without further query chaining, use ownedByCurrentTeamCached() instead. */ public static function ownedByCurrentTeam() { return StandaloneRedis::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name'); } /** * Get all Redis databases owned by current team (cached for request duration). */ public static function ownedByCurrentTeamCached() { return once(function () { return StandaloneRedis::ownedByCurrentTeam()->get(); }); } protected function serverStatus(): Attribute { return Attribute::make( get: function () { return $this->destination->server->isFunctional(); } ); } public function isConfigurationChanged(bool $save = false) { $newConfigHash = $this->image.$this->ports_mappings.$this->redis_conf; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); if ($oldConfigHash === null) { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } if ($oldConfigHash === $newConfigHash) { return false; } else { if ($save) { $this->config_hash = $newConfigHash; $this->save(); } return true; } } public function isRunning() { return (bool) str($this->status)->contains('running'); } public function isExited() { return (bool) str($this->status)->startsWith('exited'); } public function workdir() { return database_configuration_dir()."/{$this->uuid}"; } public function deleteConfigurations() { $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { instant_remote_process(['rm -rf '.$this->workdir()], $server, false); } } public function deleteVolumes() { $persistentStorages = $this->persistentStorages()->get() ?? collect(); if ($persistentStorages->count() === 0) { return; } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } public function realStatus() { return $this->getRawOriginal('status'); } public function status(): Attribute { return Attribute::make( set: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, get: function ($value) { if (str($value)->contains('(')) { $status = str($value)->before('(')->trim()->value(); $health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy'; } elseif (str($value)->contains(':')) { $status = str($value)->before(':')->trim()->value(); $health = str($value)->after(':')->trim()->value() ?? 'unhealthy'; } else { $status = $value; $health = 'unhealthy'; } return "$status:$health"; }, ); } public function tags() { return $this->morphToMany(Tag::class, 'taggable'); } public function project() { return data_get($this, 'environment.project'); } public function team() { return data_get($this, 'environment.project.team'); } public function sslCertificates() { return $this->morphMany(SslCertificate::class, 'resource'); } public function link() { if (data_get($this, 'environment.project.uuid')) { return route('project.database.configuration', [ 'project_uuid' => data_get($this, 'environment.project.uuid'), 'environment_uuid' => data_get($this, 'environment.uuid'), 'database_uuid' => data_get($this, 'uuid'), ]); } return null; } public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } public function portsMappings(): Attribute { return Attribute::make( set: fn ($value) => $value === '' ? null : $value, ); } public function portsMappingsArray(): Attribute { return Attribute::make( get: fn () => is_null($this->ports_mappings) ? [] : explode(',', $this->ports_mappings), ); } public function type(): string { return 'standalone-redis'; } public function databaseType(): Attribute { return new Attribute( get: fn () => $this->type(), ); } protected function internalDbUrl(): Attribute { return new Attribute( get: function () { $redis_version = $this->getRedisVersion(); $username_part = version_compare($redis_version, '6.0', '>=') ? rawurlencode($this->redis_username).':' : ''; $encodedPass = rawurlencode($this->redis_password); $scheme = $this->enable_ssl ? 'rediss' : 'redis'; $port = $this->enable_ssl ? 6380 : 6379; $url = "{$scheme}://{$username_part}{$encodedPass}@{$this->uuid}:{$port}/0"; if ($this->enable_ssl && $this->ssl_mode === 'verify-ca') { $url .= '?cacert=/etc/ssl/certs/coolify-ca.crt'; } return $url; } ); } protected function externalDbUrl(): Attribute { return new Attribute( get: function () { if ($this->is_public && $this->public_port) { $serverIp = $this->destination->server->getIp; if (empty($serverIp)) { return null; } $redis_version = $this->getRedisVersion(); $username_part = version_compare($redis_version, '6.0', '>=') ? rawurlencode($this->redis_username).':' : ''; $encodedPass = rawurlencode($this->redis_password); $scheme = $this->enable_ssl ? 'rediss' : 'redis'; $url = "{$scheme}://{$username_part}{$encodedPass}@{$serverIp}:{$this->public_port}/0"; if ($this->enable_ssl && $this->ssl_mode === 'verify-ca') { $url .= '?cacert=/etc/ssl/certs/coolify-ca.crt'; } return $url; } return null; } ); } public function getRedisVersion() { $image_parts = explode(':', $this->image); return $image_parts[1] ?? '0.0'; } public function environment() { return $this->belongsTo(Environment::class); } public function fileStorages() { return $this->morphMany(LocalFileVolume::class, 'resource'); } public function destination() { return $this->morphTo(); } public function runtime_environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } public function persistentStorages() { return $this->morphMany(LocalPersistentVolume::class, 'resource'); } public function scheduledBackups() { return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); } public function isBackupSolutionAvailable() { return false; } public function redisPassword(): Attribute { return new Attribute( get: function () { $password = $this->runtime_environment_variables()->where('key', 'REDIS_PASSWORD')->first(); if (! $password) { return null; } return $password->value; }, ); } public function redisUsername(): Attribute { return new Attribute( get: function () { $username = $this->runtime_environment_variables()->where('key', 'REDIS_USERNAME')->first(); if (! $username) { $this->runtime_environment_variables()->create([ 'key' => 'REDIS_USERNAME', 'value' => 'default', ]); return 'default'; } return $username->value; } ); } public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable'); } } ================================================ FILE: app/Models/Subscription.php ================================================ 'datetime', ]; } public function team() { return $this->belongsTo(Team::class); } public function billingInterval(): string { if ($this->stripe_plan_id) { $configKey = collect(config('subscription')) ->search($this->stripe_plan_id); if ($configKey && str($configKey)->contains('yearly')) { return 'yearly'; } } return 'monthly'; } public function type() { if (isStripe()) { if (! $this->stripe_plan_id) { return 'zero'; } $subscription = Subscription::where('id', $this->id)->first(); if (! $subscription) { return null; } $subscriptionPlanId = data_get($subscription, 'stripe_plan_id'); if (! $subscriptionPlanId) { return null; } $subscriptionInvoicePaid = data_get($subscription, 'stripe_invoice_paid'); if (! $subscriptionInvoicePaid) { return null; } $subscriptionConfigs = collect(config('subscription')); $stripePlanId = null; $subscriptionConfigs->map(function ($value, $key) use ($subscriptionPlanId, &$stripePlanId) { if ($value === $subscriptionPlanId) { $stripePlanId = $key; } })->first(); if ($stripePlanId) { return str($stripePlanId)->after('stripe_price_id_')->before('_')->lower(); } } return 'zero'; } } ================================================ FILE: app/Models/SwarmDocker.php ================================================ morphMany(Application::class, 'destination'); } public function postgresqls() { return $this->morphMany(StandalonePostgresql::class, 'destination'); } public function redis() { return $this->morphMany(StandaloneRedis::class, 'destination'); } public function keydbs() { return $this->morphMany(StandaloneKeydb::class, 'destination'); } public function dragonflies() { return $this->morphMany(StandaloneDragonfly::class, 'destination'); } public function clickhouses() { return $this->morphMany(StandaloneClickhouse::class, 'destination'); } public function mongodbs() { return $this->morphMany(StandaloneMongodb::class, 'destination'); } public function mysqls() { return $this->morphMany(StandaloneMysql::class, 'destination'); } public function mariadbs() { return $this->morphMany(StandaloneMariadb::class, 'destination'); } public function server() { return $this->belongsTo(Server::class); } /** * Get the server attribute using identity map caching. * This intercepts lazy-loading to use cached Server lookups. */ public function getServerAttribute(): ?Server { // Use eager loaded data if available if ($this->relationLoaded('server')) { return $this->getRelation('server'); } // Use identity map for lazy loading $server = Server::findCached($this->server_id); // Cache in relation for future access on this instance if ($server) { $this->setRelation('server', $server); } return $server; } public function services() { return $this->morphMany(Service::class, 'destination'); } public function databases() { $postgresqls = $this->postgresqls; $redis = $this->redis; $mongodbs = $this->mongodbs; $mysqls = $this->mysqls; $mariadbs = $this->mariadbs; $keydbs = $this->keydbs; $dragonflies = $this->dragonflies; $clickhouses = $this->clickhouses; return $postgresqls->concat($redis)->concat($mongodbs)->concat($mysqls)->concat($mariadbs)->concat($keydbs)->concat($dragonflies)->concat($clickhouses); } public function attachedTo() { return $this->applications?->count() > 0 || $this->databases()->count() > 0; } } ================================================ FILE: app/Models/Tag.php ================================================ id)->orderBy('name'); } public function applications() { return $this->morphedByMany(Application::class, 'taggable'); } public function services() { return $this->morphedByMany(Service::class, 'taggable'); } } ================================================ FILE: app/Models/Team.php ================================================ ['type' => 'integer', 'description' => 'The unique identifier of the team.'], 'name' => ['type' => 'string', 'description' => 'The name of the team.'], 'description' => ['type' => 'string', 'description' => 'The description of the team.'], 'personal_team' => ['type' => 'boolean', 'description' => 'Whether the team is personal or not.'], 'created_at' => ['type' => 'string', 'description' => 'The date and time the team was created.'], 'updated_at' => ['type' => 'string', 'description' => 'The date and time the team was last updated.'], 'show_boarding' => ['type' => 'boolean', 'description' => 'Whether to show the boarding screen or not.'], 'custom_server_limit' => ['type' => 'string', 'description' => 'The custom server limit.'], 'members' => new OA\Property( property: 'members', type: 'array', items: new OA\Items(ref: '#/components/schemas/User'), description: 'The members of the team.' ), ] )] class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, SendsSlack { use HasFactory, HasNotificationSettings, HasSafeStringAttribute, Notifiable; protected $guarded = []; protected $casts = [ 'personal_team' => 'boolean', ]; protected static function booted() { static::created(function ($team) { $team->emailNotificationSettings()->create([ 'use_instance_email_settings' => isDev(), ]); $team->discordNotificationSettings()->create(); $team->slackNotificationSettings()->create(); $team->telegramNotificationSettings()->create(); $team->pushoverNotificationSettings()->create(); $team->webhookNotificationSettings()->create(); }); static::saving(function ($team) { if (auth()->user()?->isMember()) { throw new \Exception('You are not allowed to update this team.'); } }); static::deleting(function ($team) { $keys = $team->privateKeys; foreach ($keys as $key) { $key->delete(); } $sources = $team->sources(); foreach ($sources as $source) { $source->delete(); } $tags = Tag::whereTeamId($team->id)->get(); foreach ($tags as $tag) { $tag->delete(); } $shared_variables = $team->environment_variables(); foreach ($shared_variables as $shared_variable) { $shared_variable->delete(); } $s3s = $team->s3s; foreach ($s3s as $s3) { $s3->delete(); } }); } public static function serverLimitReached() { $serverLimit = Team::serverLimit(); $team = currentTeam(); $servers = $team->servers->count(); return $servers >= $serverLimit; } public function subscriptionPastOverDue() { if (isCloud()) { return $this->subscription?->stripe_past_due; } return false; } public function serverOverflow() { if ($this->serverLimit() < $this->servers->count()) { return true; } return false; } public static function serverLimit() { if (currentTeam()->id === 0 && isDev()) { return 9999999; } $team = Team::find(currentTeam()->id); if (! $team) { return 0; } return data_get($team, 'limits', 0); } public function limits(): Attribute { return Attribute::make( get: function () { if (config('constants.coolify.self_hosted') || $this->id === 0) { return 999999999999; } return $this->custom_server_limit ?? 2; } ); } public function routeNotificationForDiscord() { return data_get($this, 'discord_webhook_url', null); } public function routeNotificationForTelegram() { return [ 'token' => data_get($this, 'telegram_token', null), 'chat_id' => data_get($this, 'telegram_chat_id', null), ]; } public function routeNotificationForSlack() { return data_get($this, 'slack_webhook_url', null); } public function routeNotificationForPushover() { return [ 'user' => data_get($this, 'pushover_user_key', null), 'token' => data_get($this, 'pushover_api_token', null), ]; } public function getRecipients(): array { $recipients = $this->members()->pluck('email')->toArray(); $validatedEmails = array_filter($recipients, function ($email) { return filter_var($email, FILTER_VALIDATE_EMAIL); }); if (is_null($validatedEmails)) { return []; } return array_values($validatedEmails); } public function isAnyNotificationEnabled() { if (isCloud()) { return true; } return $this->getNotificationSettings('email')?->isEnabled() || $this->getNotificationSettings('discord')?->isEnabled() || $this->getNotificationSettings('slack')?->isEnabled() || $this->getNotificationSettings('telegram')?->isEnabled() || $this->getNotificationSettings('pushover')?->isEnabled() || $this->getNotificationSettings('webhook')?->isEnabled(); } public function subscriptionEnded() { $this->subscription->update([ 'stripe_subscription_id' => null, 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, 'stripe_trial_already_ended' => false, 'stripe_past_due' => false, ]); foreach ($this->servers as $server) { $server->settings()->update([ 'is_usable' => false, 'is_reachable' => false, ]); ServerReachabilityChanged::dispatch($server); } } public function environment_variables() { return $this->hasMany(SharedEnvironmentVariable::class)->whereNull('project_id')->whereNull('environment_id'); } public function members() { return $this->belongsToMany(User::class, 'team_user', 'team_id', 'user_id')->withPivot('role'); } public function subscription() { return $this->hasOne(Subscription::class); } public function applications() { return $this->hasManyThrough(Application::class, Project::class); } public function invitations() { return $this->hasMany(TeamInvitation::class); } public function isEmpty() { if ($this->projects()->count() === 0 && $this->servers()->count() === 0 && $this->privateKeys()->count() === 0 && $this->sources()->count() === 0) { return true; } return false; } public function projects() { return $this->hasMany(Project::class); } public function servers() { return $this->hasMany(Server::class); } public function privateKeys() { return $this->hasMany(PrivateKey::class); } public function cloudProviderTokens() { return $this->hasMany(CloudProviderToken::class); } public function sources() { $sources = collect([]); $github_apps = GithubApp::where(function ($query) { $query->where(function ($q) { $q->where('team_id', $this->id) ->orWhere('is_system_wide', true); })->where('is_public', false); })->get(); $gitlab_apps = GitlabApp::where(function ($query) { $query->where(function ($q) { $q->where('team_id', $this->id) ->orWhere('is_system_wide', true); })->where('is_public', false); })->get(); return $sources->merge($github_apps)->merge($gitlab_apps); } public function s3s() { return $this->hasMany(S3Storage::class)->where('is_usable', true); } public function emailNotificationSettings() { return $this->hasOne(EmailNotificationSettings::class); } public function discordNotificationSettings() { return $this->hasOne(DiscordNotificationSettings::class); } public function telegramNotificationSettings() { return $this->hasOne(TelegramNotificationSettings::class); } public function slackNotificationSettings() { return $this->hasOne(SlackNotificationSettings::class); } public function pushoverNotificationSettings() { return $this->hasOne(PushoverNotificationSettings::class); } public function webhookNotificationSettings() { return $this->hasOne(WebhookNotificationSettings::class); } } ================================================ FILE: app/Models/TeamInvitation.php ================================================ attributes['email'] = strtolower($value); } public function team() { return $this->belongsTo(Team::class); } public static function ownedByCurrentTeam() { return TeamInvitation::whereTeamId(currentTeam()->id); } public function isValid() { $createdAt = $this->created_at; $diff = $createdAt->diffInDays(now()); if ($diff <= config('constants.invitation.link.expiration_days')) { return true; } else { $this->delete(); $user = User::whereEmail($this->email)->first(); if (filled($user)) { $user->deleteIfNotVerifiedAndForcePasswordReset(); } return false; } } } ================================================ FILE: app/Models/TelegramNotificationSettings.php ================================================ 'boolean', 'telegram_token' => 'encrypted', 'telegram_chat_id' => 'encrypted', 'deployment_success_telegram_notifications' => 'boolean', 'deployment_failure_telegram_notifications' => 'boolean', 'status_change_telegram_notifications' => 'boolean', 'backup_success_telegram_notifications' => 'boolean', 'backup_failure_telegram_notifications' => 'boolean', 'scheduled_task_success_telegram_notifications' => 'boolean', 'scheduled_task_failure_telegram_notifications' => 'boolean', 'docker_cleanup_telegram_notifications' => 'boolean', 'server_disk_usage_telegram_notifications' => 'boolean', 'server_reachable_telegram_notifications' => 'boolean', 'server_unreachable_telegram_notifications' => 'boolean', 'server_patch_telegram_notifications' => 'boolean', 'traefik_outdated_telegram_notifications' => 'boolean', 'telegram_notifications_deployment_success_thread_id' => 'encrypted', 'telegram_notifications_deployment_failure_thread_id' => 'encrypted', 'telegram_notifications_status_change_thread_id' => 'encrypted', 'telegram_notifications_backup_success_thread_id' => 'encrypted', 'telegram_notifications_backup_failure_thread_id' => 'encrypted', 'telegram_notifications_scheduled_task_success_thread_id' => 'encrypted', 'telegram_notifications_scheduled_task_failure_thread_id' => 'encrypted', 'telegram_notifications_docker_cleanup_thread_id' => 'encrypted', 'telegram_notifications_server_disk_usage_thread_id' => 'encrypted', 'telegram_notifications_server_reachable_thread_id' => 'encrypted', 'telegram_notifications_server_unreachable_thread_id' => 'encrypted', 'telegram_notifications_server_patch_thread_id' => 'encrypted', 'telegram_notifications_traefik_outdated_thread_id' => 'encrypted', ]; public function team() { return $this->belongsTo(Team::class); } public function isEnabled() { return $this->telegram_enabled; } } ================================================ FILE: app/Models/User.php ================================================ ['type' => 'integer', 'description' => 'The user identifier in the database.'], 'name' => ['type' => 'string', 'description' => 'The user name.'], 'email' => ['type' => 'string', 'description' => 'The user email.'], 'email_verified_at' => ['type' => 'string', 'description' => 'The date when the user email was verified.'], 'created_at' => ['type' => 'string', 'description' => 'The date when the user was created.'], 'updated_at' => ['type' => 'string', 'description' => 'The date when the user was updated.'], 'two_factor_confirmed_at' => ['type' => 'string', 'description' => 'The date when the user two factor was confirmed.'], 'force_password_reset' => ['type' => 'boolean', 'description' => 'The flag to force the user to reset the password.'], 'marketing_emails' => ['type' => 'boolean', 'description' => 'The flag to receive marketing emails.'], ], )] class User extends Authenticatable implements SendsEmail { use DeletesUserSessions, HasApiTokens, HasFactory, Notifiable, TwoFactorAuthenticatable; protected $guarded = []; protected $hidden = [ 'password', 'remember_token', 'two_factor_recovery_codes', 'two_factor_secret', ]; protected $casts = [ 'email_verified_at' => 'datetime', 'force_password_reset' => 'boolean', 'show_boarding' => 'boolean', 'email_change_code_expires_at' => 'datetime', ]; /** * Set the email attribute to lowercase. */ public function setEmailAttribute($value) { $this->attributes['email'] = strtolower($value); } /** * Set the pending_email attribute to lowercase. */ public function setPendingEmailAttribute($value) { $this->attributes['pending_email'] = $value ? strtolower($value) : null; } protected static function boot() { parent::boot(); static::created(function (User $user) { $team = [ 'name' => $user->name."'s Team", 'personal_team' => true, 'show_boarding' => true, ]; if ($user->id === 0) { $team['id'] = 0; $team['name'] = 'Root Team'; } $new_team = Team::create($team); $user->teams()->attach($new_team, ['role' => 'owner']); }); static::deleting(function (User $user) { \DB::transaction(function () use ($user) { $teams = $user->teams; foreach ($teams as $team) { $user_alone_in_team = $team->members->count() === 1; // Prevent deletion if user is alone in root team if ($team->id === 0 && $user_alone_in_team) { throw new \Exception('User is alone in the root team, cannot delete'); } if ($user_alone_in_team) { static::finalizeTeamDeletion($user, $team); // Delete any pending team invitations for this user TeamInvitation::whereEmail($user->email)->delete(); continue; } // Load the user's role for this team $userRole = $team->members->where('id', $user->id)->first()?->pivot?->role; if ($userRole === 'owner') { $found_other_owner_or_admin = $team->members->filter(function ($member) use ($user) { return ($member->pivot->role === 'owner' || $member->pivot->role === 'admin') && $member->id !== $user->id; })->first(); if ($found_other_owner_or_admin) { $team->members()->detach($user->id); continue; } else { $found_other_member_who_is_not_owner = $team->members->filter(function ($member) { return $member->pivot->role === 'member'; })->first(); if ($found_other_member_who_is_not_owner) { $found_other_member_who_is_not_owner->pivot->role = 'owner'; $found_other_member_who_is_not_owner->pivot->save(); $team->members()->detach($user->id); } else { static::finalizeTeamDeletion($user, $team); } continue; } } else { $team->members()->detach($user->id); } } }); }); } /** * Finalize team deletion by cleaning up all associated resources */ private static function finalizeTeamDeletion(User $user, Team $team) { $servers = $team->servers; foreach ($servers as $server) { $resources = $server->definedResources(); foreach ($resources as $resource) { $resource->forceDelete(); } $server->forceDelete(); } $projects = $team->projects; foreach ($projects as $project) { $project->forceDelete(); } $team->members()->detach($user->id); $team->delete(); } /** * Delete the user if they are not verified and have a force password reset. * This is used to clean up users that have been invited, did not accept the invitation (and did not verify their email and have a force password reset). */ public function deleteIfNotVerifiedAndForcePasswordReset() { if ($this->hasVerifiedEmail() === false && $this->force_password_reset === true) { $this->delete(); } } public function recreate_personal_team() { $team = [ 'name' => $this->name."'s Team", 'personal_team' => true, 'show_boarding' => true, ]; if ($this->id === 0) { $team['id'] = 0; $team['name'] = 'Root Team'; } $new_team = Team::create($team); $this->teams()->attach($new_team, ['role' => 'owner']); return $new_team; } public function createToken(string $name, array $abilities = ['*'], ?DateTimeInterface $expiresAt = null) { $plainTextToken = sprintf( '%s%s%s', config('sanctum.token_prefix', ''), $tokenEntropy = Str::random(40), hash('crc32b', $tokenEntropy) ); $token = $this->tokens()->create([ 'name' => $name, 'token' => hash('sha256', $plainTextToken), 'abilities' => $abilities, 'expires_at' => $expiresAt, 'team_id' => session('currentTeam')->id, ]); return new NewAccessToken($token, $token->getKey().'|'.$plainTextToken); } public function teams() { return $this->belongsToMany(Team::class)->withPivot('role'); } public function changelogReads() { return $this->hasMany(UserChangelogRead::class); } public function getUnreadChangelogCount(): int { return app(\App\Services\ChangelogService::class)->getUnreadCountForUser($this); } public function getRecipients(): array { return [$this->email]; } public function sendVerificationEmail() { $mail = new MailMessage; $url = Url::temporarySignedRoute( 'verify.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $this->getKey(), 'hash' => sha1($this->getEmailForVerification()), ] ); $mail->view('emails.email-verification', [ 'url' => $url, ]); $mail->subject('Coolify: Verify your email.'); send_user_an_email($mail, $this->email); } public function sendPasswordResetNotification($token): void { $this?->notify(new TransactionalEmailsResetPassword($token)); } public function isAdmin() { return $this->role() === 'admin' || $this->role() === 'owner'; } public function isOwner() { return $this->role() === 'owner'; } public function isMember() { return $this->role() === 'member'; } public function isAdminFromSession() { if (Auth::id() === 0) { return true; } $teams = $this->teams()->get(); $is_part_of_root_team = $teams->where('id', 0)->first(); $is_admin_of_root_team = $is_part_of_root_team && ($is_part_of_root_team->pivot->role === 'admin' || $is_part_of_root_team->pivot->role === 'owner'); if ($is_part_of_root_team && $is_admin_of_root_team) { return true; } $team = $teams->where('id', session('currentTeam')->id)->first(); $role = data_get($team, 'pivot.role'); return $role === 'admin' || $role === 'owner'; } public function isInstanceAdmin() { $found_root_team = $this->teams->filter(function ($team) { if ($team->id == 0) { $role = $team->pivot->role; if ($role !== 'admin' && $role !== 'owner') { return false; } return true; } return false; }); return $found_root_team->count() > 0; } public function currentTeam(): ?Team { $sessionTeamId = data_get(session('currentTeam'), 'id'); if (is_null($sessionTeamId)) { return null; } // Check if user actually belongs to this team if (! $this->teams->contains('id', $sessionTeamId)) { session()->forget('currentTeam'); Cache::forget('user:'.$this->id.':team:'.$sessionTeamId); return null; } return Cache::remember('user:'.$this->id.':team:'.$sessionTeamId, 3600, function () use ($sessionTeamId) { return Team::find($sessionTeamId); }); } public function role(): ?string { if (data_get($this, 'pivot')) { return $this->pivot->role; } $current = $this->currentTeam(); if (is_null($current)) { return null; } $team = $this->teams->where('id', $current->id)->first(); return data_get($team, 'pivot.role'); } /** * Get the user's role in a specific team */ public function roleInTeam(int $teamId): ?string { $team = $this->teams->where('id', $teamId)->first(); return data_get($team, 'pivot.role'); } /** * Check if the user is an admin or owner of a specific team */ public function isAdminOfTeam(int $teamId): bool { $team = $this->teams->where('id', $teamId)->first(); if (! $team) { return false; } $role = $team->pivot->role ?? null; return $role === 'admin' || $role === 'owner'; } /** * Check if the user can access system resources (team_id=0) * Must be admin/owner of root team */ public function canAccessSystemResources(): bool { // Check if user is member of root team $rootTeam = $this->teams->where('id', 0)->first(); if (! $rootTeam) { return false; } // Check if user is admin or owner of root team return $this->isAdminOfTeam(0); } public function requestEmailChange(string $newEmail): void { // Generate 6-digit code $code = sprintf('%06d', mt_rand(0, 999999)); // Set expiration using config value $expiryMinutes = config('constants.email_change.verification_code_expiry_minutes', 10); $expiresAt = Carbon::now()->addMinutes($expiryMinutes); $this->update([ 'pending_email' => $newEmail, 'email_change_code' => $code, 'email_change_code_expires_at' => $expiresAt, ]); // Send verification email to new address $this->notify(new \App\Notifications\TransactionalEmails\EmailChangeVerification($this, $code, $newEmail, $expiresAt)); } public function isEmailChangeCodeValid(string $code): bool { return $this->email_change_code === $code && $this->email_change_code_expires_at && Carbon::now()->lessThan($this->email_change_code_expires_at); } public function confirmEmailChange(string $code): bool { if (! $this->isEmailChangeCodeValid($code)) { return false; } $oldEmail = $this->email; $newEmail = $this->pending_email; // Update email and clear change request fields $this->update([ 'email' => $newEmail, 'pending_email' => null, 'email_change_code' => null, 'email_change_code_expires_at' => null, ]); // For cloud users, dispatch job to update Stripe customer email asynchronously $currentTeam = $this->currentTeam(); if (isCloud() && $currentTeam?->subscription) { dispatch(new UpdateStripeCustomerEmailJob( $currentTeam, $this->id, $newEmail, $oldEmail )); } return true; } public function clearEmailChangeRequest(): void { $this->update([ 'pending_email' => null, 'email_change_code' => null, 'email_change_code_expires_at' => null, ]); } public function hasEmailChangeRequest(): bool { return ! is_null($this->pending_email) && ! is_null($this->email_change_code) && $this->email_change_code_expires_at && Carbon::now()->lessThan($this->email_change_code_expires_at); } /** * Check if the user has a password set. * OAuth users are created without passwords. */ public function hasPassword(): bool { return ! empty($this->password); } } ================================================ FILE: app/Models/UserChangelogRead.php ================================================ 'datetime', ]; public function user(): BelongsTo { return $this->belongsTo(User::class); } public static function markAsRead(int $userId, string $identifier): void { self::firstOrCreate([ 'user_id' => $userId, 'release_tag' => $identifier, ], [ 'read_at' => now(), ]); } public static function isReadByUser(int $userId, string $identifier): bool { return self::where('user_id', $userId) ->where('release_tag', $identifier) ->exists(); } public static function getReadIdentifiersForUser(int $userId): array { return self::where('user_id', $userId) ->pluck('release_tag') ->toArray(); } } ================================================ FILE: app/Models/WebhookNotificationSettings.php ================================================ 'boolean', 'webhook_url' => 'encrypted', 'deployment_success_webhook_notifications' => 'boolean', 'deployment_failure_webhook_notifications' => 'boolean', 'status_change_webhook_notifications' => 'boolean', 'backup_success_webhook_notifications' => 'boolean', 'backup_failure_webhook_notifications' => 'boolean', 'scheduled_task_success_webhook_notifications' => 'boolean', 'scheduled_task_failure_webhook_notifications' => 'boolean', 'docker_cleanup_success_webhook_notifications' => 'boolean', 'docker_cleanup_failure_webhook_notifications' => 'boolean', 'server_disk_usage_webhook_notifications' => 'boolean', 'server_reachable_webhook_notifications' => 'boolean', 'server_unreachable_webhook_notifications' => 'boolean', 'server_patch_webhook_notifications' => 'boolean', 'traefik_outdated_webhook_notifications' => 'boolean', ]; } public function team() { return $this->belongsTo(Team::class); } public function isEnabled() { return $this->webhook_enabled; } } ================================================ FILE: app/Notifications/Application/DeploymentFailed.php ================================================ onQueue('high'); $this->application = $application; $this->deployment_uuid = $deployment_uuid; $this->preview = $preview; $this->application_name = data_get($application, 'name'); $this->project_uuid = data_get($application, 'environment.project.uuid'); $this->environment_uuid = data_get($application, 'environment.uuid'); $this->environment_name = data_get($application, 'environment.name'); $this->fqdn = data_get($application, 'fqdn'); if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } $this->deployment_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('deployment_failure'); } public function toMail(): MailMessage { $mail = new MailMessage; $pull_request_id = data_get($this->preview, 'pull_request_id', 0); $fqdn = $this->fqdn; if ($pull_request_id === 0) { $mail->subject('Coolify: Deployment failed of '.$this->application_name.'.'); } else { $fqdn = $this->preview->fqdn; $mail->subject('Coolify: Deployment failed of pull request #'.$this->preview->pull_request_id.' of '.$this->application_name.'.'); } $mail->view('emails.application-deployment-failed', [ 'name' => $this->application_name, 'fqdn' => $fqdn, 'deployment_url' => $this->deployment_url, 'pull_request_id' => data_get($this->preview, 'pull_request_id', 0), ]); return $mail; } public function toDiscord(): DiscordMessage { if ($this->preview) { $message = new DiscordMessage( title: ':cross_mark: Deployment failed', description: 'Pull request: '.$this->preview->pull_request_id, color: DiscordMessage::errorColor(), isCritical: true, ); $message->addField('Project', data_get($this->application, 'environment.project.name'), true); $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); $message->addField('Deployment Logs', '[Link]('.$this->deployment_url.')'); if ($this->fqdn) { $message->addField('Domain', $this->fqdn, true); } } else { if ($this->fqdn) { $description = '[Open application]('.$this->fqdn.')'; } else { $description = ''; } $message = new DiscordMessage( title: ':cross_mark: Deployment failed', description: $description, color: DiscordMessage::errorColor(), isCritical: true, ); $message->addField('Project', data_get($this->application, 'environment.project.name'), true); $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); $message->addField('Deployment Logs', '[Link]('.$this->deployment_url.')'); } return $message; } public function toTelegram(): array { if ($this->preview) { $message = 'Coolify: Pull request #'.$this->preview->pull_request_id.' of '.$this->application_name.' ('.$this->preview->fqdn.') deployment failed: '; } else { $message = 'Coolify: Deployment failed of '.$this->application_name.' ('.$this->fqdn.'): '; } $buttons[] = [ 'text' => 'Deployment logs', 'url' => $this->deployment_url, ]; return [ 'message' => $message, 'buttons' => [ ...$buttons, ], ]; } public function toPushover(): PushoverMessage { if ($this->preview) { $title = "Pull request #{$this->preview->pull_request_id} deployment failed"; $message = "Pull request deployment failed for {$this->application_name}"; } else { $title = 'Deployment failed'; $message = "Deployment failed for {$this->application_name}"; } $buttons[] = [ 'text' => 'Deployment logs', 'url' => $this->deployment_url, ]; return new PushoverMessage( title: $title, level: 'error', message: $message, buttons: [ ...$buttons, ], ); } public function toSlack(): SlackMessage { if ($this->preview) { $title = "Pull request #{$this->preview->pull_request_id} deployment failed"; $description = "Pull request deployment failed for {$this->application_name}"; if ($this->preview->fqdn) { $description .= "\nPreview URL: {$this->preview->fqdn}"; } } else { $title = 'Deployment failed'; $description = "Deployment failed for {$this->application_name}"; if ($this->fqdn) { $description .= "\nApplication URL: {$this->fqdn}"; } } $description .= "\n\n*Project:* ".data_get($this->application, 'environment.project.name'); $description .= "\n*Environment:* {$this->environment_name}"; $description .= "\n*<{$this->deployment_url}|Deployment Logs>*"; return new SlackMessage( title: $title, description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { $data = [ 'success' => false, 'message' => 'Deployment failed', 'event' => 'deployment_failed', 'application_name' => $this->application_name, 'application_uuid' => $this->application->uuid, 'deployment_uuid' => $this->deployment_uuid, 'deployment_url' => $this->deployment_url, 'project' => data_get($this->application, 'environment.project.name'), 'environment' => $this->environment_name, ]; if ($this->preview) { $data['pull_request_id'] = $this->preview->pull_request_id; $data['preview_fqdn'] = $this->preview->fqdn; } if ($this->fqdn) { $data['fqdn'] = $this->fqdn; } return $data; } } ================================================ FILE: app/Notifications/Application/DeploymentSuccess.php ================================================ onQueue('high'); $this->application = $application; $this->deployment_uuid = $deployment_uuid; $this->preview = $preview; $this->application_name = data_get($application, 'name'); $this->project_uuid = data_get($application, 'environment.project.uuid'); $this->environment_uuid = data_get($application, 'environment.uuid'); $this->environment_name = data_get($application, 'environment.name'); $this->fqdn = data_get($application, 'fqdn'); if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } $this->deployment_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('deployment_success'); } public function toMail(): MailMessage { $mail = new MailMessage; $pull_request_id = data_get($this->preview, 'pull_request_id', 0); $fqdn = $this->fqdn; if ($pull_request_id === 0) { $mail->subject("Coolify: New version is deployed of {$this->application_name}"); } else { $fqdn = $this->preview->fqdn; $mail->subject("Coolify: Pull request #{$pull_request_id} of {$this->application_name} deployed successfully"); } $mail->view('emails.application-deployment-success', [ 'name' => $this->application_name, 'fqdn' => $fqdn, 'deployment_url' => $this->deployment_url, 'pull_request_id' => $pull_request_id, ]); return $mail; } public function toDiscord(): DiscordMessage { if ($this->preview) { $message = new DiscordMessage( title: ':white_check_mark: Preview deployment successful', description: 'Pull request: '.$this->preview->pull_request_id, color: DiscordMessage::successColor(), ); if ($this->preview->fqdn) { $message->addField('Application', '[Link]('.$this->preview->fqdn.')'); } $message->addField('Project', data_get($this->application, 'environment.project.name'), true); $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); $message->addField('Deployment logs', '[Link]('.$this->deployment_url.')'); } else { if ($this->fqdn) { $description = '[Open application]('.$this->fqdn.')'; } else { $description = ''; } $message = new DiscordMessage( title: ':white_check_mark: New version successfully deployed', description: $description, color: DiscordMessage::successColor(), ); $message->addField('Project', data_get($this->application, 'environment.project.name'), true); $message->addField('Environment', $this->environment_name, true); $message->addField('Name', $this->application_name, true); $message->addField('Deployment logs', '[Link]('.$this->deployment_url.')'); } return $message; } public function toTelegram(): array { if ($this->preview) { $message = 'Coolify: New PR'.$this->preview->pull_request_id.' version successfully deployed of '.$this->application_name.''; if ($this->preview->fqdn) { $buttons[] = [ 'text' => 'Open Application', 'url' => $this->preview->fqdn, ]; } } else { $message = '✅ New version successfully deployed of '.$this->application_name.''; if ($this->fqdn) { $buttons[] = [ 'text' => 'Open Application', 'url' => $this->fqdn, ]; } } $buttons[] = [ 'text' => 'Deployment logs', 'url' => $this->deployment_url, ]; return [ 'message' => $message, 'buttons' => [ ...$buttons, ], ]; } public function toPushover(): PushoverMessage { if ($this->preview) { $title = "Pull request #{$this->preview->pull_request_id} successfully deployed"; $message = 'New PR'.$this->preview->pull_request_id.' version successfully deployed of '.$this->application_name.''; if ($this->preview->fqdn) { $buttons[] = [ 'text' => 'Open Application', 'url' => $this->preview->fqdn, ]; } } else { $title = 'New version successfully deployed'; $message = 'New version successfully deployed of '.$this->application_name.''; if ($this->fqdn) { $buttons[] = [ 'text' => 'Open Application', 'url' => $this->fqdn, ]; } } $buttons[] = [ 'text' => 'Deployment logs', 'url' => $this->deployment_url, ]; return new PushoverMessage( title: $title, level: 'success', message: $message, buttons: [ ...$buttons, ], ); } public function toSlack(): SlackMessage { if ($this->preview) { $title = "Pull request #{$this->preview->pull_request_id} successfully deployed"; $description = "New version successfully deployed for {$this->application_name}"; if ($this->preview->fqdn) { $description .= "\nPreview URL: {$this->preview->fqdn}"; } } else { $title = 'New version successfully deployed'; $description = "New version successfully deployed for {$this->application_name}"; if ($this->fqdn) { $description .= "\nApplication URL: {$this->fqdn}"; } } $description .= "\n\n*Project:* ".data_get($this->application, 'environment.project.name'); $description .= "\n*Environment:* {$this->environment_name}"; $description .= "\n*<{$this->deployment_url}|Deployment Logs>*"; return new SlackMessage( title: $title, description: $description, color: SlackMessage::successColor() ); } public function toWebhook(): array { $data = [ 'success' => true, 'message' => 'New version successfully deployed', 'event' => 'deployment_success', 'application_name' => $this->application_name, 'application_uuid' => $this->application->uuid, 'deployment_uuid' => $this->deployment_uuid, 'deployment_url' => $this->deployment_url, 'project' => data_get($this->application, 'environment.project.name'), 'environment' => $this->environment_name, ]; if ($this->preview) { $data['pull_request_id'] = $this->preview->pull_request_id; $data['preview_fqdn'] = $this->preview->fqdn; } if ($this->fqdn) { $data['fqdn'] = $this->fqdn; } return $data; } } ================================================ FILE: app/Notifications/Application/StatusChanged.php ================================================ onQueue('high'); $this->resource_name = data_get($resource, 'name'); $this->project_uuid = data_get($resource, 'environment.project.uuid'); $this->environment_uuid = data_get($resource, 'environment.uuid'); $this->environment_name = data_get($resource, 'environment.name'); $this->fqdn = data_get($resource, 'fqdn', null); if (str($this->fqdn)->explode(',')->count() > 1) { $this->fqdn = str($this->fqdn)->explode(',')->first(); } $this->resource_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->resource->uuid}"; } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('status_change'); } public function toMail(): MailMessage { $mail = new MailMessage; $fqdn = $this->fqdn; $mail->subject("Coolify: {$this->resource_name} has been stopped"); $mail->view('emails.application-status-changes', [ 'name' => $this->resource_name, 'fqdn' => $fqdn, 'resource_url' => $this->resource_url, ]); return $mail; } public function toDiscord(): DiscordMessage { return new DiscordMessage( title: ':cross_mark: Application stopped', description: '[Open Application in Coolify]('.$this->resource_url.')', color: DiscordMessage::errorColor(), isCritical: true, ); } public function toTelegram(): array { $message = 'Coolify: '.$this->resource_name.' has been stopped.'; return [ 'message' => $message, 'buttons' => [ [ 'text' => 'Open Application in Coolify', 'url' => $this->resource_url, ], ], ]; } public function toPushover(): PushoverMessage { $message = $this->resource_name.' has been stopped.'; return new PushoverMessage( title: 'Application stopped', level: 'error', message: $message, buttons: [ [ 'text' => 'Open Application in Coolify', 'url' => $this->resource_url, ], ], ); } public function toSlack(): SlackMessage { $title = 'Application stopped'; $description = "{$this->resource_name} has been stopped"; $description .= "\n\n*Project:* ".data_get($this->resource, 'environment.project.name'); $description .= "\n*Environment:* {$this->environment_name}"; $description .= "\n*Application URL:* {$this->resource_url}"; return new SlackMessage( title: $title, description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { return [ 'success' => false, 'message' => 'Application stopped', 'event' => 'status_changed', 'application_name' => $this->resource_name, 'application_uuid' => $this->resource->uuid, 'url' => $this->resource_url, 'project' => data_get($this->resource, 'environment.project.name'), 'environment' => $this->environment_name, 'fqdn' => $this->fqdn, ]; } } ================================================ FILE: app/Notifications/Channels/DiscordChannel.php ================================================ toDiscord(); $discordSettings = $notifiable->discordNotificationSettings; if (! $discordSettings || ! $discordSettings->isEnabled() || ! $discordSettings->discord_webhook_url) { return; } if (! $discordSettings->discord_ping_enabled) { $message->isCritical = false; } SendMessageToDiscordJob::dispatch($message, $discordSettings->discord_webhook_url); } } ================================================ FILE: app/Notifications/Channels/EmailChannel.php ================================================ members; $useInstanceEmailSettings = $notifiable->emailNotificationSettings->use_instance_email_settings; $isTransactionalEmail = data_get($notification, 'isTransactionalEmail', false); $customEmails = data_get($notification, 'emails', null); if ($useInstanceEmailSettings || $isTransactionalEmail) { $settings = instanceSettings(); } else { $settings = $notifiable->emailNotificationSettings; } $isResendEnabled = $settings->resend_enabled; $isSmtpEnabled = $settings->smtp_enabled; if ($customEmails) { $recipients = [$customEmails]; } else { $recipients = $notifiable->getRecipients(); } // Validate team membership for all recipients if (count($recipients) === 0) { throw new Exception('No email recipients found'); } // Skip team membership validation for test notifications $isTestNotification = data_get($notification, 'isTestNotification', false); if (! $isTestNotification) { foreach ($recipients as $recipient) { // Check if the recipient is part of the team if (! $members->contains('email', $recipient)) { $emailSettings = $notifiable->emailNotificationSettings; data_set($emailSettings, 'smtp_password', '********'); data_set($emailSettings, 'resend_api_key', '********'); send_internal_notification(sprintf( "Recipient is not part of the team: %s\nTeam: %s\nNotification: %s\nNotifiable: %s\nEmail Settings:\n%s", $recipient, $team, get_class($notification), get_class($notifiable), json_encode($emailSettings, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) )); throw new Exception('Recipient is not part of the team'); } } } $mailMessage = $notification->toMail($notifiable); if ($isResendEnabled) { $resend = Resend::client($settings->resend_api_key); $from = "{$settings->smtp_from_name} <{$settings->smtp_from_address}>"; $resend->emails->send([ 'from' => $from, 'to' => $recipients, 'subject' => $mailMessage->subject, 'html' => (string) $mailMessage->render(), ]); } elseif ($isSmtpEnabled) { $encryption = match (strtolower($settings->smtp_encryption)) { 'starttls' => null, 'tls' => 'tls', 'none' => null, default => null, }; $transport = new \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport( $settings->smtp_host, $settings->smtp_port, $encryption ); $transport->setUsername($settings->smtp_username ?? ''); $transport->setPassword($settings->smtp_password ?? ''); $mailer = new \Symfony\Component\Mailer\Mailer($transport); $fromEmail = $settings->smtp_from_address ?? 'noreply@localhost'; $fromName = $settings->smtp_from_name ?? 'System'; $from = new \Symfony\Component\Mime\Address($fromEmail, $fromName); $email = (new \Symfony\Component\Mime\Email) ->from($from) ->to(...$recipients) ->subject($mailMessage->subject) ->html((string) $mailMessage->render()); $mailer->send($email); } } catch (\Resend\Exceptions\ErrorException $e) { // Map HTTP status codes to user-friendly messages $userMessage = match ($e->getErrorCode()) { 403 => 'Invalid Resend API key. Please verify your API key in the Resend dashboard and update it in settings.', 401 => 'Your Resend API key has restricted permissions. Please use an API key with Full Access permissions.', 429 => 'Resend rate limit exceeded. Please try again in a few minutes.', 400 => 'Email validation failed: '.$e->getErrorMessage(), default => 'Failed to send email via Resend: '.$e->getErrorMessage(), }; // Log detailed error for admin debugging (redact sensitive data) $emailSettings = $notifiable->emailNotificationSettings ?? instanceSettings(); data_set($emailSettings, 'smtp_password', '********'); data_set($emailSettings, 'resend_api_key', '********'); send_internal_notification(sprintf( "Resend Error\nStatus Code: %s\nMessage: %s\nNotification: %s\nEmail Settings:\n%s", $e->getErrorCode(), $e->getErrorMessage(), get_class($notification), json_encode($emailSettings, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) )); // Don't report expected errors (invalid keys, validation) to Sentry if (in_array($e->getErrorCode(), [403, 401, 400])) { throw NonReportableException::fromException(new \Exception($userMessage, $e->getCode(), $e)); } throw new \Exception($userMessage, $e->getCode(), $e); } catch (\Resend\Exceptions\TransporterException $e) { send_internal_notification("Resend Transport Error: {$e->getMessage()}"); throw new \Exception('Unable to connect to Resend API. Please check your internet connection and try again.'); } catch (\Throwable $e) { // Check if this is a Resend domain verification error on cloud instances if (isCloud() && str_contains($e->getMessage(), 'domain is not verified')) { // Throw as NonReportableException so it won't go to Sentry throw NonReportableException::fromException($e); } throw $e; } } } ================================================ FILE: app/Notifications/Channels/PushoverChannel.php ================================================ toPushover(); $pushoverSettings = $notifiable->pushoverNotificationSettings; if (! $pushoverSettings || ! $pushoverSettings->isEnabled() || ! $pushoverSettings->pushover_user_key || ! $pushoverSettings->pushover_api_token) { return; } SendMessageToPushoverJob::dispatch($message, $pushoverSettings->pushover_api_token, $pushoverSettings->pushover_user_key); } } ================================================ FILE: app/Notifications/Channels/SendsDiscord.php ================================================ toSlack(); $slackSettings = $notifiable->slackNotificationSettings; if (! $slackSettings || ! $slackSettings->isEnabled() || ! $slackSettings->slack_webhook_url) { return; } SendMessageToSlackJob::dispatch($message, $slackSettings->slack_webhook_url); } } ================================================ FILE: app/Notifications/Channels/TelegramChannel.php ================================================ toTelegram($notifiable); $settings = $notifiable->telegramNotificationSettings; $message = data_get($data, 'message'); $buttons = data_get($data, 'buttons', []); $telegramToken = $settings->telegram_token; $chatId = $settings->telegram_chat_id; $threadId = match (get_class($notification)) { \App\Notifications\Application\DeploymentSuccess::class => $settings->telegram_notifications_deployment_success_thread_id, \App\Notifications\Application\DeploymentFailed::class => $settings->telegram_notifications_deployment_failure_thread_id, \App\Notifications\Application\StatusChanged::class, \App\Notifications\Container\ContainerRestarted::class, \App\Notifications\Container\ContainerStopped::class => $settings->telegram_notifications_status_change_thread_id, \App\Notifications\Database\BackupSuccess::class => $settings->telegram_notifications_backup_success_thread_id, \App\Notifications\Database\BackupFailed::class => $settings->telegram_notifications_backup_failure_thread_id, \App\Notifications\ScheduledTask\TaskSuccess::class => $settings->telegram_notifications_scheduled_task_success_thread_id, \App\Notifications\ScheduledTask\TaskFailed::class => $settings->telegram_notifications_scheduled_task_failure_thread_id, \App\Notifications\Server\DockerCleanupSuccess::class => $settings->telegram_notifications_docker_cleanup_success_thread_id, \App\Notifications\Server\DockerCleanupFailed::class => $settings->telegram_notifications_docker_cleanup_failure_thread_id, \App\Notifications\Server\HighDiskUsage::class => $settings->telegram_notifications_server_disk_usage_thread_id, \App\Notifications\Server\Unreachable::class => $settings->telegram_notifications_server_unreachable_thread_id, \App\Notifications\Server\Reachable::class => $settings->telegram_notifications_server_reachable_thread_id, \App\Notifications\Server\ServerPatchCheck::class => $settings->telegram_notifications_server_patch_thread_id, default => null, }; if (! $telegramToken || ! $chatId || ! $message) { return; } SendMessageToTelegramJob::dispatch($message, $buttons, $telegramToken, $chatId, $threadId); } } ================================================ FILE: app/Notifications/Channels/TransactionalEmailChannel.php ================================================ newEmail ? $notification->newEmail : $notifiable->email; if (! $email) { return; } $this->bootConfigs(); $mailMessage = $notification->toMail($notifiable); Mail::send( [], [], fn (Message $message) => $message ->to($email) ->subject($mailMessage->subject) ->html((string) $mailMessage->render()) ); } private function bootConfigs(): void { $type = set_transanctional_email_settings(); if (blank($type)) { throw new Exception('No email settings found.'); } } } ================================================ FILE: app/Notifications/Channels/WebhookChannel.php ================================================ webhookNotificationSettings; if (! $webhookSettings || ! $webhookSettings->isEnabled() || ! $webhookSettings->webhook_url) { if (isDev()) { ray('Webhook notification skipped - not enabled or no URL configured'); } return; } $payload = $notification->toWebhook(); if (isDev()) { ray('Dispatching webhook notification', [ 'notification' => get_class($notification), 'url' => $webhookSettings->webhook_url, 'payload' => $payload, ]); } SendWebhookJob::dispatch($payload, $webhookSettings->webhook_url); } } ================================================ FILE: app/Notifications/Container/ContainerRestarted.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('status_change'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}"); $mail->view('emails.container-restarted', [ 'containerName' => $this->name, 'serverName' => $this->server->name, 'url' => $this->url, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':warning: Resource restarted', description: "{$this->name} has been restarted automatically on {$this->server->name}.", color: DiscordMessage::infoColor(), ); if ($this->url) { $message->addField('Resource', '[Link]('.$this->url.')'); } return $message; } public function toTelegram(): array { $message = "Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}"; $payload = [ 'message' => $message, ]; if ($this->url) { $payload['buttons'] = [ [ [ 'text' => 'Check Proxy in Coolify', 'url' => $this->url, ], ], ]; } return $payload; } public function toPushover(): PushoverMessage { $buttons = []; if ($this->url) { $buttons[] = [ 'text' => 'Check Proxy in Coolify', 'url' => $this->url, ]; } return new PushoverMessage( title: 'Resource restarted', level: 'warning', message: "A resource ({$this->name}) has been restarted automatically on {$this->server->name}", buttons: $buttons, ); } public function toSlack(): SlackMessage { $title = 'Resource restarted'; $description = "A resource ({$this->name}) has been restarted automatically on {$this->server->name}"; if ($this->url) { $description .= "\n*Resource URL:* {$this->url}"; } return new SlackMessage( title: $title, description: $description, color: SlackMessage::warningColor() ); } public function toWebhook(): array { $data = [ 'success' => true, 'message' => 'Resource restarted automatically', 'event' => 'container_restarted', 'container_name' => $this->name, 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, ]; if ($this->url) { $data['url'] = $this->url; } return $data; } } ================================================ FILE: app/Notifications/Container/ContainerStopped.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('status_change'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: A resource has been stopped unexpectedly on {$this->server->name}"); $mail->view('emails.container-stopped', [ 'containerName' => $this->name, 'serverName' => $this->server->name, 'url' => $this->url, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':cross_mark: Resource stopped', description: "{$this->name} has been stopped unexpectedly on {$this->server->name}.", color: DiscordMessage::errorColor(), ); if ($this->url) { $message->addField('Resource', '[Link]('.$this->url.')'); } return $message; } public function toTelegram(): array { $message = "Coolify: A resource ($this->name) has been stopped unexpectedly on {$this->server->name}"; $payload = [ 'message' => $message, ]; if ($this->url) { $payload['buttons'] = [ [ [ 'text' => 'Open Application in Coolify', 'url' => $this->url, ], ], ]; } return $payload; } public function toPushover(): PushoverMessage { $buttons = []; if ($this->url) { $buttons[] = [ 'text' => 'Open Application in Coolify', 'url' => $this->url, ]; } return new PushoverMessage( title: 'Resource stopped', level: 'error', message: "A resource ({$this->name}) has been stopped unexpectedly on {$this->server->name}", buttons: $buttons, ); } public function toSlack(): SlackMessage { $title = 'Resource stopped'; $description = "A resource ({$this->name}) has been stopped unexpectedly on {$this->server->name}"; if ($this->url) { $description .= "\n*Resource URL:* {$this->url}"; } return new SlackMessage( title: $title, description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { $data = [ 'success' => false, 'message' => 'Resource stopped unexpectedly', 'event' => 'container_stopped', 'container_name' => $this->name, 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, ]; if ($this->url) { $data['url'] = $this->url; } return $data; } } ================================================ FILE: app/Notifications/CustomEmailNotification.php ================================================ onQueue('high'); $this->name = $database->name; $this->frequency = $backup->frequency; } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('backup_failure'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: [ACTION REQUIRED] Database Backup FAILED for {$this->database->name}"); $mail->view('emails.backup-failed', [ 'name' => $this->name, 'database_name' => $this->database_name, 'frequency' => $this->frequency, 'output' => $this->output, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':cross_mark: Database backup failed', description: "Database backup for {$this->name} (db:{$this->database_name}) has FAILED.", color: DiscordMessage::errorColor(), isCritical: true, ); $message->addField('Frequency', $this->frequency, true); $message->addField('Output', $this->output); return $message; } public function toTelegram(): array { $message = "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was FAILED.\n\nReason:\n{$this->output}"; return [ 'message' => $message, ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Database backup failed', level: 'error', message: "Database backup for {$this->name} (db:{$this->database_name}) was FAILED

Frequency: {$this->frequency} .
Reason: {$this->output}", ); } public function toSlack(): SlackMessage { $title = 'Database backup failed'; $description = "Database backup for {$this->name} (db:{$this->database_name}) has FAILED."; $description .= "\n\n*Frequency:* {$this->frequency}"; $description .= "\n\n*Error Output:* {$this->output}"; return new SlackMessage( title: $title, description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { $url = base_url().'/project/'.data_get($this->database, 'environment.project.uuid').'/environment/'.data_get($this->database, 'environment.uuid').'/database/'.$this->database->uuid; return [ 'success' => false, 'message' => 'Database backup failed', 'event' => 'backup_failed', 'database_name' => $this->name, 'database_uuid' => $this->database->uuid, 'database_type' => $this->database_name, 'frequency' => $this->frequency, 'error_output' => $this->output, 'url' => $url, ]; } } ================================================ FILE: app/Notifications/Database/BackupSuccess.php ================================================ onQueue('high'); $this->name = $database->name; $this->frequency = $backup->frequency; } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('backup_success'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Backup successfully done for {$this->database->name}"); $mail->view('emails.backup-success', [ 'name' => $this->name, 'database_name' => $this->database_name, 'frequency' => $this->frequency, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':white_check_mark: Database backup successful', description: "Database backup for {$this->name} (db:{$this->database_name}) was successful.", color: DiscordMessage::successColor(), ); $message->addField('Frequency', $this->frequency, true); return $message; } public function toTelegram(): array { $message = "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was successful."; return [ 'message' => $message, ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Database backup successful', level: 'success', message: "Database backup for {$this->name} (db:{$this->database_name}) was successful.

Frequency: {$this->frequency}.", ); } public function toSlack(): SlackMessage { $title = 'Database backup successful'; $description = "Database backup for {$this->name} (db:{$this->database_name}) was successful."; $description .= "\n\n*Frequency:* {$this->frequency}"; return new SlackMessage( title: $title, description: $description, color: SlackMessage::successColor() ); } public function toWebhook(): array { $url = base_url().'/project/'.data_get($this->database, 'environment.project.uuid').'/environment/'.data_get($this->database, 'environment.uuid').'/database/'.$this->database->uuid; return [ 'success' => true, 'message' => 'Database backup successful', 'event' => 'backup_success', 'database_name' => $this->name, 'database_uuid' => $this->database->uuid, 'database_type' => $this->database_name, 'frequency' => $this->frequency, 'url' => $url, ]; } } ================================================ FILE: app/Notifications/Database/BackupSuccessWithS3Warning.php ================================================ onQueue('high'); $this->name = $database->name; $this->frequency = $backup->frequency; if ($backup->s3) { $this->s3_storage_url = base_url().'/storages/'.$backup->s3->uuid; } } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('backup_failure'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Backup succeeded locally but S3 upload failed for {$this->database->name}"); $mail->view('emails.backup-success-with-s3-warning', [ 'name' => $this->name, 'database_name' => $this->database_name, 'frequency' => $this->frequency, 's3_error' => $this->s3_error, 's3_storage_url' => $this->s3_storage_url, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':warning: Database backup succeeded locally, S3 upload failed', description: "Database backup for {$this->name} (db:{$this->database_name}) was created successfully on local storage, but failed to upload to S3.", color: DiscordMessage::warningColor(), ); $message->addField('Frequency', $this->frequency, true); $message->addField('S3 Error', $this->s3_error); if ($this->s3_storage_url) { $message->addField('S3 Storage', '[Check Configuration]('.$this->s3_storage_url.')'); } return $message; } public function toTelegram(): array { $message = "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} succeeded locally but failed to upload to S3.\n\nS3 Error:\n{$this->s3_error}"; if ($this->s3_storage_url) { $message .= "\n\nCheck S3 Configuration: {$this->s3_storage_url}"; } return [ 'message' => $message, ]; } public function toPushover(): PushoverMessage { $message = "Database backup for {$this->name} (db:{$this->database_name}) was created successfully on local storage, but failed to upload to S3.

Frequency: {$this->frequency}.
S3 Error: {$this->s3_error}"; if ($this->s3_storage_url) { $message .= "

s3_storage_url}\">Check S3 Configuration"; } return new PushoverMessage( title: 'Database backup succeeded locally, S3 upload failed', level: 'warning', message: $message, ); } public function toSlack(): SlackMessage { $title = 'Database backup succeeded locally, S3 upload failed'; $description = "Database backup for {$this->name} (db:{$this->database_name}) was created successfully on local storage, but failed to upload to S3."; $description .= "\n\n*Frequency:* {$this->frequency}"; $description .= "\n\n*S3 Error:* {$this->s3_error}"; if ($this->s3_storage_url) { $description .= "\n\n*S3 Storage:* <{$this->s3_storage_url}|Check Configuration>"; } return new SlackMessage( title: $title, description: $description, color: SlackMessage::warningColor() ); } public function toWebhook(): array { $url = base_url().'/project/'.data_get($this->database, 'environment.project.uuid').'/environment/'.data_get($this->database, 'environment.uuid').'/database/'.$this->database->uuid; $data = [ 'success' => true, 'message' => 'Database backup succeeded locally, S3 upload failed', 'event' => 'backup_success_with_s3_warning', 'database_name' => $this->name, 'database_uuid' => $this->database->uuid, 'database_type' => $this->database_name, 'frequency' => $this->frequency, 's3_error' => $this->s3_error, 'url' => $url, ]; if ($this->s3_storage_url) { $data['s3_storage_url'] = $this->s3_storage_url; } return $data; } } ================================================ FILE: app/Notifications/Dto/DiscordMessage.php ================================================ fields[] = [ 'name' => $name, 'value' => $value, 'inline' => $inline, ]; return $this; } public function toPayload(): array { $footerText = 'Coolify v'.config('constants.coolify.version'); if (isCloud()) { $footerText = 'Coolify Cloud'; } $payload = [ 'embeds' => [ [ 'title' => $this->title, 'description' => $this->description, 'color' => $this->color, 'fields' => $this->addTimestampToFields($this->fields), 'footer' => [ 'text' => $footerText, ], ], ], ]; if ($this->isCritical) { $payload['content'] = '@here'; } return $payload; } private function addTimestampToFields(array $fields): array { $fields[] = [ 'name' => 'Time', 'value' => 'timestamp.':R>', 'inline' => true, ]; return $fields; } } ================================================ FILE: app/Notifications/Dto/PushoverMessage.php ================================================ level) { 'info' => 'ℹ️', 'error' => '❌', 'success' => '✅ ', 'warning' => '⚠️', }; } public function toPayload(string $token, string $user): array { $levelIcon = $this->getLevelIcon(); $payload = [ 'token' => $token, 'user' => $user, 'title' => "{$levelIcon} {$this->title}", 'message' => $this->message, 'html' => 1, ]; foreach ($this->buttons as $button) { $buttonUrl = data_get($button, 'url'); $text = data_get($button, 'text', 'Click here'); if ($buttonUrl && str_contains($buttonUrl, 'http://localhost')) { $buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl); } $payload['message'] .= " ".$text.''; } Log::info('Pushover message', $payload); return $payload; } } ================================================ FILE: app/Notifications/Dto/SlackMessage.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('general'); } public function toDiscord(): DiscordMessage { return new DiscordMessage( title: 'Coolify: General Notification', description: $this->message, color: DiscordMessage::infoColor(), ); } public function toTelegram(): array { return [ 'message' => $this->message, ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'General Notification', level: 'info', message: $this->message, ); } public function toSlack(): SlackMessage { return new SlackMessage( title: 'Coolify: General Notification', description: $this->message, color: SlackMessage::infoColor(), ); } } ================================================ FILE: app/Notifications/Notification.php ================================================ onQueue('high'); if ($task->application) { $this->url = $task->application->taskLink($task->uuid); } elseif ($task->service) { $this->url = $task->service->taskLink($task->uuid); } } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('scheduled_task_failure'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: [ACTION REQUIRED] Scheduled task ({$this->task->name}) failed."); $mail->view('emails.scheduled-task-failed', [ 'task' => $this->task, 'url' => $this->url, 'output' => $this->output, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':cross_mark: Scheduled task failed', description: "Scheduled task ({$this->task->name}) failed.", color: DiscordMessage::errorColor(), ); if ($this->url) { $message->addField('Scheduled task', '[Link]('.$this->url.')'); } return $message; } public function toTelegram(): array { $message = "Coolify: Scheduled task ({$this->task->name}) failed with output: {$this->output}"; if ($this->url) { $buttons[] = [ 'text' => 'Open task in Coolify', 'url' => (string) $this->url, ]; } return [ 'message' => $message, ]; } public function toPushover(): PushoverMessage { $message = "Scheduled task ({$this->task->name}) failed
"; if ($this->output) { $message .= "
Error Output:{$this->output}"; } $buttons = []; if ($this->url) { $buttons[] = [ 'text' => 'Open task in Coolify', 'url' => (string) $this->url, ]; } return new PushoverMessage( title: 'Scheduled task failed', level: 'error', message: $message, buttons: $buttons, ); } public function toSlack(): SlackMessage { $title = 'Scheduled task failed'; $description = "Scheduled task ({$this->task->name}) failed."; if ($this->output) { $description .= "\n\n*Error Output:* {$this->output}"; } if ($this->url) { $description .= "\n\n*Task URL:* {$this->url}"; } return new SlackMessage( title: $title, description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { $data = [ 'success' => false, 'message' => 'Scheduled task failed', 'event' => 'task_failed', 'task_name' => $this->task->name, 'task_uuid' => $this->task->uuid, 'output' => $this->output, ]; if ($this->task->application) { $data['application_uuid'] = $this->task->application->uuid; } elseif ($this->task->service) { $data['service_uuid'] = $this->task->service->uuid; } if ($this->url) { $data['url'] = $this->url; } return $data; } } ================================================ FILE: app/Notifications/ScheduledTask/TaskSuccess.php ================================================ onQueue('high'); if ($task->application) { $this->url = $task->application->taskLink($task->uuid); } elseif ($task->service) { $this->url = $task->service->taskLink($task->uuid); } } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('scheduled_task_success'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Scheduled task ({$this->task->name}) succeeded."); $mail->view('emails.scheduled-task-success', [ 'task' => $this->task, 'url' => $this->url, 'output' => $this->output, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':white_check_mark: Scheduled task succeeded', description: "Scheduled task ({$this->task->name}) succeeded.", color: DiscordMessage::successColor(), ); if ($this->url) { $message->addField('Scheduled task', '[Link]('.$this->url.')'); } return $message; } public function toTelegram(): array { $message = "Coolify: Scheduled task ({$this->task->name}) succeeded."; if ($this->url) { $buttons[] = [ 'text' => 'Open task in Coolify', 'url' => (string) $this->url, ]; } return [ 'message' => $message, ]; } public function toPushover(): PushoverMessage { $message = "Coolify: Scheduled task ({$this->task->name}) succeeded."; $buttons = []; if ($this->url) { $buttons[] = [ 'text' => 'Open task in Coolify', 'url' => (string) $this->url, ]; } return new PushoverMessage( title: 'Scheduled task succeeded', level: 'success', message: $message, buttons: $buttons, ); } public function toSlack(): SlackMessage { $title = 'Scheduled task succeeded'; $description = "Scheduled task ({$this->task->name}) succeeded."; if ($this->url) { $description .= "\n\n*Task URL:* {$this->url}"; } return new SlackMessage( title: $title, description: $description, color: SlackMessage::successColor() ); } public function toWebhook(): array { $data = [ 'success' => true, 'message' => 'Scheduled task succeeded', 'event' => 'task_success', 'task_name' => $this->task->name, 'task_uuid' => $this->task->uuid, 'output' => $this->output, ]; if ($this->task->application) { $data['application_uuid'] = $this->task->application->uuid; } elseif ($this->task->service) { $data['service_uuid'] = $this->task->service->uuid; } if ($this->url) { $data['url'] = $this->url; } return $data; } } ================================================ FILE: app/Notifications/Server/DockerCleanupFailed.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('docker_cleanup_failure'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: [ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}"); $mail->view('emails.docker-cleanup-failed', [ 'name' => $this->server->name, 'text' => $this->message, ]); return $mail; } public function toDiscord(): DiscordMessage { return new DiscordMessage( title: ':cross_mark: Coolify: [ACTION REQUIRED] Docker cleanup job failed on '.$this->server->name, description: $this->message, color: DiscordMessage::errorColor(), ); } public function toTelegram(): array { return [ 'message' => "Coolify: [ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}!\n\n{$this->message}", ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Docker cleanup job failed', level: 'error', message: "[ACTION REQUIRED] Docker cleanup job failed on {$this->server->name}!\n\n{$this->message}", ); } public function toSlack(): SlackMessage { return new SlackMessage( title: 'Coolify: [ACTION REQUIRED] Docker cleanup job failed', description: "Docker cleanup job failed on '{$this->server->name}'!\n\n{$this->message}", color: SlackMessage::errorColor() ); } public function toWebhook(): array { $url = base_url().'/server/'.$this->server->uuid; return [ 'success' => false, 'message' => 'Docker cleanup job failed', 'event' => 'docker_cleanup_failed', 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, 'error_message' => $this->message, 'url' => $url, ]; } } ================================================ FILE: app/Notifications/Server/DockerCleanupSuccess.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('docker_cleanup_success'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Docker cleanup job succeeded on {$this->server->name}"); $mail->view('emails.docker-cleanup-success', [ 'name' => $this->server->name, 'text' => $this->message, ]); return $mail; } public function toDiscord(): DiscordMessage { return new DiscordMessage( title: ':white_check_mark: Coolify: Docker cleanup job succeeded on '.$this->server->name, description: $this->message, color: DiscordMessage::successColor(), ); } public function toTelegram(): array { return [ 'message' => "Coolify: Docker cleanup job succeeded on {$this->server->name}!\n\n{$this->message}", ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Docker cleanup job succeeded', level: 'success', message: "Docker cleanup job succeeded on {$this->server->name}!\n\n{$this->message}", ); } public function toSlack(): SlackMessage { return new SlackMessage( title: 'Coolify: Docker cleanup job succeeded', description: "Docker cleanup job succeeded on '{$this->server->name}'!\n\n{$this->message}", color: SlackMessage::successColor() ); } public function toWebhook(): array { $url = base_url().'/server/'.$this->server->uuid; return [ 'success' => true, 'message' => 'Docker cleanup job succeeded', 'event' => 'docker_cleanup_success', 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, 'cleanup_message' => $this->message, 'url' => $url, ]; } } ================================================ FILE: app/Notifications/Server/ForceDisabled.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('server_force_disabled'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Server ({$this->server->name}) disabled because it is not paid!"); $mail->view('emails.server-force-disabled', [ 'name' => $this->server->name, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':cross_mark: Server disabled', description: "Server ({$this->server->name}) disabled because it is not paid!", color: DiscordMessage::errorColor(), ); $message->addField('Please update your subscription to enable the server again!', '[Link](https://app.coolify.io/subscriptions)'); return $message; } public function toTelegram(): array { return [ 'message' => "Coolify: Server ({$this->server->name}) disabled because it is not paid!\n All automations and integrations are stopped.\nPlease update your subscription to enable the server again [here](https://app.coolify.io/subscriptions).", ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Server disabled', level: 'error', message: "Server ({$this->server->name}) disabled because it is not paid!\n All automations and integrations are stopped.
Please update your subscription to enable the server again [here](https://app.coolify.io/subscriptions).", ); } public function toSlack(): SlackMessage { $title = 'Server disabled'; $description = "Server ({$this->server->name}) disabled because it is not paid!\n"; $description .= "All automations and integrations are stopped.\n\n"; $description .= 'Please update your subscription to enable the server again: https://app.coolify.io/subscriptions'; return new SlackMessage( title: $title, description: $description, color: SlackMessage::errorColor() ); } } ================================================ FILE: app/Notifications/Server/ForceEnabled.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('server_force_enabled'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Server ({$this->server->name}) enabled again!"); $mail->view('emails.server-force-enabled', [ 'name' => $this->server->name, ]); return $mail; } public function toDiscord(): DiscordMessage { return new DiscordMessage( title: ':white_check_mark: Server enabled', description: "Server '{$this->server->name}' enabled again!", color: DiscordMessage::successColor(), ); } public function toTelegram(): array { return [ 'message' => "Coolify: Server ({$this->server->name}) enabled again!", ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Server enabled', level: 'success', message: "Server ({$this->server->name}) enabled again!", ); } public function toSlack(): SlackMessage { return new SlackMessage( title: 'Server enabled', description: "Server '{$this->server->name}' enabled again!", color: SlackMessage::successColor() ); } } ================================================ FILE: app/Notifications/Server/HetznerDeletionFailed.php ================================================ onQueue('high'); } public function via(object $notifiable): array { ray('hello'); ray($notifiable); return $notifiable->getEnabledChannels('hetzner_deletion_failed'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: [ACTION REQUIRED] Failed to delete Hetzner server #{$this->hetznerServerId}"); $mail->view('emails.hetzner-deletion-failed', [ 'hetznerServerId' => $this->hetznerServerId, 'errorMessage' => $this->errorMessage, ]); return $mail; } public function toDiscord(): DiscordMessage { return new DiscordMessage( title: ':cross_mark: Coolify: [ACTION REQUIRED] Failed to delete Hetzner server', description: "Failed to delete Hetzner server #{$this->hetznerServerId} from Hetzner Cloud.\n\n**Error:** {$this->errorMessage}\n\nThe server has been removed from Coolify, but may still exist in your Hetzner Cloud account. Please check your Hetzner Cloud console and manually delete the server if needed.", color: DiscordMessage::errorColor(), ); } public function toTelegram(): array { return [ 'message' => "Coolify: [ACTION REQUIRED] Failed to delete Hetzner server #{$this->hetznerServerId} from Hetzner Cloud.\n\nError: {$this->errorMessage}\n\nThe server has been removed from Coolify, but may still exist in your Hetzner Cloud account. Please check your Hetzner Cloud console and manually delete the server if needed.", ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Hetzner Server Deletion Failed', level: 'error', message: "[ACTION REQUIRED] Failed to delete Hetzner server #{$this->hetznerServerId}.\n\nError: {$this->errorMessage}\n\nThe server has been removed from Coolify, but may still exist in your Hetzner Cloud account. Please check and manually delete if needed.", ); } public function toSlack(): SlackMessage { return new SlackMessage( title: 'Coolify: [ACTION REQUIRED] Hetzner Server Deletion Failed', description: "Failed to delete Hetzner server #{$this->hetznerServerId} from Hetzner Cloud.\n\nError: {$this->errorMessage}\n\nThe server has been removed from Coolify, but may still exist in your Hetzner Cloud account. Please check your Hetzner Cloud console and manually delete the server if needed.", color: SlackMessage::errorColor() ); } } ================================================ FILE: app/Notifications/Server/HighDiskUsage.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('server_disk_usage'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Server ({$this->server->name}) high disk usage detected!"); $mail->view('emails.high-disk-usage', [ 'name' => $this->server->name, 'disk_usage' => $this->disk_usage, 'threshold' => $this->server_disk_usage_notification_threshold, ]); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':cross_mark: High disk usage detected', description: "Server '{$this->server->name}' high disk usage detected!", color: DiscordMessage::errorColor(), isCritical: true, ); $message->addField('Disk usage', "{$this->disk_usage}%", true); $message->addField('Threshold', "{$this->server_disk_usage_notification_threshold}%", true); $message->addField('What to do?', '[Link](https://coolify.io/docs/knowledge-base/server/automated-cleanup)', true); $message->addField('Change Settings', '[Threshold]('.base_url().'/server/'.$this->server->uuid.'#advanced) | [Notification]('.base_url().'/notifications/discord)'); return $message; } public function toTelegram(): array { return [ 'message' => "Coolify: Server '{$this->server->name}' high disk usage detected!\nDisk usage: {$this->disk_usage}%. Threshold: {$this->server_disk_usage_notification_threshold}%.\nPlease cleanup your disk to prevent data-loss.\nHere are some tips: https://coolify.io/docs/knowledge-base/server/automated-cleanup.", ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'High disk usage detected', level: 'warning', message: "Server '{$this->server->name}' high disk usage detected!

Disk usage: {$this->disk_usage}%.
Threshold: {$this->server_disk_usage_notification_threshold}%.
Please cleanup your disk to prevent data-loss.", buttons: [ 'Change settings' => base_url().'/server/'.$this->server->uuid.'#advanced', 'Tips for cleanup' => 'https://coolify.io/docs/knowledge-base/server/automated-cleanup', ], ); } public function toSlack(): SlackMessage { $description = "Server '{$this->server->name}' high disk usage detected!\n"; $description .= "Disk usage: {$this->disk_usage}%\n"; $description .= "Threshold: {$this->server_disk_usage_notification_threshold}%\n\n"; $description .= "Please cleanup your disk to prevent data-loss.\n"; $description .= "Tips for cleanup: https://coolify.io/docs/knowledge-base/server/automated-cleanup\n"; $description .= "Change settings:\n"; $description .= '- Threshold: '.base_url().'/server/'.$this->server->uuid."#advanced\n"; $description .= '- Notifications: '.base_url().'/notifications/slack'; return new SlackMessage( title: 'High disk usage detected', description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { return [ 'success' => false, 'message' => 'High disk usage detected', 'event' => 'high_disk_usage', 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, 'disk_usage' => $this->disk_usage, 'threshold' => $this->server_disk_usage_notification_threshold, 'url' => base_url().'/server/'.$this->server->uuid, ]; } } ================================================ FILE: app/Notifications/Server/Reachable.php ================================================ onQueue('high'); $this->isRateLimited = isEmailRateLimited( limiterKey: 'server-reachable:'.$this->server->id, ); } public function via(object $notifiable): array { if ($this->isRateLimited) { return []; } return $notifiable->getEnabledChannels('server_reachable'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Server ({$this->server->name}) revived."); $mail->view('emails.server-revived', [ 'name' => $this->server->name, ]); return $mail; } public function toDiscord(): DiscordMessage { return new DiscordMessage( title: ":white_check_mark: Server '{$this->server->name}' revived", description: 'All automations & integrations are turned on again!', color: DiscordMessage::successColor(), ); } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Server revived', message: "Server '{$this->server->name}' revived. All automations & integrations are turned on again!", level: 'success', ); } public function toTelegram(): array { return [ 'message' => "Coolify: Server '{$this->server->name}' revived. All automations & integrations are turned on again!", ]; } public function toSlack(): SlackMessage { return new SlackMessage( title: 'Server revived', description: "Server '{$this->server->name}' revived.\nAll automations & integrations are turned on again!", color: SlackMessage::successColor() ); } public function toWebhook(): array { $url = base_url().'/server/'.$this->server->uuid; return [ 'success' => true, 'message' => 'Server revived', 'event' => 'server_reachable', 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, 'url' => $url, ]; } } ================================================ FILE: app/Notifications/Server/ServerPatchCheck.php ================================================ onQueue('high'); $this->serverUrl = base_url().'/server/'.$this->server->uuid.'/security/patches'; } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('server_patch'); } public function toMail($notifiable = null): MailMessage { $mail = new MailMessage; // Handle error case if (isset($this->patchData['error'])) { $mail->subject("Coolify: [ERROR] Failed to check patches on {$this->server->name}"); $mail->view('emails.server-patches-error', [ 'name' => $this->server->name, 'error' => $this->patchData['error'], 'osId' => $this->patchData['osId'] ?? 'unknown', 'package_manager' => $this->patchData['package_manager'] ?? 'unknown', 'server_url' => $this->serverUrl, ]); return $mail; } $totalUpdates = $this->patchData['total_updates'] ?? 0; $mail->subject("Coolify: [ACTION REQUIRED] {$totalUpdates} server patches available on {$this->server->name}"); $mail->view('emails.server-patches', [ 'name' => $this->server->name, 'total_updates' => $totalUpdates, 'updates' => $this->patchData['updates'] ?? [], 'osId' => $this->patchData['osId'] ?? 'unknown', 'package_manager' => $this->patchData['package_manager'] ?? 'unknown', 'server_url' => $this->serverUrl, ]); return $mail; } public function toDiscord(): DiscordMessage { // Handle error case if (isset($this->patchData['error'])) { $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $error = $this->patchData['error']; $description = "**Failed to check for updates** on server {$this->server->name}\n\n"; $description .= "**Error Details:**\n"; $description .= '• OS: '.ucfirst($osId)."\n"; $description .= "• Package Manager: {$packageManager}\n"; $description .= "• Error: {$error}\n\n"; $description .= "[Manage Server]($this->serverUrl)"; return new DiscordMessage( title: ':x: Coolify: [ERROR] Failed to check patches on '.$this->server->name, description: $description, color: DiscordMessage::errorColor(), ); } $totalUpdates = $this->patchData['total_updates'] ?? 0; $updates = $this->patchData['updates'] ?? []; $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $description = "**{$totalUpdates} package updates** available for server {$this->server->name}\n\n"; $description .= "**Summary:**\n"; $description .= '• OS: '.ucfirst($osId)."\n"; $description .= "• Package Manager: {$packageManager}\n"; $description .= "• Total Updates: {$totalUpdates}\n\n"; // Show first few packages if (count($updates) > 0) { $description .= "**Sample Updates:**\n"; $sampleUpdates = array_slice($updates, 0, 5); foreach ($sampleUpdates as $update) { $description .= "• {$update['package']}: {$update['current_version']} → {$update['new_version']}\n"; } if (count($updates) > 5) { $description .= '• ... and '.(count($updates) - 5)." more packages\n"; } // Check for critical packages $criticalPackages = collect($updates)->filter(function ($update) { return str_contains(strtolower($update['package']), 'docker') || str_contains(strtolower($update['package']), 'kernel') || str_contains(strtolower($update['package']), 'openssh') || str_contains(strtolower($update['package']), 'ssl'); }); if ($criticalPackages->count() > 0) { $description .= "\n **Critical packages detected** ({$criticalPackages->count()} packages may require restarts)"; } $description .= "\n [Manage Server Patches]($this->serverUrl)"; } return new DiscordMessage( title: ':warning: Coolify: [ACTION REQUIRED] Server patches available on '.$this->server->name, description: $description, color: DiscordMessage::errorColor(), ); } public function toTelegram(): array { // Handle error case if (isset($this->patchData['error'])) { $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $error = $this->patchData['error']; $message = "❌ Coolify: [ERROR] Failed to check patches on {$this->server->name}!\n\n"; $message .= "📊 Error Details:\n"; $message .= '• OS: '.ucfirst($osId)."\n"; $message .= "• Package Manager: {$packageManager}\n"; $message .= "• Error: {$error}\n\n"; return [ 'message' => $message, 'buttons' => [ [ 'text' => 'Manage Server', 'url' => $this->serverUrl, ], ], ]; } $totalUpdates = $this->patchData['total_updates'] ?? 0; $updates = $this->patchData['updates'] ?? []; $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $message = "🔧 Coolify: [ACTION REQUIRED] {$totalUpdates} server patches available on {$this->server->name}!\n\n"; $message .= "📊 Summary:\n"; $message .= '• OS: '.ucfirst($osId)."\n"; $message .= "• Package Manager: {$packageManager}\n"; $message .= "• Total Updates: {$totalUpdates}\n\n"; if (count($updates) > 0) { $message .= "📦 Sample Updates:\n"; $sampleUpdates = array_slice($updates, 0, 5); foreach ($sampleUpdates as $update) { $message .= "• {$update['package']}: {$update['current_version']} → {$update['new_version']}\n"; } if (count($updates) > 5) { $message .= '• ... and '.(count($updates) - 5)." more packages\n"; } // Check for critical packages $criticalPackages = collect($updates)->filter(function ($update) { return str_contains(strtolower($update['package']), 'docker') || str_contains(strtolower($update['package']), 'kernel') || str_contains(strtolower($update['package']), 'openssh') || str_contains(strtolower($update['package']), 'ssl'); }); if ($criticalPackages->count() > 0) { $message .= "\n⚠️ Critical packages detected: {$criticalPackages->count()} packages may require restarts\n"; foreach ($criticalPackages->take(3) as $package) { $message .= "• {$package['package']}: {$package['current_version']} → {$package['new_version']}\n"; } if ($criticalPackages->count() > 3) { $message .= '• ... and '.($criticalPackages->count() - 3)." more critical packages\n"; } } } return [ 'message' => $message, 'buttons' => [ [ 'text' => 'Manage Server Patches', 'url' => $this->serverUrl, ], ], ]; } public function toPushover(): PushoverMessage { // Handle error case if (isset($this->patchData['error'])) { $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $error = $this->patchData['error']; $message = "[ERROR] Failed to check patches on {$this->server->name}!\n\n"; $message .= "Error Details:\n"; $message .= '• OS: '.ucfirst($osId)."\n"; $message .= "• Package Manager: {$packageManager}\n"; $message .= "• Error: {$error}\n\n"; return new PushoverMessage( title: 'Server patch check failed', level: 'error', message: $message, buttons: [ [ 'text' => 'Manage Server', 'url' => $this->serverUrl, ], ], ); } $totalUpdates = $this->patchData['total_updates'] ?? 0; $updates = $this->patchData['updates'] ?? []; $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $message = "[ACTION REQUIRED] {$totalUpdates} server patches available on {$this->server->name}!\n\n"; $message .= "Summary:\n"; $message .= '• OS: '.ucfirst($osId)."\n"; $message .= "• Package Manager: {$packageManager}\n"; $message .= "• Total Updates: {$totalUpdates}\n\n"; if (count($updates) > 0) { $message .= "Sample Updates:\n"; $sampleUpdates = array_slice($updates, 0, 3); foreach ($sampleUpdates as $update) { $message .= "• {$update['package']}: {$update['current_version']} → {$update['new_version']}\n"; } if (count($updates) > 3) { $message .= '• ... and '.(count($updates) - 3)." more packages\n"; } // Check for critical packages $criticalPackages = collect($updates)->filter(function ($update) { return str_contains(strtolower($update['package']), 'docker') || str_contains(strtolower($update['package']), 'kernel') || str_contains(strtolower($update['package']), 'openssh') || str_contains(strtolower($update['package']), 'ssl'); }); if ($criticalPackages->count() > 0) { $message .= "\nCritical packages detected: {$criticalPackages->count()} may require restarts"; } } return new PushoverMessage( title: 'Server patches available', level: 'error', message: $message, buttons: [ [ 'text' => 'Manage Server Patches', 'url' => $this->serverUrl, ], ], ); } public function toSlack(): SlackMessage { // Handle error case if (isset($this->patchData['error'])) { $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $error = $this->patchData['error']; $description = "Failed to check patches on '{$this->server->name}'!\n\n"; $description .= "*Error Details:*\n"; $description .= '• OS: '.ucfirst($osId)."\n"; $description .= "• Package Manager: {$packageManager}\n"; $description .= "• Error: `{$error}`\n\n"; $description .= "\n:link: <{$this->serverUrl}|Manage Server>"; return new SlackMessage( title: 'Coolify: [ERROR] Server patch check failed', description: $description, color: SlackMessage::errorColor() ); } $totalUpdates = $this->patchData['total_updates'] ?? 0; $updates = $this->patchData['updates'] ?? []; $osId = $this->patchData['osId'] ?? 'unknown'; $packageManager = $this->patchData['package_manager'] ?? 'unknown'; $description = "{$totalUpdates} server patches available on '{$this->server->name}'!\n\n"; $description .= "*Summary:*\n"; $description .= '• OS: '.ucfirst($osId)."\n"; $description .= "• Package Manager: {$packageManager}\n"; $description .= "• Total Updates: {$totalUpdates}\n\n"; if (count($updates) > 0) { $description .= "*Sample Updates:*\n"; $sampleUpdates = array_slice($updates, 0, 5); foreach ($sampleUpdates as $update) { $description .= "• `{$update['package']}`: {$update['current_version']} → {$update['new_version']}\n"; } if (count($updates) > 5) { $description .= '• ... and '.(count($updates) - 5)." more packages\n"; } // Check for critical packages $criticalPackages = collect($updates)->filter(function ($update) { return str_contains(strtolower($update['package']), 'docker') || str_contains(strtolower($update['package']), 'kernel') || str_contains(strtolower($update['package']), 'openssh') || str_contains(strtolower($update['package']), 'ssl'); }); if ($criticalPackages->count() > 0) { $description .= "\n:warning: *Critical packages detected:* {$criticalPackages->count()} packages may require restarts\n"; foreach ($criticalPackages->take(3) as $package) { $description .= "• `{$package['package']}`: {$package['current_version']} → {$package['new_version']}\n"; } if ($criticalPackages->count() > 3) { $description .= '• ... and '.($criticalPackages->count() - 3)." more critical packages\n"; } } } $description .= "\n:link: <{$this->serverUrl}|Manage Server Patches>"; return new SlackMessage( title: 'Coolify: [ACTION REQUIRED] Server patches available', description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { // Handle error case if (isset($this->patchData['error'])) { return [ 'success' => false, 'message' => 'Failed to check patches', 'event' => 'server_patch_check_error', 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, 'os_id' => $this->patchData['osId'] ?? 'unknown', 'package_manager' => $this->patchData['package_manager'] ?? 'unknown', 'error' => $this->patchData['error'], 'url' => $this->serverUrl, ]; } $totalUpdates = $this->patchData['total_updates'] ?? 0; $updates = $this->patchData['updates'] ?? []; // Check for critical packages $criticalPackages = collect($updates)->filter(function ($update) { return str_contains(strtolower($update['package']), 'docker') || str_contains(strtolower($update['package']), 'kernel') || str_contains(strtolower($update['package']), 'openssh') || str_contains(strtolower($update['package']), 'ssl'); }); return [ 'success' => false, 'message' => 'Server patches available', 'event' => 'server_patch_check', 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, 'total_updates' => $totalUpdates, 'os_id' => $this->patchData['osId'] ?? 'unknown', 'package_manager' => $this->patchData['package_manager'] ?? 'unknown', 'updates' => $updates, 'critical_packages_count' => $criticalPackages->count(), 'url' => $this->serverUrl, ]; } } ================================================ FILE: app/Notifications/Server/TraefikVersionOutdated.php ================================================ onQueue('high'); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('traefik_outdated'); } private function formatVersion(string $version): string { // Add 'v' prefix if not present for consistent display return str_starts_with($version, 'v') ? $version : "v{$version}"; } private function getUpgradeTarget(array $info): string { // For minor upgrades, use the upgrade_target field (e.g., "v3.6") if (($info['type'] ?? 'patch_update') === 'minor_upgrade' && isset($info['upgrade_target'])) { return $this->formatVersion($info['upgrade_target']); } // For patch updates, show the full version return $this->formatVersion($info['latest'] ?? 'unknown'); } public function toMail($notifiable = null): MailMessage { $mail = new MailMessage; $count = $this->servers->count(); // Transform servers to include URLs $serversWithUrls = $this->servers->map(function ($server) { return [ 'name' => $server->name, 'uuid' => $server->uuid, 'url' => base_url().'/server/'.$server->uuid.'/proxy', 'outdatedInfo' => $server->outdatedInfo ?? [], ]; }); $mail->subject("Coolify: Traefik proxy outdated on {$count} server(s)"); $mail->view('emails.traefik-version-outdated', [ 'servers' => $serversWithUrls, 'count' => $count, ]); return $mail; } public function toDiscord(): DiscordMessage { $count = $this->servers->count(); $hasUpgrades = $this->servers->contains(fn ($s) => ($s->outdatedInfo['type'] ?? 'patch_update') === 'minor_upgrade' || isset($s->outdatedInfo['newer_branch_target']) ); $description = "**{$count} server(s)** running outdated Traefik proxy. Update recommended for security and features.\n\n"; $description .= "**Affected servers:**\n"; foreach ($this->servers as $server) { $info = $server->outdatedInfo ?? []; $current = $this->formatVersion($info['current'] ?? 'unknown'); $latest = $this->formatVersion($info['latest'] ?? 'unknown'); $upgradeTarget = $this->getUpgradeTarget($info); $isPatch = ($info['type'] ?? 'patch_update') === 'patch_update'; $hasNewerBranch = isset($info['newer_branch_target']); if ($isPatch && $hasNewerBranch) { $newerBranchTarget = $info['newer_branch_target']; $newerBranchLatest = $this->formatVersion($info['newer_branch_latest']); $description .= "• {$server->name}: {$current} → {$upgradeTarget} (patch update available)\n"; $description .= " ↳ Also available: {$newerBranchTarget} (latest patch: {$newerBranchLatest}) - new minor version\n"; } elseif ($isPatch) { $description .= "• {$server->name}: {$current} → {$upgradeTarget} (patch update available)\n"; } else { $description .= "• {$server->name}: {$current} (latest patch: {$latest}) → {$upgradeTarget} (new minor version available)\n"; } } $description .= "\n⚠️ It is recommended to test before switching the production version."; if ($hasUpgrades) { $description .= "\n\n📖 **For minor version upgrades**: Read the Traefik changelog before upgrading to understand breaking changes and new features."; } return new DiscordMessage( title: ':warning: Coolify: Traefik proxy outdated', description: $description, color: DiscordMessage::warningColor(), ); } public function toTelegram(): array { $count = $this->servers->count(); $hasUpgrades = $this->servers->contains(fn ($s) => ($s->outdatedInfo['type'] ?? 'patch_update') === 'minor_upgrade' || isset($s->outdatedInfo['newer_branch_target']) ); $message = "⚠️ Coolify: Traefik proxy outdated on {$count} server(s)!\n\n"; $message .= "Update recommended for security and features.\n"; $message .= "📊 Affected servers:\n"; foreach ($this->servers as $server) { $info = $server->outdatedInfo ?? []; $current = $this->formatVersion($info['current'] ?? 'unknown'); $latest = $this->formatVersion($info['latest'] ?? 'unknown'); $upgradeTarget = $this->getUpgradeTarget($info); $isPatch = ($info['type'] ?? 'patch_update') === 'patch_update'; $hasNewerBranch = isset($info['newer_branch_target']); if ($isPatch && $hasNewerBranch) { $newerBranchTarget = $info['newer_branch_target']; $newerBranchLatest = $this->formatVersion($info['newer_branch_latest']); $message .= "• {$server->name}: {$current} → {$upgradeTarget} (patch update available)\n"; $message .= " ↳ Also available: {$newerBranchTarget} (latest patch: {$newerBranchLatest}) - new minor version\n"; } elseif ($isPatch) { $message .= "• {$server->name}: {$current} → {$upgradeTarget} (patch update available)\n"; } else { $message .= "• {$server->name}: {$current} (latest patch: {$latest}) → {$upgradeTarget} (new minor version available)\n"; } } $message .= "\n⚠️ It is recommended to test before switching the production version."; if ($hasUpgrades) { $message .= "\n\n📖 For minor version upgrades: Read the Traefik changelog before upgrading to understand breaking changes and new features."; } return [ 'message' => $message, 'buttons' => [], ]; } public function toPushover(): PushoverMessage { $count = $this->servers->count(); $hasUpgrades = $this->servers->contains(fn ($s) => ($s->outdatedInfo['type'] ?? 'patch_update') === 'minor_upgrade' || isset($s->outdatedInfo['newer_branch_target']) ); $message = "Traefik proxy outdated on {$count} server(s)!\n"; $message .= "Affected servers:\n"; foreach ($this->servers as $server) { $info = $server->outdatedInfo ?? []; $current = $this->formatVersion($info['current'] ?? 'unknown'); $latest = $this->formatVersion($info['latest'] ?? 'unknown'); $upgradeTarget = $this->getUpgradeTarget($info); $isPatch = ($info['type'] ?? 'patch_update') === 'patch_update'; $hasNewerBranch = isset($info['newer_branch_target']); if ($isPatch && $hasNewerBranch) { $newerBranchTarget = $info['newer_branch_target']; $newerBranchLatest = $this->formatVersion($info['newer_branch_latest']); $message .= "• {$server->name}: {$current} → {$upgradeTarget} (patch update available)\n"; $message .= " Also: {$newerBranchTarget} (latest: {$newerBranchLatest}) - new minor version\n"; } elseif ($isPatch) { $message .= "• {$server->name}: {$current} → {$upgradeTarget} (patch update available)\n"; } else { $message .= "• {$server->name}: {$current} (latest patch: {$latest}) → {$upgradeTarget} (new minor version available)\n"; } } $message .= "\nIt is recommended to test before switching the production version."; if ($hasUpgrades) { $message .= "\n\nFor minor version upgrades: Read the Traefik changelog before upgrading."; } return new PushoverMessage( title: 'Traefik proxy outdated', level: 'warning', message: $message, ); } public function toSlack(): SlackMessage { $count = $this->servers->count(); $hasUpgrades = $this->servers->contains(fn ($s) => ($s->outdatedInfo['type'] ?? 'patch_update') === 'minor_upgrade' || isset($s->outdatedInfo['newer_branch_target']) ); $description = "Traefik proxy outdated on {$count} server(s)!\n"; $description .= "*Affected servers:*\n"; foreach ($this->servers as $server) { $info = $server->outdatedInfo ?? []; $current = $this->formatVersion($info['current'] ?? 'unknown'); $latest = $this->formatVersion($info['latest'] ?? 'unknown'); $upgradeTarget = $this->getUpgradeTarget($info); $isPatch = ($info['type'] ?? 'patch_update') === 'patch_update'; $hasNewerBranch = isset($info['newer_branch_target']); if ($isPatch && $hasNewerBranch) { $newerBranchTarget = $info['newer_branch_target']; $newerBranchLatest = $this->formatVersion($info['newer_branch_latest']); $description .= "• `{$server->name}`: {$current} → {$upgradeTarget} (patch update available)\n"; $description .= " ↳ Also available: {$newerBranchTarget} (latest patch: {$newerBranchLatest}) - new minor version\n"; } elseif ($isPatch) { $description .= "• `{$server->name}`: {$current} → {$upgradeTarget} (patch update available)\n"; } else { $description .= "• `{$server->name}`: {$current} (latest patch: {$latest}) → {$upgradeTarget} (new minor version available)\n"; } } $description .= "\n:warning: It is recommended to test before switching the production version."; if ($hasUpgrades) { $description .= "\n\n:book: For minor version upgrades: Read the Traefik changelog before upgrading to understand breaking changes and new features."; } return new SlackMessage( title: 'Coolify: Traefik proxy outdated', description: $description, color: SlackMessage::warningColor() ); } public function toWebhook(): array { $servers = $this->servers->map(function ($server) { $info = $server->outdatedInfo ?? []; $webhookData = [ 'name' => $server->name, 'uuid' => $server->uuid, 'current_version' => $info['current'] ?? 'unknown', 'latest_version' => $info['latest'] ?? 'unknown', 'update_type' => $info['type'] ?? 'patch_update', ]; // For minor upgrades, include the upgrade target (e.g., "v3.6") if (($info['type'] ?? 'patch_update') === 'minor_upgrade' && isset($info['upgrade_target'])) { $webhookData['upgrade_target'] = $info['upgrade_target']; } // Include newer branch info if available if (isset($info['newer_branch_target'])) { $webhookData['newer_branch_target'] = $info['newer_branch_target']; $webhookData['newer_branch_latest'] = $info['newer_branch_latest']; } return $webhookData; })->toArray(); return [ 'success' => false, 'message' => 'Traefik proxy outdated', 'event' => 'traefik_version_outdated', 'affected_servers_count' => $this->servers->count(), 'servers' => $servers, ]; } } ================================================ FILE: app/Notifications/Server/Unreachable.php ================================================ onQueue('high'); $this->isRateLimited = isEmailRateLimited( limiterKey: 'server-unreachable:'.$this->server->id, ); } public function via(object $notifiable): array { if ($this->isRateLimited) { return []; } return $notifiable->getEnabledChannels('server_unreachable'); } public function toMail(): ?MailMessage { $mail = new MailMessage; $mail->subject("Coolify: Your server ({$this->server->name}) is unreachable."); $mail->view('emails.server-lost-connection', [ 'name' => $this->server->name, ]); return $mail; } public function toDiscord(): ?DiscordMessage { $message = new DiscordMessage( title: ':cross_mark: Server unreachable', description: "Your server '{$this->server->name}' is unreachable.", color: DiscordMessage::errorColor(), ); $message->addField('IMPORTANT', 'We automatically try to revive your server and turn on all automations & integrations.'); return $message; } public function toTelegram(): ?array { return [ 'message' => "Coolify: Your server '{$this->server->name}' is unreachable. All automations & integrations are turned off! Please check your server! IMPORTANT: We automatically try to revive your server and turn on all automations & integrations.", ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Server unreachable', level: 'error', message: "Your server '{$this->server->name}' is unreachable.
All automations & integrations are turned off!

IMPORTANT: We automatically try to revive your server and turn on all automations & integrations.", ); } public function toSlack(): SlackMessage { $description = "Your server '{$this->server->name}' is unreachable.\n"; $description .= "All automations & integrations are turned off!\n\n"; $description .= '*IMPORTANT:* We automatically try to revive your server and turn on all automations & integrations.'; return new SlackMessage( title: 'Server unreachable', description: $description, color: SlackMessage::errorColor() ); } public function toWebhook(): array { $url = base_url().'/server/'.$this->server->uuid; return [ 'success' => false, 'message' => 'Server unreachable', 'event' => 'server_unreachable', 'server_name' => $this->server->name, 'server_uuid' => $this->server->uuid, 'url' => $url, ]; } } ================================================ FILE: app/Notifications/SslExpirationNotification.php ================================================ onQueue('high'); $this->resources = collect($resources); // Collect URLs for each resource $this->resources->each(function ($resource) { if (data_get($resource, 'environment.project.uuid')) { $routeName = match ($resource->type()) { 'application' => 'project.application.configuration', 'database' => 'project.database.configuration', 'service' => 'project.service.configuration', default => null }; if ($routeName) { $route = route($routeName, [ 'project_uuid' => data_get($resource, 'environment.project.uuid'), 'environment_uuid' => data_get($resource, 'environment.uuid'), $resource->type().'_uuid' => data_get($resource, 'uuid'), ]); $settings = instanceSettings(); if (data_get($settings, 'fqdn')) { $url = Url::fromString($route); $url = $url->withPort(null); $fqdn = data_get($settings, 'fqdn'); $fqdn = str_replace(['http://', 'https://'], '', $fqdn); $url = $url->withHost($fqdn); $this->urls[$resource->name] = $url->__toString(); } else { $this->urls[$resource->name] = $route; } } } }); } public function via(object $notifiable): array { return $notifiable->getEnabledChannels('ssl_certificate_renewal'); } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject('Coolify: [Action Required] SSL Certificates Renewed - Manual Redeployment Needed'); $mail->view('emails.ssl-certificate-renewed', [ 'resources' => $this->resources, 'urls' => $this->urls, ]); return $mail; } public function toDiscord(): DiscordMessage { $resourceNames = $this->resources->pluck('name')->join(', '); $message = new DiscordMessage( title: '🔒 SSL Certificates Renewed', description: "SSL certificates have been renewed for: {$resourceNames}.\n\n**Action Required:** These resources need to be redeployed manually.", color: DiscordMessage::warningColor(), ); foreach ($this->urls as $name => $url) { $message->addField($name, "[View Resource]({$url})"); } return $message; } public function toTelegram(): array { $resourceNames = $this->resources->pluck('name')->join(', '); $message = "Coolify: SSL certificates have been renewed for: {$resourceNames}.\n\nAction Required: These resources need to be redeployed manually for the new SSL certificates to take effect."; $buttons = []; foreach ($this->urls as $name => $url) { $buttons[] = [ 'text' => "View {$name}", 'url' => $url, ]; } return [ 'message' => $message, 'buttons' => $buttons, ]; } public function toPushover(): PushoverMessage { $resourceNames = $this->resources->pluck('name')->join(', '); $message = "SSL certificates have been renewed for: {$resourceNames}

"; $message .= 'Action Required: These resources need to be redeployed manually for the new SSL certificates to take effect.'; $buttons = []; foreach ($this->urls as $name => $url) { $buttons[] = [ 'text' => "View {$name}", 'url' => $url, ]; } return new PushoverMessage( title: 'SSL Certificates Renewed', level: 'warning', message: $message, buttons: $buttons, ); } public function toSlack(): SlackMessage { $resourceNames = $this->resources->pluck('name')->join(', '); $description = "SSL certificates have been renewed for: {$resourceNames}\n\n"; $description .= '**Action Required:** These resources need to be redeployed manually for the new SSL certificates to take effect.'; if (! empty($this->urls)) { $description .= "\n\n**Resource URLs:**\n"; foreach ($this->urls as $name => $url) { $description .= "• {$name}: {$url}\n"; } } return new SlackMessage( title: '🔒 SSL Certificates Renewed', description: $description, color: SlackMessage::warningColor() ); } } ================================================ FILE: app/Notifications/Test.php ================================================ onQueue('high'); } public function via(object $notifiable): array { if ($this->channel) { $channels = match ($this->channel) { 'email' => [EmailChannel::class], 'discord' => [DiscordChannel::class], 'telegram' => [TelegramChannel::class], 'slack' => [SlackChannel::class], 'pushover' => [PushoverChannel::class], 'webhook' => [WebhookChannel::class], default => [], }; } else { $channels = $notifiable->getEnabledChannels('test'); } return $channels; } public function middleware(object $notifiable, string $channel) { return match ($channel) { EmailChannel::class => [new RateLimited('email')], default => [], }; } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject('Coolify: Test Email'); $mail->view('emails.test'); return $mail; } public function toDiscord(): DiscordMessage { $message = new DiscordMessage( title: ':white_check_mark: Test Success', description: 'This is a test Discord notification from Coolify. :cross_mark: :warning: :information_source:', color: DiscordMessage::successColor(), isCritical: $this->ping, ); $message->addField(name: 'Dashboard', value: '[Link]('.base_url().')', inline: true); return $message; } public function toTelegram(): array { return [ 'message' => 'Coolify: This is a test Telegram notification from Coolify.', 'buttons' => [ [ 'text' => 'Go to your dashboard', 'url' => isDev() ? 'https://staging-but-dev.coolify.io' : base_url(), ], ], ]; } public function toPushover(): PushoverMessage { return new PushoverMessage( title: 'Test Pushover Notification', message: 'This is a test Pushover notification from Coolify.', buttons: [ [ 'text' => 'Go to your dashboard', 'url' => base_url(), ], ], ); } public function toSlack(): SlackMessage { return new SlackMessage( title: 'Test Slack Notification', description: 'This is a test Slack notification from Coolify.' ); } public function toWebhook(): array { return [ 'success' => true, 'message' => 'This is a test webhook notification from Coolify.', 'event' => 'test', 'url' => base_url(), ]; } } ================================================ FILE: app/Notifications/TransactionalEmails/EmailChangeVerification.php ================================================ onQueue('high'); } public function toMail(): MailMessage { // Use the configured expiry minutes value $expiryMinutes = config('constants.email_change.verification_code_expiry_minutes', 10); $mail = new MailMessage; $mail->subject('Coolify: Verify Your New Email Address'); $mail->view('emails.email-change-verification', [ 'newEmail' => $this->newEmail, 'verificationCode' => $this->verificationCode, 'expiryMinutes' => $expiryMinutes, ]); return $mail; } } ================================================ FILE: app/Notifications/TransactionalEmails/InvitationLink.php ================================================ onQueue('high'); } public function toMail(): MailMessage { $invitation = TeamInvitation::whereEmail($this->user->email)->first(); $invitation_team = Team::find($invitation->team->id); $mail = new MailMessage; $mail->subject('Coolify: Invitation for '.$invitation_team->name); $mail->view('emails.invitation-link', [ 'team' => $invitation_team->name, 'email' => $this->user->email, 'invitation_link' => $invitation->link, ]); return $mail; } } ================================================ FILE: app/Notifications/TransactionalEmails/ResetPassword.php ================================================ settings = instanceSettings(); $this->token = $token; } public static function createUrlUsing($callback) { static::$createUrlCallback = $callback; } public static function toMailUsing($callback) { static::$toMailCallback = $callback; } public function via($notifiable) { $type = set_transanctional_email_settings(); if (blank($type)) { throw new Exception('No email settings found.'); } return ['mail']; } public function toMail($notifiable) { if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $this->token); } return $this->buildMailMessage($this->resetUrl($notifiable)); } protected function buildMailMessage($url) { $mail = new MailMessage; $mail->subject('Coolify: Reset Password'); $mail->view('emails.reset-password', ['url' => $url, 'count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]); return $mail; } protected function resetUrl($notifiable) { if (static::$createUrlCallback) { return call_user_func(static::$createUrlCallback, $notifiable, $this->token); } return url(route('password.reset', [ 'token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset(), ], false)); } } ================================================ FILE: app/Notifications/TransactionalEmails/Test.php ================================================ onQueue('high'); } public function via(): array { return [EmailChannel::class]; } public function toMail(): MailMessage { $mail = new MailMessage; $mail->subject('Coolify: Test Email'); $mail->view('emails.test'); return $mail; } } ================================================ FILE: app/Policies/ApiTokenPolicy.php ================================================ id === $token->tokenable_id && $token->tokenable_type === User::class; */ return true; } /** * Determine whether the user can create API tokens. */ public function create(User $user): bool { // Authorization temporarily disabled /* // All authenticated users can create their own API tokens return true; */ return true; } /** * Determine whether the user can update the API token. */ public function update(User $user, PersonalAccessToken $token): bool { // Authorization temporarily disabled /* // Users can only update their own tokens return $user->id === $token->tokenable_id && $token->tokenable_type === User::class; */ return true; } /** * Determine whether the user can delete the API token. */ public function delete(User $user, PersonalAccessToken $token): bool { // Authorization temporarily disabled /* // Users can only delete their own tokens return $user->id === $token->tokenable_id && $token->tokenable_type === User::class; */ return true; } /** * Determine whether the user can manage their own API tokens. */ public function manage(User $user): bool { // Authorization temporarily disabled /* // All authenticated users can manage their own API tokens return true; */ return true; } /** * Determine whether the user can use root permissions for API tokens. */ public function useRootPermissions(User $user): bool { // Only admins and owners can use root permissions return $user->isAdmin() || $user->isOwner(); } /** * Determine whether the user can use write permissions for API tokens. */ public function useWritePermissions(User $user): bool { // Authorization temporarily disabled /* // Only admins and owners can use write permissions return $user->isAdmin() || $user->isOwner(); */ return true; } } ================================================ FILE: app/Policies/ApplicationPolicy.php ================================================ isAdmin()) { return true; } return false; */ return true; } /** * Determine whether the user can update the model. */ public function update(User $user, Application $application): Response { // Authorization temporarily disabled /* if ($user->isAdmin()) { return Response::allow(); } return Response::deny('As a member, you cannot update this application.

You need at least admin or owner permissions.'); */ return Response::allow(); } /** * Determine whether the user can delete the model. */ public function delete(User $user, Application $application): bool { // Authorization temporarily disabled /* if ($user->isAdmin()) { return true; } return false; */ return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, Application $application): bool { // Authorization temporarily disabled /* return true; */ return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, Application $application): bool { // Authorization temporarily disabled /* return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id); */ return true; } /** * Determine whether the user can deploy the application. */ public function deploy(User $user, Application $application): bool { // Authorization temporarily disabled /* return $user->teams->contains('id', $application->team()->first()->id); */ return true; } /** * Determine whether the user can manage deployments. */ public function manageDeployments(User $user, Application $application): bool { // Authorization temporarily disabled /* return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id); */ return true; } /** * Determine whether the user can manage environment variables. */ public function manageEnvironment(User $user, Application $application): bool { // Authorization temporarily disabled /* return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id); */ return true; } /** * Determine whether the user can cleanup deployment queue. */ public function cleanupDeploymentQueue(User $user): bool { // Authorization temporarily disabled /* return $user->isAdmin(); */ return true; } } ================================================ FILE: app/Policies/ApplicationPreviewPolicy.php ================================================ teams->contains('id', $applicationPreview->application->team()->first()->id); return true; } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, ApplicationPreview $applicationPreview) { // if ($user->isAdmin()) { // return Response::allow(); // } // return Response::deny('As a member, you cannot update this preview.

You need at least admin or owner permissions.'); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, ApplicationPreview $applicationPreview): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, ApplicationPreview $applicationPreview): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, ApplicationPreview $applicationPreview): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id); return true; } /** * Determine whether the user can deploy the preview. */ public function deploy(User $user, ApplicationPreview $applicationPreview): bool { // return $user->teams->contains('id', $applicationPreview->application->team()->first()->id); return true; } /** * Determine whether the user can manage preview deployments. */ public function manageDeployments(User $user, ApplicationPreview $applicationPreview): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id); return true; } } ================================================ FILE: app/Policies/ApplicationSettingPolicy.php ================================================ teams->contains('id', $applicationSetting->application->team()->first()->id); return true; } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, ApplicationSetting $applicationSetting): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, ApplicationSetting $applicationSetting): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, ApplicationSetting $applicationSetting): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, ApplicationSetting $applicationSetting): bool { // return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id); return true; } } ================================================ FILE: app/Policies/CloudInitScriptPolicy.php ================================================ isAdmin(); } /** * Determine whether the user can view the model. */ public function view(User $user, CloudInitScript $cloudInitScript): bool { return $user->isAdmin(); } /** * Determine whether the user can create models. */ public function create(User $user): bool { return $user->isAdmin(); } /** * Determine whether the user can update the model. */ public function update(User $user, CloudInitScript $cloudInitScript): bool { return $user->isAdmin(); } /** * Determine whether the user can delete the model. */ public function delete(User $user, CloudInitScript $cloudInitScript): bool { return $user->isAdmin(); } /** * Determine whether the user can restore the model. */ public function restore(User $user, CloudInitScript $cloudInitScript): bool { return $user->isAdmin(); } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, CloudInitScript $cloudInitScript): bool { return $user->isAdmin(); } } ================================================ FILE: app/Policies/CloudProviderTokenPolicy.php ================================================ isAdmin(); } /** * Determine whether the user can view the model. */ public function view(User $user, CloudProviderToken $cloudProviderToken): bool { return $user->isAdmin(); } /** * Determine whether the user can create models. */ public function create(User $user): bool { return $user->isAdmin(); } /** * Determine whether the user can update the model. */ public function update(User $user, CloudProviderToken $cloudProviderToken): bool { return $user->isAdmin(); } /** * Determine whether the user can delete the model. */ public function delete(User $user, CloudProviderToken $cloudProviderToken): bool { return $user->isAdmin(); } /** * Determine whether the user can restore the model. */ public function restore(User $user, CloudProviderToken $cloudProviderToken): bool { return $user->isAdmin(); } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, CloudProviderToken $cloudProviderToken): bool { return $user->isAdmin(); } } ================================================ FILE: app/Policies/DatabasePolicy.php ================================================ teams->contains('id', $database->team()->first()->id); return true; } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, $database) { // if ($user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id)) { // return Response::allow(); // } // return Response::deny('As a member, you cannot update this database.

You need at least admin or owner permissions.'); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, $database): bool { // return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, $database): bool { // return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, $database): bool { // return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id); return true; } /** * Determine whether the user can start/stop the database. */ public function manage(User $user, $database): bool { // return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id); return true; } /** * Determine whether the user can manage database backups. */ public function manageBackups(User $user, $database): bool { // return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id); return true; } /** * Determine whether the user can manage environment variables. */ public function manageEnvironment(User $user, $database): bool { // return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id); return true; } } ================================================ FILE: app/Policies/EnvironmentPolicy.php ================================================ teams->contains('id', $environment->project->team_id); return true; } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, Environment $environment): bool { // return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, Environment $environment): bool { // return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, Environment $environment): bool { // return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, Environment $environment): bool { // return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id); return true; } } ================================================ FILE: app/Policies/EnvironmentVariablePolicy.php ================================================ teams->contains('id', $githubApp->team_id) || $githubApp->is_system_wide; return true; } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, GithubApp $githubApp): bool { if ($githubApp->is_system_wide) { // return $user->isAdmin(); return true; } // return $user->isAdmin() && $user->teams->contains('id', $githubApp->team_id); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, GithubApp $githubApp): bool { if ($githubApp->is_system_wide) { // return $user->isAdmin(); return true; } // return $user->isAdmin() && $user->teams->contains('id', $githubApp->team_id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, GithubApp $githubApp): bool { return false; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, GithubApp $githubApp): bool { return false; } } ================================================ FILE: app/Policies/InstanceSettingsPolicy.php ================================================ team) { return false; } // return $user->teams()->where('teams.id', $notificationSettings->team->id)->exists(); return true; } /** * Determine whether the user can update the notification settings. */ public function update(User $user, Model $notificationSettings): bool { // Check if the notification settings belong to the user's current team if (! $notificationSettings->team) { return false; } // Only owners and admins can update notification settings // return $user->isAdmin() || $user->isOwner(); return true; } /** * Determine whether the user can manage (create, update, delete) notification settings. */ public function manage(User $user, Model $notificationSettings): bool { // return $this->update($user, $notificationSettings); return true; } /** * Determine whether the user can send test notifications. */ public function sendTest(User $user, Model $notificationSettings): bool { // return $this->update($user, $notificationSettings); return true; } } ================================================ FILE: app/Policies/PrivateKeyPolicy.php ================================================ team_id === null) { return false; } // System resource (team_id=0): Only root team admins/owners can access if ($privateKey->team_id === 0) { return $user->canAccessSystemResources(); } // Regular resource: Check team membership return $user->teams->contains('id', $privateKey->team_id); } /** * Determine whether the user can create models. */ public function create(User $user): bool { // Only admins/owners can create private keys // Members should not be able to create SSH keys that could be used for deployments return $user->isAdmin(); } /** * Determine whether the user can update the model. */ public function update(User $user, PrivateKey $privateKey): bool { // Handle null team_id if ($privateKey->team_id === null) { return false; } // System resource (team_id=0): Only root team admins/owners can update if ($privateKey->team_id === 0) { return $user->canAccessSystemResources(); } // Regular resource: Must be admin/owner of the team return $user->isAdminOfTeam($privateKey->team_id) && $user->teams->contains('id', $privateKey->team_id); } /** * Determine whether the user can delete the model. */ public function delete(User $user, PrivateKey $privateKey): bool { // Handle null team_id if ($privateKey->team_id === null) { return false; } // System resource (team_id=0): Only root team admins/owners can delete if ($privateKey->team_id === 0) { return $user->canAccessSystemResources(); } // Regular resource: Must be admin/owner of the team return $user->isAdminOfTeam($privateKey->team_id) && $user->teams->contains('id', $privateKey->team_id); } /** * Determine whether the user can restore the model. */ public function restore(User $user, PrivateKey $privateKey): bool { return false; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, PrivateKey $privateKey): bool { return false; } } ================================================ FILE: app/Policies/ProjectPolicy.php ================================================ teams->contains('id', $project->team_id); return true; } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, Project $project): bool { // return $user->isAdmin() && $user->teams->contains('id', $project->team_id); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, Project $project): bool { // return $user->isAdmin() && $user->teams->contains('id', $project->team_id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, Project $project): bool { // return $user->isAdmin() && $user->teams->contains('id', $project->team_id); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, Project $project): bool { // return $user->isAdmin() && $user->teams->contains('id', $project->team_id); return true; } } ================================================ FILE: app/Policies/ResourceCreatePolicy.php ================================================ isAdmin(); return true; } /** * Determine whether the user can create a specific resource type. */ public function create(User $user, string $resourceClass): bool { if (! in_array($resourceClass, self::CREATABLE_RESOURCES)) { return false; } // return $user->isAdmin(); return true; } /** * Authorize creation of all supported resource types. */ public function authorizeAllResourceCreation(User $user): bool { return $this->createAny($user); } } ================================================ FILE: app/Policies/S3StoragePolicy.php ================================================ teams->contains('id', $storage->team_id); } /** * Determine whether the user can create models. */ public function create(User $user): bool { return $user->isAdmin(); } /** * Determine whether the user can update the model. */ public function update(User $user, S3Storage $storage): bool { // return $user->teams->contains('id', $storage->team_id) && $user->isAdmin(); return $user->teams->contains('id', $storage->team_id); } /** * Determine whether the user can delete the model. */ public function delete(User $user, S3Storage $storage): bool { // return $user->teams->contains('id', $storage->team_id) && $user->isAdmin(); return $user->teams->contains('id', $storage->team_id); } /** * Determine whether the user can restore the model. */ public function restore(User $user, S3Storage $storage): bool { return false; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, S3Storage $storage): bool { return false; } /** * Determine whether the user can validate the connection of the model. */ public function validateConnection(User $user, S3Storage $storage): bool { return $user->teams->contains('id', $storage->team_id); } } ================================================ FILE: app/Policies/ServerPolicy.php ================================================ teams->contains('id', $server->team_id); } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, Server $server): bool { // return $user->isAdmin() && $user->teams->contains('id', $server->team_id); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, Server $server): bool { // return $user->isAdmin() && $user->teams->contains('id', $server->team_id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, Server $server): bool { return false; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, Server $server): bool { return false; } /** * Determine whether the user can manage proxy (start/stop/restart). */ public function manageProxy(User $user, Server $server): bool { // return $user->isAdmin() && $user->teams->contains('id', $server->team_id); return true; } /** * Determine whether the user can manage sentinel (start/stop). */ public function manageSentinel(User $user, Server $server): bool { // return $user->isAdmin() && $user->teams->contains('id', $server->team_id); return true; } /** * Determine whether the user can manage CA certificates. */ public function manageCaCertificate(User $user, Server $server): bool { // return $user->isAdmin() && $user->teams->contains('id', $server->team_id); return true; } /** * Determine whether the user can view security views. */ public function viewSecurity(User $user, Server $server): bool { // return $user->isAdmin() && $user->teams->contains('id', $server->team_id); return true; } } ================================================ FILE: app/Policies/ServiceApplicationPolicy.php ================================================ service); } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, ServiceApplication $serviceApplication): bool { // return Gate::allows('update', $serviceApplication->service); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, ServiceApplication $serviceApplication): bool { // return Gate::allows('delete', $serviceApplication->service); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, ServiceApplication $serviceApplication): bool { // return Gate::allows('update', $serviceApplication->service); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, ServiceApplication $serviceApplication): bool { // return Gate::allows('delete', $serviceApplication->service); return true; } } ================================================ FILE: app/Policies/ServiceDatabasePolicy.php ================================================ isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, ServiceDatabase $serviceDatabase): bool { // return Gate::allows('update', $serviceDatabase->service); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, ServiceDatabase $serviceDatabase): bool { // return Gate::allows('delete', $serviceDatabase->service); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, ServiceDatabase $serviceDatabase): bool { // return Gate::allows('update', $serviceDatabase->service); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, ServiceDatabase $serviceDatabase): bool { // return Gate::allows('delete', $serviceDatabase->service); return true; } public function manageBackups(User $user, ServiceDatabase $serviceDatabase): bool { return true; } } ================================================ FILE: app/Policies/ServicePolicy.php ================================================ isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, Service $service): bool { $team = $service->team(); if (! $team) { return false; } // return $user->isAdmin() && $user->teams->contains('id', $team->id); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, Service $service): bool { // if ($user->isAdmin()) { // return true; // } // return false; return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, Service $service): bool { // return true; return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, Service $service): bool { // if ($user->isAdmin()) { // return true; // } // return false; return true; } public function stop(User $user, Service $service): bool { $team = $service->team(); if (! $team) { return false; } // return $user->teams->contains('id', $team->id); return true; } /** * Determine whether the user can manage environment variables. */ public function manageEnvironment(User $user, Service $service): bool { $team = $service->team(); if (! $team) { return false; } // return $user->isAdmin() && $user->teams->contains('id', $team->id); return true; } /** * Determine whether the user can deploy the service. */ public function deploy(User $user, Service $service): bool { $team = $service->team(); if (! $team) { return false; } // return $user->teams->contains('id', $team->id); return true; } public function accessTerminal(User $user, Service $service): bool { // return $user->isAdmin() || $user->teams->contains('id', $service->team()->id); return true; } } ================================================ FILE: app/Policies/SharedEnvironmentVariablePolicy.php ================================================ teams->contains('id', $sharedEnvironmentVariable->team_id); } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool { // return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id); return true; } /** * Determine whether the user can delete the model. */ public function delete(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool { // return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id); return true; } /** * Determine whether the user can restore the model. */ public function restore(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool { // return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id); return true; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool { // return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id); return true; } /** * Determine whether the user can manage environment variables. */ public function manageEnvironment(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool { // return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id); return true; } } ================================================ FILE: app/Policies/StandaloneDockerPolicy.php ================================================ teams->contains('id', $standaloneDocker->server->team_id); } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, StandaloneDocker $standaloneDocker): bool { return $user->teams->contains('id', $standaloneDocker->server->team_id); } /** * Determine whether the user can delete the model. */ public function delete(User $user, StandaloneDocker $standaloneDocker): bool { return $user->teams->contains('id', $standaloneDocker->server->team_id); } /** * Determine whether the user can restore the model. */ public function restore(User $user, StandaloneDocker $standaloneDocker): bool { return false; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, StandaloneDocker $standaloneDocker): bool { return false; } } ================================================ FILE: app/Policies/SwarmDockerPolicy.php ================================================ teams->contains('id', $swarmDocker->server->team_id); } /** * Determine whether the user can create models. */ public function create(User $user): bool { // return $user->isAdmin(); return true; } /** * Determine whether the user can update the model. */ public function update(User $user, SwarmDocker $swarmDocker): bool { return $user->teams->contains('id', $swarmDocker->server->team_id); } /** * Determine whether the user can delete the model. */ public function delete(User $user, SwarmDocker $swarmDocker): bool { return $user->teams->contains('id', $swarmDocker->server->team_id); } /** * Determine whether the user can restore the model. */ public function restore(User $user, SwarmDocker $swarmDocker): bool { return false; } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, SwarmDocker $swarmDocker): bool { return false; } } ================================================ FILE: app/Policies/TeamPolicy.php ================================================ teams->contains('id', $team->id); } /** * Determine whether the user can create models. */ public function create(User $user): bool { // All authenticated users can create teams return true; } /** * Determine whether the user can update the model. */ public function update(User $user, Team $team): bool { // Only admins and owners can update team settings if (! $user->teams->contains('id', $team->id)) { return false; } return $user->isAdmin() || $user->isOwner(); } /** * Determine whether the user can delete the model. */ public function delete(User $user, Team $team): bool { // Only admins and owners can delete teams if (! $user->teams->contains('id', $team->id)) { return false; } return $user->isAdmin() || $user->isOwner(); } /** * Determine whether the user can manage team members. */ public function manageMembers(User $user, Team $team): bool { // Only admins and owners can manage team members if (! $user->teams->contains('id', $team->id)) { return false; } return $user->isAdmin() || $user->isOwner(); } /** * Determine whether the user can view admin panel. */ public function viewAdmin(User $user, Team $team): bool { // Only admins and owners can view admin panel if (! $user->teams->contains('id', $team->id)) { return false; } return $user->isAdmin() || $user->isOwner(); } /** * Determine whether the user can manage invitations. */ public function manageInvitations(User $user, Team $team): bool { // Only admins and owners can manage invitations if (! $user->teams->contains('id', $team->id)) { return false; } return $user->isAdmin() || $user->isOwner(); } } ================================================ FILE: app/Providers/AppServiceProvider.php ================================================ app->register(TelescopeServiceProvider::class); } } public function boot(): void { $this->configureCommands(); $this->configureModels(); $this->configurePasswords(); $this->configureSanctumModel(); $this->configureGitHubHttp(); } private function configureCommands(): void { if (App::isProduction()) { DB::prohibitDestructiveCommands(); } } private function configureModels(): void { // Disabled because it's causing issues with the application // Model::shouldBeStrict(); } private function configurePasswords(): void { Password::defaults(function () { return App::isProduction() ? Password::min(8) ->mixedCase() ->letters() ->numbers() ->symbols() ->uncompromised() : Password::min(8)->letters(); }); } private function configureSanctumModel(): void { Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class); } private function configureGitHubHttp(): void { Http::macro('GitHub', function (string $api_url, ?string $github_access_token = null) { if ($github_access_token) { return Http::withHeaders([ 'X-GitHub-Api-Version' => '2022-11-28', 'Accept' => 'application/vnd.github.v3+json', 'Authorization' => "Bearer $github_access_token", ])->baseUrl($api_url); } else { return Http::withHeaders([ 'Accept' => 'application/vnd.github.v3+json', ])->baseUrl($api_url); } }); } } ================================================ FILE: app/Providers/AuthServiceProvider.php ================================================ */ protected $policies = [ \App\Models\Server::class => \App\Policies\ServerPolicy::class, \App\Models\PrivateKey::class => \App\Policies\PrivateKeyPolicy::class, \App\Models\StandaloneDocker::class => \App\Policies\StandaloneDockerPolicy::class, \App\Models\SwarmDocker::class => \App\Policies\SwarmDockerPolicy::class, \App\Models\Application::class => \App\Policies\ApplicationPolicy::class, \App\Models\ApplicationPreview::class => \App\Policies\ApplicationPreviewPolicy::class, \App\Models\ApplicationSetting::class => \App\Policies\ApplicationSettingPolicy::class, \App\Models\Service::class => \App\Policies\ServicePolicy::class, \App\Models\ServiceApplication::class => \App\Policies\ServiceApplicationPolicy::class, \App\Models\ServiceDatabase::class => \App\Policies\ServiceDatabasePolicy::class, \App\Models\Project::class => \App\Policies\ProjectPolicy::class, \App\Models\Environment::class => \App\Policies\EnvironmentPolicy::class, \App\Models\EnvironmentVariable::class => \App\Policies\EnvironmentVariablePolicy::class, \App\Models\SharedEnvironmentVariable::class => \App\Policies\SharedEnvironmentVariablePolicy::class, // Database policies - all use the shared DatabasePolicy \App\Models\StandalonePostgresql::class => \App\Policies\DatabasePolicy::class, \App\Models\StandaloneMysql::class => \App\Policies\DatabasePolicy::class, \App\Models\StandaloneMariadb::class => \App\Policies\DatabasePolicy::class, \App\Models\StandaloneMongodb::class => \App\Policies\DatabasePolicy::class, \App\Models\StandaloneRedis::class => \App\Policies\DatabasePolicy::class, \App\Models\StandaloneKeydb::class => \App\Policies\DatabasePolicy::class, \App\Models\StandaloneDragonfly::class => \App\Policies\DatabasePolicy::class, \App\Models\StandaloneClickhouse::class => \App\Policies\DatabasePolicy::class, // Notification policies - all use the shared NotificationPolicy \App\Models\EmailNotificationSettings::class => \App\Policies\NotificationPolicy::class, \App\Models\DiscordNotificationSettings::class => \App\Policies\NotificationPolicy::class, \App\Models\TelegramNotificationSettings::class => \App\Policies\NotificationPolicy::class, \App\Models\SlackNotificationSettings::class => \App\Policies\NotificationPolicy::class, \App\Models\PushoverNotificationSettings::class => \App\Policies\NotificationPolicy::class, \App\Models\WebhookNotificationSettings::class => \App\Policies\NotificationPolicy::class, // API Token policy \Laravel\Sanctum\PersonalAccessToken::class => \App\Policies\ApiTokenPolicy::class, // Instance settings policy \App\Models\InstanceSettings::class => \App\Policies\InstanceSettingsPolicy::class, // Team policy \App\Models\Team::class => \App\Policies\TeamPolicy::class, // Git source policies \App\Models\GithubApp::class => \App\Policies\GithubAppPolicy::class, ]; /** * Register any authentication / authorization services. */ public function boot(): void { // Register gates for resource creation policy Gate::define('createAnyResource', [ResourceCreatePolicy::class, 'createAny']); // Register gate for terminal access Gate::define('canAccessTerminal', function ($user) { return $user->isAdmin() || $user->isOwner(); }); } } ================================================ FILE: app/Providers/BroadcastServiceProvider.php ================================================ app->singleton(ConfigurationRepository::class, function ($app) { return new ConfigurationRepository($app['config']); }); } public function boot(): void { // } } ================================================ FILE: app/Providers/DuskServiceProvider.php ================================================ visit('/login') ->type('email', 'test@example.com') ->type('password', 'password') ->press('Login'); }); } } ================================================ FILE: app/Providers/EventServiceProvider.php ================================================ [ AzureExtendSocialite::class.'@handle', AuthentikExtendSocialite::class.'@handle', ClerkExtendSocialite::class.'@handle', DiscordExtendSocialite::class.'@handle', GoogleExtendSocialite::class.'@handle', InfomaniakExtendSocialite::class.'@handle', ZitadelExtendSocialite::class.'@handle', ], ]; public function boot(): void { // } public function shouldDiscoverEvents(): bool { return true; } } ================================================ FILE: app/Providers/FortifyServiceProvider.php ================================================ app->instance(RegisterResponse::class, new class implements RegisterResponse { public function toResponse($request) { // First user (root) will be redirected to /settings instead of / on registration. if ($request->user()->currentTeam->id === 0) { return redirect()->route('settings.index'); } return redirect(RouteServiceProvider::HOME); } }); } /** * Bootstrap any application services. */ public function boot(): void { Fortify::createUsersUsing(CreateNewUser::class); Fortify::registerView(function () { $isFirstUser = User::count() === 0; $settings = instanceSettings(); if (! $settings->is_registration_enabled) { return redirect()->route('login'); } return view('auth.register', [ 'isFirstUser' => $isFirstUser, ]); }); Fortify::loginView(function () { $settings = instanceSettings(); $enabled_oauth_providers = OauthSetting::where('enabled', true)->get(); $users = User::count(); if ($users == 0) { // If there are no users, redirect to registration return redirect()->route('register'); } return view('auth.login', [ 'is_registration_enabled' => $settings->is_registration_enabled, 'enabled_oauth_providers' => $enabled_oauth_providers, ]); }); Fortify::authenticateUsing(function (Request $request) { $email = strtolower($request->email); $user = User::where('email', $email)->with('teams')->first(); if ( $user && Hash::check($request->password, $user->password) ) { $user->updated_at = now(); $user->save(); // Check if user has a pending invitation they haven't accepted yet $invitation = \App\Models\TeamInvitation::whereEmail($email)->first(); if ($invitation && $invitation->isValid()) { // User is logging in for the first time after being invited // Attach them to the invited team if not already attached if (! $user->teams()->where('team_id', $invitation->team->id)->exists()) { $user->teams()->attach($invitation->team->id, ['role' => $invitation->role]); } $user->currentTeam = $invitation->team; $invitation->delete(); } else { // Normal login - use personal team $user->currentTeam = $user->teams->firstWhere('personal_team', true); if (! $user->currentTeam) { $user->currentTeam = $user->recreate_personal_team(); } } session(['currentTeam' => $user->currentTeam]); return $user; } }); Fortify::requestPasswordResetLinkView(function () { return view('auth.forgot-password'); }); Fortify::resetPasswordView(function ($request) { return view('auth.reset-password', ['request' => $request]); }); Fortify::resetUserPasswordsUsing(ResetUserPassword::class); Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class); Fortify::updateUserPasswordsUsing(UpdateUserPassword::class); Fortify::confirmPasswordView(function () { return view('auth.confirm-password'); }); Fortify::twoFactorChallengeView(function () { return view('auth.two-factor-challenge'); }); RateLimiter::for('force-password-reset', function (Request $request) { return Limit::perMinute(15)->by($request->user()->id); }); RateLimiter::for('forgot-password', function (Request $request) { // Use real client IP (not spoofable forwarded headers) $realIp = $request->server('REMOTE_ADDR') ?? $request->ip(); return Limit::perMinute(5)->by($realIp); }); RateLimiter::for('login', function (Request $request) { $email = (string) $request->email; // Use email + real client IP (not spoofable forwarded headers) // server('REMOTE_ADDR') gives the actual connecting IP before proxy headers $realIp = $request->server('REMOTE_ADDR') ?? $request->ip(); return Limit::perMinute(5)->by($email.'|'.$realIp); }); RateLimiter::for('two-factor', function (Request $request) { return Limit::perMinute(5)->by($request->session()->get('login.id')); }); } } ================================================ FILE: app/Providers/HorizonServiceProvider.php ================================================ app->singleton(JobRepository::class, CustomJobRepository::class); $this->app->singleton(CustomJobRepositoryInterface::class, CustomJobRepository::class); } /** * Bootstrap services. */ public function boot(): void { parent::boot(); Event::listen(function (JobReserved $event) { $payload = $event->payload->decoded; $jobName = $payload['displayName']; if ($jobName === 'App\Jobs\ApplicationDeploymentJob') { $tags = $payload['tags']; $id = $payload['id']; $deploymentQueueId = collect($tags)->first(function ($tag) { return str_contains($tag, 'App\Models\ApplicationDeploymentQueue'); }); if (blank($deploymentQueueId)) { return; } $deploymentQueueId = explode(':', $deploymentQueueId)[1]; $deploymentQueue = ApplicationDeploymentQueue::find($deploymentQueueId); $deploymentQueue->update([ 'horizon_job_id' => $id, ]); } }); } protected function gate(): void { Gate::define('viewHorizon', function ($user) { $root_user = User::find(0); return in_array($user->email, [ $root_user->email, ]); }); } } ================================================ FILE: app/Providers/RouteServiceProvider.php ================================================ configureRateLimiting(); $this->routes(function () { Route::middleware('api') ->prefix('api') ->group(base_path('routes/api.php')); Route::prefix('webhooks') ->group(base_path('routes/webhooks.php')); Route::middleware('web') ->group(base_path('routes/web.php')); }); } /** * Configure the rate limiters for the application. */ protected function configureRateLimiting(): void { RateLimiter::for('api', function (Request $request) { if ($request->path() === 'api/health') { return Limit::perMinute(1000)->by($request->user()?->id ?: $request->ip()); } return Limit::perMinute((int) config('api.rate_limit'))->by($request->user()?->id ?: $request->ip()); }); RateLimiter::for('5', function (Request $request) { return Limit::perMinute(5)->by($request->user()?->id ?: $request->ip()); }); } } ================================================ FILE: app/Providers/TelescopeServiceProvider.php ================================================ hideSensitiveRequestDetails(); $isLocal = $this->app->environment('local'); Telescope::filter(function (IncomingEntry $entry) use ($isLocal) { return $isLocal || $entry->isReportableException() || $entry->isFailedRequest() || $entry->isFailedJob() || $entry->isScheduledTask() || $entry->hasMonitoredTag(); }); } /** * Prevent sensitive request details from being logged by Telescope. */ protected function hideSensitiveRequestDetails(): void { if ($this->app->environment('local')) { return; } Telescope::hideRequestParameters(['_token']); Telescope::hideRequestHeaders([ 'cookie', 'x-csrf-token', 'x-xsrf-token', ]); } /** * Register the Telescope gate. * * This gate determines who can access Telescope in non-local environments. */ protected function gate(): void { Gate::define('viewTelescope', function ($user) { $root_user = User::find(0); return in_array($user->email, [ $root_user->email, ]); }); } } ================================================ FILE: app/Repositories/CustomJobRepository.php ================================================ all(); } public function getReservedJobs(): Collection { return $this->getJobsByStatus('reserved'); } public function getJobsByStatus(string $status): Collection { $jobs = new Collection; $this->getRecent()->each(function ($job) use ($jobs, $status) { if ($job->status === $status) { $jobs->push($job); } }); return $jobs; } public function countJobsByStatus(string $status): int { return $this->getJobsByStatus($status)->count(); } public function getQueues(): array { $queues = $this->connection()->keys('queue:*'); $queues = array_map(function ($queue) { return explode(':', $queue)[2]; }, $queues); return $queues; } } ================================================ FILE: app/Rules/DockerImageFormat.php ================================================ getMessage()); } return; } // If it doesn't start with #! or #cloud-config, try to parse as YAML // (some users might omit the #cloud-config header) try { Yaml::parse($script); } catch (ParseException $e) { $fail('The :attribute must be either a valid bash script (starting with #!) or valid cloud-config YAML. YAML parse error: '.$e->getMessage()); } } } ================================================ FILE: app/Rules/ValidGitBranch.php ================================================ ', '\n', '\r', '\0', '"', "'", '\\', '!', '*', '?', '[', ']', '~', '^', ':', ' ', '#', ]; foreach ($dangerousChars as $char) { if (str_contains($branch, $char)) { Log::warning('Git branch validation failed - dangerous character', [ 'branch' => $branch, 'character' => $char, 'ip' => request()->ip(), 'user_id' => auth()->id(), ]); $fail('The :attribute contains invalid characters.'); return; } } // Git branch name rules: // - Cannot contain: .., //, @{ // - Cannot start or end with: / or . // - Cannot be empty after trimming if (str_contains($branch, '..') || str_contains($branch, '//') || str_contains($branch, '@{')) { $fail('The :attribute contains invalid patterns.'); return; } if (str_starts_with($branch, '/') || str_ends_with($branch, '/') || str_starts_with($branch, '.') || str_ends_with($branch, '.')) { $fail('The :attribute cannot start or end with / or .'); return; } // Allow only safe characters for branch names // Letters, numbers, hyphens, underscores, forward slashes, and dots if (! preg_match('/^[a-zA-Z0-9\-_\/\.]+$/', $branch)) { $fail('The :attribute contains invalid characters. Only letters, numbers, hyphens, underscores, forward slashes, and dots are allowed.'); return; } // Additional Git-specific validations // Branch name cannot be 'HEAD' if ($branch === 'HEAD') { $fail('The :attribute cannot be HEAD.'); return; } // Check for consecutive dots (not allowed in Git) if (str_contains($branch, '..')) { $fail('The :attribute cannot contain consecutive dots.'); return; } // Check for .lock suffix (reserved by Git) if (str_ends_with($branch, '.lock')) { $fail('The :attribute cannot end with .lock.'); return; } } } ================================================ FILE: app/Rules/ValidGitRepositoryUrl.php ================================================ allowSSH = $allowSSH; $this->allowIP = $allowIP; } /** * Run the validation rule. */ public function validate(string $attribute, mixed $value, Closure $fail): void { if (empty($value)) { return; } // Check for dangerous shell metacharacters that could be used for command injection $dangerousChars = [ ';', '|', '&', '$', '`', '(', ')', '{', '}', '[', ']', '<', '>', '\n', '\r', '\0', '"', "'", '\\', '!', '?', '*', '^', '%', '=', '+', '#', // Comment character that could hide commands ]; foreach ($dangerousChars as $char) { if (str_contains($value, $char)) { Log::warning('Git repository URL validation failed - dangerous character', [ 'url' => $value, 'character' => $char, 'ip' => request()->ip(), 'user_id' => auth()->id(), ]); $fail('The :attribute contains invalid characters.'); return; } } // Check for command substitution patterns $dangerousPatterns = [ '/\$\(.*\)/', // Command substitution $(...) '/\${.*}/', // Variable expansion ${...} '/;;/', // Double semicolon '/&&/', // Command chaining '/\|\|/', // Command chaining '/>>/', // Redirect append '/< $value, 'pattern' => $pattern, 'ip' => request()->ip(), 'user_id' => auth()->id(), ]); $fail('The :attribute contains invalid patterns.'); return; } } // Validate based on URL type if (str_starts_with($value, 'git@')) { if (! $this->allowSSH) { $fail('SSH URLs are not allowed.'); return; } // Validate SSH URL format (git@host:user/repo.git) if (! preg_match('/^git@[a-zA-Z0-9\.\-]+:[a-zA-Z0-9\-_\/\.~]+$/', $value)) { $fail('The :attribute is not a valid SSH repository URL.'); return; } } elseif (str_starts_with($value, 'http://') || str_starts_with($value, 'https://')) { // Validate HTTP(S) URL if (! filter_var($value, FILTER_VALIDATE_URL)) { $fail('The :attribute is not a valid URL.'); return; } $parsed = parse_url($value); // Check for IP addresses if not allowed if (! $this->allowIP && filter_var($parsed['host'] ?? '', FILTER_VALIDATE_IP)) { Log::warning('Git repository URL contains IP address', [ 'url' => $value, 'ip' => request()->ip(), 'user_id' => auth()->id(), ]); $fail('The :attribute cannot use IP addresses.'); return; } // Check for localhost/internal addresses $host = strtolower($parsed['host'] ?? ''); $internalHosts = ['localhost', '127.0.0.1', '0.0.0.0', '::1']; if (in_array($host, $internalHosts) || str_ends_with($host, '.local')) { Log::warning('Git repository URL points to internal host', [ 'url' => $value, 'host' => $host, 'ip' => request()->ip(), 'user_id' => auth()->id(), ]); $fail('The :attribute cannot point to internal hosts.'); return; } // Ensure no query parameters or fragments if (! empty($parsed['query']) || ! empty($parsed['fragment'])) { $fail('The :attribute should not contain query parameters or fragments.'); return; } // Validate path contains only safe characters $path = $parsed['path'] ?? ''; if (! empty($path) && ! preg_match('/^[a-zA-Z0-9\-_\/\.@~]+$/', $path)) { $fail('The :attribute path contains invalid characters.'); return; } } elseif (str_starts_with($value, 'git://')) { // Validate git:// protocol URL (supports both git://host/path and git://host:port/path with tilde) if (! preg_match('/^git:\/\/[a-zA-Z0-9\.\-]+(:[0-9]+)?[:\/][a-zA-Z0-9\-_\/\.~]+$/', $value)) { $fail('The :attribute is not a valid git:// URL.'); return; } } else { $fail('The :attribute must start with https://, http://, git://, or git@.'); return; } } } ================================================ FILE: app/Rules/ValidHostname.php ================================================ 253) { $fail('The :attribute must not exceed 253 characters.'); return; } // Check for dangerous shell metacharacters $dangerousChars = [ ';', '|', '&', '$', '`', '(', ')', '{', '}', '<', '>', '\n', '\r', '\0', '"', "'", '\\', '!', '*', '?', '[', ']', '~', '^', ':', '#', '@', '%', '=', '+', ',', ' ', ]; foreach ($dangerousChars as $char) { if (str_contains($hostname, $char)) { try { $logData = [ 'hostname' => $hostname, 'character' => $char, ]; if (function_exists('request') && app()->has('request')) { $logData['ip'] = request()->ip(); } if (function_exists('auth') && app()->has('auth')) { $logData['user_id'] = auth()->id(); } Log::warning('Hostname validation failed - dangerous character', $logData); } catch (\Throwable $e) { // Ignore errors when facades are not available (e.g., in unit tests) } $fail('The :attribute contains invalid characters. Only lowercase letters (a-z), numbers (0-9), hyphens (-), and dots (.) are allowed.'); return; } } // Additional validation: hostname should not start or end with a dot if (str_starts_with($hostname, '.') || str_ends_with($hostname, '.')) { $fail('The :attribute cannot start or end with a dot.'); return; } // Check for consecutive dots if (str_contains($hostname, '..')) { $fail('The :attribute cannot contain consecutive dots.'); return; } // Split into labels (segments between dots) $labels = explode('.', $hostname); foreach ($labels as $label) { // Check label length (RFC 1123: max 63 characters per label) if (strlen($label) < 1 || strlen($label) > 63) { $fail('The :attribute contains an invalid label. Each segment must be 1-63 characters.'); return; } // Check if label starts or ends with hyphen if (str_starts_with($label, '-') || str_ends_with($label, '-')) { $fail('The :attribute contains an invalid label. Labels cannot start or end with a hyphen.'); return; } // Check if label contains only valid characters (lowercase letters, digits, hyphens) if (! preg_match('/^[a-z0-9-]+$/', $label)) { $fail('The :attribute contains invalid characters. Only lowercase letters (a-z), numbers (0-9), hyphens (-), and dots (.) are allowed.'); return; } // RFC 1123 allows labels to be all numeric (unlike RFC 952) // So we don't need to check for all-numeric labels } } } ================================================ FILE: app/Rules/ValidIpOrCidr.php ================================================ $maxMask) { $invalidEntries[] = $entry; } } else { // Check if it's a valid IP if (! filter_var($entry, FILTER_VALIDATE_IP)) { $invalidEntries[] = $entry; } } } if (! empty($invalidEntries)) { $fail('The following entries are not valid IP addresses or CIDR notations: '.implode(', ', $invalidEntries)); } } } ================================================ FILE: app/Rules/ValidProxyConfigFilename.php ================================================ 255) { $fail('The :attribute must not exceed 255 characters.'); return; } // Check for path separators (prevent path traversal) if (str_contains($filename, '/') || str_contains($filename, '\\')) { $fail('The :attribute cannot contain path separators.'); return; } // Check for hidden files (starting with dot) if (str_starts_with($filename, '.')) { $fail('The :attribute cannot start with a dot (hidden files not allowed).'); return; } // Check for valid characters only: alphanumeric, dashes, underscores, dots if (! preg_match('/^[a-zA-Z0-9._-]+$/', $filename)) { $fail('The :attribute may only contain letters, numbers, dashes, underscores, and dots.'); return; } // Check for reserved filenames (case-sensitive for coolify.yaml/yml, case-insensitive check not needed as Caddyfile is exact) if (in_array($filename, self::RESERVED_FILENAMES, true)) { $fail('The :attribute uses a reserved filename.'); return; } } } ================================================ FILE: app/Rules/ValidServerIp.php ================================================ validate($attribute, $trimmed, function () use (&$failed) { $failed = true; }); if ($failed) { $fail('The :attribute must be a valid IPv4 address, IPv6 address, or hostname.'); } } } ================================================ FILE: app/Services/ChangelogService.php ================================================ fetchChangelogData(); if (! $data || ! isset($data['entries'])) { return collect(); } return collect($data['entries']) ->filter(fn ($entry) => $this->validateEntryData($entry)) ->map(function ($entry) { $entry['published_at'] = Carbon::parse($entry['published_at']); $entry['content_html'] = $this->parseMarkdown($entry['content']); return (object) $entry; }) ->filter(fn ($entry) => $entry->published_at <= now()) ->sortBy('published_at') ->reverse() ->values(); } // Load entries from recent months for performance $availableMonths = $this->getAvailableMonths(); $monthsToLoad = $availableMonths->take($recentMonths); return $monthsToLoad ->flatMap(fn ($month) => $this->getEntriesForMonth($month)) ->sortBy('published_at') ->reverse() ->values(); } public function getAllEntries(): Collection { $availableMonths = $this->getAvailableMonths(); return $availableMonths ->flatMap(fn ($month) => $this->getEntriesForMonth($month)) ->sortBy('published_at') ->reverse() ->values(); } public function getEntriesForUser(User $user): Collection { $entries = $this->getEntries(); $readIdentifiers = UserChangelogRead::getReadIdentifiersForUser($user->id); return $entries->map(function ($entry) use ($readIdentifiers) { $entry->is_read = in_array($entry->tag_name, $readIdentifiers); return $entry; })->sortBy([ ['is_read', 'asc'], // unread first ['published_at', 'desc'], // then by date ])->values(); } public function getUnreadCountForUser(User $user): int { if (isDev()) { $entries = $this->getEntries(); $readIdentifiers = UserChangelogRead::getReadIdentifiersForUser($user->id); return $entries->reject(fn ($entry) => in_array($entry->tag_name, $readIdentifiers))->count(); } else { return Cache::remember( 'user_unread_changelog_count_'.$user->id, now()->addHour(), function () use ($user) { $entries = $this->getEntries(); $readIdentifiers = UserChangelogRead::getReadIdentifiersForUser($user->id); return $entries->reject(fn ($entry) => in_array($entry->tag_name, $readIdentifiers))->count(); } ); } } public function getAvailableMonths(): Collection { $pattern = base_path('changelogs/*.json'); $files = glob($pattern); if ($files === false) { return collect(); } return collect($files) ->map(fn ($file) => basename($file, '.json')) ->filter(fn ($name) => preg_match('/^\d{4}-\d{2}$/', $name)) ->sort() ->reverse() ->values(); } public function getEntriesForMonth(string $month): Collection { $path = base_path("changelogs/{$month}.json"); if (! file_exists($path)) { return collect(); } $content = file_get_contents($path); if ($content === false) { Log::error("Failed to read changelog file: {$month}.json"); return collect(); } $data = json_decode($content, true); if (json_last_error() !== JSON_ERROR_NONE) { Log::error("Invalid JSON in {$month}.json: ".json_last_error_msg()); return collect(); } if (! isset($data['entries']) || ! is_array($data['entries'])) { return collect(); } return collect($data['entries']) ->filter(fn ($entry) => $this->validateEntryData($entry)) ->map(function ($entry) { $entry['published_at'] = Carbon::parse($entry['published_at']); $entry['content_html'] = $this->parseMarkdown($entry['content']); return (object) $entry; }) ->filter(fn ($entry) => $entry->published_at <= now()) ->sortBy('published_at') ->reverse() ->values(); } private function fetchChangelogData(): ?array { // Legacy support for old changelog.json $path = base_path('changelog.json'); if (file_exists($path)) { $content = file_get_contents($path); if ($content === false) { Log::error('Failed to read changelog.json file'); return null; } $data = json_decode($content, true); if (json_last_error() !== JSON_ERROR_NONE) { Log::error('Invalid JSON in changelog.json: '.json_last_error_msg()); return null; } return $data; } // New monthly structure - combine all months $allEntries = []; foreach ($this->getAvailableMonths() as $month) { $monthEntries = $this->getEntriesForMonth($month); foreach ($monthEntries as $entry) { $allEntries[] = (array) $entry; } } return ['entries' => $allEntries]; } public function markAsReadForUser(string $version, User $user): void { UserChangelogRead::markAsRead($user->id, $version); Cache::forget('user_unread_changelog_count_'.$user->id); } public function markAllAsReadForUser(User $user): void { $entries = $this->getEntries(); foreach ($entries as $entry) { UserChangelogRead::markAsRead($user->id, $entry->tag_name); } Cache::forget('user_unread_changelog_count_'.$user->id); } private function validateEntryData(array $data): bool { $required = ['tag_name', 'title', 'content', 'published_at']; foreach ($required as $field) { if (! isset($data[$field]) || empty($data[$field])) { return false; } } return true; } public function clearAllReadStatus(): array { try { $count = UserChangelogRead::count(); UserChangelogRead::truncate(); // Clear all user caches $this->clearAllUserCaches(); return [ 'success' => true, 'message' => "Successfully cleared {$count} read status records", ]; } catch (\Exception $e) { Log::error('Failed to clear read status: '.$e->getMessage()); return [ 'success' => false, 'message' => 'Failed to clear read status: '.$e->getMessage(), ]; } } private function clearAllUserCaches(): void { $users = User::select('id')->get(); foreach ($users as $user) { Cache::forget('user_unread_changelog_count_'.$user->id); } } private function parseMarkdown(string $content): string { $renderer = app(MarkdownRenderer::class); $html = $renderer->toHtml($content); // Apply custom Tailwind CSS classes for dark mode compatibility $html = $this->applyCustomStyling($html); return $html; } private function applyCustomStyling(string $html): string { // Headers $html = preg_replace('/]*>/', '

', $html); $html = preg_replace('/]*>/', '

', $html); $html = preg_replace('/]*>/', '

', $html); // Paragraphs $html = preg_replace('/]*>/', '

', $html); // Lists $html = preg_replace('/]*>/', '

    ', $html); $html = preg_replace('/]*>/', '
      ', $html); $html = preg_replace('/]*>/', '
    1. ', $html); // Code blocks and inline code $html = preg_replace('/]*>/', '
      ', $html);
              $html = preg_replace('/]*>/', '', $html);
      
              // Links - Apply styling to existing markdown links
              $html = preg_replace('/]*)>/', '', $html);
      
              // Convert plain URLs to clickable links (that aren't already in  tags)
              $html = preg_replace('/(?)(?"]+)(?![^<]*<\/a>)/', '$1', $html);
      
              // Strong/bold text
              $html = preg_replace('/]*>/', '', $html);
      
              // Emphasis/italic text
              $html = preg_replace('/]*>/', '', $html);
      
              return $html;
          }
      }
      
      
      ================================================
      FILE: app/Services/ConfigurationGenerator.php
      ================================================
      generateConfig();
          }
      
          protected function generateConfig(): void
          {
              if ($this->resource instanceof Application) {
                  $this->config = [
                      'id' => $this->resource->id,
                      'name' => $this->resource->name,
                      'uuid' => $this->resource->uuid,
                      'description' => $this->resource->description,
                      'coolify_details' => [
                          'project_uuid' => $this->resource->project()->uuid,
                          'environment_uuid' => $this->resource->environment->uuid,
      
                          'destination_type' => $this->resource->destination_type,
                          'destination_id' => $this->resource->destination_id,
                          'source_type' => $this->resource->source_type,
                          'source_id' => $this->resource->source_id,
                          'private_key_id' => $this->resource->private_key_id,
                      ],
      
                      'post_deployment_command' => $this->resource->post_deployment_command,
                      'post_deployment_command_container' => $this->resource->post_deployment_command_container,
                      'pre_deployment_command' => $this->resource->pre_deployment_command,
                      'pre_deployment_command_container' => $this->resource->pre_deployment_command_container,
                      'build' => [
                          'type' => $this->resource->build_pack,
                          'static_image' => $this->resource->static_image,
                          'base_directory' => $this->resource->base_directory,
                          'publish_directory' => $this->resource->publish_directory,
                          'dockerfile' => $this->resource->dockerfile,
                          'dockerfile_location' => $this->resource->dockerfile_location,
                          'dockerfile_target_build' => $this->resource->dockerfile_target_build,
                          'custom_docker_run_options' => $this->resource->custom_docker_options,
                          'compose_parsing_version' => $this->resource->compose_parsing_version,
                          'docker_compose' => $this->resource->docker_compose,
                          'docker_compose_location' => $this->resource->docker_compose_location,
                          'docker_compose_raw' => $this->resource->docker_compose_raw,
                          'docker_compose_domains' => $this->resource->docker_compose_domains,
                          'docker_compose_custom_start_command' => $this->resource->docker_compose_custom_start_command,
                          'docker_compose_custom_build_command' => $this->resource->docker_compose_custom_build_command,
                          'install_command' => $this->resource->install_command,
                          'build_command' => $this->resource->build_command,
                          'start_command' => $this->resource->start_command,
                          'watch_paths' => $this->resource->watch_paths,
                      ],
                      'source' => [
                          'git_repository' => $this->resource->git_repository,
                          'git_branch' => $this->resource->git_branch,
                          'git_commit_sha' => $this->resource->git_commit_sha,
                          'repository_project_id' => $this->resource->repository_project_id,
                      ],
                      'docker_registry_image' => $this->getDockerRegistryImage(),
                      'domains' => [
                          'fqdn' => $this->resource->fqdn,
                          'ports_exposes' => $this->resource->ports_exposes,
                          'ports_mappings' => $this->resource->ports_mappings,
                          'redirect' => $this->resource->redirect,
                          'custom_nginx_configuration' => $this->resource->custom_nginx_configuration,
                      ],
                      'environment_variables' => [
                          'production' => $this->getEnvironmentVariables(),
                          'preview' => $this->getPreviewEnvironmentVariables(),
                      ],
                      'settings' => $this->getApplicationSettings(),
                      'preview' => $this->getPreview(),
                      'limits' => $this->resource->getLimits(),
                      'health_check' => [
                          'health_check_path' => $this->resource->health_check_path,
                          'health_check_port' => $this->resource->health_check_port,
                          'health_check_host' => $this->resource->health_check_host,
                          'health_check_method' => $this->resource->health_check_method,
                          'health_check_return_code' => $this->resource->health_check_return_code,
                          'health_check_scheme' => $this->resource->health_check_scheme,
                          'health_check_response_text' => $this->resource->health_check_response_text,
                          'health_check_interval' => $this->resource->health_check_interval,
                          'health_check_timeout' => $this->resource->health_check_timeout,
                          'health_check_retries' => $this->resource->health_check_retries,
                          'health_check_start_period' => $this->resource->health_check_start_period,
                          'health_check_enabled' => $this->resource->health_check_enabled,
                      ],
                      'webhooks_secrets' => [
                          'manual_webhook_secret_github' => $this->resource->manual_webhook_secret_github,
                          'manual_webhook_secret_gitlab' => $this->resource->manual_webhook_secret_gitlab,
                          'manual_webhook_secret_bitbucket' => $this->resource->manual_webhook_secret_bitbucket,
                          'manual_webhook_secret_gitea' => $this->resource->manual_webhook_secret_gitea,
                      ],
                      'swarm' => [
                          'swarm_replicas' => $this->resource->swarm_replicas,
                          'swarm_placement_constraints' => $this->resource->swarm_placement_constraints,
                      ],
                  ];
              }
          }
      
          protected function getPreview(): array
          {
              return [
                  'preview_url_template' => $this->resource->preview_url_template,
              ];
          }
      
          protected function getDockerRegistryImage(): array
          {
              return [
                  'image' => $this->resource->docker_registry_image_name,
                  'tag' => $this->resource->docker_registry_image_tag,
              ];
          }
      
          protected function getEnvironmentVariables(): array
          {
              $variables = collect([]);
              foreach ($this->resource->environment_variables as $env) {
                  $variables->push([
                      'key' => $env->key,
                      'value' => $env->value,
                      'is_preview' => $env->is_preview,
                      'is_multiline' => $env->is_multiline,
                  ]);
              }
      
              return $variables->toArray();
          }
      
          protected function getPreviewEnvironmentVariables(): array
          {
              $variables = collect([]);
              foreach ($this->resource->environment_variables_preview as $env) {
                  $variables->push([
                      'key' => $env->key,
                      'value' => $env->value,
                      'is_preview' => $env->is_preview,
                      'is_multiline' => $env->is_multiline,
                  ]);
              }
      
              return $variables->toArray();
          }
      
          protected function getApplicationSettings(): array
          {
              $removedKeys = ['id', 'application_id', 'created_at', 'updated_at'];
              $settings = $this->resource->settings->attributesToArray();
              $settings = collect($settings)->filter(function ($value, $key) use ($removedKeys) {
                  return ! in_array($key, $removedKeys);
              })->sortBy(function ($value, $key) {
                  return $key;
              })->toArray();
      
              return $settings;
          }
      
          public function saveJson(string $path): void
          {
              file_put_contents($path, json_encode($this->config, JSON_PRETTY_PRINT));
          }
      
          public function saveYaml(string $path): void
          {
              file_put_contents($path, Yaml::dump($this->config, 6, 2));
          }
      
          public function toArray(): array
          {
              return $this->config;
          }
      
          public function toJson(): string
          {
              return json_encode($this->config, JSON_PRETTY_PRINT);
          }
      
          public function toYaml(): string
          {
              return Yaml::dump($this->config, 6, 2);
          }
      }
      
      
      ================================================
      FILE: app/Services/ConfigurationRepository.php
      ================================================
      config = $config;
          }
      
          public function updateMailConfig($settings): void
          {
              if ($settings->resend_enabled) {
                  $this->config->set('mail.default', 'resend');
                  $this->config->set('mail.from.address', $settings->smtp_from_address ?? 'test@example.com');
                  $this->config->set('mail.from.name', $settings->smtp_from_name ?? 'Test');
                  $this->config->set('resend.api_key', $settings->resend_api_key);
      
                  return;
              }
      
              if ($settings->smtp_enabled) {
                  $encryption = match (strtolower($settings->smtp_encryption)) {
                      'starttls' => null,
                      'tls' => 'tls',
                      'none' => null,
                      default => null,
                  };
      
                  $this->config->set('mail.default', 'smtp');
                  $this->config->set('mail.from.address', $settings->smtp_from_address ?? 'test@example.com');
                  $this->config->set('mail.from.name', $settings->smtp_from_name ?? 'Test');
                  $this->config->set('mail.mailers.smtp', [
                      'transport' => 'smtp',
                      'host' => $settings->smtp_host,
                      'port' => $settings->smtp_port,
                      'encryption' => $encryption,
                      'username' => $settings->smtp_username,
                      'password' => $settings->smtp_password,
                      'timeout' => $settings->smtp_timeout,
                      'local_domain' => null,
                      'auto_tls' => $settings->smtp_encryption === 'none' ? '0' : '',
                  ]);
              }
          }
      
          public function disableSshMux(): void
          {
              $this->config->set('constants.ssh.mux_enabled', false);
          }
      }
      
      
      ================================================
      FILE: app/Services/ContainerStatusAggregator.php
      ================================================
       $maxRestartCount,
                  ]);
                  $maxRestartCount = 0;
              }
      
              if ($maxRestartCount > 1000) {
                  Log::warning('High maxRestartCount detected', [
                      'maxRestartCount' => $maxRestartCount,
                      'containers' => $containerStatuses->count(),
                  ]);
              }
      
              if ($containerStatuses->isEmpty()) {
                  return 'exited';
              }
      
              // Initialize state flags
              $hasRunning = false;
              $hasRestarting = false;
              $hasUnhealthy = false;
              $hasUnknown = false;
              $hasExited = false;
              $hasStarting = false;
              $hasPaused = false;
              $hasDead = false;
              $hasDegraded = false;
      
              // Parse each status string and set flags
              foreach ($containerStatuses as $status) {
                  if (str($status)->contains('degraded')) {
                      $hasDegraded = true;
                      if (str($status)->contains('unhealthy')) {
                          $hasUnhealthy = true;
                      }
                  } elseif (str($status)->contains('restarting')) {
                      $hasRestarting = true;
                  } elseif (str($status)->contains('running')) {
                      $hasRunning = true;
                      if (str($status)->contains('unhealthy')) {
                          $hasUnhealthy = true;
                      }
                      if (str($status)->contains('unknown')) {
                          $hasUnknown = true;
                      }
                  } elseif (str($status)->contains('exited')) {
                      $hasExited = true;
                  } elseif (str($status)->contains('created') || str($status)->contains('starting')) {
                      $hasStarting = true;
                  } elseif (str($status)->contains('paused')) {
                      $hasPaused = true;
                  } elseif (str($status)->contains('dead') || str($status)->contains('removing')) {
                      $hasDead = true;
                  }
              }
      
              // Priority-based status resolution
              return $this->resolveStatus(
                  $hasRunning,
                  $hasRestarting,
                  $hasUnhealthy,
                  $hasUnknown,
                  $hasExited,
                  $hasStarting,
                  $hasPaused,
                  $hasDead,
                  $hasDegraded,
                  $maxRestartCount,
                  $preserveRestarting
              );
          }
      
          /**
           * Aggregate container statuses from Docker container objects.
           *
           * @param  Collection  $containers  Collection of Docker container objects with State property
           * @param  int  $maxRestartCount  Maximum restart count across containers (for crash loop detection)
           * @param  bool  $preserveRestarting  If true, "restarting" containers return "restarting:unknown" instead of "degraded:unhealthy"
           * @return string Aggregated status in colon format (e.g., "running:healthy")
           */
          public function aggregateFromContainers(Collection $containers, int $maxRestartCount = 0, bool $preserveRestarting = false): string
          {
              // Validate maxRestartCount parameter
              if ($maxRestartCount < 0) {
                  Log::warning('Negative maxRestartCount corrected to 0', [
                      'original_value' => $maxRestartCount,
                  ]);
                  $maxRestartCount = 0;
              }
      
              if ($maxRestartCount > 1000) {
                  Log::warning('High maxRestartCount detected', [
                      'maxRestartCount' => $maxRestartCount,
                      'containers' => $containers->count(),
                  ]);
              }
      
              if ($containers->isEmpty()) {
                  return 'exited';
              }
      
              // Initialize state flags
              $hasRunning = false;
              $hasRestarting = false;
              $hasUnhealthy = false;
              $hasUnknown = false;
              $hasExited = false;
              $hasStarting = false;
              $hasPaused = false;
              $hasDead = false;
      
              // Parse each container object and set flags
              foreach ($containers as $container) {
                  $state = data_get($container, 'State.Status', 'exited');
                  $health = data_get($container, 'State.Health.Status');
      
                  if ($state === 'restarting') {
                      $hasRestarting = true;
                  } elseif ($state === 'running') {
                      $hasRunning = true;
                      if ($health === 'unhealthy') {
                          $hasUnhealthy = true;
                      } elseif (is_null($health) || $health === 'starting') {
                          $hasUnknown = true;
                      }
                  } elseif ($state === 'exited') {
                      $hasExited = true;
                  } elseif ($state === 'created' || $state === 'starting') {
                      $hasStarting = true;
                  } elseif ($state === 'paused') {
                      $hasPaused = true;
                  } elseif ($state === 'dead' || $state === 'removing') {
                      $hasDead = true;
                  }
              }
      
              // Priority-based status resolution
              return $this->resolveStatus(
                  $hasRunning,
                  $hasRestarting,
                  $hasUnhealthy,
                  $hasUnknown,
                  $hasExited,
                  $hasStarting,
                  $hasPaused,
                  $hasDead,
                  false, // $hasDegraded - not applicable for container objects, only for status strings
                  $maxRestartCount,
                  $preserveRestarting
              );
          }
      
          /**
           * Resolve the aggregated status based on state flags (priority-based state machine).
           *
           * @param  bool  $hasRunning  Has at least one running container
           * @param  bool  $hasRestarting  Has at least one restarting container
           * @param  bool  $hasUnhealthy  Has at least one unhealthy container
           * @param  bool  $hasUnknown  Has at least one container with unknown health
           * @param  bool  $hasExited  Has at least one exited container
           * @param  bool  $hasStarting  Has at least one starting/created container
           * @param  bool  $hasPaused  Has at least one paused container
           * @param  bool  $hasDead  Has at least one dead/removing container
           * @param  bool  $hasDegraded  Has at least one degraded container
           * @param  int  $maxRestartCount  Maximum restart count (for crash loop detection)
           * @param  bool  $preserveRestarting  If true, return "restarting:unknown" instead of "degraded:unhealthy" for restarting containers
           * @return string Status in colon format (e.g., "running:healthy")
           */
          private function resolveStatus(
              bool $hasRunning,
              bool $hasRestarting,
              bool $hasUnhealthy,
              bool $hasUnknown,
              bool $hasExited,
              bool $hasStarting,
              bool $hasPaused,
              bool $hasDead,
              bool $hasDegraded,
              int $maxRestartCount,
              bool $preserveRestarting = false
          ): string {
              // Priority 1: Degraded containers from sub-resources (highest priority)
              // If any service/application within a service stack is degraded, the entire stack is degraded
              if ($hasDegraded) {
                  return 'degraded:unhealthy';
              }
      
              // Priority 2: Restarting containers
              // When preserveRestarting is true (for individual sub-resources), keep as "restarting"
              // When false (for overall service status), mark as "degraded"
              if ($hasRestarting) {
                  return $preserveRestarting ? 'restarting:unknown' : 'degraded:unhealthy';
              }
      
              // Priority 3: Crash loop detection (exited with restart count > 0)
              if ($hasExited && $maxRestartCount > 0) {
                  return 'degraded:unhealthy';
              }
      
              // Priority 4: Mixed state (some running, some exited = degraded)
              if ($hasRunning && $hasExited) {
                  return 'degraded:unhealthy';
              }
      
              // Priority 5: Mixed state (some running, some starting = still starting)
              // If any component is still starting, the entire service stack is not fully ready
              if ($hasRunning && $hasStarting) {
                  return 'starting:unknown';
              }
      
              // Priority 6: Running containers (check health status)
              if ($hasRunning) {
                  if ($hasUnhealthy) {
                      return 'running:unhealthy';
                  } elseif ($hasUnknown) {
                      return 'running:unknown';
                  } else {
                      return 'running:healthy';
                  }
              }
      
              // Priority 7: Dead or removing containers
              if ($hasDead) {
                  return 'degraded:unhealthy';
              }
      
              // Priority 8: Paused containers
              if ($hasPaused) {
                  return 'paused:unknown';
              }
      
              // Priority 9: Starting/created containers
              if ($hasStarting) {
                  return 'starting:unknown';
              }
      
              // Priority 10: All containers exited (no restart count = truly stopped)
              return 'exited';
          }
      }
      
      
      ================================================
      FILE: app/Services/DockerImageParser.php
      ================================================
      tag = $matches[2];
                  $this->isImageHash = true;
              } else {
                  // Split by : to handle the tag, but be careful with registry ports
                  $lastColon = strrpos($imageString, ':');
                  $hasSlash = str_contains($imageString, '/');
      
                  // If the last colon appears after the last slash, it's a tag
                  // Otherwise it might be a port in the registry URL
                  if ($lastColon !== false && (! $hasSlash || $lastColon > strrpos($imageString, '/'))) {
                      $mainPart = substr($imageString, 0, $lastColon);
                      $this->tag = substr($imageString, $lastColon + 1);
      
                      // Check if the tag is a SHA256 hash
                      $this->isImageHash = $this->isSha256Hash($this->tag);
                  } else {
                      $mainPart = $imageString;
                      $this->tag = 'latest';
                      $this->isImageHash = false;
                  }
              }
      
              // Split the main part by / to handle registry and image name
              $pathParts = explode('/', $mainPart);
      
              // If we have more than one part and the first part contains a dot or colon
              // it's likely a registry URL
              if (count($pathParts) > 1 && (str_contains($pathParts[0], '.') || str_contains($pathParts[0], ':'))) {
                  $this->registryUrl = array_shift($pathParts);
                  $this->imageName = implode('/', $pathParts);
              } else {
                  $this->imageName = $mainPart;
              }
      
              return $this;
          }
      
          /**
           * Check if the given string is a SHA256 hash
           */
          private function isSha256Hash(string $hash): bool
          {
              // SHA256 hashes are 64 characters long and contain only hexadecimal characters
              return preg_match('/^[a-f0-9]{64}$/i', $hash) === 1;
          }
      
          /**
           * Check if the current tag is an image hash
           */
          public function isImageHash(): bool
          {
              return $this->isImageHash;
          }
      
          /**
           * Get the full image name with hash if present
           */
          public function getFullImageNameWithHash(): string
          {
              $imageName = $this->getFullImageNameWithoutTag();
      
              if ($this->isImageHash) {
                  return $imageName.'@sha256:'.$this->tag;
              }
      
              return $imageName.':'.$this->tag;
          }
      
          public function getFullImageNameWithoutTag(): string
          {
              if ($this->registryUrl) {
                  return $this->registryUrl.'/'.$this->imageName;
              }
      
              return $this->imageName;
          }
      
          public function getRegistryUrl(): string
          {
              return $this->registryUrl;
          }
      
          public function getImageName(): string
          {
              return $this->imageName;
          }
      
          public function getTag(): string
          {
              return $this->tag;
          }
      
          public function toString(): string
          {
              $parts = [];
              if ($this->registryUrl) {
                  $parts[] = $this->registryUrl;
              }
              $parts[] = $this->imageName;
      
              if ($this->isImageHash) {
                  return implode('/', $parts).'@sha256:'.$this->tag;
              }
      
              return implode('/', $parts).':'.$this->tag;
          }
      }
      
      
      ================================================
      FILE: app/Services/HetznerService.php
      ================================================
      token = $token;
          }
      
          private function request(string $method, string $endpoint, array $data = [])
          {
              $response = Http::withHeaders([
                  'Authorization' => 'Bearer '.$this->token,
              ])
                  ->timeout(30)
                  ->retry(3, function (int $attempt, \Exception $exception) {
                      // Handle rate limiting (429 Too Many Requests)
                      if ($exception instanceof \Illuminate\Http\Client\RequestException) {
                          $response = $exception->response;
      
                          if ($response && $response->status() === 429) {
                              // Get rate limit reset timestamp from headers
                              $resetTime = $response->header('RateLimit-Reset');
      
                              if ($resetTime) {
                                  // Calculate wait time until rate limit resets
                                  $waitSeconds = max(0, $resetTime - time());
      
                                  // Cap wait time at 60 seconds for safety
                                  return min($waitSeconds, 60) * 1000;
                              }
                          }
                      }
      
                      // Exponential backoff for other retriable errors: 100ms, 200ms, 400ms
                      return $attempt * 100;
                  })
                  ->{$method}($this->baseUrl.$endpoint, $data);
      
              if (! $response->successful()) {
                  if ($response->status() === 429) {
                      $retryAfter = $response->header('Retry-After');
                      if ($retryAfter === null) {
                          $resetTime = $response->header('RateLimit-Reset');
                          $retryAfter = $resetTime ? max(0, (int) $resetTime - time()) : null;
                      }
      
                      throw new RateLimitException(
                          'Rate limit exceeded. Please try again later.',
                          $retryAfter !== null ? (int) $retryAfter : null
                      );
                  }
      
                  throw new \Exception('Hetzner API error: '.$response->json('error.message', 'Unknown error'));
              }
      
              return $response->json();
          }
      
          private function requestPaginated(string $method, string $endpoint, string $resourceKey, array $data = []): array
          {
              $allResults = [];
              $page = 1;
      
              do {
                  $data['page'] = $page;
                  $data['per_page'] = 50;
      
                  $response = $this->request($method, $endpoint, $data);
      
                  if (isset($response[$resourceKey])) {
                      $allResults = array_merge($allResults, $response[$resourceKey]);
                  }
      
                  $nextPage = $response['meta']['pagination']['next_page'] ?? null;
                  $page = $nextPage;
              } while ($nextPage !== null);
      
              return $allResults;
          }
      
          public function getLocations(): array
          {
              return $this->requestPaginated('get', '/locations', 'locations');
          }
      
          public function getImages(): array
          {
              return $this->requestPaginated('get', '/images', 'images', [
                  'type' => 'system',
              ]);
          }
      
          public function getServerTypes(): array
          {
              $types = $this->requestPaginated('get', '/server_types', 'server_types');
      
              // Filter out entries where "deprecated" is explicitly true
              $filtered = array_filter($types, function ($type) {
                  return ! (isset($type['deprecated']) && $type['deprecated'] === true);
              });
      
              return array_values($filtered);
          }
      
          public function getSshKeys(): array
          {
              return $this->requestPaginated('get', '/ssh_keys', 'ssh_keys');
          }
      
          public function uploadSshKey(string $name, string $publicKey): array
          {
              $response = $this->request('post', '/ssh_keys', [
                  'name' => $name,
                  'public_key' => $publicKey,
              ]);
      
              return $response['ssh_key'] ?? [];
          }
      
          public function createServer(array $params): array
          {
              ray('Hetzner createServer request', [
                  'endpoint' => '/servers',
                  'params' => $params,
              ]);
      
              $response = $this->request('post', '/servers', $params);
      
              ray('Hetzner createServer response', [
                  'response' => $response,
              ]);
      
              return $response['server'] ?? [];
          }
      
          public function getServer(int $serverId): array
          {
              $response = $this->request('get', "/servers/{$serverId}");
      
              return $response['server'] ?? [];
          }
      
          public function powerOnServer(int $serverId): array
          {
              $response = $this->request('post', "/servers/{$serverId}/actions/poweron");
      
              return $response['action'] ?? [];
          }
      
          public function deleteServer(int $serverId): void
          {
              $this->request('delete', "/servers/{$serverId}");
          }
      
          public function getServers(): array
          {
              return $this->requestPaginated('get', '/servers', 'servers');
          }
      
          public function findServerByIp(string $ip): ?array
          {
              $servers = $this->getServers();
      
              foreach ($servers as $server) {
                  // Check IPv4
                  $ipv4 = data_get($server, 'public_net.ipv4.ip');
                  if ($ipv4 === $ip) {
                      return $server;
                  }
      
                  // Check IPv6 (Hetzner returns the full /64 block)
                  $ipv6 = data_get($server, 'public_net.ipv6.ip');
                  if ($ipv6 && str_starts_with($ip, rtrim($ipv6, '/'))) {
                      return $server;
                  }
              }
      
              return null;
          }
      }
      
      
      ================================================
      FILE: app/Services/ProxyDashboardCacheService.php
      ================================================
      id}:traefik:dashboard_available";
          }
      
          /**
           * Check if Traefik dashboard is available from configuration
           */
          public static function isTraefikDashboardAvailableFromConfiguration(Server $server, string $proxy_configuration): void
          {
              $cacheKey = static::getCacheKey($server);
              $dashboardAvailable = str($proxy_configuration)->contains('--api.dashboard=true') &&
              str($proxy_configuration)->contains('--api.insecure=true');
              Cache::forever($cacheKey, $dashboardAvailable);
          }
      
          /**
           * Check if Traefik dashboard is available (from cache or compute)
           */
          public static function isTraefikDashboardAvailableFromCache(Server $server): bool
          {
              $cacheKey = static::getCacheKey($server);
      
              return Cache::get($cacheKey) ?? false;
          }
      
          /**
           * Clear Traefik dashboard cache for a server
           */
          public static function clearCache(Server $server): void
          {
              Cache::forget(static::getCacheKey($server));
          }
      
          /**
           * Clear Traefik dashboard cache for multiple servers
           */
          public static function clearCacheForServers(array $serverIds): void
          {
              foreach ($serverIds as $serverId) {
                  $cacheKey = "server:{$serverId}:traefik:dashboard_available";
                  Cache::forget($cacheKey);
              }
          }
      }
      
      
      ================================================
      FILE: app/Services/SchedulerLogParser.php
      ================================================
      
           */
          public function getRecentSkips(int $limit = 100, ?int $teamId = null): Collection
          {
              $logFiles = $this->getLogFiles();
      
              $skips = collect();
      
              foreach ($logFiles as $logFile) {
                  $lines = $this->readLastLines($logFile, 2000);
      
                  foreach ($lines as $line) {
                      $entry = $this->parseLogLine($line);
                      if ($entry === null || ! isset($entry['context']['skip_reason'])) {
                          continue;
                      }
      
                      if ($teamId !== null && ($entry['context']['team_id'] ?? null) !== $teamId) {
                          continue;
                      }
      
                      $skips->push([
                          'timestamp' => $entry['timestamp'],
                          'type' => $entry['context']['type'] ?? 'unknown',
                          'reason' => $entry['context']['skip_reason'],
                          'team_id' => $entry['context']['team_id'] ?? null,
                          'context' => $entry['context'],
                      ]);
                  }
              }
      
              return $skips->sortByDesc('timestamp')->values()->take($limit);
          }
      
          /**
           * Get recent manager execution logs (start/complete events).
           *
           * @return Collection
           */
          public function getRecentRuns(int $limit = 60, ?int $teamId = null): Collection
          {
              $logFiles = $this->getLogFiles();
      
              $runs = collect();
      
              foreach ($logFiles as $logFile) {
                  $lines = $this->readLastLines($logFile, 2000);
      
                  foreach ($lines as $line) {
                      $entry = $this->parseLogLine($line);
                      if ($entry === null) {
                          continue;
                      }
      
                      if (! str_contains($entry['message'], 'ScheduledJobManager') || str_contains($entry['message'], 'started')) {
                          continue;
                      }
      
                      $runs->push([
                          'timestamp' => $entry['timestamp'],
                          'message' => $entry['message'],
                          'duration_ms' => $entry['context']['duration_ms'] ?? null,
                          'dispatched' => $entry['context']['dispatched'] ?? null,
                          'skipped' => $entry['context']['skipped'] ?? null,
                      ]);
                  }
              }
      
              return $runs->sortByDesc('timestamp')->values()->take($limit);
          }
      
          private function getLogFiles(): array
          {
              $logDir = storage_path('logs');
              if (! File::isDirectory($logDir)) {
                  return [];
              }
      
              $files = File::glob($logDir.'/scheduled-*.log');
      
              // Sort by modification time, newest first
              usort($files, fn ($a, $b) => filemtime($b) - filemtime($a));
      
              // Only check last 3 days of logs
              return array_slice($files, 0, 3);
          }
      
          /**
           * @return array{timestamp: string, level: string, message: string, context: array}|null
           */
          private function parseLogLine(string $line): ?array
          {
              // Laravel daily log format: [2024-01-15 10:30:00] production.INFO: Message {"key":"value"}
              if (! preg_match('/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \w+\.(\w+): (.+)$/', $line, $matches)) {
                  return null;
              }
      
              $timestamp = $matches[1];
              $level = $matches[2];
              $rest = $matches[3];
      
              // Extract JSON context if present
              $context = [];
              if (preg_match('/^(.+?)\s+(\{.+\})\s*$/', $rest, $contextMatches)) {
                  $message = $contextMatches[1];
                  $decoded = json_decode($contextMatches[2], true);
                  if (is_array($decoded)) {
                      $context = $decoded;
                  }
              } else {
                  $message = $rest;
              }
      
              return [
                  'timestamp' => $timestamp,
                  'level' => $level,
                  'message' => $message,
                  'context' => $context,
              ];
          }
      
          /**
           * Efficiently read the last N lines of a file.
           *
           * @return string[]
           */
          private function readLastLines(string $filePath, int $lines): array
          {
              if (! File::exists($filePath)) {
                  return [];
              }
      
              $fileSize = File::size($filePath);
              if ($fileSize === 0) {
                  return [];
              }
      
              // For small files, read the whole thing
              if ($fileSize < 1024 * 1024) {
                  $content = File::get($filePath);
      
                  return array_filter(explode("\n", $content), fn ($line) => $line !== '');
              }
      
              // For large files, read from the end
              $handle = fopen($filePath, 'r');
              if ($handle === false) {
                  return [];
              }
      
              $result = [];
              $chunkSize = 8192;
              $buffer = '';
              $position = $fileSize;
      
              while ($position > 0 && count($result) < $lines) {
                  $readSize = min($chunkSize, $position);
                  $position -= $readSize;
                  fseek($handle, $position);
                  $buffer = fread($handle, $readSize).$buffer;
      
                  $bufferLines = explode("\n", $buffer);
                  $buffer = array_shift($bufferLines);
      
                  $result = array_merge(array_filter($bufferLines, fn ($line) => $line !== ''), $result);
              }
      
              if ($buffer !== '' && count($result) < $lines) {
                  array_unshift($result, $buffer);
              }
      
              fclose($handle);
      
              return array_slice($result, -$lines);
          }
      }
      
      
      ================================================
      FILE: app/Support/ValidationPatterns.php
      ================================================
       "The name may only contain letters (including Unicode), numbers, spaces, and these characters: - _ . / @ &",
                  'name.min' => 'The name must be at least :min characters.',
                  'name.max' => 'The name may not be greater than :max characters.',
              ];
          }
      
          /**
           * Get validation messages for description fields
           */
          public static function descriptionMessages(): array
          {
              return [
                  'description.regex' => "The description may only contain letters (including Unicode), numbers, spaces, and common punctuation: - _ . , ! ? ( ) ' \" + = * / @ &",
                  'description.max' => 'The description may not be greater than :max characters.',
              ];
          }
      
          /**
           * Get validation rules for file path fields (dockerfile location, docker compose location)
           */
          public static function filePathRules(int $maxLength = 255): array
          {
              return ['nullable', 'string', 'max:'.$maxLength, 'regex:'.self::FILE_PATH_PATTERN];
          }
      
          /**
           * Get validation messages for file path fields
           */
          public static function filePathMessages(string $field = 'dockerfileLocation', string $label = 'Dockerfile'): array
          {
              return [
                  "{$field}.regex" => "The {$label} location must be a valid path starting with / and containing only alphanumeric characters, dots, hyphens, underscores, slashes, @, ~, and +.",
              ];
          }
      
          /**
           * Get combined validation messages for both name and description fields
           */
          public static function combinedMessages(): array
          {
              return array_merge(self::nameMessages(), self::descriptionMessages());
          }
      }
      
      
      ================================================
      FILE: app/Traits/AuthorizesResourceCreation.php
      ================================================
      authorize('createAnyResource');
          }
      }
      
      
      ================================================
      FILE: app/Traits/CalculatesExcludedStatus.php
      ================================================
      filter(function ($container) use ($excludedContainers) {
                  $labels = data_get($container, 'Config.Labels', []);
                  $serviceName = data_get($labels, 'com.docker.compose.service');
      
                  return $serviceName && $excludedContainers->contains($serviceName);
              });
      
              // Use ContainerStatusAggregator service for state machine logic
              $aggregator = new ContainerStatusAggregator;
              $status = $aggregator->aggregateFromContainers($excludedOnly);
      
              // Append :excluded suffix
              return $this->appendExcludedSuffix($status);
          }
      
          /**
           * Calculate status for containers when all containers are excluded (simplified version).
           *
           * This version works with status strings (e.g., "running:healthy") instead of full
           * container objects, suitable for Sentinel updates that don't have full container data.
           *
           * @param  Collection  $containerStatuses  Collection of status strings keyed by container name
           * @return string Status string with :excluded suffix
           */
          protected function calculateExcludedStatusFromStrings(Collection $containerStatuses): string
          {
              // Use ContainerStatusAggregator service for state machine logic
              $aggregator = new ContainerStatusAggregator;
              $status = $aggregator->aggregateFromStrings($containerStatuses);
      
              // Append :excluded suffix
              $finalStatus = $this->appendExcludedSuffix($status);
      
              return $finalStatus;
          }
      
          /**
           * Append :excluded suffix to a status string.
           *
           * Converts status formats like:
           * - "running:healthy" → "running:healthy:excluded"
           * - "degraded:unhealthy" → "degraded:excluded" (simplified)
           * - "paused:unknown" → "paused:excluded" (simplified)
           *
           * @param  string  $status  The base status string
           * @return string Status with :excluded suffix
           */
          private function appendExcludedSuffix(string $status): string
          {
              // For degraded states, simplify to just "degraded:excluded"
              if (str($status)->startsWith('degraded')) {
                  return 'degraded:excluded';
              }
      
              // For paused/starting/exited states, simplify to just "state:excluded"
              if (str($status)->startsWith('paused')) {
                  return 'paused:excluded';
              }
      
              if (str($status)->startsWith('starting')) {
                  return 'starting:excluded';
              }
      
              if (str($status)->startsWith('exited')) {
                  return 'exited';
              }
      
              // For running states, keep the health status: "running:healthy:excluded"
              return "$status:excluded";
          }
      
          /**
           * Get excluded containers from docker-compose YAML.
           *
           * Containers are excluded if:
           * - They have exclude_from_hc: true label
           * - They have restart: no policy
           *
           * @param  string|null  $dockerComposeRaw  The raw docker-compose YAML content
           * @return Collection Collection of excluded container names
           */
          protected function getExcludedContainersFromDockerCompose(?string $dockerComposeRaw): Collection
          {
              $excludedContainers = collect();
      
              if (! $dockerComposeRaw) {
                  return $excludedContainers;
              }
      
              try {
                  $dockerCompose = \Symfony\Component\Yaml\Yaml::parse($dockerComposeRaw);
      
                  // Validate structure
                  if (! is_array($dockerCompose)) {
                      Log::warning('Docker Compose YAML did not parse to array', [
                          'yaml_length' => strlen($dockerComposeRaw),
                          'parsed_type' => gettype($dockerCompose),
                      ]);
      
                      return $excludedContainers;
                  }
      
                  $services = data_get($dockerCompose, 'services', []);
      
                  if (! is_array($services)) {
                      Log::warning('Docker Compose services is not an array', [
                          'services_type' => gettype($services),
                      ]);
      
                      return $excludedContainers;
                  }
      
                  foreach ($services as $serviceName => $serviceConfig) {
                      $excludeFromHc = data_get($serviceConfig, 'exclude_from_hc', false);
                      $restartPolicy = data_get($serviceConfig, 'restart', 'always');
      
                      if ($excludeFromHc || $restartPolicy === 'no') {
                          $excludedContainers->push($serviceName);
                      }
                  }
              } catch (ParseException $e) {
                  // Specific YAML parsing errors
                  Log::warning('Failed to parse Docker Compose YAML for health check exclusions', [
                      'error' => $e->getMessage(),
                      'line' => $e->getParsedLine(),
                      'snippet' => $e->getSnippet(),
                  ]);
      
                  return $excludedContainers;
              } catch (\Exception $e) {
                  // Unexpected errors
                  Log::error('Unexpected error parsing Docker Compose YAML', [
                      'error' => $e->getMessage(),
                      'trace' => $e->getTraceAsString(),
                  ]);
      
                  return $excludedContainers;
              }
      
              return $excludedContainers;
          }
      }
      
      
      ================================================
      FILE: app/Traits/ClearsGlobalSearchCache.php
      ================================================
      hasSearchableChanges()) {
                          $teamId = $model->getTeamIdForCache();
                          if (filled($teamId)) {
                              GlobalSearch::clearTeamCache($teamId);
                          }
                      }
                  } catch (\Throwable $e) {
                      // Silently fail cache clearing - don't break the save operation
                      ray('Failed to clear global search cache on saving: '.$e->getMessage());
                  }
              });
      
              static::created(function ($model) {
                  try {
                      // Always clear cache when model is created
                      $teamId = $model->getTeamIdForCache();
                      if (filled($teamId)) {
                          GlobalSearch::clearTeamCache($teamId);
                      }
                  } catch (\Throwable $e) {
                      // Silently fail cache clearing - don't break the create operation
                      ray('Failed to clear global search cache on creation: '.$e->getMessage());
                  }
              });
      
              static::deleted(function ($model) {
                  try {
                      // Always clear cache when model is deleted
                      $teamId = $model->getTeamIdForCache();
                      if (filled($teamId)) {
                          GlobalSearch::clearTeamCache($teamId);
                      }
                  } catch (\Throwable $e) {
                      // Silently fail cache clearing - don't break the delete operation
                      ray('Failed to clear global search cache on deletion: '.$e->getMessage());
                  }
              });
          }
      
          private function hasSearchableChanges(): bool
          {
              try {
                  // Define searchable fields based on model type
                  $searchableFields = ['name', 'description'];
      
                  // Add model-specific searchable fields
                  if ($this instanceof \App\Models\Application) {
                      $searchableFields[] = 'fqdn';
                      $searchableFields[] = 'docker_compose_domains';
                  } elseif ($this instanceof \App\Models\Server) {
                      $searchableFields[] = 'ip';
                  } elseif ($this instanceof \App\Models\Service) {
                      // Services don't have direct fqdn, but name and description are covered
                  } elseif ($this instanceof \App\Models\Project || $this instanceof \App\Models\Environment) {
                      // Projects and environments only have name and description as searchable
                  }
                  // Database models only have name and description as searchable
      
                  // Check if any searchable field is dirty
                  foreach ($searchableFields as $field) {
                      // Check if attribute exists before checking if dirty
                      if (array_key_exists($field, $this->getAttributes()) && $this->isDirty($field)) {
                          return true;
                      }
                  }
      
                  return false;
              } catch (\Throwable $e) {
                  // If checking changes fails, assume changes exist to be safe
                  ray('Failed to check searchable changes: '.$e->getMessage());
      
                  return true;
              }
          }
      
          private function getTeamIdForCache()
          {
              try {
                  // For Project models (has direct team_id)
                  if ($this instanceof \App\Models\Project) {
                      return $this->team_id ?? null;
                  }
      
                  // For Environment models (get team_id through project)
                  if ($this instanceof \App\Models\Environment) {
                      return $this->project?->team_id;
                  }
      
                  // For database models, team is accessed through environment.project.team
                  if (method_exists($this, 'team')) {
                      if ($this instanceof \App\Models\Server) {
                          $team = $this->team;
                      } else {
                          $team = $this->team();
                      }
                      if (filled($team)) {
                          return is_object($team) ? $team->id : null;
                      }
                  }
      
                  // For models with direct team_id property
                  if (property_exists($this, 'team_id') || isset($this->team_id)) {
                      return $this->team_id ?? null;
                  }
      
                  return null;
              } catch (\Throwable $e) {
                  // If we can't determine team ID, return null
                  ray('Failed to get team ID for cache: '.$e->getMessage());
      
                  return null;
              }
          }
      }
      
      
      ================================================
      FILE: app/Traits/DeletesUserSessions.php
      ================================================
      where('user_id', $this->id)->delete();
          }
      
          /**
           * Boot the trait.
           */
          protected static function bootDeletesUserSessions()
          {
              static::updated(function ($user) {
                  // Check if password was changed
                  if ($user->wasChanged('password')) {
                      $user->deleteAllSessions();
                  }
              });
          }
      }
      
      
      ================================================
      FILE: app/Traits/EnvironmentVariableAnalyzer.php
      ================================================
       [
                      'problematic_values' => ['production', 'prod'],
                      'affects' => 'Node.js/npm/yarn/bun/pnpm',
                      'issue' => 'Skips devDependencies installation which are often required for building (webpack, typescript, etc.)',
                      'recommendation' => 'Uncheck "Available at Buildtime" or use "development" during build',
                  ],
                  'NPM_CONFIG_PRODUCTION' => [
                      'problematic_values' => ['true', '1', 'yes'],
                      'affects' => 'npm/pnpm',
                      'issue' => 'Forces npm to skip devDependencies',
                      'recommendation' => 'Remove from build-time variables or set to false',
                  ],
                  'YARN_PRODUCTION' => [
                      'problematic_values' => ['true', '1', 'yes'],
                      'affects' => 'Yarn/pnpm',
                      'issue' => 'Forces yarn to skip devDependencies',
                      'recommendation' => 'Remove from build-time variables or set to false',
                  ],
                  'COMPOSER_NO_DEV' => [
                      'problematic_values' => ['1', 'true', 'yes'],
                      'affects' => 'PHP/Composer',
                      'issue' => 'Skips require-dev packages which may include build tools',
                      'recommendation' => 'Set as "Runtime only" or remove from build-time variables',
                  ],
                  'MIX_ENV' => [
                      'problematic_values' => ['prod', 'production'],
                      'affects' => 'Elixir/Phoenix',
                      'issue' => 'Production mode may skip development dependencies needed for compilation',
                      'recommendation' => 'Use "dev" for build or set as "Runtime only"',
                  ],
                  'RAILS_ENV' => [
                      'problematic_values' => ['production'],
                      'affects' => 'Ruby on Rails',
                      'issue' => 'May affect asset precompilation and dependency handling',
                      'recommendation' => 'Consider using "development" for build phase',
                  ],
                  'RACK_ENV' => [
                      'problematic_values' => ['production'],
                      'affects' => 'Ruby/Rack',
                      'issue' => 'May affect dependency handling and build behavior',
                      'recommendation' => 'Consider using "development" for build phase',
                  ],
                  'BUNDLE_WITHOUT' => [
                      'problematic_values' => ['development', 'test', 'development:test'],
                      'affects' => 'Ruby/Bundler',
                      'issue' => 'Excludes gem groups that may contain build dependencies',
                      'recommendation' => 'Remove from build-time variables or adjust groups',
                  ],
                  'FLASK_ENV' => [
                      'problematic_values' => ['production'],
                      'affects' => 'Python/Flask',
                      'issue' => 'May affect debug mode and development tools availability',
                      'recommendation' => 'Usually safe, but consider "development" for complex builds',
                  ],
                  'DJANGO_SETTINGS_MODULE' => [
                      'problematic_values' => [], // Check if contains 'production' or 'prod'
                      'affects' => 'Python/Django',
                      'issue' => 'Production settings may disable debug tools needed during build',
                      'recommendation' => 'Use development settings for build phase',
                      'check_function' => 'checkDjangoSettings',
                  ],
                  'APP_ENV' => [
                      'problematic_values' => ['production', 'prod'],
                      'affects' => 'Laravel/Symfony',
                      'issue' => 'May affect dependency installation and build optimizations',
                      'recommendation' => 'Consider using "local" or "development" for build',
                  ],
                  'ASPNETCORE_ENVIRONMENT' => [
                      'problematic_values' => ['Production'],
                      'affects' => '.NET/ASP.NET Core',
                      'issue' => 'May affect build-time configurations and optimizations',
                      'recommendation' => 'Usually safe, but verify build requirements',
                  ],
                  'CI' => [
                      'problematic_values' => ['true', '1', 'yes'],
                      'affects' => 'Various tools',
                      'issue' => 'Changes behavior in many tools (disables interactivity, changes caching)',
                      'recommendation' => 'Usually beneficial for builds, but be aware of behavior changes',
                  ],
              ];
          }
      
          /**
           * Analyze an environment variable for potential build issues.
           * Always returns a warning if the key is in our list, regardless of value.
           */
          public static function analyzeBuildVariable(string $key, string $value): ?array
          {
              $problematicVars = self::getProblematicBuildVariables();
      
              // Direct key match
              if (isset($problematicVars[$key])) {
                  $config = $problematicVars[$key];
      
                  // Check if it has a custom check function
                  if (isset($config['check_function'])) {
                      $method = $config['check_function'];
                      if (method_exists(self::class, $method)) {
                          return self::{$method}($key, $value, $config);
                      }
                  }
      
                  // Always return warning for known problematic variables
                  return [
                      'variable' => $key,
                      'value' => $value,
                      'affects' => $config['affects'],
                      'issue' => $config['issue'],
                      'recommendation' => $config['recommendation'],
                  ];
              }
      
              return null;
          }
      
          /**
           * Analyze multiple environment variables for potential build issues.
           */
          public static function analyzeBuildVariables(array $variables): array
          {
              $warnings = [];
      
              foreach ($variables as $key => $value) {
                  $warning = self::analyzeBuildVariable($key, $value);
                  if ($warning) {
                      $warnings[] = $warning;
                  }
              }
      
              return $warnings;
          }
      
          /**
           * Custom check for Django settings module.
           */
          protected static function checkDjangoSettings(string $key, string $value, array $config): ?array
          {
              // Always return warning for DJANGO_SETTINGS_MODULE when it's set as build-time
              return [
                  'variable' => $key,
                  'value' => $value,
                  'affects' => $config['affects'],
                  'issue' => $config['issue'],
                  'recommendation' => $config['recommendation'],
              ];
          }
      
          /**
           * Generate a formatted warning message for deployment logs.
           */
          public static function formatBuildWarning(array $warning): array
          {
              $messages = [
                  "⚠️ Build-time environment variable warning: {$warning['variable']}={$warning['value']}",
                  "   Affects: {$warning['affects']}",
                  "   Issue: {$warning['issue']}",
                  "   Recommendation: {$warning['recommendation']}",
              ];
      
              return $messages;
          }
      
          /**
           * Check if a variable should show a warning in the UI.
           */
          public static function shouldShowBuildWarning(string $key): bool
          {
              return isset(self::getProblematicBuildVariables()[$key]);
          }
      
          /**
           * Get UI warning message for a specific variable.
           */
          public static function getUIWarningMessage(string $key): ?string
          {
              $problematicVars = self::getProblematicBuildVariables();
      
              if (! isset($problematicVars[$key])) {
                  return null;
              }
      
              $config = $problematicVars[$key];
              $problematicValuesStr = implode(', ', $config['problematic_values']);
      
              return "Setting {$key} to {$problematicValuesStr} as a build-time variable may cause issues. {$config['issue']} Consider: {$config['recommendation']}";
          }
      
          /**
           * Get problematic variables configuration for frontend use.
           */
          public static function getProblematicVariablesForFrontend(): array
          {
              $vars = self::getProblematicBuildVariables();
              $result = [];
      
              foreach ($vars as $key => $config) {
                  // Skip the check_function as it's PHP-specific
                  $result[$key] = [
                      'problematic_values' => $config['problematic_values'],
                      'affects' => $config['affects'],
                      'issue' => $config['issue'],
                      'recommendation' => $config['recommendation'],
                  ];
              }
      
              return $result;
          }
      }
      
      
      ================================================
      FILE: app/Traits/EnvironmentVariableProtection.php
      ================================================
      startsWith('SERVICE_FQDN_') || str($key)->startsWith('SERVICE_URL_') || str($key)->startsWith('SERVICE_NAME_');
          }
      
          /**
           * Check if an environment variable is used in Docker Compose
           *
           * @param  string  $key  The environment variable key to check
           * @param  string|null  $dockerCompose  The Docker Compose YAML content
           * @return array [bool $isUsed, string $reason] Whether the variable is used and the reason if it is
           */
          protected function isEnvironmentVariableUsedInDockerCompose(string $key, ?string $dockerCompose): array
          {
              if (empty($dockerCompose)) {
                  return [false, ''];
              }
      
              try {
                  $dockerComposeData = Yaml::parse($dockerCompose);
                  $dockerEnvVars = data_get($dockerComposeData, 'services.*.environment');
      
                  foreach ($dockerEnvVars as $serviceEnvs) {
                      if (! is_array($serviceEnvs)) {
                          continue;
                      }
      
                      // Check for direct variable usage
                      foreach ($serviceEnvs as $env => $value) {
                          if ($env === $key) {
                              return [true, "Environment variable '{$key}' is used directly in the Docker Compose file."];
                          }
                      }
      
                      // Check for variable references in values
                      foreach ($serviceEnvs as $env => $value) {
                          if (is_string($value) && str_contains($value, '$'.$key)) {
                              return [true, "Environment variable '{$key}' is referenced in the Docker Compose file."];
                          }
                      }
                  }
              } catch (\Exception $e) {
                  // If there's an error parsing the Docker Compose file, we'll assume it's not used
                  return [false, ''];
              }
      
              return [false, ''];
          }
      }
      
      
      ================================================
      FILE: app/Traits/ExecuteRemoteCommand.php
      ================================================
      application)) {
                  return $text;
              }
      
              $lockedVars = collect([]);
      
              if (isset($this->application->environment_variables)) {
                  $lockedVars = $lockedVars->merge(
                      $this->application->environment_variables
                          ->where('is_shown_once', true)
                          ->pluck('real_value', 'key')
                          ->filter()
                  );
              }
      
              if (isset($this->pull_request_id) && $this->pull_request_id !== 0 && isset($this->application->environment_variables_preview)) {
                  $lockedVars = $lockedVars->merge(
                      $this->application->environment_variables_preview
                          ->where('is_shown_once', true)
                          ->pluck('real_value', 'key')
                          ->filter()
                  );
              }
      
              foreach ($lockedVars as $key => $value) {
                  $escapedValue = preg_quote($value, '/');
                  $text = preg_replace(
                      '/'.$escapedValue.'/',
                      REDACTED,
                      $text
                  );
              }
      
              return $text;
          }
      
          public function execute_remote_command(...$commands)
          {
              static::$batch_counter++;
              if ($commands instanceof Collection) {
                  $commandsText = $commands;
              } else {
                  $commandsText = collect($commands);
              }
              if ($this->server instanceof Server === false) {
                  throw new \RuntimeException('Server is not set or is not an instance of Server model');
              }
              $commandsText->each(function ($single_command) {
                  $command = data_get($single_command, 'command') ?? $single_command[0] ?? null;
                  if ($command === null) {
                      throw new \RuntimeException('Command is not set');
                  }
                  $hidden = data_get($single_command, 'hidden', false);
                  $customType = data_get($single_command, 'type');
                  $ignore_errors = data_get($single_command, 'ignore_errors', false);
                  $append = data_get($single_command, 'append', true);
                  $this->save = data_get($single_command, 'save');
                  if ($this->server->isNonRoot()) {
                      if (str($command)->startsWith('docker exec')) {
                          $command = str($command)->replace('docker exec', 'sudo docker exec');
                      } else {
                          $command = parseLineForSudo($command, $this->server);
                      }
                  }
      
                  // Check for cancellation before executing commands
                  if (isset($this->application_deployment_queue)) {
                      $this->application_deployment_queue->refresh();
                      if ($this->application_deployment_queue->status === \App\Enums\ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
                          throw new \RuntimeException('Deployment cancelled by user', 69420);
                      }
                  }
      
                  $maxRetries = config('constants.ssh.max_retries');
                  $attempt = 0;
                  $lastError = null;
                  $commandExecuted = false;
      
                  while ($attempt < $maxRetries && ! $commandExecuted) {
                      try {
                          $this->executeCommandWithProcess($command, $hidden, $customType, $append, $ignore_errors);
                          $commandExecuted = true;
                      } catch (\RuntimeException $e) {
                          $lastError = $e;
                          $errorMessage = $e->getMessage();
                          // Only retry if it's an SSH connection error and we haven't exhausted retries
                          if ($this->isRetryableSshError($errorMessage) && $attempt < $maxRetries - 1) {
                              $attempt++;
                              $delay = $this->calculateRetryDelay($attempt - 1);
      
                              // Add log entry for the retry
                              if (isset($this->application_deployment_queue)) {
                                  $this->addRetryLogEntry($attempt, $maxRetries, $delay, $errorMessage);
      
                                  // Check for cancellation during retry wait
                                  $this->application_deployment_queue->refresh();
                                  if ($this->application_deployment_queue->status === \App\Enums\ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
                                      throw new \RuntimeException('Deployment cancelled by user during retry', 69420);
                                  }
                              }
      
                              sleep($delay);
                          } else {
                              // Not retryable or max retries reached
                              throw $e;
                          }
                      }
                  }
      
                  // If we exhausted all retries and still failed
                  if (! $commandExecuted && $lastError) {
                      // Now we can set the status to FAILED since all retries have been exhausted
                      // But only if the deployment hasn't already been marked as FINISHED
                      if (isset($this->application_deployment_queue)) {
                          // Avoid clobbering a deployment that may have just been marked FINISHED
                          $this->application_deployment_queue->newQuery()
                              ->where('id', $this->application_deployment_queue->id)
                              ->where('status', '!=', ApplicationDeploymentStatus::FINISHED->value)
                              ->update([
                                  'status' => ApplicationDeploymentStatus::FAILED->value,
                              ]);
                      }
                      throw $lastError;
                  }
              });
          }
      
          /**
           * Execute the actual command with process handling
           */
          private function executeCommandWithProcess($command, $hidden, $customType, $append, $ignore_errors)
          {
              $remote_command = SshMultiplexingHelper::generateSshCommand($this->server, $command);
              $process = Process::timeout(config('constants.ssh.command_timeout'))->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden, $customType, $append) {
                  $output = str($output)->trim();
                  if ($output->startsWith('╔')) {
                      $output = "\n".$output;
                  }
      
                  // Sanitize output to ensure valid UTF-8 encoding before JSON encoding
                  $sanitized_output = sanitize_utf8_text($output);
      
                  $new_log_entry = [
                      'command' => $this->redact_sensitive_info($command),
                      'output' => $this->redact_sensitive_info($sanitized_output),
                      'type' => $customType ?? $type === 'err' ? 'stderr' : 'stdout',
                      'timestamp' => Carbon::now('UTC'),
                      'hidden' => $hidden,
                      'batch' => static::$batch_counter,
                  ];
                  if (! $this->application_deployment_queue->logs) {
                      $new_log_entry['order'] = 1;
                  } else {
                      try {
                          $previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);
                      } catch (\JsonException $e) {
                          // If existing logs are corrupted, start fresh
                          $previous_logs = [];
                          $new_log_entry['order'] = 1;
                      }
                      if (is_array($previous_logs)) {
                          $new_log_entry['order'] = count($previous_logs) + 1;
                      } else {
                          $previous_logs = [];
                          $new_log_entry['order'] = 1;
                      }
                  }
                  $previous_logs[] = $new_log_entry;
      
                  try {
                      $this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_THROW_ON_ERROR);
                  } catch (\JsonException $e) {
                      // If JSON encoding still fails, use fallback with invalid sequences replacement
                      $this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_INVALID_UTF8_SUBSTITUTE);
                  }
      
                  $this->application_deployment_queue->save();
      
                  if ($this->save) {
                      if (data_get($this->saved_outputs, $this->save, null) === null) {
                          $this->saved_outputs->put($this->save, str());
                      }
                      if ($append) {
                          $current_value = $this->saved_outputs->get($this->save);
                          $this->saved_outputs->put($this->save, str($current_value.str($sanitized_output)->trim()));
                      } else {
                          $this->saved_outputs->put($this->save, str($sanitized_output)->trim());
                      }
                  }
              });
              $this->application_deployment_queue->update([
                  'current_process_id' => $process->id(),
              ]);
      
              $process_result = $process->wait();
              if ($process_result->exitCode() !== 0) {
                  if (! $ignore_errors) {
                      // Check if deployment was cancelled while command was running
                      if (isset($this->application_deployment_queue)) {
                          $this->application_deployment_queue->refresh();
                          if ($this->application_deployment_queue->status === \App\Enums\ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
                              throw new \RuntimeException('Deployment cancelled by user', 69420);
                          }
                      }
      
                      // Don't immediately set to FAILED - let the retry logic handle it
                      // This prevents premature status changes during retryable SSH errors
                      $error = $process_result->errorOutput();
                      if (empty($error)) {
                          $error = $process_result->output() ?: 'Command failed with no error output';
                      }
                      $redactedCommand = $this->redact_sensitive_info($command);
                      throw new \RuntimeException("Command execution failed (exit code {$process_result->exitCode()}): {$redactedCommand}\nError: {$error}");
                  }
              }
          }
      
          /**
           * Add a log entry for SSH retry attempts
           */
          private function addRetryLogEntry(int $attempt, int $maxRetries, int $delay, string $errorMessage)
          {
              $retryMessage = "SSH connection failed. Retrying... (Attempt {$attempt}/{$maxRetries}, waiting {$delay}s)\nError: {$errorMessage}";
      
              $new_log_entry = [
                  'output' => $this->redact_sensitive_info($retryMessage),
                  'type' => 'stdout',
                  'timestamp' => Carbon::now('UTC'),
                  'hidden' => false,
                  'batch' => static::$batch_counter,
              ];
      
              if (! $this->application_deployment_queue->logs) {
                  $new_log_entry['order'] = 1;
                  $previous_logs = [];
              } else {
                  try {
                      $previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);
                  } catch (\JsonException $e) {
                      $previous_logs = [];
                      $new_log_entry['order'] = 1;
                  }
                  if (is_array($previous_logs)) {
                      $new_log_entry['order'] = count($previous_logs) + 1;
                  } else {
                      $previous_logs = [];
                      $new_log_entry['order'] = 1;
                  }
              }
      
              $previous_logs[] = $new_log_entry;
      
              try {
                  $this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_THROW_ON_ERROR);
              } catch (\JsonException $e) {
                  $this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_INVALID_UTF8_SUBSTITUTE);
              }
      
              $this->application_deployment_queue->save();
          }
      }
      
      
      ================================================
      FILE: app/Traits/HasConfiguration.php
      ================================================
      uuid}";
              if (! is_dir($configDir)) {
                  mkdir($configDir, 0755, true);
              }
      
              $generator->saveJson($configDir.'/coolify.json');
              $generator->saveYaml($configDir.'/coolify.yaml');
      
              // Generate a README file with basic information
              file_put_contents(
                  $configDir.'/README.md',
                  generate_readme_file($this->name, now()->toIso8601String())
              );
          }
      
          public function getConfigurationAsJson(): string
          {
              return (new ConfigurationGenerator($this))->toJson();
          }
      
          public function getConfigurationAsYaml(): string
          {
              return (new ConfigurationGenerator($this))->toYaml();
          }
      
          public function getConfigurationAsArray(): array
          {
              return (new ConfigurationGenerator($this))->toArray();
          }
      }
      
      
      ================================================
      FILE: app/Traits/HasMetrics.php
      ================================================
      getMetrics('cpu', $mins, 'percent');
          }
      
          public function getMemoryMetrics(int $mins = 5): ?array
          {
              $field = $this->isServerMetrics() ? 'usedPercent' : 'used';
      
              return $this->getMetrics('memory', $mins, $field);
          }
      
          private function getMetrics(string $type, int $mins, string $valueField): ?array
          {
              $server = $this->getMetricsServer();
              if (! $server->isMetricsEnabled()) {
                  return null;
              }
      
              $from = now()->subMinutes($mins)->toIso8601ZuluString();
              $endpoint = $this->getMetricsEndpoint($type, $from);
      
              $token = $server->settings->sentinel_token;
              if (! ServerSetting::isValidSentinelToken($token)) {
                  throw new \Exception('Invalid sentinel token format. Please regenerate the token.');
              }
      
              $response = instant_remote_process(
                  ["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$token}\" {$endpoint}'"],
                  $server,
                  false
              );
      
              if (str($response)->contains('error')) {
                  $error = json_decode($response, true);
                  $error = data_get($error, 'error', 'Something is not okay, are you okay?');
                  if ($error === 'Unauthorized') {
                      $error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
                  }
                  throw new \Exception($error);
              }
      
              $metrics = collect(json_decode($response, true))->map(function ($metric) use ($valueField) {
                  return [(int) $metric['time'], (float) ($metric[$valueField] ?? 0.0)];
              })->toArray();
      
              if ($mins > 60 && count($metrics) > 1000) {
                  $metrics = downsampleLTTB($metrics, 1000);
              }
      
              return $metrics;
          }
      
          private function isServerMetrics(): bool
          {
              return $this instanceof \App\Models\Server;
          }
      
          private function getMetricsServer(): \App\Models\Server
          {
              return $this->isServerMetrics() ? $this : $this->destination->server;
          }
      
          private function getMetricsEndpoint(string $type, string $from): string
          {
              $base = 'http://localhost:8888/api';
              if ($this->isServerMetrics()) {
                  return "{$base}/{$type}/history?from={$from}";
              }
      
              return "{$base}/container/{$this->uuid}/{$type}/history?from={$from}";
          }
      }
      
      
      ================================================
      FILE: app/Traits/HasNotificationSettings.php
      ================================================
       $this->emailNotificationSettings,
                  'discord' => $this->discordNotificationSettings,
                  'telegram' => $this->telegramNotificationSettings,
                  'slack' => $this->slackNotificationSettings,
                  'pushover' => $this->pushoverNotificationSettings,
                  'webhook' => $this->webhookNotificationSettings,
                  default => null,
              };
          }
      
          /**
           * Check if a notification channel is enabled
           */
          public function isNotificationEnabled(string $channel): bool
          {
              $settings = $this->getNotificationSettings($channel);
      
              return $settings?->isEnabled() ?? false;
          }
      
          /**
           * Check if a specific notification type is enabled for a channel
           */
          public function isNotificationTypeEnabled(string $channel, string $event): bool
          {
              $settings = $this->getNotificationSettings($channel);
      
              if (! $settings || ! $this->isNotificationEnabled($channel)) {
                  return false;
              }
      
              if (in_array($event, $this->alwaysSendEvents)) {
                  return true;
              }
      
              $settingKey = "{$event}_{$channel}_notifications";
      
              return (bool) $settings->$settingKey;
          }
      
          /**
           * Get all enabled notification channels for an event
           */
          public function getEnabledChannels(string $event): array
          {
              $channels = [];
      
              $channelMap = [
                  'email' => EmailChannel::class,
                  'discord' => DiscordChannel::class,
                  'telegram' => TelegramChannel::class,
                  'slack' => SlackChannel::class,
                  'pushover' => PushoverChannel::class,
                  'webhook' => WebhookChannel::class,
              ];
      
              if ($event === 'general') {
                  unset($channelMap['email']);
              }
      
              foreach ($channelMap as $channel => $channelClass) {
                  if ($this->isNotificationEnabled($channel) && $this->isNotificationTypeEnabled($channel, $event)) {
                      $channels[] = $channelClass;
                  }
              }
      
              return $channels;
          }
      }
      
      
      ================================================
      FILE: app/Traits/HasSafeStringAttribute.php
      ================================================
      attributes['name'] = $this->customizeName($sanitized);
          }
      
          protected function customizeName($value)
          {
              return $value; // Default: no customization
          }
      
          public function setDescriptionAttribute($value)
          {
              $this->attributes['description'] = strip_tags($value);
          }
      }
      
      
      ================================================
      FILE: app/Traits/SaveFromRedirect.php
      ================================================
      forget('from');
              if (! $parameters || $parameters->count() === 0) {
                  $parameters = $this->parameters;
              }
              $parameters = collect($parameters) ?? collect([]);
              $queries = collect($this->query) ?? collect([]);
              $parameters = $parameters->merge($queries);
              session(['from' => [
                  'back' => $this->currentRoute,
                  'route' => $route,
                  'parameters' => $parameters,
              ]]);
      
              return redirect()->route($route);
          }
      }
      
      
      ================================================
      FILE: app/Traits/SshRetryable.php
      ================================================
      getMessage();
      
                      // Check if it's retryable and not the last attempt
                      if ($this->isRetryableSshError($lastErrorMessage) && $attempt < $maxRetries - 1) {
                          $delay = $this->calculateRetryDelay($attempt);
      
                          // Add deployment log if available (for ExecuteRemoteCommand trait)
                          if (isset($this->application_deployment_queue) && method_exists($this, 'addRetryLogEntry')) {
                              $this->addRetryLogEntry($attempt + 1, $maxRetries, $delay, $lastErrorMessage);
                          }
      
                          sleep($delay);
      
                          continue;
                      }
      
                      // Not retryable or max retries reached
                      break;
                  }
              }
      
              // All retries exhausted
              if ($attempt >= $maxRetries) {
                  Log::error('SSH operation failed after all retries', array_merge($context, [
                      'attempts' => $attempt,
                      'error' => $lastErrorMessage,
                  ]));
              }
      
              if ($throwError && $lastError) {
                  // If the error message is empty, provide a more meaningful one
                  if (empty($lastErrorMessage) || trim($lastErrorMessage) === '') {
                      $contextInfo = isset($context['server']) ? " to server {$context['server']}" : '';
                      $attemptInfo = $attempt > 1 ? " after {$attempt} attempts" : '';
                      throw new \RuntimeException("SSH connection failed{$contextInfo}{$attemptInfo}", $lastError->getCode());
                  }
                  throw $lastError;
              }
      
              return null;
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Forms/Button.php
      ================================================
      canGate && $this->canResource && $this->autoDisable) {
                  $hasPermission = Gate::allows($this->canGate, $this->canResource);
      
                  if (! $hasPermission) {
                      $this->disabled = true;
                  }
              }
      
              if ($this->noStyle) {
                  $this->defaultClass = '';
              }
          }
      
          public function render(): View|Closure|string
          {
              return view('components.forms.button');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Forms/Checkbox.php
      ================================================
      canGate && $this->canResource && $this->autoDisable) {
                  $hasPermission = Gate::allows($this->canGate, $this->canResource);
      
                  if (! $hasPermission) {
                      $this->disabled = true;
                      $this->instantSave = false; // Disable instant save for unauthorized users
                  }
              }
      
              if ($this->disabled) {
                  $this->defaultClass .= ' opacity-40';
              }
          }
      
          /**
           * Get the view / contents that represent the component.
           */
          public function render(): View|Closure|string
          {
              // Store original ID for wire:model binding (property name)
              $this->modelBinding = $this->id;
      
              // Generate unique HTML ID by adding random suffix
              // This prevents duplicate IDs when multiple forms are on the same page
              if ($this->id) {
                  $uniqueSuffix = new Cuid2;
                  $this->htmlId = $this->id.'-'.$uniqueSuffix;
              } else {
                  $this->htmlId = $this->id;
              }
      
              return view('components.forms.checkbox');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Forms/Datalist.php
      ================================================
      canGate && $this->canResource && $this->autoDisable) {
                  $hasPermission = Gate::allows($this->canGate, $this->canResource);
      
                  if (! $hasPermission) {
                      $this->disabled = true;
                      $this->instantSave = false; // Disable instant save for unauthorized users
                  }
              }
          }
      
          /**
           * Get the view / contents that represent the component.
           */
          public function render(): View|Closure|string
          {
              // Store original ID for wire:model binding (property name)
              $this->modelBinding = $this->id;
      
              if (is_null($this->id)) {
                  $this->id = new Cuid2;
                  // Don't create wire:model binding for auto-generated IDs
                  $this->modelBinding = 'null';
              }
      
              // Generate unique HTML ID by adding random suffix
              // This prevents duplicate IDs when multiple forms are on the same page
              if ($this->modelBinding && $this->modelBinding !== 'null') {
                  // Use original ID with random suffix for uniqueness
                  $uniqueSuffix = new Cuid2;
                  $this->htmlId = $this->modelBinding.'-'.$uniqueSuffix;
              } else {
                  $this->htmlId = (string) $this->id;
              }
      
              if (is_null($this->name)) {
                  $this->name = $this->modelBinding !== 'null' ? $this->modelBinding : (string) $this->id;
              }
      
              return view('components.forms.datalist');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Forms/EnvVarInput.php
      ================================================
      canGate && $this->canResource && $this->autoDisable) {
                  $hasPermission = Gate::allows($this->canGate, $this->canResource);
      
                  if (! $hasPermission) {
                      $this->disabled = true;
                  }
              }
          }
      
          public function render(): View|Closure|string
          {
              // Store original ID for wire:model binding (property name)
              $this->modelBinding = $this->id;
      
              if (is_null($this->id)) {
                  $this->id = new Cuid2;
                  // Don't create wire:model binding for auto-generated IDs
                  $this->modelBinding = 'null';
              }
              // Generate unique HTML ID by adding random suffix
              // This prevents duplicate IDs when multiple forms are on the same page
              if ($this->modelBinding && $this->modelBinding !== 'null') {
                  // Use original ID with random suffix for uniqueness
                  $uniqueSuffix = new Cuid2;
                  $this->htmlId = $this->modelBinding.'-'.$uniqueSuffix;
              } else {
                  $this->htmlId = (string) $this->id;
              }
      
              if (is_null($this->name)) {
                  $this->name = $this->modelBinding !== 'null' ? $this->modelBinding : (string) $this->id;
              }
      
              if ($this->type === 'password') {
                  $this->defaultClass = $this->defaultClass.'  pr-[2.8rem]';
              }
      
              $this->scopeUrls = [
                  'team' => route('shared-variables.team.index'),
                  'project' => route('shared-variables.project.index'),
                  'environment' => $this->projectUuid && $this->environmentUuid
                      ? route('shared-variables.environment.show', [
                          'project_uuid' => $this->projectUuid,
                          'environment_uuid' => $this->environmentUuid,
                      ])
                      : route('shared-variables.environment.index'),
                  'default' => route('shared-variables.index'),
              ];
      
              return view('components.forms.env-var-input');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Forms/Input.php
      ================================================
      canGate && $this->canResource && $this->autoDisable) {
                  $hasPermission = Gate::allows($this->canGate, $this->canResource);
      
                  if (! $hasPermission) {
                      $this->disabled = true;
                  }
              }
          }
      
          public function render(): View|Closure|string
          {
              // Store original ID for wire:model binding (property name)
              $this->modelBinding = $this->id;
      
              if (is_null($this->id)) {
                  $this->id = new Cuid2;
                  // Don't create wire:model binding for auto-generated IDs
                  $this->modelBinding = 'null';
              }
              // Generate unique HTML ID by adding random suffix
              // This prevents duplicate IDs when multiple forms are on the same page
              if ($this->modelBinding && $this->modelBinding !== 'null') {
                  // Use original ID with random suffix for uniqueness
                  $uniqueSuffix = new Cuid2;
                  $this->htmlId = $this->modelBinding.'-'.$uniqueSuffix;
              } else {
                  $this->htmlId = (string) $this->id;
              }
      
              if (is_null($this->name)) {
                  $this->name = $this->modelBinding !== 'null' ? $this->modelBinding : (string) $this->id;
              }
              if ($this->type === 'password') {
                  $this->defaultClass = $this->defaultClass.'  pr-[2.8rem]';
              }
      
              // $this->label = Str::title($this->label);
              return view('components.forms.input');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Forms/Select.php
      ================================================
      canGate && $this->canResource && $this->autoDisable) {
                  $hasPermission = Gate::allows($this->canGate, $this->canResource);
      
                  if (! $hasPermission) {
                      $this->disabled = true;
                  }
              }
          }
      
          /**
           * Get the view / contents that represent the component.
           */
          public function render(): View|Closure|string
          {
              // Store original ID for wire:model binding (property name)
              $this->modelBinding = $this->id;
      
              if (is_null($this->id)) {
                  $this->id = new Cuid2;
                  // Don't create wire:model binding for auto-generated IDs
                  $this->modelBinding = 'null';
              }
      
              // Generate unique HTML ID by adding random suffix
              // This prevents duplicate IDs when multiple forms are on the same page
              if ($this->modelBinding && $this->modelBinding !== 'null') {
                  // Use original ID with random suffix for uniqueness
                  $uniqueSuffix = new Cuid2;
                  $this->htmlId = $this->modelBinding.'-'.$uniqueSuffix;
              } else {
                  $this->htmlId = (string) $this->id;
              }
      
              if (is_null($this->name)) {
                  $this->name = $this->modelBinding !== 'null' ? $this->modelBinding : (string) $this->id;
              }
      
              return view('components.forms.select');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Forms/Textarea.php
      ================================================
      canGate && $this->canResource && $this->autoDisable) {
                  $hasPermission = Gate::allows($this->canGate, $this->canResource);
      
                  if (! $hasPermission) {
                      $this->disabled = true;
                  }
              }
          }
      
          /**
           * Get the view / contents that represent the component.
           */
          public function render(): View|Closure|string
          {
              // Store original ID for wire:model binding (property name)
              $this->modelBinding = $this->id;
      
              if (is_null($this->id)) {
                  $this->id = new Cuid2;
                  // Don't create wire:model binding for auto-generated IDs
                  $this->modelBinding = 'null';
              }
      
              // Generate unique HTML ID by adding random suffix
              // This prevents duplicate IDs when multiple forms are on the same page
              if ($this->modelBinding && $this->modelBinding !== 'null') {
                  // Use original ID with random suffix for uniqueness
                  $uniqueSuffix = new Cuid2;
                  $this->htmlId = $this->modelBinding.'-'.$uniqueSuffix;
              } else {
                  $this->htmlId = (string) $this->id;
              }
      
              if (is_null($this->name)) {
                  $this->name = $this->modelBinding !== 'null' ? $this->modelBinding : (string) $this->id;
              }
      
              // $this->label = Str::title($this->label);
              return view('components.forms.textarea');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Modal.php
      ================================================
      links = collect([]);
              $service->applications()->get()->map(function ($application) {
                  $type = $application->serviceType();
                  if ($type) {
                      $links = generateServiceSpecificFqdns($application);
                      $links = $links->map(function ($link) {
                          return getFqdnWithoutPort($link);
                      });
                      $this->links = $this->links->merge($links);
                  } else {
                      if ($application->fqdn) {
                          $fqdns = collect(str($application->fqdn)->explode(','));
                          $fqdns->map(function ($fqdn) {
                              $this->links->push(getFqdnWithoutPort($fqdn));
                          });
                      }
                      if ($application->ports) {
                          $portsCollection = collect(str($application->ports)->explode(','));
                          $portsCollection->map(function ($port) {
                              if (str($port)->contains(':')) {
                                  $hostPort = str($port)->before(':');
                              } else {
                                  $hostPort = $port;
                              }
                              $this->links->push(base_url(withPort: false).":{$hostPort}");
                          });
                      }
                  }
              });
          }
      
          /**
           * Get the view / contents that represent the component.
           */
          public function render(): View|Closure|string
          {
              return view('components.services.links');
          }
      }
      
      
      ================================================
      FILE: app/View/Components/Status/Index.php
      ================================================
      complexStatus = $service->status;
          }
      
          /**
           * Get the view / contents that represent the component.
           */
          public function render(): View|Closure|string
          {
              return view('components.status.services');
          }
      }
      
      
      ================================================
      FILE: artisan
      ================================================
      #!/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);
      
      
      ================================================
      FILE: backlog/config.yml
      ================================================
      project_name: "Coolify"
      default_status: "To Do"
      statuses: ["To Do", "In Progress", "Done"]
      labels: []
      milestones: []
      date_format: yyyy-mm-dd
      max_column_width: 20
      default_editor: "vim"
      auto_open_browser: true
      default_port: 6420
      remote_operations: true
      auto_commit: false
      zero_padded_ids: 5
      bypass_git_hooks: true
      check_active_branches: true
      active_branch_days: 30
      
      
      ================================================
      FILE: backlog/tasks/task-00001 - Implement-Docker-build-caching-for-Coolify-staging-builds.md
      ================================================
      ---
      id: task-00001
      title: Implement Docker build caching for Coolify staging builds
      status: To Do
      assignee: []
      created_date: '2025-08-26 12:15'
      updated_date: '2025-08-26 12:16'
      labels:
        - heyandras
        - performance
        - docker
        - ci-cd
        - build-optimization
      dependencies: []
      priority: high
      ---
      
      ## Description
      
      Implement comprehensive Docker build caching to reduce staging build times by 50-70% through BuildKit cache mounts for dependencies and GitHub Actions registry caching. This optimization will significantly reduce build times from ~10-15 minutes to ~3-5 minutes, decrease network usage, and lower GitHub Actions costs.
      
      ## Acceptance Criteria
      
      - [ ] #1 Docker BuildKit cache mounts are added to Composer dependency installation in production Dockerfile
      - [ ] #2 Docker BuildKit cache mounts are added to NPM dependency installation in production Dockerfile
      - [ ] #3 GitHub Actions BuildX setup is configured for both AMD64 and AARCH64 jobs
      - [ ] #4 Registry cache-from and cache-to configurations are implemented for both architecture builds
      - [ ] #5 Build time reduction of at least 40% is achieved in staging builds
      - [ ] #6 GitHub Actions minutes consumption is reduced compared to baseline
      - [ ] #7 All existing build functionality remains intact with no regressions
      
      
      ## Implementation Plan
      
      1. Modify docker/production/Dockerfile to add BuildKit cache mounts:
         - Add cache mount for Composer dependencies at line 30: --mount=type=cache,target=/var/www/.composer/cache
         - Add cache mount for NPM dependencies at line 41: --mount=type=cache,target=/root/.npm
      
      2. Update .github/workflows/coolify-staging-build.yml for AMD64 job:
         - Add docker/setup-buildx-action@v3 step after checkout
         - Configure cache-from and cache-to parameters in build-push-action
         - Use registry caching with buildcache-amd64 tags
      
      3. Update .github/workflows/coolify-staging-build.yml for AARCH64 job:
         - Add docker/setup-buildx-action@v3 step after checkout  
         - Configure cache-from and cache-to parameters in build-push-action
         - Use registry caching with buildcache-aarch64 tags
      
      4. Test implementation:
         - Measure baseline build times before changes
         - Deploy changes and monitor initial build (will be slower due to cache population)
         - Measure subsequent build times to verify 40%+ improvement
         - Validate all build outputs and functionality remain unchanged
      
      5. Monitor and validate:
         - Track GitHub Actions minutes consumption reduction
         - Ensure Docker registry storage usage is reasonable
         - Verify no build failures or regressions introduced
      
      
      ================================================
      FILE: backlog/tasks/task-00001.01 - Add-BuildKit-cache-mounts-to-Dockerfile.md
      ================================================
      ---
      id: task-00001.01
      title: Add BuildKit cache mounts to Dockerfile
      status: To Do
      assignee: []
      created_date: '2025-08-26 12:19'
      labels:
        - docker
        - buildkit
        - performance
        - dockerfile
      dependencies: []
      parent_task_id: task-00001
      priority: high
      ---
      
      ## Description
      
      Modify the production Dockerfile to include BuildKit cache mounts for Composer and NPM dependencies to speed up subsequent builds by reusing cached dependency installations
      
      ## Acceptance Criteria
      
      - [ ] #1 Cache mount for Composer dependencies is added at line 30 with --mount=type=cache target=/var/www/.composer/cache,Cache mount for NPM dependencies is added at line 41 with --mount=type=cache target=/root/.npm,Dockerfile syntax remains valid and builds successfully,All existing functionality is preserved with no regressions
      
      
      
      ================================================
      FILE: backlog/tasks/task-00001.02 - Configure-BuildX-and-registry-caching-for-AMD64-staging-builds.md
      ================================================
      ---
      id: task-00001.02
      title: Configure BuildX and registry caching for AMD64 staging builds
      status: To Do
      assignee: []
      created_date: '2025-08-26 12:19'
      labels:
        - github-actions
        - buildx
        - caching
        - amd64
      dependencies: []
      parent_task_id: task-00001
      priority: high
      ---
      
      ## Description
      
      Update the GitHub Actions workflow to add BuildX setup and configure registry-based caching for the AMD64 build job to leverage Docker layer caching across builds
      
      ## Acceptance Criteria
      
      - [ ] #1 docker/setup-buildx-action@v3 step is added after checkout in AMD64 job,Registry cache configuration is added to build-push-action with cache-from and cache-to parameters,Cache tags use buildcache-amd64 naming convention for architecture-specific caching,Build job runs successfully with caching enabled,No impact on existing build outputs or functionality
      
      
      
      ================================================
      FILE: backlog/tasks/task-00001.03 - Configure-BuildX-and-registry-caching-for-AARCH64-staging-builds.md
      ================================================
      ---
      id: task-00001.03
      title: Configure BuildX and registry caching for AARCH64 staging builds
      status: To Do
      assignee: []
      created_date: '2025-08-26 12:19'
      labels:
        - github-actions
        - buildx
        - caching
        - aarch64
        - self-hosted
      dependencies: []
      parent_task_id: task-00001
      priority: high
      ---
      
      ## Description
      
      Update the GitHub Actions workflow to add BuildX setup and configure registry-based caching for the AARCH64 build job running on self-hosted ARM64 runners
      
      ## Acceptance Criteria
      
      - [ ] #1 docker/setup-buildx-action@v3 step is added after checkout in AARCH64 job,Registry cache configuration is added to build-push-action with cache-from and cache-to parameters,Cache tags use buildcache-aarch64 naming convention for architecture-specific caching,Build job runs successfully on self-hosted ARM64 runner with caching enabled,No impact on existing build outputs or functionality
      
      
      
      ================================================
      FILE: backlog/tasks/task-00001.04 - Establish-build-time-baseline-measurements.md
      ================================================
      ---
      id: task-00001.04
      title: Establish build time baseline measurements
      status: To Do
      assignee: []
      created_date: '2025-08-26 12:19'
      labels:
        - performance
        - testing
        - baseline
        - measurement
      dependencies: []
      parent_task_id: task-00001
      priority: medium
      ---
      
      ## Description
      
      Measure and document current staging build times for both AMD64 and AARCH64 architectures before implementing caching optimizations to establish a performance baseline for comparison
      
      ## Acceptance Criteria
      
      - [ ] #1 Baseline build times are measured for at least 3 consecutive AMD64 builds,Baseline build times are measured for at least 3 consecutive AARCH64 builds,Average build time and GitHub Actions minutes consumption are documented,Baseline measurements include both cold builds and any existing warm builds,Results are documented in a format suitable for comparing against post-optimization builds
      
      
      
      ================================================
      FILE: backlog/tasks/task-00001.05 - Validate-caching-implementation-and-measure-performance-improvements.md
      ================================================
      ---
      id: task-00001.05
      title: Validate caching implementation and measure performance improvements
      status: To Do
      assignee: []
      created_date: '2025-08-26 12:19'
      labels:
        - testing
        - performance
        - validation
        - measurement
      dependencies:
        - task-00001.01
        - task-00001.02
        - task-00001.03
        - task-00001.04
      parent_task_id: task-00001
      priority: high
      ---
      
      ## Description
      
      Test the complete Docker build caching implementation by running multiple staging builds and measuring performance improvements to ensure the 40% build time reduction target is achieved
      
      ## Acceptance Criteria
      
      - [ ] #1 First build after cache implementation runs successfully (expected slower due to cache population),Second and subsequent builds show significant time reduction compared to baseline,Build time reduction of at least 40% is achieved and documented,GitHub Actions minutes consumption is reduced compared to baseline measurements,All Docker images function identically to pre-optimization builds,No build failures or regressions are introduced by caching changes
      
      
      
      ================================================
      FILE: backlog/tasks/task-00001.06 - Document-cache-optimization-results-and-create-production-workflow-plan.md
      ================================================
      ---
      id: task-00001.06
      title: Document cache optimization results and create production workflow plan
      status: To Do
      assignee: []
      created_date: '2025-08-26 12:19'
      labels:
        - documentation
        - planning
        - production
        - analysis
      dependencies:
        - task-00001.05
      parent_task_id: task-00001
      priority: low
      ---
      
      ## Description
      
      Document the staging build caching results and create a detailed plan for applying the same optimizations to the production build workflow if staging results meet performance targets
      
      ## Acceptance Criteria
      
      - [ ] #1 Performance improvement results are documented with before/after metrics,Cost savings in GitHub Actions minutes are calculated and documented,Analysis of Docker registry storage impact is provided,Detailed plan for production workflow optimization is created,Recommendations for cache retention policies and cleanup strategies are provided,Documentation includes rollback procedures if issues arise
      
      
      
      ================================================
      FILE: backlog/tasks/task-00002 - Fix-Docker-cleanup-irregular-scheduling-in-cloud-environment.md
      ================================================
      ---
      id: task-00002
      title: Fix Docker cleanup irregular scheduling in cloud environment
      status: Done
      assignee:
        - '@claude'
      created_date: '2025-08-26 12:17'
      updated_date: '2025-08-26 12:26'
      labels:
        - backend
        - performance
        - cloud
      dependencies: []
      priority: high
      ---
      
      ## Description
      
      Docker cleanup jobs are running at irregular intervals instead of hourly as configured (0 * * * *) in the cloud environment with 2 Horizon workers and thousands of servers. The issue stems from the ServerManagerJob processing servers sequentially with a frozen execution time, causing timing mismatches when evaluating cron expressions for large server counts.
      
      ## Acceptance Criteria
      
      - [x] #1 Docker cleanup runs consistently at the configured hourly intervals
      - [x] #2 All eligible servers receive cleanup jobs when due
      - [x] #3 Solution handles thousands of servers efficiently
      - [x] #4 Maintains backwards compatibility with existing settings
      - [x] #5 Cloud subscription checks are properly enforced
      
      
      ## Implementation Plan
      
      1. Add processDockerCleanups() method to ScheduledJobManager
         - Implement method to fetch all eligible servers
         - Apply frozen execution time for consistent cron evaluation
         - Check server functionality and cloud subscription status
         - Dispatch DockerCleanupJob for servers where cleanup is due
      
      2. Implement helper methods in ScheduledJobManager
         - getServersForCleanup(): Fetch servers with proper cloud/self-hosted filtering
         - shouldProcessDockerCleanup(): Validate server eligibility
         - Reuse existing shouldRunNow() method with frozen execution time
      
      3. Remove Docker cleanup logic from ServerManagerJob
         - Delete lines 136-150 that handle Docker cleanup scheduling
         - Keep other server management tasks intact
      
      4. Test the implementation
         - Verify hourly execution with test servers
         - Check timezone handling
         - Validate cloud subscription filtering
         - Monitor for duplicate job prevention via WithoutOverlapping middleware
      
      5. Deploy strategy
         - First deploy updated ScheduledJobManager
         - Monitor logs for successful hourly executions
         - Once confirmed, remove cleanup from ServerManagerJob
         - No database migrations required
      
      ## Implementation Notes
      
      Successfully migrated Docker cleanup scheduling from ServerManagerJob to ScheduledJobManager.
      
      **Changes Made:**
      1. Added processDockerCleanups() method to ScheduledJobManager that processes all servers with a single frozen execution time
      2. Implemented getServersForCleanup() to fetch servers with proper cloud/self-hosted filtering
      3. Implemented shouldProcessDockerCleanup() for server eligibility validation
      4. Removed Docker cleanup logic from ServerManagerJob (lines 136-150)
      
      **Key Improvements:**
      - All servers now evaluated against the same timestamp, ensuring consistent hourly execution
      - Proper cloud subscription checks maintained
      - Backwards compatible - no database migrations or settings changes required
      - Follows the same proven pattern used for database backups
      
      **Files Modified:**
      - app/Jobs/ScheduledJobManager.php: Added Docker cleanup processing
      - app/Jobs/ServerManagerJob.php: Removed Docker cleanup logic
      
      **Testing:**
      - Syntax validation passed
      - Code formatting verified with Laravel Pint
      - PHPStan analysis completed (existing warnings unrelated to changes)
      
      
      ================================================
      FILE: backlog/tasks/task-00003 - Simplify-resource-operations-UI-replace-boxes-with-dropdown-selections.md
      ================================================
      ---
      id: task-00003
      title: Simplify resource operations UI - replace boxes with dropdown selections
      status: To Do
      assignee: []
      created_date: '2025-08-26 13:22'
      updated_date: '2025-08-26 13:22'
      labels:
        - ui
        - frontend
        - livewire
      dependencies: []
      priority: medium
      ---
      
      ## Description
      
      Replace the current box-based layout in resource-operations.blade.php with clean dropdown selections to improve UX when there are many servers, projects, or environments. The current interface becomes overwhelming and cluttered with multiple modal confirmation boxes for each option.
      
      ## Acceptance Criteria
      
      - [ ] #1 Clone section shows a dropdown to select server/destination instead of multiple boxes
      - [ ] #2 Move section shows a dropdown to select project/environment instead of multiple boxes
      - [ ] #3 Single "Clone Resource" button that triggers modal after dropdown selection
      - [ ] #4 Single "Move Resource" button that triggers modal after dropdown selection
      - [ ] #5 Authorization warnings remain in place for users without permissions
      - [ ] #6 All existing functionality preserved (cloning, moving, success messages)
      - [ ] #7 Clean, simple interface that scales well with many options
      - [ ] #8 Mobile-friendly dropdown interface
      
      
      
      ================================================
      FILE: boost.json
      ================================================
      {
          "agents": [
              "cursor",
              "claude_code",
              "codex",
              "opencode"
          ],
          "guidelines": true,
          "herd_mcp": false,
          "mcp": true,
          "packages": [
              "laravel/fortify",
              "spatie/laravel-ray"
          ],
          "sail": false,
          "skills": [
              "livewire-development",
              "pest-testing",
              "tailwindcss-development",
              "developing-with-fortify",
              "debugging-output-and-previewing-html-using-ray"
          ]
      }
      
      
      ================================================
      FILE: bootstrap/app.php
      ================================================
      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;
      
      
      ================================================
      FILE: bootstrap/cache/.gitignore
      ================================================
      *
      !.gitignore
      
      
      ================================================
      FILE: bootstrap/getHelperVersion.php
      ================================================
      user()->currentAccessToken();
      
          return data_get($token, 'team_id');
      }
      function invalidTokenResponse()
      {
          return response()->json(['message' => 'Invalid token.', 'docs' => 'https://coolify.io/docs/api-reference/authorization'], 400);
      }
      
      function serializeApiResponse($data)
      {
          if ($data instanceof Collection) {
              return $data->map(function ($d) {
                  $d = collect($d)->sortKeys();
                  $created_at = data_get($d, 'created_at');
                  $updated_at = data_get($d, 'updated_at');
                  if ($created_at) {
                      unset($d['created_at']);
                      $d['created_at'] = $created_at;
                  }
                  if ($updated_at) {
                      unset($d['updated_at']);
                      $d['updated_at'] = $updated_at;
                  }
                  if (data_get($d, 'name')) {
                      $d = $d->prepend($d['name'], 'name');
                  }
                  if (data_get($d, 'description')) {
                      $d = $d->prepend($d['description'], 'description');
                  }
                  if (data_get($d, 'uuid')) {
                      $d = $d->prepend($d['uuid'], 'uuid');
                  }
      
                  if (! is_null(data_get($d, 'id'))) {
                      $d = $d->prepend($d['id'], 'id');
                  }
      
                  return $d;
              });
          } else {
              $d = collect($data)->sortKeys();
              $created_at = data_get($d, 'created_at');
              $updated_at = data_get($d, 'updated_at');
              if ($created_at) {
                  unset($d['created_at']);
                  $d['created_at'] = $created_at;
              }
              if ($updated_at) {
                  unset($d['updated_at']);
                  $d['updated_at'] = $updated_at;
              }
              if (data_get($d, 'name')) {
                  $d = $d->prepend($d['name'], 'name');
              }
              if (data_get($d, 'description')) {
                  $d = $d->prepend($d['description'], 'description');
              }
              if (data_get($d, 'uuid')) {
                  $d = $d->prepend($d['uuid'], 'uuid');
              }
      
              if (! is_null(data_get($d, 'id'))) {
                  $d = $d->prepend($d['id'], 'id');
              }
      
              return $d;
          }
      }
      
      function sharedDataApplications()
      {
          return [
              'git_repository' => 'string',
              'git_branch' => 'string',
              'build_pack' => Rule::enum(BuildPackTypes::class),
              'is_static' => 'boolean',
              'is_spa' => 'boolean',
              'is_auto_deploy_enabled' => 'boolean',
              'is_force_https_enabled' => 'boolean',
              'static_image' => Rule::enum(StaticImageTypes::class),
              'domains' => 'string|nullable',
              'redirect' => Rule::enum(RedirectTypes::class),
              'git_commit_sha' => ['string', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9._\-\/]*$/'],
              'docker_registry_image_name' => 'string|nullable',
              'docker_registry_image_tag' => 'string|nullable',
              'install_command' => 'string|nullable',
              'build_command' => 'string|nullable',
              'start_command' => 'string|nullable',
              'ports_exposes' => 'string|regex:/^(\d+)(,\d+)*$/',
              'ports_mappings' => 'string|regex:/^(\d+:\d+)(,\d+:\d+)*$/|nullable',
              'custom_network_aliases' => 'string|nullable',
              'base_directory' => 'string|nullable',
              'publish_directory' => 'string|nullable',
              'health_check_enabled' => 'boolean',
              'health_check_type' => 'string|in:http,cmd',
              'health_check_command' => ['nullable', 'string', 'max:1000', 'regex:/^[a-zA-Z0-9 \-_.\/:=@,+]+$/'],
              'health_check_path' => ['string', 'regex:#^[a-zA-Z0-9/\-_.~%]+$#'],
              'health_check_port' => 'integer|nullable|min:1|max:65535',
              'health_check_host' => ['string', 'regex:/^[a-zA-Z0-9.\-_]+$/'],
              'health_check_method' => 'string|in:GET,HEAD,POST,OPTIONS',
              'health_check_return_code' => 'numeric',
              'health_check_scheme' => 'string|in:http,https',
              'health_check_response_text' => 'string|nullable',
              'health_check_interval' => 'numeric',
              'health_check_timeout' => 'numeric',
              'health_check_retries' => 'numeric',
              'health_check_start_period' => 'numeric',
              'limits_memory' => 'string',
              'limits_memory_swap' => 'string',
              'limits_memory_swappiness' => 'numeric',
              'limits_memory_reservation' => 'string',
              'limits_cpus' => 'string',
              'limits_cpuset' => 'string|nullable',
              'limits_cpu_shares' => 'numeric',
              'custom_labels' => 'string|nullable',
              'custom_docker_run_options' => 'string|nullable',
              'post_deployment_command' => 'string|nullable',
              'post_deployment_command_container' => 'string',
              'pre_deployment_command' => 'string|nullable',
              'pre_deployment_command_container' => 'string',
              'manual_webhook_secret_github' => 'string|nullable',
              'manual_webhook_secret_gitlab' => 'string|nullable',
              'manual_webhook_secret_bitbucket' => 'string|nullable',
              'manual_webhook_secret_gitea' => 'string|nullable',
              'dockerfile_location' => ['string', 'nullable', 'max:255', 'regex:'.\App\Support\ValidationPatterns::FILE_PATH_PATTERN],
              'docker_compose_location' => ['string', 'nullable', 'max:255', 'regex:'.\App\Support\ValidationPatterns::FILE_PATH_PATTERN],
              'docker_compose' => 'string|nullable',
              'docker_compose_domains' => 'array|nullable',
              'docker_compose_custom_start_command' => 'string|nullable',
              'docker_compose_custom_build_command' => 'string|nullable',
              'is_container_label_escape_enabled' => 'boolean',
          ];
      }
      
      function validateIncomingRequest(Request $request)
      {
          // check if request is json
          if (! $request->isJson()) {
              return response()->json([
                  'message' => 'Invalid request.',
                  'error' => 'Content-Type must be application/json.',
              ], 400);
          }
          // check if request is valid json
          if (! json_decode($request->getContent())) {
              return response()->json([
                  'message' => 'Invalid request.',
                  'error' => 'Invalid JSON.',
              ], 400);
          }
          // check if valid json is empty
          if (empty($request->json()->all())) {
              return response()->json([
                  'message' => 'Invalid request.',
                  'error' => 'Empty JSON.',
              ], 400);
          }
      }
      
      function removeUnnecessaryFieldsFromRequest(Request $request)
      {
          $request->offsetUnset('project_uuid');
          $request->offsetUnset('environment_name');
          $request->offsetUnset('environment_uuid');
          $request->offsetUnset('destination_uuid');
          $request->offsetUnset('server_uuid');
          $request->offsetUnset('type');
          $request->offsetUnset('domains');
          $request->offsetUnset('instant_deploy');
          $request->offsetUnset('github_app_uuid');
          $request->offsetUnset('private_key_uuid');
          $request->offsetUnset('use_build_server');
          $request->offsetUnset('is_static');
          $request->offsetUnset('is_spa');
          $request->offsetUnset('is_auto_deploy_enabled');
          $request->offsetUnset('is_force_https_enabled');
          $request->offsetUnset('connect_to_docker_network');
          $request->offsetUnset('force_domain_override');
          $request->offsetUnset('autogenerate_domain');
          $request->offsetUnset('is_container_label_escape_enabled');
          $request->offsetUnset('docker_compose_raw');
      }
      
      
      ================================================
      FILE: bootstrap/helpers/applications.php
      ================================================
      id;
          $deployment_link = Url::fromString($application->link()."/deployment/{$deployment_uuid}");
          $deployment_url = $deployment_link->getPath();
          $server_id = $application->destination->server->id;
          $server_name = $application->destination->server->name;
          $destination_id = $application->destination->id;
      
          if ($server) {
              $server_id = $server->id;
              $server_name = $server->name;
          }
          if ($destination) {
              $destination_id = $destination->id;
          }
      
          // Check if the deployment queue is full for this server
          $serverForQueueCheck = $server ?? Server::find($server_id);
          $queue_limit = $serverForQueueCheck->settings->deployment_queue_limit ?? 25;
          $queued_count = ApplicationDeploymentQueue::where('server_id', $server_id)
              ->where('status', ApplicationDeploymentStatus::QUEUED->value)
              ->count();
      
          if ($queued_count >= $queue_limit) {
              return [
                  'status' => 'queue_full',
                  'message' => 'Deployment queue is full. Please wait for existing deployments to complete.',
              ];
          }
      
          // Check if there's already a deployment in progress or queued for this application and commit
          $existing_deployment = ApplicationDeploymentQueue::where('application_id', $application_id)
              ->where('commit', $commit)
              ->where('pull_request_id', $pull_request_id)
              ->whereIn('status', [ApplicationDeploymentStatus::IN_PROGRESS->value, ApplicationDeploymentStatus::QUEUED->value])
              ->first();
      
          if ($existing_deployment) {
              // If force_rebuild is true or rollback is true or no_questions_asked is true, we'll still create a new deployment
              if (! $force_rebuild && ! $rollback && ! $no_questions_asked) {
                  // Return the existing deployment's details
                  return [
                      'status' => 'skipped',
                      'message' => 'Deployment already queued for this commit.',
                      'deployment_uuid' => $existing_deployment->deployment_uuid,
                      'existing_deployment' => $existing_deployment,
                  ];
              }
          }
      
          $deployment = ApplicationDeploymentQueue::create([
              'application_id' => $application_id,
              'application_name' => $application->name,
              'server_id' => $server_id,
              'server_name' => $server_name,
              'destination_id' => $destination_id,
              'deployment_uuid' => $deployment_uuid,
              'deployment_url' => $deployment_url,
              'pull_request_id' => $pull_request_id,
              'force_rebuild' => $force_rebuild,
              'is_webhook' => $is_webhook,
              'is_api' => $is_api,
              'restart_only' => $restart_only,
              'commit' => $commit,
              'rollback' => $rollback,
              'git_type' => $git_type,
              'only_this_server' => $only_this_server,
          ]);
      
          if ($no_questions_asked) {
              $deployment->update([
                  'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
              ]);
              ApplicationDeploymentJob::dispatch(
                  application_deployment_queue_id: $deployment->id,
              );
          } elseif (next_queuable($server_id, $application_id, $commit, $pull_request_id)) {
              $deployment->update([
                  'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
              ]);
              ApplicationDeploymentJob::dispatch(
                  application_deployment_queue_id: $deployment->id,
              );
          }
      
          return [
              'status' => 'queued',
              'message' => 'Deployment queued.',
              'deployment_uuid' => $deployment_uuid,
          ];
      }
      function force_start_deployment(ApplicationDeploymentQueue $deployment)
      {
          $deployment->update([
              'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
          ]);
      
          ApplicationDeploymentJob::dispatch(
              application_deployment_queue_id: $deployment->id,
          );
      }
      function queue_next_deployment(Application $application)
      {
          $server_id = $application->destination->server_id;
          $queued_deployments = ApplicationDeploymentQueue::where('server_id', $server_id)
              ->where('status', ApplicationDeploymentStatus::QUEUED)
              ->get()
              ->sortBy('created_at');
      
          foreach ($queued_deployments as $next_deployment) {
              // Check if this queued deployment can actually run
              if (next_queuable($next_deployment->server_id, $next_deployment->application_id, $next_deployment->commit, $next_deployment->pull_request_id)) {
                  $next_deployment->update([
                      'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
                  ]);
      
                  ApplicationDeploymentJob::dispatch(
                      application_deployment_queue_id: $next_deployment->id,
                  );
              }
          }
      }
      
      function next_queuable(string $server_id, string $application_id, string $commit = 'HEAD', int $pull_request_id = 0): bool
      {
          // Check if there's already a deployment in progress for this application with the same pull_request_id
          // This allows normal deployments and PR deployments to run concurrently
          $in_progress = ApplicationDeploymentQueue::where('application_id', $application_id)
              ->where('pull_request_id', $pull_request_id)
              ->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value)
              ->exists();
      
          if ($in_progress) {
              return false;
          }
      
          // Check server's concurrent build limit
          $server = Server::find($server_id);
          $concurrent_builds = $server->settings->concurrent_builds;
          $active_deployments = ApplicationDeploymentQueue::where('server_id', $server_id)
              ->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value)
              ->count();
      
          if ($active_deployments >= $concurrent_builds) {
              return false;
          }
      
          return true;
      }
      function next_after_cancel(?Server $server = null)
      {
          if ($server) {
              $next_found = ApplicationDeploymentQueue::where('server_id', data_get($server, 'id'))
                  ->where('status', ApplicationDeploymentStatus::QUEUED)
                  ->get()
                  ->sortBy('created_at');
      
              if ($next_found->count() > 0) {
                  foreach ($next_found as $next) {
                      // Use next_queuable to properly check if this deployment can run
                      if (next_queuable($next->server_id, $next->application_id, $next->commit, $next->pull_request_id)) {
                          $next->update([
                              'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
                          ]);
      
                          ApplicationDeploymentJob::dispatch(
                              application_deployment_queue_id: $next->id,
                          );
                      }
                  }
              }
          }
      }
      
      function clone_application(Application $source, $destination, array $overrides = [], bool $cloneVolumeData = false): Application
      {
          $uuid = $overrides['uuid'] ?? (string) new Cuid2;
          $server = $destination->server;
      
          if ($server->team_id !== currentTeam()->id) {
              throw new \RuntimeException('Destination does not belong to the current team.');
          }
      
          // Prepare name and URL
          $name = $overrides['name'] ?? 'clone-of-'.str($source->name)->limit(20).'-'.$uuid;
          $applicationSettings = $source->settings;
          $url = $overrides['fqdn'] ?? $source->fqdn;
      
          if ($server->proxyType() !== 'NONE' && $applicationSettings->is_container_label_readonly_enabled === true) {
              $url = generateUrl(server: $server, random: $uuid);
          }
      
          // Clone the application
          $newApplication = $source->replicate([
              'id',
              'created_at',
              'updated_at',
              'additional_servers_count',
              'additional_networks_count',
          ])->fill(array_merge([
              'uuid' => $uuid,
              'name' => $name,
              'fqdn' => $url,
              'status' => 'exited',
              'destination_id' => $destination->id,
          ], $overrides));
          $newApplication->save();
      
          // Update custom labels if needed
          if ($newApplication->destination->server->proxyType() !== 'NONE' && $applicationSettings->is_container_label_readonly_enabled === true) {
              $customLabels = str(implode('|coolify|', generateLabelsApplication($newApplication)))->replace('|coolify|', "\n");
              $newApplication->custom_labels = base64_encode($customLabels);
              $newApplication->save();
          }
      
          // Clone settings
          $newApplication->settings()->delete();
          if ($applicationSettings) {
              $newApplicationSettings = $applicationSettings->replicate([
                  'id',
                  'created_at',
                  'updated_at',
              ])->fill([
                  'application_id' => $newApplication->id,
              ]);
              $newApplicationSettings->save();
          }
      
          // Clone tags
          $tags = $source->tags;
          foreach ($tags as $tag) {
              $newApplication->tags()->attach($tag->id);
          }
      
          // Clone scheduled tasks
          $scheduledTasks = $source->scheduled_tasks()->get();
          foreach ($scheduledTasks as $task) {
              $newTask = $task->replicate([
                  'id',
                  'created_at',
                  'updated_at',
              ])->fill([
                  'uuid' => (string) new Cuid2,
                  'application_id' => $newApplication->id,
                  'team_id' => currentTeam()->id,
              ]);
              $newTask->save();
          }
      
          // Clone previews with FQDN regeneration
          $applicationPreviews = $source->previews()->get();
          foreach ($applicationPreviews as $preview) {
              $newPreview = $preview->replicate([
                  'id',
                  'created_at',
                  'updated_at',
              ])->fill([
                  'uuid' => (string) new Cuid2,
                  'application_id' => $newApplication->id,
                  'status' => 'exited',
                  'fqdn' => null,
                  'docker_compose_domains' => null,
              ]);
              $newPreview->save();
      
              // Regenerate FQDN for the cloned preview
              if ($newApplication->build_pack === 'dockercompose') {
                  $newPreview->generate_preview_fqdn_compose();
              } else {
                  $newPreview->generate_preview_fqdn();
              }
          }
      
          // Clone persistent volumes
          $persistentVolumes = $source->persistentStorages()->get();
          foreach ($persistentVolumes as $volume) {
              $newName = '';
              if (str_starts_with($volume->name, $source->uuid)) {
                  $newName = str($volume->name)->replace($source->uuid, $newApplication->uuid);
              } else {
                  $newName = $newApplication->uuid.'-'.str($volume->name)->afterLast('-');
              }
      
              $newPersistentVolume = $volume->replicate([
                  'id',
                  'created_at',
                  'updated_at',
              ])->fill([
                  'name' => $newName,
                  'resource_id' => $newApplication->id,
              ]);
              $newPersistentVolume->save();
      
              if ($cloneVolumeData) {
                  try {
                      StopApplication::dispatch($source, false, false);
                      $sourceVolume = $volume->name;
                      $targetVolume = $newPersistentVolume->name;
                      $sourceServer = $source->destination->server;
                      $targetServer = $newApplication->destination->server;
      
                      VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
      
                      queue_application_deployment(
                          deployment_uuid: (string) new Cuid2,
                          application: $source,
                          server: $sourceServer,
                          destination: $source->destination,
                          no_questions_asked: true
                      );
                  } catch (\Exception $e) {
                      \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
                  }
              }
          }
      
          // Clone file storages
          $fileStorages = $source->fileStorages()->get();
          foreach ($fileStorages as $storage) {
              $newStorage = $storage->replicate([
                  'id',
                  'created_at',
                  'updated_at',
              ])->fill([
                  'resource_id' => $newApplication->id,
              ]);
              $newStorage->save();
          }
      
          // Clone production environment variables without triggering the created hook
          $environmentVariables = $source->environment_variables()->get();
          foreach ($environmentVariables as $environmentVariable) {
              \App\Models\EnvironmentVariable::withoutEvents(function () use ($environmentVariable, $newApplication) {
                  $newEnvironmentVariable = $environmentVariable->replicate([
                      'id',
                      'created_at',
                      'updated_at',
                  ])->fill([
                      'resourceable_id' => $newApplication->id,
                      'resourceable_type' => $newApplication->getMorphClass(),
                      'is_preview' => false,
                  ]);
                  $newEnvironmentVariable->save();
              });
          }
      
          // Clone preview environment variables
          $previewEnvironmentVariables = $source->environment_variables_preview()->get();
          foreach ($previewEnvironmentVariables as $previewEnvironmentVariable) {
              \App\Models\EnvironmentVariable::withoutEvents(function () use ($previewEnvironmentVariable, $newApplication) {
                  $newPreviewEnvironmentVariable = $previewEnvironmentVariable->replicate([
                      'id',
                      'created_at',
                      'updated_at',
                  ])->fill([
                      'resourceable_id' => $newApplication->id,
                      'resourceable_type' => $newApplication->getMorphClass(),
                      'is_preview' => true,
                  ]);
                  $newPreviewEnvironmentVariable->save();
              });
          }
      
          return $newApplication;
      }
      
      
      ================================================
      FILE: bootstrap/helpers/constants.php
      ================================================
      ';
      const DATABASE_TYPES = ['postgresql', 'redis', 'mongodb', 'mysql', 'mariadb', 'keydb', 'dragonfly', 'clickhouse'];
      const VALID_CRON_STRINGS = [
          'every_minute' => '* * * * *',
          'hourly' => '0 * * * *',
          'daily' => '0 0 * * *',
          'weekly' => '0 0 * * 0',
          'monthly' => '0 0 1 * *',
          'yearly' => '0 0 1 1 *',
          '@hourly' => '0 * * * *',
          '@daily' => '0 0 * * *',
          '@weekly' => '0 0 * * 0',
          '@monthly' => '0 0 1 * *',
          '@yearly' => '0 0 1 1 *',
      ];
      const RESTART_MODE = 'unless-stopped';
      
      const DATABASE_DOCKER_IMAGES = [
          'bitnami/mariadb',
          'bitnami/mongodb',
          'bitnami/redis',
          'bitnamilegacy/mariadb',
          'bitnamilegacy/mongodb',
          'bitnamilegacy/redis',
          'bitnamisecure/mariadb',
          'bitnamisecure/mongodb',
          'bitnamisecure/redis',
          'mysql',
          'bitnami/mysql',
          'bitnamilegacy/mysql',
          'bitnamisecure/mysql',
          'mysql/mysql-server',
          'mariadb',
          'postgis/postgis',
          'postgres',
          'bitnami/postgresql',
          'bitnamilegacy/postgresql',
          'bitnamisecure/postgresql',
          'supabase/postgres',
          'elestio/postgres',
          'mongo',
          'redis',
          'memcached',
          'couchdb',
          'neo4j',
          'influxdb',
          'clickhouse/clickhouse-server',
          'timescaledb/timescaledb',
          'timescaledb',  // Matches timescale/timescaledb
          'timescaledb-ha',  // Matches timescale/timescaledb-ha
          'pgvector/pgvector',
      ];
      const SPECIFIC_SERVICES = [
          'quay.io/minio/minio',
          'minio/minio',
          'ghcr.io/coollabsio/minio',
          'coollabsio/minio',
          'svhd/logto',
          'dxflrs/garage',
      ];
      
      // Based on /etc/os-release
      const SUPPORTED_OS = [
          'ubuntu debian raspbian pop',
          'centos fedora rhel ol rocky amzn almalinux',
          'sles opensuse-leap opensuse-tumbleweed',
          'arch',
          'alpine',
      ];
      
      const NEEDS_TO_CONNECT_TO_PREDEFINED_NETWORK = [
          'pgadmin',
          'databasus',
          'redis-insight',
      ];
      const NEEDS_TO_DISABLE_GZIP = [
          'beszel' => ['beszel'],
      ];
      const NEEDS_TO_DISABLE_STRIPPREFIX = [
          'appwrite' => ['appwrite', 'appwrite-console', 'appwrite-realtime'],
      ];
      const SHARED_VARIABLE_TYPES = ['team', 'project', 'environment'];
      
      
      ================================================
      FILE: bootstrap/helpers/databases.php
      ================================================
      firstOrFail();
          $database = new StandalonePostgresql;
          $database->uuid = (new Cuid2);
          $database->name = 'postgresql-database-'.$database->uuid;
          $database->image = $databaseImage;
          $database->postgres_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->environment_id = $environmentId;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          return $database;
      }
      
      function create_standalone_redis($environment_id, $destination_uuid, ?array $otherData = null): StandaloneRedis
      {
          $destination = StandaloneDocker::where('uuid', $destination_uuid)->firstOrFail();
          $database = new StandaloneRedis;
          $database->uuid = (new Cuid2);
          $database->name = 'redis-database-'.$database->uuid;
      
          $redis_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          if ($otherData && isset($otherData['redis_password'])) {
              $redis_password = $otherData['redis_password'];
              unset($otherData['redis_password']);
          }
      
          $database->environment_id = $environment_id;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          EnvironmentVariable::create([
              'key' => 'REDIS_PASSWORD',
              'value' => $redis_password,
              'resourceable_type' => StandaloneRedis::class,
              'resourceable_id' => $database->id,
              'is_shared' => false,
          ]);
      
          EnvironmentVariable::create([
              'key' => 'REDIS_USERNAME',
              'value' => 'default',
              'resourceable_type' => StandaloneRedis::class,
              'resourceable_id' => $database->id,
              'is_shared' => false,
          ]);
      
          return $database;
      }
      
      function create_standalone_mongodb($environment_id, $destination_uuid, ?array $otherData = null): StandaloneMongodb
      {
          $destination = StandaloneDocker::where('uuid', $destination_uuid)->firstOrFail();
          $database = new StandaloneMongodb;
          $database->uuid = (new Cuid2);
          $database->name = 'mongodb-database-'.$database->uuid;
          $database->mongo_initdb_root_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->environment_id = $environment_id;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          return $database;
      }
      
      function create_standalone_mysql($environment_id, $destination_uuid, ?array $otherData = null): StandaloneMysql
      {
          $destination = StandaloneDocker::where('uuid', $destination_uuid)->firstOrFail();
          $database = new StandaloneMysql;
          $database->uuid = (new Cuid2);
          $database->name = 'mysql-database-'.$database->uuid;
          $database->mysql_root_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->mysql_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->environment_id = $environment_id;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          return $database;
      }
      
      function create_standalone_mariadb($environment_id, $destination_uuid, ?array $otherData = null): StandaloneMariadb
      {
          $destination = StandaloneDocker::where('uuid', $destination_uuid)->firstOrFail();
          $database = new StandaloneMariadb;
          $database->uuid = (new Cuid2);
          $database->name = 'mariadb-database-'.$database->uuid;
          $database->mariadb_root_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->mariadb_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->environment_id = $environment_id;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          return $database;
      }
      
      function create_standalone_keydb($environment_id, $destination_uuid, ?array $otherData = null): StandaloneKeydb
      {
          $destination = StandaloneDocker::where('uuid', $destination_uuid)->firstOrFail();
          $database = new StandaloneKeydb;
          $database->uuid = (new Cuid2);
          $database->name = 'keydb-database-'.$database->uuid;
          $database->keydb_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->environment_id = $environment_id;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          return $database;
      }
      
      function create_standalone_dragonfly($environment_id, $destination_uuid, ?array $otherData = null): StandaloneDragonfly
      {
          $destination = StandaloneDocker::where('uuid', $destination_uuid)->firstOrFail();
          $database = new StandaloneDragonfly;
          $database->uuid = (new Cuid2);
          $database->name = 'dragonfly-database-'.$database->uuid;
          $database->dragonfly_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->environment_id = $environment_id;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          return $database;
      }
      
      function create_standalone_clickhouse($environment_id, $destination_uuid, ?array $otherData = null): StandaloneClickhouse
      {
          $destination = StandaloneDocker::where('uuid', $destination_uuid)->firstOrFail();
          $database = new StandaloneClickhouse;
          $database->uuid = (new Cuid2);
          $database->name = 'clickhouse-database-'.$database->uuid;
          $database->clickhouse_admin_password = \Illuminate\Support\Str::password(length: 64, symbols: false);
          $database->environment_id = $environment_id;
          $database->destination_id = $destination->id;
          $database->destination_type = $destination->getMorphClass();
          if ($otherData) {
              $database->fill($otherData);
          }
          $database->save();
      
          return $database;
      }
      
      function deleteBackupsLocally(string|array|null $filenames, Server $server): void
      {
          if (empty($filenames)) {
              return;
          }
          if (is_string($filenames)) {
              $filenames = [$filenames];
          }
          $quotedFiles = array_map(fn ($file) => "\"$file\"", $filenames);
          instant_remote_process(['rm -f '.implode(' ', $quotedFiles)], $server, throwError: false);
      
          $foldersToCheck = collect($filenames)->map(fn ($file) => dirname($file))->unique();
          $foldersToCheck->each(fn ($folder) => deleteEmptyBackupFolder($folder, $server));
      }
      
      function deleteBackupsS3(string|array|null $filenames, S3Storage $s3): void
      {
          if (empty($filenames) || ! $s3) {
              return;
          }
          if (is_string($filenames)) {
              $filenames = [$filenames];
          }
      
          $disk = Storage::build([
              'driver' => 's3',
              'key' => $s3->key,
              'secret' => $s3->secret,
              'region' => $s3->region,
              'bucket' => $s3->bucket,
              'endpoint' => $s3->endpoint,
              'use_path_style_endpoint' => true,
              'aws_url' => $s3->awsUrl(),
          ]);
      
          $disk->delete($filenames);
      }
      
      function deleteEmptyBackupFolder($folderPath, Server $server): void
      {
          $escapedPath = escapeshellarg($folderPath);
          $escapedParentPath = escapeshellarg(dirname($folderPath));
      
          $checkEmpty = instant_remote_process(["[ -d $escapedPath ] && [ -z \"$(ls -A $escapedPath)\" ] && echo 'empty' || echo 'not empty'"], $server, throwError: false);
      
          if (trim($checkEmpty) === 'empty') {
              instant_remote_process(["rmdir $escapedPath"], $server, throwError: false);
              $checkParentEmpty = instant_remote_process(["[ -d $escapedParentPath ] && [ -z \"$(ls -A $escapedParentPath)\" ] && echo 'empty' || echo 'not empty'"], $server, throwError: false);
              if (trim($checkParentEmpty) === 'empty') {
                  instant_remote_process(["rmdir $escapedParentPath"], $server, throwError: false);
              }
          }
      }
      
      function removeOldBackups($backup): void
      {
          try {
              if ($backup->executions) {
                  // Delete old local backups (only if local backup is NOT disabled)
                  // Note: When disable_local_backup is enabled, each execution already marks its own
                  // local_storage_deleted status at the time of backup, so we don't need to retroactively
                  // update old executions
                  if (! $backup->disable_local_backup) {
                      $localBackupsToDelete = deleteOldBackupsLocally($backup);
                      if ($localBackupsToDelete->isNotEmpty()) {
                          $backup->executions()
                              ->whereIn('id', $localBackupsToDelete->pluck('id'))
                              ->update(['local_storage_deleted' => true]);
                      }
                  }
              }
      
              if ($backup->save_s3 && $backup->executions) {
                  $s3BackupsToDelete = deleteOldBackupsFromS3($backup);
                  if ($s3BackupsToDelete->isNotEmpty()) {
                      $backup->executions()
                          ->whereIn('id', $s3BackupsToDelete->pluck('id'))
                          ->update(['s3_storage_deleted' => true]);
                  }
              }
      
              // Delete execution records where all backup copies are gone
              // Case 1: Both local and S3 backups are deleted
              $backup->executions()
                  ->where('local_storage_deleted', true)
                  ->where('s3_storage_deleted', true)
                  ->delete();
      
              // Case 2: Local backup is deleted and S3 was never used (s3_uploaded is null)
              $backup->executions()
                  ->where('local_storage_deleted', true)
                  ->whereNull('s3_uploaded')
                  ->delete();
      
          } catch (\Exception $e) {
              throw $e;
          }
      }
      
      function deleteOldBackupsLocally($backup): Collection
      {
          if (! $backup || ! $backup->executions) {
              return collect();
          }
      
          $successfulBackups = $backup->executions()
              ->where('status', 'success')
              ->where('local_storage_deleted', false)
              ->orderBy('created_at', 'desc')
              ->get();
      
          if ($successfulBackups->isEmpty()) {
              return collect();
          }
      
          $retentionAmount = $backup->database_backup_retention_amount_locally;
          $retentionDays = $backup->database_backup_retention_days_locally;
          $maxStorageGB = $backup->database_backup_retention_max_storage_locally;
      
          if ($retentionAmount === 0 && $retentionDays === 0 && $maxStorageGB === 0) {
              return collect();
          }
      
          $backupsToDelete = collect();
      
          if ($retentionAmount > 0) {
              $byAmount = $successfulBackups->skip($retentionAmount);
              $backupsToDelete = $backupsToDelete->merge($byAmount);
          }
      
          if ($retentionDays > 0) {
              $oldestAllowedDate = $successfulBackups->first()->created_at->clone()->utc()->subDays($retentionDays);
              $oldBackups = $successfulBackups->filter(fn ($execution) => $execution->created_at->utc() < $oldestAllowedDate);
              $backupsToDelete = $backupsToDelete->merge($oldBackups);
          }
      
          if ($maxStorageGB > 0) {
              $maxStorageBytes = $maxStorageGB * pow(1024, 3);
              $totalSize = 0;
              $backupsOverLimit = collect();
      
              $backupsToCheck = $successfulBackups->skip(1);
      
              foreach ($backupsToCheck as $backupExecution) {
                  $totalSize += (int) $backupExecution->size;
                  if ($totalSize > $maxStorageBytes) {
                      $backupsOverLimit = $successfulBackups->filter(
                          fn ($b) => $b->created_at->utc() <= $backupExecution->created_at->utc()
                      )->skip(1);
                      break;
                  }
              }
      
              $backupsToDelete = $backupsToDelete->merge($backupsOverLimit);
          }
      
          $backupsToDelete = $backupsToDelete->unique('id');
          $processedBackups = collect();
      
          $server = null;
          if ($backup->database_type === \App\Models\ServiceDatabase::class) {
              $server = $backup->database->service->server;
          } else {
              $server = $backup->database->destination->server;
          }
      
          if (! $server) {
              return collect();
          }
      
          $filesToDelete = $backupsToDelete
              ->filter(fn ($execution) => ! empty($execution->filename))
              ->pluck('filename')
              ->all();
      
          if (! empty($filesToDelete)) {
              deleteBackupsLocally($filesToDelete, $server);
              $processedBackups = $backupsToDelete;
          }
      
          return $processedBackups;
      }
      
      function deleteOldBackupsFromS3($backup): Collection
      {
          if (! $backup || ! $backup->executions || ! $backup->s3) {
              return collect();
          }
      
          $successfulBackups = $backup->executions()
              ->where('status', 'success')
              ->where('s3_storage_deleted', false)
              ->orderBy('created_at', 'desc')
              ->get();
      
          if ($successfulBackups->isEmpty()) {
              return collect();
          }
      
          $retentionAmount = $backup->database_backup_retention_amount_s3;
          $retentionDays = $backup->database_backup_retention_days_s3;
          $maxStorageGB = $backup->database_backup_retention_max_storage_s3;
      
          if ($retentionAmount === 0 && $retentionDays === 0 && $maxStorageGB === 0) {
              return collect();
          }
      
          $backupsToDelete = collect();
      
          if ($retentionAmount > 0) {
              $byAmount = $successfulBackups->skip($retentionAmount);
              $backupsToDelete = $backupsToDelete->merge($byAmount);
          }
      
          if ($retentionDays > 0) {
              $oldestAllowedDate = $successfulBackups->first()->created_at->clone()->utc()->subDays($retentionDays);
              $oldBackups = $successfulBackups->filter(fn ($execution) => $execution->created_at->utc() < $oldestAllowedDate);
              $backupsToDelete = $backupsToDelete->merge($oldBackups);
          }
      
          if ($maxStorageGB > 0) {
              $maxStorageBytes = $maxStorageGB * pow(1024, 3);
              $totalSize = 0;
              $backupsOverLimit = collect();
      
              $backupsToCheck = $successfulBackups->skip(1);
      
              foreach ($backupsToCheck as $backupExecution) {
                  $totalSize += (int) $backupExecution->size;
                  if ($totalSize > $maxStorageBytes) {
                      $backupsOverLimit = $successfulBackups->filter(
                          fn ($b) => $b->created_at->utc() <= $backupExecution->created_at->utc()
                      )->skip(1);
                      break;
                  }
              }
      
              $backupsToDelete = $backupsToDelete->merge($backupsOverLimit);
          }
      
          $backupsToDelete = $backupsToDelete->unique('id');
          $processedBackups = collect();
      
          $filesToDelete = $backupsToDelete
              ->filter(fn ($execution) => ! empty($execution->filename))
              ->pluck('filename')
              ->all();
      
          if (! empty($filesToDelete)) {
              deleteBackupsS3($filesToDelete, $backup->s3);
              $processedBackups = $backupsToDelete;
          }
      
          return $processedBackups;
      }
      
      function isPublicPortAlreadyUsed(Server $server, int $port, ?string $id = null): bool
      {
          if ($id) {
              $foundDatabase = $server->databases()->where('public_port', $port)->where('is_public', true)->where('id', '!=', $id)->first();
          } else {
              $foundDatabase = $server->databases()->where('public_port', $port)->where('is_public', true)->first();
          }
          if ($foundDatabase) {
              return true;
          }
      
          return false;
      }
      
      
      ================================================
      FILE: bootstrap/helpers/docker.php
      ================================================
      isSwarm()) {
              $containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --format '{{json .}}' "], $server);
              $containers = format_docker_command_output_to_json($containers);
      
              $containers = $containers->map(function ($container) use ($pullRequestId, $includePullrequests) {
                  $labels = data_get($container, 'Labels');
                  $containerName = data_get($container, 'Names');
                  $hasPrLabel = str($labels)->contains('coolify.pullRequestId=');
                  $prLabelValue = null;
      
                  if ($hasPrLabel) {
                      preg_match('/coolify\.pullRequestId=(\d+)/', $labels, $matches);
                      $prLabelValue = $matches[1] ?? null;
                  }
      
                  // Treat pullRequestId=0 or missing label as base deployment (convention: 0 = no PR)
                  $isBaseDeploy = ! $hasPrLabel || (int) $prLabelValue === 0;
      
                  // If we're looking for a specific PR and this is a base deployment, exclude it
                  if ($pullRequestId !== null && $pullRequestId !== 0 && $isBaseDeploy) {
                      return null;
                  }
      
                  // If this is a base deployment, include it when not filtering for PRs
                  if ($isBaseDeploy) {
                      return $container;
                  }
      
                  if ($includePullrequests) {
                      return $container;
                  }
                  if ($pullRequestId !== null && $pullRequestId !== 0 && str($labels)->contains("coolify.pullRequestId={$pullRequestId}")) {
                      return $container;
                  }
      
                  return null;
              });
      
              $filtered = $containers->filter();
      
              return $filtered;
          }
      
          return $containers;
      }
      
      function getCurrentServiceContainerStatus(Server $server, int $id): Collection
      {
          $containers = collect([]);
          if (! $server->isSwarm()) {
              $containers = instant_remote_process(["docker ps -a --filter='label=coolify.serviceId={$id}' --format '{{json .}}' "], $server);
              $containers = format_docker_command_output_to_json($containers);
      
              return $containers->filter();
          }
      
          return $containers;
      }
      
      function format_docker_command_output_to_json($rawOutput): Collection
      {
          $outputLines = explode(PHP_EOL, $rawOutput);
          if (count($outputLines) === 1) {
              $outputLines = collect($outputLines[0]);
          } else {
              $outputLines = collect($outputLines);
          }
      
          try {
              return $outputLines
                  ->reject(fn ($line) => empty($line))
                  ->map(fn ($outputLine) => json_decode($outputLine, true, flags: JSON_THROW_ON_ERROR));
          } catch (\Throwable) {
              return collect([]);
          }
      }
      
      function format_docker_labels_to_json(string|array $rawOutput): Collection
      {
          if (is_array($rawOutput)) {
              return collect($rawOutput);
          }
          $outputLines = explode(PHP_EOL, $rawOutput);
      
          return collect($outputLines)
              ->reject(fn ($line) => empty($line))
              ->map(function ($outputLine) {
                  $outputArray = explode(',', $outputLine);
      
                  return collect($outputArray)
                      ->map(function ($outputLine) {
                          return explode('=', $outputLine);
                      })
                      ->mapWithKeys(function ($outputLine) {
                          return [$outputLine[0] => $outputLine[1]];
                      });
              })[0];
      }
      
      function format_docker_envs_to_json($rawOutput)
      {
          try {
              $outputLines = json_decode($rawOutput, true, flags: JSON_THROW_ON_ERROR);
      
              return collect(data_get($outputLines[0], 'Config.Env', []))->mapWithKeys(function ($env) {
                  $env = explode('=', $env, 2);
      
                  return [$env[0] => $env[1]];
              });
          } catch (\Throwable) {
              return collect([]);
          }
      }
      function checkMinimumDockerEngineVersion($dockerVersion)
      {
          $majorDockerVersion = (int) str($dockerVersion)->before('.')->value();
          $requiredDockerVersion = (int) str(config('constants.docker.minimum_required_version'))->before('.')->value();
          if ($majorDockerVersion < $requiredDockerVersion) {
              $dockerVersion = null;
          }
      
          return $dockerVersion;
      }
      function executeInDocker(string $containerId, string $command)
      {
          $escapedCommand = str_replace("'", "'\\''", $command);
      
          return "docker exec {$containerId} bash -c '{$escapedCommand}'";
      }
      
      function getContainerStatus(Server $server, string $container_id, bool $all_data = false, bool $throwError = false)
      {
          if ($server->isSwarm()) {
              $container = instant_remote_process(["docker service ls --filter 'name={$container_id}' --format '{{json .}}' "], $server, $throwError);
          } else {
              $container = instant_remote_process(["docker inspect --format '{{json .}}' {$container_id}"], $server, $throwError);
          }
          if (! $container) {
              return 'exited';
          }
          $container = format_docker_command_output_to_json($container);
          if ($container->isEmpty()) {
              return 'exited';
          }
          if ($all_data) {
              return $container[0];
          }
          if ($server->isSwarm()) {
              $replicas = data_get($container[0], 'Replicas');
              $replicas = explode('/', $replicas);
              $active = (int) $replicas[0];
              $total = (int) $replicas[1];
              if ($active === $total) {
                  return 'running';
              } else {
                  return 'starting';
              }
          } else {
              return data_get($container[0], 'State.Status', 'exited');
          }
      }
      
      function generateApplicationContainerName(Application $application, $pull_request_id = 0)
      {
          // TODO: refactor generateApplicationContainerName, we do not need $application and $pull_request_id
      
          $consistent_container_name = $application->settings->is_consistent_container_name_enabled;
          $now = now()->format('Hisu');
          if ($pull_request_id !== 0 && $pull_request_id !== null) {
              return $application->uuid.'-pr-'.$pull_request_id;
          } else {
              if ($consistent_container_name) {
                  return $application->uuid;
              }
      
              return $application->uuid.'-'.$now;
          }
      }
      function get_port_from_dockerfile($dockerfile): ?int
      {
          $dockerfile_array = explode("\n", $dockerfile);
          $found_exposed_port = null;
          foreach ($dockerfile_array as $line) {
              $line_str = str($line)->trim();
              if ($line_str->startsWith('EXPOSE')) {
                  $found_exposed_port = $line_str->replace('EXPOSE', '')->trim();
                  break;
              }
          }
          if ($found_exposed_port) {
              return (int) $found_exposed_port->value();
          }
      
          return null;
      }
      
      function defaultDatabaseLabels($database)
      {
          $labels = collect([]);
          $labels->push('coolify.managed=true');
          $labels->push('coolify.type=database');
          $labels->push('coolify.databaseId='.$database->id);
          $labels->push('coolify.resourceName='.Str::slug($database->name));
          $labels->push('coolify.serviceName='.Str::slug($database->name));
          $labels->push('coolify.projectName='.Str::slug($database->project()->name));
          $labels->push('coolify.environmentName='.Str::slug($database->environment->name));
          $labels->push('coolify.database.subType='.$database->type());
      
          return $labels;
      }
      
      function defaultLabels($id, $name, string $projectName, string $resourceName, string $environment, $pull_request_id = 0, string $type = 'application', $subType = null, $subId = null, $subName = null)
      {
          $labels = collect([]);
          $labels->push('coolify.managed=true');
          $labels->push('coolify.version='.config('constants.coolify.version'));
          $labels->push('coolify.'.$type.'Id='.$id);
          $labels->push("coolify.type=$type");
          $labels->push('coolify.name='.Str::slug($name));
          $labels->push('coolify.resourceName='.Str::slug($resourceName));
          $labels->push('coolify.projectName='.Str::slug($projectName));
          $labels->push('coolify.serviceName='.Str::slug($subName ?? $resourceName));
          $labels->push('coolify.environmentName='.Str::slug($environment));
      
          $labels->push('coolify.pullRequestId='.$pull_request_id);
          if ($type === 'service') {
              $subId && $labels->push('coolify.service.subId='.$subId);
              $subType && $labels->push('coolify.service.subType='.$subType);
              $subName && $labels->push('coolify.service.subName='.Str::slug($subName));
          }
      
          return $labels;
      }
      
      function generateServiceSpecificFqdns(ServiceApplication|Application $resource)
      {
          if ($resource->getMorphClass() === \App\Models\ServiceApplication::class) {
              $uuid = data_get($resource, 'uuid');
              $server = data_get($resource, 'service.server');
              $environment_variables = data_get($resource, 'service.environment_variables');
              $type = $resource->serviceType();
          } elseif ($resource->getMorphClass() === \App\Models\Application::class) {
              $uuid = data_get($resource, 'uuid');
              $server = data_get($resource, 'destination.server');
              $environment_variables = data_get($resource, 'environment_variables');
              $type = $resource->serviceType();
          }
          if (is_null($server) || is_null($type)) {
              return collect([]);
          }
          $variables = collect($environment_variables);
          $payload = collect([]);
          switch ($type) {
              case $type?->contains('minio'):
                  $MINIO_BROWSER_REDIRECT_URL = $variables->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first();
                  $MINIO_SERVER_URL = $variables->where('key', 'MINIO_SERVER_URL')->first();
      
                  if (is_null($MINIO_BROWSER_REDIRECT_URL) || is_null($MINIO_SERVER_URL)) {
                      return collect([]);
                  }
      
                  if (str($MINIO_BROWSER_REDIRECT_URL->value ?? '')->isEmpty()) {
                      $MINIO_BROWSER_REDIRECT_URL->update([
                          'value' => generateUrl(server: $server, random: 'console-'.$uuid, forceHttps: true),
                      ]);
                  }
                  if (str($MINIO_SERVER_URL->value ?? '')->isEmpty()) {
                      $MINIO_SERVER_URL->update([
                          'value' => generateUrl(server: $server, random: 'minio-'.$uuid, forceHttps: true),
                      ]);
                  }
                  $payload = collect([
                      $MINIO_BROWSER_REDIRECT_URL->value.':9001',
                      $MINIO_SERVER_URL->value.':9000',
                  ]);
                  break;
              case $type?->contains('logto'):
                  $LOGTO_ENDPOINT = $variables->where('key', 'LOGTO_ENDPOINT')->first();
                  $LOGTO_ADMIN_ENDPOINT = $variables->where('key', 'LOGTO_ADMIN_ENDPOINT')->first();
      
                  if (is_null($LOGTO_ENDPOINT) || is_null($LOGTO_ADMIN_ENDPOINT)) {
                      return collect([]);
                  }
      
                  if (str($LOGTO_ENDPOINT->value ?? '')->isEmpty()) {
                      $LOGTO_ENDPOINT->update([
                          'value' => generateUrl(server: $server, random: 'logto-'.$uuid),
                      ]);
                  }
                  if (str($LOGTO_ADMIN_ENDPOINT->value ?? '')->isEmpty()) {
                      $LOGTO_ADMIN_ENDPOINT->update([
                          'value' => generateUrl(server: $server, random: 'logto-admin-'.$uuid),
                      ]);
                  }
                  $payload = collect([
                      $LOGTO_ENDPOINT->value.':3001',
                      $LOGTO_ADMIN_ENDPOINT->value.':3002',
                  ]);
                  break;
              case $type?->contains('garage'):
                  $GARAGE_S3_API_URL = $variables->where('key', 'GARAGE_S3_API_URL')->first();
                  $GARAGE_WEB_URL = $variables->where('key', 'GARAGE_WEB_URL')->first();
                  $GARAGE_ADMIN_URL = $variables->where('key', 'GARAGE_ADMIN_URL')->first();
      
                  if (is_null($GARAGE_S3_API_URL) || is_null($GARAGE_WEB_URL) || is_null($GARAGE_ADMIN_URL)) {
                      return collect([]);
                  }
      
                  if (str($GARAGE_S3_API_URL->value ?? '')->isEmpty()) {
                      $GARAGE_S3_API_URL->update([
                          'value' => generateUrl(server: $server, random: 's3-'.$uuid, forceHttps: true),
                      ]);
                  }
                  if (str($GARAGE_WEB_URL->value ?? '')->isEmpty()) {
                      $GARAGE_WEB_URL->update([
                          'value' => generateUrl(server: $server, random: 'web-'.$uuid, forceHttps: true),
                      ]);
                  }
                  if (str($GARAGE_ADMIN_URL->value ?? '')->isEmpty()) {
                      $GARAGE_ADMIN_URL->update([
                          'value' => generateUrl(server: $server, random: 'admin-'.$uuid, forceHttps: true),
                      ]);
                  }
                  $payload = collect([
                      $GARAGE_S3_API_URL->value.':3900',
                      $GARAGE_WEB_URL->value.':3902',
                      $GARAGE_ADMIN_URL->value.':3903',
                  ]);
                  break;
          }
      
          return $payload;
      }
      
      function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null, ?string $image = null, string $redirect_direction = 'both', ?string $predefinedPort = null, bool $is_http_basic_auth_enabled = false, ?string $http_basic_auth_username = null, ?string $http_basic_auth_password = null)
      {
          $labels = collect([]);
          if ($serviceLabels) {
              $labels->push("caddy_ingress_network={$uuid}");
          } else {
              $labels->push("caddy_ingress_network={$network}");
          }
      
          $is_http_basic_auth_enabled = $is_http_basic_auth_enabled && $http_basic_auth_username !== null && $http_basic_auth_password !== null;
          if ($is_http_basic_auth_enabled) {
              $hashedPassword = password_hash($http_basic_auth_password, PASSWORD_BCRYPT, ['cost' => 10]);
          }
      
          foreach ($domains as $loop => $domain) {
              $url = Url::fromString($domain);
              $host = $url->getHost();
              $path = $url->getPath();
              $host_without_www = str($host)->replace('www.', '');
              $schema = $url->getScheme();
              $port = $url->getPort();
              $handle = 'handle_path';
              if (! $is_stripprefix_enabled) {
                  $handle = 'handle';
              }
              if (is_null($port) && ! is_null($onlyPort)) {
                  $port = $onlyPort;
              }
              if (is_null($port) && $predefinedPort) {
                  $port = $predefinedPort;
              }
              $labels->push("caddy_{$loop}={$schema}://{$host}");
              $labels->push("caddy_{$loop}.header=-Server");
              $labels->push("caddy_{$loop}.try_files={path} /index.html /index.php");
      
              if ($port) {
                  $labels->push("caddy_{$loop}.{$handle}.{$loop}_reverse_proxy={{upstreams $port}}");
              } else {
                  $labels->push("caddy_{$loop}.{$handle}.{$loop}_reverse_proxy={{upstreams}}");
              }
              $labels->push("caddy_{$loop}.{$handle}={$path}*");
              if ($is_gzip_enabled) {
                  $labels->push("caddy_{$loop}.encode=zstd gzip");
              }
              if ($redirect_direction === 'www' && ! str($host)->startsWith('www.')) {
                  $labels->push("caddy_{$loop}.redir={$schema}://www.{$host}{uri}");
              }
              if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
                  $labels->push("caddy_{$loop}.redir={$schema}://{$host_without_www}{uri}");
              }
              if ($is_http_basic_auth_enabled) {
                  $labels->push("caddy_{$loop}.basicauth.{$http_basic_auth_username}=\"{$hashedPassword}\"");
              }
          }
      
          return $labels->sort();
      }
      
      function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null, bool $generate_unique_uuid = false, ?string $image = null, string $redirect_direction = 'both', bool $is_http_basic_auth_enabled = false, ?string $http_basic_auth_username = null, ?string $http_basic_auth_password = null)
      {
          $labels = collect([]);
          $labels->push('traefik.enable=true');
          if ($is_gzip_enabled) {
              $labels->push('traefik.http.middlewares.gzip.compress=true');
          }
          $labels->push('traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https');
      
          $is_http_basic_auth_enabled = $is_http_basic_auth_enabled && $http_basic_auth_username !== null && $http_basic_auth_password !== null;
          $http_basic_auth_label = "http-basic-auth-{$uuid}";
          if ($is_http_basic_auth_enabled) {
              $hashedPassword = password_hash($http_basic_auth_password, PASSWORD_BCRYPT, ['cost' => 10]);
          }
      
          if ($is_http_basic_auth_enabled) {
              $labels->push("traefik.http.middlewares.{$http_basic_auth_label}.basicauth.users={$http_basic_auth_username}:{$hashedPassword}");
          }
      
          $middlewares_from_labels = collect([]);
      
          if ($serviceLabels) {
              $middlewares_from_labels = $serviceLabels->map(function ($item) {
                  // Handle array values from YAML parsing (e.g., "traefik.enable: true" becomes an array)
                  if (is_array($item)) {
                      // Convert array to string format "key=value"
                      $key = collect($item)->keys()->first();
                      $value = collect($item)->values()->first();
                      $item = "$key=$value";
                  }
                  if (! is_string($item)) {
                      return null;
                  }
                  if (preg_match('/traefik\.http\.middlewares\.(.*?)(\.|$)/', $item, $matches)) {
                      return $matches[1];
                  }
                  if (preg_match('/coolify\.traefik\.middlewares=(.*)/', $item, $matches)) {
                      return explode(',', $matches[1]);
                  }
      
                  return null;
              })->flatten()
                  ->filter()
                  ->unique();
          }
          foreach ($domains as $loop => $domain) {
              try {
                  if ($generate_unique_uuid) {
                      $uuid = new Cuid2;
                  }
      
                  $url = Url::fromString($domain);
                  $host = $url->getHost();
                  $path = $url->getPath();
                  $schema = $url->getScheme();
                  $port = $url->getPort();
                  if (is_null($port) && ! is_null($onlyPort)) {
                      $port = $onlyPort;
                  }
                  $http_label = "http-{$loop}-{$uuid}";
                  $https_label = "https-{$loop}-{$uuid}";
                  if ($service_name) {
                      $http_label = "http-{$loop}-{$uuid}-{$service_name}";
                      $https_label = "https-{$loop}-{$uuid}-{$service_name}";
                  }
                  if (str($image)->contains('ghost')) {
                      $labels->push("traefik.http.middlewares.redir-ghost-{$uuid}.redirectregex.regex=^{$path}/(.*)");
                      $labels->push("traefik.http.middlewares.redir-ghost-{$uuid}.redirectregex.replacement=/$1");
                      $labels->push("caddy_{$loop}.handle_path.{$loop}_redir-ghost-{$uuid}.handler=rewrite");
                      $labels->push("caddy_{$loop}.handle_path.{$loop}_redir-ghost-{$uuid}.rewrite.regexp=^{$path}/(.*)");
                      $labels->push("caddy_{$loop}.handle_path.{$loop}_redir-ghost-{$uuid}.rewrite.replacement=/$1");
                  }
      
                  $to_www_name = "{$loop}-{$uuid}-to-www";
                  $to_non_www_name = "{$loop}-{$uuid}-to-non-www";
                  $redirect_to_non_www = [
                      "traefik.http.middlewares.{$to_non_www_name}.redirectregex.regex=^(http|https)://www\.(.+)",
                      "traefik.http.middlewares.{$to_non_www_name}.redirectregex.replacement=\${1}://\${2}",
                      "traefik.http.middlewares.{$to_non_www_name}.redirectregex.permanent=false",
                  ];
                  $redirect_to_www = [
                      "traefik.http.middlewares.{$to_www_name}.redirectregex.regex=^(http|https)://(?:www\.)?(.+)",
                      "traefik.http.middlewares.{$to_www_name}.redirectregex.replacement=\${1}://www.\${2}",
                      "traefik.http.middlewares.{$to_www_name}.redirectregex.permanent=false",
                  ];
                  if ($schema === 'https') {
                      // Set labels for https
                      $labels->push("traefik.http.routers.{$https_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
                      $labels->push("traefik.http.routers.{$https_label}.entryPoints=https");
                      if ($port) {
                          $labels->push("traefik.http.routers.{$https_label}.service={$https_label}");
                          $labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port");
                      }
                      if ($path !== '/') {
                          // Middleware handling
                          $middlewares = collect([]);
                          if ($is_stripprefix_enabled && ! str($image)->contains('ghost')) {
                              $labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}");
                              $middlewares->push("{$https_label}-stripprefix");
                          }
                          if ($is_gzip_enabled) {
                              $middlewares->push('gzip');
                          }
                          if (str($image)->contains('ghost')) {
                              $middlewares->push("redir-ghost-{$uuid}");
                          }
                          if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_non_www);
                              $middlewares->push($to_non_www_name);
                          }
                          if ($redirect_direction === 'www' && ! str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_www);
                              $middlewares->push($to_www_name);
                          }
                          if ($is_http_basic_auth_enabled) {
                              $middlewares->push($http_basic_auth_label);
                          }
                          $middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
                              $middlewares->push($middleware_name);
                          });
                          if ($middlewares->isNotEmpty()) {
                              $middlewares = $middlewares->join(',');
                              $labels->push("traefik.http.routers.{$https_label}.middlewares={$middlewares}");
                          }
                      } else {
                          $middlewares = collect([]);
                          if ($is_gzip_enabled) {
                              $middlewares->push('gzip');
                          }
                          if (str($image)->contains('ghost')) {
                              $middlewares->push("redir-ghost-{$uuid}");
                          }
                          if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_non_www);
                              $middlewares->push($to_non_www_name);
                          }
                          if ($redirect_direction === 'www' && ! str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_www);
                              $middlewares->push($to_www_name);
                          }
                          if ($is_http_basic_auth_enabled) {
                              $middlewares->push($http_basic_auth_label);
                          }
                          $middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
                              $middlewares->push($middleware_name);
                          });
                          if ($middlewares->isNotEmpty()) {
                              $middlewares = $middlewares->join(',');
                              $labels->push("traefik.http.routers.{$https_label}.middlewares={$middlewares}");
                          }
                      }
                      $labels->push("traefik.http.routers.{$https_label}.tls=true");
                      $labels->push("traefik.http.routers.{$https_label}.tls.certresolver=letsencrypt");
      
                      // Set labels for http (redirect to https)
                      $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
                      $labels->push("traefik.http.routers.{$http_label}.entryPoints=http");
                      if ($port) {
                          $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port");
                          $labels->push("traefik.http.routers.{$http_label}.service={$http_label}");
                      }
                      if ($is_force_https_enabled) {
                          $labels->push("traefik.http.routers.{$http_label}.middlewares=redirect-to-https");
                      }
                  } else {
                      // Set labels for http
                      $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
                      $labels->push("traefik.http.routers.{$http_label}.entryPoints=http");
                      if ($port) {
                          $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port");
                          $labels->push("traefik.http.routers.{$http_label}.service={$http_label}");
                      }
                      if ($path !== '/') {
                          $middlewares = collect([]);
                          if ($is_stripprefix_enabled && ! str($image)->contains('ghost')) {
                              $labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}");
                              $middlewares->push("{$http_label}-stripprefix");
                          }
                          if ($is_gzip_enabled) {
                              $middlewares->push('gzip');
                          }
                          if (str($image)->contains('ghost')) {
                              $middlewares->push("redir-ghost-{$uuid}");
                          }
                          if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_non_www);
                              $middlewares->push($to_non_www_name);
                          }
                          if ($redirect_direction === 'www' && ! str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_www);
                              $middlewares->push($to_www_name);
                          }
                          if ($is_http_basic_auth_enabled) {
                              $middlewares->push($http_basic_auth_label);
                          }
                          $middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
                              $middlewares->push($middleware_name);
                          });
                          if ($middlewares->isNotEmpty()) {
                              $middlewares = $middlewares->join(',');
                              $labels->push("traefik.http.routers.{$http_label}.middlewares={$middlewares}");
                          }
                      } else {
                          $middlewares = collect([]);
                          if ($is_gzip_enabled) {
                              $middlewares->push('gzip');
                          }
                          if (str($image)->contains('ghost')) {
                              $middlewares->push("redir-ghost-{$uuid}");
                          }
                          if ($redirect_direction === 'non-www' && str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_non_www);
                              $middlewares->push($to_non_www_name);
                          }
                          if ($redirect_direction === 'www' && ! str($host)->startsWith('www.')) {
                              $labels = $labels->merge($redirect_to_www);
                              $middlewares->push($to_www_name);
                          }
                          if ($is_http_basic_auth_enabled) {
                              $middlewares->push($http_basic_auth_label);
                          }
                          $middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
                              $middlewares->push($middleware_name);
                          });
                          if ($middlewares->isNotEmpty()) {
                              $middlewares = $middlewares->join(',');
                              $labels->push("traefik.http.routers.{$http_label}.middlewares={$middlewares}");
                          }
                      }
                  }
              } catch (\Throwable) {
                  continue;
              }
          }
      
          return $labels->sort();
      }
      function generateLabelsApplication(Application $application, ?ApplicationPreview $preview = null): array
      {
          $ports = $application->settings->is_static ? [80] : $application->ports_exposes_array;
          $onlyPort = null;
          if (count($ports) > 0) {
              $onlyPort = $ports[0];
          }
          $pull_request_id = data_get($preview, 'pull_request_id', 0);
          $appUuid = $application->uuid;
          if ($pull_request_id !== 0) {
              $appUuid = $appUuid.'-pr-'.$pull_request_id;
          }
          $labels = collect([]);
          if ($pull_request_id === 0) {
              if ($application->fqdn) {
                  $domains = str(data_get($application, 'fqdn'))->explode(',');
                  $shouldGenerateLabelsExactly = $application->destination->server->settings->generate_exact_labels;
                  if ($shouldGenerateLabelsExactly) {
                      switch ($application->destination->server->proxyType()) {
                          case ProxyTypes::TRAEFIK->value:
                              $labels = $labels->merge(fqdnLabelsForTraefik(
                                  uuid: $appUuid,
                                  domains: $domains,
                                  onlyPort: $onlyPort,
                                  is_force_https_enabled: $application->isForceHttpsEnabled(),
                                  is_gzip_enabled: $application->isGzipEnabled(),
                                  is_stripprefix_enabled: $application->isStripprefixEnabled(),
                                  redirect_direction: $application->redirect,
                                  is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                                  http_basic_auth_username: $application->http_basic_auth_username,
                                  http_basic_auth_password: $application->http_basic_auth_password,
                              ));
                              break;
                          case ProxyTypes::CADDY->value:
                              $labels = $labels->merge(fqdnLabelsForCaddy(
                                  network: $application->destination->network,
                                  uuid: $appUuid,
                                  domains: $domains,
                                  onlyPort: $onlyPort,
                                  is_force_https_enabled: $application->isForceHttpsEnabled(),
                                  is_gzip_enabled: $application->isGzipEnabled(),
                                  is_stripprefix_enabled: $application->isStripprefixEnabled(),
                                  redirect_direction: $application->redirect,
                                  is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                                  http_basic_auth_username: $application->http_basic_auth_username,
                                  http_basic_auth_password: $application->http_basic_auth_password,
                              ));
                              break;
                      }
                  } else {
                      $labels = $labels->merge(fqdnLabelsForTraefik(
                          uuid: $appUuid,
                          domains: $domains,
                          onlyPort: $onlyPort,
                          is_force_https_enabled: $application->isForceHttpsEnabled(),
                          is_gzip_enabled: $application->isGzipEnabled(),
                          is_stripprefix_enabled: $application->isStripprefixEnabled(),
                          redirect_direction: $application->redirect,
                          is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                          http_basic_auth_username: $application->http_basic_auth_username,
                          http_basic_auth_password: $application->http_basic_auth_password,
                      ));
                      $labels = $labels->merge(fqdnLabelsForCaddy(
                          network: $application->destination->network,
                          uuid: $appUuid,
                          domains: $domains,
                          onlyPort: $onlyPort,
                          is_force_https_enabled: $application->isForceHttpsEnabled(),
                          is_gzip_enabled: $application->isGzipEnabled(),
                          is_stripprefix_enabled: $application->isStripprefixEnabled(),
                          redirect_direction: $application->redirect,
                          is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                          http_basic_auth_username: $application->http_basic_auth_username,
                          http_basic_auth_password: $application->http_basic_auth_password,
                      ));
                  }
              }
          } else {
              if (data_get($preview, 'fqdn')) {
                  $domains = str(data_get($preview, 'fqdn'))->explode(',');
              } else {
                  $domains = collect([]);
              }
              $shouldGenerateLabelsExactly = $application->destination->server->settings->generate_exact_labels;
              if ($shouldGenerateLabelsExactly) {
                  switch ($application->destination->server->proxyType()) {
                      case ProxyTypes::TRAEFIK->value:
                          $labels = $labels->merge(fqdnLabelsForTraefik(
                              uuid: $appUuid,
                              domains: $domains,
                              onlyPort: $onlyPort,
                              is_force_https_enabled: $application->isForceHttpsEnabled(),
                              is_gzip_enabled: $application->isGzipEnabled(),
                              is_stripprefix_enabled: $application->isStripprefixEnabled(),
                              is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                              http_basic_auth_username: $application->http_basic_auth_username,
                              http_basic_auth_password: $application->http_basic_auth_password,
                          ));
                          break;
                      case ProxyTypes::CADDY->value:
                          $labels = $labels->merge(fqdnLabelsForCaddy(
                              network: $application->destination->network,
                              uuid: $appUuid,
                              domains: $domains,
                              onlyPort: $onlyPort,
                              is_force_https_enabled: $application->isForceHttpsEnabled(),
                              is_gzip_enabled: $application->isGzipEnabled(),
                              is_stripprefix_enabled: $application->isStripprefixEnabled(),
                              is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                              http_basic_auth_username: $application->http_basic_auth_username,
                              http_basic_auth_password: $application->http_basic_auth_password,
                          ));
                          break;
                  }
              } else {
                  $labels = $labels->merge(fqdnLabelsForTraefik(
                      uuid: $appUuid,
                      domains: $domains,
                      onlyPort: $onlyPort,
                      is_force_https_enabled: $application->isForceHttpsEnabled(),
                      is_gzip_enabled: $application->isGzipEnabled(),
                      is_stripprefix_enabled: $application->isStripprefixEnabled(),
                      is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                      http_basic_auth_username: $application->http_basic_auth_username,
                      http_basic_auth_password: $application->http_basic_auth_password,
                  ));
                  $labels = $labels->merge(fqdnLabelsForCaddy(
                      network: $application->destination->network,
                      uuid: $appUuid,
                      domains: $domains,
                      onlyPort: $onlyPort,
                      is_force_https_enabled: $application->isForceHttpsEnabled(),
                      is_gzip_enabled: $application->isGzipEnabled(),
                      is_stripprefix_enabled: $application->isStripprefixEnabled(),
                      is_http_basic_auth_enabled: $application->is_http_basic_auth_enabled,
                      http_basic_auth_username: $application->http_basic_auth_username,
                      http_basic_auth_password: $application->http_basic_auth_password,
                  ));
              }
          }
      
          return $labels->all();
      }
      
      function isDatabaseImage(?string $image = null, ?array $serviceConfig = null)
      {
          if (is_null($image)) {
              return false;
          }
      
          $image = str($image);
          if ($image->contains(':')) {
              $image = str($image);
          } else {
              $image = str($image)->append(':latest');
          }
          $imageName = $image->before(':');
      
          // Extract base image name (ignore registry prefix)
          // Examples:
          //   docker.io/library/postgres -> postgres
          //   ghcr.io/postgrest/postgrest -> postgrest
          //   postgres -> postgres
          //   postgrest/postgrest -> postgrest
          $baseImageName = $imageName;
          if (str($imageName)->contains('/')) {
              $baseImageName = str($imageName)->afterLast('/');
          }
      
          // Check if base image name exactly matches a known database image
          $isKnownDatabase = false;
          foreach (DATABASE_DOCKER_IMAGES as $database_docker_image) {
              // Extract base name from database pattern for comparison
              $databaseBaseName = str($database_docker_image)->contains('/')
                  ? str($database_docker_image)->afterLast('/')
                  : $database_docker_image;
      
              if ($baseImageName == $databaseBaseName) {
                  $isKnownDatabase = true;
                  break;
              }
          }
      
          // If no database pattern found, it's definitely not a database
          if (! $isKnownDatabase) {
              return false;
          }
      
          // If we have service configuration, use additional context to make better decisions
          if (! is_null($serviceConfig)) {
              return isDatabaseImageWithContext($imageName, $serviceConfig);
          }
      
          // Fallback to original behavior for backward compatibility
          return $isKnownDatabase;
      }
      
      function isDatabaseImageWithContext(string $imageName, array $serviceConfig): bool
      {
          // Known application images that contain database names but are not databases
          $knownApplicationPatterns = [
              // SuperTokens authentication
              'supertokens/supertokens-mysql',
              'supertokens/supertokens-postgresql',
              'supertokens/supertokens-mongodb',
              'registry.supertokens.io/supertokens/supertokens-mysql',
              'registry.supertokens.io/supertokens/supertokens-postgresql',
              'registry.supertokens.io/supertokens/supertokens-mongodb',
              'registry.supertokens.io/supertokens',
      
              // Analytics and BI tools
              'metabase/metabase', // Uses databases but is not a database
              'amancevice/superset', // Uses databases but is not a database
              'nocodb/nocodb', // Uses databases but is not a database
              'ghcr.io/umami-software/umami', // Web analytics with postgresql variant
      
              // Secret management
              'infisical/infisical', // Secret management with postgres variant
      
              // Development tools
              'postgrest/postgrest', // REST API for PostgreSQL
              'supabase/postgres-meta', // PostgreSQL metadata API
              'bluewaveuptime/uptime_redis', // Uptime monitoring with Redis
          ];
      
          foreach ($knownApplicationPatterns as $pattern) {
              if (str($imageName)->contains($pattern)) {
                  return false;
              }
          }
      
          // Check for database-like ports (common database ports indicate it's likely a database)
          $databasePorts = ['3306', '5432', '27017', '6379', '8086', '9200', '7687', '8123'];
          $ports = data_get($serviceConfig, 'ports', []);
          $hasStandardDbPort = false;
      
          if (is_array($ports)) {
              foreach ($ports as $port) {
                  $portStr = is_string($port) ? $port : (string) $port;
                  foreach ($databasePorts as $dbPort) {
                      if (str($portStr)->contains($dbPort)) {
                          $hasStandardDbPort = true;
                          break 2;
                      }
                  }
              }
          }
      
          // Check environment variables for database-specific patterns
          $environment = data_get($serviceConfig, 'environment', []);
          $hasDbEnvVars = false;
          $hasAppEnvVars = false;
      
          if (is_array($environment)) {
              foreach ($environment as $env) {
                  $envStr = is_string($env) ? $env : (string) $env;
                  $envUpper = strtoupper($envStr);
      
                  // Database-specific environment variables
                  if (str($envUpper)->contains(['MYSQL_ROOT_PASSWORD', 'POSTGRES_PASSWORD', 'MONGO_INITDB_ROOT_PASSWORD', 'REDIS_PASSWORD'])) {
                      $hasDbEnvVars = true;
                  }
      
                  // Application-specific environment variables
                  if (str($envUpper)->contains(['SERVICE_FQDN', 'API_KEYS', 'APP_', 'APPLICATION_'])) {
                      $hasAppEnvVars = true;
                  }
              }
          }
      
          // Check healthcheck patterns
          $healthcheck = data_get($serviceConfig, 'healthcheck.test', []);
          $hasDbHealthcheck = false;
          $hasAppHealthcheck = false;
      
          if (is_array($healthcheck)) {
              $healthcheckStr = implode(' ', $healthcheck);
          } else {
              $healthcheckStr = is_string($healthcheck) ? $healthcheck : '';
          }
      
          if (! empty($healthcheckStr)) {
              $healthcheckUpper = strtoupper($healthcheckStr);
      
              // Database-specific healthcheck patterns
              if (str($healthcheckUpper)->contains(['PG_ISREADY', 'MYSQLADMIN PING', 'MONGO', 'REDIS-CLI PING'])) {
                  $hasDbHealthcheck = true;
              }
      
              // Application-specific healthcheck patterns (HTTP endpoints)
              if (str($healthcheckUpper)->contains(['CURL', 'WGET', 'HTTP://', 'HTTPS://', '/HEALTH', '/API/', '/HELLO'])) {
                  $hasAppHealthcheck = true;
              }
          }
      
          // Check if service depends on other database services
          $dependsOn = data_get($serviceConfig, 'depends_on', []);
          $dependsOnDatabases = false;
      
          if (is_array($dependsOn)) {
              foreach ($dependsOn as $serviceName => $config) {
                  $serviceNameStr = is_string($serviceName) ? $serviceName : (string) $serviceName;
                  if (str($serviceNameStr)->contains(['mysql', 'postgres', 'mongo', 'redis', 'mariadb'])) {
                      $dependsOnDatabases = true;
                      break;
                  }
              }
          }
      
          // Decision logic:
          // 1. If it has app-specific patterns and depends on databases, it's likely an application
          if ($hasAppEnvVars && $dependsOnDatabases) {
              return false;
          }
      
          // 2. If it has HTTP healthchecks, it's likely an application
          if ($hasAppHealthcheck) {
              return false;
          }
      
          // 3. If it has standard database ports AND database healthchecks, it's likely a database
          if ($hasStandardDbPort && $hasDbHealthcheck) {
              return true;
          }
      
          // 4. If it has database environment variables, it's likely a database
          if ($hasDbEnvVars) {
              return true;
          }
      
          // 5. Default: if it depends on databases but doesn't have database characteristics, it's an application
          if ($dependsOnDatabases) {
              return false;
          }
      
          // 6. Fallback: assume it's a database if we can't determine otherwise
          return true;
      }
      
      function convertDockerRunToCompose(?string $custom_docker_run_options = null)
      {
          $options = [];
          $compose_options = collect([]);
          preg_match_all('/(--\w+(?:-\w+)*)(?:\s|=)?([^\s-]+)?/', $custom_docker_run_options, $matches, PREG_SET_ORDER);
          $list_options = collect([
              '--cap-add',
              '--cap-drop',
              '--security-opt',
              '--sysctl',
              '--ulimit',
              '--device',
              '--shm-size',
          ]);
          $mapping = collect([
              '--cap-add' => 'cap_add',
              '--cap-drop' => 'cap_drop',
              '--security-opt' => 'security_opt',
              '--sysctl' => 'sysctls',
              '--device' => 'devices',
              '--init' => 'init',
              '--ulimit' => 'ulimits',
              '--privileged' => 'privileged',
              '--ip' => 'ip',
              '--ip6' => 'ip6',
              '--shm-size' => 'shm_size',
              '--gpus' => 'gpus',
              '--hostname' => 'hostname',
              '--entrypoint' => 'entrypoint',
          ]);
          foreach ($matches as $match) {
              $option = $match[1];
              if ($option === '--gpus') {
                  $regexForParsingDeviceIds = '/device=([0-9A-Za-z-,]+)/';
                  preg_match($regexForParsingDeviceIds, $custom_docker_run_options, $device_matches);
                  $value = $device_matches[1] ?? 'all';
                  $options[$option][] = $value;
                  $options[$option] = array_unique($options[$option]);
              }
              if ($option === '--hostname') {
                  // Match --hostname=value or --hostname value
                  $regexForParsingHostname = '/--hostname(?:=|\s+)([^\s]+)/';
                  preg_match($regexForParsingHostname, $custom_docker_run_options, $hostname_matches);
                  $value = $hostname_matches[1] ?? null;
                  if ($value && ! empty(trim($value))) {
                      $options[$option][] = $value;
                      $options[$option] = array_unique($options[$option]);
                  }
              }
              if ($option === '--entrypoint') {
                  $value = null;
                  // Match --entrypoint=value or --entrypoint value
                  // Handle quoted strings with escaped quotes: --entrypoint "python -c \"print('hi')\""
                  // Pattern matches: double-quoted (with escapes), single-quoted (with escapes), or unquoted values
                  if (preg_match(
                      '/--entrypoint(?:=|\s+)(?"(?:\\\\.|[^"])*"|\'(?:\\\\.|[^\'])*\'|[^\s]+)/',
                      $custom_docker_run_options,
                      $entrypoint_matches
                  )) {
                      $rawValue = $entrypoint_matches['raw'];
                      // Handle double-quoted strings: strip quotes and unescape special characters
                      if (str_starts_with($rawValue, '"') && str_ends_with($rawValue, '"')) {
                          $inner = substr($rawValue, 1, -1);
                          // Unescape backslash sequences: \" \$ \` \\
                          $value = preg_replace('/\\\\(["$`\\\\])/', '$1', $inner);
                      } elseif (str_starts_with($rawValue, "'") && str_ends_with($rawValue, "'")) {
                          // Handle single-quoted strings: just strip quotes (no unescaping per shell rules)
                          $value = substr($rawValue, 1, -1);
                      } else {
                          // Handle unquoted values
                          $value = $rawValue;
                      }
                  }
      
                  if ($value && trim($value) !== '') {
                      $options[$option][] = $value;
                      $options[$option] = array_values(array_unique($options[$option]));
                  }
      
                  continue;
              }
              if (isset($match[2]) && $match[2] !== '') {
                  $value = $match[2];
                  $options[$option][] = $value;
                  $options[$option] = array_unique($options[$option]);
              } else {
                  $value = true;
                  $options[$option] = $value;
              }
          }
          $options = collect($options);
          // Easily get mappings from https://github.com/composerize/composerize/blob/master/packages/composerize/src/mappings.js
          foreach ($options as $option => $value) {
              if (! data_get($mapping, $option)) {
                  continue;
              }
              if ($option === '--ulimit') {
                  $ulimits = collect([]);
                  collect($value)->map(function ($ulimit) use ($ulimits) {
                      $ulimit = explode('=', $ulimit);
                      $type = $ulimit[0];
                      $limits = explode(':', $ulimit[1]);
                      if (count($limits) == 2) {
                          $soft_limit = $limits[0];
                          $hard_limit = $limits[1];
                          $ulimits->put($type, [
                              'soft' => $soft_limit,
                              'hard' => $hard_limit,
                          ]);
                      } else {
                          $soft_limit = $ulimit[1];
                          $ulimits->put($type, [
                              'soft' => $soft_limit,
                          ]);
                      }
                  });
                  $compose_options->put($mapping[$option], $ulimits);
              } elseif ($option === '--shm-size' || $option === '--hostname') {
                  if (! is_null($value) && is_array($value) && count($value) > 0 && ! empty(trim($value[0]))) {
                      $compose_options->put($mapping[$option], $value[0]);
                  }
              } elseif ($option === '--entrypoint') {
                  if (! is_null($value) && is_array($value) && count($value) > 0 && ! empty(trim($value[0]))) {
                      // Docker compose accepts entrypoint as either a string or an array
                      // Keep it as a string for simplicity - docker compose will handle it
                      $compose_options->put($mapping[$option], $value[0]);
                  }
              } elseif ($option === '--gpus') {
                  $payload = [
                      'driver' => 'nvidia',
                      'capabilities' => ['gpu'],
                  ];
                  if (! is_null($value) && is_array($value) && count($value) > 0 && ! empty(trim($value[0]))) {
                      if (str($value[0]) != 'all') {
                          if (str($value[0])->contains(',')) {
                              $payload['device_ids'] = str($value[0])->explode(',')->toArray();
                          } else {
                              $payload['device_ids'] = [$value[0]];
                          }
                      }
                  }
                  $compose_options->put('deploy', [
                      'resources' => [
                          'reservations' => [
                              'devices' => [$payload],
                          ],
                      ],
                  ]);
              } else {
                  if ($list_options->contains($option)) {
                      if ($compose_options->has($mapping[$option])) {
                          $compose_options->put($mapping[$option], $options->get($mapping[$option]).','.$value);
                      } else {
                          $compose_options->put($mapping[$option], $value);
                      }
      
                      continue;
                  } else {
                      $compose_options->put($mapping[$option], $value);
      
                      continue;
                  }
              }
          }
      
          return $compose_options->toArray();
      }
      
      function generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $network)
      {
          $ipv4 = data_get($docker_run_options, 'ip.0');
          $ipv6 = data_get($docker_run_options, 'ip6.0');
          data_forget($docker_run_options, 'ip');
          data_forget($docker_run_options, 'ip6');
          if ($ipv4 || $ipv6) {
              data_forget($docker_compose['services'][$container_name], 'networks');
          }
          if ($ipv4) {
              $docker_compose['services'][$container_name]['networks'][$network]['ipv4_address'] = $ipv4;
          }
          if ($ipv6) {
              $docker_compose['services'][$container_name]['networks'][$network]['ipv6_address'] = $ipv6;
          }
          $docker_compose['services'][$container_name] = array_merge_recursive($docker_compose['services'][$container_name], $docker_run_options);
      
          return $docker_compose;
      }
      
      /**
       * Remove Coolify's custom Docker Compose fields from parsed YAML array
       *
       * Coolify extends Docker Compose with custom fields that are processed during
       * parsing and deployment but must be removed before sending to Docker.
       *
       * Custom fields:
       * - exclude_from_hc (service-level): Exclude service from health check monitoring
       * - content (volume-level): Auto-create file with specified content during init
       * - isDirectory / is_directory (volume-level): Mark bind mount as directory
       *
       * @param  array  $yamlCompose  Parsed Docker Compose array
       * @return array Cleaned Docker Compose array with custom fields removed
       */
      function stripCoolifyCustomFields(array $yamlCompose): array
      {
          foreach ($yamlCompose['services'] ?? [] as $serviceName => $service) {
              // Remove service-level custom fields
              unset($yamlCompose['services'][$serviceName]['exclude_from_hc']);
      
              // Remove volume-level custom fields (only for long syntax - arrays)
              if (isset($service['volumes'])) {
                  foreach ($service['volumes'] as $volumeName => $volume) {
                      // Skip if volume is string (short syntax like 'db-data:/var/lib/postgresql/data')
                      if (! is_array($volume)) {
                          continue;
                      }
      
                      unset($yamlCompose['services'][$serviceName]['volumes'][$volumeName]['content']);
                      unset($yamlCompose['services'][$serviceName]['volumes'][$volumeName]['isDirectory']);
                      unset($yamlCompose['services'][$serviceName]['volumes'][$volumeName]['is_directory']);
                  }
              }
          }
      
          return $yamlCompose;
      }
      
      function validateComposeFile(string $compose, int $server_id): string|Throwable
      {
          $uuid = Str::random(18);
          $server = Server::ownedByCurrentTeam()->find($server_id);
          try {
              if (! $server) {
                  throw new \Exception('Server not found');
              }
              $yaml_compose = Yaml::parse($compose);
      
              // Remove Coolify's custom fields before Docker validation
              $yaml_compose = stripCoolifyCustomFields($yaml_compose);
      
              $base64_compose = base64_encode(Yaml::dump($yaml_compose));
              instant_remote_process([
                  "echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null",
                  "chmod 600 /tmp/{$uuid}.yml",
                  "docker compose -f /tmp/{$uuid}.yml config --no-interpolate --no-path-resolution -q",
                  "rm /tmp/{$uuid}.yml",
              ], $server);
      
              return 'OK';
          } catch (\Throwable $e) {
              return $e->getMessage();
          } finally {
              if (filled($server)) {
                  instant_remote_process([
                      "rm /tmp/{$uuid}.yml",
                  ], $server, throwError: false);
              }
          }
      }
      
      function getContainerLogs(Server $server, string $container_id, int $lines = 100): string
      {
          if ($server->isSwarm()) {
              $output = instant_remote_process([
                  "docker service logs -n {$lines} {$container_id} 2>&1",
              ], $server);
          } else {
              $output = instant_remote_process([
                  "docker logs -n {$lines} {$container_id} 2>&1",
              ], $server);
          }
      
          $output = removeAnsiColors($output);
      
          return $output;
      }
      function escapeEnvVariables($value)
      {
          $search = ['\\', "\r", "\t", "\x0", '"', "'"];
          $replace = ['\\\\', '\\r', '\\t', '\\0', '\"', "\'"];
      
          return str_replace($search, $replace, $value);
      }
      function escapeDollarSign($value)
      {
          $search = ['$'];
          $replace = ['$$'];
      
          return str_replace($search, $replace, $value);
      }
      
      /**
       * Escape a value for use in a bash .env file that will be sourced with 'source' command
       * Wraps the value in single quotes and escapes any single quotes within the value
       *
       * @param  string|null  $value  The value to escape
       * @return string The escaped value wrapped in single quotes
       */
      function escapeBashEnvValue(?string $value): string
      {
          // Handle null or empty values
          if ($value === null || $value === '') {
              return "''";
          }
      
          // Replace single quotes with '\'' (end quote, escaped quote, start quote)
          // This is the standard way to escape single quotes in bash single-quoted strings
          $escaped = str_replace("'", "'\\''", $value);
      
          // Wrap in single quotes
          return "'{$escaped}'";
      }
      
      /**
       * Escape a value for bash double-quoted strings (allows $VAR expansion)
       *
       * This function wraps values in double quotes while escaping special characters,
       * but preserves valid bash variable references like $VAR and ${VAR}.
       *
       * @param  string|null  $value  The value to escape
       * @return string The escaped value wrapped in double quotes
       */
      function escapeBashDoubleQuoted(?string $value): string
      {
          // Handle null or empty values
          if ($value === null || $value === '') {
              return '""';
          }
      
          // Step 1: Escape backslashes first (must be done before other escaping)
          $escaped = str_replace('\\', '\\\\', $value);
      
          // Step 2: Escape double quotes
          $escaped = str_replace('"', '\\"', $escaped);
      
          // Step 3: Escape backticks (command substitution)
          $escaped = str_replace('`', '\\`', $escaped);
      
          // Step 4: Escape invalid $ patterns while preserving valid variable references
          // Valid patterns to keep:
          //   - $VAR_NAME (alphanumeric + underscore, starting with letter or _)
          //   - ${VAR_NAME} (brace expansion)
          //   - $0-$9 (positional parameters)
          // Invalid patterns to escape: $&, $#, $$, $*, $@, $!, $(, etc.
      
          // Match $ followed by anything that's NOT a valid variable start
          // Valid variable starts: letter, underscore, digit (for $0-$9), or open brace
          $escaped = preg_replace(
              '/\$(?![a-zA-Z_0-9{])/',
              '\\\$',
              $escaped
          );
      
          // Preserve pre-escaped dollars inside double quotes: turn \\$ back into \$
          // (keeps tests like "path\\to\\file" intact while restoring \$ semantics)
          $escaped = preg_replace('/\\\\(?=\$)/', '\\\\', $escaped);
      
          // Wrap in double quotes
          return "\"{$escaped}\"";
      }
      
      /**
       * Generate Docker build arguments from environment variables collection
       * Returns only keys (no values) since values are sourced from environment via export
       *
       * @param  \Illuminate\Support\Collection|array  $variables  Collection of variables with 'key', 'value', and optionally 'is_multiline'
       * @return \Illuminate\Support\Collection Collection of formatted --build-arg strings (keys only)
       */
      function generateDockerBuildArgs($variables): \Illuminate\Support\Collection
      {
          $variables = collect($variables);
      
          return $variables->map(function ($var) {
              $key = is_array($var) ? data_get($var, 'key') : $var->key;
      
              // Only return the key - Docker will get the value from the environment
              return "--build-arg {$key}";
          });
      }
      
      /**
       * Generate Docker environment flags from environment variables collection
       *
       * @param  \Illuminate\Support\Collection|array  $variables  Collection of variables with 'key', 'value', and optionally 'is_multiline'
       * @return string Space-separated environment flags
       */
      function generateDockerEnvFlags($variables): string
      {
          $variables = collect($variables);
      
          return $variables
              ->map(function ($var) {
                  $key = is_array($var) ? data_get($var, 'key') : $var->key;
                  $value = is_array($var) ? data_get($var, 'value') : $var->value;
                  $isMultiline = is_array($var) ? data_get($var, 'is_multiline', false) : ($var->is_multiline ?? false);
      
                  if ($isMultiline) {
                      // For multiline variables, strip surrounding quotes and escape for bash
                      $raw_value = trim($value, "'");
                      $escaped_value = str_replace(['\\', '"', '$', '`'], ['\\\\', '\\"', '\\$', '\\`'], $raw_value);
      
                      return "-e {$key}=\"{$escaped_value}\"";
                  }
      
                  $escaped_value = escapeshellarg($value);
      
                  return "-e {$key}={$escaped_value}";
              })
              ->implode(' ');
      }
      
      /**
       * Auto-inject -f and --env-file flags into a docker compose command if not already present
       *
       * @param  string  $command  The docker compose command to modify
       * @param  string  $composeFilePath  The path to the compose file
       * @param  string  $envFilePath  The path to the .env file
       * @return string The modified command with injected flags
       *
       * @example
       * Input:  "docker compose build"
       * Output: "docker compose -f ./docker-compose.yml --env-file .env build"
       */
      function injectDockerComposeFlags(string $command, string $composeFilePath, string $envFilePath): string
      {
          $dockerComposeReplacement = 'docker compose';
      
          // Add -f flag if not present (checks for both -f and --file with various formats)
          // Detects: -f path, -f=path, -fpath (concatenated with path chars: . / ~), --file path, --file=path
          // Note: Uses [.~/]|$ instead of \S to prevent false positives with flags like -foo, -from, -feature
          if (! preg_match('/(?:^|\s)(?:-f(?:[=\s]|[.\/~]|$)|--file(?:=|\s))/', $command)) {
              $dockerComposeReplacement .= " -f {$composeFilePath}";
          }
      
          // Add --env-file flag if not present (checks for --env-file with various formats)
          // Detects: --env-file path, --env-file=path with any whitespace
          if (! preg_match('/(?:^|\s)--env-file(?:=|\s)/', $command)) {
              $dockerComposeReplacement .= " --env-file {$envFilePath}";
          }
      
          // Replace only first occurrence to avoid modifying comments/strings/chained commands
          return preg_replace('/docker\s+compose/', $dockerComposeReplacement, $command, 1);
      }
      
      /**
       * Inject build arguments right after build-related subcommands in docker/docker compose commands.
       * This ensures build args are only applied to build operations, not to push, pull, up, etc.
       *
       * Supports:
       * - docker compose build
       * - docker buildx build
       * - docker builder build
       * - docker build (legacy)
       *
       * Examples:
       * - Input:  "docker compose -f file.yml build"
       *   Output: "docker compose -f file.yml build --build-arg X --build-arg Y"
       *
       * - Input:  "docker buildx build --platform linux/amd64"
       *   Output: "docker buildx build --build-arg X --build-arg Y --platform linux/amd64"
       *
       * - Input:  "docker builder build --tag myimage:latest"
       *   Output: "docker builder build --build-arg X --build-arg Y --tag myimage:latest"
       *
       * - Input:  "docker compose build && docker compose push"
       *   Output: "docker compose build --build-arg X --build-arg Y && docker compose push"
       *
       * - Input:  "docker compose push"
       *   Output: "docker compose push" (unchanged - no build command found)
       *
       * @param  string  $command  The docker command
       * @param  string  $buildArgsString  The build arguments to inject (e.g., "--build-arg X --build-arg Y")
       * @return string The modified command with build args injected after build subcommand
       */
      function injectDockerComposeBuildArgs(string $command, string $buildArgsString): string
      {
          // Early return if no build args to inject
          if (empty(trim($buildArgsString))) {
              return $command;
          }
      
          // Match build-related commands:
          // - ' builder build' (docker builder build)
          // - ' buildx build' (docker buildx build)
          // - ' build' (docker compose build, docker build)
          // Followed by either:
          // - whitespace (allowing service names, flags, or any valid arguments)
          // - end of string ($)
          // This regex ensures we match build subcommands, not "build" in other contexts
          // IMPORTANT: Order matters - check longer patterns first (builder build, buildx build) before ' build'
          $pattern = '/( builder build| buildx build| build)(?=\s|$)/';
      
          // Replace the first occurrence of build command with build command + build-args
          $modifiedCommand = preg_replace(
              $pattern,
              '$1 '.$buildArgsString,
              $command,
              1  // Only replace first occurrence
          );
      
          return $modifiedCommand ?? $command;
      }
      
      
      ================================================
      FILE: bootstrap/helpers/domains.php
      ================================================
      team();
          }
      
          if ($resource) {
              if ($resource->getMorphClass() === Application::class && $resource->build_pack === 'dockercompose') {
                  $domains = data_get(json_decode($resource->docker_compose_domains, true), '*.domain');
                  $domains = collect($domains);
              } else {
                  $domains = collect($resource->fqdns);
              }
          } elseif ($domain) {
              $domains = collect([$domain]);
          } else {
              return ['conflicts' => [], 'hasConflicts' => false];
          }
      
          $domains = $domains->map(function ($domain) {
              if (str($domain)->endsWith('/')) {
                  $domain = str($domain)->beforeLast('/');
              }
      
              return str($domain);
          });
      
          // Filter applications by team if we have a current team
          $appsQuery = Application::query();
          if ($currentTeam) {
              $appsQuery = $appsQuery->whereHas('environment.project', function ($query) use ($currentTeam) {
                  $query->where('team_id', $currentTeam->id);
              });
          }
          $apps = $appsQuery->get();
          foreach ($apps as $app) {
              $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
              foreach ($list_of_domains as $domain) {
                  if (str($domain)->endsWith('/')) {
                      $domain = str($domain)->beforeLast('/');
                  }
                  $naked_domain = str($domain)->value();
                  if ($domains->contains($naked_domain)) {
                      if (data_get($resource, 'uuid')) {
                          if ($resource->uuid !== $app->uuid) {
                              $conflicts[] = [
                                  'domain' => $naked_domain,
                                  'resource_name' => $app->name,
                                  'resource_link' => $app->link(),
                                  'resource_type' => 'application',
                                  'message' => "Domain $naked_domain is already in use by application '{$app->name}'",
                              ];
                          }
                      } elseif ($domain) {
                          $conflicts[] = [
                              'domain' => $naked_domain,
                              'resource_name' => $app->name,
                              'resource_link' => $app->link(),
                              'resource_type' => 'application',
                              'message' => "Domain $naked_domain is already in use by application '{$app->name}'",
                          ];
                      }
                  }
              }
          }
      
          // Filter service applications by team if we have a current team
          $serviceAppsQuery = ServiceApplication::query();
          if ($currentTeam) {
              $serviceAppsQuery = $serviceAppsQuery->whereHas('service.environment.project', function ($query) use ($currentTeam) {
                  $query->where('team_id', $currentTeam->id);
              });
          }
          $apps = $serviceAppsQuery->get();
          foreach ($apps as $app) {
              $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
              foreach ($list_of_domains as $domain) {
                  if (str($domain)->endsWith('/')) {
                      $domain = str($domain)->beforeLast('/');
                  }
                  $naked_domain = str($domain)->value();
                  if ($domains->contains($naked_domain)) {
                      if (data_get($resource, 'uuid')) {
                          if ($resource->uuid !== $app->uuid) {
                              $conflicts[] = [
                                  'domain' => $naked_domain,
                                  'resource_name' => $app->service->name,
                                  'resource_link' => $app->service->link(),
                                  'resource_type' => 'service',
                                  'message' => "Domain $naked_domain is already in use by service '{$app->service->name}'",
                              ];
                          }
                      } elseif ($domain) {
                          $conflicts[] = [
                              'domain' => $naked_domain,
                              'resource_name' => $app->service->name,
                              'resource_link' => $app->service->link(),
                              'resource_type' => 'service',
                              'message' => "Domain $naked_domain is already in use by service '{$app->service->name}'",
                          ];
                      }
                  }
              }
          }
      
          if ($resource) {
              $settings = instanceSettings();
              if (data_get($settings, 'fqdn')) {
                  $domain = data_get($settings, 'fqdn');
                  if (str($domain)->endsWith('/')) {
                      $domain = str($domain)->beforeLast('/');
                  }
                  $naked_domain = str($domain)->value();
                  if ($domains->contains($naked_domain)) {
                      $conflicts[] = [
                          'domain' => $naked_domain,
                          'resource_name' => 'Coolify Instance',
                          'resource_link' => '#',
                          'resource_type' => 'instance',
                          'message' => "Domain $naked_domain is already in use by this Coolify instance",
                      ];
                  }
              }
          }
      
          return [
              'conflicts' => $conflicts,
              'hasConflicts' => count($conflicts) > 0,
          ];
      }
      
      function checkIfDomainIsAlreadyUsedViaAPI(Collection|array $domains, ?string $teamId = null, ?string $uuid = null)
      {
          $conflicts = [];
      
          if (is_null($teamId)) {
              return ['error' => 'Team ID is required.'];
          }
          if (is_array($domains)) {
              $domains = collect($domains);
          }
      
          $domains = $domains->map(function ($domain) {
              if (str($domain)->endsWith('/')) {
                  $domain = str($domain)->beforeLast('/');
              }
      
              return str($domain);
          });
      
          $applications = Application::ownedByCurrentTeamAPI($teamId)->get(['fqdn', 'uuid', 'name', 'id', 'docker_compose_domains', 'build_pack']);
          $serviceApplications = ServiceApplication::ownedByCurrentTeamAPI($teamId)->with('service:id,name')->get(['fqdn', 'uuid', 'id', 'service_id']);
      
          if ($uuid) {
              $applications = $applications->filter(fn ($app) => $app->uuid !== $uuid);
              $serviceApplications = $serviceApplications->filter(fn ($app) => $app->uuid !== $uuid);
          }
      
          foreach ($applications as $app) {
              if (! is_null($app->fqdn)) {
                  $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
                  foreach ($list_of_domains as $domain) {
                      if (str($domain)->endsWith('/')) {
                          $domain = str($domain)->beforeLast('/');
                      }
                      $naked_domain = str($domain)->value();
                      if ($domains->contains($naked_domain)) {
                          $conflicts[] = [
                              'domain' => $naked_domain,
                              'resource_name' => $app->name,
                              'resource_uuid' => $app->uuid,
                              'resource_type' => 'application',
                              'message' => "Domain $naked_domain is already in use by application '{$app->name}'",
                          ];
                      }
                  }
              }
      
              if ($app->build_pack === 'dockercompose' && ! empty($app->docker_compose_domains)) {
                  $dockerComposeDomains = json_decode($app->docker_compose_domains, true);
                  if (is_array($dockerComposeDomains)) {
                      foreach ($dockerComposeDomains as $serviceName => $domainConfig) {
                          $domainValue = data_get($domainConfig, 'domain');
                          if (empty($domainValue)) {
                              continue;
                          }
                          $list_of_domains = collect(explode(',', $domainValue))->filter(fn ($fqdn) => $fqdn !== '');
                          foreach ($list_of_domains as $domain) {
                              if (str($domain)->endsWith('/')) {
                                  $domain = str($domain)->beforeLast('/');
                              }
                              $naked_domain = str($domain)->value();
                              if ($domains->contains($naked_domain)) {
                                  $conflicts[] = [
                                      'domain' => $naked_domain,
                                      'resource_name' => $app->name,
                                      'resource_uuid' => $app->uuid,
                                      'resource_type' => 'application',
                                      'service_name' => $serviceName,
                                      'message' => "Domain $naked_domain is already in use by application '{$app->name}' (service: {$serviceName})",
                                  ];
                              }
                          }
                      }
                  }
              }
          }
      
          foreach ($serviceApplications as $app) {
              if (str($app->fqdn)->isEmpty()) {
                  continue;
              }
              $list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
              foreach ($list_of_domains as $domain) {
                  if (str($domain)->endsWith('/')) {
                      $domain = str($domain)->beforeLast('/');
                  }
                  $naked_domain = str($domain)->value();
                  if ($domains->contains($naked_domain)) {
                      $conflicts[] = [
                          'domain' => $naked_domain,
                          'resource_name' => $app->service->name ?? 'Unknown Service',
                          'resource_uuid' => $app->uuid,
                          'resource_type' => 'service',
                          'message' => "Domain $naked_domain is already in use by service '{$app->service->name}'",
                      ];
                  }
              }
          }
      
          // Check instance-level domain
          $settings = instanceSettings();
          if (data_get($settings, 'fqdn')) {
              $domain = data_get($settings, 'fqdn');
              if (str($domain)->endsWith('/')) {
                  $domain = str($domain)->beforeLast('/');
              }
              $naked_domain = str($domain)->value();
              if ($domains->contains($naked_domain)) {
                  $conflicts[] = [
                      'domain' => $naked_domain,
                      'resource_name' => 'Coolify Instance',
                      'resource_uuid' => null,
                      'resource_type' => 'instance',
                      'message' => "Domain $naked_domain is already in use by this Coolify instance",
                  ];
              }
          }
      
          return [
              'conflicts' => $conflicts,
              'hasConflicts' => count($conflicts) > 0,
          ];
      }
      
      
      ================================================
      FILE: bootstrap/helpers/github.php
      ================================================
      api_url}/zen");
          $serverTime = CarbonImmutable::now()->setTimezone('UTC');
          $githubTime = Carbon::parse($response->header('date'));
          $timeDiff = abs($serverTime->diffInSeconds($githubTime));
      
          if ($timeDiff > 50) {
              throw new \Exception(
                  'System time is out of sync with GitHub API time:
      '. '- System time: '.$serverTime->format('Y-m-d H:i:s').' UTC
      '. '- GitHub time: '.$githubTime->format('Y-m-d H:i:s').' UTC
      '. '- Difference: '.$timeDiff.' seconds
      '. 'Please synchronize your system clock.' ); } $signingKey = InMemory::plainText($source->privateKey->private_key); $algorithm = new Sha256; $tokenBuilder = (new Builder(new JoseEncoder, ChainedFormatter::default())); $now = CarbonImmutable::now()->setTimezone('UTC'); $now = $now->setTime($now->format('H'), $now->format('i'), $now->format('s')); $jwt = $tokenBuilder ->issuedBy($source->app_id) ->issuedAt($now->modify('-1 minute')) ->expiresAt($now->modify('+8 minutes')) ->getToken($algorithm, $signingKey) ->toString(); return match ($type) { 'jwt' => $jwt, 'installation' => (function () use ($source, $jwt) { $response = Http::withHeaders([ 'Authorization' => "Bearer $jwt", 'Accept' => 'application/vnd.github.machine-man-preview+json', ])->post("{$source->api_url}/app/installations/{$source->installation_id}/access_tokens"); if (! $response->successful()) { $error = data_get($response->json(), 'message', 'no error message found'); if ($error === 'Not Found') { $error = 'Repository not found. Is it moved or deleted?'; } throw new RuntimeException("Failed to get installation token for {$source->name} with error: ".$error); } return $response->json()['token']; })(), default => throw new \InvalidArgumentException("Unsupported token type: {$type}") }; } function generateGithubInstallationToken(GithubApp $source) { return generateGithubToken($source, 'installation'); } function generateGithubJwt(GithubApp $source) { return generateGithubToken($source, 'jwt'); } function githubApi(GithubApp|GitlabApp|null $source, string $endpoint, string $method = 'get', ?array $data = null, bool $throwError = true) { if (is_null($source)) { throw new \Exception('Source is required for API calls'); } if ($source->getMorphClass() !== GithubApp::class) { throw new \InvalidArgumentException("Unsupported source type: {$source->getMorphClass()}"); } if ($source->is_public) { $response = Http::GitHub($source->api_url)->$method($endpoint); } else { $token = generateGithubInstallationToken($source); if ($data && in_array(strtolower($method), ['post', 'patch', 'put'])) { $response = Http::GitHub($source->api_url, $token)->$method($endpoint, $data); } else { $response = Http::GitHub($source->api_url, $token)->$method($endpoint); } } if (! $response->successful() && $throwError) { $resetTime = Carbon::parse((int) $response->header('X-RateLimit-Reset'))->format('Y-m-d H:i:s'); $errorMessage = data_get($response->json(), 'message', 'no error message found'); $remainingCalls = $response->header('X-RateLimit-Remaining', '0'); throw new \Exception( 'GitHub API call failed:
      '. "Error: {$errorMessage}
      ". 'Rate Limit Status:
      '. "- Remaining Calls: {$remainingCalls}
      ". "- Reset Time: {$resetTime} UTC" ); } return [ 'rate_limit_remaining' => $response->header('X-RateLimit-Remaining'), 'rate_limit_reset' => $response->header('X-RateLimit-Reset'), 'data' => collect($response->json()), ]; } function getInstallationPath(GithubApp $source) { $github = GithubApp::where('uuid', $source->uuid)->first(); $name = str(Str::kebab($github->name)); $installation_path = $github->html_url === 'https://github.com' ? 'apps' : 'github-apps'; return "$github->html_url/$installation_path/$name/installations/new"; } function getPermissionsPath(GithubApp $source) { $github = GithubApp::where('uuid', $source->uuid)->first(); $name = str(Str::kebab($github->name)); return "$github->html_url/settings/apps/$name/permissions"; } function loadRepositoryByPage(GithubApp $source, string $token, int $page) { $response = Http::GitHub($source->api_url, $token) ->timeout(20) ->retry(3, 200, throw: false) ->get('/installation/repositories', [ 'per_page' => 100, 'page' => $page, ]); $json = $response->json(); if ($response->status() !== 200) { return [ 'total_count' => 0, 'repositories' => [], ]; } if ($json['total_count'] === 0) { return [ 'total_count' => 0, 'repositories' => [], ]; } return [ 'total_count' => $json['total_count'], 'repositories' => $json['repositories'], ]; } function getGithubCommitRangeFiles(?GithubApp $source, string $owner, string $repo, string $beforeSha, string $afterSha): array { try { if (! $source) { // Manual webhooks don't have GitHub App authentication // Return empty array so watch paths are ignored (current behavior) return []; } $endpoint = "/repos/{$owner}/{$repo}/compare/{$beforeSha}...{$afterSha}"; $response = githubApi($source, $endpoint, 'get', null, false); if (! $response) { return []; } $files = collect(data_get($response, 'data.files', [])); return $files->pluck('filename')->filter()->values()->toArray(); } catch (Exception $e) { ray('Error fetching GitHub commit range files: '.$e->getMessage()); return []; } } function getGithubPullRequestFiles(?GithubApp $source, string $owner, string $repo, int $pullRequestId): array { try { if (! $source) { // Manual webhooks don't have GitHub App authentication // Return empty array so watch paths are ignored (current behavior) return []; } $endpoint = "/repos/{$owner}/{$repo}/pulls/{$pullRequestId}/files"; $response = githubApi($source, $endpoint, 'get', null, false); if (! $response) { return []; } $files = collect(data_get($response, 'data', [])); return $files->pluck('filename')->filter()->values()->toArray(); } catch (Exception $e) { ray('Error fetching GitHub PR files: '.$e->getMessage()); return []; } } ================================================ FILE: bootstrap/helpers/notifications.php ================================================ smtp_enabled || $settings->resend_enabled; } function send_internal_notification(string $message): void { try { $team = Team::find(0); $team?->notify(new GeneralNotification($message)); } catch (\Throwable $e) { ray($e->getMessage()); } } function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null): void { $settings = instanceSettings(); $type = set_transanctional_email_settings($settings); if (blank($type)) { throw new Exception('No email settings found.'); } if ($cc) { Mail::send( [], [], fn (Message $message) => $message ->to($email) ->replyTo($email) ->cc($cc) ->subject($mail->subject) ->html((string) $mail->render()) ); } else { Mail::send( [], [], fn (Message $message) => $message ->to($email) ->subject($mail->subject) ->html((string) $mail->render()) ); } } function set_transanctional_email_settings($settings = null) { if (! $settings) { $settings = instanceSettings(); } if (! data_get($settings, 'smtp_enabled') && ! data_get($settings, 'resend_enabled')) { return null; } $configRepository = app('App\Services\ConfigurationRepository'::class); $configRepository->updateMailConfig($settings); if (data_get($settings, 'resend_enabled')) { return 'resend'; } if (data_get($settings, 'smtp_enabled')) { return 'smtp'; } return null; } ================================================ FILE: bootstrap/helpers/parsers.php ================================================ getMessage(), 0, $e); } if (! is_array($parsed) || ! isset($parsed['services']) || ! is_array($parsed['services'])) { throw new \Exception('Docker Compose file must contain a "services" section'); } // Validate service names foreach ($parsed['services'] as $serviceName => $serviceConfig) { try { validateShellSafePath($serviceName, 'service name'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker Compose service name: '.$e->getMessage(). ' Service names must not contain shell metacharacters.', 0, $e ); } // Validate volumes in this service (both string and array formats) if (isset($serviceConfig['volumes']) && is_array($serviceConfig['volumes'])) { foreach ($serviceConfig['volumes'] as $volume) { if (is_string($volume)) { // String format: "source:target" or "source:target:mode" validateVolumeStringForInjection($volume); } elseif (is_array($volume)) { // Array format: {type: bind, source: ..., target: ...} if (isset($volume['source'])) { $source = $volume['source']; if (is_string($source)) { // Allow env vars and env vars with defaults (validated in parseDockerVolumeString) // Also allow env vars followed by safe path concatenation (e.g., ${VAR}/path) $isSimpleEnvVar = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/', $source); $isEnvVarWithDefault = preg_match('/^\$\{[^}]+:-[^}]*\}$/', $source); $isEnvVarWithPath = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}[\/\w\.\-]*$/', $source); if (! $isSimpleEnvVar && ! $isEnvVarWithDefault && ! $isEnvVarWithPath) { try { validateShellSafePath($source, 'volume source'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker volume definition (array syntax): '.$e->getMessage(). ' Please use safe path names without shell metacharacters.', 0, $e ); } } } } if (isset($volume['target'])) { $target = $volume['target']; if (is_string($target)) { try { validateShellSafePath($target, 'volume target'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker volume definition (array syntax): '.$e->getMessage(). ' Please use safe path names without shell metacharacters.', 0, $e ); } } } } } } } } /** * Validates a Docker volume string (format: "source:target" or "source:target:mode") * * @param string $volumeString The volume string to validate * * @throws \Exception If the volume string contains command injection attempts */ function validateVolumeStringForInjection(string $volumeString): void { // Canonical parsing also validates and throws on unsafe input parseDockerVolumeString($volumeString); } function parseDockerVolumeString(string $volumeString): array { $volumeString = trim($volumeString); $source = null; $target = null; $mode = null; // First, check if the source contains an environment variable with default value // This needs to be done before counting colons because ${VAR:-value} contains a colon $envVarPattern = '/^\$\{[^}]+:-[^}]*\}/'; $hasEnvVarWithDefault = false; $envVarEndPos = 0; if (preg_match($envVarPattern, $volumeString, $matches)) { $hasEnvVarWithDefault = true; $envVarEndPos = strlen($matches[0]); } // Count colons, but exclude those inside environment variables $effectiveVolumeString = $volumeString; if ($hasEnvVarWithDefault) { // Temporarily replace the env var to count colons correctly $effectiveVolumeString = substr($volumeString, $envVarEndPos); $colonCount = substr_count($effectiveVolumeString, ':'); } else { $colonCount = substr_count($volumeString, ':'); } if ($colonCount === 0) { // Named volume without target (unusual but valid) // Example: "myvolume" $source = $volumeString; $target = $volumeString; } elseif ($colonCount === 1) { // Simple volume mapping // Examples: "gitea:/data" or "./data:/app/data" or "${VAR:-default}:/data" if ($hasEnvVarWithDefault) { $source = substr($volumeString, 0, $envVarEndPos); $remaining = substr($volumeString, $envVarEndPos); if (strlen($remaining) > 0 && $remaining[0] === ':') { $target = substr($remaining, 1); } else { $target = $remaining; } } else { $parts = explode(':', $volumeString); $source = $parts[0]; $target = $parts[1]; } } elseif ($colonCount === 2) { // Volume with mode OR Windows path OR env var with mode // Handle env var with mode first if ($hasEnvVarWithDefault) { // ${VAR:-default}:/path:mode $source = substr($volumeString, 0, $envVarEndPos); $remaining = substr($volumeString, $envVarEndPos); if (strlen($remaining) > 0 && $remaining[0] === ':') { $remaining = substr($remaining, 1); $lastColon = strrpos($remaining, ':'); if ($lastColon !== false) { $possibleMode = substr($remaining, $lastColon + 1); $validModes = ['ro', 'rw', 'z', 'Z', 'rslave', 'rprivate', 'rshared', 'slave', 'private', 'shared', 'cached', 'delegated', 'consistent']; if (in_array($possibleMode, $validModes)) { $mode = $possibleMode; $target = substr($remaining, 0, $lastColon); } else { $target = $remaining; } } else { $target = $remaining; } } } elseif (preg_match('/^[A-Za-z]:/', $volumeString)) { // Windows path as source (C:/, D:/, etc.) // Find the second colon which is the real separator $secondColon = strpos($volumeString, ':', 2); if ($secondColon !== false) { $source = substr($volumeString, 0, $secondColon); $target = substr($volumeString, $secondColon + 1); } else { // Malformed, treat as is $source = $volumeString; $target = $volumeString; } } else { // Not a Windows path, check for mode $lastColon = strrpos($volumeString, ':'); $possibleMode = substr($volumeString, $lastColon + 1); // Check if the last part is a valid Docker volume mode $validModes = ['ro', 'rw', 'z', 'Z', 'rslave', 'rprivate', 'rshared', 'slave', 'private', 'shared', 'cached', 'delegated', 'consistent']; if (in_array($possibleMode, $validModes)) { // It's a mode // Examples: "gitea:/data:ro" or "./data:/app/data:rw" $mode = $possibleMode; $volumeWithoutMode = substr($volumeString, 0, $lastColon); $colonPos = strpos($volumeWithoutMode, ':'); if ($colonPos !== false) { $source = substr($volumeWithoutMode, 0, $colonPos); $target = substr($volumeWithoutMode, $colonPos + 1); } else { // Shouldn't happen for valid volume strings $source = $volumeWithoutMode; $target = $volumeWithoutMode; } } else { // The last colon is part of the path // For now, treat the first occurrence of : as the separator $firstColon = strpos($volumeString, ':'); $source = substr($volumeString, 0, $firstColon); $target = substr($volumeString, $firstColon + 1); } } } else { // More than 2 colons - likely Windows paths or complex cases // Use a heuristic: find the most likely separator colon // Look for patterns like "C:" at the beginning (Windows drive) if (preg_match('/^[A-Za-z]:/', $volumeString)) { // Windows path as source // Find the next colon after the drive letter $secondColon = strpos($volumeString, ':', 2); if ($secondColon !== false) { $source = substr($volumeString, 0, $secondColon); $remaining = substr($volumeString, $secondColon + 1); // Check if there's a mode at the end $lastColon = strrpos($remaining, ':'); if ($lastColon !== false) { $possibleMode = substr($remaining, $lastColon + 1); $validModes = ['ro', 'rw', 'z', 'Z', 'rslave', 'rprivate', 'rshared', 'slave', 'private', 'shared', 'cached', 'delegated', 'consistent']; if (in_array($possibleMode, $validModes)) { $mode = $possibleMode; $target = substr($remaining, 0, $lastColon); } else { $target = $remaining; } } else { $target = $remaining; } } else { // Malformed, treat as is $source = $volumeString; $target = $volumeString; } } else { // Try to parse normally, treating first : as separator $firstColon = strpos($volumeString, ':'); $source = substr($volumeString, 0, $firstColon); $remaining = substr($volumeString, $firstColon + 1); // Check for mode at the end $lastColon = strrpos($remaining, ':'); if ($lastColon !== false) { $possibleMode = substr($remaining, $lastColon + 1); $validModes = ['ro', 'rw', 'z', 'Z', 'rslave', 'rprivate', 'rshared', 'slave', 'private', 'shared', 'cached', 'delegated', 'consistent']; if (in_array($possibleMode, $validModes)) { $mode = $possibleMode; $target = substr($remaining, 0, $lastColon); } else { $target = $remaining; } } else { $target = $remaining; } } } // Handle environment variable expansion in source // Example: ${VOLUME_DB_PATH:-db} should extract default value if present if ($source && preg_match('/^\$\{([^}]+)\}$/', $source, $matches)) { $varContent = $matches[1]; // Check if there's a default value with :- if (strpos($varContent, ':-') !== false) { $parts = explode(':-', $varContent, 2); $varName = $parts[0]; $defaultValue = isset($parts[1]) ? $parts[1] : ''; // If there's a non-empty default value, use it for source if ($defaultValue !== '') { $source = $defaultValue; } else { // Empty default value, keep the variable reference for env resolution $source = '${'.$varName.'}'; } } // Otherwise keep the variable as-is for later expansion (no default value) } // Validate source path for command injection attempts // We validate the final source value after environment variable processing if ($source !== null) { // Allow environment variables like ${VAR_NAME} or ${VAR} // Also allow env vars followed by safe path concatenation (e.g., ${VAR}/path) $sourceStr = is_string($source) ? $source : $source; // Skip validation for simple environment variable references // Pattern 1: ${WORD_CHARS} with no special characters inside // Pattern 2: ${WORD_CHARS}/path/to/file (env var with path concatenation) $isSimpleEnvVar = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/', $sourceStr); $isEnvVarWithPath = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}[\/\w\.\-]*$/', $sourceStr); if (! $isSimpleEnvVar && ! $isEnvVarWithPath) { try { validateShellSafePath($sourceStr, 'volume source'); } catch (\Exception $e) { // Re-throw with more context about the volume string throw new \Exception( 'Invalid Docker volume definition: '.$e->getMessage(). ' Please use safe path names without shell metacharacters.' ); } } } // Also validate target path if ($target !== null) { $targetStr = is_string($target) ? $target : $target; // Target paths in containers are typically absolute paths, so we validate them too // but they're less likely to be dangerous since they're not used in host commands // Still, defense in depth is important try { validateShellSafePath($targetStr, 'volume target'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker volume definition: '.$e->getMessage(). ' Please use safe path names without shell metacharacters.' ); } } return [ 'source' => $source !== null ? str($source) : null, 'target' => $target !== null ? str($target) : null, 'mode' => $mode !== null ? str($mode) : null, ]; } function applicationParser(Application $resource, int $pull_request_id = 0, ?int $preview_id = null, ?string $commit = null): Collection { $uuid = data_get($resource, 'uuid'); $compose = data_get($resource, 'docker_compose_raw'); // Store original compose for later use to update docker_compose_raw with content removed $originalCompose = $compose; if (! $compose) { return collect([]); } $pullRequestId = $pull_request_id; $isPullRequest = $pullRequestId == 0 ? false : true; $server = data_get($resource, 'destination.server'); $fileStorages = $resource->fileStorages(); try { $yaml = Yaml::parse($compose); } catch (\Exception) { return collect([]); } $services = data_get($yaml, 'services', collect([])); $topLevel = collect([ 'volumes' => collect(data_get($yaml, 'volumes', [])), 'networks' => collect(data_get($yaml, 'networks', [])), 'configs' => collect(data_get($yaml, 'configs', [])), 'secrets' => collect(data_get($yaml, 'secrets', [])), ]); // If there are predefined volumes, make sure they are not null if ($topLevel->get('volumes')->count() > 0) { $temp = collect([]); foreach ($topLevel['volumes'] as $volumeName => $volume) { if (is_null($volume)) { continue; } $temp->put($volumeName, $volume); } $topLevel['volumes'] = $temp; } // Get the base docker network $baseNetwork = collect([$uuid]); if ($isPullRequest) { $baseNetwork = collect(["{$uuid}-{$pullRequestId}"]); } $parsedServices = collect([]); $allMagicEnvironments = collect([]); foreach ($services as $serviceName => $service) { // Validate service name for command injection try { validateShellSafePath($serviceName, 'service name'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker Compose service name: '.$e->getMessage(). ' Service names must not contain shell metacharacters.' ); } $magicEnvironments = collect([]); $image = data_get_str($service, 'image'); $environment = collect(data_get($service, 'environment', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); $environment = collect(data_get($service, 'environment', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); // convert environment variables to one format $environment = convertToKeyValueCollection($environment); // Add Coolify defined environments $allEnvironments = $resource->environment_variables()->get(['key', 'value']); $allEnvironments = $allEnvironments->mapWithKeys(function ($item) { return [$item['key'] => $item['value']]; }); // filter and add magic environments foreach ($environment as $key => $value) { // Get all SERVICE_ variables from keys and values $key = str($key); $value = str($value); $regex = '/\$(\{?([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\}?)/'; preg_match_all($regex, $value, $valueMatches); if (count($valueMatches[2]) > 0) { foreach ($valueMatches[2] as $match) { $match = str($match); if ($match->startsWith('SERVICE_')) { if ($magicEnvironments->has($match->value())) { continue; } $magicEnvironments->put($match->value(), ''); } } } // Get magic environments where we need to preset the FQDN // for example SERVICE_FQDN_APP_3000 (without a value) if ($key->startsWith('SERVICE_FQDN_')) { // SERVICE_FQDN_APP or SERVICE_FQDN_APP_3000 $parsed = parseServiceEnvironmentVariable($key->value()); $fqdnFor = $parsed['service_name']; $port = $parsed['port']; $fqdn = $resource->fqdn; if (blank($resource->fqdn)) { $fqdn = generateFqdn(server: $server, random: "$uuid", parserVersion: $resource->compose_parsing_version); } if ($value && get_class($value) === \Illuminate\Support\Stringable::class && $value->startsWith('/')) { $path = $value->value(); if ($path !== '/') { $fqdn = "$fqdn$path"; } } $fqdnWithPort = $fqdn; if ($port) { $fqdnWithPort = "$fqdn:$port"; } if (is_null($resource->fqdn)) { data_forget($resource, 'environment_variables'); data_forget($resource, 'environment_variables_preview'); $resource->fqdn = $fqdnWithPort; $resource->save(); } if (! $parsed['has_port']) { $resource->environment_variables()->updateOrCreate([ 'key' => $key->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdn, 'is_preview' => false, ]); } if ($parsed['has_port']) { $newKey = str($key)->beforeLast('_'); $resource->environment_variables()->updateOrCreate([ 'key' => $newKey->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdn, 'is_preview' => false, ]); } } } $allMagicEnvironments = $allMagicEnvironments->merge($magicEnvironments); if ($magicEnvironments->count() > 0) { // Generate Coolify environment variables foreach ($magicEnvironments as $key => $value) { $key = str($key); $value = replaceVariables($value); $command = parseCommandFromMagicEnvVariable($key); if ($command->value() === 'FQDN' || $command->value() === 'URL') { // ALWAYS create BOTH SERVICE_URL and SERVICE_FQDN pairs regardless of which one is in template $parsed = parseServiceEnvironmentVariable($key->value()); $serviceName = $parsed['service_name']; $port = $parsed['port']; // Extract case-preserved service name from template $strKey = str($key->value()); if ($parsed['has_port']) { if ($strKey->startsWith('SERVICE_URL_')) { $serviceNamePreserved = $strKey->after('SERVICE_URL_')->beforeLast('_')->value(); } else { $serviceNamePreserved = $strKey->after('SERVICE_FQDN_')->beforeLast('_')->value(); } } else { if ($strKey->startsWith('SERVICE_URL_')) { $serviceNamePreserved = $strKey->after('SERVICE_URL_')->value(); } else { $serviceNamePreserved = $strKey->after('SERVICE_FQDN_')->value(); } } $originalServiceName = str($serviceName)->replace('_', '-')->value(); // Always normalize service names to match docker_compose_domains lookup $serviceName = str($serviceName)->replace('-', '_')->replace('.', '_')->value(); // Generate BOTH FQDN & URL $fqdn = generateFqdn(server: $server, random: "$originalServiceName-$uuid", parserVersion: $resource->compose_parsing_version); $url = generateUrl(server: $server, random: "$originalServiceName-$uuid"); // IMPORTANT: SERVICE_FQDN env vars should NOT contain scheme (host only) // But $fqdn variable itself may contain scheme (used for database domain field) // Strip scheme for environment variable values $fqdnValueForEnv = str($fqdn)->after('://')->value(); // Append port if specified $urlWithPort = $url; $fqdnValueForEnvWithPort = $fqdnValueForEnv; if ($port && is_numeric($port)) { $urlWithPort = "$url:$port"; $fqdnValueForEnvWithPort = "$fqdnValueForEnv:$port"; } // ALWAYS create base SERVICE_FQDN variable (host only, no scheme) $resource->environment_variables()->firstOrCreate([ 'key' => "SERVICE_FQDN_{$serviceNamePreserved}", 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdnValueForEnv, 'is_preview' => false, ]); // ALWAYS create base SERVICE_URL variable (with scheme) $resource->environment_variables()->firstOrCreate([ 'key' => "SERVICE_URL_{$serviceNamePreserved}", 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $url, 'is_preview' => false, ]); // If port-specific, ALSO create port-specific pairs if ($parsed['has_port'] && $port) { $resource->environment_variables()->firstOrCreate([ 'key' => "SERVICE_FQDN_{$serviceNamePreserved}_{$port}", 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdnValueForEnvWithPort, 'is_preview' => false, ]); $resource->environment_variables()->firstOrCreate([ 'key' => "SERVICE_URL_{$serviceNamePreserved}_{$port}", 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $urlWithPort, 'is_preview' => false, ]); } if ($resource->build_pack === 'dockercompose') { // Check if a service with this name actually exists $serviceExists = false; foreach ($services as $serviceNameKey => $service) { $transformedServiceName = str($serviceNameKey)->replace('-', '_')->replace('.', '_')->value(); if ($transformedServiceName === $serviceName) { $serviceExists = true; break; } } // Only add domain if the service exists if ($serviceExists) { $domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]); $domainExists = data_get($domains->get($serviceName), 'domain'); // Update domain using URL with port if applicable $domainValue = $port ? $urlWithPort : $url; if (is_null($domainExists)) { $domains->put($serviceName, [ 'domain' => $domainValue, ]); $resource->docker_compose_domains = $domains->toJson(); $resource->save(); } } } } else { $value = generateEnvValue($command, $resource); $resource->environment_variables()->firstOrCreate([ 'key' => $key->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $value, 'is_preview' => false, ]); } } } } // generate SERVICE_NAME variables for docker compose services $serviceNameEnvironments = collect([]); if ($resource->build_pack === 'dockercompose') { $serviceNameEnvironments = generateDockerComposeServiceName($services, $pullRequestId); } // Parse the rest of the services foreach ($services as $serviceName => $service) { $image = data_get_str($service, 'image'); $restart = data_get_str($service, 'restart', RESTART_MODE); $logging = data_get($service, 'logging'); if ($server->isLogDrainEnabled()) { if ($resource->isLogDrainEnabled()) { $logging = generate_fluentd_configuration(); } } $volumes = collect(data_get($service, 'volumes', [])); $networks = collect(data_get($service, 'networks', [])); $use_network_mode = data_get($service, 'network_mode') !== null; $depends_on = collect(data_get($service, 'depends_on', [])); $labels = collect(data_get($service, 'labels', [])); if ($labels->count() > 0) { if (isAssociativeArray($labels)) { $newLabels = collect([]); $labels->each(function ($value, $key) use ($newLabels) { $newLabels->push("$key=$value"); }); $labels = $newLabels; } } $environment = collect(data_get($service, 'environment', [])); $ports = collect(data_get($service, 'ports', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); $environment = convertToKeyValueCollection($environment); $coolifyEnvironments = collect([]); $isDatabase = isDatabaseImage($image, $service); $volumesParsed = collect([]); $baseName = generateApplicationContainerName( application: $resource, pull_request_id: $pullRequestId ); $containerName = "$serviceName-$baseName"; $predefinedPort = null; $originalResource = $resource; if ($volumes->count() > 0) { foreach ($volumes as $index => $volume) { $type = null; $source = null; $target = null; $content = null; $isDirectory = false; if (is_string($volume)) { $parsed = parseDockerVolumeString($volume); $source = $parsed['source']; $target = $parsed['target']; // Mode is available in $parsed['mode'] if needed $foundConfig = $fileStorages->whereMountPath($target)->first(); if (sourceIsLocal($source)) { $type = str('bind'); if ($foundConfig) { $contentNotNull_temp = data_get($foundConfig, 'content'); if ($contentNotNull_temp) { $content = $contentNotNull_temp; } $isDirectory = data_get($foundConfig, 'is_directory'); } else { // By default, we cannot determine if the bind is a directory or not, so we set it to directory $isDirectory = true; } } else { $type = str('volume'); } } elseif (is_array($volume)) { $type = data_get_str($volume, 'type'); $source = data_get_str($volume, 'source'); $target = data_get_str($volume, 'target'); $content = data_get($volume, 'content'); $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); // Validate source and target for command injection (array/long syntax) if ($source !== null && ! empty($source->value())) { $sourceValue = $source->value(); // Allow environment variable references and env vars with path concatenation $isSimpleEnvVar = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/', $sourceValue); $isEnvVarWithDefault = preg_match('/^\$\{[^}]+:-[^}]*\}$/', $sourceValue); $isEnvVarWithPath = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}[\/\w\.\-]*$/', $sourceValue); if (! $isSimpleEnvVar && ! $isEnvVarWithDefault && ! $isEnvVarWithPath) { try { validateShellSafePath($sourceValue, 'volume source'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker volume definition (array syntax): '.$e->getMessage(). ' Please use safe path names without shell metacharacters.' ); } } } if ($target !== null && ! empty($target->value())) { try { validateShellSafePath($target->value(), 'volume target'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker volume definition (array syntax): '.$e->getMessage(). ' Please use safe path names without shell metacharacters.' ); } } $foundConfig = $fileStorages->whereMountPath($target)->first(); if ($foundConfig) { $contentNotNull_temp = data_get($foundConfig, 'content'); if ($contentNotNull_temp) { $content = $contentNotNull_temp; } $isDirectory = data_get($foundConfig, 'is_directory'); } else { // if isDirectory is not set (or false) & content is also not set, we assume it is a directory if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) { $isDirectory = true; } } } if ($type->value() === 'bind') { if ($source->value() === '/var/run/docker.sock') { $volume = $source->value().':'.$target->value(); if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } elseif ($source->value() === '/tmp' || $source->value() === '/tmp/') { $volume = $source->value().':'.$target->value(); if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } else { if ((int) $resource->compose_parsing_version >= 4) { $mainDirectory = str(base_configuration_dir().'/applications/'.$uuid); } else { $mainDirectory = str(base_configuration_dir().'/applications/'.$uuid); } $source = replaceLocalSource($source, $mainDirectory); if ($isPullRequest) { $source = addPreviewDeploymentSuffix($source, $pull_request_id); } LocalFileVolume::updateOrCreate( [ 'mount_path' => $target, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ], [ 'fs_path' => $source, 'mount_path' => $target, 'content' => $content, 'is_directory' => $isDirectory, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ] ); if (isDev()) { if ((int) $resource->compose_parsing_version >= 4) { $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/applications/'.$uuid); } else { $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/applications/'.$uuid); } } $volume = "$source:$target"; if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } } elseif ($type->value() === 'volume') { if ($topLevel->get('volumes')->has($source->value())) { $temp = $topLevel->get('volumes')->get($source->value()); if (data_get($temp, 'driver_opts.type') === 'cifs') { continue; } if (data_get($temp, 'driver_opts.type') === 'nfs') { continue; } } $slugWithoutUuid = Str::slug($source, '-'); $name = "{$uuid}_{$slugWithoutUuid}"; if ($isPullRequest) { $name = addPreviewDeploymentSuffix($name, $pull_request_id); } if (is_string($volume)) { $parsed = parseDockerVolumeString($volume); $source = $parsed['source']; $target = $parsed['target']; $source = $name; $volume = "$source:$target"; if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } elseif (is_array($volume)) { data_set($volume, 'source', $name); } $topLevel->get('volumes')->put($name, [ 'name' => $name, ]); LocalPersistentVolume::updateOrCreate( [ 'name' => $name, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ], [ 'name' => $name, 'mount_path' => $target, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ] ); } dispatch(new ServerFilesFromServerJob($originalResource)); $volumesParsed->put($index, $volume); } } if ($depends_on?->count() > 0) { if ($isPullRequest) { $newDependsOn = collect([]); $depends_on->each(function ($dependency, $condition) use ($pullRequestId, $newDependsOn) { if (is_numeric($condition)) { $dependency = addPreviewDeploymentSuffix($dependency, $pullRequestId); $newDependsOn->put($condition, $dependency); } else { $condition = addPreviewDeploymentSuffix($condition, $pullRequestId); $newDependsOn->put($condition, $dependency); } }); $depends_on = $newDependsOn; } } if (! $use_network_mode) { if ($topLevel->get('networks')?->count() > 0) { foreach ($topLevel->get('networks') as $networkName => $network) { if ($networkName === 'default') { continue; } // ignore aliases if ($network['aliases'] ?? false) { continue; } $networkExists = $networks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); if (! $networkExists) { $networks->put($networkName, null); } } } $baseNetworkExists = $networks->contains(function ($value, $_) use ($baseNetwork) { return $value == $baseNetwork; }); if (! $baseNetworkExists) { foreach ($baseNetwork as $network) { $topLevel->get('networks')->put($network, [ 'name' => $network, 'external' => true, ]); } } } // Collect/create/update ports $collectedPorts = collect([]); if ($ports->count() > 0) { foreach ($ports as $sport) { if (is_string($sport) || is_numeric($sport)) { $collectedPorts->push($sport); } if (is_array($sport)) { $target = data_get($sport, 'target'); $published = data_get($sport, 'published'); $protocol = data_get($sport, 'protocol'); $collectedPorts->push("$target:$published/$protocol"); } } } $networks_temp = collect(); if (! $use_network_mode) { foreach ($networks as $key => $network) { if (gettype($network) === 'string') { // networks: // - appwrite $networks_temp->put($network, null); } elseif (gettype($network) === 'array') { // networks: // default: // ipv4_address: 192.168.203.254 $networks_temp->put($key, $network); } } foreach ($baseNetwork as $key => $network) { $networks_temp->put($network, null); } if (data_get($resource, 'settings.connect_to_docker_network')) { $network = $resource->destination->network; $networks_temp->put($network, null); $topLevel->get('networks')->put($network, [ 'name' => $network, 'external' => true, ]); } } $normalEnvironments = $environment->diffKeys($allMagicEnvironments); $normalEnvironments = $normalEnvironments->filter(function ($value, $key) { return ! str($value)->startsWith('SERVICE_'); }); foreach ($normalEnvironments as $key => $value) { $key = str($key); $value = str($value); $originalValue = $value; $parsedValue = replaceVariables($value); if ($value->startsWith('$SERVICE_')) { $resource->environment_variables()->firstOrCreate([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $value, 'is_preview' => false, ]); continue; } if (! $value->startsWith('$')) { continue; } if ($key->value() === $parsedValue->value()) { // Simple variable reference (e.g. DATABASE_URL: ${DATABASE_URL}) // Use firstOrCreate to avoid overwriting user-saved values on redeploy $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, ]); // Add the variable to the environment using the saved DB value $environment[$key->value()] = $envVar->value; } else { if ($value->startsWith('$')) { $isRequired = false; // Extract variable content between ${...} using balanced brace matching $result = extractBalancedBraceContent($value->value(), 0); if ($result !== null) { $content = $result['content']; $split = splitOnOperatorOutsideNested($content); if ($split !== null) { // Has default value syntax (:-, -, :?, or ?) $varName = $split['variable']; $operator = $split['operator']; $defaultValue = $split['default']; $isRequired = str_contains($operator, '?'); // Create the primary variable with its default (only if it doesn't exist) $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $varName, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $defaultValue, 'is_preview' => false, 'is_required' => $isRequired, ]); // Add the variable to the environment so it will be shown in the deployable compose file $environment[$varName] = $envVar->value; // Recursively process nested variables in default value if (str_contains($defaultValue, '${')) { $searchPos = 0; $nestedResult = extractBalancedBraceContent($defaultValue, $searchPos); while ($nestedResult !== null) { $nestedContent = $nestedResult['content']; $nestedSplit = splitOnOperatorOutsideNested($nestedContent); // Determine the nested variable name $nestedVarName = $nestedSplit !== null ? $nestedSplit['variable'] : $nestedContent; // Skip SERVICE_URL_* and SERVICE_FQDN_* variables - they are handled by magic variable system $isMagicVariable = str_starts_with($nestedVarName, 'SERVICE_URL_') || str_starts_with($nestedVarName, 'SERVICE_FQDN_'); if (! $isMagicVariable) { if ($nestedSplit !== null) { $nestedEnvVar = $resource->environment_variables()->firstOrCreate([ 'key' => $nestedSplit['variable'], 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $nestedSplit['default'], 'is_preview' => false, ]); $environment[$nestedSplit['variable']] = $nestedEnvVar->value; } else { $nestedEnvVar = $resource->environment_variables()->firstOrCreate([ 'key' => $nestedContent, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, ]); $environment[$nestedContent] = $nestedEnvVar->value; } } $searchPos = $nestedResult['end'] + 1; if ($searchPos >= strlen($defaultValue)) { break; } $nestedResult = extractBalancedBraceContent($defaultValue, $searchPos); } } } else { // Simple variable reference without default $parsedKeyValue = replaceVariables($value); $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $content, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, 'is_required' => $isRequired, ]); // Add the variable to the environment using the saved DB value $environment[$content] = $envVar->value; } } else { // Fallback to old behavior for malformed input (backward compatibility) if ($value->contains(':-')) { $value = replaceVariables($value); $key = $value->before(':'); $value = $value->after(':-'); } elseif ($value->contains('-')) { $value = replaceVariables($value); $key = $value->before('-'); $value = $value->after('-'); } elseif ($value->contains(':?')) { $value = replaceVariables($value); $key = $value->before(':'); $value = $value->after(':?'); $isRequired = true; } elseif ($value->contains('?')) { $value = replaceVariables($value); $key = $value->before('?'); $value = $value->after('?'); $isRequired = true; } if ($originalValue->value() === $value->value()) { // This means the variable does not have a default value $parsedKeyValue = replaceVariables($value); $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $parsedKeyValue, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, 'is_required' => $isRequired, ]); // Add the variable to the environment using the saved DB value $environment[$parsedKeyValue->value()] = $envVar->value; continue; } $resource->environment_variables()->firstOrCreate([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $value, 'is_preview' => false, 'is_required' => $isRequired, ]); } } } } $branch = $originalResource->git_branch; if ($pullRequestId !== 0) { $branch = "pull/{$pullRequestId}/head"; } if ($originalResource->environment_variables->where('key', 'COOLIFY_BRANCH')->isEmpty()) { $coolifyEnvironments->put('COOLIFY_BRANCH', "\"{$branch}\""); } // Add COOLIFY_RESOURCE_UUID to environment if ($resource->environment_variables->where('key', 'COOLIFY_RESOURCE_UUID')->isEmpty()) { $coolifyEnvironments->put('COOLIFY_RESOURCE_UUID', "{$resource->uuid}"); } // Add COOLIFY_CONTAINER_NAME to environment if ($resource->environment_variables->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) { $coolifyEnvironments->put('COOLIFY_CONTAINER_NAME', "{$containerName}"); } if ($isPullRequest) { $preview = $resource->previews()->find($preview_id); $domains = collect(json_decode(data_get($preview, 'docker_compose_domains'))) ?? collect([]); } else { $domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]); } // Only process domains for dockercompose applications to prevent SERVICE variable recreation if ($resource->build_pack !== 'dockercompose') { $domains = collect([]); } $changedServiceName = str($serviceName)->replace('-', '_')->replace('.', '_')->value(); $fqdns = data_get($domains, "$changedServiceName.domain"); // Generate SERVICE_FQDN & SERVICE_URL for dockercompose if ($resource->build_pack === 'dockercompose') { foreach ($domains as $forServiceName => $domain) { $parsedDomain = data_get($domain, 'domain'); $serviceNameFormatted = str($serviceName)->upper()->replace('-', '_')->replace('.', '_'); if (filled($parsedDomain)) { $parsedDomain = str($parsedDomain)->explode(',')->first(); $coolifyUrl = Url::fromString($parsedDomain); $coolifyScheme = $coolifyUrl->getScheme(); $coolifyFqdn = $coolifyUrl->getHost(); $coolifyUrl = $coolifyUrl->withScheme($coolifyScheme)->withHost($coolifyFqdn)->withPort(null); $coolifyEnvironments->put('SERVICE_URL_'.str($forServiceName)->upper()->replace('-', '_')->replace('.', '_'), $coolifyUrl->__toString()); $coolifyEnvironments->put('SERVICE_FQDN_'.str($forServiceName)->upper()->replace('-', '_')->replace('.', '_'), $coolifyFqdn); $resource->environment_variables()->updateOrCreate([ 'resourceable_type' => Application::class, 'resourceable_id' => $resource->id, 'key' => 'SERVICE_URL_'.str($forServiceName)->upper()->replace('-', '_')->replace('.', '_'), ], [ 'value' => $coolifyUrl->__toString(), 'is_preview' => false, ]); $resource->environment_variables()->updateOrCreate([ 'resourceable_type' => Application::class, 'resourceable_id' => $resource->id, 'key' => 'SERVICE_FQDN_'.str($forServiceName)->upper()->replace('-', '_')->replace('.', '_'), ], [ 'value' => $coolifyFqdn, 'is_preview' => false, ]); } else { $resource->environment_variables()->where('resourceable_type', Application::class) ->where('resourceable_id', $resource->id) ->where('key', 'LIKE', "SERVICE_FQDN_{$serviceNameFormatted}%") ->update([ 'value' => null, ]); $resource->environment_variables()->where('resourceable_type', Application::class) ->where('resourceable_id', $resource->id) ->where('key', 'LIKE', "SERVICE_URL_{$serviceNameFormatted}%") ->update([ 'value' => null, ]); } } } // If the domain is set, we need to generate the FQDNs for the preview if (filled($fqdns)) { $fqdns = str($fqdns)->explode(','); if ($isPullRequest) { $preview = $resource->previews()->find($preview_id); $docker_compose_domains = collect(json_decode(data_get($preview, 'docker_compose_domains'))); if ($docker_compose_domains->count() > 0) { $found_fqdn = data_get($docker_compose_domains, "$changedServiceName.domain"); if ($found_fqdn) { $fqdns = collect($found_fqdn); } else { $fqdns = collect([]); } } else { $fqdns = $fqdns->map(function ($fqdn) use ($pullRequestId, $resource) { $preview = ApplicationPreview::findPreviewByApplicationAndPullId($resource->id, $pullRequestId); $url = Url::fromString($fqdn); $template = $resource->preview_url_template; $host = $url->getHost(); $schema = $url->getScheme(); $portInt = $url->getPort(); $port = $portInt !== null ? ':'.$portInt : ''; $random = new Cuid2; $preview_fqdn = str_replace('{{random}}', $random, $template); $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); $preview_fqdn = str_replace('{{pr_id}}', $pullRequestId, $preview_fqdn); $preview_fqdn = "$schema://$preview_fqdn{$port}"; $preview->fqdn = $preview_fqdn; $preview->save(); return $preview_fqdn; }); } } } $defaultLabels = defaultLabels( id: $resource->id, name: $containerName, projectName: $resource->project()->name, resourceName: $resource->name, pull_request_id: $pullRequestId, type: 'application', environment: $resource->environment->name, ); $isDatabase = isDatabaseImage($image, $service); // Add COOLIFY_FQDN & COOLIFY_URL to environment if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { $fqdnsWithoutPort = $fqdns->map(function ($fqdn) { return str($fqdn)->after('://')->before(':')->prepend(str($fqdn)->before('://')->append('://')); }); $coolifyEnvironments->put('COOLIFY_URL', $fqdnsWithoutPort->implode(',')); $urls = $fqdns->map(function ($fqdn) { return str($fqdn)->replace('http://', '')->replace('https://', '')->before(':'); }); $coolifyEnvironments->put('COOLIFY_FQDN', $urls->implode(',')); } add_coolify_default_environment_variables($resource, $coolifyEnvironments, $resource->environment_variables); if ($environment->count() > 0) { $environment = $environment->filter(function ($value, $key) { return ! str($key)->startsWith('SERVICE_FQDN_'); })->map(function ($value, $key) use ($resource) { // Preserve empty strings and null values with correct Docker Compose semantics: // - Empty string: Variable is set to "" (e.g., HTTP_PROXY="" means "no proxy") // - Null: Variable is unset/removed from container environment (may inherit from host) if ($value === null) { // User explicitly wants variable unset - respect that // NEVER override from database - null means "inherit from environment" // Keep as null (will be excluded from container environment) } elseif ($value === '') { // Empty string - allow database override for backward compatibility $dbEnv = $resource->environment_variables()->where('key', $key)->first(); // Only use database override if it exists AND has a non-empty value if ($dbEnv && str($dbEnv->value)->isNotEmpty()) { $value = $dbEnv->value; } // Otherwise keep empty string as-is } // Resolve shared variable patterns like {{environment.VAR}}, {{project.VAR}}, {{team.VAR}} // Without this, literal {{...}} strings end up in the compose environment: section, // which takes precedence over the resolved values in the .env file (env_file:) if (is_string($value) && str_contains($value, '{{')) { $value = resolveSharedEnvironmentVariables($value, $resource); } return $value; }); } $serviceLabels = $labels->merge($defaultLabels); if ($serviceLabels->count() > 0) { $isContainerLabelEscapeEnabled = data_get($resource, 'settings.is_container_label_escape_enabled'); if ($isContainerLabelEscapeEnabled) { $serviceLabels = $serviceLabels->map(function ($value, $key) { return escapeDollarSign($value); }); } } if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { $shouldGenerateLabelsExactly = $resource->destination->server->settings->generate_exact_labels; $uuid = $resource->uuid; $network = data_get($resource, 'destination.network'); if ($isPullRequest) { $uuid = "{$resource->uuid}-{$pullRequestId}"; } if ($isPullRequest) { $network = "{$resource->destination->network}-{$pullRequestId}"; } if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: $originalResource->isForceHttpsEnabled(), serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image )); break; case ProxyTypes::CADDY->value: $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, is_force_https_enabled: $originalResource->isForceHttpsEnabled(), serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image, predefinedPort: $predefinedPort )); break; } } else { $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: $originalResource->isForceHttpsEnabled(), serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image )); $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, is_force_https_enabled: $originalResource->isForceHttpsEnabled(), serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image, predefinedPort: $predefinedPort )); } } data_forget($service, 'volumes.*.content'); data_forget($service, 'volumes.*.isDirectory'); data_forget($service, 'volumes.*.is_directory'); data_forget($service, 'exclude_from_hc'); $volumesParsed = $volumesParsed->map(function ($volume) { data_forget($volume, 'content'); data_forget($volume, 'is_directory'); data_forget($volume, 'isDirectory'); return $volume; }); $payload = collect($service)->merge([ 'container_name' => $containerName, 'restart' => $restart->value(), 'labels' => $serviceLabels, ]); if (! $use_network_mode) { $payload['networks'] = $networks_temp; } if ($ports->count() > 0) { $payload['ports'] = $ports; } if ($volumesParsed->count() > 0) { $payload['volumes'] = $volumesParsed; } if ($environment->count() > 0 || $coolifyEnvironments->count() > 0) { $payload['environment'] = $environment->merge($coolifyEnvironments)->merge($serviceNameEnvironments); } if ($logging) { $payload['logging'] = $logging; } if ($depends_on->count() > 0) { $payload['depends_on'] = $depends_on; } // Auto-inject .env file so Coolify environment variables are available inside containers // This makes Applications behave consistently with manual .env file usage $existingEnvFiles = data_get($service, 'env_file'); $envFiles = collect(is_null($existingEnvFiles) ? [] : (is_array($existingEnvFiles) ? $existingEnvFiles : [$existingEnvFiles])) ->push('.env') ->unique() ->values(); $payload['env_file'] = $envFiles; // Inject commit-based image tag for services with build directive (for rollback support) // Only inject if service has build but no explicit image defined $hasBuild = data_get($service, 'build') !== null; $hasImage = data_get($service, 'image') !== null; if ($hasBuild && ! $hasImage && $commit) { $imageTag = str($commit)->substr(0, 128)->value(); if ($isPullRequest) { $imageTag = "pr-{$pullRequestId}"; } $imageRepo = "{$uuid}_{$serviceName}"; $payload['image'] = "{$imageRepo}:{$imageTag}"; } if ($isPullRequest) { $serviceName = addPreviewDeploymentSuffix($serviceName, $pullRequestId); } $parsedServices->put($serviceName, $payload); } $topLevel->put('services', $parsedServices); $customOrder = ['services', 'volumes', 'networks', 'configs', 'secrets']; $topLevel = $topLevel->sortBy(function ($value, $key) use ($customOrder) { return array_search($key, $customOrder); }); // Remove empty top-level sections (volumes, networks, configs, secrets) // Keep only non-empty sections to match Docker Compose best practices $topLevel = $topLevel->filter(function ($value, $key) { // Always keep 'services' section if ($key === 'services') { return true; } // Keep section only if it has content return $value instanceof Collection ? $value->isNotEmpty() : ! empty($value); }); $cleanedCompose = Yaml::dump(convertToArray($topLevel), 10, 2); $resource->docker_compose = $cleanedCompose; // Update docker_compose_raw to remove content: from volumes only // This keeps the original user input clean while preventing content reapplication // Parse the original compose again to create a clean version without Coolify additions try { $originalYaml = Yaml::parse($originalCompose); // Remove content, isDirectory, and is_directory from all volume definitions if (isset($originalYaml['services'])) { foreach ($originalYaml['services'] as $serviceName => &$service) { if (isset($service['volumes'])) { foreach ($service['volumes'] as $key => &$volume) { if (is_array($volume)) { unset($volume['content']); unset($volume['isDirectory']); unset($volume['is_directory']); } } } } } $resource->docker_compose_raw = Yaml::dump($originalYaml, 10, 2); } catch (\Exception $e) { // If parsing fails, keep the original docker_compose_raw unchanged ray('Failed to update docker_compose_raw in applicationParser: '.$e->getMessage()); } data_forget($resource, 'environment_variables'); data_forget($resource, 'environment_variables_preview'); $resource->save(); return $topLevel; } function serviceParser(Service $resource): Collection { $uuid = data_get($resource, 'uuid'); $compose = data_get($resource, 'docker_compose_raw'); // Store original compose for later use to update docker_compose_raw with content removed $originalCompose = $compose; if (! $compose) { return collect([]); } // Extract inline comments from raw YAML before Symfony parser discards them $envComments = extractYamlEnvironmentComments($compose); $server = data_get($resource, 'server'); $allServices = get_service_templates(); try { $yaml = Yaml::parse($compose); } catch (\Exception) { return collect([]); } $services = data_get($yaml, 'services', collect([])); // Clean up corrupted environment variables from previous parser bugs // (keys starting with $ or ending with } should not exist as env var names) $resource->environment_variables() ->where('resourceable_type', get_class($resource)) ->where('resourceable_id', $resource->id) ->where(function ($q) { $q->where('key', 'LIKE', '$%') ->orWhere('key', 'LIKE', '%}'); }) ->delete(); $topLevel = collect([ 'volumes' => collect(data_get($yaml, 'volumes', [])), 'networks' => collect(data_get($yaml, 'networks', [])), 'configs' => collect(data_get($yaml, 'configs', [])), 'secrets' => collect(data_get($yaml, 'secrets', [])), ]); // If there are predefined volumes, make sure they are not null if ($topLevel->get('volumes')->count() > 0) { $temp = collect([]); foreach ($topLevel['volumes'] as $volumeName => $volume) { if (is_null($volume)) { continue; } $temp->put($volumeName, $volume); } $topLevel['volumes'] = $temp; } // Get the base docker network $baseNetwork = collect([$uuid]); $parsedServices = collect([]); // Generate SERVICE_NAME variables for docker compose services $serviceNameEnvironments = generateDockerComposeServiceName($services); $allMagicEnvironments = collect([]); // Presave services foreach ($services as $serviceName => $service) { // Validate service name for command injection try { validateShellSafePath($serviceName, 'service name'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker Compose service name: '.$e->getMessage(). ' Service names must not contain shell metacharacters.' ); } $image = data_get_str($service, 'image'); // Check for manually migrated services first (respects user's conversion choice) $migratedApp = ServiceApplication::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); $migratedDb = ServiceDatabase::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); if ($migratedApp || $migratedDb) { // Use the migrated service type, ignoring image detection $isDatabase = (bool) $migratedDb; $savedService = $migratedApp ?: $migratedDb; } else { // Use image detection for non-migrated services $isDatabase = isDatabaseImage($image, $service); if ($isDatabase) { $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); if ($applicationFound) { $savedService = $applicationFound; } else { $savedService = ServiceDatabase::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, ]); } } else { $savedService = ServiceApplication::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, ]); } } // Update image if it changed if ($savedService->image !== $image) { $savedService->image = $image; $savedService->save(); } } foreach ($services as $serviceName => $service) { $predefinedPort = null; $magicEnvironments = collect([]); $image = data_get_str($service, 'image'); $environment = collect(data_get($service, 'environment', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); // Check for manually migrated services first (respects user's conversion choice) $migratedApp = ServiceApplication::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); $migratedDb = ServiceDatabase::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); if ($migratedApp || $migratedDb) { // Use the migrated service type, ignoring image detection $isDatabase = (bool) $migratedDb; } else { // Use image detection for non-migrated services $isDatabase = isDatabaseImage($image, $service); } $containerName = "$serviceName-{$resource->uuid}"; if ($serviceName === 'registry') { $tempServiceName = 'docker-registry'; } else { $tempServiceName = $serviceName; } if (str(data_get($service, 'image'))->contains('glitchtip')) { $tempServiceName = 'glitchtip'; } if ($serviceName === 'supabase-kong') { $tempServiceName = 'supabase'; } $serviceDefinition = data_get($allServices, $tempServiceName); $predefinedPort = data_get($serviceDefinition, 'port'); if ($serviceName === 'plausible') { $predefinedPort = '8000'; } if ($migratedApp || $migratedDb) { // Use the already determined migrated service $savedService = $migratedApp ?: $migratedDb; } elseif ($isDatabase) { $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); if ($applicationFound) { $savedService = $applicationFound; } else { $savedService = ServiceDatabase::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, ]); } } else { $savedService = ServiceApplication::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, ], [ 'is_gzip_enabled' => true, ]); } // Check if image changed if ($savedService->image !== $image) { $savedService->image = $image; $savedService->save(); } // Pocketbase does not need gzip for SSE. if (str($savedService->image)->contains('pocketbase') && $savedService->is_gzip_enabled) { $savedService->is_gzip_enabled = false; $savedService->save(); } $environment = collect(data_get($service, 'environment', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); // convert environment variables to one format $environment = convertToKeyValueCollection($environment); // Add Coolify defined environments $allEnvironments = $resource->environment_variables()->get(['key', 'value']); $allEnvironments = $allEnvironments->mapWithKeys(function ($item) { return [$item['key'] => $item['value']]; }); // filter and add magic environments foreach ($environment as $key => $value) { // Get all SERVICE_ variables from keys and values $key = str($key); $value = str($value); $regex = '/\$(\{?([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\}?)/'; preg_match_all($regex, $value, $valueMatches); if (count($valueMatches[2]) > 0) { foreach ($valueMatches[2] as $match) { $match = str($match); if ($match->startsWith('SERVICE_')) { if ($magicEnvironments->has($match->value())) { continue; } $magicEnvironments->put($match->value(), ''); } } } // Get magic environments where we need to preset the FQDN / URL if ($key->startsWith('SERVICE_FQDN_') || $key->startsWith('SERVICE_URL_')) { // SERVICE_FQDN_APP or SERVICE_FQDN_APP_3000 or SERVICE_URL_APP or SERVICE_URL_APP_3000 // ALWAYS create BOTH SERVICE_URL and SERVICE_FQDN pairs regardless of which one is in template $parsed = parseServiceEnvironmentVariable($key->value()); // Extract service name preserving original case from template $strKey = str($key->value()); if ($parsed['has_port']) { if ($strKey->startsWith('SERVICE_URL_')) { $serviceName = $strKey->after('SERVICE_URL_')->beforeLast('_')->value(); } elseif ($strKey->startsWith('SERVICE_FQDN_')) { $serviceName = $strKey->after('SERVICE_FQDN_')->beforeLast('_')->value(); } else { continue; } } else { if ($strKey->startsWith('SERVICE_URL_')) { $serviceName = $strKey->after('SERVICE_URL_')->value(); } elseif ($strKey->startsWith('SERVICE_FQDN_')) { $serviceName = $strKey->after('SERVICE_FQDN_')->value(); } else { continue; } } $port = $parsed['port']; $fqdnFor = $parsed['service_name']; // Only ServiceApplication has fqdn column, ServiceDatabase does not $isServiceApplication = $savedService instanceof ServiceApplication; if ($isServiceApplication && blank($savedService->fqdn)) { $fqdn = generateFqdn(server: $server, random: "$fqdnFor-$uuid", parserVersion: $resource->compose_parsing_version); $url = generateUrl($server, "$fqdnFor-$uuid"); } elseif ($isServiceApplication) { $fqdn = str($savedService->fqdn)->after('://')->before(':')->prepend(str($savedService->fqdn)->before('://')->append('://'))->value(); $url = str($savedService->fqdn)->after('://')->before(':')->prepend(str($savedService->fqdn)->before('://')->append('://'))->value(); } else { // For ServiceDatabase, generate fqdn/url without saving to the model $fqdn = generateFqdn(server: $server, random: "$fqdnFor-$uuid", parserVersion: $resource->compose_parsing_version); $url = generateUrl($server, "$fqdnFor-$uuid"); } // IMPORTANT: SERVICE_FQDN env vars should NOT contain scheme (host only) // But $fqdn variable itself may contain scheme (used for database domain field) // Strip scheme for environment variable values $fqdnValueForEnv = str($fqdn)->after('://')->value(); if ($value && get_class($value) === \Illuminate\Support\Stringable::class && $value->startsWith('/')) { $path = $value->value(); if ($path !== '/') { // Only add path if it's not already present (prevents duplication on subsequent parse() calls) if (! str($fqdn)->endsWith($path)) { $fqdn = "$fqdn$path"; } if (! str($url)->endsWith($path)) { $url = "$url$path"; } if (! str($fqdnValueForEnv)->endsWith($path)) { $fqdnValueForEnv = "$fqdnValueForEnv$path"; } } } $urlWithPort = $url; $fqdnValueForEnvWithPort = $fqdnValueForEnv; if ($fqdn && $port) { $fqdnValueForEnvWithPort = "$fqdnValueForEnv:$port"; } if ($url && $port) { $urlWithPort = "$url:$port"; } // Only save fqdn to ServiceApplication, not ServiceDatabase if ($isServiceApplication && is_null($savedService->fqdn)) { // Save URL (with scheme) to database, not FQDN if ((int) $resource->compose_parsing_version >= 5 && version_compare(config('constants.coolify.version'), '4.0.0-beta.420.7', '>=')) { $savedService->fqdn = $urlWithPort; } else { $savedService->fqdn = $urlWithPort; } $savedService->save(); } // ALWAYS create BOTH base SERVICE_URL and SERVICE_FQDN pairs (without port) $fqdnKey = "SERVICE_FQDN_{$serviceName}"; $resource->environment_variables()->updateOrCreate([ 'key' => $fqdnKey, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdnValueForEnv, 'is_preview' => false, 'comment' => $envComments[$fqdnKey] ?? null, ]); $urlKey = "SERVICE_URL_{$serviceName}"; $resource->environment_variables()->updateOrCreate([ 'key' => $urlKey, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $url, 'is_preview' => false, 'comment' => $envComments[$urlKey] ?? null, ]); // For port-specific variables, ALSO create port-specific pairs // If template variable has port, create both URL and FQDN with port suffix if ($parsed['has_port'] && $port) { $fqdnPortKey = "SERVICE_FQDN_{$serviceName}_{$port}"; $resource->environment_variables()->updateOrCreate([ 'key' => $fqdnPortKey, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdnValueForEnvWithPort, 'is_preview' => false, 'comment' => $envComments[$fqdnPortKey] ?? null, ]); $urlPortKey = "SERVICE_URL_{$serviceName}_{$port}"; $resource->environment_variables()->updateOrCreate([ 'key' => $urlPortKey, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $urlWithPort, 'is_preview' => false, 'comment' => $envComments[$urlPortKey] ?? null, ]); } } } $allMagicEnvironments = $allMagicEnvironments->merge($magicEnvironments); if ($magicEnvironments->count() > 0) { foreach ($magicEnvironments as $magicKey => $value) { $originalMagicKey = $magicKey; // Preserve original key for comment lookup $key = str($magicKey); $value = replaceVariables($value); $command = parseCommandFromMagicEnvVariable($key); if ($command->value() === 'FQDN') { $fqdnFor = $key->after('SERVICE_FQDN_')->lower()->value(); $fqdn = generateFqdn(server: $server, random: str($fqdnFor)->replace('_', '-')->value()."-$uuid", parserVersion: $resource->compose_parsing_version); $url = generateUrl(server: $server, random: str($fqdnFor)->replace('_', '-')->value()."-$uuid"); $envExists = $resource->environment_variables()->where('key', $key->value())->first(); // Also check if a port-suffixed version exists (e.g., SERVICE_FQDN_UMAMI_3000) $portSuffixedExists = $resource->environment_variables() ->where('key', 'LIKE', $key->value().'_%') ->whereRaw('key ~ ?', ['^'.$key->value().'_[0-9]+$']) ->exists(); $serviceExists = ServiceApplication::where('name', str($fqdnFor)->replace('_', '-')->value())->where('service_id', $resource->id)->first(); // Check if FQDN already has a port set (contains ':' after the domain) $fqdnHasPort = $serviceExists && str($serviceExists->fqdn)->contains(':') && str($serviceExists->fqdn)->afterLast(':')->isMatch('/^\d+$/'); // Only set FQDN if it's for the current service being processed (prevent race conditions) $isCurrentService = $serviceExists && $serviceExists->id === $savedService->id; if (! $envExists && ! $portSuffixedExists && ! $fqdnHasPort && $isCurrentService && (data_get($serviceExists, 'name') === str($fqdnFor)->replace('_', '-')->value())) { // Save URL otherwise it won't work. $serviceExists->fqdn = $url; $serviceExists->save(); } // Create FQDN variable (use firstOrCreate to avoid overwriting values // already set by direct template declarations or updateCompose) $resource->environment_variables()->firstOrCreate([ 'key' => $key->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdn, 'is_preview' => false, 'comment' => $envComments[$originalMagicKey] ?? null, ]); // Also create the paired SERVICE_URL_* variable $urlKey = 'SERVICE_URL_'.strtoupper($fqdnFor); $resource->environment_variables()->firstOrCreate([ 'key' => $urlKey, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $url, 'is_preview' => false, 'comment' => $envComments[$urlKey] ?? null, ]); } elseif ($command->value() === 'URL') { $urlFor = $key->after('SERVICE_URL_')->lower()->value(); $url = generateUrl(server: $server, random: str($urlFor)->replace('_', '-')->value()."-$uuid"); $fqdn = generateFqdn(server: $server, random: str($urlFor)->replace('_', '-')->value()."-$uuid", parserVersion: $resource->compose_parsing_version); $envExists = $resource->environment_variables()->where('key', $key->value())->first(); // Also check if a port-suffixed version exists (e.g., SERVICE_URL_DASHBOARD_6791) $portSuffixedExists = $resource->environment_variables() ->where('key', 'LIKE', $key->value().'_%') ->whereRaw('key ~ ?', ['^'.$key->value().'_[0-9]+$']) ->exists(); $serviceExists = ServiceApplication::where('name', str($urlFor)->replace('_', '-')->value())->where('service_id', $resource->id)->first(); // Check if FQDN already has a port set (contains ':' after the domain) $fqdnHasPort = $serviceExists && str($serviceExists->fqdn)->contains(':') && str($serviceExists->fqdn)->afterLast(':')->isMatch('/^\d+$/'); // Only set FQDN if it's for the current service being processed (prevent race conditions) $isCurrentService = $serviceExists && $serviceExists->id === $savedService->id; if (! $envExists && ! $portSuffixedExists && ! $fqdnHasPort && $isCurrentService && (data_get($serviceExists, 'name') === str($urlFor)->replace('_', '-')->value())) { $serviceExists->fqdn = $url; $serviceExists->save(); } // Create URL variable (use firstOrCreate to avoid overwriting values // already set by direct template declarations or updateCompose) $resource->environment_variables()->firstOrCreate([ 'key' => $key->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $url, 'is_preview' => false, 'comment' => $envComments[$originalMagicKey] ?? null, ]); // Also create the paired SERVICE_FQDN_* variable $fqdnKey = 'SERVICE_FQDN_'.strtoupper($urlFor); $resource->environment_variables()->firstOrCreate([ 'key' => $fqdnKey, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $fqdn, 'is_preview' => false, 'comment' => $envComments[$fqdnKey] ?? null, ]); } else { $value = generateEnvValue($command, $resource); $resource->environment_variables()->firstOrCreate([ 'key' => $key->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $value, 'is_preview' => false, 'comment' => $envComments[$originalMagicKey] ?? null, ]); } } } } $serviceAppsLogDrainEnabledMap = $resource->applications()->get()->keyBy('name')->map(function ($app) { return $app->isLogDrainEnabled(); }); // Parse the rest of the services foreach ($services as $serviceName => $service) { $image = data_get_str($service, 'image'); $restart = data_get_str($service, 'restart', RESTART_MODE); $logging = data_get($service, 'logging'); if ($server->isLogDrainEnabled()) { if ($serviceAppsLogDrainEnabledMap->get($serviceName)) { $logging = generate_fluentd_configuration(); } } $volumes = collect(data_get($service, 'volumes', [])); $networks = collect(data_get($service, 'networks', [])); $use_network_mode = data_get($service, 'network_mode') !== null; $depends_on = collect(data_get($service, 'depends_on', [])); $labels = collect(data_get($service, 'labels', [])); if ($labels->count() > 0) { if (isAssociativeArray($labels)) { $newLabels = collect([]); $labels->each(function ($value, $key) use ($newLabels) { $newLabels->push("$key=$value"); }); $labels = $newLabels; } } $environment = collect(data_get($service, 'environment', [])); $ports = collect(data_get($service, 'ports', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); $environment = convertToKeyValueCollection($environment); $coolifyEnvironments = collect([]); // Check for manually migrated services first (respects user's conversion choice) $migratedApp = ServiceApplication::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); $migratedDb = ServiceDatabase::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); if ($migratedApp || $migratedDb) { // Use the migrated service type, ignoring image detection $isDatabase = (bool) $migratedDb; $savedService = $migratedApp ?: $migratedDb; } else { // Use image detection for non-migrated services $isDatabase = isDatabaseImage($image, $service); } $volumesParsed = collect([]); $containerName = "$serviceName-{$resource->uuid}"; if ($serviceName === 'registry') { $tempServiceName = 'docker-registry'; } else { $tempServiceName = $serviceName; } if (str(data_get($service, 'image'))->contains('glitchtip')) { $tempServiceName = 'glitchtip'; } if ($serviceName === 'supabase-kong') { $tempServiceName = 'supabase'; } $serviceDefinition = data_get($allServices, $tempServiceName); $predefinedPort = data_get($serviceDefinition, 'port'); if ($serviceName === 'plausible') { $predefinedPort = '8000'; } if ($migratedApp || $migratedDb) { // Use the already determined migrated service $savedService = $migratedApp ?: $migratedDb; } elseif ($isDatabase) { $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); if ($applicationFound) { $savedService = $applicationFound; } else { $savedService = ServiceDatabase::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, ]); } } else { $savedService = ServiceApplication::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, ]); } $fileStorages = $savedService->fileStorages(); if ($savedService->image !== $image) { $savedService->image = $image; $savedService->save(); } $originalResource = $savedService; if ($volumes->count() > 0) { foreach ($volumes as $index => $volume) { $type = null; $source = null; $target = null; $content = null; $isDirectory = false; if (is_string($volume)) { $parsed = parseDockerVolumeString($volume); $source = $parsed['source']; $target = $parsed['target']; // Mode is available in $parsed['mode'] if needed $foundConfig = $fileStorages->whereMountPath($target)->first(); if (sourceIsLocal($source)) { $type = str('bind'); if ($foundConfig) { $contentNotNull_temp = data_get($foundConfig, 'content'); if ($contentNotNull_temp) { $content = $contentNotNull_temp; } $isDirectory = data_get($foundConfig, 'is_directory'); } else { // By default, we cannot determine if the bind is a directory or not, so we set it to directory $isDirectory = true; } } else { $type = str('volume'); } } elseif (is_array($volume)) { $type = data_get_str($volume, 'type'); $source = data_get_str($volume, 'source'); $target = data_get_str($volume, 'target'); $content = data_get($volume, 'content'); $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); // Validate source and target for command injection (array/long syntax) if ($source !== null && ! empty($source->value())) { $sourceValue = $source->value(); // Allow environment variable references and env vars with path concatenation $isSimpleEnvVar = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/', $sourceValue); $isEnvVarWithDefault = preg_match('/^\$\{[^}]+:-[^}]*\}$/', $sourceValue); $isEnvVarWithPath = preg_match('/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}[\/\w\.\-]*$/', $sourceValue); if (! $isSimpleEnvVar && ! $isEnvVarWithDefault && ! $isEnvVarWithPath) { try { validateShellSafePath($sourceValue, 'volume source'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker volume definition (array syntax): '.$e->getMessage(). ' Please use safe path names without shell metacharacters.' ); } } } if ($target !== null && ! empty($target->value())) { try { validateShellSafePath($target->value(), 'volume target'); } catch (\Exception $e) { throw new \Exception( 'Invalid Docker volume definition (array syntax): '.$e->getMessage(). ' Please use safe path names without shell metacharacters.' ); } } $foundConfig = $fileStorages->whereMountPath($target)->first(); if ($foundConfig) { $contentNotNull_temp = data_get($foundConfig, 'content'); if ($contentNotNull_temp) { $content = $contentNotNull_temp; } $isDirectory = data_get($foundConfig, 'is_directory'); } else { // if isDirectory is not set (or false) & content is also not set, we assume it is a directory if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) { $isDirectory = true; } } } if ($type->value() === 'bind') { if ($source->value() === '/var/run/docker.sock') { $volume = $source->value().':'.$target->value(); if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } elseif ($source->value() === '/tmp' || $source->value() === '/tmp/') { $volume = $source->value().':'.$target->value(); if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } else { if ((int) $resource->compose_parsing_version >= 4) { $mainDirectory = str(base_configuration_dir().'/services/'.$uuid); } else { $mainDirectory = str(base_configuration_dir().'/applications/'.$uuid); } $source = replaceLocalSource($source, $mainDirectory); LocalFileVolume::updateOrCreate( [ 'mount_path' => $target, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ], [ 'fs_path' => $source, 'mount_path' => $target, 'content' => $content, 'is_directory' => $isDirectory, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ] ); if (isDev()) { if ((int) $resource->compose_parsing_version >= 4) { $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/services/'.$uuid); } else { $source = $source->replace($mainDirectory, '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/applications/'.$uuid); } } $volume = "$source:$target"; if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } } elseif ($type->value() === 'volume') { if ($topLevel->get('volumes')->has($source->value())) { $temp = $topLevel->get('volumes')->get($source->value()); if (data_get($temp, 'driver_opts.type') === 'cifs') { continue; } if (data_get($temp, 'driver_opts.type') === 'nfs') { continue; } } $slugWithoutUuid = Str::slug($source, '-'); $name = "{$uuid}_{$slugWithoutUuid}"; if (is_string($volume)) { $parsed = parseDockerVolumeString($volume); $source = $parsed['source']; $target = $parsed['target']; $source = $name; $volume = "$source:$target"; if (isset($parsed['mode']) && $parsed['mode']) { $volume .= ':'.$parsed['mode']->value(); } } elseif (is_array($volume)) { data_set($volume, 'source', $name); } $topLevel->get('volumes')->put($name, [ 'name' => $name, ]); LocalPersistentVolume::updateOrCreate( [ 'name' => $name, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ], [ 'name' => $name, 'mount_path' => $target, 'resource_id' => $originalResource->id, 'resource_type' => get_class($originalResource), ] ); } dispatch(new ServerFilesFromServerJob($originalResource)); $volumesParsed->put($index, $volume); } } if (! $use_network_mode) { if ($topLevel->get('networks')?->count() > 0) { foreach ($topLevel->get('networks') as $networkName => $network) { if ($networkName === 'default') { continue; } // ignore aliases if ($network['aliases'] ?? false) { continue; } $networkExists = $networks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); if (! $networkExists) { $networks->put($networkName, null); } } } $baseNetworkExists = $networks->contains(function ($value, $_) use ($baseNetwork) { return $value == $baseNetwork; }); if (! $baseNetworkExists) { foreach ($baseNetwork as $network) { $topLevel->get('networks')->put($network, [ 'name' => $network, 'external' => true, ]); } } } // Collect/create/update ports $collectedPorts = collect([]); if ($ports->count() > 0) { foreach ($ports as $sport) { if (is_string($sport) || is_numeric($sport)) { $collectedPorts->push($sport); } if (is_array($sport)) { $target = data_get($sport, 'target'); $published = data_get($sport, 'published'); $protocol = data_get($sport, 'protocol'); $collectedPorts->push("$target:$published/$protocol"); } } } $originalResource->ports = $collectedPorts->implode(','); $originalResource->save(); $networks_temp = collect(); if (! $use_network_mode) { foreach ($networks as $key => $network) { if (gettype($network) === 'string') { // networks: // - appwrite $networks_temp->put($network, null); } elseif (gettype($network) === 'array') { // networks: // default: // ipv4_address: 192.168.203.254 $networks_temp->put($key, $network); } } foreach ($baseNetwork as $key => $network) { $networks_temp->put($network, null); } } $normalEnvironments = $environment->diffKeys($allMagicEnvironments); $normalEnvironments = $normalEnvironments->filter(function ($value, $key) { return ! str($value)->startsWith('SERVICE_'); }); foreach ($normalEnvironments as $key => $value) { $originalKey = $key; // Preserve original key for comment lookup $key = str($key); $value = str($value); $originalValue = $value; $parsedValue = replaceVariables($value); if ($parsedValue->startsWith('SERVICE_')) { $resource->environment_variables()->updateOrCreate([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $value, 'is_preview' => false, 'comment' => $envComments[$originalKey] ?? null, ]); continue; } if (! $value->startsWith('$')) { continue; } if ($key->value() === $parsedValue->value()) { // Simple variable reference (e.g. DATABASE_URL: ${DATABASE_URL}) // Use firstOrCreate to avoid overwriting user-saved values on redeploy $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, 'comment' => $envComments[$originalKey] ?? null, ]); // Add the variable to the environment using the saved DB value $environment[$key->value()] = $envVar->value; } else { if ($value->startsWith('$')) { $isRequired = false; // Extract variable content between ${...} using balanced brace matching $result = extractBalancedBraceContent($value->value(), 0); if ($result !== null) { $content = $result['content']; $split = splitOnOperatorOutsideNested($content); if ($split !== null) { // Has default value syntax (:-, -, :?, or ?) $varName = $split['variable']; $operator = $split['operator']; $defaultValue = $split['default']; $isRequired = str_contains($operator, '?'); // Create the primary variable with its default (only if it doesn't exist) // Use firstOrCreate instead of updateOrCreate to avoid overwriting user edits $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $varName, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $defaultValue, 'is_preview' => false, 'is_required' => $isRequired, 'comment' => $envComments[$originalKey] ?? null, ]); // Add the variable to the environment so it will be shown in the deployable compose file $environment[$varName] = $envVar->value; // Recursively process nested variables in default value if (str_contains($defaultValue, '${')) { // Extract and create nested variables $searchPos = 0; $nestedResult = extractBalancedBraceContent($defaultValue, $searchPos); while ($nestedResult !== null) { $nestedContent = $nestedResult['content']; $nestedSplit = splitOnOperatorOutsideNested($nestedContent); // Determine the nested variable name $nestedVarName = $nestedSplit !== null ? $nestedSplit['variable'] : $nestedContent; // Skip SERVICE_URL_* and SERVICE_FQDN_* variables - they are handled by magic variable system $isMagicVariable = str_starts_with($nestedVarName, 'SERVICE_URL_') || str_starts_with($nestedVarName, 'SERVICE_FQDN_'); if (! $isMagicVariable) { if ($nestedSplit !== null) { // Create nested variable with its default (only if it doesn't exist) $nestedEnvVar = $resource->environment_variables()->firstOrCreate([ 'key' => $nestedSplit['variable'], 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $nestedSplit['default'], 'is_preview' => false, ]); // Add nested variable to environment $environment[$nestedSplit['variable']] = $nestedEnvVar->value; } else { // Simple nested variable without default (only if it doesn't exist) $nestedEnvVar = $resource->environment_variables()->firstOrCreate([ 'key' => $nestedContent, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, ]); // Add nested variable to environment $environment[$nestedContent] = $nestedEnvVar->value; } } // Look for more nested variables $searchPos = $nestedResult['end'] + 1; if ($searchPos >= strlen($defaultValue)) { break; } $nestedResult = extractBalancedBraceContent($defaultValue, $searchPos); } } } else { // Simple variable reference without default // Use firstOrCreate to avoid overwriting user-saved values on redeploy $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $content, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, 'is_required' => $isRequired, 'comment' => $envComments[$originalKey] ?? null, ]); // Add the variable to the environment using the saved DB value $environment[$content] = $envVar->value; } } else { // Fallback to old behavior for malformed input (backward compatibility) if ($value->contains(':-')) { $value = replaceVariables($value); $key = $value->before(':'); $value = $value->after(':-'); } elseif ($value->contains('-')) { $value = replaceVariables($value); $key = $value->before('-'); $value = $value->after('-'); } elseif ($value->contains(':?')) { $value = replaceVariables($value); $key = $value->before(':'); $value = $value->after(':?'); $isRequired = true; } elseif ($value->contains('?')) { $value = replaceVariables($value); $key = $value->before('?'); $value = $value->after('?'); $isRequired = true; } if ($originalValue->value() === $value->value()) { // This means the variable does not have a default value // Use firstOrCreate to avoid overwriting user-saved values on redeploy $parsedKeyValue = replaceVariables($value); $envVar = $resource->environment_variables()->firstOrCreate([ 'key' => $parsedKeyValue, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'is_preview' => false, 'is_required' => $isRequired, 'comment' => $envComments[$originalKey] ?? null, ]); // Add the variable to the environment using the saved DB value $environment[$parsedKeyValue->value()] = $envVar->value; continue; } // Variable with a default value from compose — use firstOrCreate to preserve user edits $resource->environment_variables()->firstOrCreate([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $value, 'is_preview' => false, 'is_required' => $isRequired, 'comment' => $envComments[$originalKey] ?? null, ]); } } } } // Add COOLIFY_RESOURCE_UUID to environment if ($resource->environment_variables->where('key', 'COOLIFY_RESOURCE_UUID')->isEmpty()) { $coolifyEnvironments->put('COOLIFY_RESOURCE_UUID', "{$resource->uuid}"); } // Add COOLIFY_CONTAINER_NAME to environment if ($resource->environment_variables->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) { $coolifyEnvironments->put('COOLIFY_CONTAINER_NAME', "{$containerName}"); } if ($savedService->serviceType()) { $fqdns = generateServiceSpecificFqdns($savedService); } else { $fqdns = collect(data_get($savedService, 'fqdns'))->filter(); } $defaultLabels = defaultLabels( id: $resource->id, name: $containerName, projectName: $resource->project()->name, resourceName: $resource->name, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id, subName: $savedService->human_name ?? $savedService->name, environment: $resource->environment->name, ); // Add COOLIFY_FQDN & COOLIFY_URL to environment if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { $fqdnsWithoutPort = $fqdns->map(function ($fqdn) { return str($fqdn)->replace('http://', '')->replace('https://', '')->before(':'); }); $coolifyEnvironments->put('COOLIFY_FQDN', $fqdnsWithoutPort->implode(',')); $urls = $fqdns->map(function ($fqdn): Stringable { return str($fqdn)->after('://')->before(':')->prepend(str($fqdn)->before('://')->append('://')); }); $coolifyEnvironments->put('COOLIFY_URL', $urls->implode(',')); } add_coolify_default_environment_variables($resource, $coolifyEnvironments, $resource->environment_variables); if ($environment->count() > 0) { $environment = $environment->filter(function ($value, $key) { return ! str($key)->startsWith('SERVICE_FQDN_'); })->map(function ($value, $key) use ($resource) { // Preserve empty strings and null values with correct Docker Compose semantics: // - Empty string: Variable is set to "" (e.g., HTTP_PROXY="" means "no proxy") // - Null: Variable is unset/removed from container environment (may inherit from host) if ($value === null) { // User explicitly wants variable unset - respect that // NEVER override from database - null means "inherit from environment" // Keep as null (will be excluded from container environment) } elseif ($value === '') { // Empty string - allow database override for backward compatibility $dbEnv = $resource->environment_variables()->where('key', $key)->first(); // Only use database override if it exists AND has a non-empty value if ($dbEnv && str($dbEnv->value)->isNotEmpty()) { $value = $dbEnv->value; } // Otherwise keep empty string as-is } // Resolve shared variable patterns like {{environment.VAR}}, {{project.VAR}}, {{team.VAR}} // Without this, literal {{...}} strings end up in the compose environment: section, // which takes precedence over the resolved values in the .env file (env_file:) if (is_string($value) && str_contains($value, '{{')) { $value = resolveSharedEnvironmentVariables($value, $resource); } return $value; }); } $serviceLabels = $labels->merge($defaultLabels); if ($serviceLabels->count() > 0) { $isContainerLabelEscapeEnabled = data_get($resource, 'is_container_label_escape_enabled'); if ($isContainerLabelEscapeEnabled) { $serviceLabels = $serviceLabels->map(function ($value, $key) { return escapeDollarSign($value); }); } } if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) { $shouldGenerateLabelsExactly = $resource->server->settings->generate_exact_labels; $uuid = $resource->uuid; $network = data_get($resource, 'destination.network'); if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image )); break; case ProxyTypes::CADDY->value: $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image, predefinedPort: $predefinedPort )); break; } } else { $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image )); $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $network, uuid: $uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $originalResource->isGzipEnabled(), is_stripprefix_enabled: $originalResource->isStripprefixEnabled(), service_name: $serviceName, image: $image, predefinedPort: $predefinedPort )); } } if (data_get($service, 'restart') === 'no' || data_get($service, 'exclude_from_hc')) { $savedService->update(['exclude_from_status' => true]); } data_forget($service, 'volumes.*.content'); data_forget($service, 'volumes.*.isDirectory'); data_forget($service, 'volumes.*.is_directory'); data_forget($service, 'exclude_from_hc'); $volumesParsed = $volumesParsed->map(function ($volume) { data_forget($volume, 'content'); data_forget($volume, 'is_directory'); data_forget($volume, 'isDirectory'); return $volume; }); $payload = collect($service)->merge([ 'container_name' => $containerName, 'restart' => $restart->value(), 'labels' => $serviceLabels, ]); if (! $use_network_mode) { $payload['networks'] = $networks_temp; } if ($ports->count() > 0) { $payload['ports'] = $ports; } if ($volumesParsed->count() > 0) { $payload['volumes'] = $volumesParsed; } if ($environment->count() > 0 || $coolifyEnvironments->count() > 0) { $payload['environment'] = $environment->merge($coolifyEnvironments)->merge($serviceNameEnvironments); } if ($logging) { $payload['logging'] = $logging; } if ($depends_on->count() > 0) { $payload['depends_on'] = $depends_on; } // Auto-inject .env file so Coolify environment variables are available inside containers // This makes Services behave consistently with Applications $existingEnvFiles = data_get($service, 'env_file'); $envFiles = collect(is_null($existingEnvFiles) ? [] : (is_array($existingEnvFiles) ? $existingEnvFiles : [$existingEnvFiles])) ->push('.env') ->unique() ->values(); $payload['env_file'] = $envFiles; $parsedServices->put($serviceName, $payload); } $topLevel->put('services', $parsedServices); $customOrder = ['services', 'volumes', 'networks', 'configs', 'secrets']; $topLevel = $topLevel->sortBy(function ($value, $key) use ($customOrder) { return array_search($key, $customOrder); }); // Remove empty top-level sections (volumes, networks, configs, secrets) // Keep only non-empty sections to match Docker Compose best practices $topLevel = $topLevel->filter(function ($value, $key) { // Always keep 'services' section if ($key === 'services') { return true; } // Keep section only if it has content return $value instanceof Collection ? $value->isNotEmpty() : ! empty($value); }); $cleanedCompose = Yaml::dump(convertToArray($topLevel), 10, 2); $resource->docker_compose = $cleanedCompose; // Update docker_compose_raw to remove content: from volumes only // This keeps the original user input clean while preventing content reapplication // Parse the original compose again to create a clean version without Coolify additions try { $originalYaml = Yaml::parse($originalCompose); // Remove content, isDirectory, and is_directory from all volume definitions if (isset($originalYaml['services'])) { foreach ($originalYaml['services'] as $serviceName => &$service) { if (isset($service['volumes'])) { foreach ($service['volumes'] as $key => &$volume) { if (is_array($volume)) { unset($volume['content']); unset($volume['isDirectory']); unset($volume['is_directory']); } } } } } $resource->docker_compose_raw = Yaml::dump($originalYaml, 10, 2); } catch (\Exception $e) { // If parsing fails, keep the original docker_compose_raw unchanged ray('Failed to update docker_compose_raw in serviceParser: '.$e->getMessage()); } data_forget($resource, 'environment_variables'); data_forget($resource, 'environment_variables_preview'); $resource->save(); return $topLevel; } ================================================ FILE: bootstrap/helpers/proxy.php ================================================ isFunctional()) { return collect(); } $proxyType = $server->proxyType(); if (is_null($proxyType) || $proxyType === 'NONE') { return collect(); } $networks = instant_remote_process(['docker inspect --format="{{json .NetworkSettings.Networks }}" coolify-proxy'], $server, false); return collect($networks)->map(function ($network) { return collect(json_decode($network))->keys(); })->flatten()->unique(); } function collectDockerNetworksByServer(Server $server) { $allNetworks = collect([]); if ($server->isSwarm()) { $networks = collect($server->swarmDockers)->map(function ($docker) { return $docker['network']; }); } else { // Standalone networks $networks = collect($server->standaloneDockers)->map(function ($docker) { return $docker['network']; }); } $allNetworks = $allNetworks->merge($networks); // Service networks foreach ($server->services()->get() as $service) { if ($service->isRunning()) { $networks->push($service->networks()); } $allNetworks->push($service->networks()); } // Docker compose based apps $docker_compose_apps = $server->dockerComposeBasedApplications(); foreach ($docker_compose_apps as $app) { if ($app->isRunning()) { $networks->push($app->uuid); } $allNetworks->push($app->uuid); } // Docker compose based preview deployments $docker_compose_previews = $server->dockerComposeBasedPreviewDeployments(); foreach ($docker_compose_previews as $preview) { if (! $preview->isRunning()) { continue; } $pullRequestId = $preview->pull_request_id; $applicationId = $preview->application_id; $application = Application::find($applicationId); if (! $application) { continue; } $network = "{$application->uuid}-{$pullRequestId}"; $networks->push($network); $allNetworks->push($network); } $networks = collect($networks)->flatten()->unique()->filter(function ($network) { return ! isDockerPredefinedNetwork($network); }); $allNetworks = $allNetworks->flatten()->unique()->filter(function ($network) { return ! isDockerPredefinedNetwork($network); }); if ($server->isSwarm()) { if ($networks->count() === 0) { $networks = collect(['coolify-overlay']); $allNetworks = collect(['coolify-overlay']); } } else { if ($networks->count() === 0) { $networks = collect(['coolify']); $allNetworks = collect(['coolify']); } } return [ 'networks' => $networks, 'allNetworks' => $allNetworks, ]; } function connectProxyToNetworks(Server $server) { ['networks' => $networks] = collectDockerNetworksByServer($server); if ($server->isSwarm()) { $commands = $networks->map(function ($network) { return [ "docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --driver overlay --attachable $network >/dev/null", "docker network connect $network coolify-proxy >/dev/null 2>&1 || true", "echo 'Successfully connected coolify-proxy to $network network.'", ]; }); } else { $commands = $networks->map(function ($network) { return [ "docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --attachable $network >/dev/null", "docker network connect $network coolify-proxy >/dev/null 2>&1 || true", "echo 'Successfully connected coolify-proxy to $network network.'", ]; }); } return $commands->flatten(); } /** * Ensures all required networks exist before docker compose up. * This must be called BEFORE docker compose up since the compose file declares networks as external. * * @param Server $server The server to ensure networks on * @return \Illuminate\Support\Collection Commands to create networks if they don't exist */ function ensureProxyNetworksExist(Server $server) { ['allNetworks' => $networks] = collectDockerNetworksByServer($server); if ($server->isSwarm()) { $commands = $networks->map(function ($network) { return [ "echo 'Ensuring network $network exists...'", "docker network ls --format '{{.Name}}' | grep -q '^{$network}$' || docker network create --driver overlay --attachable $network", ]; }); } else { $commands = $networks->map(function ($network) { return [ "echo 'Ensuring network $network exists...'", "docker network ls --format '{{.Name}}' | grep -q '^{$network}$' || docker network create --attachable $network", ]; }); } return $commands->flatten(); } function extractCustomProxyCommands(Server $server, string $existing_config): array { $custom_commands = []; $proxy_type = $server->proxyType(); if ($proxy_type !== ProxyTypes::TRAEFIK->value || empty($existing_config)) { return $custom_commands; } try { $yaml = Yaml::parse($existing_config); $existing_commands = data_get($yaml, 'services.traefik.command', []); if (empty($existing_commands)) { return $custom_commands; } // Define default commands that Coolify generates $default_command_prefixes = [ '--ping=', '--api.', '--entrypoints.http.address=', '--entrypoints.https.address=', '--entrypoints.http.http.encodequerysemicolons=', '--entryPoints.http.http2.maxConcurrentStreams=', '--entrypoints.https.http.encodequerysemicolons=', '--entryPoints.https.http2.maxConcurrentStreams=', '--entrypoints.https.http3', '--providers.file.', '--certificatesresolvers.', '--providers.docker', '--providers.swarm', '--log.level=', '--accesslog.', ]; // Extract commands that don't match default prefixes (these are custom) foreach ($existing_commands as $command) { $is_default = false; foreach ($default_command_prefixes as $prefix) { if (str_starts_with($command, $prefix)) { $is_default = true; break; } } if (! $is_default) { $custom_commands[] = $command; } } } catch (\Exception $e) { // If we can't parse the config, return empty array // Silently fail to avoid breaking the proxy regeneration } return $custom_commands; } function generateDefaultProxyConfiguration(Server $server, array $custom_commands = []) { Log::info('Generating default proxy configuration', [ 'server_id' => $server->id, 'server_name' => $server->name, 'custom_commands_count' => count($custom_commands), 'caller' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[1]['class'] ?? 'unknown', ]); $proxy_path = $server->proxyPath(); $proxy_type = $server->proxyType(); if ($server->isSwarm()) { $networks = collect($server->swarmDockers)->map(function ($docker) { return $docker['network']; })->unique(); if ($networks->count() === 0) { $networks = collect(['coolify-overlay']); } } else { $networks = collect($server->standaloneDockers)->map(function ($docker) { return $docker['network']; })->unique(); if ($networks->count() === 0) { $networks = collect(['coolify']); } } $array_of_networks = collect([]); $filtered_networks = collect([]); $networks->map(function ($network) use ($array_of_networks, $filtered_networks) { if (isDockerPredefinedNetwork($network)) { return; // Predefined networks cannot be used in network configuration } $array_of_networks[$network] = [ 'external' => true, ]; $filtered_networks->push($network); }); if ($proxy_type === ProxyTypes::TRAEFIK->value) { $labels = [ 'traefik.enable=true', 'traefik.http.routers.traefik.entrypoints=http', 'traefik.http.routers.traefik.service=api@internal', 'traefik.http.services.traefik.loadbalancer.server.port=8080', 'coolify.managed=true', 'coolify.proxy=true', ]; $config = [ 'name' => 'coolify-proxy', 'networks' => $array_of_networks->toArray(), 'services' => [ 'traefik' => [ 'container_name' => 'coolify-proxy', 'image' => 'traefik:v3.6', 'restart' => RESTART_MODE, 'extra_hosts' => [ 'host.docker.internal:host-gateway', ], 'networks' => $filtered_networks->toArray(), 'ports' => [ '80:80', '443:443', '443:443/udp', '8080:8080', ], 'healthcheck' => [ 'test' => 'wget -qO- http://localhost:80/ping || exit 1', 'interval' => '4s', 'timeout' => '2s', 'retries' => 5, ], 'volumes' => [ '/var/run/docker.sock:/var/run/docker.sock:ro', ], 'command' => [ '--ping=true', '--ping.entrypoint=http', '--api.dashboard=true', '--entrypoints.http.address=:80', '--entrypoints.https.address=:443', '--entrypoints.http.http.encodequerysemicolons=true', '--entryPoints.http.http2.maxConcurrentStreams=250', '--entrypoints.https.http.encodequerysemicolons=true', '--entryPoints.https.http2.maxConcurrentStreams=250', '--entrypoints.https.http3', '--providers.file.directory=/traefik/dynamic/', '--providers.file.watch=true', '--certificatesresolvers.letsencrypt.acme.httpchallenge=true', '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http', '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json', ], 'labels' => $labels, ], ], ]; if (isDev()) { $config['services']['traefik']['command'][] = '--api.insecure=true'; $config['services']['traefik']['command'][] = '--log.level=debug'; $config['services']['traefik']['command'][] = '--accesslog.filepath=/traefik/access.log'; $config['services']['traefik']['command'][] = '--accesslog.bufferingsize=100'; $config['services']['traefik']['volumes'][] = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/:/traefik'; } else { $config['services']['traefik']['command'][] = '--api.insecure=false'; $config['services']['traefik']['volumes'][] = "{$proxy_path}:/traefik"; } if ($server->isSwarm()) { data_forget($config, 'services.traefik.container_name'); data_forget($config, 'services.traefik.restart'); data_forget($config, 'services.traefik.labels'); $config['services']['traefik']['command'][] = '--providers.swarm.endpoint=unix:///var/run/docker.sock'; $config['services']['traefik']['command'][] = '--providers.swarm.exposedbydefault=false'; $config['services']['traefik']['deploy'] = [ 'labels' => $labels, 'placement' => [ 'constraints' => [ 'node.role==manager', ], ], ]; } else { $config['services']['traefik']['command'][] = '--providers.docker=true'; $config['services']['traefik']['command'][] = '--providers.docker.exposedbydefault=false'; } // Append custom commands (e.g., trustedIPs for Cloudflare) if (! empty($custom_commands)) { foreach ($custom_commands as $custom_command) { $config['services']['traefik']['command'][] = $custom_command; } } } elseif ($proxy_type === 'CADDY') { $config = [ 'networks' => $array_of_networks->toArray(), 'services' => [ 'caddy' => [ 'container_name' => 'coolify-proxy', 'image' => 'lucaslorentz/caddy-docker-proxy:2.8-alpine', 'restart' => RESTART_MODE, 'extra_hosts' => [ 'host.docker.internal:host-gateway', ], 'environment' => [ 'CADDY_DOCKER_POLLING_INTERVAL=5s', 'CADDY_DOCKER_CADDYFILE_PATH=/dynamic/Caddyfile', ], 'networks' => $filtered_networks->toArray(), 'ports' => [ '80:80', '443:443', '443:443/udp', ], 'labels' => [ 'coolify.managed=true', 'coolify.proxy=true', ], 'volumes' => [ '/var/run/docker.sock:/var/run/docker.sock:ro', "{$proxy_path}/dynamic:/dynamic", "{$proxy_path}/config:/config", "{$proxy_path}/data:/data", ], ], ], ]; } else { return null; } $config = Yaml::dump($config, 12, 2); SaveProxyConfiguration::run($server, $config); return $config; } function getExactTraefikVersionFromContainer(Server $server): ?string { try { Log::debug("getExactTraefikVersionFromContainer: Server '{$server->name}' (ID: {$server->id}) - Checking for exact version"); // Method A: Execute traefik version command (most reliable) $versionCommand = "docker exec coolify-proxy traefik version 2>/dev/null | grep -oP 'Version:\s+\K\d+\.\d+\.\d+'"; Log::debug("getExactTraefikVersionFromContainer: Server '{$server->name}' (ID: {$server->id}) - Running: {$versionCommand}"); $output = instant_remote_process([$versionCommand], $server, false); if (! empty(trim($output))) { $version = trim($output); Log::debug("getExactTraefikVersionFromContainer: Server '{$server->name}' (ID: {$server->id}) - Detected exact version from command: {$version}"); return $version; } // Method B: Try OCI label as fallback $labelCommand = "docker inspect coolify-proxy --format '{{index .Config.Labels \"org.opencontainers.image.version\"}}' 2>/dev/null"; Log::debug("getExactTraefikVersionFromContainer: Server '{$server->name}' (ID: {$server->id}) - Trying OCI label"); $label = instant_remote_process([$labelCommand], $server, false); if (! empty(trim($label))) { // Extract version number from label (might have 'v' prefix) if (preg_match('/(\d+\.\d+\.\d+)/', trim($label), $matches)) { Log::debug("getExactTraefikVersionFromContainer: Server '{$server->name}' (ID: {$server->id}) - Detected from OCI label: {$matches[1]}"); return $matches[1]; } } Log::debug("getExactTraefikVersionFromContainer: Server '{$server->name}' (ID: {$server->id}) - Could not detect exact version"); return null; } catch (\Exception $e) { Log::error("getExactTraefikVersionFromContainer: Server '{$server->name}' (ID: {$server->id}) - Error: ".$e->getMessage()); return null; } } function getTraefikVersionFromDockerCompose(Server $server): ?string { try { Log::debug("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Starting version detection"); // Try to get exact version from running container (e.g., "3.6.0") $exactVersion = getExactTraefikVersionFromContainer($server); if ($exactVersion) { Log::debug("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Using exact version: {$exactVersion}"); return $exactVersion; } // Fallback: Check image tag (current method) Log::debug("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Falling back to image tag detection"); $containerName = 'coolify-proxy'; $inspectCommand = "docker inspect {$containerName} --format '{{.Config.Image}}' 2>/dev/null"; $image = instant_remote_process([$inspectCommand], $server, false); if (empty(trim($image))) { Log::debug("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Container '{$containerName}' not found or not running"); return null; } $image = trim($image); Log::debug("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Running container image: {$image}"); // Extract version from image string (e.g., "traefik:v3.6" or "traefik:3.6.0" or "traefik:latest") if (preg_match('/traefik:(v?\d+\.\d+(?:\.\d+)?|latest)/i', $image, $matches)) { Log::debug("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Extracted version from image tag: {$matches[1]}"); return $matches[1]; } Log::debug("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Image format doesn't match expected pattern: {$image}"); return null; } catch (\Exception $e) { Log::error("getTraefikVersionFromDockerCompose: Server '{$server->name}' (ID: {$server->id}) - Error: ".$e->getMessage()); return null; } } ================================================ FILE: bootstrap/helpers/remoteProcess.php ================================================ value; $command = $command instanceof Collection ? $command->toArray() : $command; if ($server->isNonRoot()) { $command = parseCommandsByLineForSudo(collect($command), $server); } $command_string = implode("\n", $command); if (Auth::check()) { $teams = Auth::user()->teams->pluck('id'); if (! $teams->contains($server->team_id) && ! $teams->contains(0)) { throw new \Exception('User is not part of the team that owns this server'); } } SshMultiplexingHelper::ensureMultiplexedConnection($server); return resolve(PrepareCoolifyTask::class, [ 'remoteProcessArgs' => new CoolifyTaskArgs( server_uuid: $server->uuid, command: $command_string, type: $type, type_uuid: $type_uuid, model: $model, ignore_errors: $ignore_errors, call_event_on_finish: $callEventOnFinish, call_event_data: $callEventData, ), ])(); } function instant_scp(string $source, string $dest, Server $server, $throwError = true) { return \App\Helpers\SshRetryHandler::retry( function () use ($source, $dest, $server) { $scp_command = SshMultiplexingHelper::generateScpCommand($server, $source, $dest); $process = Process::timeout(config('constants.ssh.command_timeout'))->run($scp_command); $output = trim($process->output()); $exitCode = $process->exitCode(); if ($exitCode !== 0) { excludeCertainErrors($process->errorOutput(), $exitCode); } return $output === 'null' ? null : $output; }, [ 'server' => $server->ip, 'source' => $source, 'dest' => $dest, 'function' => 'instant_scp', ], $throwError ); } function instant_remote_process_with_timeout(Collection|array $command, Server $server, bool $throwError = true, bool $no_sudo = false): ?string { $command = $command instanceof Collection ? $command->toArray() : $command; if ($server->isNonRoot() && ! $no_sudo) { $command = parseCommandsByLineForSudo(collect($command), $server); } $command_string = implode("\n", $command); return \App\Helpers\SshRetryHandler::retry( function () use ($server, $command_string) { $sshCommand = SshMultiplexingHelper::generateSshCommand($server, $command_string); $process = Process::timeout(30)->run($sshCommand); $output = trim($process->output()); $exitCode = $process->exitCode(); if ($exitCode !== 0) { excludeCertainErrors($process->errorOutput(), $exitCode); } // Sanitize output to ensure valid UTF-8 encoding $output = $output === 'null' ? null : sanitize_utf8_text($output); return $output; }, [ 'server' => $server->ip, 'command_preview' => substr($command_string, 0, 100), 'function' => 'instant_remote_process_with_timeout', ], $throwError ); } function instant_remote_process(Collection|array $command, Server $server, bool $throwError = true, bool $no_sudo = false, ?int $timeout = null, bool $disableMultiplexing = false): ?string { $command = $command instanceof Collection ? $command->toArray() : $command; if ($server->isNonRoot() && ! $no_sudo) { $command = parseCommandsByLineForSudo(collect($command), $server); } $command_string = implode("\n", $command); $effectiveTimeout = $timeout ?? config('constants.ssh.command_timeout'); return \App\Helpers\SshRetryHandler::retry( function () use ($server, $command_string, $effectiveTimeout, $disableMultiplexing) { $sshCommand = SshMultiplexingHelper::generateSshCommand($server, $command_string, $disableMultiplexing); $process = Process::timeout($effectiveTimeout)->run($sshCommand); $output = trim($process->output()); $exitCode = $process->exitCode(); if ($exitCode !== 0) { excludeCertainErrors($process->errorOutput(), $exitCode); } // Sanitize output to ensure valid UTF-8 encoding $output = $output === 'null' ? null : sanitize_utf8_text($output); return $output; }, [ 'server' => $server->ip, 'command_preview' => substr($command_string, 0, 100), 'function' => 'instant_remote_process', ], $throwError ); } function excludeCertainErrors(string $errorOutput, ?int $exitCode = null) { $ignoredErrors = collect([ 'Permission denied (publickey', 'Could not resolve hostname', ]); $ignored = $ignoredErrors->contains(fn ($error) => Str::contains($errorOutput, $error)); // Ensure we always have a meaningful error message $errorMessage = trim($errorOutput); if (empty($errorMessage)) { $errorMessage = "SSH command failed with exit code: $exitCode"; } if ($ignored) { // TODO: Create new exception and disable in sentry throw new \RuntimeException($errorMessage, $exitCode); } throw new \RuntimeException($errorMessage, $exitCode); } function decode_remote_command_output(?ApplicationDeploymentQueue $application_deployment_queue = null, bool $includeAll = false): Collection { if (is_null($application_deployment_queue)) { return collect([]); } $application = Application::find(data_get($application_deployment_queue, 'application_id')); $is_debug_enabled = data_get($application, 'settings.is_debug_enabled'); $logs = data_get($application_deployment_queue, 'logs'); if (empty($logs)) { return collect([]); } try { $decoded = json_decode( $logs, associative: true, flags: JSON_THROW_ON_ERROR ); } catch (\JsonException $e) { // If JSON decoding fails, try to clean up the logs and retry try { // Ensure valid UTF-8 encoding $cleaned_logs = sanitize_utf8_text($logs); $decoded = json_decode( $cleaned_logs, associative: true, flags: JSON_THROW_ON_ERROR ); } catch (\JsonException $e) { // If it still fails, return empty collection to prevent crashes return collect([]); } } if (! is_array($decoded)) { return collect([]); } $seenCommands = collect(); $formatted = collect($decoded); if (! $is_debug_enabled && ! $includeAll) { $formatted = $formatted->filter(fn ($i) => $i['hidden'] === false ?? false); } return $formatted ->sortBy(fn ($i) => data_get($i, 'order')) ->map(function ($i) { data_set($i, 'timestamp', Carbon::parse(data_get($i, 'timestamp'))->format('Y-M-d H:i:s.u')); return $i; }) ->reduce(function ($deploymentLogLines, $logItem) use ($seenCommands) { $command = data_get($logItem, 'command'); $isStderr = data_get($logItem, 'type') === 'stderr'; $isNewCommand = ! is_null($command) && ! $seenCommands->first(function ($seenCommand) use ($logItem) { return data_get($seenCommand, 'command') === data_get($logItem, 'command') && data_get($seenCommand, 'batch') === data_get($logItem, 'batch'); }); if ($isNewCommand) { $deploymentLogLines->push([ 'line' => $command, 'timestamp' => data_get($logItem, 'timestamp'), 'stderr' => $isStderr, 'hidden' => data_get($logItem, 'hidden'), 'command' => true, ]); $seenCommands->push([ 'command' => $command, 'batch' => data_get($logItem, 'batch'), ]); } $lines = explode(PHP_EOL, data_get($logItem, 'output')); foreach ($lines as $line) { $deploymentLogLines->push([ 'line' => $line, 'timestamp' => data_get($logItem, 'timestamp'), 'stderr' => $isStderr, 'hidden' => data_get($logItem, 'hidden'), ]); } return $deploymentLogLines; }, collect()); } function remove_iip($text) { // Ensure the input is valid UTF-8 before processing $text = sanitize_utf8_text($text); // Git access tokens $text = preg_replace('/x-access-token:.*?(?=@)/', 'x-access-token:'.REDACTED, $text); // ANSI color codes $text = preg_replace('/\x1b\[[0-9;]*m/', '', $text); // Generic URLs with passwords (covers database URLs, ftp, amqp, ssh, git basic auth, etc.) // (protocol://user:password@host → protocol://user:@host) $text = preg_replace('/((?:https?|postgres|mysql|mongodb|rediss?|mariadb|ftp|sftp|ssh|amqp|amqps|ldap|ldaps|s3):\/\/[^:]+:)[^@]+(@)/i', '$1'.REDACTED.'$2', $text); // Email addresses $text = preg_replace('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/', REDACTED, $text); // Bearer/JWT tokens $text = preg_replace('/Bearer\s+[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/i', 'Bearer '.REDACTED, $text); // GitHub tokens (ghp_ = personal, gho_ = OAuth, ghu_ = user-to-server, ghs_ = server-to-server, ghr_ = refresh) $text = preg_replace('/\b(gh[pousr]_[A-Za-z0-9_]{36,})\b/', REDACTED, $text); // GitLab tokens (glpat- = personal access token, glcbt- = CI build token, glrt- = runner token) $text = preg_replace('/\b(gl(?:pat|cbt|rt)-[A-Za-z0-9\-_]{20,})\b/', REDACTED, $text); // AWS credentials (Access Key ID starts with AKIA, ABIA, ACCA, ASIA) $text = preg_replace('/\b(A(?:KIA|BIA|CCA|SIA)[A-Z0-9]{16})\b/', REDACTED, $text); // AWS Secret Access Key (40 character base64-ish string, typically follows access key) $text = preg_replace('/(aws_secret_access_key|AWS_SECRET_ACCESS_KEY)[=:]\s*[\'"]?([A-Za-z0-9\/+=]{40})[\'"]?/i', '$1='.REDACTED, $text); // API keys (common patterns) $text = preg_replace('/(api[_-]?key|apikey|api[_-]?secret|secret[_-]?key)[=:]\s*[\'"]?[A-Za-z0-9\-_]{16,}[\'"]?/i', '$1='.REDACTED, $text); // Private key blocks $text = preg_replace('/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/', REDACTED, $text); return $text; } /** * Sanitizes text to ensure it contains valid UTF-8 encoding. * * This function is crucial for preventing "Malformed UTF-8 characters" errors * that can occur when Docker build output contains binary data mixed with text, * especially during image processing or builds with many assets. * * @param string|null $text The text to sanitize * @return string Valid UTF-8 encoded text */ function sanitize_utf8_text(?string $text): string { if (empty($text)) { return ''; } // Convert to UTF-8, replacing invalid sequences $sanitized = mb_convert_encoding($text, 'UTF-8', 'UTF-8'); // Additional fallback: use SUBSTITUTE flag to replace invalid sequences with substitution character if (! mb_check_encoding($sanitized, 'UTF-8')) { $sanitized = mb_convert_encoding($text, 'UTF-8', mb_detect_encoding($text, mb_detect_order(), true) ?: 'UTF-8'); } return $sanitized; } function refresh_server_connection(?PrivateKey $private_key = null) { if (is_null($private_key)) { return; } foreach ($private_key->servers as $server) { SshMultiplexingHelper::removeMuxFile($server); } } function checkRequiredCommands(Server $server) { $commands = collect(['jq', 'jc']); foreach ($commands as $command) { $commandFound = instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'command -v {$command}'"], $server, false); if ($commandFound) { continue; } try { instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'apt update && apt install -y {$command}'"], $server); } catch (\Throwable) { break; } $commandFound = instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'command -v {$command}'"], $server, false); if (! $commandFound) { break; } } } ================================================ FILE: bootstrap/helpers/services.php ================================================ = strlen($str)) { return null; } $openPos = strpos($str, '{', $startPos); if ($openPos === false) { return null; } // Track depth to find matching closing brace $depth = 1; $pos = $openPos + 1; $len = strlen($str); while ($pos < $len && $depth > 0) { if ($str[$pos] === '{') { $depth++; } elseif ($str[$pos] === '}') { $depth--; } $pos++; } if ($depth !== 0) { // Unbalanced braces return null; } return [ 'content' => substr($str, $openPos + 1, $pos - $openPos - 2), 'start' => $openPos, 'end' => $pos - 1, ]; } /** * Split variable expression on operators (:-, -, :?, ?) while respecting nested braces. * * @param string $content The content to split (without outer ${...}) * @return array|null Array with 'variable', 'operator', and 'default' keys, or null if no operator found */ function splitOnOperatorOutsideNested(string $content): ?array { $operators = [':-', '-', ':?', '?']; $depth = 0; $len = strlen($content); for ($i = 0; $i < $len; $i++) { if ($content[$i] === '{') { $depth++; } elseif ($content[$i] === '}') { $depth--; } elseif ($depth === 0) { // Check for operators only at depth 0 (outside nested braces) foreach ($operators as $op) { if (substr($content, $i, strlen($op)) === $op) { return [ 'variable' => substr($content, 0, $i), 'operator' => $op, 'default' => substr($content, $i + strlen($op)), ]; } } } } return null; } function replaceVariables(string $variable): Stringable { // Handle ${VAR} syntax with proper brace matching $str = str($variable); // Handle ${VAR} format if ($str->startsWith('${')) { $result = extractBalancedBraceContent($variable, 0); if ($result !== null) { return str($result['content']); } // Fallback to old behavior for malformed input return $str->before('}')->replaceFirst('$', '')->replaceFirst('{', ''); } // Handle {VAR} format (from regex capture group without $) if ($str->startsWith('{') && $str->endsWith('}')) { return str(substr($variable, 1, -1)); } // Handle {VAR format (from regex capture group, may be truncated) if ($str->startsWith('{')) { $result = extractBalancedBraceContent('$'.$variable, 0); if ($result !== null) { return str($result['content']); } // Fallback: remove { and get content before } return $str->replaceFirst('{', '')->before('}'); } // Handle bare $VAR format (no braces) if ($str->startsWith('$')) { return $str->replaceFirst('$', ''); } return $str; } function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Application $oneService, bool $isInit = false) { try { if ($oneService->getMorphClass() === \App\Models\Application::class) { $workdir = $oneService->workdir(); $server = $oneService->destination->server; } else { $workdir = $oneService->service->workdir(); $server = $oneService->service->server; } $fileVolumes = $oneService->fileStorages()->get(); $commands = collect([ "mkdir -p $workdir > /dev/null 2>&1 || true", "cd $workdir", ]); instant_remote_process($commands, $server); foreach ($fileVolumes as $fileVolume) { $path = str(data_get($fileVolume, 'fs_path')); $content = data_get($fileVolume, 'content'); if ($path->startsWith('.')) { $path = $path->after('.'); $fileLocation = $workdir.$path; } else { $fileLocation = $path; } // Exists and is a file $isFile = instant_remote_process(["test -f $fileLocation && echo OK || echo NOK"], $server); // Exists and is a directory $isDir = instant_remote_process(["test -d $fileLocation && echo OK || echo NOK"], $server); if ($isFile === 'OK') { // If its a file & exists $filesystemContent = instant_remote_process(["cat $fileLocation"], $server); if ($fileVolume->is_based_on_git) { $fileVolume->content = $filesystemContent; } $fileVolume->is_directory = false; $fileVolume->save(); } elseif ($isDir === 'OK') { // If its a directory & exists $fileVolume->content = null; $fileVolume->is_directory = true; $fileVolume->save(); } elseif ($isFile === 'NOK' && $isDir === 'NOK' && ! $fileVolume->is_directory && $isInit && $content) { // Does not exists (no dir or file), not flagged as directory, is init, has content $fileVolume->content = $content; $fileVolume->is_directory = false; $fileVolume->save(); $content = base64_encode($content); $dir = str($fileLocation)->dirname(); instant_remote_process([ "mkdir -p $dir", "echo '$content' | base64 -d | tee $fileLocation", ], $server); } elseif ($isFile === 'NOK' && $isDir === 'NOK' && $fileVolume->is_directory && $isInit) { // Does not exists (no dir or file), flagged as directory, is init $fileVolume->content = null; $fileVolume->is_directory = true; $fileVolume->save(); instant_remote_process(["mkdir -p $fileLocation"], $server); } elseif ($isFile === 'NOK' && $isDir === 'NOK' && ! $fileVolume->is_directory && $isInit && is_null($content)) { // Does not exists (no dir or file), not flagged as directory, is init, has no content => create directory $fileVolume->content = null; $fileVolume->is_directory = true; $fileVolume->save(); instant_remote_process(["mkdir -p $fileLocation"], $server); } } } catch (\Throwable $e) { return handleError($e); } } function updateCompose(ServiceApplication|ServiceDatabase $resource) { try { $name = data_get($resource, 'name'); $dockerComposeRaw = data_get($resource, 'service.docker_compose_raw'); if (! $dockerComposeRaw) { throw new \Exception('No compose file found or not a valid YAML file.'); } $dockerCompose = Yaml::parse($dockerComposeRaw); // Switch Image $updatedImage = data_get_str($resource, 'image'); $currentImage = data_get_str($dockerCompose, "services.{$name}.image"); if ($currentImage !== $updatedImage) { data_set($dockerCompose, "services.{$name}.image", $updatedImage->value()); $dockerComposeRaw = Yaml::dump($dockerCompose, 10, 2); $resource->service->docker_compose_raw = $dockerComposeRaw; $resource->service->save(); $resource->image = $updatedImage; $resource->save(); } // Extract SERVICE_URL and SERVICE_FQDN variable names from the compose template // to ensure we use the exact names defined in the template (which may be abbreviated) // IMPORTANT: Only extract variables that are DIRECTLY DECLARED for this service, // not variables that are merely referenced from other services $serviceConfig = data_get($dockerCompose, "services.{$name}"); $environment = data_get($serviceConfig, 'environment', []); $templateVariableNames = []; foreach ($environment as $key => $value) { if (is_int($key) && is_string($value)) { // List-style: "- SERVICE_URL_APP_3000" or "- SERVICE_URL_APP_3000=value" // Extract variable name (before '=' if present) $envVarName = str($value)->before('=')->trim(); // Only include if it's a direct declaration (not a reference like ${VAR}) // Direct declarations look like: SERVICE_URL_APP or SERVICE_URL_APP_3000 // References look like: NEXT_PUBLIC_URL=${SERVICE_URL_APP} if ($envVarName->startsWith('SERVICE_FQDN_') || $envVarName->startsWith('SERVICE_URL_')) { $templateVariableNames[] = $envVarName->value(); } } elseif (is_string($key)) { // Map-style: "SERVICE_URL_APP_3000: value" or "SERVICE_FQDN_DB: localhost" $envVarName = str($key); if ($envVarName->startsWith('SERVICE_FQDN_') || $envVarName->startsWith('SERVICE_URL_')) { $templateVariableNames[] = $envVarName->value(); } } // DO NOT extract variables that are only referenced with ${VAR_NAME} syntax // Those belong to other services and will be updated when THOSE services are updated } // Remove duplicates $templateVariableNames = array_unique($templateVariableNames); // Extract unique service names to process (preserving the original case from template) // This allows us to create both URL and FQDN pairs regardless of which one is in the template $serviceNamesToProcess = []; foreach ($templateVariableNames as $templateVarName) { $parsed = parseServiceEnvironmentVariable($templateVarName); // Extract the original service name with case preserved from the template $strKey = str($templateVarName); if ($parsed['has_port']) { // For port-specific variables, get the name between SERVICE_URL_/SERVICE_FQDN_ and the last underscore if ($strKey->startsWith('SERVICE_URL_')) { $serviceName = $strKey->after('SERVICE_URL_')->beforeLast('_')->value(); } elseif ($strKey->startsWith('SERVICE_FQDN_')) { $serviceName = $strKey->after('SERVICE_FQDN_')->beforeLast('_')->value(); } else { continue; } } else { // For base variables, get everything after SERVICE_URL_/SERVICE_FQDN_ if ($strKey->startsWith('SERVICE_URL_')) { $serviceName = $strKey->after('SERVICE_URL_')->value(); } elseif ($strKey->startsWith('SERVICE_FQDN_')) { $serviceName = $strKey->after('SERVICE_FQDN_')->value(); } else { continue; } } // Use lowercase key for array indexing (to group case variations together) $serviceKey = str($serviceName)->lower()->value(); // Track both base service name and port-specific variant if (! isset($serviceNamesToProcess[$serviceKey])) { $serviceNamesToProcess[$serviceKey] = [ 'base' => $serviceName, // Preserve original case 'ports' => [], ]; } // If this variable has a port, track it if ($parsed['has_port'] && $parsed['port']) { $serviceNamesToProcess[$serviceKey]['ports'][] = $parsed['port']; } } // Delete all existing SERVICE_URL and SERVICE_FQDN variables for these service names // We need to delete both URL and FQDN variants, with and without ports foreach ($serviceNamesToProcess as $serviceInfo) { $serviceName = $serviceInfo['base']; // Delete base variables $resource->service->environment_variables()->where('key', "SERVICE_URL_{$serviceName}")->delete(); $resource->service->environment_variables()->where('key', "SERVICE_FQDN_{$serviceName}")->delete(); // Delete port-specific variables foreach ($serviceInfo['ports'] as $port) { $resource->service->environment_variables()->where('key', "SERVICE_URL_{$serviceName}_{$port}")->delete(); $resource->service->environment_variables()->where('key', "SERVICE_FQDN_{$serviceName}_{$port}")->delete(); } } if ($resource->fqdn) { $resourceFqdns = str($resource->fqdn)->explode(','); $resourceFqdns = $resourceFqdns->first(); $url = Url::fromString($resourceFqdns); $port = $url->getPort(); $path = $url->getPath(); // Prepare URL value (with scheme and host) $urlValue = $url->getScheme().'://'.$url->getHost(); $urlValue = ($path === '/') ? $urlValue : $urlValue.$path; // Prepare FQDN value (host only, no scheme) $fqdnHost = $url->getHost(); $fqdnValue = str($fqdnHost)->after('://'); if ($path !== '/') { $fqdnValue = $fqdnValue.$path; } // For each service name found in template, create BOTH SERVICE_URL and SERVICE_FQDN pairs foreach ($serviceNamesToProcess as $serviceInfo) { $serviceName = $serviceInfo['base']; $ports = array_unique($serviceInfo['ports']); // ALWAYS create base pair (without port) $resource->service->environment_variables()->updateOrCreate([ 'resourceable_type' => Service::class, 'resourceable_id' => $resource->service_id, 'key' => "SERVICE_URL_{$serviceName}", ], [ 'value' => $urlValue, 'is_preview' => false, ]); $resource->service->environment_variables()->updateOrCreate([ 'resourceable_type' => Service::class, 'resourceable_id' => $resource->service_id, 'key' => "SERVICE_FQDN_{$serviceName}", ], [ 'value' => $fqdnValue, 'is_preview' => false, ]); // Create port-specific pairs for each port found in template or FQDN $allPorts = $ports; if ($port && ! in_array($port, $allPorts)) { $allPorts[] = $port; } foreach ($allPorts as $portNum) { $urlWithPort = $urlValue.':'.$portNum; $fqdnWithPort = $fqdnValue.':'.$portNum; $resource->service->environment_variables()->updateOrCreate([ 'resourceable_type' => Service::class, 'resourceable_id' => $resource->service_id, 'key' => "SERVICE_URL_{$serviceName}_{$portNum}", ], [ 'value' => $urlWithPort, 'is_preview' => false, ]); $resource->service->environment_variables()->updateOrCreate([ 'resourceable_type' => Service::class, 'resourceable_id' => $resource->service_id, 'key' => "SERVICE_FQDN_{$serviceName}_{$portNum}", ], [ 'value' => $fqdnWithPort, 'is_preview' => false, ]); } } } } catch (\Throwable $e) { return handleError($e); } } function serviceKeys() { return get_service_templates()->keys(); } /** * Parse a SERVICE_URL_* or SERVICE_FQDN_* variable to extract the service name and port. * * This function detects if a service environment variable has a port suffix by checking * if the last segment after the underscore is numeric. * * Examples: * - SERVICE_URL_APP_3000 → ['service_name' => 'app', 'port' => '3000', 'has_port' => true] * - SERVICE_URL_MY_API_8080 → ['service_name' => 'my_api', 'port' => '8080', 'has_port' => true] * - SERVICE_URL_MY_APP → ['service_name' => 'my_app', 'port' => null, 'has_port' => false] * - SERVICE_FQDN_REDIS_CACHE_6379 → ['service_name' => 'redis_cache', 'port' => '6379', 'has_port' => true] * * @param string $key The environment variable key (e.g., SERVICE_URL_APP_3000) * @return array{service_name: string, port: string|null, has_port: bool} Parsed service information */ function parseServiceEnvironmentVariable(string $key): array { $strKey = str($key); $lastSegment = $strKey->afterLast('_')->value(); $hasPort = is_numeric($lastSegment) && ctype_digit($lastSegment); if ($hasPort) { // Port-specific variable (e.g., SERVICE_URL_APP_3000) if ($strKey->startsWith('SERVICE_URL_')) { $serviceName = $strKey->after('SERVICE_URL_')->beforeLast('_')->lower()->value(); } elseif ($strKey->startsWith('SERVICE_FQDN_')) { $serviceName = $strKey->after('SERVICE_FQDN_')->beforeLast('_')->lower()->value(); } else { $serviceName = ''; } $port = $lastSegment; } else { // Base variable without port (e.g., SERVICE_URL_APP) if ($strKey->startsWith('SERVICE_URL_')) { $serviceName = $strKey->after('SERVICE_URL_')->lower()->value(); } elseif ($strKey->startsWith('SERVICE_FQDN_')) { $serviceName = $strKey->after('SERVICE_FQDN_')->lower()->value(); } else { $serviceName = ''; } $port = null; } return [ 'service_name' => $serviceName, 'port' => $port, 'has_port' => $hasPort, ]; } /** * Apply service-specific application prerequisites after service parse. * * This function configures application-level settings that are required for * specific one-click services to work correctly (e.g., disabling gzip for Beszel, * disabling strip prefix for Appwrite services). * * Must be called AFTER $service->parse() since it requires applications to exist. * * @param Service $service The service to apply prerequisites to */ function applyServiceApplicationPrerequisites(Service $service): void { try { // Extract service name from service name (format: "servicename-uuid") $serviceName = str($service->name)->beforeLast('-')->value(); // Apply gzip disabling if needed if (array_key_exists($serviceName, NEEDS_TO_DISABLE_GZIP)) { $applicationNames = NEEDS_TO_DISABLE_GZIP[$serviceName]; foreach ($applicationNames as $applicationName) { $application = $service->applications()->whereName($applicationName)->first(); if ($application) { $application->is_gzip_enabled = false; $application->save(); } } } // Apply stripprefix disabling if needed if (array_key_exists($serviceName, NEEDS_TO_DISABLE_STRIPPREFIX)) { $applicationNames = NEEDS_TO_DISABLE_STRIPPREFIX[$serviceName]; foreach ($applicationNames as $applicationName) { $application = $service->applications()->whereName($applicationName)->first(); if ($application) { $application->is_stripprefix_enabled = false; $application->save(); } } } } catch (\Throwable $e) { // Log error but don't throw - prerequisites are nice-to-have, not critical Log::error('Failed to apply service application prerequisites', [ 'service_id' => $service->id, 'service_name' => $service->name, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } } ================================================ FILE: bootstrap/helpers/shared.php ================================================ 'backtick (command substitution)', '$(' => 'command substitution', '${' => 'variable substitution with potential command injection', '|' => 'pipe operator', '&' => 'background/AND operator', ';' => 'command separator', "\n" => 'newline (command separator)', "\r" => 'carriage return', "\t" => 'tab (token separator)', '>' => 'output redirection', '<' => 'input redirection', ]; // Check for dangerous characters foreach ($dangerousChars as $char => $description) { if (str_contains($input, $char)) { throw new \Exception( "Invalid {$context}: contains forbidden character '{$char}' ({$description}). ". 'Shell metacharacters are not allowed for security reasons.' ); } } return $input; } /** * Validate that a string is a safe git ref (commit SHA, branch name, tag, or HEAD). * * Prevents command injection by enforcing an allowlist of characters valid for git refs. * Valid: hex SHAs, HEAD, branch/tag names (alphanumeric, dots, hyphens, underscores, slashes). * * @param string $input The git ref to validate * @param string $context Descriptive name for error messages * @return string The validated input (trimmed) * * @throws \Exception If the input contains disallowed characters */ function validateGitRef(string $input, string $context = 'git ref'): string { $input = trim($input); if ($input === '' || $input === 'HEAD') { return $input; } // Must not start with a hyphen (git flag injection) if (str_starts_with($input, '-')) { throw new \Exception("Invalid {$context}: must not start with a hyphen."); } // Allow only alphanumeric characters, dots, hyphens, underscores, and slashes if (! preg_match('/^[a-zA-Z0-9][a-zA-Z0-9._\-\/]*$/', $input)) { throw new \Exception("Invalid {$context}: contains disallowed characters. Only alphanumeric characters, dots, hyphens, underscores, and slashes are allowed."); } return $input; } function generate_readme_file(string $name, string $updated_at): string { $name = sanitize_string($name); $updated_at = sanitize_string($updated_at); return "Resource name: $name\nLatest Deployment Date: $updated_at"; } function isInstanceAdmin() { return auth()?->user()?->isInstanceAdmin() ?? false; } function currentTeam() { return Auth::user()?->currentTeam() ?? null; } function showBoarding(): bool { if (isDev()) { return false; } if (Auth::user()?->isMember()) { return false; } return currentTeam()->show_boarding ?? false; } function refreshSession(?Team $team = null): void { if (! $team) { if (Auth::user()->currentTeam()) { $team = Team::find(Auth::user()->currentTeam()->id); } else { $team = User::find(Auth::id())->teams->first(); } } // Clear old cache key format for backwards compatibility Cache::forget('team:'.Auth::id()); // Use new cache key format that includes team ID Cache::forget('user:'.Auth::id().':team:'.$team->id); Cache::remember('user:'.Auth::id().':team:'.$team->id, 3600, function () use ($team) { return $team; }); session(['currentTeam' => $team]); } function handleError(?Throwable $error = null, ?Livewire\Component $livewire = null, ?string $customErrorMessage = null) { if ($error instanceof TooManyRequestsException) { if (isset($livewire)) { return $livewire->dispatch('error', "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."); } return "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."; } if ($error instanceof UniqueConstraintViolationException) { if (isset($livewire)) { return $livewire->dispatch('error', 'Duplicate entry found. Please use a different name.'); } return 'Duplicate entry found. Please use a different name.'; } if ($error instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) { abort(404); } if ($error instanceof Throwable) { $message = $error->getMessage(); } else { $message = null; } if ($customErrorMessage) { $message = $customErrorMessage.' '.$message; } if (isset($livewire)) { return $livewire->dispatch('error', $message); } throw new Exception($message); } function get_route_parameters(): array { return Route::current()->parameters(); } function get_latest_sentinel_version(): string { try { $response = Http::get(config('constants.coolify.versions_url')); $versions = $response->json(); return data_get($versions, 'coolify.sentinel.version'); } catch (\Throwable) { return '0.0.0'; } } function get_latest_version_of_coolify(): string { try { $versions = get_versions_data(); return data_get($versions, 'coolify.v4.version', '0.0.0'); } catch (\Throwable $e) { return '0.0.0'; } } function generate_random_name(?string $cuid = null): string { $generator = new \Nubs\RandomNameGenerator\All( [ new \Nubs\RandomNameGenerator\Alliteration, ] ); if (is_null($cuid)) { $cuid = new Cuid2; } return Str::kebab("{$generator->getName()}-$cuid"); } function generateSSHKey(string $type = 'rsa') { if ($type === 'rsa') { $key = RSA::createKey(); return [ 'private' => $key->toString('PKCS1'), 'public' => $key->getPublicKey()->toString('OpenSSH', ['comment' => 'coolify-generated-ssh-key']), ]; } elseif ($type === 'ed25519') { $key = EC::createKey('Ed25519'); return [ 'private' => $key->toString('OpenSSH'), 'public' => $key->getPublicKey()->toString('OpenSSH', ['comment' => 'coolify-generated-ssh-key']), ]; } throw new Exception('Invalid key type'); } function formatPrivateKey(string $privateKey) { $privateKey = trim($privateKey); if (! str_ends_with($privateKey, "\n")) { $privateKey .= "\n"; } return $privateKey; } function generate_application_name(string $git_repository, string $git_branch, ?string $cuid = null): string { if (is_null($cuid)) { $cuid = new Cuid2; } return Str::kebab("$git_repository:$git_branch-$cuid"); } /** * Sort branches by priority: main first, master second, then alphabetically. * * @param Collection $branches Collection of branch objects with 'name' key */ function sortBranchesByPriority(Collection $branches): Collection { return $branches->sortBy(function ($branch) { $name = data_get($branch, 'name'); return match ($name) { 'main' => '0_main', 'master' => '1_master', default => '2_'.$name, }; })->values(); } function base_ip(): string { if (isDev()) { return 'localhost'; } $settings = instanceSettings(); if ($settings->public_ipv4) { return "$settings->public_ipv4"; } if ($settings->public_ipv6) { return "$settings->public_ipv6"; } return 'localhost'; } function getFqdnWithoutPort(string $fqdn) { try { $url = Url::fromString($fqdn); $host = $url->getHost(); $scheme = $url->getScheme(); $path = $url->getPath(); return "$scheme://$host$path"; } catch (\Throwable) { return $fqdn; } } /** * If fqdn is set, return it, otherwise return public ip. */ function base_url(bool $withPort = true): string { $settings = instanceSettings(); if ($settings->fqdn) { return $settings->fqdn; } $port = config('app.port'); if ($settings->public_ipv4) { if ($withPort) { if (isDev()) { return "http://localhost:$port"; } return "http://$settings->public_ipv4:$port"; } if (isDev()) { return 'http://localhost'; } return "http://$settings->public_ipv4"; } if ($settings->public_ipv6) { if ($withPort) { return "http://$settings->public_ipv6:$port"; } return "http://$settings->public_ipv6"; } return url('/'); } function isSubscribed() { return isSubscriptionActive(); } function isProduction(): bool { return ! isDev(); } function isDev(): bool { return config('app.env') === 'local'; } function isCloud(): bool { return ! config('constants.coolify.self_hosted'); } function translate_cron_expression($expression_to_validate): string { if (isset(VALID_CRON_STRINGS[$expression_to_validate])) { return VALID_CRON_STRINGS[$expression_to_validate]; } return $expression_to_validate; } function validate_cron_expression($expression_to_validate): bool { if (empty($expression_to_validate)) { return false; } $isValid = false; $expression = new CronExpression($expression_to_validate); $isValid = $expression->isValid(); if (isset(VALID_CRON_STRINGS[$expression_to_validate])) { $isValid = true; } return $isValid; } function validate_timezone(string $timezone): bool { return in_array($timezone, timezone_identifiers_list()); } function parseEnvFormatToArray($env_file_contents) { $env_array = []; $lines = explode("\n", $env_file_contents); foreach ($lines as $line) { if ($line === '' || substr($line, 0, 1) === '#') { continue; } $equals_pos = strpos($line, '='); if ($equals_pos !== false) { $key = substr($line, 0, $equals_pos); $value_and_comment = substr($line, $equals_pos + 1); $comment = null; $remainder = ''; // Check if value starts with quotes $firstChar = $value_and_comment[0] ?? ''; $isDoubleQuoted = $firstChar === '"'; $isSingleQuoted = $firstChar === "'"; if ($isDoubleQuoted) { // Find the closing double quote $closingPos = strpos($value_and_comment, '"', 1); if ($closingPos !== false) { // Extract quoted value and remove quotes $value = substr($value_and_comment, 1, $closingPos - 1); // Everything after closing quote (including comments) $remainder = substr($value_and_comment, $closingPos + 1); } else { // No closing quote - treat as unquoted $value = substr($value_and_comment, 1); } } elseif ($isSingleQuoted) { // Find the closing single quote $closingPos = strpos($value_and_comment, "'", 1); if ($closingPos !== false) { // Extract quoted value and remove quotes $value = substr($value_and_comment, 1, $closingPos - 1); // Everything after closing quote (including comments) $remainder = substr($value_and_comment, $closingPos + 1); } else { // No closing quote - treat as unquoted $value = substr($value_and_comment, 1); } } else { // Unquoted value - strip inline comments // Only treat # as comment if preceded by whitespace if (preg_match('/\s+#/', $value_and_comment, $matches, PREG_OFFSET_CAPTURE)) { // Found whitespace followed by #, extract comment $remainder = substr($value_and_comment, $matches[0][1]); $value = substr($value_and_comment, 0, $matches[0][1]); $value = rtrim($value); } else { $value = $value_and_comment; } } // Extract comment from remainder (if any) if ($remainder !== '') { // Look for # in remainder $hashPos = strpos($remainder, '#'); if ($hashPos !== false) { // Extract everything after the # and trim $comment = substr($remainder, $hashPos + 1); $comment = trim($comment); // Set to null if empty after trimming if ($comment === '') { $comment = null; } } } $env_array[$key] = [ 'value' => $value, 'comment' => $comment, ]; } } return $env_array; } /** * Extract inline comments from environment variables in raw docker-compose YAML. * * Parses raw docker-compose YAML to extract inline comments from environment sections. * Standard YAML parsers discard comments, so this pre-processes the raw text. * * Handles both formats: * - Map format: `KEY: "value" # comment` or `KEY: value # comment` * - Array format: `- KEY=value # comment` * * @param string $rawYaml The raw docker-compose.yml content * @return array Map of environment variable keys to their inline comments */ function extractYamlEnvironmentComments(string $rawYaml): array { $comments = []; $lines = explode("\n", $rawYaml); $inEnvironmentBlock = false; $environmentIndent = 0; foreach ($lines as $line) { // Skip empty lines if (trim($line) === '') { continue; } // Calculate current line's indentation (number of leading spaces) $currentIndent = strlen($line) - strlen(ltrim($line)); // Check if this line starts an environment block if (preg_match('/^(\s*)environment\s*:\s*$/', $line, $matches)) { $inEnvironmentBlock = true; $environmentIndent = strlen($matches[1]); continue; } // Check if this line starts an environment block with inline content (rare but possible) if (preg_match('/^(\s*)environment\s*:\s*\{/', $line)) { // Inline object format - not supported for comment extraction continue; } // If we're in an environment block, check if we've exited it if ($inEnvironmentBlock) { // If we hit a line with same or less indentation that's not empty, we've left the block // Unless it's a continuation of the environment block $trimmedLine = ltrim($line); // Check if this is a new top-level key (same indent as 'environment:' or less) if ($currentIndent <= $environmentIndent && ! str_starts_with($trimmedLine, '-') && ! str_starts_with($trimmedLine, '#')) { // Check if it looks like a YAML key (contains : not inside quotes) if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*\s*:/', $trimmedLine)) { $inEnvironmentBlock = false; continue; } } // Skip comment-only lines if (str_starts_with($trimmedLine, '#')) { continue; } // Try to extract environment variable and comment from this line $extracted = extractEnvVarCommentFromYamlLine($trimmedLine); if ($extracted !== null && $extracted['comment'] !== null) { $comments[$extracted['key']] = $extracted['comment']; } } } return $comments; } /** * Extract environment variable key and inline comment from a single YAML line. * * @param string $line A trimmed line from the environment section * @return array|null Array with 'key' and 'comment', or null if not an env var line */ function extractEnvVarCommentFromYamlLine(string $line): ?array { $key = null; $comment = null; // Handle array format: `- KEY=value # comment` or `- KEY # comment` if (str_starts_with($line, '-')) { $content = ltrim(substr($line, 1)); // Check for KEY=value format if (preg_match('/^([A-Za-z_][A-Za-z0-9_]*)/', $content, $keyMatch)) { $key = $keyMatch[1]; // Find comment - need to handle quoted values $comment = extractCommentAfterValue($content); } } // Handle map format: `KEY: "value" # comment` or `KEY: value # comment` elseif (preg_match('/^([A-Za-z_][A-Za-z0-9_]*)\s*:/', $line, $keyMatch)) { $key = $keyMatch[1]; // Get everything after the key and colon $afterKey = substr($line, strlen($keyMatch[0])); $comment = extractCommentAfterValue($afterKey); } if ($key === null) { return null; } return [ 'key' => $key, 'comment' => $comment, ]; } /** * Extract inline comment from a value portion of a YAML line. * * Handles quoted values (where # inside quotes is not a comment). * * @param string $valueAndComment The value portion (may include comment) * @return string|null The comment text, or null if no comment */ function extractCommentAfterValue(string $valueAndComment): ?string { $valueAndComment = ltrim($valueAndComment); if ($valueAndComment === '') { return null; } $firstChar = $valueAndComment[0] ?? ''; // Handle case where value is empty and line starts directly with comment // e.g., `KEY: # comment` becomes `# comment` after ltrim if ($firstChar === '#') { $comment = trim(substr($valueAndComment, 1)); return $comment !== '' ? $comment : null; } // Handle double-quoted value if ($firstChar === '"') { // Find closing quote (handle escaped quotes) $pos = 1; $len = strlen($valueAndComment); while ($pos < $len) { if ($valueAndComment[$pos] === '\\' && $pos + 1 < $len) { $pos += 2; // Skip escaped character continue; } if ($valueAndComment[$pos] === '"') { // Found closing quote $remainder = substr($valueAndComment, $pos + 1); return extractCommentFromRemainder($remainder); } $pos++; } // No closing quote found return null; } // Handle single-quoted value if ($firstChar === "'") { // Find closing quote (single quotes don't have escapes in YAML) $closingPos = strpos($valueAndComment, "'", 1); if ($closingPos !== false) { $remainder = substr($valueAndComment, $closingPos + 1); return extractCommentFromRemainder($remainder); } // No closing quote found return null; } // Unquoted value - find # that's preceded by whitespace // Be careful not to match # at the start of a value like color codes if (preg_match('/\s+#\s*(.*)$/', $valueAndComment, $matches)) { $comment = trim($matches[1]); return $comment !== '' ? $comment : null; } return null; } /** * Extract comment from the remainder of a line after a quoted value. * * @param string $remainder Text after the closing quote * @return string|null The comment text, or null if no comment */ function extractCommentFromRemainder(string $remainder): ?string { // Look for # in remainder $hashPos = strpos($remainder, '#'); if ($hashPos !== false) { $comment = trim(substr($remainder, $hashPos + 1)); return $comment !== '' ? $comment : null; } return null; } function data_get_str($data, $key, $default = null): Stringable { $str = data_get($data, $key, $default) ?? $default; return str($str); } function generateUrl(Server $server, string $random, bool $forceHttps = false): string { $wildcard = data_get($server, 'settings.wildcard_domain'); if (is_null($wildcard) || $wildcard === '') { $wildcard = sslip($server); } $url = Url::fromString($wildcard); $host = $url->getHost(); $path = $url->getPath() === '/' ? '' : $url->getPath(); $scheme = $url->getScheme(); if ($forceHttps) { $scheme = 'https'; } return "$scheme://{$random}.$host$path"; } function generateFqdn(Server $server, string $random, bool $forceHttps = false, int $parserVersion = 5): string { $wildcard = data_get($server, 'settings.wildcard_domain'); if (is_null($wildcard) || $wildcard === '') { $wildcard = sslip($server); } $url = Url::fromString($wildcard); $host = $url->getHost(); $path = $url->getPath() === '/' ? '' : $url->getPath(); $scheme = $url->getScheme(); if ($forceHttps) { $scheme = 'https'; } if ($parserVersion >= 5 && version_compare(config('constants.coolify.version'), '4.0.0-beta.420.7', '>=')) { return "{$random}.$host$path"; } return "$scheme://{$random}.$host$path"; } function sslip(Server $server) { if (isDev() && $server->id === 0) { return 'http://127.0.0.1.sslip.io'; } if ($server->ip === 'host.docker.internal') { $baseIp = base_ip(); return "http://$baseIp.sslip.io"; } // ipv6 if (str($server->ip)->contains(':')) { $ipv6 = str($server->ip)->replace(':', '-'); return "http://{$ipv6}.sslip.io"; } return "http://{$server->ip}.sslip.io"; } function get_service_templates(bool $force = false): Collection { if ($force) { try { $response = Http::retry(3, 1000)->get(config('constants.services.official')); if ($response->failed()) { return collect([]); } $services = $response->json(); return collect($services); } catch (\Throwable) { $services = File::get(base_path('templates/'.config('constants.services.file_name'))); return collect(json_decode($services))->sortKeys(); } } else { $services = File::get(base_path('templates/'.config('constants.services.file_name'))); return collect(json_decode($services))->sortKeys(); } } function getResourceByUuid(string $uuid, ?int $teamId = null) { if (is_null($teamId)) { return null; } $resource = queryResourcesByUuid($uuid); if (is_null($resource)) { return null; } // ServiceDatabase has a different relationship path: service->environment->project->team_id if ($resource instanceof \App\Models\ServiceDatabase) { if ($resource->service?->environment?->project?->team_id === $teamId) { return $resource; } return null; } // Standard resources: environment->project->team_id if ($resource->environment->project->team_id === $teamId) { return $resource; } return null; } function queryDatabaseByUuidWithinTeam(string $uuid, string $teamId) { $postgresql = StandalonePostgresql::whereUuid($uuid)->first(); if ($postgresql && $postgresql->team()->id == $teamId) { return $postgresql->unsetRelation('environment'); } $redis = StandaloneRedis::whereUuid($uuid)->first(); if ($redis && $redis->team()->id == $teamId) { return $redis->unsetRelation('environment'); } $mongodb = StandaloneMongodb::whereUuid($uuid)->first(); if ($mongodb && $mongodb->team()->id == $teamId) { return $mongodb->unsetRelation('environment'); } $mysql = StandaloneMysql::whereUuid($uuid)->first(); if ($mysql && $mysql->team()->id == $teamId) { return $mysql->unsetRelation('environment'); } $mariadb = StandaloneMariadb::whereUuid($uuid)->first(); if ($mariadb && $mariadb->team()->id == $teamId) { return $mariadb->unsetRelation('environment'); } $keydb = StandaloneKeydb::whereUuid($uuid)->first(); if ($keydb && $keydb->team()->id == $teamId) { return $keydb->unsetRelation('environment'); } $dragonfly = StandaloneDragonfly::whereUuid($uuid)->first(); if ($dragonfly && $dragonfly->team()->id == $teamId) { return $dragonfly->unsetRelation('environment'); } $clickhouse = StandaloneClickhouse::whereUuid($uuid)->first(); if ($clickhouse && $clickhouse->team()->id == $teamId) { return $clickhouse->unsetRelation('environment'); } return null; } function queryResourcesByUuid(string $uuid) { $resource = null; $application = Application::whereUuid($uuid)->first(); if ($application) { return $application; } $service = Service::whereUuid($uuid)->first(); if ($service) { return $service; } $postgresql = StandalonePostgresql::whereUuid($uuid)->first(); if ($postgresql) { return $postgresql; } $redis = StandaloneRedis::whereUuid($uuid)->first(); if ($redis) { return $redis; } $mongodb = StandaloneMongodb::whereUuid($uuid)->first(); if ($mongodb) { return $mongodb; } $mysql = StandaloneMysql::whereUuid($uuid)->first(); if ($mysql) { return $mysql; } $mariadb = StandaloneMariadb::whereUuid($uuid)->first(); if ($mariadb) { return $mariadb; } $keydb = StandaloneKeydb::whereUuid($uuid)->first(); if ($keydb) { return $keydb; } $dragonfly = StandaloneDragonfly::whereUuid($uuid)->first(); if ($dragonfly) { return $dragonfly; } $clickhouse = StandaloneClickhouse::whereUuid($uuid)->first(); if ($clickhouse) { return $clickhouse; } // Check for ServiceDatabase by its own UUID $serviceDatabase = ServiceDatabase::whereUuid($uuid)->first(); if ($serviceDatabase) { return $serviceDatabase; } return $resource; } function generateTagDeployWebhook($tag_name) { $baseUrl = base_url(); $api = Url::fromString($baseUrl).'/api/v1'; $endpoint = "/deploy?tag=$tag_name"; return $api.$endpoint; } function generateDeployWebhook($resource) { $baseUrl = base_url(); $api = Url::fromString($baseUrl).'/api/v1'; $endpoint = '/deploy'; $uuid = data_get($resource, 'uuid'); return $api.$endpoint."?uuid=$uuid&force=false"; } function generateGitManualWebhook($resource, $type) { if ($resource->source_id !== 0 && ! is_null($resource->source_id)) { return null; } if ($resource->getMorphClass() === \App\Models\Application::class) { $baseUrl = base_url(); return Url::fromString($baseUrl)."/webhooks/source/$type/events/manual"; } return null; } function removeAnsiColors($text) { return preg_replace('/\e[[][A-Za-z0-9];?[0-9]*m?/', '', $text); } function sanitizeLogsForExport(string $text): string { // All sanitization is now handled by remove_iip() return remove_iip($text); } function getTopLevelNetworks(Service|Application $resource) { if ($resource->getMorphClass() === \App\Models\Service::class) { if ($resource->docker_compose_raw) { try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { // If the docker-compose.yml file is not valid, we will return the network name as the key $topLevelNetworks = collect([ $resource->uuid => [ 'name' => $resource->uuid, 'external' => true, ], ]); return $topLevelNetworks->keys(); } $services = data_get($yaml, 'services'); $topLevelNetworks = collect(data_get($yaml, 'networks', [])); $definedNetwork = collect([$resource->uuid]); $services = collect($services)->map(function ($service, $_) use ($topLevelNetworks, $definedNetwork) { $serviceNetworks = collect(data_get($service, 'networks', [])); $networkMode = data_get($service, 'network_mode'); $hasValidNetworkMode = $networkMode === 'host' || (is_string($networkMode) && (str_starts_with($networkMode, 'service:') || str_starts_with($networkMode, 'container:'))); // Only add 'networks' key if 'network_mode' is not 'host' or does not start with 'service:' or 'container:' if (! $hasValidNetworkMode) { // Collect/create/update networks if ($serviceNetworks->count() > 0) { foreach ($serviceNetworks as $networkName => $networkDetails) { if ($networkName === 'default') { continue; } // ignore alias if ($networkDetails['aliases'] ?? false) { continue; } $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } } } } $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { $topLevelNetworks->put($network, [ 'name' => $network, 'external' => true, ]); } } } return $service; }); return $topLevelNetworks->keys(); } } elseif ($resource->getMorphClass() === \App\Models\Application::class) { try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { // If the docker-compose.yml file is not valid, we will return the network name as the key $topLevelNetworks = collect([ $resource->uuid => [ 'name' => $resource->uuid, 'external' => true, ], ]); return $topLevelNetworks->keys(); } $topLevelNetworks = collect(data_get($yaml, 'networks', [])); $services = data_get($yaml, 'services'); $definedNetwork = collect([$resource->uuid]); $services = collect($services)->map(function ($service, $_) use ($topLevelNetworks, $definedNetwork) { $serviceNetworks = collect(data_get($service, 'networks', [])); // Collect/create/update networks if ($serviceNetworks->count() > 0) { foreach ($serviceNetworks as $networkName => $networkDetails) { if ($networkName === 'default') { continue; } // ignore alias if ($networkDetails['aliases'] ?? false) { continue; } $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } } } } $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { $topLevelNetworks->put($network, [ 'name' => $network, 'external' => true, ]); } } return $service; }); return $topLevelNetworks->keys(); } } function sourceIsLocal(Stringable $source) { if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~') || $source->startsWith('..') || $source->startsWith('~/') || $source->startsWith('../')) { return true; } return false; } function replaceLocalSource(Stringable $source, Stringable $replacedWith) { if ($source->startsWith('.')) { $source = $source->replaceFirst('.', $replacedWith->value()); } if ($source->startsWith('~')) { $source = $source->replaceFirst('~', $replacedWith->value()); } if ($source->startsWith('..')) { $source = $source->replaceFirst('..', $replacedWith->value()); } if ($source->endsWith('/') && $source->value() !== '/') { $source = $source->replaceLast('/', ''); } return $source; } function convertToArray($collection) { if ($collection instanceof Collection) { return $collection->map(function ($item) { return convertToArray($item); })->toArray(); } elseif ($collection instanceof Stringable) { return (string) $collection; } elseif (is_array($collection)) { return array_map(function ($item) { return convertToArray($item); }, $collection); } return $collection; } function parseCommandFromMagicEnvVariable(Str|string $key): Stringable { $value = str($key); $count = substr_count($value->value(), '_'); $command = null; if ($count === 2) { if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) { // SERVICE_FQDN_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); } else { // SERVICE_BASE64_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); } } if ($count === 3) { if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) { // SERVICE_FQDN_UMAMI_1000 $command = $value->after('SERVICE_')->before('_'); } else { // SERVICE_BASE64_64_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); } } return str($command); } function parseEnvVariable(Str|string $value) { $value = str($value); $count = substr_count($value->value(), '_'); $command = null; $forService = null; $generatedValue = null; $port = null; if ($value->startsWith('SERVICE')) { if ($count === 2) { if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) { // SERVICE_FQDN_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); $forService = $value->afterLast('_'); } else { // SERVICE_BASE64_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); } } if ($count === 3) { if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) { // SERVICE_FQDN_UMAMI_1000 $command = $value->after('SERVICE_')->before('_'); $forService = $value->after('SERVICE_')->after('_')->before('_'); $port = $value->afterLast('_'); if (filter_var($port, FILTER_VALIDATE_INT) === false) { $port = null; } } else { // SERVICE_BASE64_64_UMAMI $command = $value->after('SERVICE_')->beforeLast('_'); } } } return [ 'command' => $command, 'forService' => $forService, 'generatedValue' => $generatedValue, 'port' => $port, ]; } function generateEnvValue(string $command, Service|Application|null $service = null) { switch ($command) { case 'PASSWORD': $generatedValue = Str::password(symbols: false); break; case 'PASSWORD_64': $generatedValue = Str::password(length: 64, symbols: false); break; case 'PASSWORDWITHSYMBOLS': $generatedValue = Str::password(symbols: true); break; case 'PASSWORDWITHSYMBOLS_64': $generatedValue = Str::password(length: 64, symbols: true); break; // This is not base64, it's just a random string case 'BASE64_64': $generatedValue = Str::random(64); break; case 'BASE64_128': $generatedValue = Str::random(128); break; case 'BASE64': case 'BASE64_32': $generatedValue = Str::random(32); break; // This is base64, case 'REALBASE64_64': $generatedValue = base64_encode(Str::random(64)); break; case 'REALBASE64_128': $generatedValue = base64_encode(Str::random(128)); break; case 'REALBASE64': case 'REALBASE64_32': $generatedValue = base64_encode(Str::random(32)); break; case 'HEX_32': $generatedValue = bin2hex(Str::random(32)); break; case 'HEX_64': $generatedValue = bin2hex(Str::random(64)); break; case 'HEX_128': $generatedValue = bin2hex(Str::random(128)); break; case 'USER': $generatedValue = Str::random(16); break; case 'LOWERCASEUSER': $generatedValue = Str::lower(Str::random(16)); break; case 'SUPABASEANON': $signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first(); if (is_null($signingKey)) { return; } else { $signingKey = $signingKey->value; } $key = InMemory::plainText($signingKey); $algorithm = new Sha256; $tokenBuilder = (new Builder(new JoseEncoder, ChainedFormatter::default())); $now = CarbonImmutable::now(); $now = $now->setTime($now->format('H'), $now->format('i')); $token = $tokenBuilder ->issuedBy('supabase') ->issuedAt($now) ->expiresAt($now->modify('+100 year')) ->withClaim('role', 'anon') ->getToken($algorithm, $key); $generatedValue = $token->toString(); break; case 'SUPABASESERVICE': $signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first(); if (is_null($signingKey)) { return; } else { $signingKey = $signingKey->value; } $key = InMemory::plainText($signingKey); $algorithm = new Sha256; $tokenBuilder = (new Builder(new JoseEncoder, ChainedFormatter::default())); $now = CarbonImmutable::now(); $now = $now->setTime($now->format('H'), $now->format('i')); $token = $tokenBuilder ->issuedBy('supabase') ->issuedAt($now) ->expiresAt($now->modify('+100 year')) ->withClaim('role', 'service_role') ->getToken($algorithm, $key); $generatedValue = $token->toString(); break; default: // $generatedValue = Str::random(16); $generatedValue = null; break; } return $generatedValue; } function getRealtime() { $envDefined = config('constants.pusher.port'); if (empty($envDefined)) { $url = Url::fromString(Request::getSchemeAndHttpHost()); $port = $url->getPort(); if ($port) { return '6001'; } else { return null; } } else { return $envDefined; } } function validateDNSEntry(string $fqdn, Server $server) { // https://www.cloudflare.com/ips-v4/# $cloudflare_ips = collect(['173.245.48.0/20', '103.21.244.0/22', '103.22.200.0/22', '103.31.4.0/22', '141.101.64.0/18', '108.162.192.0/18', '190.93.240.0/20', '188.114.96.0/20', '197.234.240.0/22', '198.41.128.0/17', '162.158.0.0/15', '104.16.0.0/13', '172.64.0.0/13', '131.0.72.0/22']); $url = Url::fromString($fqdn); $host = $url->getHost(); if (str($host)->contains('sslip.io')) { return true; } $settings = instanceSettings(); $is_dns_validation_enabled = data_get($settings, 'is_dns_validation_enabled'); if (! $is_dns_validation_enabled) { return true; } $dns_servers = data_get($settings, 'custom_dns_servers'); $dns_servers = str($dns_servers)->explode(','); if ($server->id === 0) { $ip = data_get($settings, 'public_ipv4', data_get($settings, 'public_ipv6', $server->ip)); } else { $ip = $server->ip; } $found_matching_ip = false; $type = \PurplePixie\PhpDns\DNSTypes::NAME_A; foreach ($dns_servers as $dns_server) { try { $query = new DNSQuery($dns_server); $results = $query->query($host, $type); if ($results === false || $query->hasError()) { ray('Error: '.$query->getLasterror()); } else { foreach ($results as $result) { if ($result->getType() == $type) { if (ipMatch($result->getData(), $cloudflare_ips->toArray(), $match)) { $found_matching_ip = true; break; } if ($result->getData() === $ip) { $found_matching_ip = true; break; } } } } } catch (\Exception) { } } return $found_matching_ip; } function ipMatch($ip, $cidrs, &$match = null) { foreach ((array) $cidrs as $cidr) { [$subnet, $mask] = explode('/', $cidr); if (((ip2long($ip) & ($mask = ~((1 << (32 - $mask)) - 1))) == (ip2long($subnet) & $mask))) { $match = $cidr; return true; } } return false; } function checkIPAgainstAllowlist($ip, $allowlist) { if (empty($allowlist)) { return false; } foreach ((array) $allowlist as $allowed) { $allowed = trim($allowed); if (empty($allowed)) { continue; } // Check if it's a CIDR notation if (str_contains($allowed, '/')) { [$subnet, $mask] = explode('/', $allowed); // Special case: 0.0.0.0 with any subnet means allow all if ($subnet === '0.0.0.0') { return true; } $mask = (int) $mask; $isIpv6Subnet = filter_var($subnet, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false; $maxMask = $isIpv6Subnet ? 128 : 32; // Validate mask for address family if ($mask < 0 || $mask > $maxMask) { continue; } if ($isIpv6Subnet) { // IPv6 CIDR matching using binary string comparison $ipBin = inet_pton($ip); $subnetBin = inet_pton($subnet); if ($ipBin === false || $subnetBin === false) { continue; } // Build a 128-bit mask from $mask prefix bits $maskBin = str_repeat("\xff", (int) ($mask / 8)); $remainder = $mask % 8; if ($remainder > 0) { $maskBin .= chr(0xFF & (0xFF << (8 - $remainder))); } $maskBin = str_pad($maskBin, 16, "\x00"); if (($ipBin & $maskBin) === ($subnetBin & $maskBin)) { return true; } } else { // IPv4 CIDR matching $ip_long = ip2long($ip); $subnet_long = ip2long($subnet); if ($ip_long === false || $subnet_long === false) { continue; } $mask_long = ~((1 << (32 - $mask)) - 1); if (($ip_long & $mask_long) == ($subnet_long & $mask_long)) { return true; } } } else { // Special case: 0.0.0.0 means allow all if ($allowed === '0.0.0.0') { return true; } // Direct IP comparison if ($ip === $allowed) { return true; } } } return false; } function deduplicateAllowlist(array $entries): array { if (count($entries) <= 1) { return array_values($entries); } // Normalize each entry into [original, ip, mask] $parsed = []; foreach ($entries as $entry) { $entry = trim($entry); if (empty($entry)) { continue; } if ($entry === '0.0.0.0') { // Special case: bare 0.0.0.0 means "allow all" — treat as /0 $parsed[] = ['original' => $entry, 'ip' => '0.0.0.0', 'mask' => 0]; } elseif (str_contains($entry, '/')) { [$ip, $mask] = explode('/', $entry); $parsed[] = ['original' => $entry, 'ip' => $ip, 'mask' => (int) $mask]; } else { $ip = $entry; $isIpv6 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false; $parsed[] = ['original' => $entry, 'ip' => $ip, 'mask' => $isIpv6 ? 128 : 32]; } } $count = count($parsed); $redundant = array_fill(0, $count, false); for ($i = 0; $i < $count; $i++) { if ($redundant[$i]) { continue; } for ($j = 0; $j < $count; $j++) { if ($i === $j || $redundant[$j]) { continue; } // Entry $j is redundant if its mask is narrower/equal (>=) than $i's mask // AND $j's network IP falls within $i's CIDR range if ($parsed[$j]['mask'] >= $parsed[$i]['mask']) { $cidr = $parsed[$i]['ip'].'/'.$parsed[$i]['mask']; if (checkIPAgainstAllowlist($parsed[$j]['ip'], [$cidr])) { $redundant[$j] = true; } } } } $result = []; for ($i = 0; $i < $count; $i++) { if (! $redundant[$i]) { $result[] = $parsed[$i]['original']; } } return $result; } function get_public_ips() { try { [$first, $second] = Process::concurrently(function (Pool $pool) { $pool->path(__DIR__)->command('curl -4s https://ifconfig.io'); $pool->path(__DIR__)->command('curl -6s https://ifconfig.io'); }); $ipv4 = $first->output(); if ($ipv4) { $ipv4 = trim($ipv4); $validate_ipv4 = filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); if ($validate_ipv4 == false) { echo "Invalid ipv4: $ipv4\n"; return; } InstanceSettings::get()->update(['public_ipv4' => $ipv4]); } } catch (\Exception $e) { echo "Error: {$e->getMessage()}\n"; } try { $ipv6 = $second->output(); if ($ipv6) { $ipv6 = trim($ipv6); $validate_ipv6 = filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); if ($validate_ipv6 == false) { echo "Invalid ipv6: $ipv6\n"; return; } InstanceSettings::get()->update(['public_ipv6' => $ipv6]); } } catch (\Throwable $e) { echo "Error: {$e->getMessage()}\n"; } } function isAnyDeploymentInprogress() { $runningJobs = ApplicationDeploymentQueue::where('horizon_job_worker', gethostname())->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value)->get(); if ($runningJobs->isEmpty()) { echo "No deployments in progress.\n"; exit(0); } $horizonJobIds = []; $deploymentDetails = []; foreach ($runningJobs as $runningJob) { $horizonJobStatus = getJobStatus($runningJob->horizon_job_id); if ($horizonJobStatus === 'unknown' || $horizonJobStatus === 'reserved') { $horizonJobIds[] = $runningJob->horizon_job_id; // Get application and team information $application = Application::find($runningJob->application_id); $teamMembers = []; $deploymentUrl = ''; if ($application) { // Get team members through the application's project $team = $application->team(); if ($team) { $teamMembers = $team->members()->pluck('email')->toArray(); } // Construct the full deployment URL if ($runningJob->deployment_url) { $baseUrl = base_url(); $deploymentUrl = $baseUrl.$runningJob->deployment_url; } } $deploymentDetails[] = [ 'id' => $runningJob->id, 'application_name' => $runningJob->application_name ?? 'Unknown', 'server_name' => $runningJob->server_name ?? 'Unknown', 'deployment_url' => $deploymentUrl, 'team_members' => $teamMembers, 'created_at' => $runningJob->created_at->format('Y-m-d H:i:s'), 'horizon_job_id' => $runningJob->horizon_job_id, ]; } } if (count($horizonJobIds) === 0) { echo "No active deployments in progress (all jobs completed or failed).\n"; exit(0); } // Display enhanced deployment information echo "\n=== Running Deployments ===\n"; echo 'Total active deployments: '.count($horizonJobIds)."\n\n"; foreach ($deploymentDetails as $index => $deployment) { echo 'Deployment #'.($index + 1).":\n"; echo ' Application: '.$deployment['application_name']."\n"; echo ' Server: '.$deployment['server_name']."\n"; echo ' Started: '.$deployment['created_at']."\n"; if ($deployment['deployment_url']) { echo ' URL: '.$deployment['deployment_url']."\n"; } if (! empty($deployment['team_members'])) { echo ' Team members: '.implode(', ', $deployment['team_members'])."\n"; } else { echo " Team members: No team members found\n"; } echo ' Horizon Job ID: '.$deployment['horizon_job_id']."\n"; echo "\n"; } exit(1); } function isBase64Encoded($strValue) { return base64_encode(base64_decode($strValue, true)) === $strValue; } function customApiValidator(Collection|array $item, array $rules) { if (is_array($item)) { $item = collect($item); } return Validator::make($item->toArray(), $rules, [ 'required' => 'This field is required.', ]); } function parseDockerComposeFile(Service|Application $resource, bool $isNew = false, int $pull_request_id = 0, ?int $preview_id = null) { if ($resource->getMorphClass() === \App\Models\Service::class) { if ($resource->docker_compose_raw) { // Extract inline comments from raw YAML before Symfony parser discards them $envComments = extractYamlEnvironmentComments($resource->docker_compose_raw); try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { throw new \RuntimeException($e->getMessage()); } $allServices = get_service_templates(); $topLevelVolumes = collect(data_get($yaml, 'volumes', [])); $topLevelNetworks = collect(data_get($yaml, 'networks', [])); $topLevelConfigs = collect(data_get($yaml, 'configs', [])); $topLevelSecrets = collect(data_get($yaml, 'secrets', [])); $services = data_get($yaml, 'services'); $generatedServiceFQDNS = collect([]); if (is_null($resource->destination)) { $destination = $resource->server->destinations()->first(); if ($destination) { $resource->destination()->associate($destination); $resource->save(); } } $definedNetwork = collect([$resource->uuid]); if ($topLevelVolumes->count() > 0) { $tempTopLevelVolumes = collect([]); foreach ($topLevelVolumes as $volumeName => $volume) { if (is_null($volume)) { continue; } $tempTopLevelVolumes->put($volumeName, $volume); } $topLevelVolumes = collect($tempTopLevelVolumes); } $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource, $allServices, $envComments) { // Workarounds for beta users. if ($serviceName === 'registry') { $tempServiceName = 'docker-registry'; } else { $tempServiceName = $serviceName; } if (str(data_get($service, 'image'))->contains('glitchtip')) { $tempServiceName = 'glitchtip'; } if ($serviceName === 'supabase-kong') { $tempServiceName = 'supabase'; } $serviceDefinition = data_get($allServices, $tempServiceName); $predefinedPort = data_get($serviceDefinition, 'port'); if ($serviceName === 'plausible') { $predefinedPort = '8000'; } // End of workarounds for beta users. $serviceVolumes = collect(data_get($service, 'volumes', [])); $servicePorts = collect(data_get($service, 'ports', [])); $serviceNetworks = collect(data_get($service, 'networks', [])); $serviceVariables = collect(data_get($service, 'environment', [])); $serviceLabels = collect(data_get($service, 'labels', [])); $networkMode = data_get($service, 'network_mode'); $hasValidNetworkMode = $networkMode === 'host' || (is_string($networkMode) && (str_starts_with($networkMode, 'service:') || str_starts_with($networkMode, 'container:'))); if ($serviceLabels->count() > 0) { $removedLabels = collect([]); $serviceLabels = $serviceLabels->filter(function ($serviceLabel, $serviceLabelName) use ($removedLabels) { // Handle array values from YAML (e.g., "traefik.enable: true" becomes an array) if (is_array($serviceLabel)) { $removedLabels->put($serviceLabelName, $serviceLabel); return false; } if (! str($serviceLabel)->contains('=')) { $removedLabels->put($serviceLabelName, $serviceLabel); return false; } return $serviceLabel; }); foreach ($removedLabels as $removedLabelName => $removedLabel) { // Convert array values to strings if (is_array($removedLabel)) { $removedLabel = (string) collect($removedLabel)->first(); } $serviceLabels->push("$removedLabelName=$removedLabel"); } } $containerName = "$serviceName-{$resource->uuid}"; // Decide if the service is a database $image = data_get_str($service, 'image'); // Check for manually migrated services first (respects user's conversion choice) $migratedApp = ServiceApplication::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); $migratedDb = ServiceDatabase::where('name', $serviceName) ->where('service_id', $resource->id) ->where('is_migrated', true) ->first(); if ($migratedApp || $migratedDb) { // Use the migrated service type, ignoring image detection $isDatabase = (bool) $migratedDb; $savedService = $migratedApp ?: $migratedDb; } else { // Use image detection for non-migrated services $isDatabase = isDatabaseImage($image, $service); // Create new serviceApplication or serviceDatabase if ($isDatabase) { if ($isNew) { $savedService = ServiceDatabase::create([ 'name' => $serviceName, 'image' => $image, 'service_id' => $resource->id, ]); } else { $savedService = ServiceDatabase::where([ 'name' => $serviceName, 'service_id' => $resource->id, ])->first(); if (is_null($savedService)) { $savedService = ServiceDatabase::create([ 'name' => $serviceName, 'image' => $image, 'service_id' => $resource->id, ]); } } } else { if ($isNew) { $savedService = ServiceApplication::create([ 'name' => $serviceName, 'image' => $image, 'service_id' => $resource->id, ]); } else { $savedService = ServiceApplication::where([ 'name' => $serviceName, 'service_id' => $resource->id, ])->first(); if (is_null($savedService)) { $savedService = ServiceApplication::create([ 'name' => $serviceName, 'image' => $image, 'service_id' => $resource->id, ]); } } } } data_set($service, 'is_database', $isDatabase); // Check if image changed if ($savedService->image !== $image) { $savedService->image = $image; $savedService->save(); } // Collect/create/update networks if ($serviceNetworks->count() > 0) { foreach ($serviceNetworks as $networkName => $networkDetails) { if ($networkName === 'default') { continue; } // ignore alias if ($networkDetails['aliases'] ?? false) { continue; } $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } } } } // Collect/create/update ports $collectedPorts = collect([]); if ($servicePorts->count() > 0) { foreach ($servicePorts as $sport) { if (is_string($sport) || is_numeric($sport)) { $collectedPorts->push($sport); } if (is_array($sport)) { $target = data_get($sport, 'target'); $published = data_get($sport, 'published'); $protocol = data_get($sport, 'protocol'); $collectedPorts->push("$target:$published/$protocol"); } } } $savedService->ports = $collectedPorts->implode(','); $savedService->save(); if (! $hasValidNetworkMode) { // Add Coolify specific networks $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { $topLevelNetworks->put($network, [ 'name' => $network, 'external' => true, ]); } } $networks = collect(); foreach ($serviceNetworks as $key => $serviceNetwork) { if (gettype($serviceNetwork) === 'string') { // networks: // - appwrite $networks->put($serviceNetwork, null); } elseif (gettype($serviceNetwork) === 'array') { // networks: // default: // ipv4_address: 192.168.203.254 // $networks->put($serviceNetwork, null); $networks->put($key, $serviceNetwork); } } foreach ($definedNetwork as $key => $network) { $networks->put($network, null); } data_set($service, 'networks', $networks->toArray()); } // Collect/create/update volumes if ($serviceVolumes->count() > 0) { $serviceVolumes = $serviceVolumes->map(function ($volume) use ($savedService, $topLevelVolumes) { $type = null; $source = null; $target = null; $content = null; $isDirectory = false; if (is_string($volume)) { $source = str($volume)->before(':'); $target = str($volume)->after(':')->beforeLast(':'); if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) { $type = str('bind'); // By default, we cannot determine if the bind is a directory or not, so we set it to directory $isDirectory = true; } else { $type = str('volume'); } } elseif (is_array($volume)) { $type = data_get_str($volume, 'type'); $source = data_get_str($volume, 'source'); $target = data_get_str($volume, 'target'); $content = data_get($volume, 'content'); $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); $foundConfig = $savedService->fileStorages()->whereMountPath($target)->first(); if ($foundConfig) { $contentNotNull = data_get($foundConfig, 'content'); if ($contentNotNull) { $content = $contentNotNull; } $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); } if (is_null($isDirectory) && is_null($content)) { // if isDirectory is not set & content is also not set, we assume it is a directory $isDirectory = true; } } if ($type?->value() === 'bind') { if ($source->value() === '/var/run/docker.sock') { return $volume; } if ($source->value() === '/tmp' || $source->value() === '/tmp/') { return $volume; } LocalFileVolume::updateOrCreate( [ 'mount_path' => $target, 'resource_id' => $savedService->id, 'resource_type' => get_class($savedService), ], [ 'fs_path' => $source, 'mount_path' => $target, 'content' => $content, 'is_directory' => $isDirectory, 'resource_id' => $savedService->id, 'resource_type' => get_class($savedService), ] ); } elseif ($type->value() === 'volume') { if ($topLevelVolumes->has($source->value())) { $v = $topLevelVolumes->get($source->value()); if (data_get($v, 'driver_opts.type') === 'cifs') { return $volume; } } $slugWithoutUuid = Str::slug($source, '-'); $name = "{$savedService->service->uuid}_{$slugWithoutUuid}"; if (is_string($volume)) { $source = str($volume)->before(':'); $target = str($volume)->after(':')->beforeLast(':'); $source = $name; $volume = "$source:$target"; } elseif (is_array($volume)) { data_set($volume, 'source', $name); } $topLevelVolumes->put($name, [ 'name' => $name, ]); LocalPersistentVolume::updateOrCreate( [ 'mount_path' => $target, 'resource_id' => $savedService->id, 'resource_type' => get_class($savedService), ], [ 'name' => $name, 'mount_path' => $target, 'resource_id' => $savedService->id, 'resource_type' => get_class($savedService), ] ); } dispatch(new ServerFilesFromServerJob($savedService)); return $volume; }); data_set($service, 'volumes', $serviceVolumes->toArray()); } // convert - SESSION_SECRET: 123 to - SESSION_SECRET=123 $convertedServiceVariables = collect([]); foreach ($serviceVariables as $variableName => $variable) { if (is_numeric($variableName)) { if (is_array($variable)) { $key = str(collect($variable)->keys()->first()); $value = str(collect($variable)->values()->first()); $variable = "$key=$value"; $convertedServiceVariables->put($variableName, $variable); } elseif (is_string($variable)) { $convertedServiceVariables->put($variableName, $variable); } } elseif (is_string($variableName)) { $convertedServiceVariables->put($variableName, $variable); } } $serviceVariables = $convertedServiceVariables; // Get variables from the service foreach ($serviceVariables as $variableName => $variable) { if (is_numeric($variableName)) { if (is_array($variable)) { // - SESSION_SECRET: 123 // - SESSION_SECRET: $key = str(collect($variable)->keys()->first()); $value = str(collect($variable)->values()->first()); } else { $variable = str($variable); if ($variable->contains('=')) { // - SESSION_SECRET=123 // - SESSION_SECRET= $key = $variable->before('='); $value = $variable->after('='); } else { // - SESSION_SECRET $key = $variable; $value = null; } } } else { // SESSION_SECRET: 123 // SESSION_SECRET: $key = str($variableName); $value = str($variable); } // Preserve original key for comment lookup before $key might be reassigned $originalKey = $key->value(); if ($key->startsWith('SERVICE_FQDN')) { if ($isNew || $savedService->fqdn === null) { $name = $key->after('SERVICE_FQDN_')->beforeLast('_')->lower(); $fqdn = generateFqdn($resource->server, "{$name->value()}-{$resource->uuid}"); if (substr_count($key->value(), '_') === 3) { // SERVICE_FQDN_UMAMI_1000 $port = $key->afterLast('_'); } else { $last = $key->afterLast('_'); if (is_numeric($last->value())) { // SERVICE_FQDN_3001 $port = $last; } else { // SERVICE_FQDN_UMAMI $port = null; } } if ($port) { $fqdn = "$fqdn:$port"; } if (substr_count($key->value(), '_') >= 2) { if ($value) { $path = $value->value(); } else { $path = null; } if ($generatedServiceFQDNS->count() > 0) { $alreadyGenerated = $generatedServiceFQDNS->has($key->value()); if ($alreadyGenerated) { $fqdn = $generatedServiceFQDNS->get($key->value()); } else { $generatedServiceFQDNS->put($key->value(), $fqdn); } } else { $generatedServiceFQDNS->put($key->value(), $fqdn); } $fqdn = "$fqdn$path"; } if (! $isDatabase) { if ($savedService->fqdn) { data_set($savedService, 'fqdn', $savedService->fqdn.','.$fqdn); } else { data_set($savedService, 'fqdn', $fqdn); } $savedService->save(); } EnvironmentVariable::create([ 'key' => $key, 'value' => $fqdn, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, 'comment' => $envComments[$originalKey] ?? null, ]); } // Caddy needs exact port in some cases. if ($predefinedPort && ! $key->endsWith("_{$predefinedPort}")) { $fqdns_exploded = str($savedService->fqdn)->explode(','); if ($fqdns_exploded->count() > 1) { continue; } $env = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ])->first(); if ($env) { $env_url = Url::fromString($savedService->fqdn); $env_port = $env_url->getPort(); if ($env_port !== $predefinedPort) { $env_url = $env_url->withPort($predefinedPort); $savedService->fqdn = $env_url->__toString(); $savedService->save(); } } } // data_forget($service, "environment.$variableName"); // $yaml = data_forget($yaml, "services.$serviceName.environment.$variableName"); // if (count(data_get($yaml, 'services.' . $serviceName . '.environment')) === 0) { // $yaml = data_forget($yaml, "services.$serviceName.environment"); // } continue; } if ($value?->startsWith('$')) { $foundEnv = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ])->first(); $value = replaceVariables($value); $key = $value; if ($value->startsWith('SERVICE_')) { $foundEnv = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ])->first(); ['command' => $command, 'forService' => $forService, 'generatedValue' => $generatedValue, 'port' => $port] = parseEnvVariable($value); if (! is_null($command)) { if ($command?->value() === 'FQDN' || $command?->value() === 'URL') { if (Str::lower($forService) === $serviceName) { $fqdn = generateFqdn($resource->server, $containerName); } else { $fqdn = generateFqdn($resource->server, Str::lower($forService).'-'.$resource->uuid); } if ($port) { $fqdn = "$fqdn:$port"; } if ($foundEnv) { $fqdn = data_get($foundEnv, 'value'); // if ($savedService->fqdn) { // $savedServiceFqdn = Url::fromString($savedService->fqdn); // $parsedFqdn = Url::fromString($fqdn); // $savedServicePath = $savedServiceFqdn->getPath(); // $parsedFqdnPath = $parsedFqdn->getPath(); // if ($savedServicePath != $parsedFqdnPath) { // $fqdn = $parsedFqdn->withPath($savedServicePath)->__toString(); // $foundEnv->value = $fqdn; // $foundEnv->save(); // } // } } else { if ($command->value() === 'URL') { $fqdn = str($fqdn)->after('://')->value(); } EnvironmentVariable::create([ 'key' => $key, 'value' => $fqdn, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, 'comment' => $envComments[$originalKey] ?? null, ]); } if (! $isDatabase) { if ($command->value() === 'FQDN' && is_null($savedService->fqdn) && ! $foundEnv) { $savedService->fqdn = $fqdn; $savedService->save(); } // Caddy needs exact port in some cases. if ($predefinedPort && ! $key->endsWith("_{$predefinedPort}") && $command?->value() === 'FQDN' && $resource->server->proxyType() === 'CADDY') { $fqdns_exploded = str($savedService->fqdn)->explode(','); if ($fqdns_exploded->count() > 1) { continue; } $env = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ])->first(); if ($env) { $env_url = Url::fromString($env->value); $env_port = $env_url->getPort(); if ($env_port !== $predefinedPort) { $env_url = $env_url->withPort($predefinedPort); $savedService->fqdn = $env_url->__toString(); $savedService->save(); } } } } } else { $generatedValue = generateEnvValue($command, $resource); if (! $foundEnv) { EnvironmentVariable::create([ 'key' => $key, 'value' => $generatedValue, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, 'comment' => $envComments[$originalKey] ?? null, ]); } } } } else { if ($value->contains(':-')) { $key = $value->before(':'); $defaultValue = $value->after(':-'); } elseif ($value->contains('-')) { $key = $value->before('-'); $defaultValue = $value->after('-'); } elseif ($value->contains(':?')) { $key = $value->before(':'); $defaultValue = $value->after(':?'); } elseif ($value->contains('?')) { $key = $value->before('?'); $defaultValue = $value->after('?'); } else { $key = $value; $defaultValue = null; } $foundEnv = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ])->first(); if ($foundEnv) { $defaultValue = data_get($foundEnv, 'value'); } EnvironmentVariable::updateOrCreate([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ], [ 'value' => $defaultValue, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, 'comment' => $envComments[$originalKey] ?? null, ]); } } } // Add labels to the service if ($savedService->serviceType()) { $fqdns = generateServiceSpecificFqdns($savedService); } else { $fqdns = collect(data_get($savedService, 'fqdns'))->filter(); } $defaultLabels = defaultLabels( id: $resource->id, name: $containerName, projectName: $resource->project()->name, resourceName: $resource->name, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id, subName: $savedService->name, environment: $resource->environment->name, ); $serviceLabels = $serviceLabels->merge($defaultLabels); if (! $isDatabase && $fqdns->count() > 0) { if ($fqdns) { $shouldGenerateLabelsExactly = $resource->server->settings->generate_exact_labels; if ($shouldGenerateLabelsExactly) { switch ($resource->server->proxyType()) { case ProxyTypes::TRAEFIK->value: $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled(), is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') )); break; case ProxyTypes::CADDY->value: $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled(), is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') )); break; } } else { $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled(), is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') )); $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled(), is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName, image: data_get($service, 'image') )); } } } if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) { data_set($service, 'logging', generate_fluentd_configuration()); } if ($serviceLabels->count() > 0) { if ($resource->is_container_label_escape_enabled) { $serviceLabels = $serviceLabels->map(function ($value, $key) { return escapeDollarSign($value); }); } } data_set($service, 'labels', $serviceLabels->toArray()); data_forget($service, 'is_database'); if (! data_get($service, 'restart')) { data_set($service, 'restart', RESTART_MODE); } if (data_get($service, 'restart') === 'no' || data_get($service, 'exclude_from_hc')) { $savedService->update(['exclude_from_status' => true]); } data_set($service, 'container_name', $containerName); data_forget($service, 'volumes.*.content'); data_forget($service, 'volumes.*.isDirectory'); data_forget($service, 'volumes.*.is_directory'); data_forget($service, 'exclude_from_hc'); data_set($service, 'environment', $serviceVariables->toArray()); updateCompose($savedService); return $service; }); $envs_from_coolify = $resource->environment_variables()->get(); $services = collect($services)->map(function ($service, $serviceName) use ($resource, $envs_from_coolify) { $serviceVariables = collect(data_get($service, 'environment', [])); $parsedServiceVariables = collect([]); foreach ($serviceVariables as $key => $value) { if (is_numeric($key)) { $value = str($value); if ($value->contains('=')) { $key = $value->before('=')->value(); $value = $value->after('=')->value(); } else { $key = $value->value(); $value = null; } $parsedServiceVariables->put($key, $value); } else { $parsedServiceVariables->put($key, $value); } } $parsedServiceVariables->put('COOLIFY_RESOURCE_UUID', "{$resource->uuid}"); $parsedServiceVariables->put('COOLIFY_CONTAINER_NAME', "$serviceName-{$resource->uuid}"); // TODO: move this in a shared function if (! $parsedServiceVariables->has('COOLIFY_APP_NAME')) { $parsedServiceVariables->put('COOLIFY_APP_NAME', "\"{$resource->name}\""); } if (! $parsedServiceVariables->has('COOLIFY_SERVER_IP')) { $parsedServiceVariables->put('COOLIFY_SERVER_IP', "\"{$resource->destination->server->ip}\""); } if (! $parsedServiceVariables->has('COOLIFY_ENVIRONMENT_NAME')) { $parsedServiceVariables->put('COOLIFY_ENVIRONMENT_NAME', "\"{$resource->environment->name}\""); } if (! $parsedServiceVariables->has('COOLIFY_PROJECT_NAME')) { $parsedServiceVariables->put('COOLIFY_PROJECT_NAME', "\"{$resource->project()->name}\""); } $parsedServiceVariables = $parsedServiceVariables->map(function ($value, $key) use ($envs_from_coolify) { if (! str($value)->startsWith('$')) { $found_env = $envs_from_coolify->where('key', $key)->first(); if ($found_env) { return $found_env->value; } } return $value; }); data_set($service, 'environment', $parsedServiceVariables->toArray()); return $service; }); $finalServices = [ 'services' => $services->toArray(), 'volumes' => $topLevelVolumes->toArray(), 'networks' => $topLevelNetworks->toArray(), 'configs' => $topLevelConfigs->toArray(), 'secrets' => $topLevelSecrets->toArray(), ]; $yaml = data_forget($yaml, 'services.*.volumes.*.content'); $resource->docker_compose_raw = Yaml::dump($yaml, 10, 2); $resource->docker_compose = Yaml::dump($finalServices, 10, 2); $resource->save(); $resource->saveComposeConfigs(); return collect($finalServices); } else { return collect([]); } } elseif ($resource->getMorphClass() === \App\Models\Application::class) { try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception) { return; } $server = $resource->destination->server; $topLevelVolumes = collect(data_get($yaml, 'volumes', [])); if ($pull_request_id !== 0) { $topLevelVolumes = collect([]); } if ($topLevelVolumes->count() > 0) { $tempTopLevelVolumes = collect([]); foreach ($topLevelVolumes as $volumeName => $volume) { if (is_null($volume)) { continue; } $tempTopLevelVolumes->put($volumeName, $volume); } $topLevelVolumes = collect($tempTopLevelVolumes); } $topLevelNetworks = collect(data_get($yaml, 'networks', [])); $topLevelConfigs = collect(data_get($yaml, 'configs', [])); $topLevelSecrets = collect(data_get($yaml, 'secrets', [])); $services = data_get($yaml, 'services'); $generatedServiceFQDNS = collect([]); if (is_null($resource->destination)) { $destination = $server->destinations()->first(); if ($destination) { $resource->destination()->associate($destination); $resource->save(); } } $definedNetwork = collect([$resource->uuid]); if ($pull_request_id !== 0) { $definedNetwork = collect(["{$resource->uuid}-$pull_request_id"]); } $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource, $server, $pull_request_id, $preview_id) { $serviceVolumes = collect(data_get($service, 'volumes', [])); $servicePorts = collect(data_get($service, 'ports', [])); $serviceNetworks = collect(data_get($service, 'networks', [])); $serviceVariables = collect(data_get($service, 'environment', [])); $serviceDependencies = collect(data_get($service, 'depends_on', [])); $serviceLabels = collect(data_get($service, 'labels', [])); $serviceBuildVariables = collect(data_get($service, 'build.args', [])); $serviceVariables = $serviceVariables->merge($serviceBuildVariables); if ($serviceLabels->count() > 0) { $removedLabels = collect([]); $serviceLabels = $serviceLabels->filter(function ($serviceLabel, $serviceLabelName) use ($removedLabels) { // Handle array values from YAML (e.g., "traefik.enable: true" becomes an array) if (is_array($serviceLabel)) { $removedLabels->put($serviceLabelName, $serviceLabel); return false; } if (! str($serviceLabel)->contains('=')) { $removedLabels->put($serviceLabelName, $serviceLabel); return false; } return $serviceLabel; }); foreach ($removedLabels as $removedLabelName => $removedLabel) { // Convert array values to strings if (is_array($removedLabel)) { $removedLabel = (string) collect($removedLabel)->first(); } $serviceLabels->push("$removedLabelName=$removedLabel"); } } $baseName = generateApplicationContainerName($resource, $pull_request_id); $containerName = "$serviceName-$baseName"; if ($resource->compose_parsing_version === '1') { if (count($serviceVolumes) > 0) { $serviceVolumes = $serviceVolumes->map(function ($volume) use ($resource, $topLevelVolumes, $pull_request_id) { if (is_string($volume)) { $volume = str($volume); if ($volume->contains(':') && ! $volume->startsWith('/')) { $name = $volume->before(':'); $mount = $volume->after(':'); if ($name->startsWith('.') || $name->startsWith('~')) { $dir = base_configuration_dir().'/applications/'.$resource->uuid; if ($name->startsWith('.')) { $name = $name->replaceFirst('.', $dir); } if ($name->startsWith('~')) { $name = $name->replaceFirst('~', $dir); } if ($pull_request_id !== 0) { $name = addPreviewDeploymentSuffix($name, $pull_request_id); } $volume = str("$name:$mount"); } else { if ($pull_request_id !== 0) { $name = addPreviewDeploymentSuffix($name, $pull_request_id); $volume = str("$name:$mount"); if ($topLevelVolumes->has($name)) { $v = $topLevelVolumes->get($name); if (data_get($v, 'driver_opts.type') === 'cifs') { // Do nothing } else { if (is_null(data_get($v, 'name'))) { data_set($v, 'name', $name); data_set($topLevelVolumes, $name, $v); } } } else { $topLevelVolumes->put($name, [ 'name' => $name, ]); } } else { if ($topLevelVolumes->has($name->value())) { $v = $topLevelVolumes->get($name->value()); if (data_get($v, 'driver_opts.type') === 'cifs') { // Do nothing } else { if (is_null(data_get($v, 'name'))) { data_set($topLevelVolumes, $name->value(), $v); } } } else { $topLevelVolumes->put($name->value(), [ 'name' => $name->value(), ]); } } } } else { if ($volume->startsWith('/')) { $name = $volume->before(':'); $mount = $volume->after(':'); if ($pull_request_id !== 0) { $name = addPreviewDeploymentSuffix($name, $pull_request_id); } $volume = str("$name:$mount"); } } } elseif (is_array($volume)) { $source = data_get($volume, 'source'); $target = data_get($volume, 'target'); $read_only = data_get($volume, 'read_only'); if ($source && $target) { if ((str($source)->startsWith('.') || str($source)->startsWith('~'))) { $dir = base_configuration_dir().'/applications/'.$resource->uuid; if (str($source, '.')) { $source = str($source)->replaceFirst('.', $dir); } if (str($source, '~')) { $source = str($source)->replaceFirst('~', $dir); } if ($pull_request_id !== 0) { $source = addPreviewDeploymentSuffix($source, $pull_request_id); } if ($read_only) { data_set($volume, 'source', $source.':'.$target.':ro'); } else { data_set($volume, 'source', $source.':'.$target); } } else { if ($pull_request_id !== 0) { $source = addPreviewDeploymentSuffix($source, $pull_request_id); } if ($read_only) { data_set($volume, 'source', $source.':'.$target.':ro'); } else { data_set($volume, 'source', $source.':'.$target); } if (! str($source)->startsWith('/')) { if ($topLevelVolumes->has($source)) { $v = $topLevelVolumes->get($source); if (data_get($v, 'driver_opts.type') === 'cifs') { // Do nothing } else { if (is_null(data_get($v, 'name'))) { data_set($v, 'name', $source); data_set($topLevelVolumes, $source, $v); } } } else { $topLevelVolumes->put($source, [ 'name' => $source, ]); } } } } } if (is_array($volume)) { return data_get($volume, 'source'); } return $volume->value(); }); data_set($service, 'volumes', $serviceVolumes->toArray()); } } elseif ($resource->compose_parsing_version === '2') { if (count($serviceVolumes) > 0) { $serviceVolumes = $serviceVolumes->map(function ($volume) use ($resource, $topLevelVolumes, $pull_request_id) { if (is_string($volume)) { $volume = str($volume); if ($volume->contains(':') && ! $volume->startsWith('/')) { $name = $volume->before(':'); $mount = $volume->after(':'); if ($name->startsWith('.') || $name->startsWith('~')) { $dir = base_configuration_dir().'/applications/'.$resource->uuid; if ($name->startsWith('.')) { $name = $name->replaceFirst('.', $dir); } if ($name->startsWith('~')) { $name = $name->replaceFirst('~', $dir); } if ($pull_request_id !== 0) { $name = addPreviewDeploymentSuffix($name, $pull_request_id); } $volume = str("$name:$mount"); } else { if ($pull_request_id !== 0) { $uuid = $resource->uuid; $name = $uuid.'-'.addPreviewDeploymentSuffix($name, $pull_request_id); $volume = str("$name:$mount"); if ($topLevelVolumes->has($name)) { $v = $topLevelVolumes->get($name); if (data_get($v, 'driver_opts.type') === 'cifs') { // Do nothing } else { if (is_null(data_get($v, 'name'))) { data_set($v, 'name', $name); data_set($topLevelVolumes, $name, $v); } } } else { $topLevelVolumes->put($name, [ 'name' => $name, ]); } } else { $uuid = $resource->uuid; $name = str($uuid."-$name"); $volume = str("$name:$mount"); if ($topLevelVolumes->has($name->value())) { $v = $topLevelVolumes->get($name->value()); if (data_get($v, 'driver_opts.type') === 'cifs') { // Do nothing } else { if (is_null(data_get($v, 'name'))) { data_set($topLevelVolumes, $name->value(), $v); } } } else { $topLevelVolumes->put($name->value(), [ 'name' => $name->value(), ]); } } } } else { if ($volume->startsWith('/')) { $name = $volume->before(':'); $mount = $volume->after(':'); if ($pull_request_id !== 0) { $name = addPreviewDeploymentSuffix($name, $pull_request_id); } $volume = str("$name:$mount"); } } } elseif (is_array($volume)) { $source = data_get($volume, 'source'); $target = data_get($volume, 'target'); $read_only = data_get($volume, 'read_only'); if ($source && $target) { $uuid = $resource->uuid; if ((str($source)->startsWith('.') || str($source)->startsWith('~') || str($source)->startsWith('/'))) { $dir = base_configuration_dir().'/applications/'.$resource->uuid; if (str($source, '.')) { $source = str($source)->replaceFirst('.', $dir); } if (str($source, '~')) { $source = str($source)->replaceFirst('~', $dir); } if ($read_only) { data_set($volume, 'source', $source.':'.$target.':ro'); } else { data_set($volume, 'source', $source.':'.$target); } } else { if ($pull_request_id === 0) { $source = $uuid."-$source"; } else { $source = $uuid.'-'.addPreviewDeploymentSuffix($source, $pull_request_id); } if ($read_only) { data_set($volume, 'source', $source.':'.$target.':ro'); } else { data_set($volume, 'source', $source.':'.$target); } if (! str($source)->startsWith('/')) { if ($topLevelVolumes->has($source)) { $v = $topLevelVolumes->get($source); if (data_get($v, 'driver_opts.type') === 'cifs') { // Do nothing } else { if (is_null(data_get($v, 'name'))) { data_set($v, 'name', $source); data_set($topLevelVolumes, $source, $v); } } } else { $topLevelVolumes->put($source, [ 'name' => $source, ]); } } } } } if (is_array($volume)) { return data_get($volume, 'source'); } dispatch(new ServerFilesFromServerJob($resource)); return $volume->value(); }); data_set($service, 'volumes', $serviceVolumes->toArray()); } } if ($pull_request_id !== 0 && count($serviceDependencies) > 0) { $serviceDependencies = $serviceDependencies->map(function ($dependency) use ($pull_request_id) { return addPreviewDeploymentSuffix($dependency, $pull_request_id); }); data_set($service, 'depends_on', $serviceDependencies->toArray()); } // Decide if the service is a database $image = data_get_str($service, 'image'); $isDatabase = isDatabaseImage($image, $service); data_set($service, 'is_database', $isDatabase); // Collect/create/update networks if ($serviceNetworks->count() > 0) { foreach ($serviceNetworks as $networkName => $networkDetails) { if ($networkName === 'default') { continue; } // ignore alias if ($networkDetails['aliases'] ?? false) { continue; } $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); if (! $networkExists) { if (is_string($networkDetails) || is_int($networkDetails)) { $topLevelNetworks->put($networkDetails, null); } } } } // Collect/create/update ports $collectedPorts = collect([]); if ($servicePorts->count() > 0) { foreach ($servicePorts as $sport) { if (is_string($sport) || is_numeric($sport)) { $collectedPorts->push($sport); } if (is_array($sport)) { $target = data_get($sport, 'target'); $published = data_get($sport, 'published'); $protocol = data_get($sport, 'protocol'); $collectedPorts->push("$target:$published/$protocol"); } } } $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { return $value == $definedNetwork; }); if (! $definedNetworkExists) { foreach ($definedNetwork as $network) { if ($pull_request_id !== 0) { $topLevelNetworks->put($network, [ 'name' => $network, 'external' => true, ]); } else { $topLevelNetworks->put($network, [ 'name' => $network, 'external' => true, ]); } } } $networks = collect(); foreach ($serviceNetworks as $key => $serviceNetwork) { if (gettype($serviceNetwork) === 'string') { // networks: // - appwrite $networks->put($serviceNetwork, null); } elseif (gettype($serviceNetwork) === 'array') { // networks: // default: // ipv4_address: 192.168.203.254 // $networks->put($serviceNetwork, null); $networks->put($key, $serviceNetwork); } } foreach ($definedNetwork as $key => $network) { $networks->put($network, null); } if (data_get($resource, 'settings.connect_to_docker_network')) { $network = $resource->destination->network; $networks->put($network, null); $topLevelNetworks->put($network, [ 'name' => $network, 'external' => true, ]); } data_set($service, 'networks', $networks->toArray()); // Get variables from the service foreach ($serviceVariables as $variableName => $variable) { if (is_numeric($variableName)) { if (is_array($variable)) { // - SESSION_SECRET: 123 // - SESSION_SECRET: $key = str(collect($variable)->keys()->first()); $value = str(collect($variable)->values()->first()); } else { $variable = str($variable); if ($variable->contains('=')) { // - SESSION_SECRET=123 // - SESSION_SECRET= $key = $variable->before('='); $value = $variable->after('='); } else { // - SESSION_SECRET $key = $variable; $value = null; } } } else { // SESSION_SECRET: 123 // SESSION_SECRET: $key = str($variableName); $value = str($variable); } if ($key->startsWith('SERVICE_FQDN')) { if ($isNew) { $name = $key->after('SERVICE_FQDN_')->beforeLast('_')->lower(); $fqdn = generateFqdn($server, "{$name->value()}-{$resource->uuid}"); if (substr_count($key->value(), '_') === 3) { // SERVICE_FQDN_UMAMI_1000 $port = $key->afterLast('_'); } else { // SERVICE_FQDN_UMAMI $port = null; } if ($port) { $fqdn = "$fqdn:$port"; } if (substr_count($key->value(), '_') >= 2) { if ($value) { $path = $value->value(); } else { $path = null; } if ($generatedServiceFQDNS->count() > 0) { $alreadyGenerated = $generatedServiceFQDNS->has($key->value()); if ($alreadyGenerated) { $fqdn = $generatedServiceFQDNS->get($key->value()); } else { $generatedServiceFQDNS->put($key->value(), $fqdn); } } else { $generatedServiceFQDNS->put($key->value(), $fqdn); } $fqdn = "$fqdn$path"; } } continue; } if ($value?->startsWith('$')) { $foundEnv = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, ])->first(); $value = replaceVariables($value); $key = $value; if ($value->startsWith('SERVICE_')) { $foundEnv = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, ])->first(); ['command' => $command, 'forService' => $forService, 'generatedValue' => $generatedValue, 'port' => $port] = parseEnvVariable($value); if (! is_null($command)) { if ($command?->value() === 'FQDN' || $command?->value() === 'URL') { if (Str::lower($forService) === $serviceName) { $fqdn = generateFqdn($server, $containerName); } else { $fqdn = generateFqdn($server, Str::lower($forService).'-'.$resource->uuid); } if ($port) { $fqdn = "$fqdn:$port"; } if ($foundEnv) { $fqdn = data_get($foundEnv, 'value'); } else { if ($command?->value() === 'URL') { $fqdn = str($fqdn)->after('://')->value(); } EnvironmentVariable::create([ 'key' => $key, 'value' => $fqdn, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, ]); } } else { $generatedValue = generateEnvValue($command); if (! $foundEnv) { EnvironmentVariable::create([ 'key' => $key, 'value' => $generatedValue, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, ]); } } } } else { if ($value->contains(':-')) { $key = $value->before(':'); $defaultValue = $value->after(':-'); } elseif ($value->contains('-')) { $key = $value->before('-'); $defaultValue = $value->after('-'); } elseif ($value->contains(':?')) { $key = $value->before(':'); $defaultValue = $value->after(':?'); } elseif ($value->contains('?')) { $key = $value->before('?'); $defaultValue = $value->after('?'); } else { $key = $value; $defaultValue = null; } $foundEnv = EnvironmentVariable::where([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, ])->first(); if ($foundEnv) { $defaultValue = data_get($foundEnv, 'value'); } if ($foundEnv) { $foundEnv->update([ 'key' => $key, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'value' => $defaultValue, ]); } else { EnvironmentVariable::create([ 'key' => $key, 'value' => $defaultValue, 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, 'is_preview' => false, ]); } } } } // Add labels to the service if ($resource->serviceType()) { $fqdns = generateServiceSpecificFqdns($resource); } else { $domains = collect(json_decode($resource->docker_compose_domains)) ?? []; if ($domains) { $fqdns = data_get($domains, "$serviceName.domain"); if ($fqdns) { $fqdns = str($fqdns)->explode(','); if ($pull_request_id !== 0) { $preview = $resource->previews()->find($preview_id); $docker_compose_domains = collect(json_decode(data_get($preview, 'docker_compose_domains'))); if ($docker_compose_domains->count() > 0) { $found_fqdn = data_get($docker_compose_domains, "$serviceName.domain"); if ($found_fqdn) { $fqdns = collect($found_fqdn); } else { $fqdns = collect([]); } } else { $fqdns = $fqdns->map(function ($fqdn) use ($pull_request_id, $resource) { $preview = ApplicationPreview::findPreviewByApplicationAndPullId($resource->id, $pull_request_id); $url = Url::fromString($fqdn); $template = $resource->preview_url_template; $host = $url->getHost(); $schema = $url->getScheme(); $random = new Cuid2; $preview_fqdn = str_replace('{{random}}', $random, $template); $preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn); $preview_fqdn = str_replace('{{pr_id}}', $pull_request_id, $preview_fqdn); $preview_fqdn = "$schema://$preview_fqdn"; $preview->fqdn = $preview_fqdn; $preview->save(); return $preview_fqdn; }); } } $shouldGenerateLabelsExactly = $server->settings->generate_exact_labels; if ($shouldGenerateLabelsExactly) { switch ($server->proxyType()) { case ProxyTypes::TRAEFIK->value: $serviceLabels = $serviceLabels->merge( fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, serviceLabels: $serviceLabels, generate_unique_uuid: $resource->build_pack === 'dockercompose', image: data_get($service, 'image'), is_force_https_enabled: $resource->isForceHttpsEnabled(), is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), ) ); break; case ProxyTypes::CADDY->value: $serviceLabels = $serviceLabels->merge( fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, serviceLabels: $serviceLabels, image: data_get($service, 'image'), is_force_https_enabled: $resource->isForceHttpsEnabled(), is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), ) ); break; } } else { $serviceLabels = $serviceLabels->merge( fqdnLabelsForTraefik( uuid: $resource->uuid, domains: $fqdns, serviceLabels: $serviceLabels, generate_unique_uuid: $resource->build_pack === 'dockercompose', image: data_get($service, 'image'), is_force_https_enabled: $resource->isForceHttpsEnabled(), is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), ) ); $serviceLabels = $serviceLabels->merge( fqdnLabelsForCaddy( network: $resource->destination->network, uuid: $resource->uuid, domains: $fqdns, serviceLabels: $serviceLabels, image: data_get($service, 'image'), is_force_https_enabled: $resource->isForceHttpsEnabled(), is_gzip_enabled: $resource->isGzipEnabled(), is_stripprefix_enabled: $resource->isStripprefixEnabled(), ) ); } } } } $defaultLabels = defaultLabels( id: $resource->id, name: $containerName, projectName: $resource->project()->name, resourceName: $resource->name, environment: $resource->environment->name, pull_request_id: $pull_request_id, type: 'application' ); $serviceLabels = $serviceLabels->merge($defaultLabels); if ($server->isLogDrainEnabled()) { if ($resource instanceof Application && $resource->isLogDrainEnabled()) { data_set($service, 'logging', generate_fluentd_configuration()); } } if ($serviceLabels->count() > 0) { if ($resource->settings->is_container_label_escape_enabled) { $serviceLabels = $serviceLabels->map(function ($value, $key) { return escapeDollarSign($value); }); } } data_set($service, 'labels', $serviceLabels->toArray()); data_forget($service, 'is_database'); if (! data_get($service, 'restart')) { data_set($service, 'restart', RESTART_MODE); } data_set($service, 'container_name', $containerName); data_forget($service, 'volumes.*.content'); data_forget($service, 'volumes.*.isDirectory'); data_forget($service, 'volumes.*.is_directory'); data_forget($service, 'exclude_from_hc'); data_set($service, 'environment', $serviceVariables->toArray()); return $service; }); if ($pull_request_id !== 0) { $services->each(function ($service, $serviceName) use ($pull_request_id, $services) { $services[addPreviewDeploymentSuffix($serviceName, $pull_request_id)] = $service; data_forget($services, $serviceName); }); } $finalServices = [ 'services' => $services->toArray(), 'volumes' => $topLevelVolumes->toArray(), 'networks' => $topLevelNetworks->toArray(), 'configs' => $topLevelConfigs->toArray(), 'secrets' => $topLevelSecrets->toArray(), ]; $resource->docker_compose_raw = Yaml::dump($yaml, 10, 2); $resource->docker_compose = Yaml::dump($finalServices, 10, 2); data_forget($resource, 'environment_variables'); data_forget($resource, 'environment_variables_preview'); $resource->save(); return collect($finalServices); } } function generate_fluentd_configuration(): array { return [ 'driver' => 'fluentd', 'options' => [ 'fluentd-address' => 'tcp://127.0.0.1:24224', 'fluentd-async' => 'true', 'fluentd-sub-second-precision' => 'true', // env vars are used in the LogDrain configurations 'env' => 'COOLIFY_APP_NAME,COOLIFY_PROJECT_NAME,COOLIFY_SERVER_IP,COOLIFY_ENVIRONMENT_NAME', ], ]; } function isAssociativeArray($array) { if ($array instanceof Collection) { $array = $array->toArray(); } if (! is_array($array)) { throw new \InvalidArgumentException('Input must be an array or a Collection.'); } if ($array === []) { return false; } return array_keys($array) !== range(0, count($array) - 1); } /** * This method adds the default environment variables to the resource. * - COOLIFY_APP_NAME * - COOLIFY_PROJECT_NAME * - COOLIFY_SERVER_IP * - COOLIFY_ENVIRONMENT_NAME * * Theses variables are added in place to the $where_to_add array. */ function add_coolify_default_environment_variables(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse|Application|Service $resource, Collection &$where_to_add, ?Collection $where_to_check = null) { // Currently disabled return; if ($resource instanceof Service) { $ip = $resource->server->ip; } else { $ip = $resource->destination->server->ip; } if (isAssociativeArray($where_to_add)) { $isAssociativeArray = true; } else { $isAssociativeArray = false; } if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_APP_NAME')->isEmpty()) { if ($isAssociativeArray) { $where_to_add->put('COOLIFY_APP_NAME', "\"{$resource->name}\""); } else { $where_to_add->push("COOLIFY_APP_NAME=\"{$resource->name}\""); } } if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_SERVER_IP')->isEmpty()) { if ($isAssociativeArray) { $where_to_add->put('COOLIFY_SERVER_IP', "\"{$ip}\""); } else { $where_to_add->push("COOLIFY_SERVER_IP=\"{$ip}\""); } } if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_ENVIRONMENT_NAME')->isEmpty()) { if ($isAssociativeArray) { $where_to_add->put('COOLIFY_ENVIRONMENT_NAME', "\"{$resource->environment->name}\""); } else { $where_to_add->push("COOLIFY_ENVIRONMENT_NAME=\"{$resource->environment->name}\""); } } if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_PROJECT_NAME')->isEmpty()) { if ($isAssociativeArray) { $where_to_add->put('COOLIFY_PROJECT_NAME', "\"{$resource->project()->name}\""); } else { $where_to_add->push("COOLIFY_PROJECT_NAME=\"{$resource->project()->name}\""); } } } function convertToKeyValueCollection($environment) { $convertedServiceVariables = collect([]); if (isAssociativeArray($environment)) { // Example: $environment = ['FOO' => 'bar', 'BAZ' => 'qux']; if ($environment instanceof Collection) { $changedEnvironment = collect([]); $environment->each(function ($value, $key) use ($changedEnvironment) { if (is_numeric($key)) { $parts = explode('=', $value, 2); if (count($parts) === 2) { $key = $parts[0]; $realValue = $parts[1] ?? ''; $changedEnvironment->put($key, $realValue); } else { $changedEnvironment->put($key, $value); } } else { $changedEnvironment->put($key, $value); } }); return $changedEnvironment; } $convertedServiceVariables = $environment; } else { // Example: $environment = ['FOO=bar', 'BAZ=qux']; foreach ($environment as $value) { if (is_string($value)) { $parts = explode('=', $value, 2); $key = $parts[0]; $realValue = $parts[1] ?? ''; if ($key) { $convertedServiceVariables->put($key, $realValue); } } } } return $convertedServiceVariables; } function instanceSettings() { return InstanceSettings::get(); } function wireNavigate(): string { try { $settings = instanceSettings(); // Return wire:navigate.hover for SPA navigation with prefetching, or empty string if disabled return ($settings->is_wire_navigate_enabled ?? true) ? 'wire:navigate.hover' : ''; } catch (\Exception $e) { return 'wire:navigate.hover'; } } /** * Redirect to a named route with SPA navigation support. * Automatically uses wire:navigate when is_wire_navigate_enabled is true. */ function redirectRoute(Livewire\Component $component, string $name, array $parameters = []): mixed { $navigate = true; try { $navigate = instanceSettings()->is_wire_navigate_enabled ?? true; } catch (\Exception $e) { $navigate = true; } return $component->redirectRoute($name, $parameters, navigate: $navigate); } function getHelperVersion(): string { $settings = instanceSettings(); // In development mode, use the dev_helper_version if set, otherwise fallback to config if (isDev() && ! empty($settings->dev_helper_version)) { return $settings->dev_helper_version; } return config('constants.coolify.helper_version'); } function loadConfigFromGit(string $repository, string $branch, string $base_directory, int $server_id, int $team_id) { $server = Server::find($server_id)->where('team_id', $team_id)->first(); if (! $server) { return; } $uuid = new Cuid2; $cloneCommand = "git clone --no-checkout -b $branch $repository ."; $workdir = rtrim($base_directory, '/'); $fileList = collect([".$workdir/coolify.json"]); $commands = collect([ "rm -rf /tmp/{$uuid}", "mkdir -p /tmp/{$uuid}", "cd /tmp/{$uuid}", $cloneCommand, 'git sparse-checkout init --cone', "git sparse-checkout set {$fileList->implode(' ')}", 'git read-tree -mu HEAD', "cat .$workdir/coolify.json", 'rm -rf /tmp/{$uuid}', ]); try { return instant_remote_process($commands, $server); } catch (\Exception) { // continue } } function loggy($message = null, array $context = []) { if (! isDev()) { return; } if (function_exists('ray') && config('app.debug')) { ray($message, $context); } if (is_null($message)) { return app('log'); } return app('log')->debug($message, $context); } function sslipDomainWarning(string $domains) { $domains = str($domains)->trim()->explode(','); $showSslipHttpsWarning = false; $domains->each(function ($domain) use (&$showSslipHttpsWarning) { if (str($domain)->contains('https') && str($domain)->contains('sslip')) { $showSslipHttpsWarning = true; } }); return $showSslipHttpsWarning; } function isEmailRateLimited(string $limiterKey, int $decaySeconds = 3600, ?callable $callbackOnSuccess = null): bool { if (isDev()) { $decaySeconds = 120; } $rateLimited = false; $executed = RateLimiter::attempt( $limiterKey, $maxAttempts = 0, function () use (&$rateLimited, &$limiterKey, $callbackOnSuccess) { isDev() && loggy('Rate limit not reached for '.$limiterKey); $rateLimited = false; if ($callbackOnSuccess) { $callbackOnSuccess(); } }, $decaySeconds, ); if (! $executed) { isDev() && loggy('Rate limit reached for '.$limiterKey.'. Rate limiter will be disabled for '.$decaySeconds.' seconds.'); $rateLimited = true; } return $rateLimited; } function defaultNginxConfiguration(string $type = 'static'): string { if ($type === 'spa') { return <<<'NGINX' server { location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } # Handle 404 errors error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; internal; } # Handle server errors (50x) error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; internal; } } NGINX; } else { return <<<'NGINX' server { location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri.html $uri/index.html $uri/index.htm $uri/ =404; } # Handle 404 errors error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; internal; } # Handle server errors (50x) error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; internal; } } NGINX; } } function convertGitUrl(string $gitRepository, string $deploymentType, GithubApp|GitlabApp|null $source = null): array { $repository = $gitRepository; $providerInfo = [ 'host' => null, 'user' => 'git', 'port' => 22, 'repository' => $gitRepository, ]; $sshMatches = []; $matches = []; // Let's try and parse the string to detect if it's a valid SSH string or not preg_match('/((.*?)\:\/\/)?(.*@.*:.*)/', $gitRepository, $sshMatches); if ($deploymentType === 'deploy_key' && empty($sshMatches) && $source) { // If this happens, the user may have provided an HTTP URL when they needed an SSH one // Let's try and fix that for known Git providers switch ($source->getMorphClass()) { case \App\Models\GithubApp::class: case \App\Models\GitlabApp::class: $providerInfo['host'] = Url::fromString($source->html_url)->getHost(); $providerInfo['port'] = $source->custom_port; $providerInfo['user'] = $source->custom_user; break; } if (! empty($providerInfo['host'])) { // Until we do not support more providers with App (like GithubApp), this will be always true, port will be 22 if ($providerInfo['port'] === 22) { $repository = "{$providerInfo['user']}@{$providerInfo['host']}:{$providerInfo['repository']}"; } else { $repository = "ssh://{$providerInfo['user']}@{$providerInfo['host']}:{$providerInfo['port']}/{$providerInfo['repository']}"; } } } preg_match('/(?<=:)\d+(?=\/)/', $gitRepository, $matches); if (count($matches) === 1) { $providerInfo['port'] = $matches[0]; $gitHost = str($gitRepository)->before(':'); $gitRepo = str($gitRepository)->after('/'); $repository = "$gitHost:$gitRepo"; } return [ 'repository' => $repository, 'port' => $providerInfo['port'], ]; } function getJobStatus(?string $jobId = null) { if (blank($jobId)) { return 'unknown'; } $jobFound = app(JobRepository::class)->getJobs([$jobId]); if ($jobFound->isEmpty()) { return 'unknown'; } return $jobFound->first()->status; } function parseDockerfileInterval(string $something) { $value = preg_replace('/[^0-9]/', '', $something); $unit = preg_replace('/[0-9]/', '', $something); // Default to seconds if no unit specified $unit = $unit ?: 's'; // Convert to seconds based on unit $seconds = (int) $value; switch ($unit) { case 'ns': $seconds = (int) ($value / 1000000000); break; case 'us': case 'µs': $seconds = (int) ($value / 1000000); break; case 'ms': $seconds = (int) ($value / 1000); break; case 'm': $seconds = (int) ($value * 60); break; case 'h': $seconds = (int) ($value * 3600); break; } return $seconds; } function addPreviewDeploymentSuffix(string $name, int $pull_request_id = 0): string { return ($pull_request_id === 0) ? $name : $name.'-pr-'.$pull_request_id; } function generateDockerComposeServiceName(mixed $services, int $pullRequestId = 0): Collection { $collection = collect([]); foreach ($services as $serviceName => $_) { $collection->put('SERVICE_NAME_'.str($serviceName)->replace('-', '_')->replace('.', '_')->upper(), addPreviewDeploymentSuffix($serviceName, $pullRequestId)); } return $collection; } function formatBytes(?int $bytes, int $precision = 2): string { if ($bytes === null || $bytes === 0) { return '0 B'; } // Handle negative numbers if ($bytes < 0) { return '0 B'; } $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; $base = 1024; $exponent = floor(log($bytes) / log($base)); $exponent = min($exponent, count($units) - 1); $value = $bytes / pow($base, $exponent); return round($value, $precision).' '.$units[$exponent]; } /** * Validates that a file path is safely within the /tmp/ directory. * Protects against path traversal attacks by resolving the real path * and verifying it stays within /tmp/. * * Note: On macOS, /tmp is often a symlink to /private/tmp, which is handled. */ function isSafeTmpPath(?string $path): bool { if (blank($path)) { return false; } // URL decode to catch encoded traversal attempts $decodedPath = urldecode($path); // Minimum length check - /tmp/x is 6 chars if (strlen($decodedPath) < 6) { return false; } // Must start with /tmp/ if (! str($decodedPath)->startsWith('/tmp/')) { return false; } // Quick check for obvious traversal attempts if (str($decodedPath)->contains('..')) { return false; } // Check for null bytes (directory traversal technique) if (str($decodedPath)->contains("\0")) { return false; } // Remove any trailing slashes for consistent validation $normalizedPath = rtrim($decodedPath, '/'); // Normalize the path by removing redundant separators and resolving . and .. // We'll do this manually since realpath() requires the path to exist $parts = explode('/', $normalizedPath); $resolvedParts = []; foreach ($parts as $part) { if ($part === '' || $part === '.') { // Skip empty parts (from //) and current directory references continue; } elseif ($part === '..') { // Parent directory - this should have been caught earlier but double-check return false; } else { $resolvedParts[] = $part; } } $resolvedPath = '/'.implode('/', $resolvedParts); // Final check: resolved path must start with /tmp/ // And must have at least one component after /tmp/ if (! str($resolvedPath)->startsWith('/tmp/') || $resolvedPath === '/tmp') { return false; } // Resolve the canonical /tmp path (handles symlinks like /tmp -> /private/tmp on macOS) $canonicalTmpPath = realpath('/tmp'); if ($canonicalTmpPath === false) { // If /tmp doesn't exist, something is very wrong, but allow non-existing paths $canonicalTmpPath = '/tmp'; } // Calculate dirname once to avoid redundant calls $dirPath = dirname($resolvedPath); // If the directory exists, resolve it via realpath to catch symlink attacks if (is_dir($dirPath)) { // For existing paths, resolve to absolute path to catch symlinks $realDir = realpath($dirPath); if ($realDir === false) { return false; } // Check if the real directory is within /tmp (or its canonical path) if (! str($realDir)->startsWith('/tmp') && ! str($realDir)->startsWith($canonicalTmpPath)) { return false; } } return true; } /** * Transform colon-delimited status format to human-readable parentheses format. * * Handles Docker container status formats with optional health check status and exclusion modifiers. * * Examples: * - running:healthy → Running (healthy) * - running:unhealthy:excluded → Running (unhealthy, excluded) * - exited:excluded → Exited (excluded) * - Proxy:running → Proxy:running (preserved as-is for headline formatting) * - running → Running * * @param string $status The status string to format * @return string The formatted status string */ function formatContainerStatus(string $status): string { // Preserve Proxy statuses as-is (they follow different format) if (str($status)->startsWith('Proxy')) { return str($status)->headline()->value(); } // Check for :excluded suffix $isExcluded = str($status)->endsWith(':excluded'); $parts = explode(':', $status); if ($isExcluded) { if (count($parts) === 3) { // Has health status: running:unhealthy:excluded → Running (unhealthy, excluded) return str($parts[0])->headline().' ('.$parts[1].', excluded)'; } else { // No health status: exited:excluded → Exited (excluded) return str($parts[0])->headline().' (excluded)'; } } elseif (count($parts) >= 2) { // Regular colon format: running:healthy → Running (healthy) return str($parts[0])->headline().' ('.$parts[1].')'; } else { // Simple status: running → Running return str($status)->headline()->value(); } } /** * Check if password confirmation should be skipped. * Returns true if: * - Two-step confirmation is globally disabled * - User has no password (OAuth users) * * Used by modal-confirmation.blade.php to determine if password step should be shown. * * @return bool True if password confirmation should be skipped */ function shouldSkipPasswordConfirmation(): bool { // Skip if two-step confirmation is globally disabled if (data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) { return true; } // Skip if user has no password (OAuth users) if (! Auth::user()?->hasPassword()) { return true; } return false; } /** * Verify password for two-step confirmation. * Skips verification if: * - Two-step confirmation is globally disabled * - User has no password (OAuth users) * * @param mixed $password The password to verify (may be array if skipped by frontend) * @param \Livewire\Component|null $component Optional Livewire component to add errors to * @return bool True if verification passed (or skipped), false if password is incorrect */ function verifyPasswordConfirmation(mixed $password, ?Livewire\Component $component = null): bool { // Skip if password confirmation should be skipped if (shouldSkipPasswordConfirmation()) { return true; } // Verify the password if (! Hash::check($password, Auth::user()->password)) { if ($component) { $component->addError('password', 'The provided password is incorrect.'); } return false; } return true; } /** * Extract hard-coded environment variables from docker-compose YAML. * * @param string $dockerComposeRaw Raw YAML content * @return \Illuminate\Support\Collection Collection of arrays with: key, value, comment, service_name */ function extractHardcodedEnvironmentVariables(string $dockerComposeRaw): \Illuminate\Support\Collection { if (blank($dockerComposeRaw)) { return collect([]); } try { $yaml = \Symfony\Component\Yaml\Yaml::parse($dockerComposeRaw); } catch (\Exception $e) { // Malformed YAML - return empty collection return collect([]); } $services = data_get($yaml, 'services', []); if (empty($services)) { return collect([]); } // Extract inline comments from raw YAML $envComments = extractYamlEnvironmentComments($dockerComposeRaw); $hardcodedVars = collect([]); foreach ($services as $serviceName => $service) { $environment = collect(data_get($service, 'environment', [])); if ($environment->isEmpty()) { continue; } // Convert environment variables to key-value format $environment = convertToKeyValueCollection($environment); foreach ($environment as $key => $value) { $hardcodedVars->push([ 'key' => $key, 'value' => $value, 'comment' => $envComments[$key] ?? null, 'service_name' => $serviceName, ]); } } return $hardcodedVars; } /** * Downsample metrics using the Largest-Triangle-Three-Buckets (LTTB) algorithm. * This preserves the visual shape of the data better than simple averaging. * * @param array $data Array of [timestamp, value] pairs * @param int $threshold Target number of points * @return array Downsampled data */ function downsampleLTTB(array $data, int $threshold): array { $dataLength = count($data); // Return unchanged if threshold >= data length, or if threshold <= 2 // (threshold <= 2 would cause division by zero in bucket calculation) if ($threshold >= $dataLength || $threshold <= 2) { return $data; } $sampled = []; $sampled[] = $data[0]; // Always keep first point $bucketSize = ($dataLength - 2) / ($threshold - 2); $a = 0; // Index of previous selected point for ($i = 0; $i < $threshold - 2; $i++) { // Calculate bucket range $bucketStart = (int) floor(($i + 1) * $bucketSize) + 1; $bucketEnd = (int) floor(($i + 2) * $bucketSize) + 1; $bucketEnd = min($bucketEnd, $dataLength - 1); // Calculate average point for next bucket (used as reference) $nextBucketStart = (int) floor(($i + 2) * $bucketSize) + 1; $nextBucketEnd = (int) floor(($i + 3) * $bucketSize) + 1; $nextBucketEnd = min($nextBucketEnd, $dataLength - 1); $avgX = 0; $avgY = 0; $nextBucketCount = $nextBucketEnd - $nextBucketStart + 1; if ($nextBucketCount > 0) { for ($j = $nextBucketStart; $j <= $nextBucketEnd; $j++) { $avgX += $data[$j][0]; $avgY += $data[$j][1]; } $avgX /= $nextBucketCount; $avgY /= $nextBucketCount; } // Find point in current bucket with largest triangle area $maxArea = -1; $maxAreaIndex = $bucketStart; $pointAX = $data[$a][0]; $pointAY = $data[$a][1]; for ($j = $bucketStart; $j <= $bucketEnd; $j++) { // Triangle area calculation $area = abs( ($pointAX - $avgX) * ($data[$j][1] - $pointAY) - ($pointAX - $data[$j][0]) * ($avgY - $pointAY) ) * 0.5; if ($area > $maxArea) { $maxArea = $area; $maxAreaIndex = $j; } } $sampled[] = $data[$maxAreaIndex]; $a = $maxAreaIndex; } $sampled[] = $data[$dataLength - 1]; // Always keep last point return $sampled; } /** * Resolve shared environment variable patterns like {{environment.VAR}}, {{project.VAR}}, {{team.VAR}}. * * This is the canonical implementation used by both EnvironmentVariable::realValue and the compose parsers * to ensure shared variable references are replaced with their actual values. */ function resolveSharedEnvironmentVariables(?string $value, $resource): ?string { if (is_null($value) || $value === '' || is_null($resource)) { return $value; } $value = trim($value); $sharedEnvsFound = str($value)->matchAll('/{{(.*?)}}/'); if ($sharedEnvsFound->isEmpty()) { return $value; } foreach ($sharedEnvsFound as $sharedEnv) { $type = str($sharedEnv)->trim()->match('/(.*?)\./'); if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) { continue; } $variable = str($sharedEnv)->trim()->match('/\.(.*)/'); $id = null; if ($type->value() === 'environment') { $id = $resource->environment->id; } elseif ($type->value() === 'project') { $id = $resource->environment->project->id; } elseif ($type->value() === 'team') { $id = $resource->team()->id; } if (is_null($id)) { continue; } $found = \App\Models\SharedEnvironmentVariable::where('type', $type) ->where('key', $variable) ->where('team_id', $resource->team()->id) ->where("{$type}_id", $id) ->first(); if ($found) { $value = str($value)->replace("{{{$sharedEnv}}}", $found->value); } } return str($value)->value(); } ================================================ FILE: bootstrap/helpers/socialite.php ================================================ redirect_uri)) { $oauth_setting->update(['redirect_uri' => route('auth.callback', $provider)]); } if ($provider === 'azure') { $azure_config = new \SocialiteProviders\Manager\Config( $oauth_setting->client_id, $oauth_setting->client_secret, $oauth_setting->redirect_uri, ['tenant' => $oauth_setting->tenant], ); return Socialite::driver('azure')->setConfig($azure_config); } if ($provider == 'authentik' || $provider == 'clerk') { $authentik_clerk_config = new \SocialiteProviders\Manager\Config( $oauth_setting->client_id, $oauth_setting->client_secret, $oauth_setting->redirect_uri, ['base_url' => $oauth_setting->base_url], ); return Socialite::driver($provider)->setConfig($authentik_clerk_config); } if ($provider == 'zitadel') { $zitadel_config = new \SocialiteProviders\Manager\Config( $oauth_setting->client_id, $oauth_setting->client_secret, $oauth_setting->redirect_uri, ['base_url' => $oauth_setting->base_url], ); return Socialite::driver('zitadel')->setConfig($zitadel_config); } if ($provider == 'google') { $google_config = new \SocialiteProviders\Manager\Config( $oauth_setting->client_id, $oauth_setting->client_secret, $oauth_setting->redirect_uri ); return Socialite::driver('google') ->setConfig($google_config) ->with(['hd' => $oauth_setting->tenant]); } $config = [ 'client_id' => $oauth_setting->client_id, 'client_secret' => $oauth_setting->client_secret, 'redirect' => $oauth_setting->redirect_uri, ]; $provider_class_map = [ 'bitbucket' => \Laravel\Socialite\Two\BitbucketProvider::class, 'discord' => \SocialiteProviders\Discord\Provider::class, 'github' => \Laravel\Socialite\Two\GithubProvider::class, 'gitlab' => \Laravel\Socialite\Two\GitlabProvider::class, 'infomaniak' => \SocialiteProviders\Infomaniak\Provider::class, ]; $socialite = Socialite::buildProvider( $provider_class_map[$provider], $config ); if ($provider == 'gitlab' && ! empty($oauth_setting->base_url)) { $socialite->setHost($oauth_setting->base_url); } return $socialite; } ================================================ FILE: bootstrap/helpers/subscriptions.php ================================================ id === 0) { return true; } $subscription = $team?->subscription; if (is_null($subscription)) { return false; } if (isStripe()) { return $subscription->stripe_invoice_paid === true; } return false; }); } function isSubscriptionOnGracePeriod() { return once(function () { $team = currentTeam(); if (! $team) { return false; } $subscription = $team?->subscription; if (! $subscription) { return false; } if (isStripe()) { return $subscription->stripe_cancel_at_period_end; } return false; }); } function subscriptionProvider() { return config('subscription.provider'); } function isStripe() { return config('subscription.provider') === 'stripe'; } function getStripeCustomerPortalSession(Team $team) { Stripe::setApiKey(config('subscription.stripe_api_key')); $return_url = route('subscription.show'); $stripe_customer_id = data_get($team, 'subscription.stripe_customer_id'); if (! $stripe_customer_id) { return null; } return \Stripe\BillingPortal\Session::create([ 'customer' => $stripe_customer_id, 'return_url' => $return_url, ]); } function allowedPathsForUnsubscribedAccounts() { return [ 'subscription/new', 'login', 'logout', 'force-password-reset', 'two-factor-challenge', 'livewire/update', 'admin', ]; } function allowedPathsForBoardingAccounts() { return [ ...allowedPathsForUnsubscribedAccounts(), 'onboarding', 'livewire/update', ]; } function allowedPathsForInvalidAccounts() { return [ 'logout', 'verify', 'force-password-reset', 'two-factor-challenge', 'livewire/update', ]; } function updateStripeCustomerEmail(Team $team, string $newEmail): void { if (! isStripe()) { return; } $stripe_customer_id = data_get($team, 'subscription.stripe_customer_id'); if (! $stripe_customer_id) { return; } Stripe::setApiKey(config('subscription.stripe_api_key')); \Stripe\Customer::update( $stripe_customer_id, ['email' => $newEmail] ); } ================================================ FILE: bootstrap/helpers/sudo.php ================================================ map(function ($line) { $trimmedLine = trim($line); // All bash keywords that should not receive sudo prefix // Using word boundary matching to avoid prefix collisions (e.g., 'do' vs 'docker', 'if' vs 'ifconfig', 'fi' vs 'find') $bashKeywords = [ 'cd', 'command', 'declare', 'echo', 'export', 'local', 'readonly', 'return', 'true', 'if', 'fi', 'for', 'done', 'while', 'until', 'case', 'esac', 'select', 'then', 'else', 'elif', 'break', 'continue', 'do', ]; // Special case: comments (no collision risk with '#') if (str_starts_with($trimmedLine, '#')) { return $line; } // Check all keywords with word boundary matching // Match keyword followed by space, semicolon, or end of line foreach ($bashKeywords as $keyword) { if (preg_match('/^'.preg_quote($keyword, '/').'(\s|;|$)/', $trimmedLine)) { // Special handling for 'if' - insert sudo after 'if ' if ($keyword === 'if') { return preg_replace('/^(\s*)if\s+/', '$1if sudo ', $line); } return $line; } } return "sudo $line"; }); $commands = $commands->map(function ($line) use ($server) { if (Str::startsWith($line, 'sudo mkdir -p')) { $path = trim(Str::after($line, 'sudo mkdir -p')); if (shouldChangeOwnership($path)) { return "$line && sudo chown -R $server->user:$server->user $path && sudo chmod -R o-rwx $path"; } return $line; } return $line; }); $commands = $commands->map(function ($line) { $line = str($line); // Detect complex piped commands that should be wrapped in bash -c $isComplexPipeCommand = ( $line->contains(' | sh') || $line->contains(' | bash') || ($line->contains(' | ') && ($line->contains('||') || $line->contains('&&'))) ); // If it's a complex pipe command and starts with sudo, wrap it in bash -c if ($isComplexPipeCommand && $line->startsWith('sudo ')) { $commandWithoutSudo = $line->after('sudo ')->value(); // Escape single quotes for bash -c by replacing ' with '\'' $escapedCommand = str_replace("'", "'\\''", $commandWithoutSudo); return "sudo bash -c '$escapedCommand'"; } // For non-complex commands, apply the original logic if (str($line)->contains('$(')) { $line = $line->replace('$(', '$(sudo '); } if (! $isComplexPipeCommand && str($line)->contains('||')) { $line = $line->replace('||', '|| sudo'); } if (! $isComplexPipeCommand && str($line)->contains('&&')) { $line = $line->replace('&&', '&& sudo'); } // Don't insert sudo into pipes for complex commands if (! $isComplexPipeCommand && str($line)->contains(' | ')) { $line = $line->replace(' | ', ' | sudo '); } return $line->value(); }); return $commands->toArray(); } function parseLineForSudo(string $command, Server $server): string { if (! str($command)->startSwith('cd') && ! str($command)->startSwith('command')) { $command = "sudo $command"; } if (Str::startsWith($command, 'sudo mkdir -p')) { $path = trim(Str::after($command, 'sudo mkdir -p')); if (shouldChangeOwnership($path)) { $command = "$command && sudo chown -R $server->user:$server->user $path && sudo chmod -R o-rwx $path"; } } if (str($command)->contains('$(') || str($command)->contains('`')) { $command = str($command)->replace('$(', '$(sudo ')->replace('`', '`sudo ')->value(); } if (str($command)->contains('||')) { $command = str($command)->replace('||', '|| sudo ')->value(); } if (str($command)->contains('&&')) { $command = str($command)->replace('&&', '&& sudo ')->value(); } return $command; } ================================================ FILE: bootstrap/helpers/timezone.php ================================================ setTimezone(new \DateTimeZone($serverTimezone)); } catch (\Exception) { $dateObj->setTimezone(new \DateTimeZone('UTC')); } return $dateObj->format('Y-m-d H:i:s T'); } function calculateDuration($startDate, $endDate = null) { if (! $endDate) { return null; } $start = new \DateTime($startDate); $end = new \DateTime($endDate); $interval = $start->diff($end); if ($interval->days > 0) { return $interval->format('%dd %Hh %Im %Ss'); } elseif ($interval->h > 0) { return $interval->format('%Hh %Im %Ss'); } else { return $interval->format('%Im %Ss'); } } ================================================ FILE: bootstrap/helpers/versions.php ================================================ '3.5.6']) */ function get_traefik_versions(): ?array { $versions = get_versions_data(); if (! $versions) { return null; } $traefikVersions = data_get($versions, 'traefik'); return is_array($traefikVersions) ? $traefikVersions : null; } /** * Invalidate the versions cache. * Call this after updating versions.json to ensure fresh data is loaded. */ function invalidate_versions_cache(): void { Cache::forget('coolify:versions:all'); } ================================================ FILE: bootstrap/includeHelpers.php ================================================ """ # remove the leading and trailing s trim = true # postprocessors postprocessors = [ # { pattern = '', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL ] # render body even when there are no releases to process # render_always = true # output file path # output = "test.md" [git] # parse the commits based on https://www.conventionalcommits.org conventional_commits = true # filter out the commits that are not conventional filter_unconventional = true # process each line of a commit as an individual commit split_commits = false # regex for preprocessing the commit messages commit_preprocessors = [ # Replace issue numbers #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, # Check spelling of the commit with https://github.com/crate-ci/typos # If the spelling is incorrect, it will be automatically fixed. #{ pattern = '.*', replace_command = 'typos --write-changes -' }, ] # regex for parsing and grouping commits commit_parsers = [ { message = "^feat", group = "🚀 Features" }, { message = "^fix", group = "🐛 Bug Fixes" }, { message = "^doc", group = "📚 Documentation" }, { message = "^perf", group = "⚡ Performance" }, { message = "^refactor", group = "🚜 Refactor" }, { message = "^style", group = "🎨 Styling" }, { message = "^test", group = "🧪 Testing" }, { message = "^chore\\(release\\): prepare for", skip = true }, { message = "^chore\\(deps.*\\)", skip = true }, { message = "^chore\\(pr\\)", skip = true }, { message = "^chore\\(pull\\)", skip = true }, { message = "^chore|^ci", group = "⚙️ Miscellaneous Tasks" }, { body = ".*security", group = "🛡️ Security" }, { message = "^revert", group = "◀️ Revert" }, { message = ".*", group = "💼 Other" }, ] # filter out the commits that are not matched by commit parsers filter_commits = false # sort the tags topologically topo_order = false # sort the commits inside sections by oldest/newest order sort_commits = "oldest" ================================================ FILE: composer.json ================================================ { "name": "coollabsio/coolify", "description": "The Coolify project.", "license": "Apache-2.0", "type": "project", "keywords": [ "coolify", "deployment", "docker", "self-hosted", "server" ], "require": { "php": "^8.4", "danharrin/livewire-rate-limiting": "^2.1.0", "doctrine/dbal": "^4.4.1", "guzzlehttp/guzzle": "^7.10.0", "laravel/fortify": "^1.34.0", "laravel/framework": "^12.49.0", "laravel/horizon": "^5.43.0", "laravel/pail": "^1.2.4", "laravel/prompts": "^0.3.11|^0.3.11|^0.3.11", "laravel/sanctum": "^4.3.0", "laravel/socialite": "^5.24.2", "laravel/tinker": "^2.11.0", "laravel/ui": "^4.6.1", "lcobucci/jwt": "^5.6.0", "league/flysystem-aws-s3-v3": "^3.31.0", "league/flysystem-sftp-v3": "^3.31", "livewire/livewire": "^3.7.8", "log1x/laravel-webfonts": "^2.0.1", "lorisleiva/laravel-actions": "^2.9.1", "nubs/random-name-generator": "^2.2", "phpseclib/phpseclib": "^3.0.49", "pion/laravel-chunk-upload": "^1.5.6", "poliander/cron": "^3.3.0", "purplepixie/phpdns": "^2.3.6", "pusher/pusher-php-server": "^7.2.7", "resend/resend-laravel": "^0.20.0", "sentry/sentry-laravel": "^4.20.1", "socialiteproviders/authentik": "^5.2", "socialiteproviders/clerk": "^5.1", "socialiteproviders/discord": "^4.2", "socialiteproviders/google": "^4.1", "socialiteproviders/infomaniak": "^4.0", "socialiteproviders/microsoft-azure": "^5.2", "socialiteproviders/zitadel": "^4.2", "spatie/laravel-activitylog": "^4.11.0", "spatie/laravel-data": "^4.19.1", "spatie/laravel-markdown": "^2.7.1", "spatie/laravel-ray": "^1.43.5", "spatie/laravel-schemaless-attributes": "^2.5.1", "spatie/url": "^2.4", "stevebauman/purify": "^6.3.1", "stripe/stripe-php": "^16.6.0", "symfony/yaml": "^7.4.1", "visus/cuid2": "^6.0.0", "yosymfony/toml": "^1.0.4", "zircote/swagger-php": "^5.8.0" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.16.5", "driftingly/rector-laravel": "^2.1.9", "fakerphp/faker": "^1.24.1", "laravel/boost": "^2.1", "laravel/dusk": "^8.3.4", "laravel/pint": "^1.27", "laravel/telescope": "^5.16.1", "mockery/mockery": "^1.6.12", "nunomaduro/collision": "^8.8.3", "pestphp/pest": "^4.3.2", "pestphp/pest-plugin-browser": "^4.2", "phpstan/phpstan": "^2.1.38", "rector/rector": "^2.3.5", "serversideup/spin": "^3.1.1", "spatie/laravel-ignition": "^2.10.0", "symfony/http-client": "^7.4.5" }, "minimum-stability": "stable", "prefer-stable": true, "autoload": { "psr-4": { "App\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" }, "files": [ "bootstrap/includeHelpers.php" ] }, "autoload-dev": { "psr-4": { "Tests\\": "tests/" } }, "config": { "allow-plugins": { "pestphp/pest-plugin": true, "php-http/discovery": true }, "optimize-autoloader": true, "preferred-install": "dist", "sort-packages": true }, "extra": { "laravel": { "dont-discover": [ "laravel/telescope" ] } }, "scripts": { "post-update-cmd": [ "@php artisan vendor:publish --tag=laravel-assets --ansi --force", "Illuminate\\Foundation\\ComposerScripts::postUpdate" ], "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "@php artisan package:discover --ansi" ], "post-root-package-install": [ "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" ], "post-create-project-cmd": [ "@php artisan key:generate --ansi" ] } } ================================================ FILE: conductor.json ================================================ { "scripts": { "setup": "./scripts/conductor-setup.sh", "run": "docker rm -f coolify coolify-minio-init coolify-realtime coolify-minio coolify-testing-host coolify-redis coolify-db coolify-mail coolify-vite; spin up; spin down" }, "runScriptMode": "nonconcurrent" } ================================================ FILE: config/api.php ================================================ env('API_RATE_LIMIT', 200), ]; ================================================ FILE: config/app.php ================================================ env('APP_ID'), 'port' => env('APP_PORT', 8000), /* |-------------------------------------------------------------------------- | Application Name |-------------------------------------------------------------------------- | | This value is the name of your application. This value is used when the | framework needs to place the application's name in a notification or | any other location as required by the application or its packages. | */ 'name' => env('APP_NAME', 'Coolify'), /* |-------------------------------------------------------------------------- | 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' => 'cache', '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' => [ /* * Laravel Framework Service Providers... */ Illuminate\Auth\AuthServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, Illuminate\Cache\CacheServiceProvider::class, Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, Illuminate\Cookie\CookieServiceProvider::class, Illuminate\Database\DatabaseServiceProvider::class, Illuminate\Encryption\EncryptionServiceProvider::class, Illuminate\Filesystem\FilesystemServiceProvider::class, Illuminate\Foundation\Providers\FoundationServiceProvider::class, Illuminate\Hashing\HashServiceProvider::class, Illuminate\Mail\MailServiceProvider::class, Illuminate\Notifications\NotificationServiceProvider::class, Illuminate\Pagination\PaginationServiceProvider::class, Illuminate\Pipeline\PipelineServiceProvider::class, Illuminate\Queue\QueueServiceProvider::class, Illuminate\Redis\RedisServiceProvider::class, Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, Illuminate\Session\SessionServiceProvider::class, Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, /* * Package Service Providers... */ \SocialiteProviders\Manager\ServiceProvider::class, /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\FortifyServiceProvider::class, App\Providers\AuthServiceProvider::class, App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\HorizonServiceProvider::class, App\Providers\RouteServiceProvider::class, App\Providers\ConfigurationServiceProvider::class, ], /* |-------------------------------------------------------------------------- | 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([ // 'ExampleClass' => App\Example\ExampleClass::class, ])->toArray(), ]; ================================================ FILE: config/auth.php ================================================ [ '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' => 10, '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, ]; ================================================ FILE: config/broadcasting.php ================================================ env('BROADCAST_DRIVER', 'pusher'), /* |-------------------------------------------------------------------------- | 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', 'coolify'), 'secret' => env('PUSHER_APP_SECRET', 'coolify'), 'app_id' => env('PUSHER_APP_ID', 'coolify'), 'options' => [ 'host' => env('PUSHER_BACKEND_HOST', 'coolify-realtime'), 'port' => env('PUSHER_BACKEND_PORT', 6001), 'scheme' => env('PUSHER_SCHEME', 'http'), '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', ], ], ]; ================================================ FILE: config/cache.php ================================================ env('CACHE_DRIVER', 'redis'), /* |-------------------------------------------------------------------------- | 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_'), ]; ================================================ FILE: config/chunk-upload.php ================================================ [ /* * Returns the folder name of the chunks. The location is in storage/app/{folder_name} */ 'chunks' => 'chunks', 'disk' => 'local', ], 'clear' => [ /* * How old chunks we should delete */ 'timestamp' => '-1 HOURS', 'schedule' => [ 'enabled' => false, 'cron' => '25 * * * *', // run every hour on the 25th minute ], ], 'chunk' => [ // setup for the chunk naming setup to ensure same name upload at same time 'name' => [ 'use' => [ 'session' => true, // should the chunk name use the session id? The uploader must send cookie!, 'browser' => false, // instead of session we can use the ip and browser? ], ], ], 'handlers' => [ // A list of handlers/providers that will be appended to existing list of handlers 'custom' => [], // Overrides the list of handlers - use only what you really want 'override' => [ // \Pion\Laravel\ChunkUpload\Handler\DropZoneUploadHandler::class ], ], ]; ================================================ FILE: config/constants.php ================================================ [ 'version' => '4.0.0-beta.468', 'helper_version' => '1.0.12', 'realtime_version' => '1.0.11', 'self_hosted' => env('SELF_HOSTED', true), 'autoupdate' => env('AUTOUPDATE'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), 'registry_url' => env('REGISTRY_URL', 'ghcr.io'), 'helper_image' => env('HELPER_IMAGE', env('REGISTRY_URL', 'ghcr.io').'/coollabsio/coolify-helper'), 'realtime_image' => env('REALTIME_IMAGE', env('REGISTRY_URL', 'ghcr.io').'/coollabsio/coolify-realtime'), 'is_windows_docker_desktop' => env('IS_WINDOWS_DOCKER_DESKTOP', false), 'cdn_url' => env('CDN_URL', 'https://cdn.coollabs.io'), 'versions_url' => env('VERSIONS_URL', env('CDN_URL', 'https://cdn.coollabs.io').'/coolify/versions.json'), 'upgrade_script_url' => env('UPGRADE_SCRIPT_URL', env('CDN_URL', 'https://cdn.coollabs.io').'/coolify/upgrade.sh'), 'releases_url' => 'https://cdn.coolify.io/releases.json', ], 'urls' => [ 'docs' => 'https://coolify.io/docs', 'contact' => 'https://coolify.io/docs/contact', ], 'services' => [ // Temporary disabled until cache is implemented // 'official' => 'https://cdn.coollabs.io/coolify/service-templates.json', 'official' => 'https://raw.githubusercontent.com/coollabsio/coolify/v4.x/templates/service-templates-latest.json', 'file_name' => 'service-templates-latest.json', ], 'terminal' => [ 'protocol' => env('TERMINAL_PROTOCOL'), 'host' => env('TERMINAL_HOST'), 'port' => env('TERMINAL_PORT'), ], 'pusher' => [ 'host' => env('PUSHER_HOST'), 'port' => env('PUSHER_PORT'), 'app_key' => env('PUSHER_APP_KEY'), ], 'migration' => [ 'is_migration_enabled' => env('MIGRATION_ENABLED', true), ], 'seeder' => [ 'is_seeder_enabled' => env('SEEDER_ENABLED', true), ], 'horizon' => [ 'is_horizon_enabled' => env('HORIZON_ENABLED', true), 'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true), ], 'docker' => [ 'minimum_required_version' => '24.0', ], 'ssh' => [ 'mux_enabled' => env('MUX_ENABLED', env('SSH_MUX_ENABLED', true)), 'mux_persist_time' => env('SSH_MUX_PERSIST_TIME', 3600), 'mux_health_check_enabled' => env('SSH_MUX_HEALTH_CHECK_ENABLED', true), 'mux_health_check_timeout' => env('SSH_MUX_HEALTH_CHECK_TIMEOUT', 5), 'mux_max_age' => env('SSH_MUX_MAX_AGE', 1800), // 30 minutes 'connection_timeout' => 10, 'server_interval' => 20, 'command_timeout' => 3600, 'max_retries' => env('SSH_MAX_RETRIES', 3), 'retry_base_delay' => env('SSH_RETRY_BASE_DELAY', 2), // seconds 'retry_max_delay' => env('SSH_RETRY_MAX_DELAY', 30), // seconds 'retry_multiplier' => env('SSH_RETRY_MULTIPLIER', 2), ], 'invitation' => [ 'link' => [ 'base_url' => '/invitations/', 'expiration_days' => 3, ], ], 'email_change' => [ 'verification_code_expiry_minutes' => 10, ], 'sentry' => [ 'sentry_dsn' => env('SENTRY_DSN'), ], 'webhooks' => [ 'feedback_discord_webhook' => env('FEEDBACK_DISCORD_WEBHOOK'), 'dev_webhook' => env('SERVEO_URL'), ], 'bunny' => [ 'storage_api_key' => env('BUNNY_STORAGE_API_KEY'), 'api_key' => env('BUNNY_API_KEY'), ], 'server_checks' => [ // Notification delay configuration for parallel server checks // Used for Traefik version checks and other future server check jobs // These settings control how long to wait before sending notifications // after dispatching parallel check jobs for all servers // Minimum delay in seconds (120s = 2 minutes) // Accounts for job processing time, retries, and network latency 'notification_delay_min' => 120, // Maximum delay in seconds (300s = 5 minutes) // Prevents excessive waiting for very large server counts 'notification_delay_max' => 300, // Scaling factor: seconds to add per server (0.2) // Formula: delay = min(max, max(min, serverCount * scaling)) // Examples: // - 100 servers: 120s (uses minimum) // - 1000 servers: 200s // - 2000 servers: 300s (hits maximum) 'notification_delay_scaling' => 0.2, ], ]; ================================================ FILE: config/cors.php ================================================ ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => false, ]; ================================================ FILE: config/database.php ================================================ env('DB_CONNECTION', 'pgsql'), /* |-------------------------------------------------------------------------- | 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' => [ 'pgsql' => [ 'driver' => 'pgsql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', 'coolify-db'), 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'coolify'), 'username' => env('DB_USERNAME', 'coolify'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', 'prefix_indexes' => true, 'search_path' => 'public', 'sslmode' => 'prefer', 'options' => [ (defined('Pdo\Pgsql::ATTR_DISABLE_PREPARES') ? \Pdo\Pgsql::ATTR_DISABLE_PREPARES : \PDO::PGSQL_ATTR_DISABLE_PREPARES) => env('DB_DISABLE_PREPARES', false), ], ], 'testing' => [ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', 'foreign_key_constraints' => true, ], ], /* |-------------------------------------------------------------------------- | 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', 'coolify-redis'), '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', 'coolify-redis'), 'username' => env('REDIS_USERNAME'), 'password' => env('REDIS_PASSWORD'), 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_CACHE_DB', '1'), ], ], ]; ================================================ FILE: config/debugbar.php ================================================ env('DEBUGBAR_ENABLED', null), 'except' => [ 'telescope*', 'horizon*', 'api*', ], /* |-------------------------------------------------------------------------- | Storage settings |-------------------------------------------------------------------------- | | DebugBar stores data for session/ajax requests. | You can disable this, so the debugbar stores data in headers/session, | but this can cause problems with large data collectors. | By default, file storage (in the storage folder) is used. Redis and PDO | can also be used. For PDO, run the package migrations first. | | Warning: Enabling storage.open will allow everyone to access previous | request, do not enable open storage in publicly available environments! | Specify a callback if you want to limit based on IP or authentication. | Leaving it to null will allow localhost only. */ 'storage' => [ 'enabled' => true, 'open' => env('DEBUGBAR_OPEN_STORAGE'), // bool/callback. 'driver' => 'file', // redis, file, pdo, socket, custom 'path' => storage_path('debugbar'), // For file driver 'connection' => null, // Leave null for default connection (Redis/PDO) 'provider' => '', // Instance of StorageInterface for custom driver 'hostname' => '127.0.0.1', // Hostname to use with the "socket" driver 'port' => 2304, // Port to use with the "socket" driver ], /* |-------------------------------------------------------------------------- | Editor |-------------------------------------------------------------------------- | | Choose your preferred editor to use when clicking file name. | | Supported: "phpstorm", "vscode", "vscode-insiders", "vscode-remote", | "vscode-insiders-remote", "vscodium", "textmate", "emacs", | "sublime", "atom", "nova", "macvim", "idea", "netbeans", | "xdebug", "espresso" | */ 'editor' => env('DEBUGBAR_EDITOR') ?: env('IGNITION_EDITOR', 'phpstorm'), /* |-------------------------------------------------------------------------- | Remote Path Mapping |-------------------------------------------------------------------------- | | If you are using a remote dev server, like Laravel Homestead, Docker, or | even a remote VPS, it will be necessary to specify your path mapping. | | Leaving one, or both of these, empty or null will not trigger the remote | URL changes and Debugbar will treat your editor links as local files. | | "remote_sites_path" is an absolute base path for your sites or projects | in Homestead, Vagrant, Docker, or another remote development server. | | Example value: "/home/vagrant/Code" | | "local_sites_path" is an absolute base path for your sites or projects | on your local computer where your IDE or code editor is running on. | | Example values: "/Users//Code", "C:\Users\\Documents\Code" | */ 'remote_sites_path' => env('DEBUGBAR_REMOTE_SITES_PATH'), 'local_sites_path' => env('DEBUGBAR_LOCAL_SITES_PATH', env('IGNITION_LOCAL_SITES_PATH')), /* |-------------------------------------------------------------------------- | Vendors |-------------------------------------------------------------------------- | | Vendor files are included by default, but can be set to false. | This can also be set to 'js' or 'css', to only include javascript or css vendor files. | Vendor files are for css: font-awesome (including fonts) and highlight.js (css files) | and for js: jquery and highlight.js | So if you want syntax highlighting, set it to true. | jQuery is set to not conflict with existing jQuery scripts. | */ 'include_vendors' => true, /* |-------------------------------------------------------------------------- | Capture Ajax Requests |-------------------------------------------------------------------------- | | The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors), | you can use this option to disable sending the data through the headers. | | Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools. | | Note for your request to be identified as ajax requests they must either send the header | X-Requested-With with the value XMLHttpRequest (most JS libraries send this), or have application/json as a Accept header. | | By default `ajax_handler_auto_show` is set to true allowing ajax requests to be shown automatically in the Debugbar. | Changing `ajax_handler_auto_show` to false will prevent the Debugbar from reloading. */ 'capture_ajax' => true, 'add_ajax_timing' => false, 'ajax_handler_auto_show' => true, 'ajax_handler_enable_tab' => true, /* |-------------------------------------------------------------------------- | Custom Error Handler for Deprecated warnings |-------------------------------------------------------------------------- | | When enabled, the Debugbar shows deprecated warnings for Symfony components | in the Messages tab. | */ 'error_handler' => false, /* |-------------------------------------------------------------------------- | Clockwork integration |-------------------------------------------------------------------------- | | The Debugbar can emulate the Clockwork headers, so you can use the Chrome | Extension, without the server-side code. It uses Debugbar collectors instead. | */ 'clockwork' => false, /* |-------------------------------------------------------------------------- | DataCollectors |-------------------------------------------------------------------------- | | Enable/disable DataCollectors | */ 'collectors' => [ 'phpinfo' => true, // Php version 'messages' => true, // Messages 'time' => true, // Time Datalogger 'memory' => true, // Memory usage 'exceptions' => true, // Exception displayer 'log' => true, // Logs from Monolog (merged in messages if enabled) 'db' => true, // Show database (PDO) queries and bindings 'views' => true, // Views with their data 'route' => true, // Current route information 'auth' => false, // Display Laravel authentication status 'gate' => true, // Display Laravel Gate checks 'session' => true, // Display session data 'symfony_request' => true, // Only one can be enabled.. 'mail' => true, // Catch mail messages 'laravel' => false, // Laravel version and environment 'events' => false, // All events fired 'default_request' => false, // Regular or special Symfony request logger 'logs' => false, // Add the latest log messages 'files' => false, // Show the included files 'config' => false, // Display config settings 'cache' => false, // Display cache events 'models' => true, // Display models 'livewire' => true, // Display Livewire (when available) 'jobs' => false, // Display dispatched jobs ], /* |-------------------------------------------------------------------------- | Extra options |-------------------------------------------------------------------------- | | Configure some DataCollectors | */ 'options' => [ 'time' => [ 'memory_usage' => false, // Calculated by subtracting memory start and end, it may be inaccurate ], 'messages' => [ 'trace' => true, // Trace the origin of the debug message ], 'memory' => [ 'reset_peak' => false, // run memory_reset_peak_usage before collecting 'with_baseline' => false, // Set boot memory usage as memory peak baseline 'precision' => 0, // Memory rounding precision ], 'auth' => [ 'show_name' => true, // Also show the users name/email in the debugbar 'show_guards' => true, // Show the guards that are used ], 'db' => [ 'with_params' => true, // Render SQL with the parameters substituted 'backtrace' => true, // Use a backtrace to find the origin of the query in your files. 'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults) 'timeline' => false, // Add the queries to the timeline 'duration_background' => true, // Show shaded background on each query relative to how long it took to execute. 'explain' => [ // Show EXPLAIN output on queries 'enabled' => false, 'types' => ['SELECT'], // Deprecated setting, is always only SELECT ], 'hints' => false, // Show hints for common mistakes 'show_copy' => false, // Show copy button next to the query, 'slow_threshold' => false, // Only track queries that last longer than this time in ms 'memory_usage' => false, // Show queries memory usage 'soft_limit' => 100, // After the soft limit, no parameters/backtrace are captured 'hard_limit' => 500, // After the hard limit, queries are ignored ], 'mail' => [ 'timeline' => false, // Add mails to the timeline 'show_body' => true, ], 'views' => [ 'timeline' => false, // Add the views to the timeline (Experimental) 'data' => false, // true for all data, 'keys' for only names, false for no parameters. 'group' => 50, // Group duplicate views. Pass value to auto-group, or true/false to force 'exclude_paths' => [ // Add the paths which you don't want to appear in the views 'vendor/filament', // Exclude Filament components by default ], ], 'route' => [ 'label' => true, // show complete route on bar ], 'session' => [ 'hiddens' => [], // hides sensitive values using array paths ], 'symfony_request' => [ 'hiddens' => [], // hides sensitive values using array paths, example: request_request.password ], 'events' => [ 'data' => false, // collect events data, listeners ], 'logs' => [ 'file' => null, ], 'cache' => [ 'values' => true, // collect cache values ], ], /* |-------------------------------------------------------------------------- | Inject Debugbar in Response |-------------------------------------------------------------------------- | | Usually, the debugbar is added just before , by listening to the | Response after the App is done. If you disable this, you have to add them | in your template yourself. See http://phpdebugbar.com/docs/rendering.html | */ 'inject' => true, /* |-------------------------------------------------------------------------- | DebugBar route prefix |-------------------------------------------------------------------------- | | Sometimes you want to set route prefix to be used by DebugBar to load | its resources from. Usually the need comes from misconfigured web server or | from trying to overcome bugs like this: http://trac.nginx.org/nginx/ticket/97 | */ 'route_prefix' => '_debugbar', /* |-------------------------------------------------------------------------- | DebugBar route middleware |-------------------------------------------------------------------------- | | Additional middleware to run on the Debugbar routes */ 'route_middleware' => [], /* |-------------------------------------------------------------------------- | DebugBar route domain |-------------------------------------------------------------------------- | | By default DebugBar route served from the same domain that request served. | To override default domain, specify it as a non-empty value. */ 'route_domain' => null, /* |-------------------------------------------------------------------------- | DebugBar theme |-------------------------------------------------------------------------- | | Switches between light and dark theme. If set to auto it will respect system preferences | Possible values: auto, light, dark */ 'theme' => env('DEBUGBAR_THEME', 'auto'), /* |-------------------------------------------------------------------------- | Backtrace stack limit |-------------------------------------------------------------------------- | | By default, the DebugBar limits the number of frames returned by the 'debug_backtrace()' function. | If you need larger stacktraces, you can increase this number. Setting it to 0 will result in no limit. */ 'debug_backtrace_limit' => 50, ]; ================================================ FILE: config/filesystems.php ================================================ 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, ], 'ssh-mux' => [ 'driver' => 'local', 'root' => storage_path('app/ssh/mux'), 'visibility' => 'private', 'throw' => false, ], 'ssh-keys' => [ 'driver' => 'local', 'root' => storage_path('app/ssh/keys'), 'visibility' => 'private', 'throw' => false, ], 'deployments' => [ 'driver' => 'local', 'root' => storage_path('app/deployments'), 'visibility' => 'private', 'throw' => false, ], 'backups' => [ 'driver' => 'local', 'root' => storage_path('app/backups'), 'visibility' => 'private', 'throw' => false, ], 's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 'throw' => false, ], ], /* |-------------------------------------------------------------------------- | 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'), ], ]; ================================================ FILE: config/fortify.php ================================================ 'web', /* |-------------------------------------------------------------------------- | Fortify Password Broker |-------------------------------------------------------------------------- | | Here you may specify which password broker Fortify can use when a user | is resetting their password. This configured value should match one | of your password brokers setup in your "auth" configuration file. | */ 'passwords' => 'users', /* |-------------------------------------------------------------------------- | Username / Email |-------------------------------------------------------------------------- | | This value defines which model attribute should be considered as your | application's "username" field. Typically, this might be the email | address of the users but you are free to change this value here. | | Out of the box, Fortify expects forgot password and reset password | requests to have a field named 'email'. If the application uses | another name for the field you may define it below as needed. | */ 'username' => 'email', 'email' => 'email', /* |-------------------------------------------------------------------------- | Home Path |-------------------------------------------------------------------------- | | Here you may configure the path where users will get redirected during | authentication or password reset when the operations are successful | and the user is authenticated. You are free to change this value. | */ 'home' => RouteServiceProvider::HOME, /* |-------------------------------------------------------------------------- | Fortify Routes Prefix / Subdomain |-------------------------------------------------------------------------- | | Here you may specify which prefix Fortify will assign to all the routes | that it registers with the application. If necessary, you may change | subdomain under which all of the Fortify routes will be available. | */ 'prefix' => '', 'domain' => null, /* |-------------------------------------------------------------------------- | Fortify Routes Middleware |-------------------------------------------------------------------------- | | Here you may specify which middleware Fortify will assign to the routes | that it registers with the application. If necessary, you may change | these middleware but typically this provided default is preferred. | */ 'middleware' => ['web'], /* |-------------------------------------------------------------------------- | Rate Limiting |-------------------------------------------------------------------------- | | By default, Fortify will throttle logins to five requests per minute for | every email and IP address combination. However, if you would like to | specify a custom rate limiter to call then you may specify it here. | */ 'limiters' => [ 'login' => 'login', 'two-factor' => 'two-factor', 'forgot-password' => 'forgot-password', ], /* |-------------------------------------------------------------------------- | Register View Routes |-------------------------------------------------------------------------- | | Here you may specify if the routes returning views should be disabled as | you may not need them when building your own application. This may be | especially true if you're writing a custom single-page application. | */ 'views' => true, /* |-------------------------------------------------------------------------- | Features |-------------------------------------------------------------------------- | | Some of the Fortify features are optional. You may disable the features | by removing them from this array. You're free to only remove some of | these features or you can even remove all of these if you need to. | */ 'features' => [ Features::registration(), Features::resetPasswords(), // Features::emailVerification(), Features::updateProfileInformation(), Features::updatePasswords(), Features::twoFactorAuthentication([ 'confirm' => true, 'confirmPassword' => true, // 'window' => 0, ]), ], ]; ================================================ FILE: config/hashing.php ================================================ '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, ], ]; ================================================ FILE: config/horizon.php ================================================ env('HORIZON_DOMAIN'), /* |-------------------------------------------------------------------------- | Horizon Path |-------------------------------------------------------------------------- | | This is the URI path where Horizon will be accessible from. Feel free | to change this path to anything you like. Note that the URI will not | affect the paths of its internal API that aren't exposed to users. | */ 'path' => env('HORIZON_PATH', 'horizon'), /* |-------------------------------------------------------------------------- | Horizon Redis Connection |-------------------------------------------------------------------------- | | This is the name of the Redis connection where Horizon will store the | meta information required for it to function. It includes the list | of supervisors, failed jobs, job metrics, and other information. | */ 'use' => 'default', /* |-------------------------------------------------------------------------- | Horizon Redis Prefix |-------------------------------------------------------------------------- | | This prefix will be used when storing all Horizon data in Redis. You | may modify the prefix when you are running multiple installations | of Horizon on the same server so that they don't have problems. | */ 'prefix' => env( 'HORIZON_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' ), /* |-------------------------------------------------------------------------- | Horizon Route Middleware |-------------------------------------------------------------------------- | | These middleware will get attached onto each Horizon route, giving you | the chance to add your own middleware to this list or change any of | the existing middleware. Or, you can simply stick with this list. | */ 'middleware' => ['web'], /* |-------------------------------------------------------------------------- | Queue Wait Time Thresholds |-------------------------------------------------------------------------- | | This option allows you to configure when the LongWaitDetected event | will be fired. Every connection / queue combination may have its | own, unique threshold (in seconds) before this event is fired. | */ 'waits' => [ 'redis:default' => 60, ], /* |-------------------------------------------------------------------------- | Job Trimming Times |-------------------------------------------------------------------------- | | Here you can configure for how long (in minutes) you desire Horizon to | persist the recent and failed jobs. Typically, recent jobs are kept | for one hour while all failed jobs are stored for an entire week. | */ 'trim' => [ 'recent' => 60, 'pending' => 60, 'completed' => 60, 'recent_failed' => 10080, 'failed' => 10080, 'monitored' => 10080, ], /* |-------------------------------------------------------------------------- | Silenced Jobs |-------------------------------------------------------------------------- | | Silencing a job will instruct Horizon to not place the job in the list | of completed jobs within the Horizon dashboard. This setting may be | used to fully remove any noisy jobs from the completed jobs list. | */ 'silenced' => [ // App\Jobs\ExampleJob::class, ], /* |-------------------------------------------------------------------------- | Metrics |-------------------------------------------------------------------------- | | Here you can configure how many snapshots should be kept to display in | the metrics graph. This will get used in combination with Horizon's | `horizon:snapshot` schedule to define how long to retain metrics. | */ 'metrics' => [ 'trim_snapshots' => [ 'job' => 24, 'queue' => 24, ], ], /* |-------------------------------------------------------------------------- | Fast Termination |-------------------------------------------------------------------------- | | When this option is enabled, Horizon's "terminate" command will not | wait on all of the workers to terminate unless the --wait option | is provided. Fast termination can shorten deployment delay by | allowing a new instance of Horizon to start while the last | instance will continue to terminate each of its workers. | */ 'fast_termination' => false, /* |-------------------------------------------------------------------------- | Memory Limit (MB) |-------------------------------------------------------------------------- | | This value describes the maximum amount of memory the Horizon master | supervisor may consume before it is terminated and restarted. For | configuring these limits on your workers, see the next section. | */ 'memory_limit' => 64, /* |-------------------------------------------------------------------------- | Queue Worker Configuration |-------------------------------------------------------------------------- | | Here you may define the queue worker settings used by your application | in all environments. These supervisors and settings handle all your | queued jobs and will be provisioned by Horizon during deployment. | */ 'defaults' => [ 's6' => [ 'connection' => 'redis', 'balance' => env('HORIZON_BALANCE', 'false'), 'queue' => env('HORIZON_QUEUES', 'high,default'), 'maxTime' => env('HORIZON_MAX_TIME', 0), 'maxJobs' => 400, 'memory' => 128, 'tries' => 1, 'nice' => 0, 'sleep' => 3, 'timeout' => env('HORIZON_TIMEOUT', 36000), ], ], 'environments' => [ 'production' => [ 's6' => [ 'autoScalingStrategy' => 'size', 'minProcesses' => env('HORIZON_MIN_PROCESSES', 1), 'maxProcesses' => env('HORIZON_MAX_PROCESSES', 4), 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1), 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1), ], ], 'local' => [ 's6' => [ 'autoScalingStrategy' => 'size', 'minProcesses' => env('HORIZON_MIN_PROCESSES', 1), 'maxProcesses' => env('HORIZON_MAX_PROCESSES', 4), 'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1), 'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1), ], ], ], ]; ================================================ FILE: config/livewire.php ================================================ 'App\\Livewire', /* |--------------------------------------------------------------------------- | View Path |--------------------------------------------------------------------------- | | This value is used to specify where Livewire component Blade templates are | stored when running file creation commands like `artisan make:livewire`. | It is also used if you choose to omit a component's render() method. | */ 'view_path' => resource_path('views/livewire'), /* |--------------------------------------------------------------------------- | Layout |--------------------------------------------------------------------------- | The view that will be used as the layout when rendering a single component | as an entire page via `Route::get('/post/create', CreatePost::class);`. | In this case, the view returned by CreatePost will render into $slot. | */ 'layout' => 'components.layout', /* |--------------------------------------------------------------------------- | Temporary File Uploads |--------------------------------------------------------------------------- | | Livewire handles file uploads by storing uploads in a temporary directory | before the file is stored permanently. All file uploads are directed to | a global endpoint for temporary storage. You may configure this below: | */ 'temporary_file_upload' => [ 'disk' => null, // Example: 'local', 's3' | Default: 'default' 'rules' => [ // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB) 'file', 'max:256000', ], 'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp' 'middleware' => null, // Example: 'throttle:5,1' | Default: 'throttle:60,1' 'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs... 'png', 'gif', 'bmp', 'svg', 'wav', 'mp4', 'mov', 'avi', 'wmv', 'mp3', 'm4a', 'jpg', 'jpeg', 'mpga', 'webp', 'wma', ], 'max_upload_time' => 5, // Max duration (in minutes) before an upload is invalidated... ], /* |--------------------------------------------------------------------------- | Render On Redirect |--------------------------------------------------------------------------- | | This value determines if Livewire will run a component's `render()` method | after a redirect has been triggered using something like `redirect(...)` | Setting this to true will render the view once more before redirecting | */ 'render_on_redirect' => false, /* |--------------------------------------------------------------------------- | Eloquent Model Binding |--------------------------------------------------------------------------- | | Previous versions of Livewire supported binding directly to eloquent model | properties using wire:model by default. However, this behavior has been | deemed too "magical" and has therefore been put under a feature flag. | */ 'legacy_model_binding' => false, /* |--------------------------------------------------------------------------- | Auto-inject Frontend Assets |--------------------------------------------------------------------------- | | By default, Livewire automatically injects its JavaScript and CSS into the | and of pages containing Livewire components. By disabling | this behavior, you need to use @livewireStyles and @livewireScripts. | */ 'inject_assets' => true, /* |--------------------------------------------------------------------------- | Navigate (SPA mode) |--------------------------------------------------------------------------- | | By adding `` to links in your Livewire application, Livewire | will prevent the default link handling and instead request those pages | via AJAX, creating an SPA-like effect. Configure this behavior here. | */ 'navigate' => [ 'show_progress_bar' => true, 'progress_bar_color' => '#ffff00', ], /* |--------------------------------------------------------------------------- | HTML Morph Markers |--------------------------------------------------------------------------- | | Livewire intelligently "morphs" existing HTML into the newly rendered HTML | after each update. To make this process more reliable, Livewire injects | "markers" into the rendered Blade surrounding @if, @class & @foreach. | */ 'inject_morph_markers' => true, /* |--------------------------------------------------------------------------- | Pagination Theme |--------------------------------------------------------------------------- | | When enabling Livewire's pagination feature by using the `WithPagination` | trait, Livewire will use Tailwind templates to render pagination views | on the page. If you want Bootstrap CSS, you can specify: "bootstrap" | */ 'pagination_theme' => 'tailwind', 'lazy_placeholder' => 'components.page-loading', ]; ================================================ FILE: config/logging.php ================================================ 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'), ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 14, ], 'slack' => [ 'driver' => 'slack', 'url' => env('LOG_SLACK_WEBHOOK_URL'), 'username' => 'Laravel Log', 'emoji' => ':boom:', 'level' => env('LOG_LEVEL', 'critical'), ], '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'), ], ], 'stderr' => [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), 'handler' => StreamHandler::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ 'stream' => 'php://stderr', ], ], 'syslog' => [ 'driver' => 'syslog', 'level' => env('LOG_LEVEL', 'debug'), 'facility' => LOG_USER, ], 'errorlog' => [ 'driver' => 'errorlog', 'level' => env('LOG_LEVEL', 'debug'), ], 'null' => [ 'driver' => 'monolog', 'handler' => NullHandler::class, ], 'emergency' => [ 'path' => storage_path('logs/laravel.log'), ], 'scheduled' => [ 'driver' => 'daily', 'path' => storage_path('logs/scheduled.log'), 'level' => 'debug', 'days' => 1, ], 'scheduled-errors' => [ 'driver' => 'daily', 'path' => storage_path('logs/scheduled-errors.log'), 'level' => 'warning', 'days' => 14, ], ], ]; ================================================ FILE: config/mail.php ================================================ env('MAIL_MAILER', 'array'), /* |-------------------------------------------------------------------------- | 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', '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'), ], 'resend' => [ 'transport' => 'resend', ], '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'), ], ], ]; ================================================ FILE: config/purify.php ================================================ 'default', /* |-------------------------------------------------------------------------- | Config sets |-------------------------------------------------------------------------- | | Here you may configure various sets of configuration for differentiated use of HTMLPurifier. | A specific set of configuration can be applied by calling the "config($name)" method on | a Purify instance. Feel free to add/remove/customize these attributes as you wish. | | Documentation: http://htmlpurifier.org/live/configdoc/plain.html | | Core.Encoding The encoding to convert input to. | HTML.Doctype Doctype to use during filtering. | HTML.Allowed The allowed HTML Elements with their allowed attributes. | HTML.ForbiddenElements The forbidden HTML elements. Elements that are listed in this | string will be removed, however their content will remain. | CSS.AllowedProperties The Allowed CSS properties. | AutoFormat.AutoParagraph Newlines are converted in to paragraphs whenever possible. | AutoFormat.RemoveEmpty Remove empty elements that contribute no semantic information to the document. | */ 'configs' => [ 'default' => [ 'Core.Encoding' => 'utf-8', 'HTML.Doctype' => 'HTML 4.01 Transitional', 'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,b,u,strong,i,em,s,del,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src],blockquote', 'HTML.ForbiddenElements' => '', 'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align', 'AutoFormat.AutoParagraph' => false, 'AutoFormat.RemoveEmpty' => false, ], ], /* |-------------------------------------------------------------------------- | HTMLPurifier definitions |-------------------------------------------------------------------------- | | Here you may specify a class that augments the HTML definitions used by | HTMLPurifier. Additional HTML5 definitions are provided out of the box. | When specifying a custom class, make sure it implements the interface: | | \Stevebauman\Purify\Definitions\Definition | | Note that these definitions are applied to every Purifier instance. | | Documentation: http://htmlpurifier.org/docs/enduser-customize.html | */ 'definitions' => Html5Definition::class, /* |-------------------------------------------------------------------------- | HTMLPurifier CSS definitions |-------------------------------------------------------------------------- | | Here you may specify a class that augments the CSS definitions used by | HTMLPurifier. When specifying a custom class, make sure it implements | the interface: | | \Stevebauman\Purify\Definitions\CssDefinition | | Note that these definitions are applied to every Purifier instance. | | CSS should be extending $definition->info['css-attribute'] = values | See HTMLPurifier_CSSDefinition for further explanation | */ 'css-definitions' => null, /* |-------------------------------------------------------------------------- | Serializer |-------------------------------------------------------------------------- | | The storage implementation where HTMLPurifier can store its serializer files. | If the filesystem cache is in use, the path must be writable through the | storage disk by the web server, otherwise an exception will be thrown. | */ 'serializer' => [ 'driver' => env('CACHE_STORE', env('CACHE_DRIVER', 'file')), 'cache' => \Stevebauman\Purify\Cache\CacheDefinitionCache::class, ], // 'serializer' => [ // 'disk' => env('FILESYSTEM_DISK', 'local'), // 'path' => 'purify', // 'cache' => \Stevebauman\Purify\Cache\FilesystemDefinitionCache::class, // ], ]; ================================================ FILE: config/queue.php ================================================ env('QUEUE_CONNECTION', 'redis'), /* |-------------------------------------------------------------------------- | 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' => 86400, 'block_for' => null, 'after_commit' => true, ], ], /* |-------------------------------------------------------------------------- | 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', 'pgsql'), 'table' => 'failed_jobs', ], ]; ================================================ FILE: config/ray.php ================================================ env('RAY_ENABLED', true), /* * When enabled, all cache events will automatically be sent to Ray. */ 'send_cache_to_ray' => env('SEND_CACHE_TO_RAY', false), /* * When enabled, all things passed to `dump` or `dd` * will be sent to Ray as well. */ 'send_dumps_to_ray' => env('SEND_DUMPS_TO_RAY', true), /* * When enabled all job events will automatically be sent to Ray. */ 'send_jobs_to_ray' => env('SEND_JOBS_TO_RAY', false), /* * When enabled, all things logged to the application log * will be sent to Ray as well. */ 'send_log_calls_to_ray' => env('SEND_LOG_CALLS_TO_RAY', true), /* * When enabled, all queries will automatically be sent to Ray. */ 'send_queries_to_ray' => env('SEND_QUERIES_TO_RAY', false), /** * When enabled, all duplicate queries will automatically be sent to Ray. */ 'send_duplicate_queries_to_ray' => env('SEND_DUPLICATE_QUERIES_TO_RAY', false), /* * When enabled, slow queries will automatically be sent to Ray. */ 'send_slow_queries_to_ray' => env('SEND_SLOW_QUERIES_TO_RAY', false), /** * Queries that are longer than this number of milliseconds will be regarded as slow. */ 'slow_query_threshold_in_ms' => env('RAY_SLOW_QUERY_THRESHOLD_IN_MS', 500), /* * When enabled, all requests made to this app will automatically be sent to Ray. */ 'send_requests_to_ray' => env('SEND_REQUESTS_TO_RAY', false), /** * When enabled, all Http Client requests made by this app will be automatically sent to Ray. */ 'send_http_client_requests_to_ray' => env('SEND_HTTP_CLIENT_REQUESTS_TO_RAY', false), /* * When enabled, all views that are rendered automatically be sent to Ray. */ 'send_views_to_ray' => env('SEND_VIEWS_TO_RAY', false), /* * When enabled, all exceptions will be automatically sent to Ray. */ 'send_exceptions_to_ray' => env('SEND_EXCEPTIONS_TO_RAY', true), /* * When enabled, all deprecation notices will be automatically sent to Ray. */ 'send_deprecated_notices_to_ray' => env('SEND_DEPRECATED_NOTICES_TO_RAY', false), /* * The host used to communicate with the Ray app. * When using Docker on Mac or Windows, you can replace localhost with 'host.docker.internal' * When using Docker on Linux, you can replace localhost with '172.17.0.1' * When using Homestead with the VirtualBox provider, you can replace localhost with '10.0.2.2' * When using Homestead with the Parallels provider, you can replace localhost with '10.211.55.2' */ 'host' => env('RAY_HOST', 'host.docker.internal'), /* * The port number used to communicate with the Ray app. */ 'port' => env('RAY_PORT', 23517), /* * Absolute base path for your sites or projects in Homestead, * Vagrant, Docker, or another remote development server. */ 'remote_path' => env('RAY_REMOTE_PATH', null), /* * Absolute base path for your sites or projects on your local * computer where your IDE or code editor is running on. */ 'local_path' => env('RAY_LOCAL_PATH', null), /* * When this setting is enabled, the package will not try to format values sent to Ray. */ 'always_send_raw_values' => false, ]; ================================================ FILE: config/sanctum.php ================================================ 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' => [ 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class, 'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, ], ]; ================================================ FILE: config/sentry.php ================================================ config('constants.sentry.sentry_dsn'), // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) 'release' => config('constants.coolify.version'), // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), 'breadcrumbs' => [ // Capture Laravel logs in breadcrumbs 'logs' => true, // Capture Laravel cache events in breadcrumbs 'cache' => true, // Capture Livewire components in breadcrumbs 'livewire' => true, // Capture SQL queries in breadcrumbs 'sql_queries' => true, // Capture bindings on SQL queries logged in breadcrumbs 'sql_bindings' => true, // Capture queue job information in breadcrumbs 'queue_info' => true, // Capture command information in breadcrumbs 'command_info' => true, // Capture HTTP client requests information in breadcrumbs 'http_client_requests' => true, ], 'tracing' => [ // Trace queue jobs as their own transactions 'queue_job_transactions' => env('SENTRY_TRACE_QUEUE_ENABLED', false), // Capture queue jobs as spans when executed on the sync driver 'queue_jobs' => true, // Capture SQL queries as spans 'sql_queries' => true, // Try to find out where the SQL query originated from and add it to the query spans 'sql_origin' => true, // Capture views as spans 'views' => true, // Capture Livewire components as spans 'livewire' => true, // Capture HTTP client requests as spans 'http_client_requests' => true, // Capture Redis operations as spans (this enables Redis events in Laravel) 'redis_commands' => env('SENTRY_TRACE_REDIS_COMMANDS', false), // Try to find out where the Redis command originated from and add it to the command spans 'redis_origin' => true, // Indicates if the tracing integrations supplied by Sentry should be loaded 'default_integrations' => true, // Indicates that requests without a matching route should be traced 'missing_routes' => false, ], // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii 'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false), // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate 'enable_tracing' => env('SENTRY_ENABLE_TRACING', false), 'traces_sample_rate' => 0.2, 'profiles_sample_rate' => env('SENTRY_PROFILES_SAMPLE_RATE') === null ? null : (float) env('SENTRY_PROFILES_SAMPLE_RATE'), ]; ================================================ FILE: config/services.php ================================================ [ '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'), ], 'azure' => [ 'client_id' => env('AZURE_CLIENT_ID'), 'client_secret' => env('AZURE_CLIENT_SECRET'), 'redirect' => env('AZURE_REDIRECT_URI'), 'tenant' => env('AZURE_TENANT_ID'), 'proxy' => env('AZURE_PROXY'), ], 'authentik' => [ 'base_url' => env('AUTHENTIK_BASE_URL'), 'client_id' => env('AUTHENTIK_CLIENT_ID'), 'client_secret' => env('AUTHENTIK_CLIENT_SECRET'), 'redirect' => env('AUTHENTIK_REDIRECT_URI'), ], 'clerk' => [ 'client_id' => env('CLERK_CLIENT_ID'), 'client_secret' => env('CLERK_CLIENT_SECRET'), 'redirect' => env('CLERK_REDIRECT_URI'), 'base_url' => env('CLERK_BASE_URL'), ], 'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => env('GOOGLE_REDIRECT_URI'), 'tenant' => env('GOOGLE_TENANT'), ], 'zitadel' => [ 'client_id' => env('ZITADEL_CLIENT_ID'), 'client_secret' => env('ZITADEL_CLIENT_SECRET'), 'redirect' => env('ZITADEL_REDIRECT_URI'), 'base_url' => env('ZITADEL_BASE_URL'), ], ]; ================================================ FILE: config/session.php ================================================ env('SESSION_DRIVER', 'database'), /* |-------------------------------------------------------------------------- | 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', 10080), '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' => true, /* |-------------------------------------------------------------------------- | 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', ]; ================================================ FILE: config/subscription.php ================================================ env('SUBSCRIPTION_PROVIDER', null), // stripe // Stripe 'stripe_api_key' => env('STRIPE_API_KEY', null), 'stripe_webhook_secret' => env('STRIPE_WEBHOOK_SECRET', null), 'stripe_excluded_plans' => env('STRIPE_EXCLUDED_PLANS', null), 'stripe_price_id_dynamic_monthly' => env('STRIPE_PRICE_ID_DYNAMIC_MONTHLY', null), 'stripe_price_id_dynamic_yearly' => env('STRIPE_PRICE_ID_DYNAMIC_YEARLY', null), ]; ================================================ FILE: config/telescope.php ================================================ env('TELESCOPE_ENABLED', false), /* |-------------------------------------------------------------------------- | Telescope Domain |-------------------------------------------------------------------------- | | This is the subdomain where Telescope will be accessible from. If the | setting is null, Telescope will reside under the same domain as the | application. Otherwise, this value will be used as the subdomain. | */ 'domain' => env('TELESCOPE_DOMAIN'), /* |-------------------------------------------------------------------------- | Telescope Path |-------------------------------------------------------------------------- | | This is the URI path where Telescope will be accessible from. Feel free | to change this path to anything you like. Note that the URI will not | affect the paths of its internal API that aren't exposed to users. | */ 'path' => env('TELESCOPE_PATH', 'telescope'), /* |-------------------------------------------------------------------------- | Telescope Storage Driver |-------------------------------------------------------------------------- | | This configuration options determines the storage driver that will | be used to store Telescope's data. In addition, you may set any | custom options as needed by the particular driver you choose. | */ 'driver' => env('TELESCOPE_DRIVER', 'database'), 'storage' => [ 'database' => [ 'connection' => env('DB_CONNECTION', 'pgsql'), 'chunk' => 1000, ], ], /* |-------------------------------------------------------------------------- | Telescope Queue |-------------------------------------------------------------------------- | | This configuration options determines the queue connection and queue | which will be used to process ProcessPendingUpdate jobs. This can | be changed if you would prefer to use a non-default connection. | */ 'queue' => [ 'connection' => env('TELESCOPE_QUEUE_CONNECTION', 'redis'), 'queue' => env('TELESCOPE_QUEUE', 'default'), ], /* |-------------------------------------------------------------------------- | Telescope Route Middleware |-------------------------------------------------------------------------- | | These middleware will be assigned to every Telescope route, giving you | the chance to add your own middleware to this list or change any of | the existing middleware. Or, you can simply stick with this list. | */ 'middleware' => [ 'web', Authorize::class, ], /* |-------------------------------------------------------------------------- | Allowed / Ignored Paths & Commands |-------------------------------------------------------------------------- | | The following array lists the URI paths and Artisan commands that will | not be watched by Telescope. In addition to this list, some Laravel | commands, like migrations and queue commands, are always ignored. | */ 'only_paths' => [ // 'api/*' ], 'ignore_paths' => [ 'livewire*', 'nova-api*', 'pulse*', ], 'ignore_commands' => [ // ], /* |-------------------------------------------------------------------------- | Telescope Watchers |-------------------------------------------------------------------------- | | The following array lists the "watchers" that will be registered with | Telescope. The watchers gather the application's profile data when | a request or task is executed. Feel free to customize this list. | */ 'watchers' => [ Watchers\BatchWatcher::class => env('TELESCOPE_BATCH_WATCHER', true), Watchers\CacheWatcher::class => [ 'enabled' => env('TELESCOPE_CACHE_WATCHER', true), 'hidden' => [], ], Watchers\ClientRequestWatcher::class => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true), Watchers\CommandWatcher::class => [ 'enabled' => env('TELESCOPE_COMMAND_WATCHER', true), 'ignore' => [], ], Watchers\DumpWatcher::class => [ 'enabled' => env('TELESCOPE_DUMP_WATCHER', true), 'always' => env('TELESCOPE_DUMP_WATCHER_ALWAYS', false), ], Watchers\EventWatcher::class => [ 'enabled' => env('TELESCOPE_EVENT_WATCHER', true), 'ignore' => [], ], Watchers\ExceptionWatcher::class => env('TELESCOPE_EXCEPTION_WATCHER', true), Watchers\GateWatcher::class => [ 'enabled' => env('TELESCOPE_GATE_WATCHER', true), 'ignore_abilities' => [], 'ignore_packages' => true, 'ignore_paths' => [], ], Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true), Watchers\LogWatcher::class => [ 'enabled' => env('TELESCOPE_LOG_WATCHER', true), 'level' => 'error', ], Watchers\MailWatcher::class => env('TELESCOPE_MAIL_WATCHER', true), Watchers\ModelWatcher::class => [ 'enabled' => env('TELESCOPE_MODEL_WATCHER', true), 'events' => ['eloquent.*'], 'hydrations' => true, ], Watchers\NotificationWatcher::class => env('TELESCOPE_NOTIFICATION_WATCHER', true), Watchers\QueryWatcher::class => [ 'enabled' => env('TELESCOPE_QUERY_WATCHER', true), 'ignore_packages' => true, 'ignore_paths' => [], 'slow' => 100, ], Watchers\RedisWatcher::class => env('TELESCOPE_REDIS_WATCHER', true), Watchers\RequestWatcher::class => [ 'enabled' => env('TELESCOPE_REQUEST_WATCHER', true), 'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64), 'ignore_http_methods' => [], 'ignore_status_codes' => [], ], Watchers\ScheduleWatcher::class => env('TELESCOPE_SCHEDULE_WATCHER', true), Watchers\ViewWatcher::class => env('TELESCOPE_VIEW_WATCHER', true), ], ]; ================================================ FILE: config/testing.php ================================================ env('DUSK_TEST_EMAIL', 'test@example.com'), 'dusk_test_password' => env('DUSK_TEST_PASSWORD', 'password'), ]; ================================================ FILE: config/view.php ================================================ [ 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')) ), ]; ================================================ FILE: database/factories/ApplicationFactory.php ================================================ fake()->unique()->name(), 'destination_id' => 1, 'git_repository' => fake()->url(), 'git_branch' => fake()->word(), 'build_pack' => 'nixpacks', 'ports_exposes' => '3000', 'environment_id' => 1, 'destination_id' => 1, ]; } } ================================================ FILE: database/factories/EnvironmentFactory.php ================================================ fake()->unique()->word(), 'project_id' => 1, ]; } } ================================================ FILE: database/factories/ProjectFactory.php ================================================ fake()->unique()->company(), 'team_id' => 1, ]; } } ================================================ FILE: database/factories/ScheduledTaskFactory.php ================================================ fake()->word(), 'command' => 'echo hello', 'frequency' => '* * * * *', 'timeout' => 300, 'enabled' => true, 'team_id' => Team::factory(), ]; } } ================================================ FILE: database/factories/ServerFactory.php ================================================ fake()->unique()->name(), 'ip' => fake()->unique()->ipv4(), 'private_key_id' => 1, ]; } } ================================================ FILE: database/factories/ServiceFactory.php ================================================ fake()->unique()->word(), 'destination_type' => \App\Models\StandaloneDocker::class, 'destination_id' => 1, 'environment_id' => 1, 'docker_compose_raw' => 'version: "3"', ]; } } ================================================ FILE: database/factories/StandaloneDockerFactory.php ================================================ fake()->uuid(), 'name' => fake()->unique()->word(), 'network' => 'coolify', 'server_id' => 1, ]; } } ================================================ FILE: database/factories/TeamFactory.php ================================================ */ class TeamFactory extends Factory { protected $model = Team::class; /** * Define the model's default state. * * @return array */ public function definition(): array { return [ 'name' => $this->faker->company().' Team', 'description' => $this->faker->sentence(), 'personal_team' => false, 'show_boarding' => false, ]; } /** * Indicate that the team is a personal team. */ public function personal(): static { return $this->state(fn (array $attributes) => [ 'personal_team' => true, 'name' => $this->faker->firstName()."'s Team", ]); } } ================================================ FILE: database/factories/UserFactory.php ================================================ */ class UserFactory extends Factory { /** * Define the model's default state. * * @return array */ public function definition(): array { return [ '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, ]); } } ================================================ FILE: database/migrations/2014_10_12_000000_create_users_table.php ================================================ id(); $table->string('name')->default('Anonymous'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('users'); } }; ================================================ FILE: database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php ================================================ string('email')->primary(); $table->string('token'); $table->timestamp('created_at')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('password_reset_tokens'); } }; ================================================ FILE: database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php ================================================ text('two_factor_secret') ->after('password') ->nullable(); $table->text('two_factor_recovery_codes') ->after('two_factor_secret') ->nullable(); if (Fortify::confirmsTwoFactorAuthentication()) { $table->timestamp('two_factor_confirmed_at') ->after('two_factor_recovery_codes') ->nullable(); } }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn(array_merge([ 'two_factor_secret', 'two_factor_recovery_codes', ], Fortify::confirmsTwoFactorAuthentication() ? [ 'two_factor_confirmed_at', ] : [])); }); } }; ================================================ FILE: database/migrations/2018_08_08_100000_create_telescope_entries_table.php ================================================ getConnection()); $schema->create('telescope_entries', function (Blueprint $table) { $table->bigIncrements('sequence'); $table->uuid('uuid'); $table->uuid('batch_id'); $table->string('family_hash')->nullable(); $table->boolean('should_display_on_index')->default(true); $table->string('type', 20); $table->longText('content'); $table->dateTime('created_at')->nullable(); $table->unique('uuid'); $table->index('batch_id'); $table->index('family_hash'); $table->index('created_at'); $table->index(['type', 'should_display_on_index']); }); $schema->create('telescope_entries_tags', function (Blueprint $table) { $table->uuid('entry_uuid'); $table->string('tag'); $table->primary(['entry_uuid', 'tag']); $table->index('tag'); $table->foreign('entry_uuid') ->references('uuid') ->on('telescope_entries') ->onDelete('cascade'); }); $schema->create('telescope_monitoring', function (Blueprint $table) { $table->string('tag')->primary(); }); } /** * Reverse the migrations. */ public function down(): void { $schema = Schema::connection($this->getConnection()); $schema->dropIfExists('telescope_entries_tags'); $schema->dropIfExists('telescope_entries'); $schema->dropIfExists('telescope_monitoring'); } }; ================================================ FILE: database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php ================================================ id(); $table->morphs('tokenable'); $table->string('name'); $table->string('token', 64)->unique(); $table->string('team_id'); $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'); } }; ================================================ FILE: database/migrations/2023_03_20_112410_create_activity_log_table.php ================================================ create(config('activitylog.table_name'), function (Blueprint $table) { $table->id(); $table->string('log_name')->nullable(); $table->text('description'); $table->nullableMorphs('subject', 'subject'); $table->nullableMorphs('causer', 'causer'); $table->json('properties')->nullable(); $table->timestamps(); $table->index('log_name'); }); } public function down() { Schema::connection(config('activitylog.database_connection'))->dropIfExists(config('activitylog.table_name')); } } ================================================ FILE: database/migrations/2023_03_20_112411_add_event_column_to_activity_log_table.php ================================================ table(config('activitylog.table_name'), function (Blueprint $table) { $table->string('event')->nullable()->after('subject_type'); }); } public function down() { Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) { $table->dropColumn('event'); }); } } ================================================ FILE: database/migrations/2023_03_20_112412_add_batch_uuid_column_to_activity_log_table.php ================================================ table(config('activitylog.table_name'), function (Blueprint $table) { $table->uuid('batch_uuid')->nullable()->after('properties'); }); } public function down() { Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) { $table->dropColumn('batch_uuid'); }); } } ================================================ FILE: database/migrations/2023_03_20_112809_create_sessions_table.php ================================================ string('id')->primary(); $table->foreignId('user_id')->nullable()->index(); $table->string('ip_address', 45)->nullable(); $table->text('user_agent')->nullable(); $table->longText('payload'); $table->integer('last_activity')->index(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('sessions'); } }; ================================================ FILE: database/migrations/2023_03_20_112811_create_teams_table.php ================================================ id(); $table->string('name'); $table->string('description')->nullable(); $table->boolean('personal_team')->default(false); $table->schemalessAttributes('smtp'); $table->schemalessAttributes('smtp_notifications'); $table->schemalessAttributes('discord'); $table->schemalessAttributes('discord_notifications'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('teams'); } }; ================================================ FILE: database/migrations/2023_03_20_112812_create_team_user_table.php ================================================ id(); $table->foreignId('team_id'); $table->foreignId('user_id'); $table->string('role')->default('member'); $table->timestamps(); $table->unique(['team_id', 'user_id']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('team_user'); } }; ================================================ FILE: database/migrations/2023_03_20_112813_create_team_invitations_table.php ================================================ id(); $table->string('uuid')->unique(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->string('email'); $table->string('role')->default('member'); $table->string('link'); $table->string('via')->default('link'); $table->timestamps(); $table->unique(['team_id', 'email']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('team_invitations'); } }; ================================================ FILE: database/migrations/2023_03_20_112814_create_instance_settings_table.php ================================================ id(); $table->string('public_ipv4')->nullable(); $table->string('public_ipv6')->nullable(); $table->string('fqdn')->nullable(); $table->string('wildcard_domain')->nullable(); $table->string('default_redirect_404')->nullable(); $table->integer('public_port_min')->default(9000); $table->integer('public_port_max')->default(9100); $table->boolean('do_not_track')->default(false); $table->boolean('is_auto_update_enabled')->default(true); $table->boolean('is_registration_enabled')->default(true); $table->schemalessAttributes('smtp'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('instance_settings'); } }; ================================================ FILE: database/migrations/2023_03_24_140711_create_servers_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->string('ip'); $table->integer('port')->default(22); $table->string('user')->default('root'); $table->foreignId('team_id'); $table->foreignId('private_key_id'); $table->schemalessAttributes('proxy'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('servers'); } }; ================================================ FILE: database/migrations/2023_03_24_140712_create_server_settings_table.php ================================================ id(); $table->boolean('is_part_of_swarm')->default(false); $table->boolean('is_jump_server')->default(false); $table->boolean('is_build_server')->default(false); $table->boolean('is_reachable')->default(false); $table->boolean('is_usable')->default(false); $table->foreignId('server_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('server_settings'); } }; ================================================ FILE: database/migrations/2023_03_24_140853_create_private_keys_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->longText('private_key'); $table->boolean('is_git_related')->default(false); $table->foreignId('team_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('private_keys'); } }; ================================================ FILE: database/migrations/2023_03_27_075351_create_projects_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->foreignId('team_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('projects'); } }; ================================================ FILE: database/migrations/2023_03_27_075443_create_project_settings_table.php ================================================ id(); $table->string('wildcard_domain')->nullable(); $table->foreignId('project_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('project_settings'); } }; ================================================ FILE: database/migrations/2023_03_27_075444_create_environments_table.php ================================================ id(); $table->string('name'); $table->foreignId('project_id'); $table->timestamps(); $table->unique(['name', 'project_id']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('environments'); } }; ================================================ FILE: database/migrations/2023_03_27_081716_create_applications_table.php ================================================ id(); $table->integer('repository_project_id')->nullable(); $table->string('uuid')->unique(); $table->string('name'); $table->string('fqdn')->unique()->nullable(); $table->string('config_hash')->nullable(); $table->string('git_repository'); $table->string('git_branch'); $table->string('git_commit_sha')->default('HEAD'); // TODO: remove this column, it is not used $table->string('git_full_url')->nullable(); $table->string('docker_registry_image_name')->nullable(); $table->string('docker_registry_image_tag')->nullable(); $table->string('build_pack'); $table->string('static_image')->default('nginx:alpine'); $table->string('install_command')->nullable(); $table->string('build_command')->nullable(); $table->string('start_command')->nullable(); $table->string('ports_exposes'); $table->string('ports_mappings')->nullable(); $table->string('base_directory')->default('/'); $table->string('publish_directory')->nullable(); $table->string('health_check_path')->default('/'); $table->string('health_check_port')->nullable(); $table->string('health_check_host')->default('localhost'); $table->string('health_check_method')->default('GET'); $table->integer('health_check_return_code')->default(200); $table->string('health_check_scheme')->default('http'); $table->string('health_check_response_text')->nullable(); $table->integer('health_check_interval')->default(5); $table->integer('health_check_timeout')->default(5); $table->integer('health_check_retries')->default(10); $table->integer('health_check_start_period')->default(5); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default('0'); $table->integer('limits_cpu_shares')->default(1024); $table->string('status')->default('exited'); $table->string('preview_url_template')->default('{{pr_id}}.{{domain}}'); $table->nullableMorphs('destination'); $table->nullableMorphs('source'); $table->foreignId('private_key_id')->nullable(); $table->foreignId('environment_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('applications'); } }; ================================================ FILE: database/migrations/2023_03_27_081717_create_application_settings_table.php ================================================ id(); $table->boolean('is_static')->default(false); $table->boolean('is_git_submodules_enabled')->default(true); $table->boolean('is_git_lfs_enabled')->default(true); $table->boolean('is_auto_deploy_enabled')->default(true); $table->boolean('is_force_https_enabled')->default(true); $table->boolean('is_debug_enabled')->default(false); $table->boolean('is_preview_deployments_enabled')->default(false); // $table->boolean('is_dual_cert')->default(false); // $table->boolean('is_custom_ssl')->default(false); // $table->boolean('is_http2')->default(false); $table->foreignId('application_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('application_settings'); } }; ================================================ FILE: database/migrations/2023_03_27_081718_create_application_previews_table.php ================================================ id(); $table->string('uuid')->unique(); $table->integer('pull_request_id'); $table->string('pull_request_html_url'); $table->integer('pull_request_issue_comment_id')->nullable(); $table->string('fqdn')->unique()->nullable(); $table->string('status')->default('exited'); $table->foreignId('application_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('application_previews'); } }; ================================================ FILE: database/migrations/2023_03_27_083621_create_services_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->morphs('destination'); $table->foreignId('environment_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('services'); } }; ================================================ FILE: database/migrations/2023_03_27_085020_create_standalone_dockers_table.php ================================================ id(); $table->string('name'); $table->string('uuid')->unique(); $table->string('network'); $table->foreignId('server_id'); $table->unique(['server_id', 'network']); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_dockers'); } }; ================================================ FILE: database/migrations/2023_03_27_085022_create_swarm_dockers_table.php ================================================ id(); $table->string('name'); $table->string('uuid')->unique(); $table->foreignId('server_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('swarm_dockers'); } }; ================================================ FILE: database/migrations/2023_03_28_062150_create_kubernetes_table.php ================================================ id(); $table->string('uuid')->unique(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('kubernetes'); } }; ================================================ FILE: database/migrations/2023_03_28_083723_create_github_apps_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('organization')->nullable(); $table->string('api_url'); $table->string('html_url'); $table->string('custom_user')->default('git'); $table->integer('custom_port')->default(22); $table->integer('app_id')->nullable(); $table->integer('installation_id')->nullable(); $table->string('client_id')->nullable(); $table->longText('client_secret')->nullable(); $table->longText('webhook_secret')->nullable(); $table->boolean('is_system_wide')->default(false); $table->boolean('is_public')->default(false); $table->foreignId('private_key_id')->nullable(); $table->foreignId('team_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('github_apps'); } }; ================================================ FILE: database/migrations/2023_03_28_083726_create_gitlab_apps_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('organization')->nullable(); $table->string('api_url'); $table->string('html_url'); $table->integer('custom_port')->default(22); $table->string('custom_user')->default('git'); $table->boolean('is_system_wide')->default(false); $table->boolean('is_public')->default(false); $table->integer('app_id')->nullable(); $table->string('app_secret')->nullable(); $table->integer('oauth_id')->nullable(); $table->string('group_name')->nullable(); $table->longText('public_key')->nullable(); $table->longText('webhook_token')->nullable(); $table->integer('deploy_key_id')->nullable(); $table->foreignId('private_key_id')->nullable(); $table->foreignId('team_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('gitlab_apps'); } }; ================================================ FILE: database/migrations/2023_04_03_111012_create_local_persistent_volumes_table.php ================================================ id(); $table->string('name'); $table->string('mount_path'); $table->string('host_path')->nullable(); $table->string('container_id')->nullable(); $table->nullableMorphs('resource'); $table->unique(['name', 'resource_id', 'resource_type']); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('local_persistent_volumes'); } }; ================================================ FILE: database/migrations/2023_05_04_194548_create_environment_variables_table.php ================================================ id(); $table->string('key'); $table->string('value')->nullable(); $table->boolean('is_build_time')->default(false); $table->boolean('is_preview')->default(false); $table->foreignId('application_id')->nullable(); $table->foreignId('service_id')->nullable(); $table->foreignId('database_id')->nullable(); $table->unique(['key', 'application_id', 'is_build_time', 'is_preview']); $table->unique(['key', 'service_id', 'is_build_time', 'is_preview']); $table->unique(['key', 'database_id', 'is_build_time', 'is_preview']); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('environment_variables'); } }; ================================================ FILE: database/migrations/2023_05_17_104039_create_failed_jobs_table.php ================================================ 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'); } }; ================================================ FILE: database/migrations/2023_05_24_083426_create_application_deployment_queues_table.php ================================================ id(); $table->string('application_id'); $table->string('deployment_uuid')->unique(); $table->integer('pull_request_id')->default(0); $table->boolean('force_rebuild')->default(false); $table->string('commit')->default('HEAD'); $table->string('status')->default('queued'); $table->boolean('is_webhook')->default(false); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('application_deployment_queues'); } }; ================================================ FILE: database/migrations/2023_06_22_131459_move_wildcard_to_server.php ================================================ dropColumn('wildcard_domain'); }); Schema::table('server_settings', function (Blueprint $table) { $table->string('wildcard_domain')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('project_settings', function (Blueprint $table) { $table->string('wildcard_domain')->nullable(); }); Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('wildcard_domain'); }); } }; ================================================ FILE: database/migrations/2023_06_23_084605_remove_wildcard_domain_from_instancesettings.php ================================================ dropColumn('wildcard_domain'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->string('wildcard_domain')->nullable(); }); } }; ================================================ FILE: database/migrations/2023_06_23_110548_next_channel_updates.php ================================================ boolean('next_channel')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('next_channel'); }); } }; ================================================ FILE: database/migrations/2023_06_23_114131_change_env_var_value_length.php ================================================ text('value')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->string('value')->nullable()->change(); }); } }; ================================================ FILE: database/migrations/2023_06_23_114132_remove_default_redirect_from_instance_settings.php ================================================ dropColumn('default_redirect_404'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->string('default_redirect_404')->nullable(); }); } }; ================================================ FILE: database/migrations/2023_06_23_114133_use_application_deployment_queues_as_activity.php ================================================ text('logs')->default(null)->nullable(); $table->string('current_process_id')->default(null)->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('logs'); $table->dropColumn('current_process_id'); }); } }; ================================================ FILE: database/migrations/2023_06_23_114134_add_disk_usage_percentage_to_servers.php ================================================ integer('cleanup_after_percentage')->default(80); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('cleanup_after_percentage'); }); } }; ================================================ FILE: database/migrations/2023_07_13_115117_create_subscriptions_table.php ================================================ id(); $table->string('lemon_subscription_id'); $table->string('lemon_order_id'); $table->string('lemon_product_id'); $table->string('lemon_variant_id'); $table->string('lemon_variant_name'); $table->string('lemon_customer_id'); $table->string('lemon_status'); $table->string('lemon_trial_ends_at')->nullable(); $table->string('lemon_renews_at'); $table->string('lemon_ends_at')->nullable(); $table->string('lemon_update_payment_menthod_url'); $table->foreignId('team_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('subscriptions'); } }; ================================================ FILE: database/migrations/2023_07_13_120719_create_webhooks_table.php ================================================ id(); $table->enum('status', ['pending', 'success', 'failed'])->default('pending'); $table->enum('type', ['github', 'gitlab', 'bitbucket', 'lemonsqueezy']); $table->longText('payload'); $table->longText('failure_reason')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('webhooks'); } }; ================================================ FILE: database/migrations/2023_07_13_120721_add_license_to_instance_settings.php ================================================ boolean('is_resale_license_active')->default(false); $table->longText('resale_license')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('is_resale_license_active'); $table->dropColumn('resale_license'); }); } }; ================================================ FILE: database/migrations/2023_07_27_182013_smtp_discord_schemaless_to_normal.php ================================================ boolean('smtp_enabled')->default(false); $table->string('smtp_from_address')->nullable(); $table->string('smtp_from_name')->nullable(); $table->string('smtp_recipients')->nullable(); $table->string('smtp_host')->nullable(); $table->integer('smtp_port')->nullable(); $table->string('smtp_encryption')->nullable(); $table->text('smtp_username')->nullable(); $table->text('smtp_password')->nullable(); $table->integer('smtp_timeout')->nullable(); $table->boolean('smtp_notifications_test')->default(true); $table->boolean('smtp_notifications_deployments')->default(false); $table->boolean('smtp_notifications_status_changes')->default(false); $table->boolean('discord_enabled')->default(false); $table->string('discord_webhook_url')->nullable(); $table->boolean('discord_notifications_test')->default(true); $table->boolean('discord_notifications_deployments')->default(true); $table->boolean('discord_notifications_status_changes')->default(true); }); $teams = Team::all(); foreach ($teams as $team) { $team->smtp_enabled = data_get($team, 'smtp.enabled', false); $team->smtp_from_address = data_get($team, 'smtp.from_address'); $team->smtp_from_name = data_get($team, 'smtp.from_name'); $team->smtp_recipients = data_get($team, 'smtp.recipients'); $team->smtp_host = data_get($team, 'smtp.host'); $team->smtp_port = data_get($team, 'smtp.port'); $team->smtp_encryption = data_get($team, 'smtp.encryption'); $team->smtp_username = data_get($team, 'smtp.username'); $team->smtp_password = data_get($team, 'smtp.password'); $team->smtp_timeout = data_get($team, 'smtp.timeout'); $team->smtp_notifications_test = data_get($team, 'smtp_notifications.test', true); $team->smtp_notifications_deployments = data_get($team, 'smtp_notifications.deployments', false); $team->smtp_notifications_status_changes = data_get($team, 'smtp_notifications.status_changes', false); $team->discord_enabled = data_get($team, 'discord.enabled', false); $team->discord_webhook_url = data_get($team, 'discord.webhook_url'); $team->discord_notifications_test = data_get($team, 'discord_notifications.test', true); $team->discord_notifications_deployments = data_get($team, 'discord_notifications.deployments', true); $team->discord_notifications_status_changes = data_get($team, 'discord_notifications.status_changes', true); $team->save(); } Schema::table('teams', function (Blueprint $table) { $table->dropColumn('smtp'); $table->dropColumn('smtp_notifications'); $table->dropColumn('discord'); $table->dropColumn('discord_notifications'); }); Schema::table('instance_settings', function (Blueprint $table) { $table->boolean('smtp_enabled')->default(false); $table->string('smtp_from_address')->nullable(); $table->string('smtp_from_name')->nullable(); $table->text('smtp_recipients')->nullable(); $table->string('smtp_host')->nullable(); $table->integer('smtp_port')->nullable(); $table->string('smtp_encryption')->nullable(); $table->text('smtp_username')->nullable(); $table->text('smtp_password')->nullable(); $table->integer('smtp_timeout')->nullable(); }); $instance_settings = InstanceSettings::all(); foreach ($instance_settings as $instance_setting) { $instance_setting->smtp_enabled = data_get($instance_setting, 'smtp.enabled', false); $instance_setting->smtp_from_address = data_get($instance_setting, 'smtp.from_address'); $instance_setting->smtp_from_name = data_get($instance_setting, 'smtp.from_name'); $instance_setting->smtp_recipients = data_get($instance_setting, 'smtp.recipients'); $instance_setting->smtp_host = data_get($instance_setting, 'smtp.host'); $instance_setting->smtp_port = data_get($instance_setting, 'smtp.port'); $instance_setting->smtp_encryption = data_get($instance_setting, 'smtp.encryption'); $instance_setting->smtp_username = data_get($instance_setting, 'smtp.username'); $instance_setting->smtp_password = data_get($instance_setting, 'smtp.password'); $instance_setting->smtp_timeout = data_get($instance_setting, 'smtp.timeout'); $instance_setting->save(); } Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('smtp'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->schemalessAttributes('smtp'); $table->schemalessAttributes('smtp_notifications'); $table->schemalessAttributes('discord'); $table->schemalessAttributes('discord_notifications'); }); $teams = Team::all(); foreach ($teams as $team) { $team->smtp = [ 'enabled' => $team->smtp_enabled, 'from_address' => $team->smtp_from_address, 'from_name' => $team->smtp_from_name, 'recipients' => $team->smtp_recipients, 'host' => $team->smtp_host, 'port' => $team->smtp_port, 'encryption' => $team->smtp_encryption, 'username' => $team->smtp_username, 'password' => $team->smtp_password, 'timeout' => $team->smtp_timeout, ]; $team->smtp_notifications = [ 'test' => $team->smtp_notifications_test, 'deployments' => $team->smtp_notifications_deployments, 'status_changes' => $team->smtp_notifications_status_changes, ]; $team->discord = [ 'enabled' => $team->discord_enabled, 'webhook_url' => $team->discord_webhook_url, ]; $team->discord_notifications = [ 'test' => $team->discord_notifications_test, 'deployments' => $team->discord_notifications_deployments, 'status_changes' => $team->discord_notifications_status_changes, ]; $team->save(); } Schema::table('teams', function (Blueprint $table) { $table->dropColumn('smtp_enabled'); $table->dropColumn('smtp_from_address'); $table->dropColumn('smtp_from_name'); $table->dropColumn('smtp_recipients'); $table->dropColumn('smtp_host'); $table->dropColumn('smtp_port'); $table->dropColumn('smtp_encryption'); $table->dropColumn('smtp_username'); $table->dropColumn('smtp_password'); $table->dropColumn('smtp_timeout'); $table->dropColumn('smtp_notifications_test'); $table->dropColumn('smtp_notifications_deployments'); $table->dropColumn('smtp_notifications_status_changes'); $table->dropColumn('discord_enabled'); $table->dropColumn('discord_webhook_url'); $table->dropColumn('discord_notifications_test'); $table->dropColumn('discord_notifications_deployments'); $table->dropColumn('discord_notifications_status_changes'); }); Schema::table('instance_settings', function (Blueprint $table) { $table->schemalessAttributes('smtp'); }); $instance_setting = instanceSettings(); $instance_setting->smtp = [ 'enabled' => $instance_setting->smtp_enabled, 'from_address' => $instance_setting->smtp_from_address, 'from_name' => $instance_setting->smtp_from_name, 'recipients' => $instance_setting->smtp_recipients, 'host' => $instance_setting->smtp_host, 'port' => $instance_setting->smtp_port, 'encryption' => $instance_setting->smtp_encryption, 'username' => $instance_setting->smtp_username, 'password' => $instance_setting->smtp_password, 'timeout' => $instance_setting->smtp_timeout, ]; $instance_setting->save(); Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('smtp_enabled'); $table->dropColumn('smtp_from_address'); $table->dropColumn('smtp_from_name'); $table->dropColumn('smtp_recipients'); $table->dropColumn('smtp_host'); $table->dropColumn('smtp_port'); $table->dropColumn('smtp_encryption'); $table->dropColumn('smtp_username'); $table->dropColumn('smtp_password'); $table->dropColumn('smtp_timeout'); }); } }; ================================================ FILE: database/migrations/2023_08_06_142951_add_description_field_to_applications_table.php ================================================ string('description')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('description'); }); } }; ================================================ FILE: database/migrations/2023_08_06_142952_remove_foreignId_environment_variables.php ================================================ dropColumn('service_id'); $table->dropColumn('database_id'); $table->foreignId('standalone_postgresql_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->foreignId('service_id')->nullable(); $table->foreignId('database_id')->nullable(); $table->dropColumn('standalone_postgresql_id'); }); } }; ================================================ FILE: database/migrations/2023_08_06_142954_add_readonly_localpersistentvolumes.php ================================================ boolean('is_readonly')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('local_persistent_volumes', function (Blueprint $table) { $table->dropColumn('is_readonly'); }); } }; ================================================ FILE: database/migrations/2023_08_07_073651_create_s3_storages_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->longText('description')->nullable(); $table->string('region')->default('us-east-1'); $table->longText('key'); $table->longText('secret'); $table->longText('bucket'); $table->longText('endpoint')->nullable(); $table->foreignId('team_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('s3_storages'); } }; ================================================ FILE: database/migrations/2023_08_07_142950_create_standalone_postgresqls_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->string('postgres_user')->default('postgres'); $table->text('postgres_password'); $table->string('postgres_db')->default('postgres'); $table->string('postgres_initdb_args')->nullable(); $table->string('postgres_host_auth_method')->nullable(); $table->json('init_scripts')->nullable(); $table->string('status')->default('exited'); $table->string('image')->default('postgres:15-alpine'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default('0'); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_postgresqls'); } }; ================================================ FILE: database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php ================================================ id(); $table->text('description')->nullable(); $table->string('uuid')->unique(); $table->boolean('enabled')->default(true); $table->boolean('save_s3')->default(true); $table->string('frequency'); $table->integer('number_of_backups_locally')->default(7); $table->morphs('database'); $table->foreignId('s3_storage_id')->nullable(); $table->foreignId('team_id'); $table->timestamps(); }); } public function down(): void { Schema::dropIfExists('scheduled_database_backups'); } }; ================================================ FILE: database/migrations/2023_08_10_113306_create_scheduled_database_backup_executions_table.php ================================================ id(); $table->string('uuid')->unique(); $table->enum('status', ['success', 'failed', 'running'])->default('running'); $table->longText('message')->nullable(); $table->text('size')->nullable(); $table->text('filename')->nullable(); $table->foreignId('scheduled_database_backup_id'); $table->timestamps(); }); } public function down(): void { Schema::dropIfExists('scheduled_database_backup_executions'); } }; ================================================ FILE: database/migrations/2023_08_10_201311_add_backup_notifications_to_teams.php ================================================ boolean('smtp_notifications_database_backups')->default(true)->after('smtp_notifications_status_changes'); $table->boolean('discord_notifications_database_backups')->default(true)->after('discord_notifications_status_changes'); }); } public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('smtp_notifications_database_backups'); $table->dropColumn('discord_notifications_database_backups'); }); } }; ================================================ FILE: database/migrations/2023_08_11_190528_add_dockerfile_to_applications_table.php ================================================ longText('dockerfile')->nullable(); }); } public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('dockerfile'); }); } }; ================================================ FILE: database/migrations/2023_08_15_095902_create_waitlists_table.php ================================================ id(); $table->string('uuid'); $table->string('type'); $table->string('email')->unique(); $table->boolean('verified')->default(false); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('waitlists'); } }; ================================================ FILE: database/migrations/2023_08_15_111125_update_users_table.php ================================================ boolean('force_password_reset')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('force_password_reset'); }); } }; ================================================ FILE: database/migrations/2023_08_15_111126_update_servers_add_unreachable_count_table.php ================================================ integer('unreachable_count')->default(0); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('unreachable_count'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071048_add_boarding_to_teams.php ================================================ boolean('show_boarding')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('show_boarding'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071049_update_webhooks_type.php ================================================ string('type')->change(); }); DB::statement('ALTER TABLE webhooks DROP CONSTRAINT webhooks_type_check'); } /** * Reverse the migrations. */ public function down(): void { Schema::table('webhooks', function (Blueprint $table) { $table->string('type')->change(); }); } }; ================================================ FILE: database/migrations/2023_08_22_071050_update_subscriptions_stripe.php ================================================ boolean('stripe_invoice_paid')->default(false); $table->string('stripe_subscription_id')->nullable(); $table->string('stripe_customer_id')->nullable(); $table->boolean('stripe_cancel_at_period_end')->default(false); $table->string('lemon_subscription_id')->nullable()->change(); $table->string('lemon_order_id')->nullable()->change(); $table->string('lemon_product_id')->nullable()->change(); $table->string('lemon_variant_id')->nullable()->change(); $table->string('lemon_variant_name')->nullable()->change(); $table->string('lemon_customer_id')->nullable()->change(); $table->string('lemon_status')->nullable()->change(); $table->string('lemon_renews_at')->nullable()->change(); $table->string('lemon_update_payment_menthod_url')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->dropColumn('stripe_invoice_paid'); $table->dropColumn('stripe_subscription_id'); $table->dropColumn('stripe_customer_id'); $table->dropColumn('stripe_cancel_at_period_end'); $table->string('lemon_subscription_id')->change(); $table->string('lemon_order_id')->change(); $table->string('lemon_product_id')->change(); $table->string('lemon_variant_id')->change(); $table->string('lemon_variant_name')->change(); $table->string('lemon_customer_id')->change(); $table->string('lemon_status')->change(); $table->string('lemon_renews_at')->change(); $table->string('lemon_update_payment_menthod_url')->change(); }); } }; ================================================ FILE: database/migrations/2023_08_22_071051_add_stripe_plan_to_subscriptions.php ================================================ string('stripe_plan_id')->nullable()->after('stripe_cancel_at_period_end'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->dropColumn('stripe_plan_id'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071052_add_resend_as_email.php ================================================ boolean('resend_enabled')->default(false); $table->text('resend_api_key')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('resend_enabled'); $table->dropColumn('resend_api_key'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071053_add_resend_as_email_to_teams.php ================================================ boolean('resend_enabled')->default(false); $table->text('resend_api_key')->nullable(); $table->boolean('use_instance_email_settings')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('resend_enabled'); $table->dropColumn('resend_api_key'); $table->dropColumn('use_instance_email_settings'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071054_add_stripe_reasons.php ================================================ string('stripe_feedback')->nullable()->after('stripe_cancel_at_period_end'); $table->string('stripe_comment')->nullable()->after('stripe_feedback'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->dropColumn('stripe_feedback'); $table->dropColumn('stripe_comment'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071055_add_discord_notifications_to_teams.php ================================================ boolean('telegram_enabled')->default(false); $table->text('telegram_token')->nullable(); $table->text('telegram_chat_id')->nullable(); $table->boolean('telegram_notifications_test')->default(true); $table->boolean('telegram_notifications_deployments')->default(true); $table->boolean('telegram_notifications_status_changes')->default(true); $table->boolean('telegram_notifications_database_backups')->default(true); }); } public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('telegram_enabled'); $table->dropColumn('telegram_token'); $table->dropColumn('telegram_chat_id'); $table->dropColumn('telegram_notifications_test'); $table->dropColumn('telegram_notifications_deployments'); $table->dropColumn('telegram_notifications_status_changes'); $table->dropColumn('telegram_notifications_database_backups'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071056_update_telegram_notifications.php ================================================ text('telegram_notifications_test_message_thread_id')->nullable(); $table->text('telegram_notifications_deployments_message_thread_id')->nullable(); $table->text('telegram_notifications_status_changes_message_thread_id')->nullable(); $table->text('telegram_notifications_database_backups_message_thread_id')->nullable(); }); } public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('telegram_message_thread_id'); $table->dropColumn('telegram_notifications_test_message_thread_id'); $table->dropColumn('telegram_notifications_deployments_message_thread_id'); $table->dropColumn('telegram_notifications_status_changes_message_thread_id'); $table->dropColumn('telegram_notifications_database_backups_message_thread_id'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071057_add_nixpkgsarchive_to_applications.php ================================================ string('nixpkgsarchive')->nullable(); }); } public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('nixpkgsarchive'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071058_add_nixpkgsarchive_to_applications_remove.php ================================================ dropColumn('nixpkgsarchive'); }); } public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->string('nixpkgsarchive')->nullable(); }); } }; ================================================ FILE: database/migrations/2023_08_22_071059_add_stripe_trial_ended.php ================================================ boolean('stripe_trial_already_ended')->default(false)->after('stripe_cancel_at_period_end'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->dropColumn('stripe_trial_already_ended'); }); } }; ================================================ FILE: database/migrations/2023_08_22_071060_change_invitation_link_length.php ================================================ text('link')->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('team_invitations', function (Blueprint $table) { $table->string('link')->change(); }); } }; ================================================ FILE: database/migrations/2023_09_20_082541_update_services_table.php ================================================ foreignId('server_id')->nullable(); $table->longText('description')->nullable(); $table->longText('docker_compose_raw'); $table->longText('docker_compose')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('services', function (Blueprint $table) { $table->dropColumn('server_id'); $table->dropColumn('description'); $table->dropColumn('docker_compose_raw'); $table->dropColumn('docker_compose'); }); } }; ================================================ FILE: database/migrations/2023_09_20_082733_create_service_databases_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('human_name')->nullable(); $table->longText('description')->nullable(); $table->longText('ports')->nullable(); $table->longText('exposes')->nullable(); $table->string('status')->default('exited'); $table->foreignId('service_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('service_databases'); } }; ================================================ FILE: database/migrations/2023_09_20_082737_create_service_applications_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('human_name')->nullable(); $table->longText('description')->nullable(); $table->string('fqdn')->unique()->nullable(); $table->longText('ports')->nullable(); $table->longText('exposes')->nullable(); $table->string('status')->default('exited'); $table->foreignId('service_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('service_applications'); } }; ================================================ FILE: database/migrations/2023_09_20_083549_update_environment_variables_table.php ================================================ foreignId('service_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('service_id'); }); } }; ================================================ FILE: database/migrations/2023_09_22_185356_create_local_file_volumes_table.php ================================================ id(); $table->string('uuid'); $table->mediumText('fs_path'); $table->string('mount_path'); $table->mediumText('content')->nullable(); $table->nullableMorphs('resource'); $table->unique(['mount_path', 'resource_id', 'resource_type']); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('local_file_volumes'); } }; ================================================ FILE: database/migrations/2023_09_23_111808_update_servers_with_cloudflared.php ================================================ boolean('is_cloudflare_tunnel')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_cloudflare_tunnel'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111809_remove_destination_from_services_table.php ================================================ dropColumn('destination_type'); $table->dropColumn('destination_id'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('services', function (Blueprint $table) { $table->morphs('destination'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111811_update_service_applications_table.php ================================================ boolean('exclude_from_status')->default(false); $table->boolean('required_fqdn')->default(false); $table->string('image')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('exclude_from_status'); $table->dropColumn('required_fqdn'); $table->dropColumn('image'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111812_update_service_databases_table.php ================================================ boolean('exclude_from_status')->default(false); $table->string('image')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('service_databases', function (Blueprint $table) { $table->dropColumn('exclude_from_status'); $table->dropColumn('image'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111813_update_users_databases_table.php ================================================ boolean('marketing_emails')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('marketing_emails'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111814_update_local_file_volumes_table.php ================================================ boolean('is_directory')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('local_file_volumes', function (Blueprint $table) { $table->dropColumn('is_directory'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111815_add_healthcheck_disable_to_apps_table.php ================================================ boolean('health_check_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('health_check_enabled'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111816_add_destination_to_services_table.php ================================================ nullableMorphs('destination'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('services', function (Blueprint $table) { $table->dropMorphs('destination'); }); } }; ================================================ FILE: database/migrations/2023_09_23_111817_use_instance_email_settings_by_default.php ================================================ boolean('use_instance_email_settings')->default(true)->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->boolean('use_instance_email_settings')->default(false)->change(); }); } }; ================================================ FILE: database/migrations/2023_09_23_111818_set_notifications_on_by_default.php ================================================ boolean('smtp_notifications_deployments')->default(true)->change(); $table->boolean('smtp_notifications_status_changes')->default(true)->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->boolean('smtp_notifications_deployments')->default(false)->change(); $table->boolean('smtp_notifications_status_changes')->default(false)->change(); }); } }; ================================================ FILE: database/migrations/2023_09_23_111819_add_server_emails.php ================================================ boolean('unreachable_email_sent')->default(false); $table->dropColumn('unreachable_count'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('unreachable_email_sent'); $table->integer('unreachable_count')->default(0); }); } }; ================================================ FILE: database/migrations/2023_10_08_111819_add_server_unreachable_count.php ================================================ integer('unreachable_count')->default(0); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('unreachable_count'); }); } }; ================================================ FILE: database/migrations/2023_10_10_100320_update_s3_storages_table.php ================================================ boolean('is_usable')->default(false); $table->boolean('unusable_email_sent')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('s3_storages', function (Blueprint $table) { $table->dropColumn('is_usable'); $table->dropColumn('unusable_email_sent'); }); } }; ================================================ FILE: database/migrations/2023_10_10_113144_add_dockerfile_location_applications_table.php ================================================ string('dockerfile_location')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('dockerfile_location'); }); } }; ================================================ FILE: database/migrations/2023_10_12_132430_create_standalone_redis_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->text('redis_password'); $table->longText('redis_conf')->nullable(); $table->string('status')->default('exited'); $table->string('image')->default('redis:7.2'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default('0'); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_redis'); } }; ================================================ FILE: database/migrations/2023_10_12_132431_add_standalone_redis_to_environment_variables_table.php ================================================ foreignId('standalone_redis_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('standalone_redis_id'); }); } }; ================================================ FILE: database/migrations/2023_10_12_132432_add_database_selection_to_backups.php ================================================ text('databases_to_backup')->nullable(); }); Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { $table->string('database_name')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('scheduled_database_backups', function (Blueprint $table) { $table->dropColumn('databases_to_backup'); }); Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { $table->dropColumn('database_name'); }); } }; ================================================ FILE: database/migrations/2023_10_18_072519_add_custom_labels_applications_table.php ================================================ text('custom_labels')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('custom_labels'); }); } }; ================================================ FILE: database/migrations/2023_10_19_101331_create_standalone_mongodbs_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->text('mongo_conf')->nullable(); $table->text('mongo_initdb_root_username')->default('root'); $table->text('mongo_initdb_root_password'); $table->text('mongo_initdb_database')->default('default'); $table->string('status')->default('exited'); $table->string('image')->default('mongo:7'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default('0'); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_mongodbs'); } }; ================================================ FILE: database/migrations/2023_10_19_101332_add_standalone_mongodb_to_environment_variables_table.php ================================================ foreignId('standalone_mongodb_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('standalone_mongodb_id'); }); } }; ================================================ FILE: database/migrations/2023_10_24_103548_create_standalone_mysqls_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->text('mysql_root_password'); $table->string('mysql_user')->default('mysql'); $table->text('mysql_password'); $table->string('mysql_database')->default('default'); $table->longText('mysql_conf')->nullable(); $table->string('status')->default('exited'); $table->string('image')->default('mysql:8'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default('0'); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_mysqls'); } }; ================================================ FILE: database/migrations/2023_10_24_120523_create_standalone_mariadbs_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->text('mariadb_root_password'); $table->string('mariadb_user')->default('mariadb'); $table->text('mariadb_password'); $table->string('mariadb_database')->default('default'); $table->longText('mariadb_conf')->nullable(); $table->string('status')->default('exited'); $table->string('image')->default('mariadb:11'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default('0'); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_mariadbs'); } }; ================================================ FILE: database/migrations/2023_10_24_120524_add_standalone_mysql_to_environment_variables_table.php ================================================ foreignId('standalone_mysql_id')->nullable(); $table->foreignId('standalone_mariadb_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('standalone_mysql_id'); $table->dropColumn('standalone_mariadb_id'); }); } }; ================================================ FILE: database/migrations/2023_10_24_124934_add_is_shown_once_to_environment_variables_table.php ================================================ boolean('is_shown_once')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('is_shown_once'); }); } }; ================================================ FILE: database/migrations/2023_11_01_100437_add_restart_to_deployment_queue.php ================================================ boolean('restart_only')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('restart_only'); }); } }; ================================================ FILE: database/migrations/2023_11_07_123731_add_target_build_dockerfile.php ================================================ string('dockerfile_target_build')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('dockerfile_target_build'); }); } }; ================================================ FILE: database/migrations/2023_11_08_112815_add_custom_config_standalone_postgresql.php ================================================ longText('postgres_conf')->nullable(); $table->string('image')->default('postgres:16-alpine')->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropColumn('postgres_conf'); $table->string('image')->default('postgres:15-alpine')->change(); }); } }; ================================================ FILE: database/migrations/2023_11_09_133332_add_public_port_to_service_databases.php ================================================ integer('public_port')->nullable(); $table->boolean('is_public')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('service_databases', function (Blueprint $table) { $table->dropColumn('public_port'); $table->dropColumn('is_public'); }); } }; ================================================ FILE: database/migrations/2023_11_12_180605_change_fqdn_to_longer_field.php ================================================ longText('fqdn')->nullable()->change(); }); Schema::table('application_previews', function (Blueprint $table) { $table->longText('fqdn')->nullable()->change(); }); Schema::table('service_applications', function (Blueprint $table) { $table->longText('fqdn')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->string('fqdn')->nullable()->change(); }); Schema::table('application_previews', function (Blueprint $table) { $table->string('fqdn')->nullable()->change(); }); Schema::table('service_applications', function (Blueprint $table) { $table->string('fqdn')->nullable()->change(); }); } }; ================================================ FILE: database/migrations/2023_11_13_133059_add_sponsorship_disable.php ================================================ boolean('is_notification_sponsorship_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('is_notification_sponsorship_enabled'); }); } }; ================================================ FILE: database/migrations/2023_11_14_103450_add_manual_webhook_secret.php ================================================ string('manual_webhook_secret_github')->nullable(); $table->string('manual_webhook_secret_gitlab')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('manual_webhook_secret_github'); $table->dropColumn('manual_webhook_secret_gitlab'); }); } }; ================================================ FILE: database/migrations/2023_11_14_121416_add_git_type.php ================================================ string('git_type')->nullable(); }); Schema::table('application_deployment_queues', function (Blueprint $table) { $table->string('git_type')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_previews', function (Blueprint $table) { $table->dropColumn('git_type'); }); Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('git_type'); }); } }; ================================================ FILE: database/migrations/2023_11_16_101819_add_high_disk_usage_notification.php ================================================ boolean('high_disk_usage_notification_sent')->default(false); $table->renameColumn('unreachable_email_sent', 'unreachable_notification_sent'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('high_disk_usage_notification_sent'); $table->renameColumn('unreachable_notification_sent', 'unreachable_email_sent'); }); } }; ================================================ FILE: database/migrations/2023_11_16_220647_add_log_drains.php ================================================ boolean('is_logdrain_newrelic_enabled')->default(false); $table->string('logdrain_newrelic_license_key')->nullable(); $table->string('logdrain_newrelic_base_uri')->nullable(); $table->boolean('is_logdrain_highlight_enabled')->default(false); $table->string('logdrain_highlight_project_id')->nullable(); $table->boolean('is_logdrain_axiom_enabled')->default(false); $table->string('logdrain_axiom_dataset_name')->nullable(); $table->string('logdrain_axiom_api_key')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_logdrain_newrelic_enabled'); $table->dropColumn('logdrain_newrelic_license_key'); $table->dropColumn('logdrain_newrelic_base_uri'); $table->dropColumn('is_logdrain_highlight_enabled'); $table->dropColumn('logdrain_highlight_project_id'); $table->dropColumn('is_logdrain_axiom_enabled'); $table->dropColumn('logdrain_axiom_dataset_name'); $table->dropColumn('logdrain_axiom_api_key'); }); } }; ================================================ FILE: database/migrations/2023_11_17_160437_add_drain_log_enable_by_service.php ================================================ boolean('is_log_drain_enabled')->default(false); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->boolean('is_log_drain_enabled')->default(false); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->boolean('is_log_drain_enabled')->default(false); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->boolean('is_log_drain_enabled')->default(false); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->boolean('is_log_drain_enabled')->default(false); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->boolean('is_log_drain_enabled')->default(false); }); Schema::table('service_applications', function (Blueprint $table) { $table->boolean('is_log_drain_enabled')->default(false); }); Schema::table('service_databases', function (Blueprint $table) { $table->boolean('is_log_drain_enabled')->default(false); }); Schema::table('servers', function (Blueprint $table) { $table->boolean('log_drain_notification_sent')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('service_databases', function (Blueprint $table) { $table->dropColumn('is_log_drain_enabled'); }); Schema::table('servers', function (Blueprint $table) { $table->dropColumn('log_drain_notification_sent'); }); } }; ================================================ FILE: database/migrations/2023_11_20_094628_add_gpu_settings.php ================================================ boolean('is_gpu_enabled')->default(false); $table->string('gpu_driver')->default('nvidia'); $table->string('gpu_count')->nullable(); $table->string('gpu_device_ids')->nullable(); $table->longText('gpu_options')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_gpu_enabled'); $table->dropColumn('gpu_driver'); $table->dropColumn('gpu_count'); $table->dropColumn('gpu_device_ids'); $table->dropColumn('gpu_options'); }); } }; ================================================ FILE: database/migrations/2023_11_21_121920_add_additional_destinations_to_apps.php ================================================ string('additional_destinations')->nullable()->after('destination'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('additional_destinations'); }); } }; ================================================ FILE: database/migrations/2023_11_24_080341_add_docker_compose_location.php ================================================ string('docker_compose_location')->nullable()->default('/docker-compose.yaml')->after('dockerfile_location'); $table->string('docker_compose_pr_location')->nullable()->default('/docker-compose.yaml')->after('docker_compose_location'); $table->longText('docker_compose')->nullable()->after('docker_compose_location'); $table->longText('docker_compose_pr')->nullable()->after('docker_compose_location'); $table->longText('docker_compose_raw')->nullable()->after('docker_compose'); $table->longText('docker_compose_pr_raw')->nullable()->after('docker_compose'); $table->text('docker_compose_domains')->nullable()->after('docker_compose_raw'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('docker_compose_location'); $table->dropColumn('docker_compose_pr_location'); $table->dropColumn('docker_compose'); $table->dropColumn('docker_compose_pr'); $table->dropColumn('docker_compose_raw'); $table->dropColumn('docker_compose_pr_raw'); $table->dropColumn('docker_compose_domains'); }); } }; ================================================ FILE: database/migrations/2023_11_28_143533_add_fields_to_swarm_dockers.php ================================================ string('network'); $table->unique(['server_id', 'network']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('swarm_dockers', function (Blueprint $table) { $table->dropColumn('network'); }); } }; ================================================ FILE: database/migrations/2023_11_29_075937_change_swarm_properties.php ================================================ renameColumn('is_part_of_swarm', 'is_swarm_manager'); $table->boolean('is_swarm_worker')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->renameColumn('is_swarm_manager', 'is_part_of_swarm'); $table->dropColumn('is_swarm_worker'); }); } }; ================================================ FILE: database/migrations/2023_12_01_091723_save_logs_view_settings.php ================================================ boolean('is_include_timestamps')->default(false); }); Schema::table('service_applications', function (Blueprint $table) { $table->boolean('is_include_timestamps')->default(false); }); Schema::table('service_databases', function (Blueprint $table) { $table->boolean('is_include_timestamps')->default(false); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->boolean('is_include_timestamps')->default(false); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->boolean('is_include_timestamps')->default(false); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->boolean('is_include_timestamps')->default(false); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->boolean('is_include_timestamps')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_include_timestamps'); }); Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('is_include_timestamps'); }); Schema::table('service_databases', function (Blueprint $table) { $table->dropColumn('is_include_timestamps'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->dropColumn('is_include_timestamps'); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropColumn('is_include_timestamps'); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropColumn('is_include_timestamps'); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->dropColumn('is_include_timestamps'); }); } }; ================================================ FILE: database/migrations/2023_12_01_095356_add_custom_fluentd_config_for_logdrains.php ================================================ boolean('is_logdrain_custom_enabled')->default(false); $table->text('logdrain_custom_config')->nullable(); $table->text('logdrain_custom_config_parser')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_logdrain_custom_enabled'); $table->dropColumn('logdrain_custom_config'); $table->dropColumn('logdrain_custom_config_parser'); }); } }; ================================================ FILE: database/migrations/2023_12_08_162228_add_soft_delete_services.php ================================================ softDeletes(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('services', function (Blueprint $table) { $table->dropSoftDeletes(); }); } }; ================================================ FILE: database/migrations/2023_12_11_103611_add_realtime_connection_problem.php ================================================ boolean('is_notification_realtime_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('is_notification_realtime_enabled'); }); } }; ================================================ FILE: database/migrations/2023_12_13_110214_add_soft_deletes.php ================================================ softDeletes(); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('service_applications', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('service_databases', function (Blueprint $table) { $table->softDeletes(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropSoftDeletes(); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropSoftDeletes(); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropSoftDeletes(); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->dropSoftDeletes(); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->dropSoftDeletes(); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->dropSoftDeletes(); }); Schema::table('service_applications', function (Blueprint $table) { $table->dropSoftDeletes(); }); Schema::table('service_databases', function (Blueprint $table) { $table->dropSoftDeletes(); }); } }; ================================================ FILE: database/migrations/2023_12_17_155616_add_custom_docker_compose_start_command.php ================================================ string('docker_compose_custom_start_command')->nullable(); $table->string('docker_compose_custom_build_command')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('docker_compose_custom_start_command'); $table->dropColumn('docker_compose_custom_build_command'); }); } }; ================================================ FILE: database/migrations/2023_12_18_093514_add_swarm_related_things.php ================================================ integer('swarm_replicas')->default(1); $table->text('swarm_placement_constraints')->nullable(); }); Schema::table('application_settings', function (Blueprint $table) { $table->boolean('is_swarm_only_worker_nodes')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('swarm_replicas'); $table->dropColumn('swarm_placement_constraints'); }); Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_swarm_only_worker_nodes'); }); } }; ================================================ FILE: database/migrations/2023_12_19_124111_add_swarm_cluster_grouping.php ================================================ integer('swarm_cluster')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('swarm_cluster'); }); } }; ================================================ FILE: database/migrations/2023_12_30_134507_add_description_to_environments.php ================================================ string('description')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environments', function (Blueprint $table) { $table->dropColumn('description'); }); } }; ================================================ FILE: database/migrations/2023_12_31_173041_create_scheduled_tasks_table.php ================================================ id(); $table->string('uuid')->unique(); $table->boolean('enabled')->default(true); $table->string('name'); $table->string('command'); $table->string('frequency'); $table->string('container')->nullable(); $table->timestamps(); $table->foreignId('application_id')->nullable(); $table->foreignId('service_id')->nullable(); $table->foreignId('team_id'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('scheduled_tasks'); } }; ================================================ FILE: database/migrations/2024_01_01_231053_create_scheduled_task_executions_table.php ================================================ id(); $table->string('uuid')->unique(); $table->enum('status', ['success', 'failed', 'running'])->default('running'); $table->longText('message')->nullable(); $table->foreignId('scheduled_task_id'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('scheduled_task_executions'); } }; ================================================ FILE: database/migrations/2024_01_02_113855_add_raw_compose_deployment.php ================================================ boolean('is_raw_compose_deployment_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_raw_compose_deployment_enabled'); }); } }; ================================================ FILE: database/migrations/2024_01_12_123422_update_cpuset_limits.php ================================================ string('limits_cpuset')->nullable()->default(null)->change(); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default(null)->change(); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default(null)->change(); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default(null)->change(); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default(null)->change(); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default(null)->change(); }); Application::where('limits_cpuset', '0')->update(['limits_cpuset' => null]); StandalonePostgresql::where('limits_cpuset', '0')->update(['limits_cpuset' => null]); StandaloneRedis::where('limits_cpuset', '0')->update(['limits_cpuset' => null]); StandaloneMariadb::where('limits_cpuset', '0')->update(['limits_cpuset' => null]); StandaloneMysql::where('limits_cpuset', '0')->update(['limits_cpuset' => null]); StandaloneMongodb::where('limits_cpuset', '0')->update(['limits_cpuset' => null]); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default('0')->change(); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default('0')->change(); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default('0')->change(); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default('0')->change(); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default('0')->change(); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->string('limits_cpuset')->nullable()->default('0')->change(); }); Application::where('limits_cpuset', null)->update(['limits_cpuset' => '0']); StandalonePostgresql::where('limits_cpuset', null)->update(['limits_cpuset' => '0']); StandaloneRedis::where('limits_cpuset', null)->update(['limits_cpuset' => '0']); StandaloneMariadb::where('limits_cpuset', null)->update(['limits_cpuset' => '0']); StandaloneMysql::where('limits_cpuset', null)->update(['limits_cpuset' => '0']); StandaloneMongodb::where('limits_cpuset', null)->update(['limits_cpuset' => '0']); } }; ================================================ FILE: database/migrations/2024_01_15_084609_add_custom_dns_server.php ================================================ boolean('is_dns_validation_enabled')->default(true); $table->string('custom_dns_servers')->nullable()->default('1.1.1.1'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('is_dns_validation_enabled'); $table->dropColumn('custom_dns_servers'); }); } }; ================================================ FILE: database/migrations/2024_01_16_115005_add_build_server_enable.php ================================================ boolean('is_build_server_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_build_server_enabled'); }); } }; ================================================ FILE: database/migrations/2024_01_21_130328_add_docker_network_to_services.php ================================================ boolean('connect_to_docker_network')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('services', function (Blueprint $table) { $table->dropColumn('connect_to_docker_network'); }); } }; ================================================ FILE: database/migrations/2024_01_23_095832_add_manual_webhook_secret_bitbucket.php ================================================ string('manual_webhook_secret_bitbucket')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('manual_webhook_secret_bitbucket'); }); } }; ================================================ FILE: database/migrations/2024_01_23_113129_create_shared_environment_variables_table.php ================================================ id(); $table->string('key'); $table->string('value')->nullable(); $table->boolean('is_shown_once')->default(false); $table->enum('type', ['team', 'project', 'environment'])->default('team'); $table->foreignId('team_id')->constrained()->onDelete('cascade'); $table->foreignId('project_id')->nullable()->constrained()->onDelete('cascade'); $table->foreignId('environment_id')->nullable()->constrained()->onDelete('cascade'); $table->unique(['key', 'project_id', 'team_id']); $table->unique(['key', 'environment_id', 'team_id']); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('shared_environment_variables'); } }; ================================================ FILE: database/migrations/2024_01_24_095449_add_concurrent_number_of_builds_per_server.php ================================================ integer('concurrent_builds')->default(2); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('concurrent_builds'); }); } }; ================================================ FILE: database/migrations/2024_01_25_073212_add_server_id_to_queues.php ================================================ integer('server_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('server_id'); }); } }; ================================================ FILE: database/migrations/2024_01_27_164724_add_application_name_and_deployment_url_to_queue.php ================================================ string('application_name')->nullable(); $table->string('server_name')->nullable(); $table->string('deployment_url')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('application_name'); $table->dropColumn('server_name'); $table->dropColumn('deployment_url'); }); } }; ================================================ FILE: database/migrations/2024_01_29_072322_change_env_variable_length.php ================================================ text('value')->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('shared_environment_variables', function (Blueprint $table) { $table->string('value')->change(); }); } }; ================================================ FILE: database/migrations/2024_01_29_145200_add_custom_docker_run_options.php ================================================ string('custom_docker_run_options')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); } }; ================================================ FILE: database/migrations/2024_02_01_111228_create_tags_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name')->unique(); $table->foreignId('team_id')->nullable()->constrained()->onDelete('cascade'); $table->timestamps(); }); Schema::create('taggables', function (Blueprint $table) { $table->unsignedBigInteger('tag_id'); $table->unsignedBigInteger('taggable_id'); $table->string('taggable_type'); $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade'); $table->unique(['tag_id', 'taggable_id', 'taggable_type'], 'taggable_unique'); // Composite unique index }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('taggables'); Schema::dropIfExists('tags'); } }; ================================================ FILE: database/migrations/2024_02_05_105215_add_destination_to_app_deployments.php ================================================ string('destination_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('destination_id'); }); } }; ================================================ FILE: database/migrations/2024_02_06_132748_add_additional_destinations.php ================================================ id(); $table->foreignId('application_id')->constrained()->onDelete('cascade'); $table->foreignId('server_id')->constrained()->onDelete('cascade'); $table->string('status')->default('exited'); $table->foreignId('standalone_docker_id')->constrained()->onDelete('cascade'); $table->timestamps(); }); Schema::table('applications', function (Blueprint $table) { $table->dropColumn('additional_destinations'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('additional_destinations'); Schema::table('applications', function (Blueprint $table) { $table->string('additional_destinations')->nullable()->after('destination'); }); } }; ================================================ FILE: database/migrations/2024_02_08_075523_add_post_deployment_to_applications.php ================================================ string('post_deployment_command')->nullable(); $table->string('post_deployment_command_container')->nullable(); $table->string('pre_deployment_command')->nullable(); $table->string('pre_deployment_command_container')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('post_deployment_command'); $table->dropColumn('post_deployment_command_container'); $table->dropColumn('pre_deployment_command'); $table->dropColumn('pre_deployment_command_container'); }); } }; ================================================ FILE: database/migrations/2024_02_08_112304_add_dynamic_timeout_for_deployments.php ================================================ integer('dynamic_timeout')->default(3600); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('dynamic_timeout'); }); } }; ================================================ FILE: database/migrations/2024_02_15_101921_add_consistent_application_container_name.php ================================================ boolean('is_consistent_container_name_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_consistent_container_name_enabled'); }); } }; ================================================ FILE: database/migrations/2024_02_15_192025_add_is_gzip_enabled_to_services.php ================================================ boolean('is_gzip_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('is_gzip_enabled'); }); } }; ================================================ FILE: database/migrations/2024_02_20_165045_add_permissions_to_github_app.php ================================================ string('contents')->nullable(); $table->string('metadata')->nullable(); $table->string('pull_requests')->nullable(); $table->string('administration')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('github_apps', function (Blueprint $table) { $table->dropColumn('contents'); $table->dropColumn('metadata'); $table->dropColumn('pull_requests'); $table->dropColumn('administration'); }); } }; ================================================ FILE: database/migrations/2024_02_22_090900_add_only_this_server_deployment.php ================================================ boolean('only_this_server')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('only_this_server'); }); } }; ================================================ FILE: database/migrations/2024_02_23_143119_add_custom_server_limits_to_teams_ultimate.php ================================================ integer('custom_server_limit')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('custom_server_limit'); }); } }; ================================================ FILE: database/migrations/2024_02_25_222150_add_server_force_disabled_field.php ================================================ boolean('force_disabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('force_disabled'); }); } }; ================================================ FILE: database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php ================================================ boolean('is_gzip_enabled')->default(true); $table->boolean('is_stripprefix_enabled')->default(true); }); Schema::table('service_applications', function (Blueprint $table) { $table->boolean('is_stripprefix_enabled')->default(true); }); Schema::table('service_databases', function (Blueprint $table) { $table->boolean('is_gzip_enabled')->default(true); $table->boolean('is_stripprefix_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_gzip_enabled'); $table->dropColumn('is_stripprefix_enabled'); }); Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('is_stripprefix_enabled'); }); Schema::table('service_databases', function (Blueprint $table) { $table->dropColumn('is_gzip_enabled'); $table->dropColumn('is_stripprefix_enabled'); }); } }; ================================================ FILE: database/migrations/2024_03_07_115054_add_notifications_notification_disable.php ================================================ boolean('is_notification_notifications_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('is_notification_notifications_enabled'); }); } }; ================================================ FILE: database/migrations/2024_03_08_180457_nullable_password.php ================================================ string('password')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->string('password')->nullable(false)->change(); }); } }; ================================================ FILE: database/migrations/2024_03_11_150013_create_oauth_settings.php ================================================ id(); $table->string('provider')->unique(); $table->boolean('enabled')->default(false); $table->string('client_id')->nullable(); $table->text('client_secret')->nullable(); $table->string('redirect_uri')->nullable(); $table->string('tenant')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('oauth_settings'); } }; ================================================ FILE: database/migrations/2024_03_14_214402_add_multiline_envs.php ================================================ boolean('is_multiline')->default(false); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->boolean('is_multiline')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('is_multiline'); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->dropColumn('is_multiline'); }); } }; ================================================ FILE: database/migrations/2024_03_18_101440_add_version_of_envs.php ================================================ string('version')->default('4.0.0-beta.239'); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->string('version')->default('4.0.0-beta.239'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('version'); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->dropColumn('version'); }); } }; ================================================ FILE: database/migrations/2024_03_22_080914_remove_popup_notifications.php ================================================ dropColumn('is_notification_sponsorship_enabled'); $table->dropColumn('is_notification_notifications_enabled'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->boolean('is_notification_sponsorship_enabled')->default(true); $table->boolean('is_notification_notifications_enabled')->default(true); }); } }; ================================================ FILE: database/migrations/2024_03_26_122110_remove_realtime_notifications.php ================================================ dropColumn('is_notification_realtime_enabled'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->boolean('is_notification_realtime_enabled')->default(true); }); } }; ================================================ FILE: database/migrations/2024_03_28_114620_add_watch_paths_to_apps.php ================================================ longText('watch_paths')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('watch_paths'); }); } }; ================================================ FILE: database/migrations/2024_04_09_095517_make_custom_docker_commands_longer.php ================================================ text('custom_docker_run_options')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->string('custom_docker_run_options')->nullable()->change(); }); } }; ================================================ FILE: database/migrations/2024_04_10_071920_create_standalone_keydbs_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->text('keydb_password'); $table->longText('keydb_conf')->nullable(); $table->boolean('is_log_drain_enabled')->default(false); $table->boolean('is_include_timestamps')->default(false); $table->softDeletes(); $table->string('status')->default('exited'); $table->string('image')->default('eqalpha/keydb:latest'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default(null); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); Schema::table('environment_variables', function (Blueprint $table) { $table->foreignId('standalone_keydb_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_keydbs'); Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('standalone_keydb_id'); }); } }; ================================================ FILE: database/migrations/2024_04_10_082220_create_standalone_dragonflies_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->text('dragonfly_password'); $table->boolean('is_log_drain_enabled')->default(false); $table->boolean('is_include_timestamps')->default(false); $table->softDeletes(); $table->string('status')->default('exited'); $table->string('image')->default('docker.dragonflydb.io/dragonflydb/dragonfly'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default(null); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); Schema::table('environment_variables', function (Blueprint $table) { $table->foreignId('standalone_dragonfly_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_dragonflies'); Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('standalone_dragonfly_id'); }); } }; ================================================ FILE: database/migrations/2024_04_10_091519_create_standalone_clickhouses_table.php ================================================ id(); $table->string('uuid')->unique(); $table->string('name'); $table->string('description')->nullable(); $table->string('clickhouse_admin_user')->default('default'); $table->text('clickhouse_admin_password'); $table->boolean('is_log_drain_enabled')->default(false); $table->boolean('is_include_timestamps')->default(false); $table->softDeletes(); $table->string('status')->default('exited'); $table->string('image')->default('bitnami/clickhouse'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); $table->text('ports_mappings')->nullable(); $table->string('limits_memory')->default('0'); $table->string('limits_memory_swap')->default('0'); $table->integer('limits_memory_swappiness')->default(60); $table->string('limits_memory_reservation')->default('0'); $table->string('limits_cpus')->default('0'); $table->string('limits_cpuset')->nullable()->default(null); $table->integer('limits_cpu_shares')->default(1024); $table->timestamp('started_at')->nullable(); $table->morphs('destination'); $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); Schema::table('environment_variables', function (Blueprint $table) { $table->foreignId('standalone_clickhouse_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('standalone_clickhouses'); Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('standalone_clickhouse_id'); }); } }; ================================================ FILE: database/migrations/2024_04_10_124015_add_permission_local_file_volumes.php ================================================ string('chown')->nullable(); $table->string('chmod')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('local_file_volumes', function (Blueprint $table) { $table->dropColumn('chown'); $table->dropColumn('chmod'); }); } }; ================================================ FILE: database/migrations/2024_04_12_092337_add_config_hash_to_other_resources.php ================================================ string('config_hash')->nullable(); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); Schema::table('services', function (Blueprint $table) { $table->string('config_hash')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->dropColumn('config_hash'); }); Schema::table('services', function (Blueprint $table) { $table->dropColumn('config_hash'); }); } }; ================================================ FILE: database/migrations/2024_04_15_094703_add_literal_variables.php ================================================ boolean('is_literal')->default(false); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->boolean('is_literal')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('is_literal'); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->dropColumn('is_literal'); }); } }; ================================================ FILE: database/migrations/2024_04_16_083919_add_service_type_on_creation.php ================================================ string('service_type')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('services', function (Blueprint $table) { $table->dropColumn('service_type'); }); } }; ================================================ FILE: database/migrations/2024_04_17_132541_add_rollback_queues.php ================================================ boolean('rollback')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('rollback'); }); } }; ================================================ FILE: database/migrations/2024_04_25_073615_add_docker_network_to_application_settings.php ================================================ boolean('connect_to_docker_network')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('connect_to_docker_network'); }); } }; ================================================ FILE: database/migrations/2024_04_29_111956_add_custom_hc_indicator_apps.php ================================================ boolean('custom_healthcheck_found')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('custom_healthcheck_found'); }); } }; ================================================ FILE: database/migrations/2024_05_06_093236_add_custom_name_to_application_settings.php ================================================ string('custom_internal_name')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('custom_internal_name'); }); } }; ================================================ FILE: database/migrations/2024_05_07_124019_add_server_metrics.php ================================================ boolean('is_metrics_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('is_metrics_enabled'); }); } }; ================================================ FILE: database/migrations/2024_05_10_085215_make_stripe_comment_longer.php ================================================ longText('stripe_comment')->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->string('stripe_comment')->change(); }); } }; ================================================ FILE: database/migrations/2024_05_15_091757_add_commit_message_to_app_deployment_queue.php ================================================ string('commit_message', 50)->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('commit_message'); }); } }; ================================================ FILE: database/migrations/2024_05_15_151236_add_container_escape_toggle.php ================================================ boolean('is_container_label_escape_enabled')->default(true); }); Schema::table('services', function (Blueprint $table) { $table->boolean('is_container_label_escape_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_container_label_escape_enabled'); }); Schema::table('services', function (Blueprint $table) { $table->dropColumn('is_container_label_escape_enabled'); }); } }; ================================================ FILE: database/migrations/2024_05_17_082012_add_env_sorting_toggle.php ================================================ boolean('is_env_sorting_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_env_sorting_enabled'); }); } }; ================================================ FILE: database/migrations/2024_05_21_125739_add_scheduled_tasks_notification_to_teams.php ================================================ boolean('telegram_notifications_scheduled_tasks')->default(true); $table->boolean('smtp_notifications_scheduled_tasks')->default(false)->after('smtp_notifications_status_changes'); $table->boolean('discord_notifications_scheduled_tasks')->default(true)->after('discord_notifications_status_changes'); $table->text('telegram_notifications_scheduled_tasks_thread_id')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('telegram_notifications_scheduled_tasks'); $table->dropColumn('smtp_notifications_scheduled_tasks'); $table->dropColumn('discord_notifications_scheduled_tasks'); $table->dropColumn('telegram_notifications_scheduled_tasks_thread_id'); }); } }; ================================================ FILE: database/migrations/2024_05_22_103942_change_pre_post_deployment_commands_length_in_applications.php ================================================ text('post_deployment_command')->nullable()->change(); $table->text('pre_deployment_command')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->string('post_deployment_command')->nullable()->change(); $table->string('pre_deployment_command')->nullable()->change(); }); } }; ================================================ FILE: database/migrations/2024_05_23_091713_add_gitea_webhook_to_applications.php ================================================ string('manual_webhook_secret_gitea')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('manual_webhook_secret_gitea'); }); } }; ================================================ FILE: database/migrations/2024_06_05_101019_add_docker_compose_pr_domains.php ================================================ text('docker_compose_domains')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_previews', function (Blueprint $table) { $table->dropColumn('docker_compose_domains'); }); } }; ================================================ FILE: database/migrations/2024_06_06_103938_change_pr_issue_commend_id_type.php ================================================ string('pull_request_issue_comment_id')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_previews', function (Blueprint $table) { $table->integer('pull_request_issue_comment_id')->nullable()->change(); }); } }; ================================================ FILE: database/migrations/2024_06_11_081614_add_www_non_www_redirect.php ================================================ enum('redirect', ['www', 'non-www', 'both'])->default('both')->after('domain'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('redirect'); }); } }; ================================================ FILE: database/migrations/2024_06_18_105948_move_server_metrics.php ================================================ dropColumn('is_metrics_enabled'); }); Schema::table('server_settings', function (Blueprint $table) { $table->boolean('is_metrics_enabled')->default(false); $table->integer('metrics_refresh_rate_seconds')->default(5); $table->integer('metrics_history_days')->default(30); $table->string('metrics_token')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->boolean('is_metrics_enabled')->default(true); }); Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_metrics_enabled'); $table->dropColumn('metrics_refresh_rate_seconds'); $table->dropColumn('metrics_history_days'); $table->dropColumn('metrics_token'); }); } }; ================================================ FILE: database/migrations/2024_06_20_102551_add_server_api_sentinel.php ================================================ boolean('is_server_api_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_server_api_enabled'); }); } }; ================================================ FILE: database/migrations/2024_06_21_143358_add_api_deployment_type.php ================================================ boolean('is_api')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('is_api'); }); } }; ================================================ FILE: database/migrations/2024_06_22_081140_alter_instance_settings_add_instance_name.php ================================================ string('instance_name')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('instance_name'); }); } }; ================================================ FILE: database/migrations/2024_06_25_184323_update_db.php ================================================ dropColumn('docker_compose_pr_location'); $table->dropColumn('docker_compose_pr'); $table->dropColumn('docker_compose_pr_raw'); }); Schema::table('subscriptions', function (Blueprint $table) { $table->dropColumn('lemon_subscription_id'); $table->dropColumn('lemon_order_id'); $table->dropColumn('lemon_product_id'); $table->dropColumn('lemon_variant_id'); $table->dropColumn('lemon_variant_name'); $table->dropColumn('lemon_customer_id'); $table->dropColumn('lemon_status'); $table->dropColumn('lemon_renews_at'); $table->dropColumn('lemon_update_payment_menthod_url'); $table->dropColumn('lemon_trial_ends_at'); $table->dropColumn('lemon_ends_at'); }); Schema::table('environment_variables', function (Blueprint $table) { $table->string('uuid')->nullable()->after('id'); }); EnvironmentVariable::all()->each(function (EnvironmentVariable $environmentVariable) { $environmentVariable->update([ 'uuid' => (string) new Cuid2, ]); }); Schema::table('environment_variables', function (Blueprint $table) { $table->string('uuid')->nullable(false)->change(); }); Schema::table('server_settings', function (Blueprint $table) { $table->integer('metrics_history_days')->default(7)->change(); }); DB::table('server_settings')->update(['metrics_history_days' => 7]); } catch (\Exception $e) { Log::error('Error updating db: '.$e->getMessage()); } } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->string('docker_compose_pr_location')->nullable()->default('/docker-compose.yaml')->after('docker_compose_location'); $table->longText('docker_compose_pr')->nullable()->after('docker_compose_location'); $table->longText('docker_compose_pr_raw')->nullable()->after('docker_compose'); }); Schema::table('subscriptions', function (Blueprint $table) { $table->string('lemon_subscription_id')->nullable()->after('stripe_subscription_id'); $table->string('lemon_order_id')->nullable()->after('lemon_subscription_id'); $table->string('lemon_product_id')->nullable()->after('lemon_order_id'); $table->string('lemon_variant_id')->nullable()->after('lemon_product_id'); $table->string('lemon_variant_name')->nullable()->after('lemon_variant_id'); $table->string('lemon_customer_id')->nullable()->after('lemon_variant_name'); $table->string('lemon_status')->nullable()->after('lemon_customer_id'); $table->timestamp('lemon_renews_at')->nullable()->after('lemon_status'); $table->string('lemon_update_payment_menthod_url')->nullable()->after('lemon_renews_at'); $table->timestamp('lemon_trial_ends_at')->nullable()->after('lemon_update_payment_menthod_url'); $table->timestamp('lemon_ends_at')->nullable()->after('lemon_trial_ends_at'); }); Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('uuid'); }); Schema::table('server_settings', function (Blueprint $table) { $table->integer('metrics_history_days')->default(30)->change(); }); Server::all()->each(function (Server $server) { $server->settings->update([ 'metrics_history_days' => 30, ]); }); } }; ================================================ FILE: database/migrations/2024_07_01_115528_add_is_api_allowed_and_iplist.php ================================================ boolean('is_api_enabled')->default(true); $table->text('allowed_ips')->nullable(); }); } public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('is_api_enabled'); $table->dropColumn('allowed_ips'); }); } }; ================================================ FILE: database/migrations/2024_07_05_120217_remove_unique_from_tag_names.php ================================================ dropUnique(['name']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('tags', function (Blueprint $table) { $table->unique(['name']); }); } }; ================================================ FILE: database/migrations/2024_07_11_083719_application_compose_versions.php ================================================ string('compose_parsing_version')->default('1'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('compose_parsing_version'); }); } }; ================================================ FILE: database/migrations/2024_07_17_123828_add_is_container_labels_readonly.php ================================================ boolean('is_container_label_readonly_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_container_label_readonly_enabled'); }); } }; ================================================ FILE: database/migrations/2024_07_18_110424_create_application_settings_is_preserve_repository_enabled.php ================================================ boolean('is_preserve_repository_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_preserve_repository_enabled'); }); } }; ================================================ FILE: database/migrations/2024_07_18_123458_add_force_cleanup_server.php ================================================ boolean('is_force_cleanup_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_force_cleanup_enabled'); }); } }; ================================================ FILE: database/migrations/2024_07_19_132617_disable_healtcheck_by_default.php ================================================ boolean('health_check_enabled')->default(false)->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->boolean('health_check_enabled')->default(true)->change(); }); } }; ================================================ FILE: database/migrations/2024_07_23_112710_add_validation_logs_to_servers.php ================================================ text('validation_logs')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('validation_logs'); }); } }; ================================================ FILE: database/migrations/2024_08_05_142659_add_update_frequency_settings.php ================================================ string('auto_update_frequency')->default('0 0 * * *'); $table->string('update_check_frequency')->default('0 * * * *'); $table->boolean('new_version_available')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('update_check_frequency'); $table->dropColumn('auto_update_frequency'); $table->dropColumn('new_version_available'); }); } }; ================================================ FILE: database/migrations/2024_08_07_155324_add_proxy_label_chooser.php ================================================ boolean('generate_exact_labels')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('generate_exact_labels'); }); } }; ================================================ FILE: database/migrations/2024_08_09_215659_add_server_cleanup_fields_to_server_settings_table.php ================================================ boolean('force_docker_cleanup')->default(false); $table->string('docker_cleanup_frequency')->default('*/10 * * * *'); $table->integer('docker_cleanup_threshold')->default(80); // Remove old columns $table->dropColumn('cleanup_after_percentage'); $table->dropColumn('is_force_cleanup_enabled'); }); foreach ($serverSettings as $serverSetting) { $serverSetting->force_docker_cleanup = $serverSetting->is_force_cleanup_enabled; $serverSetting->docker_cleanup_threshold = $serverSetting->cleanup_after_percentage; $serverSetting->save(); } } /** * Reverse the migrations. * * @return void */ public function down() { $serverSettings = ServerSetting::all(); Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('force_docker_cleanup'); $table->dropColumn('docker_cleanup_frequency'); $table->dropColumn('docker_cleanup_threshold'); // Add back old columns $table->integer('cleanup_after_percentage')->default(80); $table->boolean('force_server_cleanup')->default(false); $table->boolean('is_force_cleanup_enabled')->default(false); }); foreach ($serverSettings as $serverSetting) { $serverSetting->is_force_cleanup_enabled = $serverSetting->force_docker_cleanup; $serverSetting->cleanup_after_percentage = $serverSetting->docker_cleanup_threshold; $serverSetting->save(); } } } ================================================ FILE: database/migrations/2024_08_12_131659_add_local_file_volume_based_on_git.php ================================================ boolean('is_based_on_git')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('local_file_volumes', function (Blueprint $table) { $table->dropColumn('is_based_on_git'); }); } }; ================================================ FILE: database/migrations/2024_08_12_155023_add_timezone_to_server_and_instance_settings.php ================================================ string('server_timezone')->default(''); }); Schema::table('instance_settings', function (Blueprint $table) { $table->string('instance_timezone')->default('UTC'); }); } public function down() { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('server_timezone'); }); Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('instance_timezone'); }); } } ================================================ FILE: database/migrations/2024_08_14_183120_add_order_to_environment_variables_table.php ================================================ integer('order')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('order'); }); } }; ================================================ FILE: database/migrations/2024_08_15_115907_add_build_server_id_to_deployment_queue.php ================================================ integer('build_server_id')->nullable()->after('server_id'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('build_server_id'); }); } }; ================================================ FILE: database/migrations/2024_08_16_105649_add_custom_docker_options_to_dbs.php ================================================ text('custom_docker_run_options')->nullable(); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->text('custom_docker_run_options')->nullable(); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->text('custom_docker_run_options')->nullable(); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->text('custom_docker_run_options')->nullable(); }); Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->text('custom_docker_run_options')->nullable(); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->text('custom_docker_run_options')->nullable(); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->text('custom_docker_run_options')->nullable(); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->text('custom_docker_run_options')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->dropColumn('custom_docker_run_options'); }); } }; ================================================ FILE: database/migrations/2024_08_27_090528_add_compose_parsing_version_to_services.php ================================================ string('compose_parsing_version')->default('2'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('services', function (Blueprint $table) { $table->dropColumn('compose_parsing_version'); }); } }; ================================================ FILE: database/migrations/2024_09_05_085700_add_helper_version_to_instance_settings.php ================================================ string('helper_version')->default('1.0.0'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('helper_version'); }); } }; ================================================ FILE: database/migrations/2024_09_06_062534_change_server_cleanup_to_forced.php ================================================ boolean('force_docker_cleanup')->default(true)->change(); }); $serverSettings = ServerSetting::all(); foreach ($serverSettings as $serverSetting) { if ($serverSetting->force_docker_cleanup === false) { $serverSetting->force_docker_cleanup = true; $serverSetting->docker_cleanup_frequency = '*/10 * * * *'; $serverSetting->save(); } } } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->boolean('force_docker_cleanup')->default(false)->change(); }); } }; ================================================ FILE: database/migrations/2024_09_07_185402_change_cleanup_schedule.php ================================================ string('docker_cleanup_frequency')->default('0 0 * * *')->change(); }); $serverSettings = ServerSetting::all(); foreach ($serverSettings as $serverSetting) { if ($serverSetting->force_docker_cleanup && $serverSetting->docker_cleanup_frequency === '*/10 * * * *') { $serverSetting->docker_cleanup_frequency = '0 0 * * *'; $serverSetting->save(); } } } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->string('docker_cleanup_frequency')->default('*/10 * * * *')->change(); }); } }; ================================================ FILE: database/migrations/2024_09_08_130756_update_server_settings_default_timezone.php ================================================ string('server_timezone')->default('UTC')->change(); }); DB::table('server_settings') ->whereNull('server_timezone') ->orWhere('server_timezone', '') ->update(['server_timezone' => 'UTC']); } public function down() { Schema::table('server_settings', function (Blueprint $table) { $table->string('server_timezone')->default('')->change(); }); } } ================================================ FILE: database/migrations/2024_09_16_111428_encrypt_existing_private_keys.php ================================================ chunkById(100, function ($keys) { foreach ($keys as $key) { DB::table('private_keys') ->where('id', $key->id) ->update(['private_key' => Crypt::encryptString($key->private_key)]); } }); } catch (\Exception $e) { echo 'Encrypting private keys failed.'; echo $e->getMessage(); } } } ================================================ FILE: database/migrations/2024_09_17_111226_add_ssh_key_fingerprint_to_private_keys_table.php ================================================ string('fingerprint')->after('private_key')->nullable(); }); try { DB::table('private_keys')->chunkById(100, function ($keys) { foreach ($keys as $key) { $fingerprint = PrivateKey::generateFingerprint($key->private_key); if ($fingerprint) { $key->fingerprint = $fingerprint; $key->save(); } } }); } catch (\Exception $e) { echo 'Generating fingerprints failed.'; echo $e->getMessage(); } } public function down() { Schema::table('private_keys', function (Blueprint $table) { $table->dropColumn('fingerprint'); }); } } ================================================ FILE: database/migrations/2024_09_22_165240_add_advanced_options_to_cleanup_options_to_servers_settings_table.php ================================================ boolean('delete_unused_volumes')->default(false); $table->boolean('delete_unused_networks')->default(false); }); } public function down() { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('delete_unused_volumes'); $table->dropColumn('delete_unused_networks'); }); } }; ================================================ FILE: database/migrations/2024_09_26_083441_disable_api_by_default.php ================================================ boolean('is_api_enabled')->default(false)->change(); }); } }; ================================================ FILE: database/migrations/2024_10_03_095427_add_dump_all_to_standalone_postgresqls.php ================================================ boolean('dump_all')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('scheduled_database_backups', function (Blueprint $table) { $table->dropColumn('dump_all'); }); } }; ================================================ FILE: database/migrations/2024_10_10_081444_remove_constraint_from_service_applications_fqdn.php ================================================ dropUnique(['fqdn']); }); Schema::table('applications', function (Blueprint $table) { $table->dropUnique(['fqdn']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('service_applications', function (Blueprint $table) { $table->unique('fqdn'); }); Schema::table('applications', function (Blueprint $table) { $table->unique('fqdn'); }); } }; ================================================ FILE: database/migrations/2024_10_11_114331_add_required_env_variables.php ================================================ boolean('is_required')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('is_required'); }); } }; ================================================ FILE: database/migrations/2024_10_14_090416_update_metrics_token_in_server_settings.php ================================================ dropColumn('metrics_token'); $table->dropColumn('metrics_refresh_rate_seconds'); $table->dropColumn('metrics_history_days'); $table->dropColumn('is_server_api_enabled'); $table->boolean('is_sentinel_enabled')->default(false); $table->text('sentinel_token')->nullable(); $table->integer('sentinel_metrics_refresh_rate_seconds')->default(10); $table->integer('sentinel_metrics_history_days')->default(7); $table->integer('sentinel_push_interval_seconds')->default(60); $table->string('sentinel_custom_url')->nullable(); }); Schema::table('servers', function (Blueprint $table) { $table->dateTime('sentinel_updated_at')->default(now()); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->string('metrics_token')->nullable(); $table->integer('metrics_refresh_rate_seconds')->default(5); $table->integer('metrics_history_days')->default(30); $table->boolean('is_server_api_enabled')->default(false); $table->dropColumn('is_sentinel_enabled'); $table->dropColumn('sentinel_token'); $table->dropColumn('sentinel_metrics_refresh_rate_seconds'); $table->dropColumn('sentinel_metrics_history_days'); $table->dropColumn('sentinel_push_interval_seconds'); $table->dropColumn('sentinel_custom_url'); }); Schema::table('servers', function (Blueprint $table) { $table->dropColumn('sentinel_updated_at'); }); } }; ================================================ FILE: database/migrations/2024_10_15_172139_add_is_shared_to_environment_variables.php ================================================ boolean('is_shared')->default(false); }); } public function down() { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('is_shared'); }); } } ================================================ FILE: database/migrations/2024_10_16_120026_move_redis_password_to_envs.php ================================================ where('id', $redis->id)->value('redis_password'); EnvironmentVariable::create([ 'standalone_redis_id' => $redis->id, 'key' => 'REDIS_PASSWORD', 'value' => $redis_password, ]); EnvironmentVariable::create([ 'standalone_redis_id' => $redis->id, 'key' => 'REDIS_USERNAME', 'value' => 'default', ]); } }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropColumn('redis_password'); }); } catch (\Exception $e) { echo 'Moving Redis passwords to envs failed.'; echo $e->getMessage(); } } } ================================================ FILE: database/migrations/2024_10_16_192133_add_confirmation_settings_to_instance_settings_table.php ================================================ boolean('disable_two_step_confirmation')->default(false); }); } public function down() { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('disable_two_step_confirmation'); }); } }; ================================================ FILE: database/migrations/2024_10_17_093722_add_soft_delete_to_servers.php ================================================ softDeletes(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropSoftDeletes(); }); } }; ================================================ FILE: database/migrations/2024_10_22_105745_add_server_disk_usage_threshold.php ================================================ integer('server_disk_usage_notification_threshold')->default(80)->after('docker_cleanup_threshold'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('server_disk_usage_notification_threshold'); }); } }; ================================================ FILE: database/migrations/2024_10_22_121223_add_server_disk_usage_notification.php ================================================ boolean('discord_notifications_server_disk_usage')->default(true)->after('discord_enabled'); $table->boolean('smtp_notifications_server_disk_usage')->default(true)->after('smtp_enabled'); $table->boolean('telegram_notifications_server_disk_usage')->default(true)->after('telegram_enabled'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->dropColumn('discord_notifications_server_disk_usage'); $table->dropColumn('smtp_notifications_server_disk_usage'); $table->dropColumn('telegram_notifications_server_disk_usage'); }); } }; ================================================ FILE: database/migrations/2024_10_29_093927_add_is_sentinel_debug_enabled_to_server_settings.php ================================================ boolean('is_sentinel_debug_enabled')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_sentinel_debug_enabled'); }); } }; ================================================ FILE: database/migrations/2024_10_30_074601_rename_token_permissions.php ================================================ abilities)) { $abilities->push('root'); } if (in_array('read-only', $token->abilities)) { $abilities->push('read'); } if (in_array('view:sensitive', $token->abilities)) { $abilities->push('read', 'read:sensitive'); } $token->abilities = $abilities->unique()->values()->all(); $token->save(); } } catch (\Exception $e) { \Log::error('Error renaming token permissions: '.$e->getMessage()); } } /** * Reverse the migrations. */ public function down(): void { try { $tokens = PersonalAccessToken::all(); foreach ($tokens as $token) { $abilities = collect(); if (in_array('root', $token->abilities)) { $abilities->push('*'); } else { if (in_array('read', $token->abilities)) { $abilities->push('read-only'); } if (in_array('read:sensitive', $token->abilities)) { $abilities->push('view:sensitive'); } } $token->abilities = $abilities->unique()->values()->all(); $token->save(); } } catch (\Exception $e) { \Log::error('Error renaming token permissions: '.$e->getMessage()); } } }; ================================================ FILE: database/migrations/2024_11_02_213214_add_last_online_at_to_resources.php ================================================ timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('application_previews', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('service_applications', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('service_databases', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->timestamp('last_online_at')->default(now())->after('updated_at'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('application_previews', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('service_databases', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->dropColumn('last_online_at'); }); } }; ================================================ FILE: database/migrations/2024_11_11_125335_add_custom_nginx_configuration_to_static.php ================================================ longText('custom_nginx_configuration')->nullable()->after('static_image'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('custom_nginx_configuration'); }); } }; ================================================ FILE: database/migrations/2024_11_11_125366_add_index_to_activity_log.php ================================================ getDriverName() !== 'pgsql') { return; } try { DB::statement('ALTER TABLE activity_log ALTER COLUMN properties TYPE jsonb USING properties::jsonb'); DB::statement('CREATE INDEX idx_activity_type_uuid ON activity_log USING GIN (properties jsonb_path_ops)'); } catch (\Exception $e) { Log::error('Error adding index to activity_log: '.$e->getMessage()); } } public function down() { if (DB::connection()->getDriverName() !== 'pgsql') { return; } try { DB::statement('DROP INDEX IF EXISTS idx_activity_type_uuid'); DB::statement('ALTER TABLE activity_log ALTER COLUMN properties TYPE json USING properties::json'); } catch (\Exception $e) { Log::error('Error dropping index from activity_log: '.$e->getMessage()); } } } ================================================ FILE: database/migrations/2024_11_22_124742_add_uuid_to_environments_table.php ================================================ string('uuid')->after('id')->nullable()->unique(); }); DB::table('environments') ->whereNull('uuid') ->chunkById(100, function ($environments) { foreach ($environments as $environment) { DB::table('environments') ->where('id', $environment->id) ->update(['uuid' => (string) new Cuid2]); } }); Schema::table('environments', function (Blueprint $table) { $table->string('uuid')->nullable(false)->change(); }); } public function down(): void { Schema::table('environments', function (Blueprint $table) { $table->dropColumn('uuid'); }); } }; ================================================ FILE: database/migrations/2024_12_05_091823_add_disable_build_cache_advanced_option.php ================================================ boolean('disable_build_cache')->default(false); }); } public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('disable_build_cache'); }); } }; ================================================ FILE: database/migrations/2024_12_05_212355_create_email_notification_settings_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('smtp_enabled')->default(false); $table->text('smtp_from_address')->nullable(); $table->text('smtp_from_name')->nullable(); $table->text('smtp_recipients')->nullable(); $table->text('smtp_host')->nullable(); $table->integer('smtp_port')->nullable(); $table->string('smtp_encryption')->nullable(); $table->text('smtp_username')->nullable(); $table->text('smtp_password')->nullable(); $table->integer('smtp_timeout')->nullable(); $table->boolean('resend_enabled')->default(false); $table->text('resend_api_key')->nullable(); $table->boolean('use_instance_email_settings')->default(false); $table->boolean('deployment_success_email_notifications')->default(false); $table->boolean('deployment_failure_email_notifications')->default(true); $table->boolean('status_change_email_notifications')->default(false); $table->boolean('backup_success_email_notifications')->default(false); $table->boolean('backup_failure_email_notifications')->default(true); $table->boolean('scheduled_task_success_email_notifications')->default(false); $table->boolean('scheduled_task_failure_email_notifications')->default(true); $table->boolean('docker_cleanup_success_email_notifications')->default(false); $table->boolean('docker_cleanup_failure_email_notifications')->default(true); $table->boolean('server_disk_usage_email_notifications')->default(true); $table->boolean('server_reachable_email_notifications')->default(false); $table->boolean('server_unreachable_email_notifications')->default(true); $table->unique(['team_id']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('email_notification_settings'); } }; ================================================ FILE: database/migrations/2024_12_05_212416_create_discord_notification_settings_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('discord_enabled')->default(false); $table->text('discord_webhook_url')->nullable(); $table->boolean('deployment_success_discord_notifications')->default(false); $table->boolean('deployment_failure_discord_notifications')->default(true); $table->boolean('status_change_discord_notifications')->default(false); $table->boolean('backup_success_discord_notifications')->default(false); $table->boolean('backup_failure_discord_notifications')->default(true); $table->boolean('scheduled_task_success_discord_notifications')->default(false); $table->boolean('scheduled_task_failure_discord_notifications')->default(true); $table->boolean('docker_cleanup_success_discord_notifications')->default(false); $table->boolean('docker_cleanup_failure_discord_notifications')->default(true); $table->boolean('server_disk_usage_discord_notifications')->default(true); $table->boolean('server_reachable_discord_notifications')->default(false); $table->boolean('server_unreachable_discord_notifications')->default(true); $table->unique(['team_id']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('discord_notification_settings'); } }; ================================================ FILE: database/migrations/2024_12_05_212440_create_telegram_notification_settings_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('telegram_enabled')->default(false); $table->text('telegram_token')->nullable(); $table->text('telegram_chat_id')->nullable(); $table->boolean('deployment_success_telegram_notifications')->default(false); $table->boolean('deployment_failure_telegram_notifications')->default(true); $table->boolean('status_change_telegram_notifications')->default(false); $table->boolean('backup_success_telegram_notifications')->default(false); $table->boolean('backup_failure_telegram_notifications')->default(true); $table->boolean('scheduled_task_success_telegram_notifications')->default(false); $table->boolean('scheduled_task_failure_telegram_notifications')->default(true); $table->boolean('docker_cleanup_success_telegram_notifications')->default(false); $table->boolean('docker_cleanup_failure_telegram_notifications')->default(true); $table->boolean('server_disk_usage_telegram_notifications')->default(true); $table->boolean('server_reachable_telegram_notifications')->default(false); $table->boolean('server_unreachable_telegram_notifications')->default(true); $table->text('telegram_notifications_deployment_success_thread_id')->nullable(); $table->text('telegram_notifications_deployment_failure_thread_id')->nullable(); $table->text('telegram_notifications_status_change_thread_id')->nullable(); $table->text('telegram_notifications_backup_success_thread_id')->nullable(); $table->text('telegram_notifications_backup_failure_thread_id')->nullable(); $table->text('telegram_notifications_scheduled_task_success_thread_id')->nullable(); $table->text('telegram_notifications_scheduled_task_failure_thread_id')->nullable(); $table->text('telegram_notifications_docker_cleanup_success_thread_id')->nullable(); $table->text('telegram_notifications_docker_cleanup_failure_thread_id')->nullable(); $table->text('telegram_notifications_server_disk_usage_thread_id')->nullable(); $table->text('telegram_notifications_server_reachable_thread_id')->nullable(); $table->text('telegram_notifications_server_unreachable_thread_id')->nullable(); $table->unique(['team_id']); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('telegram_notification_settings'); } }; ================================================ FILE: database/migrations/2024_12_05_212546_migrate_email_notification_settings_from_teams_table.php ================================================ get(); foreach ($teams as $team) { try { DB::table('email_notification_settings')->updateOrInsert( ['team_id' => $team->id], [ 'smtp_enabled' => $team->smtp_enabled ?? false, 'smtp_from_address' => $team->smtp_from_address ? Crypt::encryptString($team->smtp_from_address) : null, 'smtp_from_name' => $team->smtp_from_name ? Crypt::encryptString($team->smtp_from_name) : null, 'smtp_recipients' => $team->smtp_recipients ? Crypt::encryptString($team->smtp_recipients) : null, 'smtp_host' => $team->smtp_host ? Crypt::encryptString($team->smtp_host) : null, 'smtp_port' => $team->smtp_port, 'smtp_encryption' => $team->smtp_encryption, 'smtp_username' => $team->smtp_username ? Crypt::encryptString($team->smtp_username) : null, 'smtp_password' => $team->smtp_password, 'smtp_timeout' => $team->smtp_timeout, 'use_instance_email_settings' => $team->use_instance_email_settings ?? false, 'resend_enabled' => $team->resend_enabled ?? false, 'resend_api_key' => $team->resend_api_key, 'deployment_success_email_notifications' => $team->smtp_notifications_deployments ?? false, 'deployment_failure_email_notifications' => $team->smtp_notifications_deployments ?? true, 'backup_success_email_notifications' => $team->smtp_notifications_database_backups ?? false, 'backup_failure_email_notifications' => $team->smtp_notifications_database_backups ?? true, 'scheduled_task_success_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? false, 'scheduled_task_failure_email_notifications' => $team->smtp_notifications_scheduled_tasks ?? true, 'status_change_email_notifications' => $team->smtp_notifications_status_changes ?? false, 'server_disk_usage_email_notifications' => $team->smtp_notifications_server_disk_usage ?? true, ] ); } catch (Exception $e) { \Log::error('Error migrating email notification settings from teams table: '.$e->getMessage()); } } Schema::table('teams', function (Blueprint $table) { $table->dropColumn([ 'smtp_enabled', 'smtp_from_address', 'smtp_from_name', 'smtp_recipients', 'smtp_host', 'smtp_port', 'smtp_encryption', 'smtp_username', 'smtp_password', 'smtp_timeout', 'use_instance_email_settings', 'resend_enabled', 'resend_api_key', 'smtp_notifications_test', 'smtp_notifications_deployments', 'smtp_notifications_database_backups', 'smtp_notifications_scheduled_tasks', 'smtp_notifications_status_changes', 'smtp_notifications_server_disk_usage', ]); }); } public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->boolean('smtp_enabled')->default(false); $table->string('smtp_from_address')->nullable(); $table->string('smtp_from_name')->nullable(); $table->string('smtp_recipients')->nullable(); $table->string('smtp_host')->nullable(); $table->integer('smtp_port')->nullable(); $table->string('smtp_encryption')->nullable(); $table->text('smtp_username')->nullable(); $table->text('smtp_password')->nullable(); $table->integer('smtp_timeout')->nullable(); $table->boolean('use_instance_email_settings')->default(false); $table->boolean('resend_enabled')->default(false); $table->text('resend_api_key')->nullable(); $table->boolean('smtp_notifications_test')->default(false); $table->boolean('smtp_notifications_deployments')->default(false); $table->boolean('smtp_notifications_database_backups')->default(true); $table->boolean('smtp_notifications_scheduled_tasks')->default(false); $table->boolean('smtp_notifications_status_changes')->default(false); $table->boolean('smtp_notifications_server_disk_usage')->default(true); }); $settings = DB::table('email_notification_settings')->get(); foreach ($settings as $setting) { try { DB::table('teams') ->where('id', $setting->team_id) ->update([ 'smtp_enabled' => $setting->smtp_enabled, 'smtp_from_address' => $setting->smtp_from_address ? Crypt::decryptString($setting->smtp_from_address) : null, 'smtp_from_name' => $setting->smtp_from_name ? Crypt::decryptString($setting->smtp_from_name) : null, 'smtp_recipients' => $setting->smtp_recipients ? Crypt::decryptString($setting->smtp_recipients) : null, 'smtp_host' => $setting->smtp_host ? Crypt::decryptString($setting->smtp_host) : null, 'smtp_port' => $setting->smtp_port, 'smtp_encryption' => $setting->smtp_encryption, 'smtp_username' => $setting->smtp_username ? Crypt::decryptString($setting->smtp_username) : null, 'smtp_password' => $setting->smtp_password, 'smtp_timeout' => $setting->smtp_timeout, 'use_instance_email_settings' => $setting->use_instance_email_settings, 'resend_enabled' => $setting->resend_enabled, 'resend_api_key' => $setting->resend_api_key, 'smtp_notifications_deployments' => $setting->deployment_success_email_notifications || $setting->deployment_failure_email_notifications, 'smtp_notifications_database_backups' => $setting->backup_success_email_notifications || $setting->backup_failure_email_notifications, 'smtp_notifications_scheduled_tasks' => $setting->scheduled_task_success_email_notifications || $setting->scheduled_task_failure_email_notifications, 'smtp_notifications_status_changes' => $setting->status_change_email_notifications, ]); } catch (Exception $e) { \Log::error('Error migrating email notification settings from teams table: '.$e->getMessage()); } } } }; ================================================ FILE: database/migrations/2024_12_05_212631_migrate_discord_notification_settings_from_teams_table.php ================================================ get(); foreach ($teams as $team) { try { DB::table('discord_notification_settings')->updateOrInsert( ['team_id' => $team->id], [ 'discord_enabled' => $team->discord_enabled ?? false, 'discord_webhook_url' => $team->discord_webhook_url ? Crypt::encryptString($team->discord_webhook_url) : null, 'deployment_success_discord_notifications' => $team->discord_notifications_deployments ?? false, 'deployment_failure_discord_notifications' => $team->discord_notifications_deployments ?? true, 'backup_success_discord_notifications' => $team->discord_notifications_database_backups ?? false, 'backup_failure_discord_notifications' => $team->discord_notifications_database_backups ?? true, 'scheduled_task_success_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? false, 'scheduled_task_failure_discord_notifications' => $team->discord_notifications_scheduled_tasks ?? true, 'status_change_discord_notifications' => $team->discord_notifications_status_changes ?? false, 'server_disk_usage_discord_notifications' => $team->discord_notifications_server_disk_usage ?? true, ] ); } catch (Exception $e) { \Log::error('Error migrating discord notification settings from teams table: '.$e->getMessage()); } } Schema::table('teams', function (Blueprint $table) { $table->dropColumn([ 'discord_enabled', 'discord_webhook_url', 'discord_notifications_test', 'discord_notifications_deployments', 'discord_notifications_status_changes', 'discord_notifications_database_backups', 'discord_notifications_scheduled_tasks', 'discord_notifications_server_disk_usage', ]); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->boolean('discord_enabled')->default(false); $table->string('discord_webhook_url')->nullable(); $table->boolean('discord_notifications_test')->default(true); $table->boolean('discord_notifications_deployments')->default(true); $table->boolean('discord_notifications_status_changes')->default(true); $table->boolean('discord_notifications_database_backups')->default(true); $table->boolean('discord_notifications_scheduled_tasks')->default(true); $table->boolean('discord_notifications_server_disk_usage')->default(true); }); $settings = DB::table('discord_notification_settings')->get(); foreach ($settings as $setting) { try { DB::table('teams') ->where('id', $setting->team_id) ->update([ 'discord_enabled' => $setting->discord_enabled, 'discord_webhook_url' => Crypt::decryptString($setting->discord_webhook_url), 'discord_notifications_deployments' => $setting->deployment_success_discord_notifications || $setting->deployment_failure_discord_notifications, 'discord_notifications_status_changes' => $setting->status_change_discord_notifications, 'discord_notifications_database_backups' => $setting->backup_success_discord_notifications || $setting->backup_failure_discord_notifications, 'discord_notifications_scheduled_tasks' => $setting->scheduled_task_success_discord_notifications || $setting->scheduled_task_failure_discord_notifications, 'discord_notifications_server_disk_usage' => $setting->server_disk_usage_discord_notifications, ]); } catch (Exception $e) { \Log::error('Error migrating discord notification settings from teams table: '.$e->getMessage()); } } } }; ================================================ FILE: database/migrations/2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table.php ================================================ get(); foreach ($teams as $team) { try { DB::table('telegram_notification_settings')->updateOrInsert( ['team_id' => $team->id], [ 'telegram_enabled' => $team->telegram_enabled ?? false, 'telegram_token' => $team->telegram_token ? Crypt::encryptString($team->telegram_token) : null, 'telegram_chat_id' => $team->telegram_chat_id ? Crypt::encryptString($team->telegram_chat_id) : null, 'deployment_success_telegram_notifications' => $team->telegram_notifications_deployments ?? false, 'deployment_failure_telegram_notifications' => $team->telegram_notifications_deployments ?? true, 'backup_success_telegram_notifications' => $team->telegram_notifications_database_backups ?? false, 'backup_failure_telegram_notifications' => $team->telegram_notifications_database_backups ?? true, 'scheduled_task_success_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? false, 'scheduled_task_failure_telegram_notifications' => $team->telegram_notifications_scheduled_tasks ?? true, 'status_change_telegram_notifications' => $team->telegram_notifications_status_changes ?? false, 'server_disk_usage_telegram_notifications' => $team->telegram_notifications_server_disk_usage ?? true, 'telegram_notifications_deployment_success_thread_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null, 'telegram_notifications_deployment_failure_thread_id' => $team->telegram_notifications_deployments_message_thread_id ? Crypt::encryptString($team->telegram_notifications_deployments_message_thread_id) : null, 'telegram_notifications_backup_success_thread_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null, 'telegram_notifications_backup_failure_thread_id' => $team->telegram_notifications_database_backups_message_thread_id ? Crypt::encryptString($team->telegram_notifications_database_backups_message_thread_id) : null, 'telegram_notifications_scheduled_task_success_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null, 'telegram_notifications_scheduled_task_failure_thread_id' => $team->telegram_notifications_scheduled_tasks_thread_id ? Crypt::encryptString($team->telegram_notifications_scheduled_tasks_thread_id) : null, 'telegram_notifications_status_change_thread_id' => $team->telegram_notifications_status_changes_message_thread_id ? Crypt::encryptString($team->telegram_notifications_status_changes_message_thread_id) : null, ] ); } catch (Exception $e) { Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); } } Schema::table('teams', function (Blueprint $table) { $table->dropColumn([ 'telegram_enabled', 'telegram_token', 'telegram_chat_id', 'telegram_notifications_test', 'telegram_notifications_deployments', 'telegram_notifications_status_changes', 'telegram_notifications_database_backups', 'telegram_notifications_scheduled_tasks', 'telegram_notifications_server_disk_usage', 'telegram_notifications_test_message_thread_id', 'telegram_notifications_deployments_message_thread_id', 'telegram_notifications_status_changes_message_thread_id', 'telegram_notifications_database_backups_message_thread_id', 'telegram_notifications_scheduled_tasks_thread_id', ]); }); } public function down(): void { Schema::table('teams', function (Blueprint $table) { $table->boolean('telegram_enabled')->default(false); $table->text('telegram_token')->nullable(); $table->text('telegram_chat_id')->nullable(); $table->boolean('telegram_notifications_test')->default(true); $table->boolean('telegram_notifications_deployments')->default(true); $table->boolean('telegram_notifications_status_changes')->default(true); $table->boolean('telegram_notifications_database_backups')->default(true); $table->boolean('telegram_notifications_scheduled_tasks')->default(true); $table->boolean('telegram_notifications_server_disk_usage')->default(true); $table->text('telegram_notifications_test_message_thread_id')->nullable(); $table->text('telegram_notifications_deployments_message_thread_id')->nullable(); $table->text('telegram_notifications_status_changes_message_thread_id')->nullable(); $table->text('telegram_notifications_database_backups_message_thread_id')->nullable(); $table->text('telegram_notifications_scheduled_tasks_thread_id')->nullable(); }); $settings = DB::table('telegram_notification_settings')->get(); foreach ($settings as $setting) { try { DB::table('teams') ->where('id', $setting->team_id) ->update([ 'telegram_enabled' => $setting->telegram_enabled, 'telegram_token' => $setting->telegram_token ? Crypt::decryptString($setting->telegram_token) : null, 'telegram_chat_id' => $setting->telegram_chat_id ? Crypt::decryptString($setting->telegram_chat_id) : null, 'telegram_notifications_deployments' => $setting->deployment_success_telegram_notifications || $setting->deployment_failure_telegram_notifications, 'telegram_notifications_status_changes' => $setting->status_change_telegram_notifications, 'telegram_notifications_database_backups' => $setting->backup_success_telegram_notifications || $setting->backup_failure_telegram_notifications, 'telegram_notifications_scheduled_tasks' => $setting->scheduled_task_success_telegram_notifications || $setting->scheduled_task_failure_telegram_notifications, 'telegram_notifications_server_disk_usage' => $setting->server_disk_usage_telegram_notifications, 'telegram_notifications_deployments_message_thread_id' => $setting->telegram_notifications_deployment_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_deployment_success_thread_id) : null, 'telegram_notifications_status_changes_message_thread_id' => $setting->telegram_notifications_status_change_thread_id ? Crypt::decryptString($setting->telegram_notifications_status_change_thread_id) : null, 'telegram_notifications_database_backups_message_thread_id' => $setting->telegram_notifications_backup_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_backup_success_thread_id) : null, 'telegram_notifications_scheduled_tasks_thread_id' => $setting->telegram_notifications_scheduled_task_success_thread_id ? Crypt::decryptString($setting->telegram_notifications_scheduled_task_success_thread_id) : null, ]); } catch (Exception $e) { Log::error('Error migrating telegram notification settings from teams table: '.$e->getMessage()); } } } }; ================================================ FILE: database/migrations/2024_12_06_142014_create_slack_notification_settings_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('slack_enabled')->default(false); $table->text('slack_webhook_url')->nullable(); $table->boolean('deployment_success_slack_notifications')->default(false); $table->boolean('deployment_failure_slack_notifications')->default(true); $table->boolean('status_change_slack_notifications')->default(false); $table->boolean('backup_success_slack_notifications')->default(false); $table->boolean('backup_failure_slack_notifications')->default(true); $table->boolean('scheduled_task_success_slack_notifications')->default(false); $table->boolean('scheduled_task_failure_slack_notifications')->default(true); $table->boolean('docker_cleanup_success_slack_notifications')->default(false); $table->boolean('docker_cleanup_failure_slack_notifications')->default(true); $table->boolean('server_disk_usage_slack_notifications')->default(true); $table->boolean('server_reachable_slack_notifications')->default(false); $table->boolean('server_unreachable_slack_notifications')->default(true); $table->unique(['team_id']); }); $teams = DB::table('teams')->get(); foreach ($teams as $team) { try { DB::table('slack_notification_settings')->insert([ 'team_id' => $team->id, ]); } catch (\Throwable $e) { Log::error('Error creating slack notification settings for existing teams: '.$e->getMessage()); } } } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('slack_notification_settings'); } }; ================================================ FILE: database/migrations/2024_12_09_105711_drop_waitlists_table.php ================================================ id(); $table->string('uuid'); $table->string('type'); $table->string('email')->unique(); $table->boolean('verified')->default(false); $table->timestamps(); }); } }; ================================================ FILE: database/migrations/2024_12_10_122142_encrypt_instance_settings_email_columns.php ================================================ text('smtp_from_address')->nullable()->change(); $table->text('smtp_from_name')->nullable()->change(); $table->text('smtp_recipients')->nullable()->change(); $table->text('smtp_host')->nullable()->change(); $table->text('smtp_username')->nullable()->change(); }); if (DB::table('instance_settings')->exists()) { $settings = DB::table('instance_settings')->get(); foreach ($settings as $setting) { try { DB::table('instance_settings')->where('id', $setting->id)->update([ 'smtp_from_address' => $setting->smtp_from_address ? Crypt::encryptString($setting->smtp_from_address) : null, 'smtp_from_name' => $setting->smtp_from_name ? Crypt::encryptString($setting->smtp_from_name) : null, 'smtp_recipients' => $setting->smtp_recipients ? Crypt::encryptString($setting->smtp_recipients) : null, 'smtp_host' => $setting->smtp_host ? Crypt::encryptString($setting->smtp_host) : null, 'smtp_username' => $setting->smtp_username ? Crypt::encryptString($setting->smtp_username) : null, ]); } catch (Exception $e) { \Log::error('Error encrypting instance settings email columns: '.$e->getMessage()); } } } } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->string('smtp_from_address')->nullable()->change(); $table->string('smtp_from_name')->nullable()->change(); $table->string('smtp_recipients')->nullable()->change(); $table->string('smtp_host')->nullable()->change(); $table->string('smtp_username')->nullable()->change(); }); if (DB::table('instance_settings')->exists()) { $settings = DB::table('instance_settings')->get(); foreach ($settings as $setting) { try { DB::table('instance_settings')->where('id', $setting->id)->update([ 'smtp_from_address' => $setting->smtp_from_address ? Crypt::decryptString($setting->smtp_from_address) : null, 'smtp_from_name' => $setting->smtp_from_name ? Crypt::decryptString($setting->smtp_from_name) : null, 'smtp_recipients' => $setting->smtp_recipients ? Crypt::decryptString($setting->smtp_recipients) : null, 'smtp_host' => $setting->smtp_host ? Crypt::decryptString($setting->smtp_host) : null, 'smtp_username' => $setting->smtp_username ? Crypt::decryptString($setting->smtp_username) : null, ]); } catch (Exception $e) { \Log::error('Error decrypting instance settings email columns: '.$e->getMessage()); } } } } }; ================================================ FILE: database/migrations/2024_12_10_122143_drop_resale_license.php ================================================ dropColumn('is_resale_license_active'); $table->dropColumn('resale_license'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->boolean('is_resale_license_active')->default(false); $table->longText('resale_license')->nullable(); }); } }; ================================================ FILE: database/migrations/2024_12_11_135026_create_pushover_notification_settings_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('pushover_enabled')->default(false); $table->text('pushover_user_key')->nullable(); $table->text('pushover_api_token')->nullable(); $table->boolean('deployment_success_pushover_notifications')->default(false); $table->boolean('deployment_failure_pushover_notifications')->default(true); $table->boolean('status_change_pushover_notifications')->default(false); $table->boolean('backup_success_pushover_notifications')->default(false); $table->boolean('backup_failure_pushover_notifications')->default(true); $table->boolean('scheduled_task_success_pushover_notifications')->default(false); $table->boolean('scheduled_task_failure_pushover_notifications')->default(true); $table->boolean('docker_cleanup_success_pushover_notifications')->default(false); $table->boolean('docker_cleanup_failure_pushover_notifications')->default(true); $table->boolean('server_disk_usage_pushover_notifications')->default(true); $table->boolean('server_reachable_pushover_notifications')->default(false); $table->boolean('server_unreachable_pushover_notifications')->default(true); $table->unique(['team_id']); }); $teams = DB::table('teams')->get(); foreach ($teams as $team) { try { DB::table('pushover_notification_settings')->insert([ 'team_id' => $team->id, ]); } catch (\Throwable $e) { Log::error('Error creating pushover notification settings for existing teams: '.$e->getMessage()); } } } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('pushover_notification_settings'); } }; ================================================ FILE: database/migrations/2024_12_11_161418_add_authentik_base_url_to_oauth_settings_table.php ================================================ string('base_url')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('oauth_settings', function (Blueprint $table) { $table->dropColumn('base_url'); }); } }; ================================================ FILE: database/migrations/2024_12_13_103007_encrypt_resend_api_key_in_instance_settings.php ================================================ exists()) { $settings = DB::table('instance_settings')->get(); foreach ($settings as $setting) { try { DB::table('instance_settings')->where('id', $setting->id)->update([ 'resend_api_key' => $setting->resend_api_key ? Crypt::encryptString($setting->resend_api_key) : null, ]); } catch (Exception $e) { \Log::error('Error encrypting resend_api_key: '.$e->getMessage()); } } } } /** * Reverse the migrations. */ public function down(): void { if (DB::table('instance_settings')->exists()) { $settings = DB::table('instance_settings')->get(); foreach ($settings as $setting) { try { DB::table('instance_settings')->where('id', $setting->id)->update([ 'resend_api_key' => $setting->resend_api_key ? Crypt::decryptString($setting->resend_api_key) : null, ]); } catch (Exception $e) { \Log::error('Error decrypting resend_api_key: '.$e->getMessage()); } } } } }; ================================================ FILE: database/migrations/2024_12_16_134437_add_resourceable_columns_to_environment_variables_table.php ================================================ string('resourceable_type')->nullable(); $table->unsignedBigInteger('resourceable_id')->nullable(); $table->index(['resourceable_type', 'resourceable_id']); }); // Populate the new columns DB::table('environment_variables')->whereNotNull('application_id') ->update([ 'resourceable_type' => 'App\\Models\\Application', 'resourceable_id' => DB::raw('application_id'), ]); DB::table('environment_variables')->whereNotNull('service_id') ->update([ 'resourceable_type' => 'App\\Models\\Service', 'resourceable_id' => DB::raw('service_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_postgresql_id') ->update([ 'resourceable_type' => 'App\\Models\\StandalonePostgresql', 'resourceable_id' => DB::raw('standalone_postgresql_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_redis_id') ->update([ 'resourceable_type' => 'App\\Models\\StandaloneRedis', 'resourceable_id' => DB::raw('standalone_redis_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_mongodb_id') ->update([ 'resourceable_type' => 'App\\Models\\StandaloneMongodb', 'resourceable_id' => DB::raw('standalone_mongodb_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_mysql_id') ->update([ 'resourceable_type' => 'App\\Models\\StandaloneMysql', 'resourceable_id' => DB::raw('standalone_mysql_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_mariadb_id') ->update([ 'resourceable_type' => 'App\\Models\\StandaloneMariadb', 'resourceable_id' => DB::raw('standalone_mariadb_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_keydb_id') ->update([ 'resourceable_type' => 'App\\Models\\StandaloneKeydb', 'resourceable_id' => DB::raw('standalone_keydb_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_dragonfly_id') ->update([ 'resourceable_type' => 'App\\Models\\StandaloneDragonfly', 'resourceable_id' => DB::raw('standalone_dragonfly_id'), ]); DB::table('environment_variables')->whereNotNull('standalone_clickhouse_id') ->update([ 'resourceable_type' => 'App\\Models\\StandaloneClickhouse', 'resourceable_id' => DB::raw('standalone_clickhouse_id'), ]); // After successful migration, we can drop the old foreign key columns Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn([ 'application_id', 'service_id', 'standalone_postgresql_id', 'standalone_redis_id', 'standalone_mongodb_id', 'standalone_mysql_id', 'standalone_mariadb_id', 'standalone_keydb_id', 'standalone_dragonfly_id', 'standalone_clickhouse_id', ]); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { // Restore the old columns $table->unsignedBigInteger('application_id')->nullable(); $table->unsignedBigInteger('service_id')->nullable(); $table->unsignedBigInteger('standalone_postgresql_id')->nullable(); $table->unsignedBigInteger('standalone_redis_id')->nullable(); $table->unsignedBigInteger('standalone_mongodb_id')->nullable(); $table->unsignedBigInteger('standalone_mysql_id')->nullable(); $table->unsignedBigInteger('standalone_mariadb_id')->nullable(); $table->unsignedBigInteger('standalone_keydb_id')->nullable(); $table->unsignedBigInteger('standalone_dragonfly_id')->nullable(); $table->unsignedBigInteger('standalone_clickhouse_id')->nullable(); }); Schema::table('environment_variables', function (Blueprint $table) { // Restore data from polymorphic relationship DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\Application') ->update(['application_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\Service') ->update(['service_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandalonePostgresql') ->update(['standalone_postgresql_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandaloneRedis') ->update(['standalone_redis_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandaloneMongodb') ->update(['standalone_mongodb_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandaloneMysql') ->update(['standalone_mysql_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandaloneMariadb') ->update(['standalone_mariadb_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandaloneKeydb') ->update(['standalone_keydb_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandaloneDragonfly') ->update(['standalone_dragonfly_id' => DB::raw('resourceable_id')]); DB::table('environment_variables') ->where('resourceable_type', 'App\\Models\\StandaloneClickhouse') ->update(['standalone_clickhouse_id' => DB::raw('resourceable_id')]); // Drop the polymorphic columns $table->dropIndex(['resourceable_type', 'resourceable_id']); $table->dropColumn(['resourceable_type', 'resourceable_id']); }); } }; ================================================ FILE: database/migrations/2024_12_17_140637_add_server_disk_usage_check_frequency_to_server_settings_table.php ================================================ string('server_disk_usage_check_frequency')->default('0 23 * * *'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('server_disk_usage_check_frequency'); }); } }; ================================================ FILE: database/migrations/2024_12_23_142402_update_email_encryption_values.php ================================================ 'starttls', 'ssl' => 'tls', '' => 'none', ]; /** * Run the migrations. */ public function up(): void { try { DB::beginTransaction(); $instanceSettings = DB::table('instance_settings')->get(); foreach ($instanceSettings as $setting) { try { if (array_key_exists($setting->smtp_encryption, $this->encryptionMappings)) { DB::table('instance_settings') ->where('id', $setting->id) ->update([ 'smtp_encryption' => $this->encryptionMappings[$setting->smtp_encryption], ]); } } catch (\Exception $e) { \Log::error('Failed to update instance settings: '.$e->getMessage()); } } $emailSettings = DB::table('email_notification_settings')->get(); foreach ($emailSettings as $setting) { try { if (array_key_exists($setting->smtp_encryption, $this->encryptionMappings)) { DB::table('email_notification_settings') ->where('id', $setting->id) ->update([ 'smtp_encryption' => $this->encryptionMappings[$setting->smtp_encryption], ]); } } catch (\Exception $e) { \Log::error('Failed to update email settings: '.$e->getMessage()); } } DB::commit(); } catch (\Exception $e) { DB::rollBack(); \Log::error('Failed to update email encryption: '.$e->getMessage()); throw $e; } } /** * Reverse the migrations. */ public function down(): void { try { DB::beginTransaction(); $reverseMapping = [ 'starttls' => 'tls', 'tls' => 'ssl', 'none' => '', ]; $instanceSettings = DB::table('instance_settings')->get(); foreach ($instanceSettings as $setting) { try { if (array_key_exists($setting->smtp_encryption, $reverseMapping)) { DB::table('instance_settings') ->where('id', $setting->id) ->update([ 'smtp_encryption' => $reverseMapping[$setting->smtp_encryption], ]); } } catch (\Exception $e) { \Log::error('Failed to reverse instance settings: '.$e->getMessage()); } } $emailSettings = DB::table('email_notification_settings')->get(); foreach ($emailSettings as $setting) { try { if (array_key_exists($setting->smtp_encryption, $reverseMapping)) { DB::table('email_notification_settings') ->where('id', $setting->id) ->update([ 'smtp_encryption' => $reverseMapping[$setting->smtp_encryption], ]); } } catch (\Exception $e) { \Log::error('Failed to reverse email settings: '.$e->getMessage()); } } DB::commit(); } catch (\Exception $e) { DB::rollBack(); \Log::error('Failed to reverse email encryption: '.$e->getMessage()); throw $e; } } } ================================================ FILE: database/migrations/2025_01_05_050736_add_network_aliases_to_applications_table.php ================================================ text('custom_network_aliases')->nullable(); }); } public function down() { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('custom_network_aliases'); }); } }; ================================================ FILE: database/migrations/2025_01_08_154008_switch_up_readonly_labels.php ================================================ update([ 'is_container_label_readonly_enabled' => DB::raw('NOT is_container_label_readonly_enabled'), ]); Schema::table('application_settings', function (Blueprint $table) { $table->boolean('is_container_label_readonly_enabled')->default(true)->change(); }); } /** * Reverse the migrations. */ public function down(): void { DB::table('application_settings') ->update([ 'is_container_label_readonly_enabled' => DB::raw('NOT is_container_label_readonly_enabled'), ]); Schema::table('application_settings', function (Blueprint $table) { $table->boolean('is_container_label_readonly_enabled')->default(false)->change(); }); } }; ================================================ FILE: database/migrations/2025_01_10_135244_add_horizon_job_details_to_queue.php ================================================ string('horizon_job_id')->nullable(); $table->string('horizon_job_worker')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('horizon_job_id'); $table->dropColumn('horizon_job_worker'); }); } }; ================================================ FILE: database/migrations/2025_01_13_130238_add_backup_retention_fields_to_scheduled_database_backups_table.php ================================================ renameColumn('number_of_backups_locally', 'database_backup_retention_amount_locally'); $table->integer('database_backup_retention_amount_locally')->default(0)->nullable(false)->change(); $table->integer('database_backup_retention_days_locally')->default(0)->nullable(false); $table->decimal('database_backup_retention_max_storage_locally', 17, 7)->default(0)->nullable(false); $table->integer('database_backup_retention_amount_s3')->default(0)->nullable(false); $table->integer('database_backup_retention_days_s3')->default(0)->nullable(false); $table->decimal('database_backup_retention_max_storage_s3', 17, 7)->default(0)->nullable(false); }); } public function down() { Schema::table('scheduled_database_backups', function (Blueprint $table) { $table->renameColumn('database_backup_retention_amount_locally', 'number_of_backups_locally')->nullable(true)->change(); $table->dropColumn([ 'database_backup_retention_days_locally', 'database_backup_retention_max_storage_locally', 'database_backup_retention_amount_s3', 'database_backup_retention_days_s3', 'database_backup_retention_max_storage_s3', ]); }); } }; ================================================ FILE: database/migrations/2025_01_15_130416_create_docker_cleanup_executions_table.php ================================================ id(); $table->string('uuid')->unique(); $table->enum('status', ['success', 'failed', 'running'])->default('running'); $table->text('message')->nullable(); $table->json('cleanup_log')->nullable(); $table->foreignId('server_id'); $table->timestamps(); $table->timestamp('finished_at')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('docker_cleanup_executions'); } }; ================================================ FILE: database/migrations/2025_01_16_110406_change_commit_message_to_text_in_application_deployment_queues.php ================================================ text('commit_message')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->string('commit_message', 50)->nullable()->change(); }); } }; ================================================ FILE: database/migrations/2025_01_16_130238_add_finished_at_to_executions_tables.php ================================================ timestamp('finished_at')->nullable(); }); Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { $table->timestamp('finished_at')->nullable(); }); Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->timestamp('finished_at')->nullable(); }); } public function down() { Schema::table('application_deployment_queues', function (Blueprint $table) { $table->dropColumn('finished_at'); }); Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { $table->dropColumn('finished_at'); }); Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->dropColumn('finished_at'); }); } }; ================================================ FILE: database/migrations/2025_01_21_125205_update_finished_at_timestamps_if_not_set.php ================================================ whereNull('finished_at') ->update(['finished_at' => DB::raw('updated_at')]); } catch (\Exception $e) { \Log::error('Failed to update not set finished_at timestamps for application_deployment_queues: '.$e->getMessage()); } try { DB::table('scheduled_database_backup_executions') ->whereNull('finished_at') ->update(['finished_at' => DB::raw('updated_at')]); } catch (\Exception $e) { \Log::error('Failed to update not set finished_at timestamps for scheduled_database_backup_executions: '.$e->getMessage()); } try { DB::table('scheduled_task_executions') ->whereNull('finished_at') ->update(['finished_at' => DB::raw('updated_at')]); } catch (\Exception $e) { \Log::error('Failed to update not set finished_at timestamps for scheduled_task_executions: '.$e->getMessage()); } } }; ================================================ FILE: database/migrations/2025_01_22_101105_remove_wrongly_created_envs.php ================================================ each(function (EnvironmentVariable $environmentVariable) { $environmentVariable->delete(); }); } catch (\Exception $e) { Log::error('Failed to delete wrongly created environment variables: '.$e->getMessage()); } } }; ================================================ FILE: database/migrations/2025_01_27_102616_add_ssl_fields_to_database_tables.php ================================================ boolean('enable_ssl')->default(false); $table->enum('ssl_mode', ['allow', 'prefer', 'require', 'verify-ca', 'verify-full'])->default('require'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->boolean('enable_ssl')->default(false); $table->enum('ssl_mode', ['PREFERRED', 'REQUIRED', 'VERIFY_CA', 'VERIFY_IDENTITY'])->default('REQUIRED'); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->boolean('enable_ssl')->default(false); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->boolean('enable_ssl')->default(false); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->boolean('enable_ssl')->default(false); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->boolean('enable_ssl')->default(false); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->boolean('enable_ssl')->default(true); $table->enum('ssl_mode', ['allow', 'prefer', 'require', 'verify-full'])->default('require'); }); } /** * Reverse the migrations. */ public function down() { Schema::table('standalone_postgresqls', function (Blueprint $table) { $table->dropColumn('enable_ssl'); $table->dropColumn('ssl_mode'); }); Schema::table('standalone_mysqls', function (Blueprint $table) { $table->dropColumn('enable_ssl'); $table->dropColumn('ssl_mode'); }); Schema::table('standalone_mariadbs', function (Blueprint $table) { $table->dropColumn('enable_ssl'); }); Schema::table('standalone_redis', function (Blueprint $table) { $table->dropColumn('enable_ssl'); }); Schema::table('standalone_keydbs', function (Blueprint $table) { $table->dropColumn('enable_ssl'); }); Schema::table('standalone_dragonflies', function (Blueprint $table) { $table->dropColumn('enable_ssl'); }); Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->dropColumn('enable_ssl'); $table->dropColumn('ssl_mode'); }); } }; ================================================ FILE: database/migrations/2025_01_27_153741_create_ssl_certificates_table.php ================================================ id(); $table->text('ssl_certificate'); $table->text('ssl_private_key'); $table->text('configuration_dir')->nullable(); $table->text('mount_path')->nullable(); $table->string('resource_type')->nullable(); $table->unsignedBigInteger('resource_id')->nullable(); $table->unsignedBigInteger('server_id'); $table->text('common_name'); $table->json('subject_alternative_names')->nullable(); $table->timestamp('valid_until'); $table->boolean('is_ca_certificate')->default(false); $table->timestamps(); $table->foreign('server_id')->references('id')->on('servers'); }); } public function down() { Schema::dropIfExists('ssl_certificates'); } }; ================================================ FILE: database/migrations/2025_01_30_125223_encrypt_local_file_volumes_fields.php ================================================ text('mount_path')->nullable()->change(); }); if (DB::table('local_file_volumes')->exists()) { DB::beginTransaction(); DB::table('local_file_volumes') ->orderBy('id') ->chunk(100, function ($volumes) { foreach ($volumes as $volume) { try { $fs_path = $volume->fs_path; $mount_path = $volume->mount_path; $content = $volume->content; // Check if fields are already encrypted by attempting to decrypt try { if ($fs_path) { Crypt::decryptString($fs_path); } } catch (\Exception $e) { $fs_path = $fs_path ? Crypt::encryptString($fs_path) : null; } try { if ($mount_path) { Crypt::decryptString($mount_path); } } catch (\Exception $e) { $mount_path = $mount_path ? Crypt::encryptString($mount_path) : null; } try { if ($content) { Crypt::decryptString($content); } } catch (\Exception $e) { $content = $content ? Crypt::encryptString($content) : null; } DB::table('local_file_volumes')->where('id', $volume->id)->update([ 'fs_path' => $fs_path, 'mount_path' => $mount_path, 'content' => $content, ]); echo "Updated volume {$volume->id}\n"; } catch (\Exception $e) { echo "Error encrypting local file volume fields: {$e->getMessage()}\n"; Log::error('Error encrypting local file volume fields: '.$e->getMessage()); } } }); DB::commit(); } } /** * Reverse the migrations. */ public function down(): void { Schema::table('local_file_volumes', function (Blueprint $table) { $table->string('fs_path')->change(); $table->string('mount_path')->nullable()->change(); $table->longText('content')->nullable()->change(); }); if (DB::table('local_file_volumes')->exists()) { DB::beginTransaction(); DB::table('local_file_volumes') ->orderBy('id') ->chunk(100, function ($volumes) { foreach ($volumes as $volume) { try { $fs_path = $volume->fs_path; $mount_path = $volume->mount_path; $content = $volume->content; // Check if fields are already decrypted by attempting to decrypt try { if ($fs_path) { Crypt::decryptString($fs_path); } } catch (\Exception $e) { $fs_path = $fs_path ? Crypt::decryptString($fs_path) : null; } try { if ($mount_path) { Crypt::decryptString($mount_path); } } catch (\Exception $e) { $mount_path = $mount_path ? Crypt::decryptString($mount_path) : null; } try { if ($content) { Crypt::decryptString($content); } } catch (\Exception $e) { $content = $content ? Crypt::decryptString($content) : null; } DB::table('local_file_volumes')->where('id', $volume->id)->update([ 'fs_path' => $fs_path, 'mount_path' => $mount_path, 'content' => $content, ]); echo "Updated volume {$volume->id}\n"; } catch (\Exception $e) { echo "Error decrypting local file volume fields: {$e->getMessage()}\n"; Log::error('Error decrypting local file volume fields: '.$e->getMessage()); } } }); DB::commit(); } } }; ================================================ FILE: database/migrations/2025_02_27_125249_add_index_to_scheduled_task_executions.php ================================================ index(['scheduled_task_id', 'created_at'], 'scheduled_task_executions_task_id_created_at_index'); }); Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { $table->index( ['scheduled_database_backup_id', 'created_at'], 'scheduled_db_backup_executions_backup_id_created_at_index' ); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->dropIndex('scheduled_task_executions_task_id_created_at_index'); }); Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { $table->dropIndex('scheduled_db_backup_executions_backup_id_created_at_index'); }); } }; ================================================ FILE: database/migrations/2025_03_01_112617_add_stripe_past_due.php ================================================ boolean('stripe_past_due')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->dropColumn('stripe_past_due'); }); } }; ================================================ FILE: database/migrations/2025_03_14_140150_add_storage_deletion_tracking_to_backup_executions.php ================================================ boolean('local_storage_deleted')->default(false); $table->boolean('s3_storage_deleted')->default(false); }); } }; ================================================ FILE: database/migrations/2025_03_21_104103_disable_discord_here.php ================================================ boolean('discord_ping_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('discord_notification_settings', function (Blueprint $table) { $table->dropColumn('discord_ping_enabled'); }); } }; ================================================ FILE: database/migrations/2025_03_26_104103_disable_mongodb_ssl_by_default.php ================================================ boolean('enable_ssl')->default(false)->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('standalone_mongodbs', function (Blueprint $table) { $table->boolean('enable_ssl')->default(true)->change(); }); } }; ================================================ FILE: database/migrations/2025_03_29_204400_revert_some_local_volume_encryption.php ================================================ exists()) { echo "Found local_file_volumes table, proceeding with migration...\n"; // First, get all volumes and decrypt their values $decryptedVolumes = collect(); $totalVolumes = DB::table('local_file_volumes')->count(); echo "Total volumes to process: {$totalVolumes}\n"; DB::table('local_file_volumes') ->orderBy('id') ->chunk(100, function ($volumes) use (&$decryptedVolumes) { echo 'Processing chunk of '.count($volumes)." volumes...\n"; foreach ($volumes as $volume) { try { $fs_path = $volume->fs_path; $mount_path = $volume->mount_path; try { if ($fs_path) { $fs_path = Crypt::decryptString($fs_path); } } catch (\Exception $e) { echo "Warning: Could not decrypt fs_path for volume {$volume->id}\n"; } try { if ($mount_path) { $mount_path = Crypt::decryptString($mount_path); } } catch (\Exception $e) { echo "Warning: Could not decrypt mount_path for volume {$volume->id}\n"; } $decryptedVolumes->push([ 'id' => $volume->id, 'fs_path' => $fs_path, 'mount_path' => $mount_path, 'resource_id' => $volume->resource_id, 'resource_type' => $volume->resource_type, ]); } catch (\Exception $e) { echo "Error decrypting volume {$volume->id}: {$e->getMessage()}\n"; Log::error("Error decrypting volume {$volume->id}: ".$e->getMessage()); } } }); echo 'Finished processing all volumes. Found '.$decryptedVolumes->count()." total volumes.\n"; // Group by the unique constraint fields and keep only the first occurrence $uniqueVolumes = $decryptedVolumes->groupBy(function ($volume) { return $volume['mount_path'].'|'.$volume['resource_id'].'|'.$volume['resource_type']; })->map(function ($group) { return $group->first(); }); echo 'After deduplication, found '.$uniqueVolumes->count()." unique volumes.\n"; // Get IDs to delete (all except the ones we're keeping) $idsToKeep = $uniqueVolumes->pluck('id')->toArray(); $idsToDelete = $decryptedVolumes->pluck('id')->diff($idsToKeep)->toArray(); // Delete duplicate records if (! empty($idsToDelete)) { echo "\nFound ".count($idsToDelete)." duplicate volumes to delete.\n"; // Show details of volumes being deleted $volumesToDelete = $decryptedVolumes->whereIn('id', $idsToDelete); echo "\nVolumes to be deleted:\n"; foreach ($volumesToDelete as $volume) { echo "ID: {$volume['id']}, Mount Path: {$volume['mount_path']}, Resource ID: {$volume['resource_id']}, Resource Type: {$volume['resource_type']}\n"; echo "FS Path: {$volume['fs_path']}\n"; echo "-------------------\n"; } DB::table('local_file_volumes')->whereIn('id', $idsToDelete)->delete(); echo 'Deleted '.count($idsToDelete)." duplicate volume(s)\n"; } echo "\nUpdating remaining volumes with decrypted values...\n"; $updateCount = 0; // Update the remaining records with decrypted values foreach ($uniqueVolumes as $volume) { try { DB::table('local_file_volumes')->where('id', $volume['id'])->update([ 'fs_path' => $volume['fs_path'], 'mount_path' => $volume['mount_path'], ]); $updateCount++; } catch (\Exception $e) { echo "Error updating volume {$volume['id']}: {$e->getMessage()}\n"; Log::error("Error updating volume {$volume['id']}: ".$e->getMessage()); } } echo "Successfully updated {$updateCount} volumes.\n"; } else { echo "No local_file_volumes table found, skipping migration.\n"; } echo "Migration completed successfully.\n"; } /** * Reverse the migrations. */ public function down(): void { if (DB::table('local_file_volumes')->exists()) { DB::table('local_file_volumes') ->orderBy('id') ->chunk(100, function ($volumes) { foreach ($volumes as $volume) { DB::beginTransaction(); try { $fs_path = $volume->fs_path; $mount_path = $volume->mount_path; try { if ($fs_path) { $fs_path = Crypt::encrypt($fs_path); } } catch (\Exception $e) { } try { if ($mount_path) { $mount_path = Crypt::encrypt($mount_path); } } catch (\Exception $e) { } DB::table('local_file_volumes')->where('id', $volume->id)->update([ 'fs_path' => $fs_path, 'mount_path' => $mount_path, ]); echo "Updated volume {$volume->id}\n"; } catch (\Exception $e) { echo "Error decrypting local file volume fields: {$e->getMessage()}\n"; Log::error('Error decrypting local file volume fields: '.$e->getMessage()); } DB::commit(); } }); } } }; ================================================ FILE: database/migrations/2025_03_31_124212_add_specific_spa_configuration.php ================================================ boolean('is_spa')->default(false); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_spa'); }); } }; ================================================ FILE: database/migrations/2025_04_01_124212_stripe_comment_nullable.php ================================================ longText('stripe_comment')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->longText('stripe_comment')->nullable(false)->change(); }); } }; ================================================ FILE: database/migrations/2025_04_17_110026_add_application_http_basic_auth_fields.php ================================================ boolean('is_http_basic_auth_enabled')->default(false); $table->string('http_basic_auth_username')->nullable(true)->default(null); $table->string('http_basic_auth_password')->nullable(true)->default(null); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('is_http_basic_auth_enabled'); $table->dropColumn('http_basic_auth_username'); $table->dropColumn('http_basic_auth_password'); }); } }; ================================================ FILE: database/migrations/2025_04_30_134146_add_is_migrated_to_services.php ================================================ boolean('is_migrated')->default(false); }); Schema::table('service_databases', function (Blueprint $table) { $table->boolean('is_migrated')->default(false); $table->string('custom_type')->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('is_migrated'); }); Schema::table('service_databases', function (Blueprint $table) { $table->dropColumn('is_migrated'); $table->dropColumn('custom_type'); }); } }; ================================================ FILE: database/migrations/2025_05_26_100258_add_server_patch_notifications.php ================================================ boolean('server_patch_email_notifications')->default(true); }); // Add server patch notification fields to discord notification settings Schema::table('discord_notification_settings', function (Blueprint $table) { $table->boolean('server_patch_discord_notifications')->default(true); }); // Add server patch notification fields to telegram notification settings Schema::table('telegram_notification_settings', function (Blueprint $table) { $table->boolean('server_patch_telegram_notifications')->default(true); $table->string('telegram_notifications_server_patch_thread_id')->nullable(); }); // Add server patch notification fields to slack notification settings Schema::table('slack_notification_settings', function (Blueprint $table) { $table->boolean('server_patch_slack_notifications')->default(true); }); // Add server patch notification fields to pushover notification settings Schema::table('pushover_notification_settings', function (Blueprint $table) { $table->boolean('server_patch_pushover_notifications')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { // Remove server patch notification fields from email notification settings Schema::table('email_notification_settings', function (Blueprint $table) { $table->dropColumn('server_patch_email_notifications'); }); // Remove server patch notification fields from discord notification settings Schema::table('discord_notification_settings', function (Blueprint $table) { $table->dropColumn('server_patch_discord_notifications'); }); // Remove server patch notification fields from telegram notification settings Schema::table('telegram_notification_settings', function (Blueprint $table) { $table->dropColumn([ 'server_patch_telegram_notifications', 'telegram_notifications_server_patch_thread_id', ]); }); // Remove server patch notification fields from slack notification settings Schema::table('slack_notification_settings', function (Blueprint $table) { $table->dropColumn('server_patch_slack_notifications'); }); // Remove server patch notification fields from pushover notification settings Schema::table('pushover_notification_settings', function (Blueprint $table) { $table->dropColumn('server_patch_pushover_notifications'); }); } }; ================================================ FILE: database/migrations/2025_05_29_100258_add_terminal_enabled_to_server_settings.php ================================================ boolean('is_terminal_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('is_terminal_enabled'); }); } }; ================================================ FILE: database/migrations/2025_06_06_073345_create_server_previous_ip.php ================================================ string('ip_previous')->nullable()->after('ip'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('ip_previous'); }); } }; ================================================ FILE: database/migrations/2025_06_16_123532_change_sentinel_on_by_default.php ================================================ boolean('is_sentinel_enabled')->default(true)->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('server_settings', function (Blueprint $table) { $table->boolean('is_sentinel_enabled')->default(false)->change(); }); } }; ================================================ FILE: database/migrations/2025_06_25_131350_add_is_sponsorship_popup_enabled_to_instance_settings_table.php ================================================ boolean('is_sponsorship_popup_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('is_sponsorship_popup_enabled'); }); } }; ================================================ FILE: database/migrations/2025_06_26_131350_optimize_activity_log_indexes.php ================================================ >\'type_uuid\'), created_at DESC)'); // Add specific index for status queries on properties DB::unprepared('CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activity_properties_status ON activity_log ((properties->>\'status\'))'); } catch (\Exception $e) { Log::error('Error adding optimized indexes to activity_log: '.$e->getMessage()); } } /** * Reverse the migrations. */ public function down(): void { try { DB::unprepared('DROP INDEX CONCURRENTLY IF EXISTS idx_activity_type_uuid_created_at'); DB::unprepared('DROP INDEX CONCURRENTLY IF EXISTS idx_activity_properties_status'); } catch (\Exception $e) { Log::error('Error dropping optimized indexes from activity_log: '.$e->getMessage()); } } }; ================================================ FILE: database/migrations/2025_07_14_191016_add_deleted_at_to_application_previews_table.php ================================================ softDeletes(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_previews', function (Blueprint $table) { $table->dropSoftDeletes(); }); } }; ================================================ FILE: database/migrations/2025_07_16_202201_add_timeout_to_scheduled_database_backups_table.php ================================================ integer('timeout')->default(3600); }); } }; ================================================ FILE: database/migrations/2025_08_07_142403_create_user_changelog_reads_table.php ================================================ id(); $table->foreignId('user_id')->constrained()->onDelete('cascade'); $table->string('release_tag'); // GitHub tag_name (e.g., "v4.0.0-beta.420.6") $table->timestamp('read_at'); $table->timestamps(); $table->unique(['user_id', 'release_tag']); $table->index('user_id'); $table->index('release_tag'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('user_changelog_reads'); } }; ================================================ FILE: database/migrations/2025_08_17_102422_add_disable_local_backup_to_scheduled_database_backups_table.php ================================================ boolean('disable_local_backup')->default(false)->after('save_s3'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('scheduled_database_backups', function (Blueprint $table) { $table->dropColumn('disable_local_backup'); }); } }; ================================================ FILE: database/migrations/2025_08_18_104146_add_email_change_fields_to_users_table.php ================================================ string('pending_email')->nullable()->after('email'); $table->string('email_change_code', 6)->nullable()->after('pending_email'); $table->timestamp('email_change_code_expires_at')->nullable()->after('email_change_code'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn(['pending_email', 'email_change_code', 'email_change_code_expires_at']); }); } }; ================================================ FILE: database/migrations/2025_08_18_154244_change_env_sorting_default_to_false.php ================================================ boolean('is_env_sorting_enabled')->default(false)->change(); }); } }; ================================================ FILE: database/migrations/2025_08_21_080234_add_git_shallow_clone_to_application_settings_table.php ================================================ boolean('is_git_shallow_clone_enabled')->default(true)->after('is_git_lfs_enabled'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_git_shallow_clone_enabled'); }); } }; ================================================ FILE: database/migrations/2025_09_05_142446_add_pr_deployments_public_enabled_to_application_settings.php ================================================ boolean('is_pr_deployments_public_enabled')->default(false)->after('is_preview_deployments_enabled'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('is_pr_deployments_public_enabled'); }); } }; ================================================ FILE: database/migrations/2025_09_10_172952_remove_is_readonly_from_local_persistent_volumes_table.php ================================================ dropColumn('is_readonly'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('local_persistent_volumes', function (Blueprint $table) { $table->boolean('is_readonly')->default(false); }); } }; ================================================ FILE: database/migrations/2025_09_10_173300_drop_webhooks_table.php ================================================ id(); $table->enum('status', ['pending', 'success', 'failed'])->default('pending'); $table->string('type'); $table->longText('payload'); $table->longText('failure_reason')->nullable(); $table->timestamps(); }); } }; ================================================ FILE: database/migrations/2025_09_10_173402_drop_kubernetes_table.php ================================================ id(); $table->string('uuid')->unique(); $table->timestamps(); }); } }; ================================================ FILE: database/migrations/2025_09_11_143432_remove_is_build_time_from_environment_variables_table.php ================================================ dropColumn('is_build_time'); } }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { // Re-add the is_build_time column if (! Schema::hasColumn('environment_variables', 'is_build_time')) { $table->boolean('is_build_time')->default(false)->after('value'); } }); } }; ================================================ FILE: database/migrations/2025_09_11_150344_add_is_buildtime_only_to_environment_variables_table.php ================================================ boolean('is_buildtime_only')->default(false)->after('is_preview'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('is_buildtime_only'); }); } }; ================================================ FILE: database/migrations/2025_09_17_081112_add_use_build_secrets_to_application_settings.php ================================================ boolean('use_build_secrets')->default(false)->after('is_build_server_enabled'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('use_build_secrets'); }); } }; ================================================ FILE: database/migrations/2025_09_18_080152_add_runtime_and_buildtime_to_environment_variables_table.php ================================================ boolean('is_runtime')->default(true)->after('is_buildtime_only'); $table->boolean('is_buildtime')->default(true)->after('is_runtime'); }); // Migrate existing data from is_buildtime_only to new fields DB::table('environment_variables') ->where('is_buildtime_only', true) ->update([ 'is_runtime' => false, 'is_buildtime' => true, ]); DB::table('environment_variables') ->where('is_buildtime_only', false) ->update([ 'is_runtime' => true, 'is_buildtime' => true, ]); // Remove the old is_buildtime_only column Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('is_buildtime_only'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { // Re-add the is_buildtime_only column $table->boolean('is_buildtime_only')->default(false)->after('is_preview'); }); // Restore data to is_buildtime_only based on new fields DB::table('environment_variables') ->where('is_runtime', false) ->where('is_buildtime', true) ->update(['is_buildtime_only' => true]); DB::table('environment_variables') ->where('is_runtime', true) ->update(['is_buildtime_only' => false]); // Remove new columns Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn(['is_runtime', 'is_buildtime']); }); } }; ================================================ FILE: database/migrations/2025_10_03_154100_update_clickhouse_image.php ================================================ string('image')->default('bitnamilegacy/clickhouse')->change(); }); // Optionally, update any existing rows with the old default to the new one DB::table('standalone_clickhouses') ->where('image', 'bitnami/clickhouse') ->update(['image' => 'bitnamilegacy/clickhouse']); } public function down() { Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->string('image')->default('bitnami/clickhouse')->change(); }); // Optionally, revert any changed values DB::table('standalone_clickhouses') ->where('image', 'bitnamilegacy/clickhouse') ->update(['image' => 'bitnami/clickhouse']); } }; ================================================ FILE: database/migrations/2025_10_07_120723_add_s3_uploaded_to_scheduled_database_backup_executions_table.php ================================================ boolean('s3_uploaded')->nullable()->after('filename'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('scheduled_database_backup_executions', function (Blueprint $table) { $table->dropColumn('s3_uploaded'); }); } }; ================================================ FILE: database/migrations/2025_10_08_181125_create_cloud_provider_tokens_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->onDelete('cascade'); $table->string('provider'); $table->text('token'); $table->string('name')->nullable(); $table->timestamps(); $table->index(['team_id', 'provider']); }); } } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('cloud_provider_tokens'); } }; ================================================ FILE: database/migrations/2025_10_08_185203_add_hetzner_server_id_to_servers_table.php ================================================ bigInteger('hetzner_server_id')->nullable()->after('id'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('servers', 'hetzner_server_id')) { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('hetzner_server_id'); }); } } }; ================================================ FILE: database/migrations/2025_10_09_095905_add_cloud_provider_token_id_to_servers_table.php ================================================ foreignId('cloud_provider_token_id')->nullable()->after('private_key_id')->constrained()->onDelete('set null'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('servers', 'cloud_provider_token_id')) { Schema::table('servers', function (Blueprint $table) { $table->dropForeign(['cloud_provider_token_id']); $table->dropColumn('cloud_provider_token_id'); }); } } }; ================================================ FILE: database/migrations/2025_10_09_113602_add_hetzner_server_status_to_servers_table.php ================================================ string('hetzner_server_status')->nullable()->after('hetzner_server_id'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('servers', 'hetzner_server_status')) { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('hetzner_server_status'); }); } } }; ================================================ FILE: database/migrations/2025_10_09_125036_add_is_validating_to_servers_table.php ================================================ boolean('is_validating')->default(false)->after('hetzner_server_status'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('servers', 'is_validating')) { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('is_validating'); }); } } }; ================================================ FILE: database/migrations/2025_11_02_161923_add_dev_helper_version_to_instance_settings.php ================================================ string('dev_helper_version')->nullable(); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('instance_settings', 'dev_helper_version')) { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('dev_helper_version'); }); } } }; ================================================ FILE: database/migrations/2025_11_09_000001_add_timeout_to_scheduled_tasks_table.php ================================================ integer('timeout')->default(300)->after('frequency'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('scheduled_tasks', 'timeout')) { Schema::table('scheduled_tasks', function (Blueprint $table) { $table->dropColumn('timeout'); }); } } }; ================================================ FILE: database/migrations/2025_11_09_000002_improve_scheduled_task_executions_tracking.php ================================================ timestamp('started_at')->nullable()->after('scheduled_task_id'); }); } if (! Schema::hasColumn('scheduled_task_executions', 'retry_count')) { Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->integer('retry_count')->default(0)->after('status'); }); } if (! Schema::hasColumn('scheduled_task_executions', 'duration')) { Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->decimal('duration', 10, 2)->nullable()->after('retry_count')->comment('Duration in seconds'); }); } if (! Schema::hasColumn('scheduled_task_executions', 'error_details')) { Schema::table('scheduled_task_executions', function (Blueprint $table) { $table->text('error_details')->nullable()->after('message'); }); } } /** * Reverse the migrations. */ public function down(): void { $columns = ['started_at', 'retry_count', 'duration', 'error_details']; foreach ($columns as $column) { if (Schema::hasColumn('scheduled_task_executions', $column)) { Schema::table('scheduled_task_executions', function (Blueprint $table) use ($column) { $table->dropColumn($column); }); } } } }; ================================================ FILE: database/migrations/2025_11_10_112500_add_restart_tracking_to_applications_table.php ================================================ integer('restart_count')->default(0)->after('status'); }); } if (! Schema::hasColumn('applications', 'last_restart_at')) { Schema::table('applications', function (Blueprint $table) { $table->timestamp('last_restart_at')->nullable()->after('restart_count'); }); } if (! Schema::hasColumn('applications', 'last_restart_type')) { Schema::table('applications', function (Blueprint $table) { $table->string('last_restart_type', 10)->nullable()->after('last_restart_at'); }); } } /** * Reverse the migrations. */ public function down(): void { $columns = ['restart_count', 'last_restart_at', 'last_restart_type']; foreach ($columns as $column) { if (Schema::hasColumn('applications', $column)) { Schema::table('applications', function (Blueprint $table) use ($column) { $table->dropColumn($column); }); } } } }; ================================================ FILE: database/migrations/2025_11_12_130931_add_traefik_version_tracking_to_servers_table.php ================================================ string('detected_traefik_version')->nullable(); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('servers', 'detected_traefik_version')) { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('detected_traefik_version'); }); } } }; ================================================ FILE: database/migrations/2025_11_12_131252_add_traefik_outdated_to_email_notification_settings.php ================================================ boolean('traefik_outdated_email_notifications')->default(true); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('email_notification_settings', 'traefik_outdated_email_notifications')) { Schema::table('email_notification_settings', function (Blueprint $table) { $table->dropColumn('traefik_outdated_email_notifications'); }); } } }; ================================================ FILE: database/migrations/2025_11_12_133400_add_traefik_outdated_thread_id_to_telegram_notification_settings.php ================================================ text('telegram_notifications_traefik_outdated_thread_id')->nullable(); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('telegram_notification_settings', 'telegram_notifications_traefik_outdated_thread_id')) { Schema::table('telegram_notification_settings', function (Blueprint $table) { $table->dropColumn('telegram_notifications_traefik_outdated_thread_id'); }); } } }; ================================================ FILE: database/migrations/2025_11_14_114632_add_traefik_outdated_info_to_servers_table.php ================================================ json('traefik_outdated_info')->nullable(); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('servers', 'traefik_outdated_info')) { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('traefik_outdated_info'); }); } } }; ================================================ FILE: database/migrations/2025_11_16_000001_create_webhook_notification_settings_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->boolean('webhook_enabled')->default(false); $table->text('webhook_url')->nullable(); $table->boolean('deployment_success_webhook_notifications')->default(false); $table->boolean('deployment_failure_webhook_notifications')->default(true); $table->boolean('status_change_webhook_notifications')->default(false); $table->boolean('backup_success_webhook_notifications')->default(false); $table->boolean('backup_failure_webhook_notifications')->default(true); $table->boolean('scheduled_task_success_webhook_notifications')->default(false); $table->boolean('scheduled_task_failure_webhook_notifications')->default(true); $table->boolean('docker_cleanup_success_webhook_notifications')->default(false); $table->boolean('docker_cleanup_failure_webhook_notifications')->default(true); $table->boolean('server_disk_usage_webhook_notifications')->default(true); $table->boolean('server_reachable_webhook_notifications')->default(false); $table->boolean('server_unreachable_webhook_notifications')->default(true); $table->boolean('server_patch_webhook_notifications')->default(false); $table->boolean('traefik_outdated_webhook_notifications')->default(true); $table->unique(['team_id']); }); } // Populate webhook notification settings for existing teams (only if they don't already have settings) DB::table('teams')->chunkById(100, function ($teams) { foreach ($teams as $team) { try { // Check if settings already exist for this team $exists = DB::table('webhook_notification_settings') ->where('team_id', $team->id) ->exists(); if (! $exists) { // Only insert if no settings exist - don't overwrite existing preferences DB::table('webhook_notification_settings')->insert([ 'team_id' => $team->id, 'webhook_enabled' => false, 'webhook_url' => null, 'deployment_success_webhook_notifications' => false, 'deployment_failure_webhook_notifications' => true, 'status_change_webhook_notifications' => false, 'backup_success_webhook_notifications' => false, 'backup_failure_webhook_notifications' => true, 'scheduled_task_success_webhook_notifications' => false, 'scheduled_task_failure_webhook_notifications' => true, 'docker_cleanup_success_webhook_notifications' => false, 'docker_cleanup_failure_webhook_notifications' => true, 'server_disk_usage_webhook_notifications' => true, 'server_reachable_webhook_notifications' => false, 'server_unreachable_webhook_notifications' => true, 'server_patch_webhook_notifications' => false, 'traefik_outdated_webhook_notifications' => true, ]); } } catch (\Throwable $e) { Log::error('Error creating webhook notification settings for team '.$team->id.': '.$e->getMessage()); } } }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('webhook_notification_settings'); } }; ================================================ FILE: database/migrations/2025_11_16_000002_create_cloud_init_scripts_table.php ================================================ id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->string('name'); $table->text('script'); // Encrypted in the model $table->timestamps(); }); } } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('cloud_init_scripts'); } }; ================================================ FILE: database/migrations/2025_11_17_092707_add_traefik_outdated_to_notification_settings.php ================================================ boolean('traefik_outdated_discord_notifications')->default(true); }); Schema::table('slack_notification_settings', function (Blueprint $table) { $table->boolean('traefik_outdated_slack_notifications')->default(true); }); // Only add if table exists and column doesn't exist if (Schema::hasTable('webhook_notification_settings') && ! Schema::hasColumn('webhook_notification_settings', 'traefik_outdated_webhook_notifications')) { Schema::table('webhook_notification_settings', function (Blueprint $table) { $table->boolean('traefik_outdated_webhook_notifications')->default(true); }); } Schema::table('telegram_notification_settings', function (Blueprint $table) { $table->boolean('traefik_outdated_telegram_notifications')->default(true); }); Schema::table('pushover_notification_settings', function (Blueprint $table) { $table->boolean('traefik_outdated_pushover_notifications')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('discord_notification_settings', function (Blueprint $table) { $table->dropColumn('traefik_outdated_discord_notifications'); }); Schema::table('slack_notification_settings', function (Blueprint $table) { $table->dropColumn('traefik_outdated_slack_notifications'); }); // Only drop if table and column exist if (Schema::hasTable('webhook_notification_settings') && Schema::hasColumn('webhook_notification_settings', 'traefik_outdated_webhook_notifications')) { Schema::table('webhook_notification_settings', function (Blueprint $table) { $table->dropColumn('traefik_outdated_webhook_notifications'); }); } Schema::table('telegram_notification_settings', function (Blueprint $table) { $table->dropColumn('traefik_outdated_telegram_notifications'); }); Schema::table('pushover_notification_settings', function (Blueprint $table) { $table->dropColumn('traefik_outdated_pushover_notifications'); }); } }; ================================================ FILE: database/migrations/2025_11_17_145255_add_comment_to_environment_variables_table.php ================================================ string('comment', 256)->nullable(); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->string('comment', 256)->nullable(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('environment_variables', function (Blueprint $table) { $table->dropColumn('comment'); }); Schema::table('shared_environment_variables', function (Blueprint $table) { $table->dropColumn('comment'); }); } }; ================================================ FILE: database/migrations/2025_11_18_083747_cleanup_dockerfile_data_for_non_dockerfile_buildpacks.php ================================================ where('build_pack', '!=', 'dockerfile') ->update([ 'dockerfile' => null, 'dockerfile_location' => null, 'dockerfile_target_build' => null, 'custom_healthcheck_found' => false, ]); } /** * Reverse the migrations. */ public function down(): void { // No rollback needed - we're cleaning up corrupt data } }; ================================================ FILE: database/migrations/2025_11_26_124200_add_build_cache_settings_to_application_settings.php ================================================ boolean('inject_build_args_to_dockerfile')->default(true)->after('use_build_secrets'); }); } if (! Schema::hasColumn('application_settings', 'include_source_commit_in_build')) { Schema::table('application_settings', function (Blueprint $table) { $table->boolean('include_source_commit_in_build')->default(false)->after('inject_build_args_to_dockerfile'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('application_settings', 'inject_build_args_to_dockerfile')) { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('inject_build_args_to_dockerfile'); }); } if (Schema::hasColumn('application_settings', 'include_source_commit_in_build')) { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('include_source_commit_in_build'); }); } } }; ================================================ FILE: database/migrations/2025_11_28_000001_migrate_clickhouse_to_official_image.php ================================================ string('clickhouse_db') ->default('default') ->after('clickhouse_admin_password'); }); } // Change the default value for the 'image' column to the official image Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->string('image')->default('clickhouse/clickhouse-server:25.11')->change(); }); // Update existing ClickHouse instances from Bitnami images to official image StandaloneClickhouse::where(function ($query) { $query->where('image', 'like', '%bitnami/clickhouse%') ->orWhere('image', 'like', '%bitnamilegacy/clickhouse%'); }) ->update([ 'image' => 'clickhouse/clickhouse-server:25.11', 'clickhouse_db' => DB::raw("COALESCE(clickhouse_db, 'default')"), ]); // Update volume mount paths from Bitnami to official image paths LocalPersistentVolume::where('resource_type', StandaloneClickhouse::class) ->where('mount_path', '/bitnami/clickhouse') ->update(['mount_path' => '/var/lib/clickhouse']); } /** * Reverse the migrations. */ public function down(): void { // Revert the default value for the 'image' column Schema::table('standalone_clickhouses', function (Blueprint $table) { $table->string('image')->default('bitnamilegacy/clickhouse')->change(); }); // Revert existing ClickHouse instances back to Bitnami image StandaloneClickhouse::where('image', 'clickhouse/clickhouse-server:25.11') ->update(['image' => 'bitnamilegacy/clickhouse']); // Revert volume mount paths LocalPersistentVolume::where('resource_type', StandaloneClickhouse::class) ->where('mount_path', '/var/lib/clickhouse') ->update(['mount_path' => '/bitnami/clickhouse']); } }; ================================================ FILE: database/migrations/2025_12_04_134435_add_deployment_queue_limit_to_server_settings.php ================================================ integer('deployment_queue_limit')->default(25)->after('concurrent_builds'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('server_settings', 'deployment_queue_limit')) { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('deployment_queue_limit'); }); } } }; ================================================ FILE: database/migrations/2025_12_05_000000_add_docker_images_to_keep_to_application_settings.php ================================================ integer('docker_images_to_keep')->default(2); }); } } public function down(): void { if (Schema::hasColumn('application_settings', 'docker_images_to_keep')) { Schema::table('application_settings', function (Blueprint $table) { $table->dropColumn('docker_images_to_keep'); }); } } }; ================================================ FILE: database/migrations/2025_12_05_100000_add_disable_application_image_retention_to_server_settings.php ================================================ boolean('disable_application_image_retention')->default(false); }); } } public function down(): void { if (Schema::hasColumn('server_settings', 'disable_application_image_retention')) { Schema::table('server_settings', function (Blueprint $table) { $table->dropColumn('disable_application_image_retention'); }); } } }; ================================================ FILE: database/migrations/2025_12_08_135600_add_performance_indexes.php ================================================ getDriverName() !== 'pgsql') { return; } foreach ($this->indexes as [$table, $columns, $indexName]) { if (! $this->indexExists($indexName)) { $columnList = implode(', ', array_map(fn ($col) => "\"$col\"", $columns)); DB::statement("CREATE INDEX \"{$indexName}\" ON \"{$table}\" ({$columnList})"); } } } public function down(): void { if (DB::connection()->getDriverName() !== 'pgsql') { return; } foreach ($this->indexes as [, , $indexName]) { DB::statement("DROP INDEX IF EXISTS \"{$indexName}\""); } } private function indexExists(string $indexName): bool { $result = DB::selectOne( 'SELECT 1 FROM pg_indexes WHERE indexname = ?', [$indexName] ); return $result !== null; } }; ================================================ FILE: database/migrations/2025_12_10_135600_add_uuid_to_cloud_provider_tokens.php ================================================ string('uuid')->nullable()->unique()->after('id'); }); // Generate UUIDs for existing records using chunked processing DB::table('cloud_provider_tokens') ->whereNull('uuid') ->chunkById(500, function ($tokens) { foreach ($tokens as $token) { DB::table('cloud_provider_tokens') ->where('id', $token->id) ->update(['uuid' => (string) new Cuid2]); } }); // Make uuid non-nullable after filling in values Schema::table('cloud_provider_tokens', function (Blueprint $table) { $table->string('uuid')->nullable(false)->change(); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('cloud_provider_tokens', 'uuid')) { Schema::table('cloud_provider_tokens', function (Blueprint $table) { $table->dropColumn('uuid'); }); } } }; ================================================ FILE: database/migrations/2025_12_15_143052_trim_s3_storage_credentials.php ================================================ select(['id', 'key', 'secret', 'endpoint', 'bucket', 'region']) ->orderBy('id') ->chunk(100, function ($storages) { foreach ($storages as $storage) { try { DB::transaction(function () use ($storage) { $updates = []; // Trim endpoint (not encrypted) if ($storage->endpoint !== null) { $trimmedEndpoint = trim($storage->endpoint); if ($trimmedEndpoint !== $storage->endpoint) { $updates['endpoint'] = $trimmedEndpoint; } } // Trim bucket (not encrypted) if ($storage->bucket !== null) { $trimmedBucket = trim($storage->bucket); if ($trimmedBucket !== $storage->bucket) { $updates['bucket'] = $trimmedBucket; } } // Trim region (not encrypted) if ($storage->region !== null) { $trimmedRegion = trim($storage->region); if ($trimmedRegion !== $storage->region) { $updates['region'] = $trimmedRegion; } } // Trim key (encrypted) - verify re-encryption works before saving if ($storage->key !== null) { try { $decryptedKey = Crypt::decryptString($storage->key); $trimmedKey = trim($decryptedKey); if ($trimmedKey !== $decryptedKey) { $encryptedKey = Crypt::encryptString($trimmedKey); // Verify the new encryption is valid if (Crypt::decryptString($encryptedKey) === $trimmedKey) { $updates['key'] = $encryptedKey; } else { Log::warning("S3 storage ID {$storage->id}: Re-encryption verification failed for key, skipping"); } } } catch (\Throwable $e) { Log::warning("Could not decrypt S3 storage key for ID {$storage->id}: ".$e->getMessage()); } } // Trim secret (encrypted) - verify re-encryption works before saving if ($storage->secret !== null) { try { $decryptedSecret = Crypt::decryptString($storage->secret); $trimmedSecret = trim($decryptedSecret); if ($trimmedSecret !== $decryptedSecret) { $encryptedSecret = Crypt::encryptString($trimmedSecret); // Verify the new encryption is valid if (Crypt::decryptString($encryptedSecret) === $trimmedSecret) { $updates['secret'] = $encryptedSecret; } else { Log::warning("S3 storage ID {$storage->id}: Re-encryption verification failed for secret, skipping"); } } } catch (\Throwable $e) { Log::warning("Could not decrypt S3 storage secret for ID {$storage->id}: ".$e->getMessage()); } } if (! empty($updates)) { DB::table('s3_storages')->where('id', $storage->id)->update($updates); Log::info("Trimmed whitespace from S3 storage credentials for ID {$storage->id}", [ 'fields_updated' => array_keys($updates), ]); } }); } catch (\Throwable $e) { Log::error("Failed to process S3 storage ID {$storage->id}: ".$e->getMessage()); // Continue with next record instead of failing entire migration } } }); } /** * Reverse the migrations. */ public function down(): void { // Cannot reverse trimming operation } }; ================================================ FILE: database/migrations/2025_12_17_000001_add_is_wire_navigate_enabled_to_instance_settings_table.php ================================================ boolean('is_wire_navigate_enabled')->default(true); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('instance_settings', function (Blueprint $table) { $table->dropColumn('is_wire_navigate_enabled'); }); } }; ================================================ FILE: database/migrations/2025_12_17_000002_add_restart_tracking_to_standalone_databases.php ================================================ tables as $table) { if (! Schema::hasColumn($table, 'restart_count')) { Schema::table($table, function (Blueprint $blueprint) { $blueprint->integer('restart_count')->default(0)->after('status'); }); } if (! Schema::hasColumn($table, 'last_restart_at')) { Schema::table($table, function (Blueprint $blueprint) { $blueprint->timestamp('last_restart_at')->nullable()->after('restart_count'); }); } if (! Schema::hasColumn($table, 'last_restart_type')) { Schema::table($table, function (Blueprint $blueprint) { $blueprint->string('last_restart_type', 10)->nullable()->after('last_restart_at'); }); } } } /** * Reverse the migrations. */ public function down(): void { $columns = ['restart_count', 'last_restart_at', 'last_restart_type']; foreach ($this->tables as $table) { foreach ($columns as $column) { if (Schema::hasColumn($table, $column)) { Schema::table($table, function (Blueprint $blueprint) use ($column) { $blueprint->dropColumn($column); }); } } } } }; ================================================ FILE: database/migrations/2025_12_25_072315_add_cmd_healthcheck_to_applications_table.php ================================================ text('health_check_type')->default('http')->after('health_check_enabled'); }); } if (! Schema::hasColumn('applications', 'health_check_command')) { Schema::table('applications', function (Blueprint $table) { $table->text('health_check_command')->nullable()->after('health_check_type'); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('applications', 'health_check_type')) { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('health_check_type'); }); } if (Schema::hasColumn('applications', 'health_check_command')) { Schema::table('applications', function (Blueprint $table) { $table->dropColumn('health_check_command'); }); } } }; ================================================ FILE: database/migrations/2026_02_26_163035_add_stripe_refunded_at_to_subscriptions_table.php ================================================ timestamp('stripe_refunded_at')->nullable()->after('stripe_past_due'); }); } public function down(): void { Schema::table('subscriptions', function (Blueprint $table) { $table->dropColumn('stripe_refunded_at'); }); } }; ================================================ FILE: database/migrations/2026_02_27_000000_add_public_port_timeout_to_databases.php ================================================ integer('public_port_timeout')->nullable()->default(3600)->after('public_port'); }); } } } /** * Reverse the migrations. */ public function down(): void { $tables = [ 'standalone_postgresqls', 'standalone_mysqls', 'standalone_mariadbs', 'standalone_redis', 'standalone_mongodbs', 'standalone_clickhouses', 'standalone_keydbs', 'standalone_dragonflies', 'service_databases', ]; foreach ($tables as $table) { if (Schema::hasTable($table) && Schema::hasColumn($table, 'public_port_timeout')) { Schema::table($table, function (Blueprint $table) { $table->dropColumn('public_port_timeout'); }); } } } }; ================================================ FILE: database/migrations/2026_03_11_000000_add_server_metadata_to_servers_table.php ================================================ json('server_metadata')->nullable(); }); } } /** * Reverse the migrations. */ public function down(): void { if (Schema::hasColumn('servers', 'server_metadata')) { Schema::table('servers', function (Blueprint $table) { $table->dropColumn('server_metadata'); }); } } }; ================================================ FILE: database/schema/testing-schema.sql ================================================ -- Generated by: php artisan schema:generate-testing -- Date: 2026-02-11 13:10:01 -- Last migration: 2025_12_17_000002_add_restart_tracking_to_standalone_databases CREATE TABLE IF NOT EXISTS "activity_log" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "log_name" TEXT, "description" TEXT NOT NULL, "subject_type" TEXT, "subject_id" INTEGER, "causer_type" TEXT, "causer_id" INTEGER, "properties" TEXT, "created_at" TEXT, "updated_at" TEXT, "event" TEXT, "batch_uuid" TEXT ); CREATE TABLE IF NOT EXISTS "additional_destinations" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "application_id" INTEGER NOT NULL, "server_id" INTEGER NOT NULL, "status" TEXT DEFAULT 'exited' NOT NULL, "standalone_docker_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "application_deployment_queues" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "application_id" TEXT NOT NULL, "deployment_uuid" TEXT NOT NULL, "pull_request_id" INTEGER DEFAULT 0 NOT NULL, "force_rebuild" INTEGER DEFAULT false NOT NULL, "commit" TEXT DEFAULT 'HEAD' NOT NULL, "status" TEXT DEFAULT 'queued' NOT NULL, "is_webhook" INTEGER DEFAULT false NOT NULL, "created_at" TEXT, "updated_at" TEXT, "logs" TEXT, "current_process_id" TEXT, "restart_only" INTEGER DEFAULT false NOT NULL, "git_type" TEXT, "server_id" INTEGER, "application_name" TEXT, "server_name" TEXT, "deployment_url" TEXT, "destination_id" TEXT, "only_this_server" INTEGER DEFAULT false NOT NULL, "rollback" INTEGER DEFAULT false NOT NULL, "commit_message" TEXT, "is_api" INTEGER DEFAULT false NOT NULL, "build_server_id" INTEGER, "horizon_job_id" TEXT, "horizon_job_worker" TEXT, "finished_at" TEXT ); CREATE TABLE IF NOT EXISTS "application_previews" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "pull_request_id" INTEGER NOT NULL, "pull_request_html_url" TEXT NOT NULL, "pull_request_issue_comment_id" TEXT, "fqdn" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "application_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "git_type" TEXT, "docker_compose_domains" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "deleted_at" TEXT ); CREATE TABLE IF NOT EXISTS "application_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "is_static" INTEGER DEFAULT false NOT NULL, "is_git_submodules_enabled" INTEGER DEFAULT true NOT NULL, "is_git_lfs_enabled" INTEGER DEFAULT true NOT NULL, "is_auto_deploy_enabled" INTEGER DEFAULT true NOT NULL, "is_force_https_enabled" INTEGER DEFAULT true NOT NULL, "is_debug_enabled" INTEGER DEFAULT false NOT NULL, "is_preview_deployments_enabled" INTEGER DEFAULT false NOT NULL, "application_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_gpu_enabled" INTEGER DEFAULT false NOT NULL, "gpu_driver" TEXT DEFAULT 'nvidia' NOT NULL, "gpu_count" TEXT, "gpu_device_ids" TEXT, "gpu_options" TEXT, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "is_swarm_only_worker_nodes" INTEGER DEFAULT true NOT NULL, "is_raw_compose_deployment_enabled" INTEGER DEFAULT false NOT NULL, "is_build_server_enabled" INTEGER DEFAULT false NOT NULL, "is_consistent_container_name_enabled" INTEGER DEFAULT false NOT NULL, "is_gzip_enabled" INTEGER DEFAULT true NOT NULL, "is_stripprefix_enabled" INTEGER DEFAULT true NOT NULL, "connect_to_docker_network" INTEGER DEFAULT false NOT NULL, "custom_internal_name" TEXT, "is_container_label_escape_enabled" INTEGER DEFAULT true NOT NULL, "is_env_sorting_enabled" INTEGER DEFAULT false NOT NULL, "is_container_label_readonly_enabled" INTEGER DEFAULT true NOT NULL, "is_preserve_repository_enabled" INTEGER DEFAULT false NOT NULL, "disable_build_cache" INTEGER DEFAULT false NOT NULL, "is_spa" INTEGER DEFAULT false NOT NULL, "is_git_shallow_clone_enabled" INTEGER DEFAULT true NOT NULL, "is_pr_deployments_public_enabled" INTEGER DEFAULT false NOT NULL, "use_build_secrets" INTEGER DEFAULT false NOT NULL, "inject_build_args_to_dockerfile" INTEGER DEFAULT true NOT NULL, "include_source_commit_in_build" INTEGER DEFAULT false NOT NULL, "docker_images_to_keep" INTEGER DEFAULT 2 NOT NULL ); CREATE TABLE IF NOT EXISTS "applications" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "repository_project_id" INTEGER, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "fqdn" TEXT, "config_hash" TEXT, "git_repository" TEXT NOT NULL, "git_branch" TEXT NOT NULL, "git_commit_sha" TEXT DEFAULT 'HEAD' NOT NULL, "git_full_url" TEXT, "docker_registry_image_name" TEXT, "docker_registry_image_tag" TEXT, "build_pack" TEXT NOT NULL, "static_image" TEXT DEFAULT 'nginx:alpine' NOT NULL, "install_command" TEXT, "build_command" TEXT, "start_command" TEXT, "ports_exposes" TEXT NOT NULL, "ports_mappings" TEXT, "base_directory" TEXT DEFAULT '/' NOT NULL, "publish_directory" TEXT, "health_check_path" TEXT DEFAULT '/' NOT NULL, "health_check_port" TEXT, "health_check_host" TEXT DEFAULT 'localhost' NOT NULL, "health_check_method" TEXT DEFAULT 'GET' NOT NULL, "health_check_return_code" INTEGER DEFAULT 200 NOT NULL, "health_check_scheme" TEXT DEFAULT 'http' NOT NULL, "health_check_response_text" TEXT, "health_check_interval" INTEGER DEFAULT 5 NOT NULL, "health_check_timeout" INTEGER DEFAULT 5 NOT NULL, "health_check_retries" INTEGER DEFAULT 10 NOT NULL, "health_check_start_period" INTEGER DEFAULT 5 NOT NULL, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "status" TEXT DEFAULT 'exited' NOT NULL, "preview_url_template" TEXT DEFAULT '{{pr_id}}.{{domain}}' NOT NULL, "destination_type" TEXT, "destination_id" INTEGER, "source_type" TEXT, "source_id" INTEGER, "private_key_id" INTEGER, "environment_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "description" TEXT, "dockerfile" TEXT, "health_check_enabled" INTEGER DEFAULT false NOT NULL, "dockerfile_location" TEXT, "custom_labels" TEXT, "dockerfile_target_build" TEXT, "manual_webhook_secret_github" TEXT, "manual_webhook_secret_gitlab" TEXT, "docker_compose_location" TEXT DEFAULT '/docker-compose.yaml', "docker_compose" TEXT, "docker_compose_raw" TEXT, "docker_compose_domains" TEXT, "deleted_at" TEXT, "docker_compose_custom_start_command" TEXT, "docker_compose_custom_build_command" TEXT, "swarm_replicas" INTEGER DEFAULT 1 NOT NULL, "swarm_placement_constraints" TEXT, "manual_webhook_secret_bitbucket" TEXT, "custom_docker_run_options" TEXT, "post_deployment_command" TEXT, "post_deployment_command_container" TEXT, "pre_deployment_command" TEXT, "pre_deployment_command_container" TEXT, "watch_paths" TEXT, "custom_healthcheck_found" INTEGER DEFAULT false NOT NULL, "manual_webhook_secret_gitea" TEXT, "redirect" TEXT DEFAULT 'both' NOT NULL, "compose_parsing_version" TEXT DEFAULT '1' NOT NULL, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "custom_nginx_configuration" TEXT, "custom_network_aliases" TEXT, "is_http_basic_auth_enabled" INTEGER DEFAULT false NOT NULL, "http_basic_auth_username" TEXT, "http_basic_auth_password" TEXT, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "cloud_init_scripts" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "name" TEXT NOT NULL, "script" TEXT NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "cloud_provider_tokens" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "provider" TEXT NOT NULL, "token" TEXT NOT NULL, "name" TEXT, "created_at" TEXT, "updated_at" TEXT, "uuid" TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS "discord_notification_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "discord_enabled" INTEGER DEFAULT false NOT NULL, "discord_webhook_url" TEXT, "deployment_success_discord_notifications" INTEGER DEFAULT false NOT NULL, "deployment_failure_discord_notifications" INTEGER DEFAULT true NOT NULL, "status_change_discord_notifications" INTEGER DEFAULT false NOT NULL, "backup_success_discord_notifications" INTEGER DEFAULT false NOT NULL, "backup_failure_discord_notifications" INTEGER DEFAULT true NOT NULL, "scheduled_task_success_discord_notifications" INTEGER DEFAULT false NOT NULL, "scheduled_task_failure_discord_notifications" INTEGER DEFAULT true NOT NULL, "docker_cleanup_success_discord_notifications" INTEGER DEFAULT false NOT NULL, "docker_cleanup_failure_discord_notifications" INTEGER DEFAULT true NOT NULL, "server_disk_usage_discord_notifications" INTEGER DEFAULT true NOT NULL, "server_reachable_discord_notifications" INTEGER DEFAULT false NOT NULL, "server_unreachable_discord_notifications" INTEGER DEFAULT true NOT NULL, "discord_ping_enabled" INTEGER DEFAULT true NOT NULL, "server_patch_discord_notifications" INTEGER DEFAULT true NOT NULL, "traefik_outdated_discord_notifications" INTEGER DEFAULT true NOT NULL ); CREATE TABLE IF NOT EXISTS "docker_cleanup_executions" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "status" TEXT DEFAULT 'running' NOT NULL, "message" TEXT, "cleanup_log" TEXT, "server_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "finished_at" TEXT ); CREATE TABLE IF NOT EXISTS "email_notification_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "smtp_enabled" INTEGER DEFAULT false NOT NULL, "smtp_from_address" TEXT, "smtp_from_name" TEXT, "smtp_recipients" TEXT, "smtp_host" TEXT, "smtp_port" INTEGER, "smtp_encryption" TEXT, "smtp_username" TEXT, "smtp_password" TEXT, "smtp_timeout" INTEGER, "resend_enabled" INTEGER DEFAULT false NOT NULL, "resend_api_key" TEXT, "use_instance_email_settings" INTEGER DEFAULT false NOT NULL, "deployment_success_email_notifications" INTEGER DEFAULT false NOT NULL, "deployment_failure_email_notifications" INTEGER DEFAULT true NOT NULL, "status_change_email_notifications" INTEGER DEFAULT false NOT NULL, "backup_success_email_notifications" INTEGER DEFAULT false NOT NULL, "backup_failure_email_notifications" INTEGER DEFAULT true NOT NULL, "scheduled_task_success_email_notifications" INTEGER DEFAULT false NOT NULL, "scheduled_task_failure_email_notifications" INTEGER DEFAULT true NOT NULL, "docker_cleanup_success_email_notifications" INTEGER DEFAULT false NOT NULL, "docker_cleanup_failure_email_notifications" INTEGER DEFAULT true NOT NULL, "server_disk_usage_email_notifications" INTEGER DEFAULT true NOT NULL, "server_reachable_email_notifications" INTEGER DEFAULT false NOT NULL, "server_unreachable_email_notifications" INTEGER DEFAULT true NOT NULL, "server_patch_email_notifications" INTEGER DEFAULT true NOT NULL, "traefik_outdated_email_notifications" INTEGER DEFAULT true NOT NULL ); CREATE TABLE IF NOT EXISTS "environment_variables" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "key" TEXT NOT NULL, "value" TEXT, "is_preview" INTEGER DEFAULT false NOT NULL, "created_at" TEXT, "updated_at" TEXT, "is_shown_once" INTEGER DEFAULT false NOT NULL, "is_multiline" INTEGER DEFAULT false NOT NULL, "version" TEXT DEFAULT '4.0.0-beta.239' NOT NULL, "is_literal" INTEGER DEFAULT false NOT NULL, "uuid" TEXT NOT NULL, "order" INTEGER, "is_required" INTEGER DEFAULT false NOT NULL, "is_shared" INTEGER DEFAULT false NOT NULL, "resourceable_type" TEXT, "resourceable_id" INTEGER, "is_runtime" INTEGER DEFAULT true NOT NULL, "is_buildtime" INTEGER DEFAULT true NOT NULL ); CREATE TABLE IF NOT EXISTS "environments" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" TEXT NOT NULL, "project_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "description" TEXT, "uuid" TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS "failed_jobs" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "connection" TEXT NOT NULL, "queue" TEXT NOT NULL, "payload" TEXT NOT NULL, "exception" TEXT NOT NULL, "failed_at" TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL ); CREATE TABLE IF NOT EXISTS "github_apps" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "organization" TEXT, "api_url" TEXT NOT NULL, "html_url" TEXT NOT NULL, "custom_user" TEXT DEFAULT 'git' NOT NULL, "custom_port" INTEGER DEFAULT 22 NOT NULL, "app_id" INTEGER, "installation_id" INTEGER, "client_id" TEXT, "client_secret" TEXT, "webhook_secret" TEXT, "is_system_wide" INTEGER DEFAULT false NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "private_key_id" INTEGER, "team_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "contents" TEXT, "metadata" TEXT, "pull_requests" TEXT, "administration" TEXT ); CREATE TABLE IF NOT EXISTS "gitlab_apps" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "organization" TEXT, "api_url" TEXT NOT NULL, "html_url" TEXT NOT NULL, "custom_port" INTEGER DEFAULT 22 NOT NULL, "custom_user" TEXT DEFAULT 'git' NOT NULL, "is_system_wide" INTEGER DEFAULT false NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "app_id" INTEGER, "app_secret" TEXT, "oauth_id" INTEGER, "group_name" TEXT, "public_key" TEXT, "webhook_token" TEXT, "deploy_key_id" INTEGER, "private_key_id" INTEGER, "team_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "instance_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "public_ipv4" TEXT, "public_ipv6" TEXT, "fqdn" TEXT, "public_port_min" INTEGER DEFAULT 9000 NOT NULL, "public_port_max" INTEGER DEFAULT 9100 NOT NULL, "do_not_track" INTEGER DEFAULT false NOT NULL, "is_auto_update_enabled" INTEGER DEFAULT true NOT NULL, "is_registration_enabled" INTEGER DEFAULT true NOT NULL, "created_at" TEXT, "updated_at" TEXT, "next_channel" INTEGER DEFAULT false NOT NULL, "smtp_enabled" INTEGER DEFAULT false NOT NULL, "smtp_from_address" TEXT, "smtp_from_name" TEXT, "smtp_recipients" TEXT, "smtp_host" TEXT, "smtp_port" INTEGER, "smtp_encryption" TEXT, "smtp_username" TEXT, "smtp_password" TEXT, "smtp_timeout" INTEGER, "resend_enabled" INTEGER DEFAULT false NOT NULL, "resend_api_key" TEXT, "is_dns_validation_enabled" INTEGER DEFAULT true NOT NULL, "custom_dns_servers" TEXT DEFAULT '1.1.1.1', "instance_name" TEXT, "is_api_enabled" INTEGER DEFAULT false NOT NULL, "allowed_ips" TEXT, "auto_update_frequency" TEXT DEFAULT '0 0 * * *' NOT NULL, "update_check_frequency" TEXT DEFAULT '0 * * * *' NOT NULL, "new_version_available" INTEGER DEFAULT false NOT NULL, "instance_timezone" TEXT DEFAULT 'UTC' NOT NULL, "helper_version" TEXT DEFAULT '1.0.0' NOT NULL, "disable_two_step_confirmation" INTEGER DEFAULT false NOT NULL, "is_sponsorship_popup_enabled" INTEGER DEFAULT true NOT NULL, "dev_helper_version" TEXT, "is_wire_navigate_enabled" INTEGER DEFAULT true NOT NULL ); CREATE TABLE IF NOT EXISTS "local_file_volumes" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "fs_path" TEXT NOT NULL, "mount_path" TEXT, "content" TEXT, "resource_type" TEXT, "resource_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "is_directory" INTEGER DEFAULT false NOT NULL, "chown" TEXT, "chmod" TEXT, "is_based_on_git" INTEGER DEFAULT false NOT NULL ); CREATE TABLE IF NOT EXISTS "local_persistent_volumes" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" TEXT NOT NULL, "mount_path" TEXT NOT NULL, "host_path" TEXT, "container_id" TEXT, "resource_type" TEXT, "resource_id" INTEGER, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "migrations" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "migration" TEXT NOT NULL, "batch" INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS "oauth_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "provider" TEXT NOT NULL, "enabled" INTEGER DEFAULT false NOT NULL, "client_id" TEXT, "client_secret" TEXT, "redirect_uri" TEXT, "tenant" TEXT, "created_at" TEXT, "updated_at" TEXT, "base_url" TEXT ); CREATE TABLE IF NOT EXISTS "password_reset_tokens" ( "email" TEXT NOT NULL, "token" TEXT NOT NULL, "created_at" TEXT ); CREATE TABLE IF NOT EXISTS "personal_access_tokens" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "tokenable_type" TEXT NOT NULL, "tokenable_id" INTEGER NOT NULL, "name" TEXT NOT NULL, "token" TEXT NOT NULL, "team_id" TEXT NOT NULL, "abilities" TEXT, "last_used_at" TEXT, "expires_at" TEXT, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "private_keys" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "private_key" TEXT NOT NULL, "is_git_related" INTEGER DEFAULT false NOT NULL, "team_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "fingerprint" TEXT ); CREATE TABLE IF NOT EXISTS "project_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "project_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "projects" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "team_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "pushover_notification_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "pushover_enabled" INTEGER DEFAULT false NOT NULL, "pushover_user_key" TEXT, "pushover_api_token" TEXT, "deployment_success_pushover_notifications" INTEGER DEFAULT false NOT NULL, "deployment_failure_pushover_notifications" INTEGER DEFAULT true NOT NULL, "status_change_pushover_notifications" INTEGER DEFAULT false NOT NULL, "backup_success_pushover_notifications" INTEGER DEFAULT false NOT NULL, "backup_failure_pushover_notifications" INTEGER DEFAULT true NOT NULL, "scheduled_task_success_pushover_notifications" INTEGER DEFAULT false NOT NULL, "scheduled_task_failure_pushover_notifications" INTEGER DEFAULT true NOT NULL, "docker_cleanup_success_pushover_notifications" INTEGER DEFAULT false NOT NULL, "docker_cleanup_failure_pushover_notifications" INTEGER DEFAULT true NOT NULL, "server_disk_usage_pushover_notifications" INTEGER DEFAULT true NOT NULL, "server_reachable_pushover_notifications" INTEGER DEFAULT false NOT NULL, "server_unreachable_pushover_notifications" INTEGER DEFAULT true NOT NULL, "server_patch_pushover_notifications" INTEGER DEFAULT true NOT NULL, "traefik_outdated_pushover_notifications" INTEGER DEFAULT true NOT NULL ); CREATE TABLE IF NOT EXISTS "s3_storages" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "region" TEXT DEFAULT 'us-east-1' NOT NULL, "key" TEXT NOT NULL, "secret" TEXT NOT NULL, "bucket" TEXT NOT NULL, "endpoint" TEXT, "team_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "is_usable" INTEGER DEFAULT false NOT NULL, "unusable_email_sent" INTEGER DEFAULT false NOT NULL ); CREATE TABLE IF NOT EXISTS "scheduled_database_backup_executions" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "status" TEXT DEFAULT 'running' NOT NULL, "message" TEXT, "size" TEXT, "filename" TEXT, "scheduled_database_backup_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "database_name" TEXT, "finished_at" TEXT, "local_storage_deleted" INTEGER DEFAULT false NOT NULL, "s3_storage_deleted" INTEGER DEFAULT false NOT NULL, "s3_uploaded" INTEGER ); CREATE TABLE IF NOT EXISTS "scheduled_database_backups" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "description" TEXT, "uuid" TEXT NOT NULL, "enabled" INTEGER DEFAULT true NOT NULL, "save_s3" INTEGER DEFAULT true NOT NULL, "frequency" TEXT NOT NULL, "database_backup_retention_amount_locally" INTEGER DEFAULT 0 NOT NULL, "database_type" TEXT NOT NULL, "database_id" INTEGER NOT NULL, "s3_storage_id" INTEGER, "team_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "databases_to_backup" TEXT, "dump_all" INTEGER DEFAULT false NOT NULL, "database_backup_retention_days_locally" INTEGER DEFAULT 0 NOT NULL, "database_backup_retention_max_storage_locally" REAL DEFAULT '0' NOT NULL, "database_backup_retention_amount_s3" INTEGER DEFAULT 0 NOT NULL, "database_backup_retention_days_s3" INTEGER DEFAULT 0 NOT NULL, "database_backup_retention_max_storage_s3" REAL DEFAULT '0' NOT NULL, "timeout" INTEGER DEFAULT 3600 NOT NULL, "disable_local_backup" INTEGER DEFAULT false NOT NULL ); CREATE TABLE IF NOT EXISTS "scheduled_task_executions" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "status" TEXT DEFAULT 'running' NOT NULL, "message" TEXT, "scheduled_task_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "finished_at" TEXT, "started_at" TEXT, "retry_count" INTEGER DEFAULT 0 NOT NULL, "duration" REAL, "error_details" TEXT ); CREATE TABLE IF NOT EXISTS "scheduled_tasks" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "enabled" INTEGER DEFAULT true NOT NULL, "name" TEXT NOT NULL, "command" TEXT NOT NULL, "frequency" TEXT NOT NULL, "container" TEXT, "created_at" TEXT, "updated_at" TEXT, "application_id" INTEGER, "service_id" INTEGER, "team_id" INTEGER NOT NULL, "timeout" INTEGER DEFAULT 300 NOT NULL ); CREATE TABLE IF NOT EXISTS "server_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "is_swarm_manager" INTEGER DEFAULT false NOT NULL, "is_jump_server" INTEGER DEFAULT false NOT NULL, "is_build_server" INTEGER DEFAULT false NOT NULL, "is_reachable" INTEGER DEFAULT false NOT NULL, "is_usable" INTEGER DEFAULT false NOT NULL, "server_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "wildcard_domain" TEXT, "is_cloudflare_tunnel" INTEGER DEFAULT false NOT NULL, "is_logdrain_newrelic_enabled" INTEGER DEFAULT false NOT NULL, "logdrain_newrelic_license_key" TEXT, "logdrain_newrelic_base_uri" TEXT, "is_logdrain_highlight_enabled" INTEGER DEFAULT false NOT NULL, "logdrain_highlight_project_id" TEXT, "is_logdrain_axiom_enabled" INTEGER DEFAULT false NOT NULL, "logdrain_axiom_dataset_name" TEXT, "logdrain_axiom_api_key" TEXT, "is_swarm_worker" INTEGER DEFAULT false NOT NULL, "is_logdrain_custom_enabled" INTEGER DEFAULT false NOT NULL, "logdrain_custom_config" TEXT, "logdrain_custom_config_parser" TEXT, "concurrent_builds" INTEGER DEFAULT 2 NOT NULL, "dynamic_timeout" INTEGER DEFAULT 3600 NOT NULL, "force_disabled" INTEGER DEFAULT false NOT NULL, "is_metrics_enabled" INTEGER DEFAULT false NOT NULL, "generate_exact_labels" INTEGER DEFAULT false NOT NULL, "force_docker_cleanup" INTEGER DEFAULT true NOT NULL, "docker_cleanup_frequency" TEXT DEFAULT '0 0 * * *' NOT NULL, "docker_cleanup_threshold" INTEGER DEFAULT 80 NOT NULL, "server_timezone" TEXT DEFAULT 'UTC' NOT NULL, "delete_unused_volumes" INTEGER DEFAULT false NOT NULL, "delete_unused_networks" INTEGER DEFAULT false NOT NULL, "is_sentinel_enabled" INTEGER DEFAULT true NOT NULL, "sentinel_token" TEXT, "sentinel_metrics_refresh_rate_seconds" INTEGER DEFAULT 10 NOT NULL, "sentinel_metrics_history_days" INTEGER DEFAULT 7 NOT NULL, "sentinel_push_interval_seconds" INTEGER DEFAULT 60 NOT NULL, "sentinel_custom_url" TEXT, "server_disk_usage_notification_threshold" INTEGER DEFAULT 80 NOT NULL, "is_sentinel_debug_enabled" INTEGER DEFAULT false NOT NULL, "server_disk_usage_check_frequency" TEXT DEFAULT '0 23 * * *' NOT NULL, "is_terminal_enabled" INTEGER DEFAULT true NOT NULL, "deployment_queue_limit" INTEGER DEFAULT 25 NOT NULL, "disable_application_image_retention" INTEGER DEFAULT false NOT NULL ); CREATE TABLE IF NOT EXISTS "servers" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "ip" TEXT NOT NULL, "port" INTEGER DEFAULT 22 NOT NULL, "user" TEXT DEFAULT 'root' NOT NULL, "team_id" INTEGER NOT NULL, "private_key_id" INTEGER NOT NULL, "proxy" TEXT, "created_at" TEXT, "updated_at" TEXT, "unreachable_notification_sent" INTEGER DEFAULT false NOT NULL, "unreachable_count" INTEGER DEFAULT 0 NOT NULL, "high_disk_usage_notification_sent" INTEGER DEFAULT false NOT NULL, "log_drain_notification_sent" INTEGER DEFAULT false NOT NULL, "swarm_cluster" INTEGER, "validation_logs" TEXT, "sentinel_updated_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "deleted_at" TEXT, "ip_previous" TEXT, "hetzner_server_id" INTEGER, "cloud_provider_token_id" INTEGER, "hetzner_server_status" TEXT, "is_validating" INTEGER DEFAULT false NOT NULL, "detected_traefik_version" TEXT, "traefik_outdated_info" TEXT ); CREATE TABLE IF NOT EXISTS "service_applications" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "human_name" TEXT, "description" TEXT, "fqdn" TEXT, "ports" TEXT, "exposes" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "service_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "exclude_from_status" INTEGER DEFAULT false NOT NULL, "required_fqdn" INTEGER DEFAULT false NOT NULL, "image" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "is_gzip_enabled" INTEGER DEFAULT true NOT NULL, "is_stripprefix_enabled" INTEGER DEFAULT true NOT NULL, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "is_migrated" INTEGER DEFAULT false NOT NULL ); CREATE TABLE IF NOT EXISTS "service_databases" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "human_name" TEXT, "description" TEXT, "ports" TEXT, "exposes" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "service_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "exclude_from_status" INTEGER DEFAULT false NOT NULL, "image" TEXT, "public_port" INTEGER, "is_public" INTEGER DEFAULT false NOT NULL, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "is_gzip_enabled" INTEGER DEFAULT true NOT NULL, "is_stripprefix_enabled" INTEGER DEFAULT true NOT NULL, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "is_migrated" INTEGER DEFAULT false NOT NULL, "custom_type" TEXT ); CREATE TABLE IF NOT EXISTS "services" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "environment_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "server_id" INTEGER, "description" TEXT, "docker_compose_raw" TEXT NOT NULL, "docker_compose" TEXT, "destination_type" TEXT, "destination_id" INTEGER, "deleted_at" TEXT, "connect_to_docker_network" INTEGER DEFAULT false NOT NULL, "config_hash" TEXT, "service_type" TEXT, "is_container_label_escape_enabled" INTEGER DEFAULT true NOT NULL, "compose_parsing_version" TEXT DEFAULT '2' NOT NULL ); CREATE TABLE IF NOT EXISTS "sessions" ( "id" TEXT NOT NULL, "user_id" INTEGER, "ip_address" TEXT, "user_agent" TEXT, "payload" TEXT NOT NULL, "last_activity" INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS "shared_environment_variables" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "key" TEXT NOT NULL, "value" TEXT NOT NULL, "is_shown_once" INTEGER DEFAULT false NOT NULL, "type" TEXT DEFAULT 'team' NOT NULL, "team_id" INTEGER NOT NULL, "project_id" INTEGER, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "is_multiline" INTEGER DEFAULT false NOT NULL, "version" TEXT DEFAULT '4.0.0-beta.239' NOT NULL, "is_literal" INTEGER DEFAULT false NOT NULL ); CREATE TABLE IF NOT EXISTS "slack_notification_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "slack_enabled" INTEGER DEFAULT false NOT NULL, "slack_webhook_url" TEXT, "deployment_success_slack_notifications" INTEGER DEFAULT false NOT NULL, "deployment_failure_slack_notifications" INTEGER DEFAULT true NOT NULL, "status_change_slack_notifications" INTEGER DEFAULT false NOT NULL, "backup_success_slack_notifications" INTEGER DEFAULT false NOT NULL, "backup_failure_slack_notifications" INTEGER DEFAULT true NOT NULL, "scheduled_task_success_slack_notifications" INTEGER DEFAULT false NOT NULL, "scheduled_task_failure_slack_notifications" INTEGER DEFAULT true NOT NULL, "docker_cleanup_success_slack_notifications" INTEGER DEFAULT false NOT NULL, "docker_cleanup_failure_slack_notifications" INTEGER DEFAULT true NOT NULL, "server_disk_usage_slack_notifications" INTEGER DEFAULT true NOT NULL, "server_reachable_slack_notifications" INTEGER DEFAULT false NOT NULL, "server_unreachable_slack_notifications" INTEGER DEFAULT true NOT NULL, "server_patch_slack_notifications" INTEGER DEFAULT true NOT NULL, "traefik_outdated_slack_notifications" INTEGER DEFAULT true NOT NULL ); CREATE TABLE IF NOT EXISTS "ssl_certificates" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "ssl_certificate" TEXT NOT NULL, "ssl_private_key" TEXT NOT NULL, "configuration_dir" TEXT, "mount_path" TEXT, "resource_type" TEXT, "resource_id" INTEGER, "server_id" INTEGER NOT NULL, "common_name" TEXT NOT NULL, "subject_alternative_names" TEXT, "valid_until" TEXT NOT NULL, "is_ca_certificate" INTEGER DEFAULT false NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_clickhouses" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "clickhouse_admin_user" TEXT DEFAULT 'default' NOT NULL, "clickhouse_admin_password" TEXT NOT NULL, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'clickhouse/clickhouse-server:25.11' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "clickhouse_db" TEXT DEFAULT 'default' NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_dockers" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" TEXT NOT NULL, "uuid" TEXT NOT NULL, "network" TEXT NOT NULL, "server_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_dragonflies" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "dragonfly_password" TEXT NOT NULL, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'docker.dragonflydb.io/dragonflydb/dragonfly' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "enable_ssl" INTEGER DEFAULT false NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_keydbs" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "keydb_password" TEXT NOT NULL, "keydb_conf" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'eqalpha/keydb:latest' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "enable_ssl" INTEGER DEFAULT false NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_mariadbs" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "mariadb_root_password" TEXT NOT NULL, "mariadb_user" TEXT DEFAULT 'mariadb' NOT NULL, "mariadb_password" TEXT NOT NULL, "mariadb_database" TEXT DEFAULT 'default' NOT NULL, "mariadb_conf" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'mariadb:11' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "enable_ssl" INTEGER DEFAULT false NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_mongodbs" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "mongo_conf" TEXT, "mongo_initdb_root_username" TEXT DEFAULT 'root' NOT NULL, "mongo_initdb_root_password" TEXT NOT NULL, "mongo_initdb_database" TEXT DEFAULT 'default' NOT NULL, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'mongo:7' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "enable_ssl" INTEGER DEFAULT false NOT NULL, "ssl_mode" TEXT DEFAULT 'require' NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_mysqls" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "mysql_root_password" TEXT NOT NULL, "mysql_user" TEXT DEFAULT 'mysql' NOT NULL, "mysql_password" TEXT NOT NULL, "mysql_database" TEXT DEFAULT 'default' NOT NULL, "mysql_conf" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'mysql:8' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "enable_ssl" INTEGER DEFAULT false NOT NULL, "ssl_mode" TEXT DEFAULT 'REQUIRED' NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_postgresqls" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "postgres_user" TEXT DEFAULT 'postgres' NOT NULL, "postgres_password" TEXT NOT NULL, "postgres_db" TEXT DEFAULT 'postgres' NOT NULL, "postgres_initdb_args" TEXT, "postgres_host_auth_method" TEXT, "init_scripts" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'postgres:16-alpine' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "postgres_conf" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "enable_ssl" INTEGER DEFAULT false NOT NULL, "ssl_mode" TEXT DEFAULT 'require' NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "standalone_redis" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "redis_conf" TEXT, "status" TEXT DEFAULT 'exited' NOT NULL, "image" TEXT DEFAULT 'redis:7.2' NOT NULL, "is_public" INTEGER DEFAULT false NOT NULL, "public_port" INTEGER, "ports_mappings" TEXT, "limits_memory" TEXT DEFAULT '0' NOT NULL, "limits_memory_swap" TEXT DEFAULT '0' NOT NULL, "limits_memory_swappiness" INTEGER DEFAULT 60 NOT NULL, "limits_memory_reservation" TEXT DEFAULT '0' NOT NULL, "limits_cpus" TEXT DEFAULT '0' NOT NULL, "limits_cpuset" TEXT, "limits_cpu_shares" INTEGER DEFAULT 1024 NOT NULL, "started_at" TEXT, "destination_type" TEXT NOT NULL, "destination_id" INTEGER NOT NULL, "environment_id" INTEGER, "created_at" TEXT, "updated_at" TEXT, "is_log_drain_enabled" INTEGER DEFAULT false NOT NULL, "is_include_timestamps" INTEGER DEFAULT false NOT NULL, "deleted_at" TEXT, "config_hash" TEXT, "custom_docker_run_options" TEXT, "last_online_at" TEXT DEFAULT '2026-02-11 12:51:02' NOT NULL, "enable_ssl" INTEGER DEFAULT false NOT NULL, "restart_count" INTEGER DEFAULT 0 NOT NULL, "last_restart_at" TEXT, "last_restart_type" TEXT ); CREATE TABLE IF NOT EXISTS "subscriptions" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "stripe_invoice_paid" INTEGER DEFAULT false NOT NULL, "stripe_subscription_id" TEXT, "stripe_customer_id" TEXT, "stripe_cancel_at_period_end" INTEGER DEFAULT false NOT NULL, "stripe_plan_id" TEXT, "stripe_feedback" TEXT, "stripe_comment" TEXT, "stripe_trial_already_ended" INTEGER DEFAULT false NOT NULL, "stripe_past_due" INTEGER DEFAULT false NOT NULL ); CREATE TABLE IF NOT EXISTS "swarm_dockers" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" TEXT NOT NULL, "uuid" TEXT NOT NULL, "server_id" INTEGER NOT NULL, "created_at" TEXT, "updated_at" TEXT, "network" TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS "taggables" ( "tag_id" INTEGER NOT NULL, "taggable_id" INTEGER NOT NULL, "taggable_type" TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS "tags" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "name" TEXT NOT NULL, "team_id" INTEGER, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "team_invitations" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" TEXT NOT NULL, "team_id" INTEGER NOT NULL, "email" TEXT NOT NULL, "role" TEXT DEFAULT 'member' NOT NULL, "link" TEXT NOT NULL, "via" TEXT DEFAULT 'link' NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "team_user" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "user_id" INTEGER NOT NULL, "role" TEXT DEFAULT 'member' NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "teams" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" TEXT NOT NULL, "description" TEXT, "personal_team" INTEGER DEFAULT false NOT NULL, "created_at" TEXT, "updated_at" TEXT, "show_boarding" INTEGER DEFAULT false NOT NULL, "custom_server_limit" INTEGER ); CREATE TABLE IF NOT EXISTS "telegram_notification_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "telegram_enabled" INTEGER DEFAULT false NOT NULL, "telegram_token" TEXT, "telegram_chat_id" TEXT, "deployment_success_telegram_notifications" INTEGER DEFAULT false NOT NULL, "deployment_failure_telegram_notifications" INTEGER DEFAULT true NOT NULL, "status_change_telegram_notifications" INTEGER DEFAULT false NOT NULL, "backup_success_telegram_notifications" INTEGER DEFAULT false NOT NULL, "backup_failure_telegram_notifications" INTEGER DEFAULT true NOT NULL, "scheduled_task_success_telegram_notifications" INTEGER DEFAULT false NOT NULL, "scheduled_task_failure_telegram_notifications" INTEGER DEFAULT true NOT NULL, "docker_cleanup_success_telegram_notifications" INTEGER DEFAULT false NOT NULL, "docker_cleanup_failure_telegram_notifications" INTEGER DEFAULT true NOT NULL, "server_disk_usage_telegram_notifications" INTEGER DEFAULT true NOT NULL, "server_reachable_telegram_notifications" INTEGER DEFAULT false NOT NULL, "server_unreachable_telegram_notifications" INTEGER DEFAULT true NOT NULL, "telegram_notifications_deployment_success_thread_id" TEXT, "telegram_notifications_deployment_failure_thread_id" TEXT, "telegram_notifications_status_change_thread_id" TEXT, "telegram_notifications_backup_success_thread_id" TEXT, "telegram_notifications_backup_failure_thread_id" TEXT, "telegram_notifications_scheduled_task_success_thread_id" TEXT, "telegram_notifications_scheduled_task_failure_thread_id" TEXT, "telegram_notifications_docker_cleanup_success_thread_id" TEXT, "telegram_notifications_docker_cleanup_failure_thread_id" TEXT, "telegram_notifications_server_disk_usage_thread_id" TEXT, "telegram_notifications_server_reachable_thread_id" TEXT, "telegram_notifications_server_unreachable_thread_id" TEXT, "server_patch_telegram_notifications" INTEGER DEFAULT true NOT NULL, "telegram_notifications_server_patch_thread_id" TEXT, "telegram_notifications_traefik_outdated_thread_id" TEXT, "traefik_outdated_telegram_notifications" INTEGER DEFAULT true NOT NULL ); CREATE TABLE IF NOT EXISTS "telescope_entries" ( "sequence" INTEGER NOT NULL, "uuid" TEXT NOT NULL, "batch_id" TEXT NOT NULL, "family_hash" TEXT, "should_display_on_index" INTEGER DEFAULT true NOT NULL, "type" TEXT NOT NULL, "content" TEXT NOT NULL, "created_at" TEXT ); CREATE TABLE IF NOT EXISTS "telescope_entries_tags" ( "entry_uuid" TEXT NOT NULL, "tag" TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS "telescope_monitoring" ( "tag" TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS "user_changelog_reads" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" INTEGER NOT NULL, "release_tag" TEXT NOT NULL, "read_at" TEXT NOT NULL, "created_at" TEXT, "updated_at" TEXT ); CREATE TABLE IF NOT EXISTS "users" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" TEXT DEFAULT 'Anonymous' NOT NULL, "email" TEXT NOT NULL, "email_verified_at" TEXT, "password" TEXT, "remember_token" TEXT, "created_at" TEXT, "updated_at" TEXT, "two_factor_secret" TEXT, "two_factor_recovery_codes" TEXT, "two_factor_confirmed_at" TEXT, "force_password_reset" INTEGER DEFAULT false NOT NULL, "marketing_emails" INTEGER DEFAULT true NOT NULL, "pending_email" TEXT, "email_change_code" TEXT, "email_change_code_expires_at" TEXT ); CREATE TABLE IF NOT EXISTS "webhook_notification_settings" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "team_id" INTEGER NOT NULL, "webhook_enabled" INTEGER DEFAULT false NOT NULL, "webhook_url" TEXT, "deployment_success_webhook_notifications" INTEGER DEFAULT false NOT NULL, "deployment_failure_webhook_notifications" INTEGER DEFAULT true NOT NULL, "status_change_webhook_notifications" INTEGER DEFAULT false NOT NULL, "backup_success_webhook_notifications" INTEGER DEFAULT false NOT NULL, "backup_failure_webhook_notifications" INTEGER DEFAULT true NOT NULL, "scheduled_task_success_webhook_notifications" INTEGER DEFAULT false NOT NULL, "scheduled_task_failure_webhook_notifications" INTEGER DEFAULT true NOT NULL, "docker_cleanup_success_webhook_notifications" INTEGER DEFAULT false NOT NULL, "docker_cleanup_failure_webhook_notifications" INTEGER DEFAULT true NOT NULL, "server_disk_usage_webhook_notifications" INTEGER DEFAULT true NOT NULL, "server_reachable_webhook_notifications" INTEGER DEFAULT false NOT NULL, "server_unreachable_webhook_notifications" INTEGER DEFAULT true NOT NULL, "server_patch_webhook_notifications" INTEGER DEFAULT false NOT NULL, "traefik_outdated_webhook_notifications" INTEGER DEFAULT true NOT NULL ); CREATE INDEX IF NOT EXISTS "activity_log_log_name_index" ON "activity_log" (log_name); CREATE INDEX IF NOT EXISTS "causer" ON "activity_log" (causer_type, causer_id); CREATE INDEX IF NOT EXISTS "subject" ON "activity_log" (subject_type, subject_id); CREATE UNIQUE INDEX IF NOT EXISTS "application_deployment_queues_deployment_uuid_unique" ON "application_deployment_queues" (deployment_uuid); CREATE INDEX IF NOT EXISTS "idx_deployment_queues_app_status_pr_created" ON "application_deployment_queues" (application_id, status, pull_request_id, created_at); CREATE INDEX IF NOT EXISTS "idx_deployment_queues_status_server" ON "application_deployment_queues" (status, server_id); CREATE UNIQUE INDEX IF NOT EXISTS "application_previews_fqdn_unique" ON "application_previews" (fqdn); CREATE UNIQUE INDEX IF NOT EXISTS "application_previews_uuid_unique" ON "application_previews" (uuid); CREATE INDEX IF NOT EXISTS "applications_destination_type_destination_id_index" ON "applications" (destination_type, destination_id); CREATE INDEX IF NOT EXISTS "applications_source_type_source_id_index" ON "applications" (source_type, source_id); CREATE UNIQUE INDEX IF NOT EXISTS "applications_uuid_unique" ON "applications" (uuid); CREATE INDEX IF NOT EXISTS "idx_cloud_init_scripts_team_id" ON "cloud_init_scripts" (team_id); CREATE INDEX IF NOT EXISTS "cloud_provider_tokens_team_id_provider_index" ON "cloud_provider_tokens" (team_id, provider); CREATE UNIQUE INDEX IF NOT EXISTS "cloud_provider_tokens_uuid_unique" ON "cloud_provider_tokens" (uuid); CREATE INDEX IF NOT EXISTS "idx_cloud_provider_tokens_team_id" ON "cloud_provider_tokens" (team_id); CREATE UNIQUE INDEX IF NOT EXISTS "discord_notification_settings_team_id_unique" ON "discord_notification_settings" (team_id); CREATE UNIQUE INDEX IF NOT EXISTS "docker_cleanup_executions_uuid_unique" ON "docker_cleanup_executions" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "email_notification_settings_team_id_unique" ON "email_notification_settings" (team_id); CREATE INDEX IF NOT EXISTS "environment_variables_resourceable_type_resourceable_id_index" ON "environment_variables" (resourceable_type, resourceable_id); CREATE UNIQUE INDEX IF NOT EXISTS "environments_name_project_id_unique" ON "environments" (name, project_id); CREATE UNIQUE INDEX IF NOT EXISTS "environments_uuid_unique" ON "environments" (uuid); CREATE INDEX IF NOT EXISTS "idx_environments_project_id" ON "environments" (project_id); CREATE UNIQUE INDEX IF NOT EXISTS "failed_jobs_uuid_unique" ON "failed_jobs" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "github_apps_uuid_unique" ON "github_apps" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "gitlab_apps_uuid_unique" ON "gitlab_apps" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "local_file_volumes_mount_path_resource_id_resource_type_unique" ON "local_file_volumes" (mount_path, resource_id, resource_type); CREATE INDEX IF NOT EXISTS "local_file_volumes_resource_type_resource_id_index" ON "local_file_volumes" (resource_type, resource_id); CREATE UNIQUE INDEX IF NOT EXISTS "local_persistent_volumes_name_resource_id_resource_type_unique" ON "local_persistent_volumes" (name, resource_id, resource_type); CREATE INDEX IF NOT EXISTS "local_persistent_volumes_resource_type_resource_id_index" ON "local_persistent_volumes" (resource_type, resource_id); CREATE UNIQUE INDEX IF NOT EXISTS "oauth_settings_provider_unique" ON "oauth_settings" (provider); CREATE UNIQUE INDEX IF NOT EXISTS "personal_access_tokens_token_unique" ON "personal_access_tokens" (token); CREATE INDEX IF NOT EXISTS "personal_access_tokens_tokenable_type_tokenable_id_index" ON "personal_access_tokens" (tokenable_type, tokenable_id); CREATE INDEX IF NOT EXISTS "idx_private_keys_team_id" ON "private_keys" (team_id); CREATE UNIQUE INDEX IF NOT EXISTS "private_keys_uuid_unique" ON "private_keys" (uuid); CREATE INDEX IF NOT EXISTS "idx_projects_team_id" ON "projects" (team_id); CREATE UNIQUE INDEX IF NOT EXISTS "projects_uuid_unique" ON "projects" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "pushover_notification_settings_team_id_unique" ON "pushover_notification_settings" (team_id); CREATE UNIQUE INDEX IF NOT EXISTS "s3_storages_uuid_unique" ON "s3_storages" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "scheduled_database_backup_executions_uuid_unique" ON "scheduled_database_backup_executions" (uuid); CREATE INDEX IF NOT EXISTS "scheduled_db_backup_executions_backup_id_created_at_index" ON "scheduled_database_backup_executions" (scheduled_database_backup_id, created_at); CREATE INDEX IF NOT EXISTS "scheduled_database_backups_database_type_database_id_index" ON "scheduled_database_backups" (database_type, database_id); CREATE UNIQUE INDEX IF NOT EXISTS "scheduled_database_backups_uuid_unique" ON "scheduled_database_backups" (uuid); CREATE INDEX IF NOT EXISTS "scheduled_task_executions_task_id_created_at_index" ON "scheduled_task_executions" (scheduled_task_id, created_at); CREATE UNIQUE INDEX IF NOT EXISTS "scheduled_task_executions_uuid_unique" ON "scheduled_task_executions" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "scheduled_tasks_uuid_unique" ON "scheduled_tasks" (uuid); CREATE INDEX IF NOT EXISTS "idx_servers_team_id" ON "servers" (team_id); CREATE UNIQUE INDEX IF NOT EXISTS "servers_uuid_unique" ON "servers" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "service_applications_uuid_unique" ON "service_applications" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "service_databases_uuid_unique" ON "service_databases" (uuid); CREATE INDEX IF NOT EXISTS "services_destination_type_destination_id_index" ON "services" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "services_uuid_unique" ON "services" (uuid); CREATE INDEX IF NOT EXISTS "sessions_last_activity_index" ON "sessions" (last_activity); CREATE INDEX IF NOT EXISTS "sessions_user_id_index" ON "sessions" (user_id); CREATE UNIQUE INDEX IF NOT EXISTS "shared_environment_variables_key_environment_id_team_id_unique" ON "shared_environment_variables" (key, environment_id, team_id); CREATE UNIQUE INDEX IF NOT EXISTS "shared_environment_variables_key_project_id_team_id_unique" ON "shared_environment_variables" (key, project_id, team_id); CREATE UNIQUE INDEX IF NOT EXISTS "slack_notification_settings_team_id_unique" ON "slack_notification_settings" (team_id); CREATE INDEX IF NOT EXISTS "standalone_clickhouses_destination_type_destination_id_index" ON "standalone_clickhouses" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_clickhouses_uuid_unique" ON "standalone_clickhouses" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_dockers_server_id_network_unique" ON "standalone_dockers" (server_id, network); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_dockers_uuid_unique" ON "standalone_dockers" (uuid); CREATE INDEX IF NOT EXISTS "standalone_dragonflies_destination_type_destination_id_index" ON "standalone_dragonflies" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_dragonflies_uuid_unique" ON "standalone_dragonflies" (uuid); CREATE INDEX IF NOT EXISTS "standalone_keydbs_destination_type_destination_id_index" ON "standalone_keydbs" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_keydbs_uuid_unique" ON "standalone_keydbs" (uuid); CREATE INDEX IF NOT EXISTS "standalone_mariadbs_destination_type_destination_id_index" ON "standalone_mariadbs" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_mariadbs_uuid_unique" ON "standalone_mariadbs" (uuid); CREATE INDEX IF NOT EXISTS "standalone_mongodbs_destination_type_destination_id_index" ON "standalone_mongodbs" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_mongodbs_uuid_unique" ON "standalone_mongodbs" (uuid); CREATE INDEX IF NOT EXISTS "standalone_mysqls_destination_type_destination_id_index" ON "standalone_mysqls" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_mysqls_uuid_unique" ON "standalone_mysqls" (uuid); CREATE INDEX IF NOT EXISTS "standalone_postgresqls_destination_type_destination_id_index" ON "standalone_postgresqls" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_postgresqls_uuid_unique" ON "standalone_postgresqls" (uuid); CREATE INDEX IF NOT EXISTS "standalone_redis_destination_type_destination_id_index" ON "standalone_redis" (destination_type, destination_id); CREATE UNIQUE INDEX IF NOT EXISTS "standalone_redis_uuid_unique" ON "standalone_redis" (uuid); CREATE INDEX IF NOT EXISTS "idx_subscriptions_team_id" ON "subscriptions" (team_id); CREATE UNIQUE INDEX IF NOT EXISTS "swarm_dockers_server_id_network_unique" ON "swarm_dockers" (server_id, network); CREATE UNIQUE INDEX IF NOT EXISTS "swarm_dockers_uuid_unique" ON "swarm_dockers" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "taggable_unique" ON "taggables" (tag_id, taggable_id, taggable_type); CREATE UNIQUE INDEX IF NOT EXISTS "tags_uuid_unique" ON "tags" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "team_invitations_team_id_email_unique" ON "team_invitations" (team_id, email); CREATE UNIQUE INDEX IF NOT EXISTS "team_invitations_uuid_unique" ON "team_invitations" (uuid); CREATE UNIQUE INDEX IF NOT EXISTS "team_user_team_id_user_id_unique" ON "team_user" (team_id, user_id); CREATE UNIQUE INDEX IF NOT EXISTS "telegram_notification_settings_team_id_unique" ON "telegram_notification_settings" (team_id); CREATE INDEX IF NOT EXISTS "telescope_entries_batch_id_index" ON "telescope_entries" (batch_id); CREATE INDEX IF NOT EXISTS "telescope_entries_created_at_index" ON "telescope_entries" (created_at); CREATE INDEX IF NOT EXISTS "telescope_entries_family_hash_index" ON "telescope_entries" (family_hash); CREATE INDEX IF NOT EXISTS "telescope_entries_type_should_display_on_index_index" ON "telescope_entries" (type, should_display_on_index); CREATE UNIQUE INDEX IF NOT EXISTS "telescope_entries_uuid_unique" ON "telescope_entries" (uuid); CREATE INDEX IF NOT EXISTS "telescope_entries_tags_tag_index" ON "telescope_entries_tags" (tag); CREATE INDEX IF NOT EXISTS "user_changelog_reads_release_tag_index" ON "user_changelog_reads" (release_tag); CREATE INDEX IF NOT EXISTS "user_changelog_reads_user_id_index" ON "user_changelog_reads" (user_id); CREATE UNIQUE INDEX IF NOT EXISTS "user_changelog_reads_user_id_release_tag_unique" ON "user_changelog_reads" (user_id, release_tag); CREATE UNIQUE INDEX IF NOT EXISTS "users_email_unique" ON "users" (email); CREATE UNIQUE INDEX IF NOT EXISTS "webhook_notification_settings_team_id_unique" ON "webhook_notification_settings" (team_id); -- Migration records INSERT INTO "migrations" ("id", "migration", "batch") VALUES (1, '2014_10_12_000000_create_users_table', 1); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (2, '2014_10_12_100000_create_password_reset_tokens_table', 2); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (3, '2014_10_12_200000_add_two_factor_columns_to_users_table', 3); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (4, '2018_08_08_100000_create_telescope_entries_table', 4); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (5, '2019_12_14_000001_create_personal_access_tokens_table', 5); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (6, '2023_03_20_112410_create_activity_log_table', 6); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (7, '2023_03_20_112411_add_event_column_to_activity_log_table', 7); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (8, '2023_03_20_112412_add_batch_uuid_column_to_activity_log_table', 8); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (9, '2023_03_20_112809_create_sessions_table', 9); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (10, '2023_03_20_112811_create_teams_table', 10); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (11, '2023_03_20_112812_create_team_user_table', 11); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (12, '2023_03_20_112813_create_team_invitations_table', 12); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (13, '2023_03_20_112814_create_instance_settings_table', 13); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (14, '2023_03_24_140711_create_servers_table', 14); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (15, '2023_03_24_140712_create_server_settings_table', 15); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (16, '2023_03_24_140853_create_private_keys_table', 16); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (17, '2023_03_27_075351_create_projects_table', 17); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (18, '2023_03_27_075443_create_project_settings_table', 18); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (19, '2023_03_27_075444_create_environments_table', 19); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (20, '2023_03_27_081716_create_applications_table', 20); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (21, '2023_03_27_081717_create_application_settings_table', 21); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (22, '2023_03_27_081718_create_application_previews_table', 22); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (23, '2023_03_27_083621_create_services_table', 23); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (24, '2023_03_27_085020_create_standalone_dockers_table', 24); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (25, '2023_03_27_085022_create_swarm_dockers_table', 25); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (26, '2023_03_28_062150_create_kubernetes_table', 26); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (27, '2023_03_28_083723_create_github_apps_table', 27); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (28, '2023_03_28_083726_create_gitlab_apps_table', 28); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (29, '2023_04_03_111012_create_local_persistent_volumes_table', 29); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (30, '2023_05_04_194548_create_environment_variables_table', 30); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (31, '2023_05_17_104039_create_failed_jobs_table', 31); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (32, '2023_05_24_083426_create_application_deployment_queues_table', 32); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (33, '2023_06_22_131459_move_wildcard_to_server', 33); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (34, '2023_06_23_084605_remove_wildcard_domain_from_instancesettings', 34); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (35, '2023_06_23_110548_next_channel_updates', 35); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (36, '2023_06_23_114131_change_env_var_value_length', 36); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (37, '2023_06_23_114132_remove_default_redirect_from_instance_settings', 37); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (38, '2023_06_23_114133_use_application_deployment_queues_as_activity', 38); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (39, '2023_06_23_114134_add_disk_usage_percentage_to_servers', 39); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (40, '2023_07_13_115117_create_subscriptions_table', 40); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (41, '2023_07_13_120719_create_webhooks_table', 41); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (42, '2023_07_13_120721_add_license_to_instance_settings', 42); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (43, '2023_07_27_182013_smtp_discord_schemaless_to_normal', 43); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (44, '2023_08_06_142951_add_description_field_to_applications_table', 44); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (45, '2023_08_06_142952_remove_foreignId_environment_variables', 45); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (46, '2023_08_06_142954_add_readonly_localpersistentvolumes', 46); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (47, '2023_08_07_073651_create_s3_storages_table', 47); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (48, '2023_08_07_142950_create_standalone_postgresqls_table', 48); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (49, '2023_08_08_150103_create_scheduled_database_backups_table', 49); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (50, '2023_08_10_113306_create_scheduled_database_backup_executions_table', 50); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (51, '2023_08_10_201311_add_backup_notifications_to_teams', 51); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (52, '2023_08_11_190528_add_dockerfile_to_applications_table', 52); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (53, '2023_08_15_095902_create_waitlists_table', 53); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (54, '2023_08_15_111125_update_users_table', 54); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (55, '2023_08_15_111126_update_servers_add_unreachable_count_table', 55); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (56, '2023_08_22_071048_add_boarding_to_teams', 56); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (57, '2023_08_22_071049_update_webhooks_type', 57); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (58, '2023_08_22_071050_update_subscriptions_stripe', 58); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (59, '2023_08_22_071051_add_stripe_plan_to_subscriptions', 59); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (60, '2023_08_22_071052_add_resend_as_email', 60); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (61, '2023_08_22_071053_add_resend_as_email_to_teams', 61); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (62, '2023_08_22_071054_add_stripe_reasons', 62); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (63, '2023_08_22_071055_add_discord_notifications_to_teams', 63); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (64, '2023_08_22_071056_update_telegram_notifications', 64); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (65, '2023_08_22_071057_add_nixpkgsarchive_to_applications', 65); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (66, '2023_08_22_071058_add_nixpkgsarchive_to_applications_remove', 66); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (67, '2023_08_22_071059_add_stripe_trial_ended', 67); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (68, '2023_08_22_071060_change_invitation_link_length', 68); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (69, '2023_09_20_082541_update_services_table', 69); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (70, '2023_09_20_082733_create_service_databases_table', 70); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (71, '2023_09_20_082737_create_service_applications_table', 71); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (72, '2023_09_20_083549_update_environment_variables_table', 72); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (73, '2023_09_22_185356_create_local_file_volumes_table', 73); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (74, '2023_09_23_111808_update_servers_with_cloudflared', 74); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (75, '2023_09_23_111809_remove_destination_from_services_table', 75); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (76, '2023_09_23_111811_update_service_applications_table', 76); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (77, '2023_09_23_111812_update_service_databases_table', 77); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (78, '2023_09_23_111813_update_users_databases_table', 78); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (79, '2023_09_23_111814_update_local_file_volumes_table', 79); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (80, '2023_09_23_111815_add_healthcheck_disable_to_apps_table', 80); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (81, '2023_09_23_111816_add_destination_to_services_table', 81); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (82, '2023_09_23_111817_use_instance_email_settings_by_default', 82); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (83, '2023_09_23_111818_set_notifications_on_by_default', 83); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (84, '2023_09_23_111819_add_server_emails', 84); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (85, '2023_10_08_111819_add_server_unreachable_count', 85); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (86, '2023_10_10_100320_update_s3_storages_table', 86); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (87, '2023_10_10_113144_add_dockerfile_location_applications_table', 87); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (88, '2023_10_12_132430_create_standalone_redis_table', 88); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (89, '2023_10_12_132431_add_standalone_redis_to_environment_variables_table', 89); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (90, '2023_10_12_132432_add_database_selection_to_backups', 90); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (91, '2023_10_18_072519_add_custom_labels_applications_table', 91); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (92, '2023_10_19_101331_create_standalone_mongodbs_table', 92); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (93, '2023_10_19_101332_add_standalone_mongodb_to_environment_variables_table', 93); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (94, '2023_10_24_103548_create_standalone_mysqls_table', 94); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (95, '2023_10_24_120523_create_standalone_mariadbs_table', 95); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (96, '2023_10_24_120524_add_standalone_mysql_to_environment_variables_table', 96); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (97, '2023_10_24_124934_add_is_shown_once_to_environment_variables_table', 97); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (98, '2023_11_01_100437_add_restart_to_deployment_queue', 98); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (99, '2023_11_07_123731_add_target_build_dockerfile', 99); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (100, '2023_11_08_112815_add_custom_config_standalone_postgresql', 100); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (101, '2023_11_09_133332_add_public_port_to_service_databases', 101); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (102, '2023_11_12_180605_change_fqdn_to_longer_field', 102); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (103, '2023_11_13_133059_add_sponsorship_disable', 103); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (104, '2023_11_14_103450_add_manual_webhook_secret', 104); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (105, '2023_11_14_121416_add_git_type', 105); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (106, '2023_11_16_101819_add_high_disk_usage_notification', 106); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (107, '2023_11_16_220647_add_log_drains', 107); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (108, '2023_11_17_160437_add_drain_log_enable_by_service', 108); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (109, '2023_11_20_094628_add_gpu_settings', 109); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (110, '2023_11_21_121920_add_additional_destinations_to_apps', 110); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (111, '2023_11_24_080341_add_docker_compose_location', 111); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (112, '2023_11_28_143533_add_fields_to_swarm_dockers', 112); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (113, '2023_11_29_075937_change_swarm_properties', 113); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (114, '2023_12_01_091723_save_logs_view_settings', 114); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (115, '2023_12_01_095356_add_custom_fluentd_config_for_logdrains', 115); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (116, '2023_12_08_162228_add_soft_delete_services', 116); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (117, '2023_12_11_103611_add_realtime_connection_problem', 117); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (118, '2023_12_13_110214_add_soft_deletes', 118); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (119, '2023_12_17_155616_add_custom_docker_compose_start_command', 119); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (120, '2023_12_18_093514_add_swarm_related_things', 120); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (121, '2023_12_19_124111_add_swarm_cluster_grouping', 121); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (122, '2023_12_30_134507_add_description_to_environments', 122); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (123, '2023_12_31_173041_create_scheduled_tasks_table', 123); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (124, '2024_01_01_231053_create_scheduled_task_executions_table', 124); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (125, '2024_01_02_113855_add_raw_compose_deployment', 125); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (126, '2024_01_12_123422_update_cpuset_limits', 126); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (127, '2024_01_15_084609_add_custom_dns_server', 127); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (128, '2024_01_16_115005_add_build_server_enable', 128); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (129, '2024_01_21_130328_add_docker_network_to_services', 129); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (130, '2024_01_23_095832_add_manual_webhook_secret_bitbucket', 130); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (131, '2024_01_23_113129_create_shared_environment_variables_table', 131); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (132, '2024_01_24_095449_add_concurrent_number_of_builds_per_server', 132); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (133, '2024_01_25_073212_add_server_id_to_queues', 133); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (134, '2024_01_27_164724_add_application_name_and_deployment_url_to_queue', 134); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (135, '2024_01_29_072322_change_env_variable_length', 135); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (136, '2024_01_29_145200_add_custom_docker_run_options', 136); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (137, '2024_02_01_111228_create_tags_table', 137); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (138, '2024_02_05_105215_add_destination_to_app_deployments', 138); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (139, '2024_02_06_132748_add_additional_destinations', 139); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (140, '2024_02_08_075523_add_post_deployment_to_applications', 140); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (141, '2024_02_08_112304_add_dynamic_timeout_for_deployments', 141); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (142, '2024_02_15_101921_add_consistent_application_container_name', 142); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (143, '2024_02_15_192025_add_is_gzip_enabled_to_services', 143); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (144, '2024_02_20_165045_add_permissions_to_github_app', 144); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (145, '2024_02_22_090900_add_only_this_server_deployment', 145); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (146, '2024_02_23_143119_add_custom_server_limits_to_teams_ultimate', 146); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (147, '2024_02_25_222150_add_server_force_disabled_field', 147); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (148, '2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings', 148); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (149, '2024_03_07_115054_add_notifications_notification_disable', 149); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (150, '2024_03_08_180457_nullable_password', 150); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (151, '2024_03_11_150013_create_oauth_settings', 151); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (152, '2024_03_14_214402_add_multiline_envs', 152); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (153, '2024_03_18_101440_add_version_of_envs', 153); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (154, '2024_03_22_080914_remove_popup_notifications', 154); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (155, '2024_03_26_122110_remove_realtime_notifications', 155); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (156, '2024_03_28_114620_add_watch_paths_to_apps', 156); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (157, '2024_04_09_095517_make_custom_docker_commands_longer', 157); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (158, '2024_04_10_071920_create_standalone_keydbs_table', 158); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (159, '2024_04_10_082220_create_standalone_dragonflies_table', 159); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (160, '2024_04_10_091519_create_standalone_clickhouses_table', 160); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (161, '2024_04_10_124015_add_permission_local_file_volumes', 161); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (162, '2024_04_12_092337_add_config_hash_to_other_resources', 162); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (163, '2024_04_15_094703_add_literal_variables', 163); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (164, '2024_04_16_083919_add_service_type_on_creation', 164); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (165, '2024_04_17_132541_add_rollback_queues', 165); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (166, '2024_04_25_073615_add_docker_network_to_application_settings', 166); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (167, '2024_04_29_111956_add_custom_hc_indicator_apps', 167); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (168, '2024_05_06_093236_add_custom_name_to_application_settings', 168); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (169, '2024_05_07_124019_add_server_metrics', 169); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (170, '2024_05_10_085215_make_stripe_comment_longer', 170); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (171, '2024_05_15_091757_add_commit_message_to_app_deployment_queue', 171); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (172, '2024_05_15_151236_add_container_escape_toggle', 172); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (173, '2024_05_17_082012_add_env_sorting_toggle', 173); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (174, '2024_05_21_125739_add_scheduled_tasks_notification_to_teams', 174); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (175, '2024_05_22_103942_change_pre_post_deployment_commands_length_in_applications', 175); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (176, '2024_05_23_091713_add_gitea_webhook_to_applications', 176); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (177, '2024_06_05_101019_add_docker_compose_pr_domains', 177); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (178, '2024_06_06_103938_change_pr_issue_commend_id_type', 178); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (179, '2024_06_11_081614_add_www_non_www_redirect', 179); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (180, '2024_06_18_105948_move_server_metrics', 180); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (181, '2024_06_20_102551_add_server_api_sentinel', 181); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (182, '2024_06_21_143358_add_api_deployment_type', 182); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (183, '2024_06_22_081140_alter_instance_settings_add_instance_name', 183); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (184, '2024_06_25_184323_update_db', 184); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (185, '2024_07_01_115528_add_is_api_allowed_and_iplist', 185); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (186, '2024_07_05_120217_remove_unique_from_tag_names', 186); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (187, '2024_07_11_083719_application_compose_versions', 187); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (188, '2024_07_17_123828_add_is_container_labels_readonly', 188); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (189, '2024_07_18_110424_create_application_settings_is_preserve_repository_enabled', 189); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (190, '2024_07_18_123458_add_force_cleanup_server', 190); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (191, '2024_07_19_132617_disable_healtcheck_by_default', 191); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (192, '2024_07_23_112710_add_validation_logs_to_servers', 192); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (193, '2024_08_05_142659_add_update_frequency_settings', 193); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (194, '2024_08_07_155324_add_proxy_label_chooser', 194); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (195, '2024_08_09_215659_add_server_cleanup_fields_to_server_settings_table', 195); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (196, '2024_08_12_131659_add_local_file_volume_based_on_git', 196); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (197, '2024_08_12_155023_add_timezone_to_server_and_instance_settings', 197); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (198, '2024_08_14_183120_add_order_to_environment_variables_table', 198); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (199, '2024_08_15_115907_add_build_server_id_to_deployment_queue', 199); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (200, '2024_08_16_105649_add_custom_docker_options_to_dbs', 200); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (201, '2024_08_27_090528_add_compose_parsing_version_to_services', 201); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (202, '2024_09_05_085700_add_helper_version_to_instance_settings', 202); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (203, '2024_09_06_062534_change_server_cleanup_to_forced', 203); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (204, '2024_09_07_185402_change_cleanup_schedule', 204); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (205, '2024_09_08_130756_update_server_settings_default_timezone', 205); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (206, '2024_09_16_111428_encrypt_existing_private_keys', 206); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (207, '2024_09_17_111226_add_ssh_key_fingerprint_to_private_keys_table', 207); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (208, '2024_09_22_165240_add_advanced_options_to_cleanup_options_to_servers_settings_table', 208); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (209, '2024_09_26_083441_disable_api_by_default', 209); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (210, '2024_10_03_095427_add_dump_all_to_standalone_postgresqls', 210); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (211, '2024_10_10_081444_remove_constraint_from_service_applications_fqdn', 211); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (212, '2024_10_11_114331_add_required_env_variables', 212); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (213, '2024_10_14_090416_update_metrics_token_in_server_settings', 213); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (214, '2024_10_15_172139_add_is_shared_to_environment_variables', 214); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (215, '2024_10_16_120026_move_redis_password_to_envs', 215); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (216, '2024_10_16_192133_add_confirmation_settings_to_instance_settings_table', 216); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (217, '2024_10_17_093722_add_soft_delete_to_servers', 217); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (218, '2024_10_22_105745_add_server_disk_usage_threshold', 218); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (219, '2024_10_22_121223_add_server_disk_usage_notification', 219); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (220, '2024_10_29_093927_add_is_sentinel_debug_enabled_to_server_settings', 220); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (221, '2024_10_30_074601_rename_token_permissions', 221); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (222, '2024_11_02_213214_add_last_online_at_to_resources', 222); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (223, '2024_11_11_125335_add_custom_nginx_configuration_to_static', 223); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (224, '2024_11_11_125366_add_index_to_activity_log', 224); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (225, '2024_11_22_124742_add_uuid_to_environments_table', 225); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (226, '2024_12_05_091823_add_disable_build_cache_advanced_option', 226); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (227, '2024_12_05_212355_create_email_notification_settings_table', 227); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (228, '2024_12_05_212416_create_discord_notification_settings_table', 228); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (229, '2024_12_05_212440_create_telegram_notification_settings_table', 229); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (230, '2024_12_05_212546_migrate_email_notification_settings_from_teams_table', 230); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (231, '2024_12_05_212631_migrate_discord_notification_settings_from_teams_table', 231); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (232, '2024_12_05_212705_migrate_telegram_notification_settings_from_teams_table', 232); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (233, '2024_12_06_142014_create_slack_notification_settings_table', 233); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (234, '2024_12_09_105711_drop_waitlists_table', 234); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (235, '2024_12_10_122142_encrypt_instance_settings_email_columns', 235); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (236, '2024_12_10_122143_drop_resale_license', 236); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (237, '2024_12_11_135026_create_pushover_notification_settings_table', 237); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (238, '2024_12_11_161418_add_authentik_base_url_to_oauth_settings_table', 238); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (239, '2024_12_13_103007_encrypt_resend_api_key_in_instance_settings', 239); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (240, '2024_12_16_134437_add_resourceable_columns_to_environment_variables_table', 240); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (241, '2024_12_17_140637_add_server_disk_usage_check_frequency_to_server_settings_table', 241); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (242, '2024_12_23_142402_update_email_encryption_values', 242); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (243, '2025_01_05_050736_add_network_aliases_to_applications_table', 243); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (244, '2025_01_08_154008_switch_up_readonly_labels', 244); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (245, '2025_01_10_135244_add_horizon_job_details_to_queue', 245); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (246, '2025_01_13_130238_add_backup_retention_fields_to_scheduled_database_backups_table', 246); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (247, '2025_01_15_130416_create_docker_cleanup_executions_table', 247); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (248, '2025_01_16_110406_change_commit_message_to_text_in_application_deployment_queues', 248); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (249, '2025_01_16_130238_add_finished_at_to_executions_tables', 249); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (250, '2025_01_21_125205_update_finished_at_timestamps_if_not_set', 250); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (251, '2025_01_22_101105_remove_wrongly_created_envs', 251); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (252, '2025_01_27_102616_add_ssl_fields_to_database_tables', 252); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (253, '2025_01_27_153741_create_ssl_certificates_table', 253); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (254, '2025_01_30_125223_encrypt_local_file_volumes_fields', 254); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (255, '2025_02_27_125249_add_index_to_scheduled_task_executions', 255); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (256, '2025_03_01_112617_add_stripe_past_due', 256); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (257, '2025_03_14_140150_add_storage_deletion_tracking_to_backup_executions', 257); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (258, '2025_03_21_104103_disable_discord_here', 258); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (259, '2025_03_26_104103_disable_mongodb_ssl_by_default', 259); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (260, '2025_03_29_204400_revert_some_local_volume_encryption', 260); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (261, '2025_03_31_124212_add_specific_spa_configuration', 261); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (262, '2025_04_01_124212_stripe_comment_nullable', 262); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (263, '2025_04_17_110026_add_application_http_basic_auth_fields', 263); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (264, '2025_04_30_134146_add_is_migrated_to_services', 264); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (265, '2025_05_26_100258_add_server_patch_notifications', 265); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (266, '2025_05_29_100258_add_terminal_enabled_to_server_settings', 266); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (267, '2025_06_06_073345_create_server_previous_ip', 267); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (268, '2025_06_16_123532_change_sentinel_on_by_default', 268); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (269, '2025_06_25_131350_add_is_sponsorship_popup_enabled_to_instance_settings_table', 269); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (270, '2025_06_26_131350_optimize_activity_log_indexes', 270); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (271, '2025_07_14_191016_add_deleted_at_to_application_previews_table', 271); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (272, '2025_07_16_202201_add_timeout_to_scheduled_database_backups_table', 272); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (273, '2025_08_07_142403_create_user_changelog_reads_table', 273); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (274, '2025_08_17_102422_add_disable_local_backup_to_scheduled_database_backups_table', 274); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (275, '2025_08_18_104146_add_email_change_fields_to_users_table', 275); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (276, '2025_08_18_154244_change_env_sorting_default_to_false', 276); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (277, '2025_08_21_080234_add_git_shallow_clone_to_application_settings_table', 277); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (278, '2025_09_05_142446_add_pr_deployments_public_enabled_to_application_settings', 278); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (279, '2025_09_10_172952_remove_is_readonly_from_local_persistent_volumes_table', 279); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (280, '2025_09_10_173300_drop_webhooks_table', 280); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (281, '2025_09_10_173402_drop_kubernetes_table', 281); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (282, '2025_09_11_143432_remove_is_build_time_from_environment_variables_table', 282); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (283, '2025_09_11_150344_add_is_buildtime_only_to_environment_variables_table', 283); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (284, '2025_09_17_081112_add_use_build_secrets_to_application_settings', 284); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (285, '2025_09_18_080152_add_runtime_and_buildtime_to_environment_variables_table', 285); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (286, '2025_10_03_154100_update_clickhouse_image', 286); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (287, '2025_10_07_120723_add_s3_uploaded_to_scheduled_database_backup_executions_table', 287); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (288, '2025_10_08_181125_create_cloud_provider_tokens_table', 288); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (289, '2025_10_08_185203_add_hetzner_server_id_to_servers_table', 289); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (290, '2025_10_09_095905_add_cloud_provider_token_id_to_servers_table', 290); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (291, '2025_10_09_113602_add_hetzner_server_status_to_servers_table', 291); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (292, '2025_10_09_125036_add_is_validating_to_servers_table', 292); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (293, '2025_11_02_161923_add_dev_helper_version_to_instance_settings', 293); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (294, '2025_11_09_000001_add_timeout_to_scheduled_tasks_table', 294); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (295, '2025_11_09_000002_improve_scheduled_task_executions_tracking', 295); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (296, '2025_11_10_112500_add_restart_tracking_to_applications_table', 296); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (297, '2025_11_12_130931_add_traefik_version_tracking_to_servers_table', 297); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (298, '2025_11_12_131252_add_traefik_outdated_to_email_notification_settings', 298); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (299, '2025_11_12_133400_add_traefik_outdated_thread_id_to_telegram_notification_settings', 299); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (300, '2025_11_14_114632_add_traefik_outdated_info_to_servers_table', 300); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (301, '2025_11_16_000001_create_webhook_notification_settings_table', 301); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (302, '2025_11_16_000002_create_cloud_init_scripts_table', 302); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (303, '2025_11_17_092707_add_traefik_outdated_to_notification_settings', 303); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (304, '2025_11_18_083747_cleanup_dockerfile_data_for_non_dockerfile_buildpacks', 304); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (305, '2025_11_26_124200_add_build_cache_settings_to_application_settings', 305); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (306, '2025_11_28_000001_migrate_clickhouse_to_official_image', 306); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (307, '2025_12_04_134435_add_deployment_queue_limit_to_server_settings', 307); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (308, '2025_12_05_000000_add_docker_images_to_keep_to_application_settings', 308); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (309, '2025_12_05_100000_add_disable_application_image_retention_to_server_settings', 309); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (310, '2025_12_08_135600_add_performance_indexes', 310); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (311, '2025_12_10_135600_add_uuid_to_cloud_provider_tokens', 311); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (312, '2025_12_15_143052_trim_s3_storage_credentials', 312); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (313, '2025_12_17_000001_add_is_wire_navigate_enabled_to_instance_settings_table', 313); INSERT INTO "migrations" ("id", "migration", "batch") VALUES (314, '2025_12_17_000002_add_restart_tracking_to_standalone_databases', 314); ================================================ FILE: database/seeders/ApplicationSeeder.php ================================================ 'docker-compose', 'name' => 'Docker Compose Example', 'repository_project_id' => 603035348, 'git_repository' => 'coollabsio/coolify-examples', 'git_branch' => 'v4.x', 'base_directory' => '/docker-compose', 'docker_compose_location' => '/docker-compose-test.yaml', 'build_pack' => 'dockercompose', 'ports_exposes' => '80', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 1, 'source_type' => GithubApp::class, ]); Application::create([ 'uuid' => 'nodejs', 'name' => 'NodeJS Fastify Example', 'fqdn' => 'http://nodejs.127.0.0.1.sslip.io', 'repository_project_id' => 603035348, 'git_repository' => 'coollabsio/coolify-examples', 'git_branch' => 'v4.x', 'base_directory' => '/nodejs', 'build_pack' => 'nixpacks', 'ports_exposes' => '3000', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 1, 'source_type' => GithubApp::class, ]); Application::create([ 'uuid' => 'dockerfile', 'name' => 'Dockerfile Example', 'fqdn' => 'http://dockerfile.127.0.0.1.sslip.io', 'repository_project_id' => 603035348, 'git_repository' => 'coollabsio/coolify-examples', 'git_branch' => 'v4.x', 'base_directory' => '/dockerfile', 'build_pack' => 'dockerfile', 'ports_exposes' => '80', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 0, 'source_type' => GithubApp::class, ]); Application::create([ 'uuid' => 'dockerfile-pure', 'name' => 'Pure Dockerfile Example', 'fqdn' => 'http://pure-dockerfile.127.0.0.1.sslip.io', 'git_repository' => 'coollabsio/coolify', 'git_branch' => 'v4.x', 'git_commit_sha' => 'HEAD', 'build_pack' => 'dockerfile', 'ports_exposes' => '80', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 0, 'source_type' => GithubApp::class, 'dockerfile' => 'FROM nginx EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ', ]); Application::create([ 'uuid' => 'crashloop', 'name' => 'Crash Loop Example', 'git_repository' => 'coollabsio/coolify', 'git_branch' => 'v4.x', 'git_commit_sha' => 'HEAD', 'build_pack' => 'dockerfile', 'ports_exposes' => '80', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 0, 'source_type' => GithubApp::class, 'dockerfile' => 'FROM alpine CMD ["sh", "-c", "echo Crashing in 5 seconds... && sleep 5 && exit 1"] ', ]); Application::create([ 'uuid' => 'github-deploy-key', 'name' => 'GitHub Deploy Key Example', 'fqdn' => 'http://github-deploy-key.127.0.0.1.sslip.io', 'git_repository' => 'git@github.com:coollabsio/coolify-examples-deploy-key.git', 'git_branch' => 'main', 'build_pack' => 'nixpacks', 'ports_exposes' => '80', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 0, 'source_type' => GithubApp::class, 'private_key_id' => 1, ]); Application::create([ 'uuid' => 'gitlab-deploy-key', 'name' => 'GitLab Deploy Key Example', 'fqdn' => 'http://gitlab-deploy-key.127.0.0.1.sslip.io', 'git_repository' => 'git@gitlab.com:coollabsio/php-example.git', 'git_branch' => 'main', 'build_pack' => 'nixpacks', 'ports_exposes' => '80', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 1, 'source_type' => GitlabApp::class, 'private_key_id' => 1, ]); Application::create([ 'uuid' => 'gitlab-public-example', 'name' => 'GitLab Public Example', 'fqdn' => 'http://gitlab-public.127.0.0.1.sslip.io', 'git_repository' => 'https://gitlab.com/andrasbacsai/coolify-examples.git', 'base_directory' => '/astro/static', 'publish_directory' => '/dist', 'git_branch' => 'main', 'build_pack' => 'nixpacks', 'ports_exposes' => '80', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, 'source_id' => 1, 'source_type' => GitlabApp::class, ]); } } ================================================ FILE: database/seeders/ApplicationSettingsSeeder.php ================================================ load(['settings']); $application_1->settings->is_debug_enabled = false; $application_1->settings->save(); $gitlabPublic = Application::where('uuid', 'gitlab-public-example')->first(); if ($gitlabPublic) { $gitlabPublic->load(['settings']); $gitlabPublic->settings->is_static = true; $gitlabPublic->settings->save(); } } } ================================================ FILE: database/seeders/CaSslCertSeeder.php ================================================ sslCertificates()->where('is_ca_certificate', true)->first(); if (! $existingCaCert) { $caCert = SslHelper::generateSslCertificate( commonName: 'Coolify CA Certificate', serverId: $server->id, isCaCertificate: true, validityDays: 10 * 365 ); } else { $caCert = $existingCaCert; } $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; $base64Cert = base64_encode($caCert->ssl_certificate); $commands = collect([ "mkdir -p $caCertPath", "chown -R 9999:root $caCertPath", "chmod -R 700 $caCertPath", "rm -rf $caCertPath/coolify-ca.crt", "echo '{$base64Cert}' | base64 -d | tee $caCertPath/coolify-ca.crt > /dev/null", "chmod 644 $caCertPath/coolify-ca.crt", ]); remote_process($commands, $server); } }); } } ================================================ FILE: database/seeders/DatabaseSeeder.php ================================================ call([ InstanceSettingsSeeder::class, UserSeeder::class, TeamSeeder::class, PrivateKeySeeder::class, PopulateSshKeysDirectorySeeder::class, ServerSeeder::class, ServerSettingSeeder::class, ProjectSeeder::class, StandaloneDockerSeeder::class, GithubAppSeeder::class, GitlabAppSeeder::class, ApplicationSeeder::class, ApplicationSettingsSeeder::class, LocalPersistentVolumeSeeder::class, S3StorageSeeder::class, StandalonePostgresqlSeeder::class, OauthSettingSeeder::class, DisableTwoStepConfirmationSeeder::class, SentinelSeeder::class, CaSslCertSeeder::class, PersonalAccessTokenSeeder::class, ]); } } ================================================ FILE: database/seeders/DisableTwoStepConfirmationSeeder.php ================================================ updateOrInsert( [], ['disable_two_step_confirmation' => true] ); } } ================================================ FILE: database/seeders/GithubAppSeeder.php ================================================ 0, 'uuid' => 'github-public', 'name' => 'Public GitHub', 'api_url' => 'https://api.github.com', 'html_url' => 'https://github.com', 'is_public' => true, 'team_id' => 0, ]); GithubApp::create([ 'name' => 'coolify-laravel-dev-public', 'uuid' => 'github-app', 'organization' => 'coollabsio', 'api_url' => 'https://api.github.com', 'html_url' => 'https://github.com', 'is_public' => false, 'app_id' => 292941, 'installation_id' => 37267016, 'client_id' => 'Iv1.220e564d2b0abd8c', 'client_secret' => '116d1d80289f378410dd70ab4e4b81dd8d2c52b6', 'webhook_secret' => '326a47b49054f03288f800d81247ec9414d0abf3', 'private_key_id' => 2, 'team_id' => 0, ]); } } ================================================ FILE: database/seeders/GitlabAppSeeder.php ================================================ 1, 'uuid' => 'gitlab-public', 'name' => 'Public GitLab', 'api_url' => 'https://gitlab.com/api/v4', 'html_url' => 'https://gitlab.com', 'is_public' => true, 'team_id' => 0, ]); } } ================================================ FILE: database/seeders/InstanceSettingsSeeder.php ================================================ 0, 'is_registration_enabled' => true, 'is_api_enabled' => isDev(), 'smtp_enabled' => true, 'smtp_host' => 'coolify-mail', 'smtp_port' => 1025, 'smtp_from_address' => 'hi@localhost.com', 'smtp_from_name' => 'Coolify', ]); try { $ipv4 = Process::run('curl -4s https://ifconfig.io')->output(); $ipv4 = trim($ipv4); $ipv4 = filter_var($ipv4, FILTER_VALIDATE_IP); $settings = instanceSettings(); if (is_null($settings->public_ipv4) && $ipv4) { $settings->update(['public_ipv4' => $ipv4]); } $ipv6 = Process::run('curl -6s https://ifconfig.io')->output(); $ipv6 = trim($ipv6); $ipv6 = filter_var($ipv6, FILTER_VALIDATE_IP); $settings = instanceSettings(); if (is_null($settings->public_ipv6) && $ipv6) { $settings->update(['public_ipv6' => $ipv6]); } } catch (\Throwable $e) { echo "Error: {$e->getMessage()}\n"; } } } ================================================ FILE: database/seeders/LocalPersistentVolumeSeeder.php ================================================ 'test-pv', 'mount_path' => '/data', 'resource_id' => 1, 'resource_type' => Application::class, ]); } } ================================================ FILE: database/seeders/OauthSettingSeeder.php ================================================ 0; // We changed how providers are defined in the database, so we authentik does not exists, we need to recreate all of the auth providers // Before authentik was a provider, providers started with 0 id $isOauthAuthentik = OauthSetting::where('provider', 'authentik')->exists(); if (! $isOauthSeeded || $isOauthAuthentik) { foreach ($providers as $provider) { OauthSetting::updateOrCreate([ 'provider' => $provider, ]); } return; } $allProviders = OauthSetting::all(); $notFoundProviders = $providers->diff($allProviders->pluck('provider')); $allProviders->each(function ($provider) { $provider->delete(); }); $allProviders->each(function ($provider) { $provider = new OauthSetting; $provider->provider = $provider->provider; unset($provider->id); $provider->save(); }); foreach ($notFoundProviders as $provider) { OauthSetting::create([ 'provider' => $provider, ]); } } catch (\Exception $e) { Log::error($e->getMessage()); } } } ================================================ FILE: database/seeders/PersonalAccessTokenSeeder.php ================================================ environment('production')) { $this->command->warn('Skipping PersonalAccessTokenSeeder in production environment'); return; } // Get the first user (usually the admin user created during setup) $user = User::find(0); if (! $user) { $this->command->warn('No user found. Please run UserSeeder first.'); return; } // Get the user's first team $team = $user->teams()->first(); if (! $team) { $this->command->warn('No team found for user. Cannot create API tokens.'); return; } // Define test tokens with different scopes $testTokens = [ [ 'name' => 'Development Root Token', 'token' => 'root', 'abilities' => ['root'], ], [ 'name' => 'Development Read Token', 'token' => 'read', 'abilities' => ['read'], ], [ 'name' => 'Development Read Sensitive Token', 'token' => 'read-sensitive', 'abilities' => ['read', 'read:sensitive'], ], [ 'name' => 'Development Write Token', 'token' => 'write', 'abilities' => ['write'], ], [ 'name' => 'Development Write Sensitive Token', 'token' => 'write-sensitive', 'abilities' => ['write', 'write:sensitive'], ], [ 'name' => 'Development Deploy Token', 'token' => 'deploy', 'abilities' => ['deploy'], ], ]; // First, remove all existing development tokens for this user $deletedCount = PersonalAccessToken::where('tokenable_id', $user->id) ->where('tokenable_type', get_class($user)) ->whereIn('name', array_column($testTokens, 'name')) ->delete(); if ($deletedCount > 0) { $this->command->info("Removed {$deletedCount} existing development token(s)."); } // Now create fresh tokens foreach ($testTokens as $tokenData) { // Create the token with a simple format: Bearer {scope} // The token format in the database is the hash of the plain text token $plainTextToken = $tokenData['token']; PersonalAccessToken::create([ 'tokenable_type' => get_class($user), 'tokenable_id' => $user->id, 'name' => $tokenData['name'], 'token' => hash('sha256', $plainTextToken), 'abilities' => $tokenData['abilities'], 'team_id' => $team->id, ]); $this->command->info("Created token '{$tokenData['name']}' with Bearer token: {$plainTextToken}"); } $this->command->info(''); $this->command->info('Test API tokens created successfully!'); $this->command->info('You can use these tokens in development as:'); $this->command->info(' Bearer root - Root access'); $this->command->info(' Bearer read - Read only access'); $this->command->info(' Bearer read-sensitive - Read with sensitive data access'); $this->command->info(' Bearer write - Write access'); $this->command->info(' Bearer write-sensitive - Write with sensitive data access'); $this->command->info(' Bearer deploy - Deploy access'); } } ================================================ FILE: database/seeders/PopulateSshKeysDirectorySeeder.php ================================================ deleteDirectory(''); Storage::disk('ssh-keys')->makeDirectory(''); Storage::disk('ssh-mux')->deleteDirectory(''); Storage::disk('ssh-mux')->makeDirectory(''); PrivateKey::chunk(100, function ($keys) { foreach ($keys as $key) { $key->storeInFileSystem(); } }); if (isDev()) { Process::run('chown -R 9999:9999 '.storage_path('app/ssh/keys')); Process::run('chown -R 9999:9999 '.storage_path('app/ssh/mux')); } else { Process::run('chown -R 9999:root '.storage_path('app/ssh/keys')); Process::run('chown -R 9999:root '.storage_path('app/ssh/mux')); } } catch (\Throwable $e) { echo "Error: {$e->getMessage()}\n"; } } } ================================================ FILE: database/seeders/PrivateKeySeeder.php ================================================ 'ssh', 'team_id' => 0, 'name' => 'Testing Host Key', 'description' => 'This is a test docker container', 'private_key' => '-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== -----END OPENSSH PRIVATE KEY----- ', ]); PrivateKey::create([ 'uuid' => 'github-key', 'team_id' => 0, 'name' => 'development-github-app', 'description' => 'This is the key for using the development GitHub app', 'private_key' => '-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAstJo/SfYh3tquc2BA29a1X3pdPpXazRgtKsb5fHOwQs1rE04 VyJYW6QCToSH4WS1oKt6iI4ma4uivn8rnkZFdw3mpcLp2ofcoeV3YPKX6pN/RiJC if+g8gCaFywOxy2pjXOLPZeFJSXFqc4UOymbhESUyDnMfk4/RvnubMiv3jINo4Ow 4Tv7tRzAdMlMrx3hEhi142oQuyl1kc4WQOM9cAV0bd+62ga3EYSnsWTnC9AaFtWk eGC5w/7knHJ5QZ9tKApkG3/29vJXY7WwCRUROEHqkvQhRDP0uqRPBdR48iG87Dwq ePa6TodkFaVfyHS/OUZzRiTn6MOSyQQFg0QIIwIDAQABAoIBAQCsmGebSJU2lwl4 0oAeZ6E9hG0LagFsSL66QpkHxO9w5bflWRbzCwRLVy6eyE46XzDrJfd7y/ALR1hK E4ZvGpY7heBDx7BdK1rprAggO6YjVD+42qJsfZ3DVo9jpDOTTWBkVcxkI1Xwd9ej wHNIcy1WabdM1nSoyC9M+ziEKOOOShXc5Q6e+zEzSBbwjc1fvvXZOH4VXZZ1DllE xGu0jFS23TLnXATxh8SdfYgnvfZgB5n72P9m/lj3FmkuJq57DLZhBwN3Zd4wom03 K7/J4K2Ssnjdv/HjVgrRgpMv7oMxfclN/Aiq878Ue4Mav6LjnLENyHbyR0WxQjY6 lZ7UMEeJAoGBAOCGepk3rCMFa3a6GagN6lYzAkLxB5y0PsefiDo6w+PeEj1tUvSd aQkiP7uvUC7a5GNp9yE8W79/O1jJXYJq15kMBpUshzfgdzyzDDCj+qvm6nbTWtP9 rP30h81R+NGdOStgs0OVZSjMWnIoii3Rv3UV4+iQXZd67+wd/kbTWtWVAoGBAMvj xv4wjt7OwtK/6oAhcNd2V9EUQp6PPpMkUyPicWdsLsoNOcuTpWvEc0AomdIGGjgI AIor1ggCxjEhbCDaZucOFUghciUup+PjyQyQT+3bjvCWuUmi0Vt51G7RE0jjZjQt 2+W9V4yDcJ5R5ow6veYvT0ZOjVTScDYowTBulgjXAoGBALFxVl7UotQiqmVwempY ZQSu13C0MIHl6V+2cuEiJEJn9R5a0h7EcIhpatkXmlUNZUY0Lr0ziIb1NJ/ctGwn qDAqUuF+CXddjJ6KGm4uiiNlIZO7QaMcbqVdph3cVLrEeLQRfltBLGtr5WcnJt1D UP5lyHK59V2MKSUAJz8uNjFpAoGAL5fR4Y/wKa5V5+AImzQzJPho81MpYd3KG4rF JYE8O4oTOfLwZMboPEm1JWrUzSPDhwTHK3mkEmajYOCOXvTcRF8TNK0p+ef0JMwN KDOflMRFj39/bOLmv9Wmct+3ArKiLtftlqkmAJTF+w7fJCiqH0s31A+OChi9PMcy oV2PBC0CgYAXOm08kFOQA+bPBdLAte8Ga89frh6asH/Z8ucfsz9/zMMG/hhq5nF3 7TItY9Pblc2Fp805J13G96zWLX4YGyLwXXkYs+Ae7QoqjonTw7/mUDARY1Zxs9m/ a1C8EDKapCw5hAhizEFOUQKOygL8Ipn+tmEUkORYdZ8Q8cWFCv9nIw== -----END RSA PRIVATE KEY-----', 'is_git_related' => true, ]); } } ================================================ FILE: database/seeders/ProductionSeeder.php ================================================ where('user_id', 0)->first() === null) { DB::table('team_user')->insert([ 'user_id' => 0, 'team_id' => 0, 'role' => 'owner', 'created_at' => now(), 'updated_at' => now(), ]); } } if (InstanceSettings::find(0) == null) { InstanceSettings::create([ 'id' => 0, ]); } if (GithubApp::find(0) == null) { GithubApp::create([ 'id' => 0, 'name' => 'Public GitHub', 'api_url' => 'https://api.github.com', 'html_url' => 'https://github.com', 'is_public' => true, 'team_id' => 0, ]); } if (GitlabApp::find(0) == null) { GitlabApp::create([ 'id' => 0, 'name' => 'Public GitLab', 'api_url' => 'https://gitlab.com/api/v4', 'html_url' => 'https://gitlab.com', 'is_public' => true, 'team_id' => 0, ]); } if (! isCloud() && config('constants.coolify.is_windows_docker_desktop') == false) { $coolify_key_name = '@host.docker.internal'; $ssh_keys_directory = Storage::disk('ssh-keys')->files(); $coolify_key = collect($ssh_keys_directory)->firstWhere(fn ($item) => str($item)->contains($coolify_key_name)); $private_key_found = PrivateKey::find(0); if (! $private_key_found) { if ($coolify_key) { $user = str($coolify_key)->before('@')->after('id.'); $coolify_key = Storage::disk('ssh-keys')->get($coolify_key); PrivateKey::create([ 'id' => 0, 'team_id' => 0, 'name' => 'localhost\'s key', 'description' => 'The private key for the Coolify host machine (localhost).', 'private_key' => $coolify_key, ]); echo "SSH key found for the Coolify host machine (localhost).\n"; } else { echo "No SSH key found for the Coolify host machine (localhost).\n"; echo "Please read the following documentation (point 3) to fix it: https://coolify. io/docs/knowledge-base/server/openssh/\n"; echo "Your localhost connection won't work until then."; } } } if (! isCloud()) { if (Server::find(0) == null) { $server_details = [ 'id' => 0, 'name' => 'localhost', 'description' => "This is the server where Coolify is running on. Don't delete this!", 'user' => $user, 'ip' => 'host.docker.internal', 'team_id' => 0, 'private_key_id' => 0, ]; $server_details['proxy'] = ServerMetadata::from([ 'type' => ProxyTypes::TRAEFIK->value, 'status' => ProxyStatus::EXITED->value, 'last_saved_settings' => null, 'last_applied_settings' => null, ]); $server = Server::create($server_details); $server->settings->is_reachable = true; $server->settings->is_usable = true; $server->settings->save(); StartProxy::dispatch($server); CheckAndStartSentinelJob::dispatch($server); } else { $server = Server::find(0); $server->settings->is_reachable = true; $server->settings->is_usable = true; $server->settings->save(); $shouldStart = CheckProxy::run($server); if ($shouldStart) { StartProxy::dispatch($server); } if ($server->isSentinelEnabled()) { CheckAndStartSentinelJob::dispatch($server); } } if (StandaloneDocker::find(0) == null) { StandaloneDocker::create([ 'id' => 0, 'name' => 'localhost-coolify', 'network' => 'coolify', 'server_id' => 0, ]); } } if (config('constants.coolify.is_windows_docker_desktop')) { PrivateKey::updateOrCreate( [ 'id' => 0, 'team_id' => 0, ], [ 'name' => 'Testing-host', 'description' => 'This is a a docker container with SSH access', 'private_key' => '-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== -----END OPENSSH PRIVATE KEY----- ', ] ); if (Server::find(0) == null) { $server_details = [ 'id' => 0, 'uuid' => 'coolify-testing-host', 'name' => 'localhost', 'description' => "This is the server where Coolify is running on. Don't delete this!", 'user' => 'root', 'ip' => 'coolify-testing-host', 'team_id' => 0, 'private_key_id' => 0, ]; $server_details['proxy'] = ServerMetadata::from([ 'type' => ProxyTypes::TRAEFIK->value, 'status' => ProxyStatus::EXITED->value, 'last_saved_settings' => null, 'last_applied_settings' => null, ]); $server = Server::create($server_details); $server->settings->is_reachable = true; $server->settings->is_usable = true; $server->settings->save(); } else { $server = Server::find(0); $server->settings->is_reachable = true; $server->settings->is_usable = true; $server->settings->save(); } if (StandaloneDocker::find(0) == null) { StandaloneDocker::create([ 'id' => 0, 'name' => 'localhost-coolify', 'network' => 'coolify', 'server_id' => 0, ]); } } get_public_ips(); $this->call(OauthSettingSeeder::class); $this->call(PopulateSshKeysDirectorySeeder::class); $this->call(SentinelSeeder::class); $this->call(RootUserSeeder::class); $this->call(CaSslCertSeeder::class); } } ================================================ FILE: database/seeders/ProjectSeeder.php ================================================ 'project', 'name' => 'My first project', 'description' => 'This is a test project in development', 'team_id' => 0, ]); // Update the auto-created environment with a deterministic UUID $project->environments()->first()->update(['uuid' => 'production']); } } ================================================ FILE: database/seeders/RootUserSeeder.php ================================================ exists()) { echo "\n INFO Root user already exists. Skipping creation.\n\n"; return; } if (! env('ROOT_USER_EMAIL') || ! env('ROOT_USER_PASSWORD')) { return; } $validator = Validator::make([ 'email' => env('ROOT_USER_EMAIL'), 'username' => env('ROOT_USERNAME', 'Root User'), 'password' => env('ROOT_USER_PASSWORD'), ], [ 'email' => ['required', 'email:rfc,dns', 'max:255'], 'username' => ['required', 'string', 'min:3', 'max:255', 'regex:/^[\w\s-]+$/'], 'password' => ['required', 'string', 'min:8', Password::min(8)->mixedCase()->letters()->numbers()->symbols()->uncompromised()], ]); if ($validator->fails()) { echo "\n ERROR Invalid Root User Environment Variables\n"; foreach ($validator->errors()->all() as $error) { echo " → {$error}\n"; } echo "\n"; return; } try { User::create([ 'id' => 0, 'name' => env('ROOT_USERNAME', 'Root User'), 'email' => env('ROOT_USER_EMAIL'), 'password' => Hash::make(env('ROOT_USER_PASSWORD')), ]); echo "\n SUCCESS Root user created successfully.\n\n"; } catch (\Exception $e) { echo "\n ERROR Failed to create root user: {$e->getMessage()}\n\n"; return; } try { InstanceSettings::updateOrCreate( ['id' => 0], ['is_registration_enabled' => false] ); echo "\n SUCCESS Registration has been disabled successfully.\n\n"; } catch (\Exception $e) { echo "\n ERROR Failed to update instance settings: {$e->getMessage()}\n\n"; } } catch (\Exception $e) { echo "\n ERROR An unexpected error occurred: {$e->getMessage()}\n\n"; } } } ================================================ FILE: database/seeders/S3StorageSeeder.php ================================================ 'minio', 'name' => 'Local MinIO', 'description' => 'Local MinIO S3 Storage', 'key' => 'minioadmin', 'secret' => 'minioadmin', 'bucket' => 'local', 'endpoint' => 'http://coolify-minio:9000', 'team_id' => 0, 'is_usable' => true, ]); } } ================================================ FILE: database/seeders/SentinelSeeder.php ================================================ settings->sentinel_token)->isEmpty()) { $server->settings->generateSentinelToken(ignoreEvent: true); } if (str($server->settings->sentinel_custom_url)->isEmpty()) { $url = $server->settings->generateSentinelUrl(ignoreEvent: true); if (str($url)->isEmpty()) { $server->settings->is_sentinel_enabled = false; $server->settings->save(); } } } catch (\Throwable $e) { Log::error('Error seeding sentinel: '.$e->getMessage()); } } }); } } ================================================ FILE: database/seeders/ServerSeeder.php ================================================ 0, 'uuid' => 'localhost', 'name' => 'localhost', 'description' => 'This is a test docker container in development mode', 'ip' => 'coolify-testing-host', 'team_id' => 0, 'private_key_id' => 1, 'proxy' => [ 'type' => ProxyTypes::TRAEFIK->value, 'status' => ProxyStatus::EXITED->value, ], ]); } } ================================================ FILE: database/seeders/ServerSettingSeeder.php ================================================ load(['settings']); $server_2->settings->wildcard_domain = 'http://127.0.0.1.sslip.io'; $server_2->settings->is_build_server = false; $server_2->settings->is_usable = true; $server_2->settings->is_reachable = true; $server_2->settings->save(); } } ================================================ FILE: database/seeders/SharedEnvironmentVariableSeeder.php ================================================ 'NODE_ENV', 'value' => 'team_env', 'type' => 'team', 'team_id' => 0, ]); SharedEnvironmentVariable::create([ 'key' => 'NODE_ENV', 'value' => 'env_env', 'type' => 'environment', 'environment_id' => 1, 'team_id' => 0, ]); SharedEnvironmentVariable::create([ 'key' => 'NODE_ENV', 'value' => 'project_env', 'type' => 'project', 'project_id' => 1, 'team_id' => 0, ]); } } ================================================ FILE: database/seeders/StandaloneDockerSeeder.php ================================================ 0, 'uuid' => 'docker', 'name' => 'Standalone Docker 1', 'network' => 'coolify', 'server_id' => 0, ]); } } } ================================================ FILE: database/seeders/StandalonePostgresqlSeeder.php ================================================ 'postgresql', 'name' => 'Local PostgreSQL', 'description' => 'Local PostgreSQL for testing', 'postgres_password' => 'postgres', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, ]); } } ================================================ FILE: database/seeders/StandaloneRedisSeeder.php ================================================ 'Local PostgreSQL', 'description' => 'Local PostgreSQL for testing', 'redis_password' => 'redis', 'environment_id' => 1, 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, ]); } } ================================================ FILE: database/seeders/TeamSeeder.php ================================================ description = 'The root team'; $root_user_personal_team->save(); $normal_user_in_root_team->teams()->attach($root_user_personal_team); $normal_user_not_in_root_team = User::find(2); $normal_user_in_root_team_personal_team = Team::find(1); $normal_user_not_in_root_team->teams()->attach($normal_user_in_root_team_personal_team, ['role' => 'admin']); } } ================================================ FILE: database/seeders/UserSeeder.php ================================================ create([ 'id' => 0, 'name' => 'Root User', 'email' => 'test@example.com', ]); User::factory()->create([ 'id' => 1, 'name' => 'Normal User (but in root team)', 'email' => 'test2@example.com', ]); User::factory()->create([ 'id' => 2, 'name' => 'Normal User (not in root team)', 'email' => 'test3@example.com', ]); } } ================================================ FILE: docker/coolify-helper/Dockerfile ================================================ # Versions # https://hub.docker.com/_/alpine ARG BASE_IMAGE=alpine:3.21 # https://download.docker.com/linux/static/stable/ ARG DOCKER_VERSION=28.0.0 # https://github.com/docker/compose/releases ARG DOCKER_COMPOSE_VERSION=2.38.2 # https://github.com/docker/buildx/releases ARG DOCKER_BUILDX_VERSION=0.25.0 # https://github.com/buildpacks/pack/releases ARG PACK_VERSION=0.38.2 # https://github.com/railwayapp/nixpacks/releases ARG NIXPACKS_VERSION=1.41.0 # https://github.com/minio/mc/releases ARG MINIO_VERSION=RELEASE.2025-08-13T08-35-41Z FROM minio/mc:${MINIO_VERSION} AS minio-client FROM ${BASE_IMAGE} AS base ARG TARGETPLATFORM ARG DOCKER_VERSION ARG DOCKER_COMPOSE_VERSION ARG DOCKER_BUILDX_VERSION ARG PACK_VERSION ARG NIXPACKS_VERSION USER root WORKDIR /artifacts RUN apk add --no-cache bash curl git git-lfs openssh-client tar tini RUN mkdir -p ~/.docker/cli-plugins RUN if [[ ${TARGETPLATFORM} == 'linux/amd64' ]]; then \ curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx && \ curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose && \ (curl -sSL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) && \ (curl -sSL https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux.tgz | tar -C /usr/local/bin/ --no-same-owner -xzv pack) && \ curl -sSL https://nixpacks.com/install.sh | bash && \ chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \ ;fi RUN if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \ curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-arm64 -o ~/.docker/cli-plugins/docker-buildx && \ curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-aarch64 -o ~/.docker/cli-plugins/docker-compose && \ (curl -sSL https://download.docker.com/linux/static/stable/aarch64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) && \ (curl -sSL https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux-arm64.tgz | tar -C /usr/local/bin/ --no-same-owner -xzv pack) && \ curl -sSL https://nixpacks.com/install.sh | bash && \ chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \ ;fi COPY --from=minio-client /usr/bin/mc /usr/bin/mc RUN chmod +x /usr/bin/mc ENTRYPOINT ["/sbin/tini", "--"] CMD ["tail", "-f", "/dev/null"] ================================================ FILE: docker/coolify-realtime/Dockerfile ================================================ # Versions # https://github.com/soketi/soketi/releases ARG SOKETI_VERSION=1.6-16-alpine # https://github.com/cloudflare/cloudflared/releases ARG CLOUDFLARED_VERSION=2025.7.0 FROM quay.io/soketi/soketi:${SOKETI_VERSION} ARG TARGETPLATFORM ARG CLOUDFLARED_VERSION WORKDIR /terminal RUN apk add --no-cache openssh-client make g++ python3 curl COPY docker/coolify-realtime/package.json ./ RUN npm i RUN npm rebuild node-pty --update-binary COPY docker/coolify-realtime/soketi-entrypoint.sh /soketi-entrypoint.sh COPY docker/coolify-realtime/terminal-server.js /terminal/terminal-server.js COPY docker/coolify-realtime/terminal-utils.js /terminal/terminal-utils.js # Install Cloudflared based on architecture RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \ curl -sSL "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-amd64" -o /usr/local/bin/cloudflared; \ elif [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \ curl -sSL "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-arm64" -o /usr/local/bin/cloudflared; \ fi && \ chmod +x /usr/local/bin/cloudflared ENTRYPOINT ["/bin/sh", "/soketi-entrypoint.sh"] ================================================ FILE: docker/coolify-realtime/package.json ================================================ { "private": true, "type": "module", "dependencies": { "@xterm/addon-fit": "0.11.0", "@xterm/xterm": "6.0.0", "cookie": "1.1.1", "axios": "1.13.6", "dotenv": "17.3.1", "node-pty": "1.1.0", "ws": "8.19.0" } } ================================================ FILE: docker/coolify-realtime/soketi-entrypoint.sh ================================================ #!/bin/sh # Function to timestamp logs # Check if the first argument is 'watch' if [ "$1" = "watch" ]; then WATCH_MODE="--watch" else WATCH_MODE="" fi timestamp() { date "+%Y-%m-%d %H:%M:%S" } # Start the terminal server in the background with logging node $WATCH_MODE /terminal/terminal-server.js > >(while read line; do echo "$(timestamp) [TERMINAL] $line"; done) 2>&1 & TERMINAL_PID=$! # Start the Soketi process in the background with logging node /app/bin/server.js start > >(while read line; do echo "$(timestamp) [SOKETI] $line"; done) 2>&1 & SOKETI_PID=$! # Function to forward signals to child processes forward_signal() { kill -$1 $TERMINAL_PID $SOKETI_PID } # Forward SIGTERM to child processes trap 'forward_signal TERM' TERM # Wait for any process to exit wait -n # Exit with status of process that exited first exit $? ================================================ FILE: docker/coolify-realtime/terminal-server.js ================================================ import { WebSocketServer } from 'ws'; import http from 'http'; import pty from 'node-pty'; import axios from 'axios'; import cookie from 'cookie'; import 'dotenv/config'; import { extractHereDocContent, extractSshArgs, extractTargetHost, extractTimeout, isAuthorizedTargetHost, } from './terminal-utils.js'; const userSessions = new Map(); const terminalDebugEnabled = ['local', 'development'].includes( String(process.env.APP_ENV || process.env.NODE_ENV || '').toLowerCase() ); function logTerminal(level, message, context = {}) { if (!terminalDebugEnabled) { return; } const formattedMessage = `[TerminalServer] ${message}`; if (Object.keys(context).length > 0) { console[level](formattedMessage, context); return; } console[level](formattedMessage); } const server = http.createServer((req, res) => { if (req.url === '/ready') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('OK'); } else { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not Found'); } }); const getSessionCookie = (req) => { const cookies = cookie.parse(req.headers.cookie || ''); const xsrfToken = cookies['XSRF-TOKEN']; const appName = process.env.APP_NAME || 'laravel'; const sessionCookieName = `${appName.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase()}_session`; return { sessionCookieName, xsrfToken: xsrfToken, laravelSession: cookies[sessionCookieName] } } const verifyClient = async (info, callback) => { const { xsrfToken, laravelSession, sessionCookieName } = getSessionCookie(info.req); const requestContext = { remoteAddress: info.req.socket?.remoteAddress, origin: info.origin, sessionCookieName, hasXsrfToken: Boolean(xsrfToken), hasLaravelSession: Boolean(laravelSession), }; logTerminal('log', 'Verifying websocket client.', requestContext); // Verify presence of required tokens if (!laravelSession || !xsrfToken) { logTerminal('warn', 'Rejecting websocket client because required auth tokens are missing.', requestContext); return callback(false, 401, 'Unauthorized: Missing required tokens'); } try { // Authenticate with Laravel backend const response = await axios.post(`http://coolify:8080/terminal/auth`, null, { headers: { 'Cookie': `${sessionCookieName}=${laravelSession}`, 'X-XSRF-TOKEN': xsrfToken }, }); if (response.status === 200) { logTerminal('log', 'Websocket client authentication succeeded.', requestContext); callback(true); } else { logTerminal('warn', 'Websocket client authentication returned a non-success status.', { ...requestContext, status: response.status, }); callback(false, 401, 'Unauthorized: Invalid credentials'); } } catch (error) { logTerminal('error', 'Websocket client authentication failed.', { ...requestContext, error: error.message, responseStatus: error.response?.status, responseData: error.response?.data, }); callback(false, 500, 'Internal Server Error'); } }; const wss = new WebSocketServer({ server, path: '/terminal/ws', verifyClient: verifyClient }); wss.on('connection', async (ws, req) => { const userId = generateUserId(); const userSession = { ws, userId, ptyProcess: null, isActive: false, authorizedIPs: [] }; const { xsrfToken, laravelSession, sessionCookieName } = getSessionCookie(req); const connectionContext = { userId, remoteAddress: req.socket?.remoteAddress, sessionCookieName, hasXsrfToken: Boolean(xsrfToken), hasLaravelSession: Boolean(laravelSession), }; // Verify presence of required tokens if (!laravelSession || !xsrfToken) { logTerminal('warn', 'Closing websocket connection because required auth tokens are missing.', connectionContext); ws.close(401, 'Unauthorized: Missing required tokens'); return; } try { const response = await axios.post(`http://coolify:8080/terminal/auth/ips`, null, { headers: { 'Cookie': `${sessionCookieName}=${laravelSession}`, 'X-XSRF-TOKEN': xsrfToken }, }); userSession.authorizedIPs = response.data.ipAddresses || []; logTerminal('log', 'Fetched authorized terminal hosts for websocket session.', { ...connectionContext, authorizedIPs: userSession.authorizedIPs, }); } catch (error) { logTerminal('error', 'Failed to fetch authorized terminal hosts.', { ...connectionContext, error: error.message, responseStatus: error.response?.status, responseData: error.response?.data, }); ws.close(1011, 'Failed to fetch terminal authorization data'); return; } userSessions.set(userId, userSession); logTerminal('log', 'Terminal websocket connection established.', { ...connectionContext, authorizedHostCount: userSession.authorizedIPs.length, }); ws.on('message', (message) => { handleMessage(userSession, message); }); ws.on('error', (err) => handleError(err, userId)); ws.on('close', (code, reason) => { logTerminal('log', 'Terminal websocket connection closed.', { userId, code, reason: reason?.toString(), }); handleClose(userId); }); }); const messageHandlers = { message: (session, data) => session.ptyProcess.write(data), resize: (session, { cols, rows }) => { cols = cols > 0 ? cols : 80; rows = rows > 0 ? rows : 30; session.ptyProcess.resize(cols, rows) }, pause: (session) => session.ptyProcess.pause(), resume: (session) => session.ptyProcess.resume(), ping: (session) => session.ws.send('pong'), checkActive: (session, data) => { if (data === 'force' && session.isActive) { killPtyProcess(session.userId); } else { session.ws.send(session.isActive); } }, command: (session, data) => handleCommand(session.ws, data, session.userId) }; function handleMessage(userSession, message) { const parsed = parseMessage(message); if (!parsed) { logTerminal('warn', 'Ignoring websocket message because JSON parsing failed.', { userId: userSession.userId, rawMessage: String(message).slice(0, 500), }); return; } logTerminal('log', 'Received websocket message.', { userId: userSession.userId, keys: Object.keys(parsed), isActive: userSession.isActive, }); Object.entries(parsed).forEach(([key, value]) => { const handler = messageHandlers[key]; if (handler && (userSession.isActive || key === 'checkActive' || key === 'command' || key === 'ping')) { handler(userSession, value); } else if (!handler) { logTerminal('warn', 'Ignoring websocket message with unknown handler key.', { userId: userSession.userId, key, }); } else { logTerminal('warn', 'Ignoring websocket message because no PTY session is active yet.', { userId: userSession.userId, key, }); } }); } function parseMessage(message) { try { return JSON.parse(message); } catch (e) { logTerminal('error', 'Failed to parse websocket message.', { error: e?.message ?? e, }); return null; } } async function handleCommand(ws, command, userId) { const userSession = userSessions.get(userId); if (userSession && userSession.isActive) { const result = await killPtyProcess(userId); if (!result) { logTerminal('warn', 'Rejecting new terminal command because the previous PTY could not be terminated.', { userId, }); // if terminal is still active, even after we tried to kill it, dont continue and show error ws.send('unprocessable'); return; } } const commandString = command[0].split('\n').join(' '); const timeout = extractTimeout(commandString); const sshArgs = extractSshArgs(commandString); const hereDocContent = extractHereDocContent(commandString); // Extract target host from SSH command const targetHost = extractTargetHost(sshArgs); logTerminal('log', 'Parsed terminal command metadata.', { userId, targetHost, timeout, sshArgs, authorizedIPs: userSession?.authorizedIPs ?? [], }); if (!targetHost) { logTerminal('warn', 'Rejecting terminal command because no target host could be extracted.', { userId, sshArgs, }); ws.send('Invalid SSH command: No target host found'); return; } // Validate target host against authorized IPs if (!isAuthorizedTargetHost(targetHost, userSession.authorizedIPs)) { logTerminal('warn', 'Rejecting terminal command because target host is not authorized.', { userId, targetHost, authorizedIPs: userSession.authorizedIPs, }); ws.send(`Unauthorized: Target host ${targetHost} not in authorized list`); return; } const options = { name: 'xterm-color', cols: 80, rows: 30, cwd: process.env.HOME, env: {}, }; // NOTE: - Initiates a process within the Terminal container // Establishes an SSH connection to root@coolify with RequestTTY enabled // Executes the 'docker exec' command to connect to a specific container logTerminal('log', 'Spawning PTY process for terminal session.', { userId, targetHost, timeout, }); const ptyProcess = pty.spawn('ssh', sshArgs.concat([hereDocContent]), options); userSession.ptyProcess = ptyProcess; userSession.isActive = true; ws.send('pty-ready'); ptyProcess.onData((data) => { ws.send(data); }); // when parent closes ptyProcess.onExit(({ exitCode, signal }) => { logTerminal(exitCode === 0 ? 'log' : 'error', 'PTY process exited.', { userId, exitCode, signal, }); ws.send('pty-exited'); userSession.isActive = false; }); if (timeout) { setTimeout(async () => { await killPtyProcess(userId); }, timeout * 1000); } } async function handleError(err, userId) { logTerminal('error', 'WebSocket error.', { userId, error: err?.message ?? err, }); await killPtyProcess(userId); } async function handleClose(userId) { logTerminal('log', 'Cleaning up terminal websocket session.', { userId, }); await killPtyProcess(userId); userSessions.delete(userId); } async function killPtyProcess(userId) { const session = userSessions.get(userId); if (!session?.ptyProcess) return false; return new Promise((resolve) => { // Loop to ensure terminal is killed before continuing let killAttempts = 0; const maxAttempts = 5; const attemptKill = () => { killAttempts++; logTerminal('log', 'Attempting to terminate PTY process.', { userId, killAttempts, maxAttempts, }); // session.ptyProcess.kill() wont work here because of https://github.com/moby/moby/issues/9098 // patch with https://github.com/moby/moby/issues/9098#issuecomment-189743947 session.ptyProcess.write('set +o history\nkill -TERM -$$ && exit\nset -o history\n'); setTimeout(() => { if (!session.isActive || !session.ptyProcess) { logTerminal('log', 'PTY process terminated successfully.', { userId, killAttempts, }); resolve(true); return; } if (killAttempts < maxAttempts) { attemptKill(); } else { logTerminal('warn', 'PTY process still active after maximum termination attempts.', { userId, killAttempts, }); resolve(false); } }, 500); }; attemptKill(); }); } function generateUserId() { return Math.random().toString(36).substring(2, 11); } server.listen(6002, () => { logTerminal('log', 'Terminal debug logging is enabled.', { terminalDebugEnabled, }); }); ================================================ FILE: docker/coolify-realtime/terminal-utils.js ================================================ export function extractTimeout(commandString) { const timeoutMatch = commandString.match(/timeout (\d+)/); return timeoutMatch ? parseInt(timeoutMatch[1], 10) : null; } function normalizeShellArgument(argument) { if (!argument) { return argument; } return argument .replace(/'([^']*)'/g, '$1') .replace(/"([^"]*)"/g, '$1'); } export function extractSshArgs(commandString) { const sshCommandMatch = commandString.match(/ssh (.+?) 'bash -se'/); if (!sshCommandMatch) return []; const argsString = sshCommandMatch[1]; let sshArgs = []; let current = ''; let inQuotes = false; let quoteChar = ''; let i = 0; while (i < argsString.length) { const char = argsString[i]; if (!inQuotes && (char === '"' || char === "'")) { inQuotes = true; quoteChar = char; current += char; } else if (inQuotes && char === quoteChar) { inQuotes = false; current += char; quoteChar = ''; } else if (!inQuotes && char === ' ') { if (current.trim()) { sshArgs.push(current.trim()); current = ''; } } else { current += char; } i++; } if (current.trim()) { sshArgs.push(current.trim()); } sshArgs = sshArgs.map((arg) => normalizeShellArgument(arg)); sshArgs = sshArgs.map(arg => arg === 'RequestTTY=no' ? 'RequestTTY=yes' : arg); if (!sshArgs.includes('RequestTTY=yes') && !sshArgs.some(arg => arg.includes('RequestTTY='))) { sshArgs.push('-o', 'RequestTTY=yes'); } return sshArgs; } export function extractHereDocContent(commandString) { const delimiterMatch = commandString.match(/<< (\S+)/); const delimiter = delimiterMatch ? delimiterMatch[1] : null; const escapedDelimiter = delimiter?.slice(1).trim().replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&'); if (!escapedDelimiter) { return ''; } const hereDocRegex = new RegExp(`<< \\\\${escapedDelimiter}([\\s\\S\\.]*?)${escapedDelimiter}`); const hereDocMatch = commandString.match(hereDocRegex); return hereDocMatch ? hereDocMatch[1] : ''; } export function normalizeHostForAuthorization(host) { if (!host) { return null; } let normalizedHost = host.trim(); while ( normalizedHost.length >= 2 && ((normalizedHost.startsWith("'") && normalizedHost.endsWith("'")) || (normalizedHost.startsWith('"') && normalizedHost.endsWith('"'))) ) { normalizedHost = normalizedHost.slice(1, -1).trim(); } if (normalizedHost.startsWith('[') && normalizedHost.endsWith(']')) { normalizedHost = normalizedHost.slice(1, -1); } return normalizedHost.toLowerCase(); } export function extractTargetHost(sshArgs) { const userAtHost = sshArgs.find(arg => { if (arg.includes('storage/app/ssh/keys/')) { return false; } return /^[^@]+@[^@]+$/.test(arg); }); if (!userAtHost) { return null; } const atIndex = userAtHost.indexOf('@'); return normalizeHostForAuthorization(userAtHost.slice(atIndex + 1)); } export function isAuthorizedTargetHost(targetHost, authorizedHosts = []) { const normalizedTargetHost = normalizeHostForAuthorization(targetHost); if (!normalizedTargetHost) { return false; } return authorizedHosts .map(host => normalizeHostForAuthorization(host)) .includes(normalizedTargetHost); } ================================================ FILE: docker/coolify-realtime/terminal-utils.test.js ================================================ import test from 'node:test'; import assert from 'node:assert/strict'; import { extractSshArgs, extractTargetHost, isAuthorizedTargetHost, normalizeHostForAuthorization, } from './terminal-utils.js'; test('extractTargetHost normalizes quoted IPv4 hosts from generated ssh commands', () => { const sshArgs = extractSshArgs( "timeout 3600 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR -o ServerAliveInterval=20 -o ConnectTimeout=10 'root'@'10.0.0.5' 'bash -se' << \\\\$abc\necho hi\nabc" ); assert.equal(extractTargetHost(sshArgs), '10.0.0.5'); }); test('extractSshArgs strips shell quotes from port and user host arguments before spawning ssh', () => { const sshArgs = extractSshArgs( "timeout 3600 ssh -p '22' -o StrictHostKeyChecking=no 'root'@'10.0.0.5' 'bash -se' << \\\\$abc\necho hi\nabc" ); assert.deepEqual(sshArgs.slice(0, 5), ['-p', '22', '-o', 'StrictHostKeyChecking=no', 'root@10.0.0.5']); }); test('extractSshArgs preserves proxy command as a single normalized ssh option value', () => { const sshArgs = extractSshArgs( "timeout 3600 ssh -o ProxyCommand='cloudflared access ssh --hostname %h' -o StrictHostKeyChecking=no 'root'@'example.com' 'bash -se' << \\\\$abc\necho hi\nabc" ); assert.equal(sshArgs[1], 'ProxyCommand=cloudflared access ssh --hostname %h'); assert.equal(sshArgs[4], 'root@example.com'); }); test('isAuthorizedTargetHost matches normalized hosts against plain allowlist values', () => { assert.equal(isAuthorizedTargetHost("'10.0.0.5'", ['10.0.0.5']), true); assert.equal(isAuthorizedTargetHost('"host.docker.internal"', ['host.docker.internal']), true); }); test('normalizeHostForAuthorization unwraps bracketed IPv6 hosts', () => { assert.equal(normalizeHostForAuthorization("'[2001:db8::10]'"), '2001:db8::10'); assert.equal(isAuthorizedTargetHost("'[2001:db8::10]'", ['2001:db8::10']), true); }); test('isAuthorizedTargetHost rejects hosts that are not in the allowlist', () => { assert.equal(isAuthorizedTargetHost("'10.0.0.9'", ['10.0.0.5']), false); }); ================================================ FILE: docker/development/Dockerfile ================================================ # Versions # https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine # https://github.com/minio/mc/releases ARG MINIO_VERSION=RELEASE.2025-05-21T01-59-54Z # https://github.com/cloudflare/cloudflared/releases ARG CLOUDFLARED_VERSION=2025.7.0 # https://www.postgresql.org/support/versioning/ # Note: We are using version 18 of the postgres client (while still using postgres 15 for the postgres server) as version 15 has been removed from Alpine 3.23+ https://pkgs.alpinelinux.org/packages?name=postgresql*-client&branch=v3.23&repo=&arch=x86_64&origin=&flagged=&maintainer= ARG POSTGRES_VERSION=18 # ================================================================= # Get MinIO client # ================================================================= FROM minio/mc:${MINIO_VERSION} AS minio-client # ================================================================= # Final Stage: Production image # ================================================================= FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION} ARG USER_ID ARG GROUP_ID ARG TARGETPLATFORM ARG POSTGRES_VERSION ARG CLOUDFLARED_VERSION WORKDIR /var/www/html USER root RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \ docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx # Install PostgreSQL repository and keys RUN apk add --no-cache gnupg && \ mkdir -p /usr/share/keyrings && \ curl -fSsL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor > /usr/share/keyrings/postgresql.gpg # Install system dependencies RUN apk add --no-cache \ postgresql${POSTGRES_VERSION}-client \ openssh-client \ git \ git-lfs \ jq \ lsof \ vim # Install PHP extensions RUN install-php-extensions sockets # Configure shell aliases RUN echo "alias ll='ls -al'" >> /etc/profile && \ echo "alias a='php artisan'" >> /etc/profile && \ echo "alias logs='tail -f storage/logs/laravel.log'" >> /etc/profile # Install Cloudflared based on architecture RUN mkdir -p /usr/local/bin && \ if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \ curl -sSL "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-amd64" -o /usr/local/bin/cloudflared; \ elif [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \ curl -sSL "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-arm64" -o /usr/local/bin/cloudflared; \ fi && \ chmod +x /usr/local/bin/cloudflared # Configure PHP COPY docker/development/etc/php/conf.d/zzz-custom-php.ini /usr/local/etc/php/conf.d/zzz-custom-php.ini ENV PHP_OPCACHE_ENABLE=0 # Configure Nginx and S6 overlay COPY docker/development/etc/nginx/conf.d/custom.conf /etc/nginx/conf.d/custom.conf COPY docker/development/etc/nginx/site-opts.d/http.conf /etc/nginx/site-opts.d/http.conf COPY --chmod=755 docker/development/etc/s6-overlay/ /etc/s6-overlay/ RUN mkdir -p /etc/nginx/conf.d && \ chown -R www-data:www-data /etc/nginx && \ chmod -R 755 /etc/nginx # Install MinIO client COPY --from=minio-client /usr/bin/mc /usr/bin/mc RUN chmod +x /usr/bin/mc # Switch to non-root user USER www-data ================================================ FILE: docker/development/etc/nginx/conf.d/custom.conf ================================================ # Custom nginx configuration # Disable access logs access_log off; ================================================ FILE: docker/development/etc/nginx/site-opts.d/http.conf ================================================ listen 8080 default_server; listen [::]:8080 default_server; root /var/www/html/public; # Set allowed "index" files index index.html index.htm index.php; server_name _; charset utf-8; # Set max upload to 2048M client_max_body_size 2048M; # Set client body buffer to handle Sentinel payloads in memory client_body_buffer_size 256k; # Healthchecks: Set /healthcheck to be the healthcheck URL location /healthcheck { access_log off; # set max 5 seconds for healthcheck fastcgi_read_timeout 5s; include fastcgi_params; fastcgi_param SCRIPT_NAME /healthcheck; fastcgi_param SCRIPT_FILENAME /healthcheck; fastcgi_pass 127.0.0.1:9000; } # Have NGINX try searching for PHP files as well location / { try_files $uri $uri/ /index.php?$query_string; } # Pass "*.php" files to PHP-FPM location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; fastcgi_read_timeout 99; } ================================================ FILE: docker/development/etc/php/conf.d/zzz-custom-php.ini ================================================ error_reporting = E_ERROR error_log = /dev/stderr log_errors = On log_errors_max_len = 8192 ignore_repeated_errors = On ignore_repeated_source = On upload_max_filesize = 256M post_max_size = 256M memory_limit = ${PHP_MEMORY_LIMIT:-512M} ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/horizon/dependencies.d/init-setup ================================================ ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/horizon/run ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { php artisan start:horizon } ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/horizon/type ================================================ longrun ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/init-setup/type ================================================ oneshot ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/init-setup/up ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { composer install } foreground { php artisan migrate --step } foreground { php artisan dev --init } ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/scheduler-worker/dependencies.d/init-setup ================================================ ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/scheduler-worker/run ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { php artisan start:scheduler } ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/scheduler-worker/type ================================================ longrun ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/user/contents.d/horizon ================================================ ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/user/contents.d/init-setup ================================================ ================================================ FILE: docker/development/etc/s6-overlay/s6-rc.d/user/contents.d/scheduler-worker ================================================ ================================================ FILE: docker/production/Dockerfile ================================================ # Versions # https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine # https://github.com/minio/mc/releases ARG MINIO_VERSION=RELEASE.2025-05-21T01-59-54Z # https://github.com/cloudflare/cloudflared/releases ARG CLOUDFLARED_VERSION=2025.7.0 # https://www.postgresql.org/support/versioning/ # Note: We are using version 18 of the postgres client (while still using postgres 15 for the postgres server) as version 15 has been removed from Alpine 3.23+ https://pkgs.alpinelinux.org/packages?name=postgresql*-client&branch=v3.23&repo=&arch=x86_64&origin=&flagged=&maintainer= ARG POSTGRES_VERSION=18 # Add user/group ARG USER_ID=9999 ARG GROUP_ID=9999 # ================================================================= # Stage 1: Composer dependencies # ================================================================= FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION} AS base USER root ARG USER_ID ARG GROUP_ID RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \ docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx WORKDIR /var/www/html COPY --chown=www-data:www-data composer.json composer.lock ./ RUN --mount=type=cache,target=/tmp/cache \ COMPOSER_CACHE_DIR=/tmp/cache composer install --no-dev --no-interaction --no-plugins --no-scripts --prefer-dist USER www-data # ================================================================= # Stage 2: Frontend assets compilation # ================================================================= FROM node:24-alpine AS static-assets WORKDIR /app COPY package*.json vite.config.js postcss.config.cjs ./ RUN --mount=type=cache,target=/root/.npm \ npm ci COPY . . RUN npm run build # ================================================================= # Stage 3: Get MinIO client # ================================================================= FROM minio/mc:${MINIO_VERSION} AS minio-client # ================================================================= # Final Stage: Production image # ================================================================= FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION} ARG USER_ID ARG GROUP_ID ARG TARGETPLATFORM ARG POSTGRES_VERSION ARG CLOUDFLARED_VERSION ARG CI=true WORKDIR /var/www/html USER root RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \ docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx # Install PostgreSQL repository and keys RUN apk add --no-cache gnupg && \ mkdir -p /usr/share/keyrings && \ curl -fSsL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor > /usr/share/keyrings/postgresql.gpg # Install system dependencies RUN --mount=type=cache,target=/var/cache/apk \ apk upgrade && \ apk add --no-cache \ postgresql${POSTGRES_VERSION}-client \ openssh-client \ git \ git-lfs \ jq \ lsof \ vim # Configure shell aliases RUN echo "alias ll='ls -al'" >> /etc/profile && \ echo "alias a='php artisan'" >> /etc/profile && \ echo "alias logs='tail -f storage/logs/laravel.log'" >> /etc/profile # Install Cloudflared based on architecture RUN mkdir -p /usr/local/bin && \ if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \ curl -sSL "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-amd64" -o /usr/local/bin/cloudflared; \ elif [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \ curl -sSL "https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-arm64" -o /usr/local/bin/cloudflared; \ fi && \ chmod +x /usr/local/bin/cloudflared # Configure PHP COPY docker/production/etc/php/conf.d/zzz-custom-php.ini /usr/local/etc/php/conf.d/zzz-custom-php.ini ENV PHP_OPCACHE_ENABLE=1 # Configure entrypoint COPY --chmod=755 docker/production/entrypoint.d/ /etc/entrypoint.d # Copy application files from previous stages COPY --from=base --chown=www-data:www-data /var/www/html/vendor ./vendor COPY --from=static-assets --chown=www-data:www-data /app/public/build ./public/build # Copy application source code COPY --chown=www-data:www-data composer.json composer.lock ./ COPY --chown=www-data:www-data app ./app COPY --chown=www-data:www-data bootstrap ./bootstrap COPY --chown=www-data:www-data config ./config COPY --chown=www-data:www-data database ./database COPY --chown=www-data:www-data lang ./lang COPY --chown=www-data:www-data public ./public COPY --chown=www-data:www-data routes ./routes COPY --chown=www-data:www-data storage ./storage COPY --chown=www-data:www-data templates ./templates COPY --chown=www-data:www-data resources/views ./resources/views COPY --chown=www-data:www-data artisan artisan COPY --chown=www-data:www-data openapi.yaml ./openapi.yaml COPY --chown=www-data:www-data changelogs/ ./changelogs/ RUN composer dump-autoload # Configure Nginx and S6 overlay COPY docker/production/etc/nginx/conf.d/custom.conf /etc/nginx/conf.d/custom.conf COPY docker/production/etc/nginx/site-opts.d/http.conf /etc/nginx/site-opts.d/http.conf COPY --chmod=755 docker/production/etc/s6-overlay/ /etc/s6-overlay/ RUN mkdir -p /etc/nginx/conf.d && \ chown -R www-data:www-data /etc/nginx && \ chmod -R 755 /etc/nginx # Install MinIO client COPY --from=minio-client /usr/bin/mc /usr/bin/mc RUN chmod +x /usr/bin/mc # Switch to non-root user USER www-data ================================================ FILE: docker/production/entrypoint.d/99-debug-mode.sh ================================================ # Debug mode if [ "$APP_DEBUG" = "true" ]; then echo "Debug mode is enabled" echo "Installing development dependencies..." composer install --dev --no-scripts echo "Clearing optimized classes..." php artisan optimize:clear fi ================================================ FILE: docker/production/etc/nginx/conf.d/custom.conf ================================================ # Custom nginx configuration # Disable access logs access_log off; ================================================ FILE: docker/production/etc/nginx/site-opts.d/http.conf ================================================ listen 8080 default_server; listen [::]:8080 default_server; root /var/www/html/public; # Set allowed "index" files index index.html index.htm index.php; server_name _; charset utf-8; # Set max upload to 2048M client_max_body_size 2048M; # Set client body buffer to handle Sentinel payloads in memory client_body_buffer_size 256k; # Healthchecks: Set /healthcheck to be the healthcheck URL location /healthcheck { access_log off; # set max 5 seconds for healthcheck fastcgi_read_timeout 5s; include fastcgi_params; fastcgi_param SCRIPT_NAME /healthcheck; fastcgi_param SCRIPT_FILENAME /healthcheck; fastcgi_pass 127.0.0.1:9000; } # Have NGINX try searching for PHP files as well location / { try_files $uri $uri/ /index.php?$query_string; } # Pass "*.php" files to PHP-FPM location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; fastcgi_read_timeout 99; } ================================================ FILE: docker/production/etc/php/conf.d/zzz-custom-php.ini ================================================ error_reporting = E_ERROR error_log = /var/www/html/storage/logs/php-error.log log_errors = Off log_errors_max_len = 8192 ignore_repeated_errors = On ignore_repeated_source = On upload_max_filesize = 256M post_max_size = 256M memory_limit = ${PHP_MEMORY_LIMIT:-512M} ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/db-migration/type ================================================ oneshot ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/db-migration/up ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { php artisan start:migration } ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/horizon/dependencies.d/init-script ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/horizon/run ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { php artisan start:horizon } ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/horizon/type ================================================ longrun ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/init-script/dependencies.d/init-seeder ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/init-script/type ================================================ oneshot ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/init-script/up ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { php artisan app:init } ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/init-seeder/dependencies.d/db-migration ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/init-seeder/type ================================================ oneshot ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/init-seeder/up ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { php artisan start:seeder } ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/scheduler-worker/dependencies.d/init-script ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/scheduler-worker/run ================================================ #!/command/execlineb -P # Use with-contenv to ensure environment variables are available with-contenv cd /var/www/html foreground { php artisan start:scheduler } ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/scheduler-worker/type ================================================ longrun ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/db-migration ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/horizon ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/init-script ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/init-seeder ================================================ ================================================ FILE: docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/scheduler-worker ================================================ ================================================ FILE: docker/testing-host/Dockerfile ================================================ # Versions # https://download.docker.com/linux/static/stable/ ARG DOCKER_VERSION=28.0.0 # https://github.com/docker/compose/releases ARG DOCKER_COMPOSE_VERSION=2.38.2 # https://github.com/docker/buildx/releases ARG DOCKER_BUILDX_VERSION=0.25.0 FROM debian:12-slim ARG TARGETPLATFORM ARG DOCKER_VERSION ARG DOCKER_COMPOSE_VERSION ARG DOCKER_BUILDX_VERSION USER root WORKDIR /root ENV PATH="/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin:$PATH" RUN apt update && apt -y install openssh-client openssh-server curl wget git jq jc RUN mkdir -p ~/.docker/cli-plugins RUN curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx RUN curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose RUN (curl -sSL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) RUN chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /root/.docker/cli-plugins/docker-buildx # Setup sshd RUN ssh-keygen -A RUN mkdir -p /run/sshd RUN mkdir -p ~/.ssh RUN echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuGmoeGq/pojrsyP1pszcNVuZx9iFkCELtxrh31QJ68 coolify@coolify-instance" >> ~/.ssh/authorized_keys EXPOSE 22 CMD ["/usr/sbin/sshd", "-D", "-o", "ListenAddress=0.0.0.0", "-o", "Port=22"] ================================================ FILE: docker-compose-maxio.dev.yml ================================================ services: coolify: image: coolify:dev pull_policy: never build: context: . dockerfile: ./docker/development/Dockerfile args: - USER_ID=${USERID:-1000} - GROUP_ID=${GROUPID:-1000} ports: - "${APP_PORT:-8000}:8080" environment: AUTORUN_ENABLED: false PUSHER_HOST: "${PUSHER_HOST}" PUSHER_PORT: "${PUSHER_PORT}" PUSHER_SCHEME: "${PUSHER_SCHEME:-http}" PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}" PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}" PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" healthcheck: test: curl -sf http://127.0.0.1:8080/api/health || exit 1 interval: 5s retries: 10 timeout: 2s volumes: - .:/var/www/html/:cached - dev_backups_data:/var/www/html/storage/app/backups networks: - coolify postgres: pull_policy: always ports: - "${FORWARD_DB_PORT:-5432}:5432" env_file: - .env environment: POSTGRES_USER: "${DB_USERNAME:-coolify}" POSTGRES_PASSWORD: "${DB_PASSWORD:-password}" POSTGRES_DB: "${DB_DATABASE:-coolify}" POSTGRES_HOST_AUTH_METHOD: "trust" healthcheck: test: [ "CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB" ] interval: 5s retries: 10 timeout: 2s volumes: - dev_postgres_data:/var/lib/postgresql/data redis: pull_policy: always ports: - "${FORWARD_REDIS_PORT:-6379}:6379" env_file: - .env healthcheck: test: redis-cli ping interval: 5s retries: 10 timeout: 2s volumes: - dev_redis_data:/data soketi: image: coolify-realtime:dev pull_policy: never build: context: . dockerfile: ./docker/coolify-realtime/Dockerfile env_file: - .env ports: - "${FORWARD_SOKETI_PORT:-6001}:6001" - "6002:6002" volumes: - ./storage:/var/www/html/storage - ./docker/coolify-realtime/terminal-server.js:/terminal/terminal-server.js - ./docker/coolify-realtime/terminal-utils.js:/terminal/terminal-utils.js environment: SOKETI_DEBUG: "false" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" SOKETI_HOST: "${SOKETI_HOST:-0.0.0.0}" healthcheck: test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:6001/ready && curl -fsS http://127.0.0.1:6002/ready || exit 1" ] interval: 5s retries: 10 timeout: 2s entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"] vite: image: node:24-alpine pull_policy: always container_name: coolify-vite working_dir: /var/www/html environment: VITE_HOST: "${VITE_HOST:-localhost}" VITE_PORT: "${VITE_PORT:-5173}" ports: - "${VITE_PORT:-5173}:${VITE_PORT:-5173}" volumes: - .:/var/www/html/:cached command: sh -c "npm install && npm run dev" networks: - coolify testing-host: image: coolify-testing-host:dev pull_policy: never build: context: . dockerfile: ./docker/testing-host/Dockerfile init: true container_name: coolify-testing-host volumes: - /var/run/docker.sock:/var/run/docker.sock - dev_coolify_data:/data/coolify - dev_backups_data:/data/coolify/backups - dev_postgres_data:/data/coolify/_volumes/database - dev_redis_data:/data/coolify/_volumes/redis - dev_minio_data:/data/coolify/_volumes/minio networks: - coolify mailpit: image: axllent/mailpit:latest pull_policy: always container_name: coolify-mail ports: - "${FORWARD_MAILPIT_PORT:-1025}:1025" - "${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025" networks: - coolify # maxio: # image: ghcr.io/coollabsio/maxio # pull_policy: always # container_name: coolify-maxio # ports: # - "${FORWARD_MAXIO_PORT:-9000}:9000" # environment: # MAXIO_ACCESS_KEY: "${MAXIO_ACCESS_KEY:-maxioadmin}" # MAXIO_SECRET_KEY: "${MAXIO_SECRET_KEY:-maxioadmin}" # volumes: # - dev_maxio_data:/data # networks: # - coolify minio: image: ghcr.io/coollabsio/minio:RELEASE.2025-10-15T17-29-55Z # Released on 15 October 2025 pull_policy: always container_name: coolify-minio command: server /data --console-address ":9001" ports: - "${FORWARD_MINIO_PORT:-9000}:9000" - "${FORWARD_MINIO_PORT_CONSOLE:-9001}:9001" environment: MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}" MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}" volumes: - dev_minio_data:/data - dev_maxio_data:/data networks: - coolify # maxio-init: # image: minio/mc:latest # pull_policy: always # container_name: coolify-maxio-init # restart: no # depends_on: # - maxio # entrypoint: > # /bin/sh -c " # echo 'Waiting for MaxIO to be ready...'; # until mc alias set local http://coolify-maxio:9000 maxioadmin maxioadmin 2>/dev/null; do # echo 'MaxIO not ready yet, waiting...'; # sleep 2; # done; # echo 'MaxIO is ready, creating bucket if needed...'; # mc mb local/local --ignore-existing; # echo 'MaxIO initialization complete - bucket local is ready'; # " # networks: # - coolify minio-init: image: minio/mc:latest pull_policy: always container_name: coolify-minio-init restart: no depends_on: - minio entrypoint: > /bin/sh -c " echo 'Waiting for MinIO to be ready...'; until mc alias set local http://coolify-minio:9000 minioadmin minioadmin 2>/dev/null; do echo 'MinIO not ready yet, waiting...'; sleep 2; done; echo 'MinIO is ready, creating bucket if needed...'; mc mb local/local --ignore-existing; echo 'MinIO initialization complete - bucket local is ready'; " networks: - coolify volumes: dev_backups_data: dev_postgres_data: dev_redis_data: dev_coolify_data: dev_minio_data: dev_maxio_data: networks: coolify: name: coolify external: false ================================================ FILE: docker-compose.dev.yml ================================================ services: coolify: image: coolify:dev pull_policy: never build: context: . dockerfile: ./docker/development/Dockerfile args: - USER_ID=${USERID:-1000} - GROUP_ID=${GROUPID:-1000} ports: - "${APP_PORT:-8000}:8080" environment: AUTORUN_ENABLED: false PUSHER_HOST: "${PUSHER_HOST}" PUSHER_PORT: "${PUSHER_PORT}" PUSHER_SCHEME: "${PUSHER_SCHEME:-http}" PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}" PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}" PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" healthcheck: test: curl -sf http://127.0.0.1:8080/api/health || exit 1 interval: 5s retries: 10 timeout: 2s volumes: - .:/var/www/html/:cached - dev_backups_data:/var/www/html/storage/app/backups networks: - coolify postgres: pull_policy: always ports: - "${FORWARD_DB_PORT:-5432}:5432" env_file: - .env environment: POSTGRES_USER: "${DB_USERNAME:-coolify}" POSTGRES_PASSWORD: "${DB_PASSWORD:-password}" POSTGRES_DB: "${DB_DATABASE:-coolify}" POSTGRES_HOST_AUTH_METHOD: "trust" healthcheck: test: [ "CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB" ] interval: 5s retries: 10 timeout: 2s volumes: - dev_postgres_data:/var/lib/postgresql/data redis: pull_policy: always ports: - "${FORWARD_REDIS_PORT:-6379}:6379" env_file: - .env healthcheck: test: redis-cli ping interval: 5s retries: 10 timeout: 2s volumes: - dev_redis_data:/data soketi: image: coolify-realtime:dev pull_policy: never build: context: . dockerfile: ./docker/coolify-realtime/Dockerfile env_file: - .env ports: - "${FORWARD_SOKETI_PORT:-6001}:6001" - "6002:6002" volumes: - ./storage:/var/www/html/storage - ./docker/coolify-realtime/terminal-server.js:/terminal/terminal-server.js - ./docker/coolify-realtime/terminal-utils.js:/terminal/terminal-utils.js environment: SOKETI_DEBUG: "false" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" SOKETI_HOST: "${SOKETI_HOST:-0.0.0.0}" healthcheck: test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:6001/ready && curl -fsS http://127.0.0.1:6002/ready || exit 1" ] interval: 5s retries: 10 timeout: 2s entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"] vite: image: node:24-alpine pull_policy: always container_name: coolify-vite working_dir: /var/www/html environment: VITE_HOST: "${VITE_HOST:-localhost}" VITE_PORT: "${VITE_PORT:-5173}" ports: - "${VITE_PORT:-5173}:${VITE_PORT:-5173}" volumes: - .:/var/www/html/:cached command: sh -c "npm install && npm run dev" networks: - coolify testing-host: image: coolify-testing-host:dev pull_policy: never build: context: . dockerfile: ./docker/testing-host/Dockerfile init: true container_name: coolify-testing-host volumes: - /var/run/docker.sock:/var/run/docker.sock - dev_coolify_data:/data/coolify - dev_backups_data:/data/coolify/backups - dev_postgres_data:/data/coolify/_volumes/database - dev_redis_data:/data/coolify/_volumes/redis - dev_minio_data:/data/coolify/_volumes/minio networks: - coolify mailpit: image: axllent/mailpit:latest pull_policy: always container_name: coolify-mail ports: - "${FORWARD_MAILPIT_PORT:-1025}:1025" - "${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025" networks: - coolify minio: image: ghcr.io/coollabsio/minio:RELEASE.2025-10-15T17-29-55Z # Released on 15 October 2025 pull_policy: always container_name: coolify-minio command: server /data --console-address ":9001" ports: - "${FORWARD_MINIO_PORT:-9000}:9000" - "${FORWARD_MINIO_PORT_CONSOLE:-9001}:9001" environment: MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}" MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}" volumes: - dev_minio_data:/data networks: - coolify minio-init: image: minio/mc:latest pull_policy: always container_name: coolify-minio-init restart: no depends_on: - minio entrypoint: > /bin/sh -c " echo 'Waiting for MinIO to be ready...'; until mc alias set local http://coolify-minio:9000 minioadmin minioadmin 2>/dev/null; do echo 'MinIO not ready yet, waiting...'; sleep 2; done; echo 'MinIO is ready, creating bucket if needed...'; mc mb local/local --ignore-existing; echo 'MinIO initialization complete - bucket local is ready'; " networks: - coolify volumes: dev_backups_data: dev_postgres_data: dev_redis_data: dev_coolify_data: dev_minio_data: networks: coolify: name: coolify external: false ================================================ FILE: docker-compose.prod.yml ================================================ services: coolify: image: "${REGISTRY_URL:-ghcr.io}/coollabsio/coolify:${LATEST_IMAGE:-latest}" volumes: - type: bind source: /data/coolify/source/.env target: /var/www/html/.env read_only: true - /data/coolify/ssh:/var/www/html/storage/app/ssh - /data/coolify/applications:/var/www/html/storage/app/applications - /data/coolify/databases:/var/www/html/storage/app/databases - /data/coolify/services:/var/www/html/storage/app/services - /data/coolify/backups:/var/www/html/storage/app/backups environment: - APP_ENV=${APP_ENV:-production} - PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-256M} - PHP_FPM_PM_CONTROL=${PHP_FPM_PM_CONTROL:-dynamic} - PHP_FPM_PM_START_SERVERS=${PHP_FPM_PM_START_SERVERS:-1} - PHP_FPM_PM_MIN_SPARE_SERVERS=${PHP_FPM_PM_MIN_SPARE_SERVERS:-1} - PHP_FPM_PM_MAX_SPARE_SERVERS=${PHP_FPM_PM_MAX_SPARE_SERVERS:-10} env_file: - /data/coolify/source/.env ports: - "${APP_PORT:-8000}:8080" expose: - "${APP_PORT:-8000}" healthcheck: test: curl --fail http://127.0.0.1:8080/api/health || exit 1 interval: 5s retries: 10 timeout: 2s depends_on: postgres: condition: service_healthy redis: condition: service_healthy soketi: condition: service_healthy postgres: volumes: - coolify-db:/var/lib/postgresql/data environment: POSTGRES_USER: "${DB_USERNAME}" POSTGRES_PASSWORD: "${DB_PASSWORD}" POSTGRES_DB: "${DB_DATABASE:-coolify}" healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${DB_USERNAME}", "-d", "${DB_DATABASE:-coolify}" ] interval: 5s retries: 10 timeout: 2s redis: command: redis-server --save 20 1 --loglevel warning --requirepass ${REDIS_PASSWORD} environment: REDIS_PASSWORD: "${REDIS_PASSWORD}" volumes: - coolify-redis:/data healthcheck: test: redis-cli ping interval: 5s retries: 10 timeout: 2s soketi: image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.11' ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" volumes: - /data/coolify/ssh:/var/www/html/storage/app/ssh environment: APP_NAME: "${APP_NAME:-Coolify}" SOKETI_DEBUG: "${SOKETI_DEBUG:-false}" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}" SOKETI_HOST: "${SOKETI_HOST:-0.0.0.0}" healthcheck: test: [ "CMD-SHELL", "wget -qO- http://127.0.0.1:6001/ready && wget -qO- http://127.0.0.1:6002/ready || exit 1" ] interval: 5s retries: 10 timeout: 2s volumes: coolify-db: name: coolify-db coolify-redis: name: coolify-redis networks: coolify: external: true ================================================ FILE: docker-compose.windows.yml ================================================ services: coolify-testing-host: init: true image: "ghcr.io/coollabsio/coolify-testing-host:latest" pull_policy: always container_name: coolify-testing-host volumes: - //var/run/docker.sock://var/run/docker.sock - ./:/data/coolify coolify: image: "ghcr.io/coollabsio/coolify:latest" pull_policy: always container_name: coolify restart: always working_dir: /var/www/html extra_hosts: - 'host.docker.internal:host-gateway' volumes: - type: bind source: .env target: /var/www/html/.env read_only: true - ./ssh:/var/www/html/storage/app/ssh - ./applications:/var/www/html/storage/app/applications - ./databases:/var/www/html/storage/app/databases - ./services:/var/www/html/storage/app/services - ./backups:/var/www/html/storage/app/backups env_file: - .env environment: - APP_ID - APP_ENV=production - APP_NAME - APP_KEY - DB_PASSWORD - REDIS_PASSWORD - SSL_MODE=off - PHP_PM_CONTROL=dynamic - PHP_PM_START_SERVERS=1 - PHP_PM_MIN_SPARE_SERVERS=1 - PHP_PM_MAX_SPARE_SERVERS=10 - PUSHER_APP_ID - PUSHER_APP_KEY - PUSHER_APP_SECRET - AUTOUPDATE=true - SELF_HOSTED=true - SSH_MUX_ENABLED=false - IS_WINDOWS_DOCKER_DESKTOP=true ports: - "${APP_PORT:-8000}:8080" expose: - "${APP_PORT:-8000}" healthcheck: test: curl --fail http://localhost:8080/api/health || exit 1 interval: 5s retries: 10 timeout: 2s depends_on: postgres: condition: service_healthy redis: condition: service_healthy postgres: image: postgres:15-alpine pull_policy: always container_name: coolify-db restart: always env_file: - .env volumes: - coolify-db:/var/lib/postgresql/data environment: POSTGRES_USER: "${DB_USERNAME}" POSTGRES_PASSWORD: "${DB_PASSWORD}" POSTGRES_DB: "${DB_DATABASE:-coolify}" healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${DB_USERNAME}", "-d", "${DB_DATABASE:-coolify}" ] interval: 5s retries: 10 timeout: 2s redis: image: redis:7-alpine pull_policy: always container_name: coolify-redis restart: always command: redis-server --save 20 1 --loglevel warning --requirepass ${REDIS_PASSWORD} env_file: - .env environment: REDIS_PASSWORD: "${REDIS_PASSWORD}" volumes: - coolify-redis:/data healthcheck: test: redis-cli ping interval: 5s retries: 10 timeout: 2s soketi: image: 'ghcr.io/coollabsio/coolify-realtime:1.0.10' pull_policy: always container_name: coolify-realtime restart: always env_file: - .env ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" volumes: - ./ssh:/var/www/html/storage/app/ssh environment: APP_NAME: "${APP_NAME:-Coolify}" SOKETI_DEBUG: "${SOKETI_DEBUG:-false}" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}" SOKETI_HOST: "${SOKETI_HOST:-0.0.0.0}" healthcheck: test: [ "CMD-SHELL", "wget -qO- http://127.0.0.1:6001/ready && wget -qO- http://127.0.0.1:6002/ready || exit 1" ] interval: 5s retries: 10 timeout: 2s volumes: coolify-db: name: coolify-db coolify-redis: name: coolify-redis ================================================ FILE: docker-compose.yml ================================================ services: coolify: container_name: coolify restart: always working_dir: /var/www/html extra_hosts: - host.docker.internal:host-gateway networks: - coolify depends_on: - postgres - redis - soketi postgres: image: postgres:15-alpine container_name: coolify-db restart: always networks: - coolify redis: image: redis:7-alpine container_name: coolify-redis restart: always networks: - coolify soketi: container_name: coolify-realtime extra_hosts: - host.docker.internal:host-gateway restart: always networks: - coolify networks: coolify: name: coolify driver: bridge external: false ================================================ FILE: jean.json ================================================ { "scripts": { "setup": "cp $JEAN_ROOT_PATH/.env . && mkdir -p .claude && cp $JEAN_ROOT_PATH/.claude/settings.local.json .claude/settings.local.json", "run": "docker rm -f coolify coolify-minio-init coolify-realtime coolify-minio coolify-testing-host coolify-redis coolify-db coolify-mail coolify-vite; spin up; spin down" } } ================================================ FILE: lang/ar.json ================================================ { "auth.login": "تسجيل الدخول", "auth.login.authentik": "تسجيل الدخول باستخدام Authentik", "auth.login.azure": "تسجيل الدخول باستخدام Microsoft", "auth.login.bitbucket": "تسجيل الدخول باستخدام Bitbucket", "auth.login.clerk": "تسجيل الدخول باستخدام Clerk", "auth.login.discord": "تسجيل الدخول باستخدام Discord", "auth.login.github": "تسجيل الدخول باستخدام GitHub", "auth.login.gitlab": "تسجيل الدخول باستخدام Gitlab", "auth.login.google": "تسجيل الدخول باستخدام Google", "auth.login.infomaniak": "تسجيل الدخول باستخدام Infomaniak", "auth.already_registered": "هل سبق لك التسجيل؟", "auth.confirm_password": "تأكيد كلمة المرور", "auth.forgot_password_link": "هل نسيت كلمة المرور؟", "auth.forgot_password_heading": "استعادة كلمة المرور", "auth.forgot_password_send_email": "إرسال بريد إلكتروني لإعادة تعيين كلمة المرور", "auth.register_now": "تسجيل", "auth.logout": "تسجيل الخروج", "auth.register": "تسجيل", "auth.registration_disabled": "تم تعطيل التسجيل. يرجى التواصل مع المسؤول.", "auth.reset_password": "إعادة تعيين كلمة المرور", "auth.failed": "هذه البيانات لا تتطابق مع سجلاتنا.", "auth.failed.callback": "فشل في معالجة استدعاء من مزود تسجيل الدخول.", "auth.failed.password": "كلمة المرور المقدمة غير صحيحة.", "auth.failed.email": "لا يمكننا العثور على مستخدم بهذا البريد الإلكتروني.", "auth.throttle": "عدد محاولات تسجيل الدخول كثيرة جدًا. يرجى المحاولة مرة أخرى في :seconds ثانية.", "input.name": "الاسم", "input.email": "البريد الإلكتروني", "input.password": "كلمة المرور", "input.password.again": "كلمة المرور مرة أخرى", "input.code": "الرمز لمرة واحدة", "input.recovery_code": "رمز الاسترداد", "button.save": "حفظ", "repository.url": "أمثلة
      للمستودعات العامة، استخدم https://....
      للمستودعات الخاصة، استخدم git@....

      سيتم تحديد الفرع main لـ https://github.com/coollabsio/coolify-examples
      سيتم تحديد الفرع nodejs-fastify لـ https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify
      سيتم تحديد الفرع main لـ https://gitea.com/sedlav/expressjs.git
      سيتم تحديد الفرع main لـ https://gitlab.com/andrasbacsai/nodejs-example.git.", "service.stop": "سيتم إيقاف هذه الخدمة.", "resource.docker_cleanup": "قم بتشغيل Docker Cleanup (قم بإزالة الصور غير المستخدمة وذاكرة التخزين المؤقت للمنشئ).", "resource.non_persistent": "سيتم حذف جميع البيانات غير الدائمة.", "resource.delete_volumes": "حذف جميع المجلدات والملفات المرتبطة بهذا المورد بشكل دائم.", "resource.delete_connected_networks": "حذف جميع الشبكات غير المحددة مسبقًا والمرتبطة بهذا المورد بشكل دائم.", "resource.delete_configurations": "حذف جميع ملفات التعريف من الخادم بشكل دائم.", "database.delete_backups_locally": "حذف كافة النسخ الاحتياطية نهائيًا من التخزين المحلي.", "warning.sslipdomain": "تم حفظ ملفات التعريف الخاصة بك، ولكن استخدام نطاق sslip مع https غير مستحسن، لأن خوادم Let's Encrypt مع هذا النطاق العام محدودة المعدل (ستفشل عملية التحقق من شهادة SSL).

      استخدم نطاقك الخاص بدلاً من ذلك." } ================================================ FILE: lang/az.json ================================================ { "auth.login": "Daxil ol", "auth.login.authentik": "Authentik ilə daxil ol", "auth.login.azure": "Azure ilə daxil ol", "auth.login.bitbucket": "Bitbucket ilə daxil ol", "auth.login.clerk": "Clerk ilə daxil ol", "auth.login.discord": "Discord ilə daxil ol", "auth.login.github": "Github ilə daxil ol", "auth.login.gitlab": "GitLab ilə daxil ol", "auth.login.google": "Google ilə daxil ol", "auth.login.infomaniak": "Infomaniak ilə daxil ol", "auth.already_registered": "Qeytiyatınız var?", "auth.confirm_password": "Şifrəni təsdiqləyin", "auth.forgot_password_link": "Şifrəmi unutdum?", "auth.forgot_password_heading": "Şifrəni bərpa et", "auth.forgot_password_send_email": "Şifrəni sıfırlamaq üçün e-poçt göndər", "auth.register_now": "Qeydiyyat", "auth.logout": "Çıxış", "auth.register": "Qeydiyyat", "auth.registration_disabled": "Qeydiyyat bağlıdır. Administratorla əlaqə saxlayın.", "auth.reset_password": "Şifrənin bərpası", "auth.failed": "Bu məlumatlar bizim qeydlərimizlə uyğun gəlmir.", "auth.failed.callback": "Giriş təminatçısından geri çağırma işlənə bilmədi.", "auth.failed.password": "Daxil etdiyiniz şifrə yanlışdır.", "auth.failed.email": "Bu e-poçt ünvanı ilə istifadəçi tapılmadı.", "auth.throttle": "Çox sayda uğursuz giriş cəhdi. Zəhmət olmasa :seconds saniyə sonra yenidən cəhd edin.", "input.name": "Ad", "input.email": "E-poçt", "input.password": "Şifrə", "input.password.again": "Şifrəni təkrar daxil edin", "input.code": "Bir dəfəlik kod", "input.recovery_code": "Bərpa kodu", "button.save": "Yadda saxla", "repository.url": "Nümunələr
      Publik repozitoriyalar üçün https://... istifadə edin.
      Özəl repozitoriyalar üçün git@... istifadə edin.

      https://github.com/coollabsio/coolify-examples main branch-ı seçiləcək
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify branch-ı seçiləcək.
      https://gitea.com/sedlav/expressjs.git main branch-ı seçiləcək.
      https://gitlab.com/andrasbacsai/nodejs-example.git main branch-ı seçiləcək.", "service.stop": "Bu xidmət dayandırılacaq.", "resource.docker_cleanup": "Docker təmizlənməsini işə salın (istifadə olunmayan şəkillər və builder keşini silin).", "resource.non_persistent": "Bütün qeyri-daimi məlumatlar silinəcək.", "resource.delete_volumes": "Bu resursla əlaqəli bütün həcm məlumatları tamamilə silinəcək.", "resource.delete_connected_networks": "Bu resursla əlaqəli bütün əvvəlcədən təyin olunmamış şəbəkələr tamamilə silinəcək.", "resource.delete_configurations": "Serverdən bütün konfiqurasiya faylları tamamilə silinəcək.", "database.delete_backups_locally": "Bütün ehtiyat nüsxələr lokal yaddaşdan tamamilə silinəcək.", "warning.sslipdomain": "Konfiqurasiya yadda saxlanıldı, lakin sslip domeni ilə https TÖVSİYƏ EDİLMİR, çünki Let's Encrypt serverləri bu ümumi domenlə məhdudlaşdırılır (SSL sertifikatının təsdiqlənməsi uğursuz olacaq).

      Əvəzində öz domeninizdən istifadə edin." } ================================================ FILE: lang/cs.json ================================================ { "auth.login": "Přihlásit se", "auth.login.azure": "Přihlásit se pomocí Microsoftu", "auth.login.bitbucket": "Přihlásit se pomocí Bitbucketu", "auth.login.clerk": "Přihlásit se pomocí Clerk", "auth.login.discord": "Přihlásit se pomocí Discordu", "auth.login.github": "Přihlásit se pomocí GitHubu", "auth.login.gitlab": "Přihlásit se pomocí Gitlabu", "auth.login.google": "Přihlásit se pomocí Google", "auth.login.infomaniak": "Přihlásit se pomocí Infomaniak", "auth.already_registered": "Již jste registrováni?", "auth.confirm_password": "Potvrďte heslo", "auth.forgot_password_link": "Zapomněli jste heslo?", "auth.forgot_password_heading": "Obnovení hesla", "auth.forgot_password_send_email": "Poslat e-mail pro resetování hesla", "auth.register_now": "Registrovat se", "auth.logout": "Odhlásit se", "auth.register": "Registrovat se", "auth.registration_disabled": "Registrace je zakázána. Kontaktujte prosím administrátora.", "auth.reset_password": "Obnovit heslo", "auth.failed": "Tyto údaje neodpovídají našim záznamům.", "auth.failed.callback": "Nepodařilo se zpracovat zpětné volání od poskytovatele přihlášení.", "auth.failed.password": "Zadané heslo je nesprávné.", "auth.failed.email": "Nemůžeme najít uživatele s touto e-mailovou adresou.", "auth.throttle": "Příliš mnoho pokusů o přihlášení. Zkuste to prosím znovu za :seconds sekund.", "input.name": "Jméno", "input.email": "E-mail", "input.password": "Heslo", "input.password.again": "Heslo znovu", "input.code": "Jednorázový kód", "input.recovery_code": "Obnovovací kód", "button.save": "Uložit", "repository.url": "Příklady
      Pro veřejné repozitáře, použijte https://....
      Pro soukromé repozitáře, použijte git@....

      https://github.com/coollabsio/coolify-examples main branch bude zvolena
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify branch bude vybrána.
      https://gitea.com/sedlav/expressjs.git main branch vybrána.
      https://gitlab.com/andrasbacsai/nodejs-example.git main branch bude vybrána." } ================================================ FILE: lang/de.json ================================================ { "auth.login": "Anmelden", "auth.login.azure": "Mit Microsoft anmelden", "auth.login.bitbucket": "Mit Bitbucket anmelden", "auth.login.clerk": "Mit Clerk anmelden", "auth.login.discord": "Mit Discord anmelden", "auth.login.github": "Mit GitHub anmelden", "auth.login.gitlab": "Mit GitLab anmelden", "auth.login.google": "Mit Google anmelden", "auth.login.infomaniak": "Mit Infomaniak anmelden", "auth.login.zitadel": "Mit Zitadel anmelden", "auth.already_registered": "Bereits registriert?", "auth.confirm_password": "Passwort bestätigen", "auth.forgot_password_link": "Passwort vergessen?", "auth.forgot_password_heading": "Passwort-Wiederherstellung", "auth.forgot_password_send_email": "Passwort zurücksetzen E-Mail senden", "auth.register_now": "Registrieren", "auth.logout": "Abmelden", "auth.register": "Registrieren", "auth.registration_disabled": "Registrierung ist deaktiviert. Bitte kontaktiere einen Administrator.", "auth.reset_password": "Passwort zurücksetzen", "auth.failed": "Diese Anmeldedaten wurden nicht gefunden.", "auth.failed.callback": "Fehlerhafte Verarbeitung der Antwort des Anmeldeanbieters.", "auth.failed.password": "Das angegebene Passwort ist inkorrekt.", "auth.failed.email": "Wir können keinen Benutzer mit dieser E-Mail Adresse finden.", "auth.throttle": "Zu viele Anmeldeversuche. Bitte versuche es in :seconds Sekunden erneut.", "input.name": "Name", "input.email": "E-Mail", "input.password": "Passwort", "input.password.again": "Passwort wiederholen", "input.code": "Einmalcode", "input.recovery_code": "Wiederherstellungscode", "button.save": "Speichern", "repository.url": "Beispiele
      Für öffentliche Repositories benutze https://....
      Für private Repositories benutze git@....

      https://github.com/coollabsio/coolify-examples main Branch wird ausgewählt
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify Branch wird ausgewählt.
      https://gitea.com/sedlav/expressjs.git main Branch wird ausgewählt.
      https://gitlab.com/andrasbacsai/nodejs-example.git main Branch wird ausgewählt." } ================================================ FILE: lang/en/passwords.php ================================================ 'Your password has been reset.', 'sent' => 'If an account exists with this email address, you will receive a password reset link shortly.', 'throttled' => 'Please wait before retrying.', 'token' => 'This password reset token is invalid.', 'user' => 'If an account exists with this email address, you will receive a password reset link shortly.', ]; ================================================ FILE: lang/en.json ================================================ { "auth.login": "Login", "auth.login.authentik": "Login with Authentik", "auth.login.azure": "Login with Microsoft", "auth.login.bitbucket": "Login with Bitbucket", "auth.login.clerk": "Login with Clerk", "auth.login.discord": "Login with Discord", "auth.login.github": "Login with GitHub", "auth.login.gitlab": "Login with Gitlab", "auth.login.google": "Login with Google", "auth.login.infomaniak": "Login with Infomaniak", "auth.login.zitadel": "Login with Zitadel", "auth.already_registered": "Already registered?", "auth.confirm_password": "Confirm password", "auth.forgot_password_link": "Forgot password?", "auth.forgot_password_heading": "Password recovery", "auth.forgot_password_send_email": "Send password reset email", "auth.register_now": "Register", "auth.logout": "Logout", "auth.register": "Register", "auth.registration_disabled": "Registration is disabled. Please contact the administrator.", "auth.reset_password": "Reset password", "auth.failed": "These credentials do not match our records.", "auth.failed.callback": "Failed to process callback from login provider.", "auth.failed.password": "The provided password is incorrect.", "auth.failed.email": "If an account exists with this email address, you will receive a password reset link shortly.", "auth.throttle": "Too many login attempts. Please try again in :seconds seconds.", "input.name": "Name", "input.email": "Email", "input.password": "Password", "input.password.again": "Password again", "input.code": "One-time code", "input.recovery_code": "Recovery code", "button.save": "Save", "repository.url": "Examples
      For Public repositories, use https://....
      For Private repositories, use git@....

      https://github.com/coollabsio/coolify-examples main branch will be selected
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify branch will be selected.
      https://gitea.com/sedlav/expressjs.git main branch will be selected.
      https://gitlab.com/andrasbacsai/nodejs-example.git main branch will be selected.", "service.stop": "This service will be stopped.", "resource.docker_cleanup": "Run Docker Cleanup (remove unused images and builder cache).", "resource.non_persistent": "All non-persistent data will be deleted.", "resource.delete_volumes": "Permanently delete all volumes associated with this resource.", "resource.delete_connected_networks": "Permanently delete all non-predefined networks associated with this resource.", "resource.delete_configurations": "Permanently delete all configuration files from the server.", "database.delete_backups_locally": "All backups will be permanently deleted from local storage.", "warning.sslipdomain": "Your configuration is saved, but sslip domain with https is NOT recommended, because Let's Encrypt servers with this public domain are rate limited (SSL certificate validation will fail).

      Use your own domain instead." } ================================================ FILE: lang/es.json ================================================ { "auth.login": "Iniciar Sesión", "auth.login.azure": "Acceder con Microsoft", "auth.login.bitbucket": "Acceder con Bitbucket", "auth.login.clerk": "Acceder con Clerk", "auth.login.discord": "Acceder con Discord", "auth.login.github": "Acceder con GitHub", "auth.login.gitlab": "Acceder con Gitlab", "auth.login.google": "Acceder con Google", "auth.login.infomaniak": "Acceder con Infomaniak", "auth.already_registered": "¿Ya estás registrado?", "auth.confirm_password": "Confirmar contraseña", "auth.forgot_password_link": "¿Olvidaste tu contraseña?", "auth.forgot_password_heading": "Recuperación de contraseña", "auth.forgot_password_send_email": "Enviar correo de recuperación de contraseña", "auth.register_now": "Registrar", "auth.logout": "Cerrar sesión", "auth.register": "Registrar", "auth.registration_disabled": "El registro está desactivado. Por favor contacta con el administrador.", "auth.reset_password": "Cambiar contraseña", "auth.failed": "Las credenciales no coinciden con nuestro registro..", "auth.failed.callback": "Falló el proceso de inicio de sesión con el proveedor.", "auth.failed.password": "La contraseña es incorrecta.", "auth.failed.email": "No encontramos un usuario con ese correo.", "auth.throttle": "Demasiados intentos. Por favor inténtalo en :seconds segundos.", "input.name": "Nombre", "input.email": "Correo", "input.password": "Contraseña", "input.password.again": "Escribe la contraseña otra vez", "input.code": "Código de único uso", "input.recovery_code": "Código de recuperación", "button.save": "Guardar", "repository.url": "Examples
      Para repositorios públicos, usar https://....
      Para repositorios privados, usar git@....

      https://github.com/coollabsio/coolify-examples main la rama 'main' será seleccionada.
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify la rama 'nodejs-fastify' será seleccionada.
      https://gitea.com/sedlav/expressjs.git main la rama 'main' será seleccionada.
      https://gitlab.com/andrasbacsai/nodejs-example.git main la rama 'main' será seleccionada." } ================================================ FILE: lang/fa.json ================================================ { "auth.login": "ورود", "auth.login.azure": "ورود با مایکروسافت", "auth.login.bitbucket": "ورود با Bitbucket", "auth.login.clerk": "ورود با Clerk", "auth.login.discord": "ورود با Discord", "auth.login.github": "ورود با گیت هاب", "auth.login.gitlab": "ورود با گیت لب", "auth.login.google": "ورود با گوگل", "auth.login.infomaniak": "ورود با Infomaniak", "auth.already_registered": "قبلاً ثبت نام کرده‌اید؟", "auth.confirm_password": "تایید رمز عبور", "auth.forgot_password_link": "رمز عبور را فراموش کرده‌اید؟", "auth.forgot_password_heading": "بازیابی رمز عبور", "auth.forgot_password_send_email": "ارسال ایمیل بازیابی رمز عبور", "auth.register_now": "ثبت نام", "auth.logout": "خروج", "auth.register": "ثبت نام", "auth.registration_disabled": "ثبت نام غیر فعال است. لطفا با ادمین تماس بگیرید.", "auth.reset_password": "بازیابی رمز عبور", "auth.failed": "این اطلاعات با سوابق ما مطابقت ندارد.", "auth.failed.callback": "پردازش بازگشت از ارائه‌دهنده ورود با شکست مواجه شد.", "auth.failed.password": "رمز عبور ارائه شده نادرست است.", "auth.failed.email": "ما نمی توانیم کاربر با آدرس ایمیل مورد نظر را پیدا کنیم.", "auth.throttle": "تعداد تلاش‌های ورود بیش از حد است. لطفاً در :seconds ثانیه دوباره تلاش کنید.", "input.name": "نام", "input.email": "ایمیل", "input.password": "رمز عبور", "input.password.again": "تکرار رمز عبور", "input.code": "کد یک‌ بار مصرف", "input.recovery_code": "کد بازیابی", "button.save": "ذخیره", "repository.url": "مثال‌ها
      برای مخازن عمومی، از https://... استفاده کنید.
      برای مخازن خصوصی، از git@... استفاده کنید.

      شاخه main انتخاب خواهد شد.
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify شاخه nodejs-fastify انتخاب خواهد شد.
      https://gitea.com/sedlav/expressjs.git شاخه main انتخاب خواهد شد.
      https://gitlab.com/andrasbacsai/nodejs-example.git شاخه main انتخاب خواهد شد." } ================================================ FILE: lang/fr.json ================================================ { "auth.login": "Connexion", "auth.login.authentik": "Connexion avec Authentik", "auth.login.azure": "Connexion avec Microsoft", "auth.login.bitbucket": "Connexion avec Bitbucket", "auth.login.clerk": "Connexion avec Clerk", "auth.login.discord": "Connexion avec Discord", "auth.login.github": "Connexion avec GitHub", "auth.login.gitlab": "Connexion avec Gitlab", "auth.login.google": "Connexion avec Google", "auth.login.infomaniak": "Connexion avec Infomaniak", "auth.already_registered": "Déjà enregistré ?", "auth.confirm_password": "Confirmer le mot de passe", "auth.forgot_password_link": "Mot de passe oublié ?", "auth.forgot_password_heading": "Récupération du mot de passe", "auth.forgot_password_send_email": "Envoyer l'email de réinitialisation de mot de passe", "auth.register_now": "S'enregistrer", "auth.logout": "Déconnexion", "auth.register": "S'enregistrer", "auth.registration_disabled": "L'enregistrement est désactivé. Merci de contacter l'administrateur.", "auth.reset_password": "Réinitialiser le mot de passe", "auth.failed": "Aucune correspondance n'a été trouvée pour les informations d'identification renseignées.", "auth.failed.callback": "Erreur lors du processus de retour de la plateforme de connexion.", "auth.failed.password": "Le mot de passe renseigné est incorrect.", "auth.failed.email": "Aucun utilisateur avec cette adresse email n'a été trouvé.", "auth.throttle": "Trop de tentatives de connexion. Merci de réessayer dans :seconds secondes.", "input.name": "Nom", "input.email": "Email", "input.password": "Mot de passe", "input.password.again": "Mot de passe identique", "input.code": "Code à usage unique", "input.recovery_code": "Code de récupération", "button.save": "Sauvegarder", "repository.url": "Exemples
      Pour les dépôts publiques, utilisez https://....
      Pour les dépôts privés, utilisez git@....

      https://github.com/coollabsio/coolify-examples main sera la branche selectionnée
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify sera la branche selectionnée.
      https://gitea.com/sedlav/expressjs.git main sera la branche selectionnée.
      https://gitlab.com/andrasbacsai/nodejs-example.git main sera la branche selectionnée.", "service.stop": "Ce service sera arrêté.", "resource.docker_cleanup": "Exécuter le nettoyage Docker (supprimer les images inutilisées et le cache du builder).", "resource.non_persistent": "Toutes les données non persistantes seront supprimées.", "resource.delete_volumes": "Supprimer définitivement tous les volumes associés à cette ressource.", "resource.delete_connected_networks": "Supprimer définitivement tous les réseaux non-prédéfinis associés à cette ressource.", "resource.delete_configurations": "Supprimer définitivement tous les fichiers de configuration du serveur.", "database.delete_backups_locally": "Toutes les sauvegardes seront définitivement supprimées du stockage local.", "warning.sslipdomain": "Votre configuration est enregistrée, mais l'utilisation du domaine sslip avec https N'EST PAS recommandée, car les serveurs Let's Encrypt avec ce domaine public sont limités en taux (la validation du certificat SSL échouera).

      Utilisez plutôt votre propre domaine." } ================================================ FILE: lang/id.json ================================================ { "auth.login": "Masuk", "auth.login.authentik": "Masuk dengan Authentik", "auth.login.azure": "Masuk dengan Microsoft", "auth.login.bitbucket": "Masuk dengan Bitbucket", "auth.login.clerk": "Masuk dengan Clerk", "auth.login.discord": "Masuk dengan Discord", "auth.login.github": "Masuk dengan GitHub", "auth.login.gitlab": "Masuk dengan Gitlab", "auth.login.google": "Masuk dengan Google", "auth.login.infomaniak": "Masuk dengan Infomaniak", "auth.already_registered": "Sudah terdaftar?", "auth.confirm_password": "Konfirmasi kata sandi", "auth.forgot_password_link": "Lupa kata sandi?", "auth.forgot_password_heading": "Pemulihan Kata Sandi", "auth.forgot_password_send_email": "Kirim email reset kata sandi", "auth.register_now": "Daftar", "auth.logout": "Keluar", "auth.register": "Daftar", "auth.registration_disabled": "Pendaftaran dinonaktifkan. Harap hubungi administrator.", "auth.reset_password": "Reset kata sandi", "auth.failed": "Kredensial ini tidak cocok dengan catatan kami.", "auth.failed.callback": "Gagal memproses callback dari penyedia login.", "auth.failed.password": "Kata sandi yang diberikan salah.", "auth.failed.email": "Kami tidak dapat menemukan pengguna dengan alamat e-mail tersebut.", "auth.throttle": "Terlalu banyak percobaan login. Silakan coba lagi dalam :seconds detik.", "input.name": "Nama", "input.email": "Email", "input.password": "Kata sandi", "input.password.again": "Kata sandi lagi", "input.code": "Kode sekali pakai", "input.recovery_code": "Kode pemulihan", "button.save": "Simpan", "repository.url": "Contoh
      Untuk repositori Publik, gunakan https://....
      Untuk repositori Privat, gunakan git@....

      https://github.com/coollabsio/coolify-examples cabang main akan dipilih
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify cabang nodejs-fastify akan dipilih.
      https://gitea.com/sedlav/expressjs.git cabang main akan dipilih.
      https://gitlab.com/andrasbacsai/nodejs-example.git cabang main akan dipilih.", "service.stop": "Layanan ini akan dihentikan.", "resource.docker_cleanup": "Jalankan Pembersihan Docker (hapus gambar yang tidak digunakan dan cache builder).", "resource.non_persistent": "Semua data non-persisten akan dihapus.", "resource.delete_volumes": "Hapus permanen semua volume yang terkait dengan sumber daya ini.", "resource.delete_connected_networks": "Hapus permanen semua jaringan non-predefined yang terkait dengan sumber daya ini.", "resource.delete_configurations": "Hapus permanen semua file konfigurasi dari server.", "database.delete_backups_locally": "Semua backup akan dihapus permanen dari penyimpanan lokal.", "warning.sslipdomain": "Konfigurasi Anda disimpan, tetapi domain sslip dengan https TIDAK direkomendasikan, karena server Let's Encrypt dengan domain publik ini dibatasi (validasi sertifikat SSL akan gagal).

      Gunakan domain Anda sendiri sebagai gantinya." } ================================================ FILE: lang/it.json ================================================ { "auth.login": "Accedi", "auth.login.authentik": "Accedi con Authentik", "auth.login.azure": "Accedi con Microsoft", "auth.login.bitbucket": "Accedi con Bitbucket", "auth.login.clerk": "Accedi con Clerk", "auth.login.discord": "Accedi con Discord", "auth.login.github": "Accedi con GitHub", "auth.login.gitlab": "Accedi con Gitlab", "auth.login.google": "Accedi con Google", "auth.login.infomaniak": "Accedi con Infomaniak", "auth.already_registered": "Già registrato?", "auth.confirm_password": "Conferma password", "auth.forgot_password_link": "Hai dimenticato la password?", "auth.forgot_password_heading": "Recupero password", "auth.forgot_password_send_email": "Invia email per reimpostare la password", "auth.register_now": "Registrati", "auth.logout": "Esci", "auth.register": "Registrati", "auth.registration_disabled": "La registrazione è disabilitata. Si prega di contattare l'amministratore.", "auth.reset_password": "Reimposta password", "auth.failed": "Queste credenziali non corrispondono ai nostri record.", "auth.failed.callback": "Errore durante l'elaborazione del callback dal provider di accesso.", "auth.failed.password": "La password fornita non è corretta.", "auth.failed.email": "Non possiamo trovare un utente con questo indirizzo email.", "auth.throttle": "Troppi tentativi di accesso. Per favore riprova tra :seconds secondi.", "input.name": "Nome", "input.email": "Email", "input.password": "Password", "input.password.again": "Ripeti password", "input.code": "Codice monouso", "input.recovery_code": "Codice di recupero", "button.save": "Salva", "repository.url": "Esempi
      Per i repository pubblici, utilizza https://....
      Per i repository privati, utilizza git@....

      https://github.com/coollabsio/coolify-examples verrà selezionato il branch main
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify verrà selezionato il branch nodejs-fastify.
      https://gitea.com/sedlav/expressjs.git verrà selezionato il branch main.
      https://gitlab.com/andrasbacsai/nodejs-example.git verrà selezionato il branch main.", "service.stop": "Questo servizio verrà arrestato.", "resource.docker_cleanup": "Esegui pulizia Docker (rimuove immagini non utilizzate e cache del builder).", "resource.non_persistent": "Tutti i dati non persistenti verranno eliminati.", "resource.delete_volumes": "Elimina definitivamente tutti i volumi associati a questa risorsa.", "resource.delete_connected_networks": "Elimina definitivamente tutte le reti non predefinite associate a questa risorsa.", "resource.delete_configurations": "Elimina definitivamente tutti i file di configurazione dal server.", "database.delete_backups_locally": "Tutti i backup verranno eliminati definitivamente dall'archiviazione locale.", "warning.sslipdomain": "La tua configurazione è stata salvata, ma il dominio sslip con https NON è raccomandato, poiché i server di Let's Encrypt con questo dominio pubblico hanno limitazioni di frequenza (la convalida del certificato SSL fallirà).

      Utilizza invece il tuo dominio personale." } ================================================ FILE: lang/ja.json ================================================ { "auth.login": "ログイン", "auth.login.azure": "Microsoftでログイン", "auth.login.bitbucket": "Bitbucketでログイン", "auth.login.clerk": "Clerkでログイン", "auth.login.discord": "Discordでログイン", "auth.login.github": "GitHubでログイン", "auth.login.gitlab": "Gitlabでログイン", "auth.login.google": "Googleでログイン", "auth.login.infomaniak": "Infomaniakでログイン", "auth.already_registered": "すでに登録済みですか?", "auth.confirm_password": "パスワードを確認", "auth.forgot_password_link": "パスワードをお忘れですか?", "auth.forgot_password_heading": "パスワードの再設定", "auth.forgot_password_send_email": "パスワードリセットメールを送信", "auth.register_now": "今すぐ登録", "auth.logout": "ログアウト", "auth.register": "登録", "auth.registration_disabled": "登録は無効です。管理者に連絡してください。", "auth.reset_password": "パスワードをリセット", "auth.failed": "これらの資格情報は記録と一致しません。", "auth.failed.callback": "ログインプロバイダーからのコールバックの処理に失敗しました。", "auth.failed.password": "提供されたパスワードが正しくありません。", "auth.failed.email": "そのメールアドレスのユーザーが見つかりません。", "auth.throttle": "ログイン試行回数が多すぎます。:seconds秒後にもう一度お試しください。", "input.name": "名前", "input.email": "メール", "input.password": "パスワード", "input.password.again": "パスワード再入力", "input.code": "ワンタイムコード", "input.recovery_code": "リカバリーコード", "button.save": "保存", "repository.url": "
      公開リポジトリの場合はhttps://...を使用してください。
      プライベートリポジトリの場合はgit@...を使用してください。

      https://github.com/coollabsio/coolify-examples mainブランチが選択されます
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastifyブランチが選択されます。
      https://gitea.com/sedlav/expressjs.git mainブランチが選択されます。
      https://gitlab.com/andrasbacsai/nodejs-example.git mainブランチが選択されます。" } ================================================ FILE: lang/no.json ================================================ { "auth.login": "Logg inn", "auth.login.authentik": "Logg inn med Authentik", "auth.login.azure": "Logg inn med Microsoft", "auth.login.bitbucket": "Logg inn med Bitbucket", "auth.login.clerk": "Logg inn med Clerk", "auth.login.discord": "Logg inn med Discord", "auth.login.github": "Logg inn med GitHub", "auth.login.gitlab": "Logg inn med Gitlab", "auth.login.google": "Logg inn med Google", "auth.login.infomaniak": "Logg inn med Infomaniak", "auth.already_registered": "Allerede registrert?", "auth.confirm_password": "Bekreft passord", "auth.forgot_password_link": "Glemt passord?", "auth.forgot_password_heading": "Gjenoppretting av passord", "auth.forgot_password_send_email": "Send e-post for tilbakestilling av passord", "auth.register_now": "Registrer deg", "auth.logout": "Logg ut", "auth.register": "Registrer", "auth.registration_disabled": "Registrering er deaktivert. Vennligst kontakt administrator.", "auth.reset_password": "Tilbakestill passord", "auth.failed": "Disse legitimasjonene samsvarer ikke med våre registre.", "auth.failed.callback": "Klarte ikke å behandle tilbakekall fra innloggingsleverandør.", "auth.failed.password": "Det oppgitte passordet er feil.", "auth.failed.email": "Vi finner ingen bruker med den e-postadressen.", "auth.throttle": "For mange innloggingsforsøk. Vennligst prøv igjen om :seconds sekunder.", "input.name": "Navn", "input.email": "E-post", "input.password": "Passord", "input.password.again": "Passord igjen", "input.code": "Engangskode", "input.recovery_code": "Gjenopprettingskode", "button.save": "Lagre", "repository.url": "Eksempler
      For offentlige repositorier, bruk https://....
      For private repositorier, bruk git@....

      https://github.com/coollabsio/coolify-examples main gren vil bli valgt
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify gren vil bli valgt.
      https://gitea.com/sedlav/expressjs.git main gren vil bli valgt.
      https://gitlab.com/andrasbacsai/nodejs-example.git main gren vil bli valgt.", "service.stop": "Denne tjenesten vil bli stoppet.", "resource.docker_cleanup": "Kjør Docker-opprydding (fjern ubrukte bilder og byggebuffer).", "resource.non_persistent": "Alle ikke-persistente data vil bli slettet.", "resource.delete_volumes": "Slett alle volumer tilknyttet denne ressursen permanent.", "resource.delete_connected_networks": "Slett alle ikke-forhåndsdefinerte nettverk tilknyttet denne ressursen permanent.", "resource.delete_configurations": "Slett alle konfigurasjonsfiler fra serveren permanent.", "database.delete_backups_locally": "Alle sikkerhetskopier vil bli slettet permanent fra lokal lagring.", "warning.sslipdomain": "Konfigurasjonen din er lagret, men sslip-domene med https er IKKE anbefalt, fordi Let's Encrypt-servere med dette offentlige domenet er hastighetsbegrenset (SSL-sertifikatvalidering vil mislykkes).

      Bruk ditt eget domene i stedet." } ================================================ FILE: lang/pl.json ================================================ { "auth.login": "Zaloguj", "auth.login.authentik": "Zaloguj się przez Authentik", "auth.login.azure": "Zaloguj się przez Microsoft", "auth.login.bitbucket": "Zaloguj się przez Bitbucket", "auth.login.clerk": "Zaloguj się przez Clerk", "auth.login.discord": "Zaloguj się przez Discord", "auth.login.github": "Zaloguj się przez GitHub", "auth.login.gitlab": "Zaloguj się przez Gitlab", "auth.login.google": "Zaloguj się przez Google", "auth.login.infomaniak": "Zaloguj się przez Infomaniak", "auth.login.zitadel": "Zaloguj się przez Zitadel", "auth.already_registered": "Już zarejestrowany?", "auth.confirm_password": "Potwierdź hasło", "auth.forgot_password_link": "Zapomniałeś hasło?", "auth.forgot_password_heading": "Odzyskiwanie hasła", "auth.forgot_password_send_email": "Wyślij email resetujący hasło", "auth.register_now": "Zarejestruj", "auth.logout": "Wyloguj", "auth.register": "Zarejestruj", "auth.registration_disabled": "Rejestracja jest wyłączona. Skontaktuj się z administratorem.", "auth.reset_password": "Zresetuj hasło", "auth.failed": "Podane dane nie zgadzają się z naszymi rekordami.", "auth.failed.callback": "Nie udało się przeprocesować callbacku od dostawcy logowania.", "auth.failed.password": "Podane hasło jest nieprawidłowe.", "auth.failed.email": "Nie znaleziono użytkownika z takim adresem email.", "auth.throttle": "Zbyt wiele prób logowania. Spróbuj ponownie za :seconds sekund.", "input.name": "Nazwa", "input.email": "Email", "input.password": "Hasło", "input.password.again": "Hasło ponownie", "input.code": "Jednorazowy kod", "input.recovery_code": "Kod odzyskiwania", "button.save": "Zapisz", "repository.url": "Przykłady
      Dla publicznych repozytoriów użyj https://....
      Dla prywatnych repozytoriów, użyj git@....

      https://github.com/coollabsio/coolify-examples - zostanie wybrany branch main
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify - zostanie wybrany branch nodejs-fastify
      https://gitea.com/sedlav/expressjs.git - zostanie wybrany branch main
      https://gitlab.com/andrasbacsai/nodejs-example.git - zostanie wybrany branch main", "service.stop": "Ten serwis zostanie zatrzymany.", "resource.docker_cleanup": "Uruchom Docker Cleanup (usunie nieużywane obrazy i cache buildera).", "resource.non_persistent": "Wszystkie nietrwałe dane zostaną usunięte.", "resource.delete_volumes": "Trwale usuń wszystkie wolumeny powiązane z tym zasobem.", "resource.delete_connected_networks": "Trwale usuń wszystkie niepredefiniowane sieci powiązane z tym zasobem.", "resource.delete_configurations": "Trwale usuń wszystkie pliki konfiguracyjne z serwera.", "database.delete_backups_locally": "Wszystkie backupy zostaną trwale usunięte z lokalnej pamięci.", "warning.sslipdomain": "Twoja konfiguracja została zapisana, lecz domena sslip z https jest NIEZALECANA, ponieważ serwery Let's Encrypt z tą publiczną domeną są pod rate limitem (walidacja certyfikatu SSL certificate się nie powiedzie).

      Lepiej użyj własnej domeny." } ================================================ FILE: lang/pt-br.json ================================================ { "auth.login": "Entrar", "auth.login.authentik": "Entrar com Authentik", "auth.login.azure": "Entrar com Microsoft", "auth.login.bitbucket": "Entrar com Bitbucket", "auth.login.clerk": "Entrar com Clerk", "auth.login.discord": "Entrar com Discord", "auth.login.github": "Entrar com GitHub", "auth.login.gitlab": "Entrar com Gitlab", "auth.login.google": "Entrar com Google", "auth.login.infomaniak": "Entrar com Infomaniak", "auth.login.zitadel": "Entrar com Zitadel", "auth.already_registered": "Já tem uma conta?", "auth.confirm_password": "Confirmar senha", "auth.forgot_password_link": "Esqueceu a senha?", "auth.forgot_password_heading": "Recuperação de senha", "auth.forgot_password_send_email": "Enviar e-mail para redefinir senha", "auth.register_now": "Cadastre-se", "auth.logout": "Sair", "auth.register": "Cadastrar", "auth.registration_disabled": "O registro está desativado. Por favor, contate o administrador.", "auth.reset_password": "Redefinir senha", "auth.failed": "Essas credenciais não correspondem aos nossos registros.", "auth.failed.callback": "Falha ao processar o callback do provedor de login.", "auth.failed.password": "A senha fornecida está incorreta.", "auth.failed.email": "Não encontramos nenhum usuário com esse endereço de e-mail.", "auth.throttle": "Muitas tentativas de login. Por favor, tente novamente em :seconds segundos.", "input.name": "Nome", "input.email": "E-mail", "input.password": "Senha", "input.password.again": "Senha novamente", "input.code": "Código de uso único", "input.recovery_code": "Código de recuperação", "button.save": "Salvar", "repository.url": "Exemplos
      Para repositórios públicos, use https://....
      Para repositórios privados, use git@....

      https://github.com/coollabsio/coolify-examples main branch será selecionado
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify branch será selecionado.
      https://gitea.com/sedlav/expressjs.git main branch será selecionado.
      https://gitlab.com/andrasbacsai/nodejs-example.git main branch será selecionado.", "service.stop": "Este serviço será parado.", "resource.docker_cleanup": "Executar limpeza do Docker (remover imagens não utilizadas e cache de build).", "resource.non_persistent": "Todos os dados não persistentes serão excluídos.", "resource.delete_volumes": "Excluir permanentemente todos os volumes associados a este recurso.", "resource.delete_connected_networks": "Excluir permanentemente todas as redes não predefinidas associadas a este recurso.", "resource.delete_configurations": "Excluir permanentemente todos os arquivos de configuração do servidor.", "database.delete_backups_locally": "Todos os backups serão excluídos permanentemente do armazenamento local.", "warning.sslipdomain": "Sua configuração foi salva, mas o domínio sslip com https NÃO é recomendado, porque os servidores do Let's Encrypt com este domínio público têm limitação de taxa (a validação do certificado SSL falhará).

      Use seu próprio domínio em vez disso." } ================================================ FILE: lang/pt.json ================================================ { "auth.login": "Entrar", "auth.login.authentik": "Entrar com Authentik", "auth.login.azure": "Entrar com Microsoft", "auth.login.bitbucket": "Entrar com Bitbucket", "auth.login.clerk": "Entrar com Clerk", "auth.login.discord": "Entrar com Discord", "auth.login.github": "Entrar com GitHub", "auth.login.gitlab": "Entrar com Gitlab", "auth.login.google": "Entrar com Google", "auth.login.infomaniak": "Entrar com Infomaniak", "auth.login.zitadel": "Entrar com Zitadel", "auth.already_registered": "Já tem uma conta?", "auth.confirm_password": "Confirmar senha", "auth.forgot_password_link": "Esqueceu a senha?", "auth.forgot_password_heading": "Recuperação de senha", "auth.forgot_password_send_email": "Enviar e-mail de redefinição de senha", "auth.register_now": "Cadastrar-se", "auth.logout": "Sair", "auth.register": "Cadastrar", "auth.registration_disabled": "Cadastro desativado. Por favor, entre em contato com o administrador.", "auth.reset_password": "Redefinir senha", "auth.failed": "Essas credenciais não correspondem aos nossos registros.", "auth.failed.callback": "Falha ao processar o callback do provedor de login.", "auth.failed.password": "A senha fornecida está incorreta.", "auth.failed.email": "Não encontramos um usuário com esse endereço de e-mail.", "auth.throttle": "Muitas tentativas de login. Por favor, tente novamente em :seconds segundos.", "input.name": "Nome", "input.email": "E-mail", "input.password": "Senha", "input.password.again": "Repetir senha", "input.code": "Código único", "input.recovery_code": "Código de recuperação", "button.save": "Salvar", "repository.url": "Exemplos
      Para repositórios públicos, use https://....
      Para repositórios privados, use git@....

      https://github.com/coollabsio/coolify-examples a branch main será selecionada
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify a branch nodejs-fastify será selecionada.
      https://gitea.com/sedlav/expressjs.git a branch main será selecionada.
      https://gitlab.com/andrasbacsai/nodejs-example.git a branch main será selecionada.", "service.stop": "Este serviço será parado.", "resource.docker_cleanup": "Executar limpeza do Docker (remover imagens não utilizadas e cache de build).", "resource.non_persistent": "Todos os dados não persistentes serão excluídos.", "resource.delete_volumes": "Excluir permanentemente todos os volumes associados a este recurso.", "resource.delete_connected_networks": "Excluir permanentemente todas as redes não predefinidas associadas a este recurso.", "resource.delete_configurations": "Excluir permanentemente todos os arquivos de configuração do servidor.", "database.delete_backups_locally": "Todos os backups serão excluídos permanentemente do armazenamento local.", "warning.sslipdomain": "Sua configuração foi salva, mas o domínio sslip com https NÃO é recomendado, porque os servidores do Let's Encrypt com este domínio público têm limitação de taxa (a validação do certificado SSL falhará).

      Use seu próprio domínio em vez disso." } ================================================ FILE: lang/ro.json ================================================ { "auth.login": "Autentificare", "auth.login.azure": "Autentificare prin Microsoft", "auth.login.bitbucket": "Autentificare prin Bitbucket", "auth.login.clerk": "Autentificare prin Clerk", "auth.login.discord": "Autentificare prin Discord", "auth.login.github": "Autentificare prin GitHub", "auth.login.gitlab": "Autentificare prin Gitlab", "auth.login.google": "Autentificare prin Google", "auth.login.infomaniak": "Autentificare prin Infomaniak", "auth.already_registered": "Sunteți deja înregistrat?", "auth.confirm_password": "Confirmați parola", "auth.forgot_password_link": "Ați uitat parola?", "auth.forgot_password_heading": "Recuperare parolă", "auth.forgot_password_send_email": "Trimiteți e-mail-ul pentru resetarea parolei", "auth.register_now": "Înregistrare", "auth.logout": "Deconectare", "auth.register": "Înregistrare", "auth.registration_disabled": "Înregistrarea este dezactivată. Vă rugăm să contactați administratorul site-ului.", "auth.reset_password": "Resetare parolă", "auth.failed": "Autentificare nereușită. Vă rugăm să verificați datele introduse.", "auth.failed.callback": "A apărut o eroare în timpul autentificării cu furnizorul extern.", "auth.failed.password": "Parola furnizată este incorectă.", "auth.failed.email": "Nu putem găsi un utilizator cu această adresă de e-mail.", "auth.throttle": "Prea multe încercări de autentificare. Vă rugăm să încercați din nou în :seconds secunde.", "input.name": "Nume", "input.email": "E-mail", "input.password": "Parolă", "input.password.again": "Repetați parola", "input.code": "Cod de unică folosință", "input.recovery_code": "Cod de recuperare", "button.save": "Salvare", "repository.url": "Exemple
      Pentru depozite publice, utilizați https://....
      Pentru depozite private, utilizați git@....

      https://github.com/coollabsio/coolify-examples va fi selectată ramura main
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify va fi selectată ramura nodejs-fastify.
      https://gitea.com/sedlav/expressjs.git va fi selectată ramura main.
      https://gitlab.com/andrasbacsai/nodejs-example.git va fi selectată ramura main.", "service.stop": "Acest serviciu va fi oprit.", "resource.docker_cleanup": "Executați curățarea Docker (eliminați imaginile neutilizate și memoria cache a constructorului).", "resource.non_persistent": "Toate datele nepersistente vor fi șterse.", "resource.delete_volumes": "Ștergeți definitiv toate volumele asociate cu această resursă.", "resource.delete_connected_networks": "Ștergeți definitiv toate rețelele non-predefinite asociate cu această resursă.", "resource.delete_configurations": "Ștergeți definitiv toate fișierele de configurare de pe server.", "database.delete_backups_locally": "Toate copiile de rezervă vor fi șterse definitiv din stocarea locală." } ================================================ FILE: lang/tr.json ================================================ { "auth.login": "Giriş", "auth.login.azure": "Microsoft ile Giriş Yap", "auth.login.bitbucket": "Bitbucket ile Giriş Yap", "auth.login.clerk": "Clerk ile Giriş Yap", "auth.login.discord": "Discord ile Giriş Yap", "auth.login.github": "GitHub ile Giriş Yap", "auth.login.gitlab": "GitLab ile Giriş Yap", "auth.login.google": "Google ile Giriş Yap", "auth.login.infomaniak": "Infomaniak ile Giriş Yap", "auth.already_registered": "Zaten kayıtlı mısınız?", "auth.confirm_password": "Şifreyi Onayla", "auth.forgot_password_link": "Şifrenizi mi unuttunuz?", "auth.forgot_password_heading": "Şifre Kurtarma", "auth.forgot_password_send_email": "Şifre sıfırlama e-postası gönder", "auth.register_now": "Kayıt Ol", "auth.logout": "Çıkış Yap", "auth.register": "Kayıt Ol", "auth.registration_disabled": "Kayıt devre dışı bırakıldı. Lütfen yöneticiyle iletişime geçin.", "auth.reset_password": "Şifreyi Sıfırla", "auth.failed": "Bu kimlik bilgileri kayıtlarımızla eşleşmiyor.", "auth.failed.callback": "Giriş sağlayıcıdan gelen istek işlenemedi.", "auth.failed.password": "Sağlanan şifre yanlış.", "auth.failed.email": "Bu e-posta adresiyle bir kullanıcı bulamıyoruz.", "auth.throttle": "Çok fazla giriş denemesi. Lütfen :seconds saniye sonra tekrar deneyin.", "input.name": "İsim", "input.email": "E-posta", "input.password": "Şifre", "input.password.again": "Şifreyi Tekrar Girin", "input.code": "Tek Kullanımlık Kod", "input.recovery_code": "Kurtarma Kodu", "button.save": "Kaydet", "repository.url": "Örnekler
      Halka açık depolar için https://... kullanın.
      Özel depolar için git@... kullanın.

      https://github.com/coollabsio/coolify-examples main dalı seçilecek
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify dalı seçilecek.
      https://gitea.com/sedlav/expressjs.git main dalı seçilecek.
      https://gitlab.com/andrasbacsai/nodejs-example.git main dalı seçilecek.", "service.stop": "Bu servis durdurulacak.", "resource.docker_cleanup": "Docker temizliği çalıştır (kullanılmayan imajları ve oluşturucu önbelleğini kaldır).", "resource.non_persistent": "Tüm kalıcı olmayan veriler silinecek.", "resource.delete_volumes": "Bu kaynakla ilişkili tüm hacimler kalıcı olarak silinecek.", "resource.delete_connected_networks": "Bu kaynakla ilişkili önceden tanımlanmamış tüm ağlar kalıcı olarak silinecek.", "resource.delete_configurations": "Sunucudaki tüm yapılandırma dosyaları kalıcı olarak silinecek.", "database.delete_backups_locally": "Tüm yedekler yerel depolamadan kalıcı olarak silinecek.", "warning.sslipdomain": "Yapılandırmanız kaydedildi, ancak sslip domain ile https ÖNERİLMEZ, çünkü Let's Encrypt sunucuları bu genel domain ile sınırlandırılmıştır (SSL sertifikası doğrulaması başarısız olur).

      Bunun yerine kendi domaininizi kullanın." } ================================================ FILE: lang/vi.json ================================================ { "auth.login": "Đăng Nhập", "auth.login.azure": "Đăng Nhập Bằng Microsoft", "auth.login.bitbucket": "Đăng Nhập Bằng Bitbucket", "auth.login.clerk": "Đăng Nhập Bằng Clerk", "auth.login.discord": "Đăng Nhập Bằng Discord", "auth.login.github": "Đăng Nhập Bằng GitHub", "auth.login.gitlab": "Đăng Nhập Bằng Gitlab", "auth.login.google": "Đăng Nhập Bằng Google", "auth.login.infomaniak": "Đăng Nhập Bằng Infomaniak", "auth.already_registered": "Đã đăng ký?", "auth.confirm_password": "Nhập lại mật khẩu", "auth.forgot_password_link": "Quên mật khẩu?", "auth.forgot_password_heading": "Khôi phục mật khẩu", "auth.forgot_password_send_email": "Gửi email đặt lại mật khẩu", "auth.register_now": "Đăng ký ngay", "auth.logout": "Đăng xuất", "auth.register": "Đăng ký", "auth.registration_disabled": "Đăng ký không khả dụng. Vui lòng liên hệ quản trị viên.", "auth.reset_password": "Đặt lại mật khẩu", "auth.failed": "Thông tin đăng nhập không khớp với bất kỳ tài khoản nào.", "auth.failed.callback": "Xử lý thông tin từ nhà cung cấp đăng nhập thất bại.", "auth.failed.password": "Mật khẩu bạn cung cấp không chính xác.", "auth.failed.email": "Không có người dùng nào đã đăng ký với email đó.", "auth.throttle": "Quá nhiều lần đăng nhập thất bại. Vui lòng thử lại sau :seconds giây.", "input.name": "Tên", "input.email": "Email", "input.password": "Mật khẩu", "input.password.again": "Mật khẩu lần nữa", "input.code": "One-time code", "input.recovery_code": "Mã khôi phục", "button.save": "Lưu", "repository.url": "Ví dụ
      Với repo công khai, sử dụng https://....
      Với repo riêng tư, sử dụng git@....

      https://github.com/coollabsio/coolify-examples nhánh chính sẽ được chọn
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nhánh nodejs-fastify sẽ được chọn.
      https://gitea.com/sedlav/expressjs.git nhánh chính sẽ được chọn.
      https://gitlab.com/andrasbacsai/nodejs-example.git nhánh chính sẽ được chọn." } ================================================ FILE: lang/zh-cn.json ================================================ { "auth.login": "登录", "auth.login.authentik": "使用 Authentik 登录", "auth.login.azure": "使用 Microsoft 登录", "auth.login.bitbucket": "使用 Bitbucket 登录", "auth.login.clerk": "使用 Clerk 登录", "auth.login.discord": "使用 Discord 登录", "auth.login.github": "使用 GitHub 登录", "auth.login.gitlab": "使用 Gitlab 登录", "auth.login.google": "使用 Google 登录", "auth.login.infomaniak": "使用 Infomaniak 登录", "auth.login.zitadel": "使用 Zitadel 登录", "auth.already_registered": "已经注册?", "auth.confirm_password": "确认密码", "auth.forgot_password_link": "忘记密码?", "auth.forgot_password_heading": "密码找回", "auth.forgot_password_send_email": "发送密码重置邮件", "auth.register_now": "注册", "auth.logout": "退出登录", "auth.register": "注册", "auth.registration_disabled": "注册已禁用,请联系管理员", "auth.reset_password": "重置密码", "auth.failed": "这些凭据与我们的记录不符", "auth.failed.callback": "处理第三方登录的回调时出错", "auth.failed.password": "密码错误", "auth.failed.email": "该账户未注册", "auth.throttle": "登录次数过多,请在 :seconds 秒后重试", "input.name": "用户名", "input.email": "邮箱", "input.password": "密码", "input.password.again": "确认密码", "input.code": "验证码", "input.recovery_code": "恢复码", "button.save": "保存", "repository.url": "示例
      对于公共代码仓库,请使用 https://...
      对于私有代码仓库,请使用 git@...

      https://github.com/coollabsio/coolify-examples main 分支将被选择
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify 分支将被选择。
      https://gitea.com/sedlav/expressjs.git main 分支将被选择。
      https://gitlab.com/andrasbacsai/nodejs-example.git main 分支将被选择", "service.stop": "此服务将被停止。", "resource.docker_cleanup": "运行 Docker 清理(删除未使用的镜像和构建缓存)。", "resource.non_persistent": "所有非持久性数据将被删除。", "resource.delete_volumes": "永久删除与此资源关联的所有卷。", "resource.delete_connected_networks": "永久删除与此资源关联的所有非预定义网络。", "resource.delete_configurations": "永久删除服务器上的所有配置文件。", "database.delete_backups_locally": "所有备份将从本地存储中永久删除。", "warning.sslipdomain": "您的配置已保存,但不建议将 sslip 域与 https 一起使用,因为 Let's Encrypt 服务器对此公共域有速率限制(SSL 证书验证将失败)。

      请改用您自己的域名。" } ================================================ FILE: lang/zh-tw.json ================================================ { "auth.login": "登入", "auth.login.azure": "使用 Microsoft 登入", "auth.login.bitbucket": "使用 Bitbucket 登入", "auth.login.clerk": "使用 Clerk 登入", "auth.login.discord": "使用 Discord 登入", "auth.login.github": "使用 GitHub 登入", "auth.login.gitlab": "使用 Gitlab 登入", "auth.login.google": "使用 Google 登入", "auth.login.infomaniak": "使用 Infomaniak 登入", "auth.already_registered": "已經註冊?", "auth.confirm_password": "確認密碼", "auth.forgot_password_link": "忘記密碼?", "auth.forgot_password_heading": "密碼找回", "auth.forgot_password_send_email": "發送重設密碼電郵", "auth.register_now": "註冊", "auth.logout": "登出", "auth.register": "註冊", "auth.registration_disabled": "註冊已停用,請聯絡管理員。", "auth.reset_password": "重設密碼", "auth.failed": "這些憑證與我們的記錄不符。", "auth.failed.callback": "無法處理來自登入提供者的回呼。", "auth.failed.password": "密碼錯誤。", "auth.failed.email": "找不到該電子郵件地址的使用者。", "auth.throttle": "登入嘗試次數太多。請在 :seconds 秒後重試。", "input.name": "名稱", "input.email": "電子郵件", "input.password": "密碼", "input.password.again": "再次輸入密碼", "input.code": "一次性代碼", "input.recovery_code": "恢復碼", "button.save": "儲存", "repository.url": "例子
      對於公共代碼倉庫,請使用 https://...
      對於私有代碼倉庫,請使用 git@...

      https://github.com/coollabsio/coolify-examples main 分支將被選擇
      https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify 分支將被選擇。
      https://gitea.com/sedlav/expressjs.git main 分支將被選擇。
      https://gitlab.com/andrasbacsai/nodejs-example.git main 分支將被選擇。" } ================================================ FILE: openapi.json ================================================ { "openapi": "3.1.0", "info": { "title": "Coolify", "version": "0.1" }, "servers": [ { "url": "https:\/\/app.coolify.io\/api\/v1", "description": "Coolify Cloud API. Change the host to your own instance if you are self-hosting." } ], "paths": { "\/applications": { "get": { "tags": [ "Applications" ], "summary": "List", "description": "List all applications.", "operationId": "list-applications", "parameters": [ { "name": "tag", "in": "query", "description": "Filter applications by tag name.", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all applications.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/Application" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/public": { "post": { "tags": [ "Applications" ], "summary": "Create (Public)", "description": "Create new application based on a public git repository.", "operationId": "create-public-application", "requestBody": { "description": "Application object that needs to be created.", "required": true, "content": { "application\/json": { "schema": { "required": [ "project_uuid", "server_uuid", "environment_name", "environment_uuid", "git_repository", "git_branch", "build_pack", "ports_exposes" ], "properties": { "project_uuid": { "type": "string", "description": "The project UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "environment_name": { "type": "string", "description": "The environment name. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "The environment UUID. You need to provide at least one of environment_name or environment_uuid." }, "git_repository": { "type": "string", "description": "The git repository URL." }, "git_branch": { "type": "string", "description": "The git branch." }, "build_pack": { "type": "string", "enum": [ "nixpacks", "static", "dockerfile", "dockercompose" ], "description": "The build pack type." }, "ports_exposes": { "type": "string", "description": "The ports to expose." }, "destination_uuid": { "type": "string", "description": "The destination UUID." }, "name": { "type": "string", "description": "The application name." }, "description": { "type": "string", "description": "The application description." }, "domains": { "type": "string", "description": "The application URLs in a comma-separated list." }, "git_commit_sha": { "type": "string", "description": "The git commit SHA." }, "docker_registry_image_name": { "type": "string", "description": "The docker registry image name." }, "docker_registry_image_tag": { "type": "string", "description": "The docker registry image tag." }, "is_static": { "type": "boolean", "description": "The flag to indicate if the application is static." }, "is_spa": { "type": "boolean", "description": "The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true." }, "is_auto_deploy_enabled": { "type": "boolean", "description": "The flag to indicate if auto-deploy is enabled on git push. Defaults to true." }, "is_force_https_enabled": { "type": "boolean", "description": "The flag to indicate if HTTPS is forced. Defaults to true." }, "static_image": { "type": "string", "enum": [ "nginx:alpine" ], "description": "The static image." }, "install_command": { "type": "string", "description": "The install command." }, "build_command": { "type": "string", "description": "The build command." }, "start_command": { "type": "string", "description": "The start command." }, "ports_mappings": { "type": "string", "description": "The ports mappings." }, "base_directory": { "type": "string", "description": "The base directory for all commands." }, "publish_directory": { "type": "string", "description": "The publish directory." }, "health_check_enabled": { "type": "boolean", "description": "Health check enabled." }, "health_check_path": { "type": "string", "description": "Health check path." }, "health_check_port": { "type": "string", "nullable": true, "description": "Health check port." }, "health_check_host": { "type": "string", "nullable": true, "description": "Health check host." }, "health_check_method": { "type": "string", "description": "Health check method." }, "health_check_return_code": { "type": "integer", "description": "Health check return code." }, "health_check_scheme": { "type": "string", "description": "Health check scheme." }, "health_check_response_text": { "type": "string", "nullable": true, "description": "Health check response text." }, "health_check_interval": { "type": "integer", "description": "Health check interval in seconds." }, "health_check_timeout": { "type": "integer", "description": "Health check timeout in seconds." }, "health_check_retries": { "type": "integer", "description": "Health check retries count." }, "health_check_start_period": { "type": "integer", "description": "Health check start period in seconds." }, "limits_memory": { "type": "string", "description": "Memory limit." }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit." }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness." }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation." }, "limits_cpus": { "type": "string", "description": "CPU limit." }, "limits_cpuset": { "type": "string", "nullable": true, "description": "CPU set." }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares." }, "custom_labels": { "type": "string", "description": "Custom labels." }, "custom_docker_run_options": { "type": "string", "description": "Custom docker run options." }, "post_deployment_command": { "type": "string", "description": "Post deployment command." }, "post_deployment_command_container": { "type": "string", "description": "Post deployment command container." }, "pre_deployment_command": { "type": "string", "description": "Pre deployment command." }, "pre_deployment_command_container": { "type": "string", "description": "Pre deployment command container." }, "manual_webhook_secret_github": { "type": "string", "description": "Manual webhook secret for Github." }, "manual_webhook_secret_gitlab": { "type": "string", "description": "Manual webhook secret for Gitlab." }, "manual_webhook_secret_bitbucket": { "type": "string", "description": "Manual webhook secret for Bitbucket." }, "manual_webhook_secret_gitea": { "type": "string", "description": "Manual webhook secret for Gitea." }, "redirect": { "type": "string", "nullable": true, "description": "How to set redirect with Traefik \/ Caddy. www<->non-www.", "enum": [ "www", "non-www", "both" ] }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the application should be deployed instantly." }, "dockerfile": { "type": "string", "description": "The Dockerfile content." }, "dockerfile_location": { "type": "string", "description": "The Dockerfile location in the repository." }, "docker_compose_location": { "type": "string", "description": "The Docker Compose location." }, "docker_compose_custom_start_command": { "type": "string", "description": "The Docker Compose custom start command." }, "docker_compose_custom_build_command": { "type": "string", "description": "The Docker Compose custom build command." }, "docker_compose_domains": { "type": "array", "description": "Array of URLs to be applied to containers of a dockercompose application.", "items": { "properties": { "name": { "type": "string", "description": "The service name as defined in docker-compose." }, "domain": { "type": "string", "description": "Comma-separated list of URLs (e.g. \"http:\/\/app.coolify.io,https:\/\/app2.coolify.io\")" } }, "type": "object" } }, "watch_paths": { "type": "string", "description": "The watch paths." }, "use_build_server": { "type": "boolean", "nullable": true, "description": "Use build server." }, "is_http_basic_auth_enabled": { "type": "boolean", "description": "HTTP Basic Authentication enabled." }, "http_basic_auth_username": { "type": "string", "nullable": true, "description": "Username for HTTP Basic Authentication" }, "http_basic_auth_password": { "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "force_domain_override": { "type": "boolean", "description": "Force domain usage even if conflicts are detected. Default is false." }, "autogenerate_domain": { "type": "boolean", "default": true, "description": "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." }, "is_container_label_escape_enabled": { "type": "boolean", "default": true, "description": "Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off." } }, "type": "object" } } } }, "responses": { "201": { "description": "Application created successfully.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/private-github-app": { "post": { "tags": [ "Applications" ], "summary": "Create (Private - GH App)", "description": "Create new application based on a private repository through a Github App.", "operationId": "create-private-github-app-application", "requestBody": { "description": "Application object that needs to be created.", "required": true, "content": { "application\/json": { "schema": { "required": [ "project_uuid", "server_uuid", "environment_name", "environment_uuid", "github_app_uuid", "git_repository", "git_branch", "build_pack", "ports_exposes" ], "properties": { "project_uuid": { "type": "string", "description": "The project UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "environment_name": { "type": "string", "description": "The environment name. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "The environment UUID. You need to provide at least one of environment_name or environment_uuid." }, "github_app_uuid": { "type": "string", "description": "The Github App UUID." }, "git_repository": { "type": "string", "description": "The git repository URL." }, "git_branch": { "type": "string", "description": "The git branch." }, "ports_exposes": { "type": "string", "description": "The ports to expose." }, "destination_uuid": { "type": "string", "description": "The destination UUID." }, "build_pack": { "type": "string", "enum": [ "nixpacks", "static", "dockerfile", "dockercompose" ], "description": "The build pack type." }, "name": { "type": "string", "description": "The application name." }, "description": { "type": "string", "description": "The application description." }, "domains": { "type": "string", "description": "The application URLs in a comma-separated list." }, "git_commit_sha": { "type": "string", "description": "The git commit SHA." }, "docker_registry_image_name": { "type": "string", "description": "The docker registry image name." }, "docker_registry_image_tag": { "type": "string", "description": "The docker registry image tag." }, "is_static": { "type": "boolean", "description": "The flag to indicate if the application is static." }, "is_spa": { "type": "boolean", "description": "The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true." }, "is_auto_deploy_enabled": { "type": "boolean", "description": "The flag to indicate if auto-deploy is enabled on git push. Defaults to true." }, "is_force_https_enabled": { "type": "boolean", "description": "The flag to indicate if HTTPS is forced. Defaults to true." }, "static_image": { "type": "string", "enum": [ "nginx:alpine" ], "description": "The static image." }, "install_command": { "type": "string", "description": "The install command." }, "build_command": { "type": "string", "description": "The build command." }, "start_command": { "type": "string", "description": "The start command." }, "ports_mappings": { "type": "string", "description": "The ports mappings." }, "base_directory": { "type": "string", "description": "The base directory for all commands." }, "publish_directory": { "type": "string", "description": "The publish directory." }, "health_check_enabled": { "type": "boolean", "description": "Health check enabled." }, "health_check_path": { "type": "string", "description": "Health check path." }, "health_check_port": { "type": "string", "nullable": true, "description": "Health check port." }, "health_check_host": { "type": "string", "nullable": true, "description": "Health check host." }, "health_check_method": { "type": "string", "description": "Health check method." }, "health_check_return_code": { "type": "integer", "description": "Health check return code." }, "health_check_scheme": { "type": "string", "description": "Health check scheme." }, "health_check_response_text": { "type": "string", "nullable": true, "description": "Health check response text." }, "health_check_interval": { "type": "integer", "description": "Health check interval in seconds." }, "health_check_timeout": { "type": "integer", "description": "Health check timeout in seconds." }, "health_check_retries": { "type": "integer", "description": "Health check retries count." }, "health_check_start_period": { "type": "integer", "description": "Health check start period in seconds." }, "limits_memory": { "type": "string", "description": "Memory limit." }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit." }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness." }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation." }, "limits_cpus": { "type": "string", "description": "CPU limit." }, "limits_cpuset": { "type": "string", "nullable": true, "description": "CPU set." }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares." }, "custom_labels": { "type": "string", "description": "Custom labels." }, "custom_docker_run_options": { "type": "string", "description": "Custom docker run options." }, "post_deployment_command": { "type": "string", "description": "Post deployment command." }, "post_deployment_command_container": { "type": "string", "description": "Post deployment command container." }, "pre_deployment_command": { "type": "string", "description": "Pre deployment command." }, "pre_deployment_command_container": { "type": "string", "description": "Pre deployment command container." }, "manual_webhook_secret_github": { "type": "string", "description": "Manual webhook secret for Github." }, "manual_webhook_secret_gitlab": { "type": "string", "description": "Manual webhook secret for Gitlab." }, "manual_webhook_secret_bitbucket": { "type": "string", "description": "Manual webhook secret for Bitbucket." }, "manual_webhook_secret_gitea": { "type": "string", "description": "Manual webhook secret for Gitea." }, "redirect": { "type": "string", "nullable": true, "description": "How to set redirect with Traefik \/ Caddy. www<->non-www.", "enum": [ "www", "non-www", "both" ] }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the application should be deployed instantly." }, "dockerfile": { "type": "string", "description": "The Dockerfile content." }, "dockerfile_location": { "type": "string", "description": "The Dockerfile location in the repository" }, "docker_compose_location": { "type": "string", "description": "The Docker Compose location." }, "docker_compose_custom_start_command": { "type": "string", "description": "The Docker Compose custom start command." }, "docker_compose_custom_build_command": { "type": "string", "description": "The Docker Compose custom build command." }, "docker_compose_domains": { "type": "array", "description": "Array of URLs to be applied to containers of a dockercompose application.", "items": { "properties": { "name": { "type": "string", "description": "The service name as defined in docker-compose." }, "domain": { "type": "string", "description": "Comma-separated list of URLs (e.g. \"http:\/\/app.coolify.io,https:\/\/app2.coolify.io\")" } }, "type": "object" } }, "watch_paths": { "type": "string", "description": "The watch paths." }, "use_build_server": { "type": "boolean", "nullable": true, "description": "Use build server." }, "is_http_basic_auth_enabled": { "type": "boolean", "description": "HTTP Basic Authentication enabled." }, "http_basic_auth_username": { "type": "string", "nullable": true, "description": "Username for HTTP Basic Authentication" }, "http_basic_auth_password": { "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "force_domain_override": { "type": "boolean", "description": "Force domain usage even if conflicts are detected. Default is false." }, "autogenerate_domain": { "type": "boolean", "default": true, "description": "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." }, "is_container_label_escape_enabled": { "type": "boolean", "default": true, "description": "Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off." } }, "type": "object" } } } }, "responses": { "201": { "description": "Application created successfully.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/private-deploy-key": { "post": { "tags": [ "Applications" ], "summary": "Create (Private - Deploy Key)", "description": "Create new application based on a private repository through a Deploy Key.", "operationId": "create-private-deploy-key-application", "requestBody": { "description": "Application object that needs to be created.", "required": true, "content": { "application\/json": { "schema": { "required": [ "project_uuid", "server_uuid", "environment_name", "environment_uuid", "private_key_uuid", "git_repository", "git_branch", "build_pack", "ports_exposes" ], "properties": { "project_uuid": { "type": "string", "description": "The project UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "environment_name": { "type": "string", "description": "The environment name. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "The environment UUID. You need to provide at least one of environment_name or environment_uuid." }, "private_key_uuid": { "type": "string", "description": "The private key UUID." }, "git_repository": { "type": "string", "description": "The git repository URL." }, "git_branch": { "type": "string", "description": "The git branch." }, "ports_exposes": { "type": "string", "description": "The ports to expose." }, "destination_uuid": { "type": "string", "description": "The destination UUID." }, "build_pack": { "type": "string", "enum": [ "nixpacks", "static", "dockerfile", "dockercompose" ], "description": "The build pack type." }, "name": { "type": "string", "description": "The application name." }, "description": { "type": "string", "description": "The application description." }, "domains": { "type": "string", "description": "The application URLs in a comma-separated list." }, "git_commit_sha": { "type": "string", "description": "The git commit SHA." }, "docker_registry_image_name": { "type": "string", "description": "The docker registry image name." }, "docker_registry_image_tag": { "type": "string", "description": "The docker registry image tag." }, "is_static": { "type": "boolean", "description": "The flag to indicate if the application is static." }, "is_spa": { "type": "boolean", "description": "The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true." }, "is_auto_deploy_enabled": { "type": "boolean", "description": "The flag to indicate if auto-deploy is enabled on git push. Defaults to true." }, "is_force_https_enabled": { "type": "boolean", "description": "The flag to indicate if HTTPS is forced. Defaults to true." }, "static_image": { "type": "string", "enum": [ "nginx:alpine" ], "description": "The static image." }, "install_command": { "type": "string", "description": "The install command." }, "build_command": { "type": "string", "description": "The build command." }, "start_command": { "type": "string", "description": "The start command." }, "ports_mappings": { "type": "string", "description": "The ports mappings." }, "base_directory": { "type": "string", "description": "The base directory for all commands." }, "publish_directory": { "type": "string", "description": "The publish directory." }, "health_check_enabled": { "type": "boolean", "description": "Health check enabled." }, "health_check_path": { "type": "string", "description": "Health check path." }, "health_check_port": { "type": "string", "nullable": true, "description": "Health check port." }, "health_check_host": { "type": "string", "nullable": true, "description": "Health check host." }, "health_check_method": { "type": "string", "description": "Health check method." }, "health_check_return_code": { "type": "integer", "description": "Health check return code." }, "health_check_scheme": { "type": "string", "description": "Health check scheme." }, "health_check_response_text": { "type": "string", "nullable": true, "description": "Health check response text." }, "health_check_interval": { "type": "integer", "description": "Health check interval in seconds." }, "health_check_timeout": { "type": "integer", "description": "Health check timeout in seconds." }, "health_check_retries": { "type": "integer", "description": "Health check retries count." }, "health_check_start_period": { "type": "integer", "description": "Health check start period in seconds." }, "limits_memory": { "type": "string", "description": "Memory limit." }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit." }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness." }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation." }, "limits_cpus": { "type": "string", "description": "CPU limit." }, "limits_cpuset": { "type": "string", "nullable": true, "description": "CPU set." }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares." }, "custom_labels": { "type": "string", "description": "Custom labels." }, "custom_docker_run_options": { "type": "string", "description": "Custom docker run options." }, "post_deployment_command": { "type": "string", "description": "Post deployment command." }, "post_deployment_command_container": { "type": "string", "description": "Post deployment command container." }, "pre_deployment_command": { "type": "string", "description": "Pre deployment command." }, "pre_deployment_command_container": { "type": "string", "description": "Pre deployment command container." }, "manual_webhook_secret_github": { "type": "string", "description": "Manual webhook secret for Github." }, "manual_webhook_secret_gitlab": { "type": "string", "description": "Manual webhook secret for Gitlab." }, "manual_webhook_secret_bitbucket": { "type": "string", "description": "Manual webhook secret for Bitbucket." }, "manual_webhook_secret_gitea": { "type": "string", "description": "Manual webhook secret for Gitea." }, "redirect": { "type": "string", "nullable": true, "description": "How to set redirect with Traefik \/ Caddy. www<->non-www.", "enum": [ "www", "non-www", "both" ] }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the application should be deployed instantly." }, "dockerfile": { "type": "string", "description": "The Dockerfile content." }, "dockerfile_location": { "type": "string", "description": "The Dockerfile location in the repository." }, "docker_compose_location": { "type": "string", "description": "The Docker Compose location." }, "docker_compose_custom_start_command": { "type": "string", "description": "The Docker Compose custom start command." }, "docker_compose_custom_build_command": { "type": "string", "description": "The Docker Compose custom build command." }, "docker_compose_domains": { "type": "array", "description": "Array of URLs to be applied to containers of a dockercompose application.", "items": { "properties": { "name": { "type": "string", "description": "The service name as defined in docker-compose." }, "domain": { "type": "string", "description": "Comma-separated list of URLs (e.g. \"http:\/\/app.coolify.io,https:\/\/app2.coolify.io\")" } }, "type": "object" } }, "watch_paths": { "type": "string", "description": "The watch paths." }, "use_build_server": { "type": "boolean", "nullable": true, "description": "Use build server." }, "is_http_basic_auth_enabled": { "type": "boolean", "description": "HTTP Basic Authentication enabled." }, "http_basic_auth_username": { "type": "string", "nullable": true, "description": "Username for HTTP Basic Authentication" }, "http_basic_auth_password": { "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "force_domain_override": { "type": "boolean", "description": "Force domain usage even if conflicts are detected. Default is false." }, "autogenerate_domain": { "type": "boolean", "default": true, "description": "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." }, "is_container_label_escape_enabled": { "type": "boolean", "default": true, "description": "Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off." } }, "type": "object" } } } }, "responses": { "201": { "description": "Application created successfully.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/dockerfile": { "post": { "tags": [ "Applications" ], "summary": "Create (Dockerfile without git)", "description": "Create new application based on a simple Dockerfile (without git).", "operationId": "create-dockerfile-application", "requestBody": { "description": "Application object that needs to be created.", "required": true, "content": { "application\/json": { "schema": { "required": [ "project_uuid", "server_uuid", "environment_name", "environment_uuid", "dockerfile" ], "properties": { "project_uuid": { "type": "string", "description": "The project UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "environment_name": { "type": "string", "description": "The environment name. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "The environment UUID. You need to provide at least one of environment_name or environment_uuid." }, "dockerfile": { "type": "string", "description": "The Dockerfile content." }, "build_pack": { "type": "string", "enum": [ "nixpacks", "static", "dockerfile", "dockercompose" ], "description": "The build pack type." }, "ports_exposes": { "type": "string", "description": "The ports to expose." }, "destination_uuid": { "type": "string", "description": "The destination UUID." }, "name": { "type": "string", "description": "The application name." }, "description": { "type": "string", "description": "The application description." }, "domains": { "type": "string", "description": "The application URLs in a comma-separated list." }, "docker_registry_image_name": { "type": "string", "description": "The docker registry image name." }, "docker_registry_image_tag": { "type": "string", "description": "The docker registry image tag." }, "ports_mappings": { "type": "string", "description": "The ports mappings." }, "base_directory": { "type": "string", "description": "The base directory for all commands." }, "health_check_enabled": { "type": "boolean", "description": "Health check enabled." }, "health_check_path": { "type": "string", "description": "Health check path." }, "health_check_port": { "type": "string", "nullable": true, "description": "Health check port." }, "health_check_host": { "type": "string", "nullable": true, "description": "Health check host." }, "health_check_method": { "type": "string", "description": "Health check method." }, "health_check_return_code": { "type": "integer", "description": "Health check return code." }, "health_check_scheme": { "type": "string", "description": "Health check scheme." }, "health_check_response_text": { "type": "string", "nullable": true, "description": "Health check response text." }, "health_check_interval": { "type": "integer", "description": "Health check interval in seconds." }, "health_check_timeout": { "type": "integer", "description": "Health check timeout in seconds." }, "health_check_retries": { "type": "integer", "description": "Health check retries count." }, "health_check_start_period": { "type": "integer", "description": "Health check start period in seconds." }, "limits_memory": { "type": "string", "description": "Memory limit." }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit." }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness." }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation." }, "limits_cpus": { "type": "string", "description": "CPU limit." }, "limits_cpuset": { "type": "string", "nullable": true, "description": "CPU set." }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares." }, "custom_labels": { "type": "string", "description": "Custom labels." }, "custom_docker_run_options": { "type": "string", "description": "Custom docker run options." }, "post_deployment_command": { "type": "string", "description": "Post deployment command." }, "post_deployment_command_container": { "type": "string", "description": "Post deployment command container." }, "pre_deployment_command": { "type": "string", "description": "Pre deployment command." }, "pre_deployment_command_container": { "type": "string", "description": "Pre deployment command container." }, "manual_webhook_secret_github": { "type": "string", "description": "Manual webhook secret for Github." }, "manual_webhook_secret_gitlab": { "type": "string", "description": "Manual webhook secret for Gitlab." }, "manual_webhook_secret_bitbucket": { "type": "string", "description": "Manual webhook secret for Bitbucket." }, "manual_webhook_secret_gitea": { "type": "string", "description": "Manual webhook secret for Gitea." }, "redirect": { "type": "string", "nullable": true, "description": "How to set redirect with Traefik \/ Caddy. www<->non-www.", "enum": [ "www", "non-www", "both" ] }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the application should be deployed instantly." }, "is_force_https_enabled": { "type": "boolean", "description": "The flag to indicate if HTTPS is forced. Defaults to true." }, "use_build_server": { "type": "boolean", "nullable": true, "description": "Use build server." }, "is_http_basic_auth_enabled": { "type": "boolean", "description": "HTTP Basic Authentication enabled." }, "http_basic_auth_username": { "type": "string", "nullable": true, "description": "Username for HTTP Basic Authentication" }, "http_basic_auth_password": { "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "force_domain_override": { "type": "boolean", "description": "Force domain usage even if conflicts are detected. Default is false." }, "autogenerate_domain": { "type": "boolean", "default": true, "description": "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." }, "is_container_label_escape_enabled": { "type": "boolean", "default": true, "description": "Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off." } }, "type": "object" } } } }, "responses": { "201": { "description": "Application created successfully.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/dockerimage": { "post": { "tags": [ "Applications" ], "summary": "Create (Docker Image without git)", "description": "Create new application based on a prebuilt docker image (without git).", "operationId": "create-dockerimage-application", "requestBody": { "description": "Application object that needs to be created.", "required": true, "content": { "application\/json": { "schema": { "required": [ "project_uuid", "server_uuid", "environment_name", "environment_uuid", "docker_registry_image_name", "ports_exposes" ], "properties": { "project_uuid": { "type": "string", "description": "The project UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "environment_name": { "type": "string", "description": "The environment name. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "The environment UUID. You need to provide at least one of environment_name or environment_uuid." }, "docker_registry_image_name": { "type": "string", "description": "The docker registry image name." }, "docker_registry_image_tag": { "type": "string", "description": "The docker registry image tag." }, "ports_exposes": { "type": "string", "description": "The ports to expose." }, "destination_uuid": { "type": "string", "description": "The destination UUID." }, "name": { "type": "string", "description": "The application name." }, "description": { "type": "string", "description": "The application description." }, "domains": { "type": "string", "description": "The application URLs in a comma-separated list." }, "ports_mappings": { "type": "string", "description": "The ports mappings." }, "health_check_enabled": { "type": "boolean", "description": "Health check enabled." }, "health_check_path": { "type": "string", "description": "Health check path." }, "health_check_port": { "type": "string", "nullable": true, "description": "Health check port." }, "health_check_host": { "type": "string", "nullable": true, "description": "Health check host." }, "health_check_method": { "type": "string", "description": "Health check method." }, "health_check_return_code": { "type": "integer", "description": "Health check return code." }, "health_check_scheme": { "type": "string", "description": "Health check scheme." }, "health_check_response_text": { "type": "string", "nullable": true, "description": "Health check response text." }, "health_check_interval": { "type": "integer", "description": "Health check interval in seconds." }, "health_check_timeout": { "type": "integer", "description": "Health check timeout in seconds." }, "health_check_retries": { "type": "integer", "description": "Health check retries count." }, "health_check_start_period": { "type": "integer", "description": "Health check start period in seconds." }, "limits_memory": { "type": "string", "description": "Memory limit." }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit." }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness." }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation." }, "limits_cpus": { "type": "string", "description": "CPU limit." }, "limits_cpuset": { "type": "string", "nullable": true, "description": "CPU set." }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares." }, "custom_labels": { "type": "string", "description": "Custom labels." }, "custom_docker_run_options": { "type": "string", "description": "Custom docker run options." }, "post_deployment_command": { "type": "string", "description": "Post deployment command." }, "post_deployment_command_container": { "type": "string", "description": "Post deployment command container." }, "pre_deployment_command": { "type": "string", "description": "Pre deployment command." }, "pre_deployment_command_container": { "type": "string", "description": "Pre deployment command container." }, "manual_webhook_secret_github": { "type": "string", "description": "Manual webhook secret for Github." }, "manual_webhook_secret_gitlab": { "type": "string", "description": "Manual webhook secret for Gitlab." }, "manual_webhook_secret_bitbucket": { "type": "string", "description": "Manual webhook secret for Bitbucket." }, "manual_webhook_secret_gitea": { "type": "string", "description": "Manual webhook secret for Gitea." }, "redirect": { "type": "string", "nullable": true, "description": "How to set redirect with Traefik \/ Caddy. www<->non-www.", "enum": [ "www", "non-www", "both" ] }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the application should be deployed instantly." }, "is_force_https_enabled": { "type": "boolean", "description": "The flag to indicate if HTTPS is forced. Defaults to true." }, "use_build_server": { "type": "boolean", "nullable": true, "description": "Use build server." }, "is_http_basic_auth_enabled": { "type": "boolean", "description": "HTTP Basic Authentication enabled." }, "http_basic_auth_username": { "type": "string", "nullable": true, "description": "Username for HTTP Basic Authentication" }, "http_basic_auth_password": { "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "force_domain_override": { "type": "boolean", "description": "Force domain usage even if conflicts are detected. Default is false." }, "autogenerate_domain": { "type": "boolean", "default": true, "description": "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." }, "is_container_label_escape_enabled": { "type": "boolean", "default": true, "description": "Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off." } }, "type": "object" } } } }, "responses": { "201": { "description": "Application created successfully.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/dockercompose": { "post": { "tags": [ "Applications" ], "summary": "Create (Docker Compose)", "description": "Deprecated: Use POST \/api\/v1\/services instead.", "operationId": "create-dockercompose-application", "requestBody": { "description": "Application object that needs to be created.", "required": true, "content": { "application\/json": { "schema": { "required": [ "project_uuid", "server_uuid", "environment_name", "environment_uuid", "docker_compose_raw" ], "properties": { "project_uuid": { "type": "string", "description": "The project UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "environment_name": { "type": "string", "description": "The environment name. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "The environment UUID. You need to provide at least one of environment_name or environment_uuid." }, "docker_compose_raw": { "type": "string", "description": "The Docker Compose raw content." }, "destination_uuid": { "type": "string", "description": "The destination UUID if the server has more than one destinations." }, "name": { "type": "string", "description": "The application name." }, "description": { "type": "string", "description": "The application description." }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the application should be deployed instantly." }, "use_build_server": { "type": "boolean", "nullable": true, "description": "Use build server." }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "force_domain_override": { "type": "boolean", "description": "Force domain usage even if conflicts are detected. Default is false." }, "is_container_label_escape_enabled": { "type": "boolean", "default": true, "description": "Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off." } }, "type": "object" } } } }, "responses": { "201": { "description": "Application created successfully.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } } }, "deprecated": true, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}": { "get": { "tags": [ "Applications" ], "summary": "Get", "description": "Get application by UUID.", "operationId": "get-application-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get application by UUID.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Application" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Applications" ], "summary": "Delete", "description": "Delete application by UUID.", "operationId": "delete-application-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "delete_configurations", "in": "query", "description": "Delete configurations.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "delete_volumes", "in": "query", "description": "Delete volumes.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "docker_cleanup", "in": "query", "description": "Run docker cleanup.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "delete_connected_networks", "in": "query", "description": "Delete connected networks.", "required": false, "schema": { "type": "boolean", "default": true } } ], "responses": { "200": { "description": "Application deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Application deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Applications" ], "summary": "Update", "description": "Update application by UUID.", "operationId": "update-application-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Application updated.", "required": true, "content": { "application\/json": { "schema": { "properties": { "project_uuid": { "type": "string", "description": "The project UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "environment_name": { "type": "string", "description": "The environment name." }, "github_app_uuid": { "type": "string", "description": "The Github App UUID." }, "git_repository": { "type": "string", "description": "The git repository URL." }, "git_branch": { "type": "string", "description": "The git branch." }, "ports_exposes": { "type": "string", "description": "The ports to expose." }, "destination_uuid": { "type": "string", "description": "The destination UUID." }, "build_pack": { "type": "string", "enum": [ "nixpacks", "static", "dockerfile", "dockercompose" ], "description": "The build pack type." }, "name": { "type": "string", "description": "The application name." }, "description": { "type": "string", "description": "The application description." }, "domains": { "type": "string", "description": "The application URLs in a comma-separated list." }, "git_commit_sha": { "type": "string", "description": "The git commit SHA." }, "docker_registry_image_name": { "type": "string", "description": "The docker registry image name." }, "docker_registry_image_tag": { "type": "string", "description": "The docker registry image tag." }, "is_static": { "type": "boolean", "description": "The flag to indicate if the application is static." }, "is_spa": { "type": "boolean", "description": "The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true." }, "is_auto_deploy_enabled": { "type": "boolean", "description": "The flag to indicate if auto-deploy is enabled on git push. Defaults to true." }, "is_force_https_enabled": { "type": "boolean", "description": "The flag to indicate if HTTPS is forced. Defaults to true." }, "install_command": { "type": "string", "description": "The install command." }, "build_command": { "type": "string", "description": "The build command." }, "start_command": { "type": "string", "description": "The start command." }, "ports_mappings": { "type": "string", "description": "The ports mappings." }, "base_directory": { "type": "string", "description": "The base directory for all commands." }, "publish_directory": { "type": "string", "description": "The publish directory." }, "health_check_enabled": { "type": "boolean", "description": "Health check enabled." }, "health_check_path": { "type": "string", "description": "Health check path." }, "health_check_port": { "type": "string", "nullable": true, "description": "Health check port." }, "health_check_host": { "type": "string", "nullable": true, "description": "Health check host." }, "health_check_method": { "type": "string", "description": "Health check method." }, "health_check_return_code": { "type": "integer", "description": "Health check return code." }, "health_check_scheme": { "type": "string", "description": "Health check scheme." }, "health_check_response_text": { "type": "string", "nullable": true, "description": "Health check response text." }, "health_check_interval": { "type": "integer", "description": "Health check interval in seconds." }, "health_check_timeout": { "type": "integer", "description": "Health check timeout in seconds." }, "health_check_retries": { "type": "integer", "description": "Health check retries count." }, "health_check_start_period": { "type": "integer", "description": "Health check start period in seconds." }, "limits_memory": { "type": "string", "description": "Memory limit." }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit." }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness." }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation." }, "limits_cpus": { "type": "string", "description": "CPU limit." }, "limits_cpuset": { "type": "string", "nullable": true, "description": "CPU set." }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares." }, "custom_labels": { "type": "string", "description": "Custom labels." }, "custom_docker_run_options": { "type": "string", "description": "Custom docker run options." }, "post_deployment_command": { "type": "string", "description": "Post deployment command." }, "post_deployment_command_container": { "type": "string", "description": "Post deployment command container." }, "pre_deployment_command": { "type": "string", "description": "Pre deployment command." }, "pre_deployment_command_container": { "type": "string", "description": "Pre deployment command container." }, "manual_webhook_secret_github": { "type": "string", "description": "Manual webhook secret for Github." }, "manual_webhook_secret_gitlab": { "type": "string", "description": "Manual webhook secret for Gitlab." }, "manual_webhook_secret_bitbucket": { "type": "string", "description": "Manual webhook secret for Bitbucket." }, "manual_webhook_secret_gitea": { "type": "string", "description": "Manual webhook secret for Gitea." }, "redirect": { "type": "string", "nullable": true, "description": "How to set redirect with Traefik \/ Caddy. www<->non-www.", "enum": [ "www", "non-www", "both" ] }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the application should be deployed instantly." }, "dockerfile": { "type": "string", "description": "The Dockerfile content." }, "dockerfile_location": { "type": "string", "description": "The Dockerfile location in the repository." }, "docker_compose_location": { "type": "string", "description": "The Docker Compose location." }, "docker_compose_custom_start_command": { "type": "string", "description": "The Docker Compose custom start command." }, "docker_compose_custom_build_command": { "type": "string", "description": "The Docker Compose custom build command." }, "docker_compose_domains": { "type": "array", "description": "Array of URLs to be applied to containers of a dockercompose application.", "items": { "properties": { "name": { "type": "string", "description": "The service name as defined in docker-compose." }, "domain": { "type": "string", "description": "Comma-separated list of URLs (e.g. \"http:\/\/app.coolify.io,https:\/\/app2.coolify.io\")" } }, "type": "object" } }, "watch_paths": { "type": "string", "description": "The watch paths." }, "use_build_server": { "type": "boolean", "nullable": true, "description": "Use build server." }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "force_domain_override": { "type": "boolean", "description": "Force domain usage even if conflicts are detected. Default is false." }, "is_container_label_escape_enabled": { "type": "boolean", "default": true, "description": "Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off." } }, "type": "object" } } } }, "responses": { "200": { "description": "Application updated.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/logs": { "get": { "tags": [ "Applications" ], "summary": "Get application logs.", "description": "Get application logs by UUID.", "operationId": "get-application-logs-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "lines", "in": "query", "description": "Number of lines to show from the end of the logs.", "required": false, "schema": { "type": "integer", "format": "int32", "default": 100 } } ], "responses": { "200": { "description": "Get application logs by UUID.", "content": { "application\/json": { "schema": { "properties": { "logs": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/envs": { "get": { "tags": [ "Applications" ], "summary": "List Envs", "description": "List all envs by application UUID.", "operationId": "list-envs-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "All environment variables by application UUID.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/EnvironmentVariable" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Applications" ], "summary": "Create Env", "description": "Create env by application UUID.", "operationId": "create-env-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Env created.", "required": true, "content": { "application\/json": { "schema": { "properties": { "key": { "type": "string", "description": "The key of the environment variable." }, "value": { "type": "string", "description": "The value of the environment variable." }, "is_preview": { "type": "boolean", "description": "The flag to indicate if the environment variable is used in preview deployments." }, "is_literal": { "type": "boolean", "description": "The flag to indicate if the environment variable is a literal, nothing espaced." }, "is_multiline": { "type": "boolean", "description": "The flag to indicate if the environment variable is multiline." }, "is_shown_once": { "type": "boolean", "description": "The flag to indicate if the environment variable's value is shown on the UI." } }, "type": "object" } } } }, "responses": { "201": { "description": "Environment variable created.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "nc0k04gk8g0cgsk440g0koko" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Applications" ], "summary": "Update Env", "description": "Update env by application UUID.", "operationId": "update-env-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Env updated.", "required": true, "content": { "application\/json": { "schema": { "required": [ "key", "value" ], "properties": { "key": { "type": "string", "description": "The key of the environment variable." }, "value": { "type": "string", "description": "The value of the environment variable." }, "is_preview": { "type": "boolean", "description": "The flag to indicate if the environment variable is used in preview deployments." }, "is_literal": { "type": "boolean", "description": "The flag to indicate if the environment variable is a literal, nothing espaced." }, "is_multiline": { "type": "boolean", "description": "The flag to indicate if the environment variable is multiline." }, "is_shown_once": { "type": "boolean", "description": "The flag to indicate if the environment variable's value is shown on the UI." } }, "type": "object" } } } }, "responses": { "201": { "description": "Environment variable updated.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/EnvironmentVariable" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/envs\/bulk": { "patch": { "tags": [ "Applications" ], "summary": "Update Envs (Bulk)", "description": "Update multiple envs by application UUID.", "operationId": "update-envs-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Bulk envs updated.", "required": true, "content": { "application\/json": { "schema": { "required": [ "data" ], "properties": { "data": { "type": "array", "items": { "properties": { "key": { "type": "string", "description": "The key of the environment variable." }, "value": { "type": "string", "description": "The value of the environment variable." }, "is_preview": { "type": "boolean", "description": "The flag to indicate if the environment variable is used in preview deployments." }, "is_literal": { "type": "boolean", "description": "The flag to indicate if the environment variable is a literal, nothing espaced." }, "is_multiline": { "type": "boolean", "description": "The flag to indicate if the environment variable is multiline." }, "is_shown_once": { "type": "boolean", "description": "The flag to indicate if the environment variable's value is shown on the UI." } }, "type": "object" } } }, "type": "object" } } } }, "responses": { "201": { "description": "Environment variables updated.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/EnvironmentVariable" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/envs\/{env_uuid}": { "delete": { "tags": [ "Applications" ], "summary": "Delete Env", "description": "Delete env by UUID.", "operationId": "delete-env-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "env_uuid", "in": "path", "description": "UUID of the environment variable.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Environment variable deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Environment variable deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/start": { "get": { "tags": [ "Applications" ], "summary": "Start", "description": "Start application. `Post` request is also accepted.", "operationId": "start-application-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "force", "in": "query", "description": "Force rebuild.", "schema": { "type": "boolean", "default": false } }, { "name": "instant_deploy", "in": "query", "description": "Instant deploy (skip queuing).", "schema": { "type": "boolean", "default": false } } ], "responses": { "200": { "description": "Start application.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Deployment request queued.", "description": "Message." }, "deployment_uuid": { "type": "string", "example": "doogksw", "description": "UUID of the deployment." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/stop": { "get": { "tags": [ "Applications" ], "summary": "Stop", "description": "Stop application. `Post` request is also accepted.", "operationId": "stop-application-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "docker_cleanup", "in": "query", "description": "Perform docker cleanup (prune networks, volumes, etc.).", "schema": { "type": "boolean", "default": true } } ], "responses": { "200": { "description": "Stop application.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Application stopping request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/restart": { "get": { "tags": [ "Applications" ], "summary": "Restart", "description": "Restart application. `Post` request is also accepted.", "operationId": "restart-application-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Restart application.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Restart request queued." }, "deployment_uuid": { "type": "string", "example": "doogksw", "description": "UUID of the deployment." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/cloud-tokens": { "get": { "tags": [ "Cloud Tokens" ], "summary": "List Cloud Provider Tokens", "description": "List all cloud provider tokens for the authenticated team.", "operationId": "list-cloud-tokens", "responses": { "200": { "description": "Get all cloud provider tokens.", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "uuid": { "type": "string" }, "name": { "type": "string" }, "provider": { "type": "string", "enum": [ "hetzner", "digitalocean" ] }, "team_id": { "type": "integer" }, "servers_count": { "type": "integer" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Cloud Tokens" ], "summary": "Create Cloud Provider Token", "description": "Create a new cloud provider token. The token will be validated before being stored.", "operationId": "create-cloud-token", "requestBody": { "description": "Cloud provider token details", "required": true, "content": { "application\/json": { "schema": { "required": [ "provider", "token", "name" ], "properties": { "provider": { "type": "string", "enum": [ "hetzner", "digitalocean" ], "example": "hetzner", "description": "The cloud provider." }, "token": { "type": "string", "example": "your-api-token-here", "description": "The API token for the cloud provider." }, "name": { "type": "string", "example": "My Hetzner Token", "description": "A friendly name for the token." } }, "type": "object" } } } }, "responses": { "201": { "description": "Cloud provider token created.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "og888os", "description": "The UUID of the token." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/cloud-tokens\/{uuid}": { "get": { "tags": [ "Cloud Tokens" ], "summary": "Get Cloud Provider Token", "description": "Get cloud provider token by UUID.", "operationId": "get-cloud-token-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Token UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get cloud provider token by UUID", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" }, "name": { "type": "string" }, "provider": { "type": "string" }, "team_id": { "type": "integer" }, "servers_count": { "type": "integer" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Cloud Tokens" ], "summary": "Delete Cloud Provider Token", "description": "Delete cloud provider token by UUID. Cannot delete if token is used by any servers.", "operationId": "delete-cloud-token-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the cloud provider token.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Cloud provider token deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Cloud provider token deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Cloud Tokens" ], "summary": "Update Cloud Provider Token", "description": "Update cloud provider token name.", "operationId": "update-cloud-token-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Token UUID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Cloud provider token updated.", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The friendly name for the token." } }, "type": "object" } } } }, "responses": { "200": { "description": "Cloud provider token updated.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/cloud-tokens\/{uuid}\/validate": { "post": { "tags": [ "Cloud Tokens" ], "summary": "Validate Cloud Provider Token", "description": "Validate a cloud provider token against the provider API.", "operationId": "validate-cloud-token-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Token UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Token validation result.", "content": { "application\/json": { "schema": { "properties": { "valid": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "Token is valid." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases": { "get": { "tags": [ "Databases" ], "summary": "List", "description": "List all databases.", "operationId": "list-databases", "responses": { "200": { "description": "Get all databases", "content": { "application\/json": { "schema": { "type": "string" }, "example": "Content is very complex. Will be implemented later." } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}\/backups": { "get": { "tags": [ "Databases" ], "summary": "Get", "description": "Get backups details by database UUID.", "operationId": "get-database-backups-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all backups for a database", "content": { "application\/json": { "schema": { "type": "string" }, "example": "Content is very complex. Will be implemented later." } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Databases" ], "summary": "Create Backup", "description": "Create a new scheduled backup configuration for a database", "operationId": "create-database-backup", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Backup configuration data", "required": true, "content": { "application\/json": { "schema": { "required": [ "frequency" ], "properties": { "frequency": { "type": "string", "description": "Backup frequency (cron expression or: every_minute, hourly, daily, weekly, monthly, yearly)" }, "enabled": { "type": "boolean", "description": "Whether the backup is enabled", "default": true }, "save_s3": { "type": "boolean", "description": "Whether to save backups to S3", "default": false }, "s3_storage_uuid": { "type": "string", "description": "S3 storage UUID (required if save_s3 is true)" }, "databases_to_backup": { "type": "string", "description": "Comma separated list of databases to backup" }, "dump_all": { "type": "boolean", "description": "Whether to dump all databases", "default": false }, "backup_now": { "type": "boolean", "description": "Whether to trigger backup immediately after creation" }, "database_backup_retention_amount_locally": { "type": "integer", "description": "Number of backups to retain locally" }, "database_backup_retention_days_locally": { "type": "integer", "description": "Number of days to retain backups locally" }, "database_backup_retention_max_storage_locally": { "type": "integer", "description": "Max storage (MB) for local backups" }, "database_backup_retention_amount_s3": { "type": "integer", "description": "Number of backups to retain in S3" }, "database_backup_retention_days_s3": { "type": "integer", "description": "Number of days to retain backups in S3" }, "database_backup_retention_max_storage_s3": { "type": "integer", "description": "Max storage (MB) for S3 backups" } }, "type": "object" } } } }, "responses": { "201": { "description": "Backup configuration created successfully", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "format": "uuid", "example": "550e8400-e29b-41d4-a716-446655440000" }, "message": { "type": "string", "example": "Backup configuration created successfully." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}": { "get": { "tags": [ "Databases" ], "summary": "Get", "description": "Get database by UUID.", "operationId": "get-database-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all databases", "content": { "application\/json": { "schema": { "type": "string" }, "example": "Content is very complex. Will be implemented later." } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Databases" ], "summary": "Delete", "description": "Delete database by UUID.", "operationId": "delete-database-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } }, { "name": "delete_configurations", "in": "query", "description": "Delete configurations.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "delete_volumes", "in": "query", "description": "Delete volumes.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "docker_cleanup", "in": "query", "description": "Run docker cleanup.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "delete_connected_networks", "in": "query", "description": "Delete connected networks.", "required": false, "schema": { "type": "boolean", "default": true } } ], "responses": { "200": { "description": "Database deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Database deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Databases" ], "summary": "Update", "description": "Update database by UUID.", "operationId": "update-database-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "postgres_user": { "type": "string", "description": "PostgreSQL user" }, "postgres_password": { "type": "string", "description": "PostgreSQL password" }, "postgres_db": { "type": "string", "description": "PostgreSQL database" }, "postgres_initdb_args": { "type": "string", "description": "PostgreSQL initdb args" }, "postgres_host_auth_method": { "type": "string", "description": "PostgreSQL host auth method" }, "postgres_conf": { "type": "string", "description": "PostgreSQL conf" }, "clickhouse_admin_user": { "type": "string", "description": "Clickhouse admin user" }, "clickhouse_admin_password": { "type": "string", "description": "Clickhouse admin password" }, "dragonfly_password": { "type": "string", "description": "DragonFly password" }, "redis_password": { "type": "string", "description": "Redis password" }, "redis_conf": { "type": "string", "description": "Redis conf" }, "keydb_password": { "type": "string", "description": "KeyDB password" }, "keydb_conf": { "type": "string", "description": "KeyDB conf" }, "mariadb_conf": { "type": "string", "description": "MariaDB conf" }, "mariadb_root_password": { "type": "string", "description": "MariaDB root password" }, "mariadb_user": { "type": "string", "description": "MariaDB user" }, "mariadb_password": { "type": "string", "description": "MariaDB password" }, "mariadb_database": { "type": "string", "description": "MariaDB database" }, "mongo_conf": { "type": "string", "description": "Mongo conf" }, "mongo_initdb_root_username": { "type": "string", "description": "Mongo initdb root username" }, "mongo_initdb_root_password": { "type": "string", "description": "Mongo initdb root password" }, "mongo_initdb_database": { "type": "string", "description": "Mongo initdb init database" }, "mysql_root_password": { "type": "string", "description": "MySQL root password" }, "mysql_password": { "type": "string", "description": "MySQL password" }, "mysql_user": { "type": "string", "description": "MySQL user" }, "mysql_database": { "type": "string", "description": "MySQL database" }, "mysql_conf": { "type": "string", "description": "MySQL conf" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}\/backups\/{scheduled_backup_uuid}": { "delete": { "tags": [ "Databases" ], "summary": "Delete backup configuration", "description": "Deletes a backup configuration and all its executions.", "operationId": "delete-backup-configuration-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database", "required": true, "schema": { "type": "string" } }, { "name": "scheduled_backup_uuid", "in": "path", "description": "UUID of the backup configuration to delete", "required": true, "schema": { "type": "string" } }, { "name": "delete_s3", "in": "query", "description": "Whether to delete all backup files from S3", "required": false, "schema": { "type": "boolean", "default": false } } ], "responses": { "200": { "description": "Backup configuration deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Backup configuration and all executions deleted." } }, "type": "object" } } } }, "404": { "description": "Backup configuration not found.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Backup configuration not found." } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Databases" ], "summary": "Update", "description": "Update a specific backup configuration for a given database, identified by its UUID and the backup ID", "operationId": "update-database-backup", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } }, { "name": "scheduled_backup_uuid", "in": "path", "description": "UUID of the backup configuration.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Database backup configuration data", "required": true, "content": { "application\/json": { "schema": { "properties": { "save_s3": { "type": "boolean", "description": "Whether data is saved in s3 or not" }, "s3_storage_uuid": { "type": "string", "description": "S3 storage UUID" }, "backup_now": { "type": "boolean", "description": "Whether to take a backup now or not" }, "enabled": { "type": "boolean", "description": "Whether the backup is enabled or not" }, "databases_to_backup": { "type": "string", "description": "Comma separated list of databases to backup" }, "dump_all": { "type": "boolean", "description": "Whether all databases are dumped or not" }, "frequency": { "type": "string", "description": "Frequency of the backup" }, "database_backup_retention_amount_locally": { "type": "integer", "description": "Retention amount of the backup locally" }, "database_backup_retention_days_locally": { "type": "integer", "description": "Retention days of the backup locally" }, "database_backup_retention_max_storage_locally": { "type": "integer", "description": "Max storage of the backup locally" }, "database_backup_retention_amount_s3": { "type": "integer", "description": "Retention amount of the backup in s3" }, "database_backup_retention_days_s3": { "type": "integer", "description": "Retention days of the backup in s3" }, "database_backup_retention_max_storage_s3": { "type": "integer", "description": "Max storage of the backup in S3" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database backup configuration updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/postgresql": { "post": { "tags": [ "Databases" ], "summary": "Create (PostgreSQL)", "description": "Create a new PostgreSQL database.", "operationId": "create-database-postgresql", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "postgres_user": { "type": "string", "description": "PostgreSQL user" }, "postgres_password": { "type": "string", "description": "PostgreSQL password" }, "postgres_db": { "type": "string", "description": "PostgreSQL database" }, "postgres_initdb_args": { "type": "string", "description": "PostgreSQL initdb args" }, "postgres_host_auth_method": { "type": "string", "description": "PostgreSQL host auth method" }, "postgres_conf": { "type": "string", "description": "PostgreSQL conf" }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/clickhouse": { "post": { "tags": [ "Databases" ], "summary": "Create (Clickhouse)", "description": "Create a new Clickhouse database.", "operationId": "create-database-clickhouse", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "clickhouse_admin_user": { "type": "string", "description": "Clickhouse admin user" }, "clickhouse_admin_password": { "type": "string", "description": "Clickhouse admin password" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/dragonfly": { "post": { "tags": [ "Databases" ], "summary": "Create (DragonFly)", "description": "Create a new DragonFly database.", "operationId": "create-database-dragonfly", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "dragonfly_password": { "type": "string", "description": "DragonFly password" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/redis": { "post": { "tags": [ "Databases" ], "summary": "Create (Redis)", "description": "Create a new Redis database.", "operationId": "create-database-redis", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "redis_password": { "type": "string", "description": "Redis password" }, "redis_conf": { "type": "string", "description": "Redis conf" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/keydb": { "post": { "tags": [ "Databases" ], "summary": "Create (KeyDB)", "description": "Create a new KeyDB database.", "operationId": "create-database-keydb", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "keydb_password": { "type": "string", "description": "KeyDB password" }, "keydb_conf": { "type": "string", "description": "KeyDB conf" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/mariadb": { "post": { "tags": [ "Databases" ], "summary": "Create (MariaDB)", "description": "Create a new MariaDB database.", "operationId": "create-database-mariadb", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "mariadb_conf": { "type": "string", "description": "MariaDB conf" }, "mariadb_root_password": { "type": "string", "description": "MariaDB root password" }, "mariadb_user": { "type": "string", "description": "MariaDB user" }, "mariadb_password": { "type": "string", "description": "MariaDB password" }, "mariadb_database": { "type": "string", "description": "MariaDB database" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/mysql": { "post": { "tags": [ "Databases" ], "summary": "Create (MySQL)", "description": "Create a new MySQL database.", "operationId": "create-database-mysql", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "mysql_root_password": { "type": "string", "description": "MySQL root password" }, "mysql_password": { "type": "string", "description": "MySQL password" }, "mysql_user": { "type": "string", "description": "MySQL user" }, "mysql_database": { "type": "string", "description": "MySQL database" }, "mysql_conf": { "type": "string", "description": "MySQL conf" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/mongodb": { "post": { "tags": [ "Databases" ], "summary": "Create (MongoDB)", "description": "Create a new MongoDB database.", "operationId": "create-database-mongodb", "requestBody": { "description": "Database data", "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "server_uuid": { "type": "string", "description": "UUID of the server" }, "project_uuid": { "type": "string", "description": "UUID of the project" }, "environment_name": { "type": "string", "description": "Name of the environment. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "UUID of the environment. You need to provide at least one of environment_name or environment_uuid." }, "destination_uuid": { "type": "string", "description": "UUID of the destination if the server has multiple destinations" }, "mongo_conf": { "type": "string", "description": "MongoDB conf" }, "mongo_initdb_root_username": { "type": "string", "description": "MongoDB initdb root username" }, "name": { "type": "string", "description": "Name of the database" }, "description": { "type": "string", "description": "Description of the database" }, "image": { "type": "string", "description": "Docker Image of the database" }, "is_public": { "type": "boolean", "description": "Is the database public?" }, "public_port": { "type": "integer", "description": "Public port of the database" }, "limits_memory": { "type": "string", "description": "Memory limit of the database" }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit of the database" }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness of the database" }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation of the database" }, "limits_cpus": { "type": "string", "description": "CPU limit of the database" }, "limits_cpuset": { "type": "string", "description": "CPU set of the database" }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares of the database" }, "instant_deploy": { "type": "boolean", "description": "Instant deploy the database" } }, "type": "object" } } } }, "responses": { "200": { "description": "Database updated" }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}\/backups\/{scheduled_backup_uuid}\/executions\/{execution_uuid}": { "delete": { "tags": [ "Databases" ], "summary": "Delete backup execution", "description": "Deletes a specific backup execution.", "operationId": "delete-backup-execution-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database", "required": true, "schema": { "type": "string" } }, { "name": "scheduled_backup_uuid", "in": "path", "description": "UUID of the backup configuration", "required": true, "schema": { "type": "string" } }, { "name": "execution_uuid", "in": "path", "description": "UUID of the backup execution to delete", "required": true, "schema": { "type": "string" } }, { "name": "delete_s3", "in": "query", "description": "Whether to delete the backup from S3", "required": false, "schema": { "type": "boolean", "default": false } } ], "responses": { "200": { "description": "Backup execution deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Backup execution deleted." } }, "type": "object" } } } }, "404": { "description": "Backup execution not found.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Backup execution not found." } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}\/backups\/{scheduled_backup_uuid}\/executions": { "get": { "tags": [ "Databases" ], "summary": "List backup executions", "description": "Get all executions for a specific backup configuration.", "operationId": "list-backup-executions", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database", "required": true, "schema": { "type": "string" } }, { "name": "scheduled_backup_uuid", "in": "path", "description": "UUID of the backup configuration", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of backup executions", "content": { "application\/json": { "schema": { "properties": { "executions": { "type": "array", "items": { "properties": { "uuid": { "type": "string" }, "filename": { "type": "string" }, "size": { "type": "integer" }, "created_at": { "type": "string" }, "message": { "type": "string" }, "status": { "type": "string" } }, "type": "object" } } }, "type": "object" } } } }, "404": { "description": "Backup configuration not found." } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}\/start": { "get": { "tags": [ "Databases" ], "summary": "Start", "description": "Start database. `Post` request is also accepted.", "operationId": "start-database-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Start database.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Database starting request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}\/stop": { "get": { "tags": [ "Databases" ], "summary": "Stop", "description": "Stop database. `Post` request is also accepted.", "operationId": "stop-database-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } }, { "name": "docker_cleanup", "in": "query", "description": "Perform docker cleanup (prune networks, volumes, etc.).", "schema": { "type": "boolean", "default": true } } ], "responses": { "200": { "description": "Stop database.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Database stopping request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/databases\/{uuid}\/restart": { "get": { "tags": [ "Databases" ], "summary": "Restart", "description": "Restart database. `Post` request is also accepted.", "operationId": "restart-database-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the database.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Restart database.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Database restaring request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/deployments": { "get": { "tags": [ "Deployments" ], "summary": "List", "description": "List currently running deployments", "operationId": "list-deployments", "responses": { "200": { "description": "Get all currently running deployments.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/ApplicationDeploymentQueue" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/deployments\/{uuid}": { "get": { "tags": [ "Deployments" ], "summary": "Get", "description": "Get deployment by UUID.", "operationId": "get-deployment-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Deployment UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get deployment by UUID.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/ApplicationDeploymentQueue" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/deployments\/{uuid}\/cancel": { "post": { "tags": [ "Deployments" ], "summary": "Cancel", "description": "Cancel a deployment by UUID.", "operationId": "cancel-deployment-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Deployment UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Deployment cancelled successfully.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Deployment cancelled successfully." }, "deployment_uuid": { "type": "string", "example": "cm37r6cqj000008jm0veg5tkm" }, "status": { "type": "string", "example": "cancelled-by-user" } }, "type": "object" } } } }, "400": { "description": "Deployment cannot be cancelled (already finished\/failed\/cancelled).", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Deployment cannot be cancelled. Current status: finished" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "403": { "description": "User doesn't have permission to cancel this deployment.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "You do not have permission to cancel this deployment." } }, "type": "object" } } } }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/deploy": { "get": { "tags": [ "Deployments" ], "summary": "Deploy", "description": "Deploy by tag or uuid. `Post` request also accepted with `uuid` and `tag` json body.", "operationId": "deploy-by-tag-or-uuid", "parameters": [ { "name": "tag", "in": "query", "description": "Tag name(s). Comma separated list is also accepted.", "schema": { "type": "string" } }, { "name": "uuid", "in": "query", "description": "Resource UUID(s). Comma separated list is also accepted.", "schema": { "type": "string" } }, { "name": "force", "in": "query", "description": "Force rebuild (without cache)", "schema": { "type": "boolean" } }, { "name": "pr", "in": "query", "description": "Pull Request Id for deploying specific PR builds. Cannot be used with tag parameter.", "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Get deployment(s) UUID's", "content": { "application\/json": { "schema": { "properties": { "deployments": { "type": "array", "items": { "properties": { "message": { "type": "string" }, "resource_uuid": { "type": "string" }, "deployment_uuid": { "type": "string" } }, "type": "object" } } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/deployments\/applications\/{uuid}": { "get": { "tags": [ "Deployments" ], "summary": "List application deployments", "description": "List application deployments by using the app uuid", "operationId": "list-deployments-by-app-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "skip", "in": "query", "description": "Number of records to skip.", "required": false, "schema": { "type": "integer", "default": 0, "minimum": 0 } }, { "name": "take", "in": "query", "description": "Number of records to take.", "required": false, "schema": { "type": "integer", "default": 10, "minimum": 1 } } ], "responses": { "200": { "description": "List application deployments by using the app uuid.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/Application" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/github-apps": { "get": { "tags": [ "GitHub Apps" ], "summary": "List", "description": "List all GitHub apps.", "operationId": "list-github-apps", "responses": { "200": { "description": "List of GitHub apps.", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "id": { "type": "integer" }, "uuid": { "type": "string" }, "name": { "type": "string" }, "organization": { "type": "string", "nullable": true }, "api_url": { "type": "string" }, "html_url": { "type": "string" }, "custom_user": { "type": "string" }, "custom_port": { "type": "integer" }, "app_id": { "type": "integer" }, "installation_id": { "type": "integer" }, "client_id": { "type": "string" }, "private_key_id": { "type": "integer" }, "is_system_wide": { "type": "boolean" }, "is_public": { "type": "boolean" }, "team_id": { "type": "integer" }, "type": { "type": "string" } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "GitHub Apps" ], "summary": "Create GitHub App", "description": "Create a new GitHub app.", "operationId": "create-github-app", "requestBody": { "description": "GitHub app creation payload.", "required": true, "content": { "application\/json": { "schema": { "required": [ "name", "api_url", "html_url", "app_id", "installation_id", "client_id", "client_secret", "private_key_uuid" ], "properties": { "name": { "type": "string", "description": "Name of the GitHub app." }, "organization": { "type": "string", "nullable": true, "description": "Organization to associate the app with." }, "api_url": { "type": "string", "description": "API URL for the GitHub app (e.g., https:\/\/api.github.com)." }, "html_url": { "type": "string", "description": "HTML URL for the GitHub app (e.g., https:\/\/github.com)." }, "custom_user": { "type": "string", "description": "Custom user for SSH access (default: git)." }, "custom_port": { "type": "integer", "description": "Custom port for SSH access (default: 22)." }, "app_id": { "type": "integer", "description": "GitHub App ID from GitHub." }, "installation_id": { "type": "integer", "description": "GitHub Installation ID." }, "client_id": { "type": "string", "description": "GitHub OAuth App Client ID." }, "client_secret": { "type": "string", "description": "GitHub OAuth App Client Secret." }, "webhook_secret": { "type": "string", "description": "Webhook secret for GitHub webhooks." }, "private_key_uuid": { "type": "string", "description": "UUID of an existing private key for GitHub App authentication." }, "is_system_wide": { "type": "boolean", "description": "Is this app system-wide (cloud only)." } }, "type": "object" } } } }, "responses": { "201": { "description": "GitHub app created successfully.", "content": { "application\/json": { "schema": { "properties": { "id": { "type": "integer" }, "uuid": { "type": "string" }, "name": { "type": "string" }, "organization": { "type": "string", "nullable": true }, "api_url": { "type": "string" }, "html_url": { "type": "string" }, "custom_user": { "type": "string" }, "custom_port": { "type": "integer" }, "app_id": { "type": "integer" }, "installation_id": { "type": "integer" }, "client_id": { "type": "string" }, "private_key_id": { "type": "integer" }, "is_system_wide": { "type": "boolean" }, "team_id": { "type": "integer" } }, "type": "object" } } } }, "400": { "$ref": "#\/components\/responses\/400" }, "401": { "$ref": "#\/components\/responses\/401" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/github-apps\/{github_app_id}\/repositories": { "get": { "tags": [ "GitHub Apps" ], "summary": "Load Repositories for a GitHub App", "description": "Fetch repositories from GitHub for a given GitHub app.", "operationId": "load-repositories", "parameters": [ { "name": "github_app_id", "in": "path", "description": "GitHub App ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Repositories loaded successfully.", "content": { "application\/json": { "schema": { "properties": { "repositories": { "type": "array", "items": { "type": "object" } } }, "type": "object" } } } }, "400": { "$ref": "#\/components\/responses\/400" }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/github-apps\/{github_app_id}\/repositories\/{owner}\/{repo}\/branches": { "get": { "tags": [ "GitHub Apps" ], "summary": "Load Branches for a GitHub Repository", "description": "Fetch branches from GitHub for a given repository.", "operationId": "load-branches", "parameters": [ { "name": "github_app_id", "in": "path", "description": "GitHub App ID", "required": true, "schema": { "type": "integer" } }, { "name": "owner", "in": "path", "description": "Repository owner", "required": true, "schema": { "type": "string" } }, { "name": "repo", "in": "path", "description": "Repository name", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Branches loaded successfully.", "content": { "application\/json": { "schema": { "properties": { "branches": { "type": "array", "items": { "type": "object" } } }, "type": "object" } } } }, "400": { "$ref": "#\/components\/responses\/400" }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/github-apps\/{github_app_id}": { "delete": { "tags": [ "GitHub Apps" ], "summary": "Delete GitHub App", "description": "Delete a GitHub app if it's not being used by any applications.", "operationId": "deleteGithubApp", "parameters": [ { "name": "github_app_id", "in": "path", "description": "GitHub App ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "GitHub app deleted successfully", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "GitHub app deleted successfully" } }, "type": "object" } } } }, "401": { "description": "Unauthorized" }, "404": { "description": "GitHub app not found" }, "409": { "description": "Conflict - GitHub app is in use", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "This GitHub app is being used by 5 application(s). Please delete all applications first." } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "GitHub Apps" ], "summary": "Update GitHub App", "description": "Update an existing GitHub app.", "operationId": "updateGithubApp", "parameters": [ { "name": "github_app_id", "in": "path", "description": "GitHub App ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "GitHub App name" }, "organization": { "type": "string", "nullable": true, "description": "GitHub organization" }, "api_url": { "type": "string", "description": "GitHub API URL" }, "html_url": { "type": "string", "description": "GitHub HTML URL" }, "custom_user": { "type": "string", "description": "Custom user for SSH" }, "custom_port": { "type": "integer", "description": "Custom port for SSH" }, "app_id": { "type": "integer", "description": "GitHub App ID" }, "installation_id": { "type": "integer", "description": "GitHub Installation ID" }, "client_id": { "type": "string", "description": "GitHub Client ID" }, "client_secret": { "type": "string", "description": "GitHub Client Secret" }, "webhook_secret": { "type": "string", "description": "GitHub Webhook Secret" }, "private_key_uuid": { "type": "string", "description": "Private key UUID" }, "is_system_wide": { "type": "boolean", "description": "Is system wide (non-cloud instances only)" } }, "type": "object" } } } }, "responses": { "200": { "description": "GitHub app updated successfully", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "GitHub app updated successfully" }, "data": { "type": "object", "description": "Updated GitHub app data" } }, "type": "object" } } } }, "401": { "description": "Unauthorized" }, "404": { "description": "GitHub app not found" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/hetzner\/locations": { "get": { "tags": [ "Hetzner" ], "summary": "Get Hetzner Locations", "description": "Get all available Hetzner datacenter locations.", "operationId": "get-hetzner-locations", "parameters": [ { "name": "cloud_provider_token_uuid", "in": "query", "description": "Cloud provider token UUID. Required if cloud_provider_token_id is not provided.", "required": false, "schema": { "type": "string" } }, { "name": "cloud_provider_token_id", "in": "query", "description": "Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.", "required": false, "deprecated": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of Hetzner locations.", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "description": { "type": "string" }, "country": { "type": "string" }, "city": { "type": "string" }, "latitude": { "type": "number" }, "longitude": { "type": "number" } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/hetzner\/server-types": { "get": { "tags": [ "Hetzner" ], "summary": "Get Hetzner Server Types", "description": "Get all available Hetzner server types (instance sizes).", "operationId": "get-hetzner-server-types", "parameters": [ { "name": "cloud_provider_token_uuid", "in": "query", "description": "Cloud provider token UUID. Required if cloud_provider_token_id is not provided.", "required": false, "schema": { "type": "string" } }, { "name": "cloud_provider_token_id", "in": "query", "description": "Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.", "required": false, "deprecated": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of Hetzner server types.", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "description": { "type": "string" }, "cores": { "type": "integer" }, "memory": { "type": "number" }, "disk": { "type": "integer" }, "prices": { "type": "array", "items": { "type": "object", "properties": { "location": { "type": "string", "description": "Datacenter location name" }, "price_hourly": { "type": "object", "properties": { "net": { "type": "string" }, "gross": { "type": "string" } } }, "price_monthly": { "type": "object", "properties": { "net": { "type": "string" }, "gross": { "type": "string" } } } } } } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/hetzner\/images": { "get": { "tags": [ "Hetzner" ], "summary": "Get Hetzner Images", "description": "Get all available Hetzner system images (operating systems).", "operationId": "get-hetzner-images", "parameters": [ { "name": "cloud_provider_token_uuid", "in": "query", "description": "Cloud provider token UUID. Required if cloud_provider_token_id is not provided.", "required": false, "schema": { "type": "string" } }, { "name": "cloud_provider_token_id", "in": "query", "description": "Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.", "required": false, "deprecated": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of Hetzner images.", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "description": { "type": "string" }, "type": { "type": "string" }, "os_flavor": { "type": "string" }, "os_version": { "type": "string" }, "architecture": { "type": "string" } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/hetzner\/ssh-keys": { "get": { "tags": [ "Hetzner" ], "summary": "Get Hetzner SSH Keys", "description": "Get all SSH keys stored in the Hetzner account.", "operationId": "get-hetzner-ssh-keys", "parameters": [ { "name": "cloud_provider_token_uuid", "in": "query", "description": "Cloud provider token UUID. Required if cloud_provider_token_id is not provided.", "required": false, "schema": { "type": "string" } }, { "name": "cloud_provider_token_id", "in": "query", "description": "Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.", "required": false, "deprecated": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of Hetzner SSH keys.", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "fingerprint": { "type": "string" }, "public_key": { "type": "string" } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/servers\/hetzner": { "post": { "tags": [ "Hetzner" ], "summary": "Create Hetzner Server", "description": "Create a new server on Hetzner and register it in Coolify.", "operationId": "create-hetzner-server", "requestBody": { "description": "Hetzner server creation parameters", "required": true, "content": { "application\/json": { "schema": { "required": [ "location", "server_type", "image", "private_key_uuid" ], "properties": { "cloud_provider_token_uuid": { "type": "string", "example": "abc123", "description": "Cloud provider token UUID. Required if cloud_provider_token_id is not provided." }, "cloud_provider_token_id": { "type": "string", "example": "abc123", "description": "Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.", "deprecated": true }, "location": { "type": "string", "example": "nbg1", "description": "Hetzner location name" }, "server_type": { "type": "string", "example": "cx11", "description": "Hetzner server type name" }, "image": { "type": "integer", "example": 15512617, "description": "Hetzner image ID" }, "name": { "type": "string", "example": "my-server", "description": "Server name (auto-generated if not provided)" }, "private_key_uuid": { "type": "string", "example": "xyz789", "description": "Private key UUID" }, "enable_ipv4": { "type": "boolean", "example": true, "description": "Enable IPv4 (default: true)" }, "enable_ipv6": { "type": "boolean", "example": true, "description": "Enable IPv6 (default: true)" }, "hetzner_ssh_key_ids": { "type": "array", "items": { "type": "integer" }, "description": "Additional Hetzner SSH key IDs" }, "cloud_init_script": { "type": "string", "description": "Cloud-init YAML script (optional)" }, "instant_validate": { "type": "boolean", "example": false, "description": "Validate server immediately after creation" } }, "type": "object" } } } }, "responses": { "201": { "description": "Hetzner server created.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "og888os", "description": "The UUID of the server." }, "hetzner_server_id": { "type": "integer", "description": "The Hetzner server ID." }, "ip": { "type": "string", "description": "The server IP address." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" }, "429": { "$ref": "#\/components\/responses\/429" } }, "security": [ { "bearerAuth": [] } ] } }, "\/version": { "get": { "summary": "Version", "description": "Get Coolify version.", "operationId": "version", "responses": { "200": { "description": "Returns the version of the application", "content": { "text\/html": { "schema": { "type": "string" }, "example": "v4.0.0" } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/enable": { "get": { "summary": "Enable API", "description": "Enable API (only with root permissions).", "operationId": "enable-api", "responses": { "200": { "description": "Enable API.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "API enabled." } }, "type": "object" } } } }, "403": { "description": "You are not allowed to enable the API.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "You are not allowed to enable the API." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/disable": { "get": { "summary": "Disable API", "description": "Disable API (only with root permissions).", "operationId": "disable-api", "responses": { "200": { "description": "Disable API.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "API disabled." } }, "type": "object" } } } }, "403": { "description": "You are not allowed to disable the API.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "You are not allowed to disable the API." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/health": { "get": { "summary": "Healthcheck", "description": "Healthcheck endpoint.", "operationId": "healthcheck", "responses": { "200": { "description": "Healthcheck endpoint.", "content": { "text\/html": { "schema": { "type": "string" }, "example": "OK" } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } } } }, "\/projects": { "get": { "tags": [ "Projects" ], "summary": "List", "description": "List projects.", "operationId": "list-projects", "responses": { "200": { "description": "Get all projects.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/Project" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Projects" ], "summary": "Create", "description": "Create Project.", "operationId": "create-project", "requestBody": { "description": "Project created.", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The name of the project." }, "description": { "type": "string", "description": "The description of the project." } }, "type": "object" } } } }, "responses": { "201": { "description": "Project created.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "og888os", "description": "The UUID of the project." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/projects\/{uuid}": { "get": { "tags": [ "Projects" ], "summary": "Get", "description": "Get project by UUID.", "operationId": "get-project-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Project UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Project details", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Project" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "description": "Project not found." } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Projects" ], "summary": "Delete", "description": "Delete project by UUID.", "operationId": "delete-project-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Project deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Project deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Projects" ], "summary": "Update", "description": "Update Project.", "operationId": "update-project-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the project.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Project updated.", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The name of the project." }, "description": { "type": "string", "description": "The description of the project." } }, "type": "object" } } } }, "responses": { "201": { "description": "Project updated.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "og888os" }, "name": { "type": "string", "example": "Project Name" }, "description": { "type": "string", "example": "Project Description" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/projects\/{uuid}\/{environment_name_or_uuid}": { "get": { "tags": [ "Projects" ], "summary": "Environment", "description": "Get environment by name or UUID.", "operationId": "get-environment-by-name-or-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Project UUID", "required": true, "schema": { "type": "string" } }, { "name": "environment_name_or_uuid", "in": "path", "description": "Environment name or UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Environment details", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Environment" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/projects\/{uuid}\/environments": { "get": { "tags": [ "Projects" ], "summary": "List Environments", "description": "List all environments in a project.", "operationId": "get-environments", "parameters": [ { "name": "uuid", "in": "path", "description": "Project UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of environments", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/Environment" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "description": "Project not found." }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Projects" ], "summary": "Create Environment", "description": "Create environment in project.", "operationId": "create-environment", "parameters": [ { "name": "uuid", "in": "path", "description": "Project UUID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Environment created.", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The name of the environment." } }, "type": "object" } } } }, "responses": { "201": { "description": "Environment created.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "env123", "description": "The UUID of the environment." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "description": "Project not found." }, "409": { "description": "Environment with this name already exists." }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/projects\/{uuid}\/environments\/{environment_name_or_uuid}": { "delete": { "tags": [ "Projects" ], "summary": "Delete Environment", "description": "Delete environment by name or UUID. Environment must be empty.", "operationId": "delete-environment", "parameters": [ { "name": "uuid", "in": "path", "description": "Project UUID", "required": true, "schema": { "type": "string" } }, { "name": "environment_name_or_uuid", "in": "path", "description": "Environment name or UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Environment deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Environment deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "description": "Environment has resources, so it cannot be deleted." }, "404": { "description": "Project or environment not found." }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/resources": { "get": { "tags": [ "Resources" ], "summary": "List", "description": "Get all resources.", "operationId": "list-resources", "responses": { "200": { "description": "Get all resources", "content": { "application\/json": { "schema": { "type": "string" }, "example": "Content is very complex. Will be implemented later." } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/scheduled-tasks": { "get": { "tags": [ "Scheduled Tasks" ], "summary": "List Tasks", "description": "List all scheduled tasks for an application.", "operationId": "list-scheduled-tasks-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all scheduled tasks for an application.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/ScheduledTask" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Scheduled Tasks" ], "summary": "Create Task", "description": "Create a new scheduled task for an application.", "operationId": "create-scheduled-task-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Scheduled task data", "required": true, "content": { "application\/json": { "schema": { "required": [ "name", "command", "frequency" ], "properties": { "name": { "type": "string", "description": "The name of the scheduled task." }, "command": { "type": "string", "description": "The command to execute." }, "frequency": { "type": "string", "description": "The frequency of the scheduled task." }, "container": { "type": "string", "nullable": true, "description": "The container where the command should be executed." }, "timeout": { "type": "integer", "description": "The timeout of the scheduled task in seconds.", "default": 300 }, "enabled": { "type": "boolean", "description": "The flag to indicate if the scheduled task is enabled.", "default": true } }, "type": "object" } } } }, "responses": { "201": { "description": "Scheduled task created.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/ScheduledTask" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/scheduled-tasks\/{task_uuid}": { "delete": { "tags": [ "Scheduled Tasks" ], "summary": "Delete Task", "description": "Delete a scheduled task for an application.", "operationId": "delete-scheduled-task-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "task_uuid", "in": "path", "description": "UUID of the scheduled task.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Scheduled task deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Scheduled task deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Scheduled Tasks" ], "summary": "Update Task", "description": "Update a scheduled task for an application.", "operationId": "update-scheduled-task-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "task_uuid", "in": "path", "description": "UUID of the scheduled task.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Scheduled task data", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The name of the scheduled task." }, "command": { "type": "string", "description": "The command to execute." }, "frequency": { "type": "string", "description": "The frequency of the scheduled task." }, "container": { "type": "string", "nullable": true, "description": "The container where the command should be executed." }, "timeout": { "type": "integer", "description": "The timeout of the scheduled task in seconds.", "default": 300 }, "enabled": { "type": "boolean", "description": "The flag to indicate if the scheduled task is enabled.", "default": true } }, "type": "object" } } } }, "responses": { "200": { "description": "Scheduled task updated.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/ScheduledTask" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/applications\/{uuid}\/scheduled-tasks\/{task_uuid}\/executions": { "get": { "tags": [ "Scheduled Tasks" ], "summary": "List Executions", "description": "List all executions for a scheduled task on an application.", "operationId": "list-scheduled-task-executions-by-application-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the application.", "required": true, "schema": { "type": "string" } }, { "name": "task_uuid", "in": "path", "description": "UUID of the scheduled task.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all executions for a scheduled task.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/ScheduledTaskExecution" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/scheduled-tasks": { "get": { "tags": [ "Scheduled Tasks" ], "summary": "List Tasks", "description": "List all scheduled tasks for a service.", "operationId": "list-scheduled-tasks-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all scheduled tasks for a service.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/ScheduledTask" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Scheduled Tasks" ], "summary": "Create Task", "description": "Create a new scheduled task for a service.", "operationId": "create-scheduled-task-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Scheduled task data", "required": true, "content": { "application\/json": { "schema": { "required": [ "name", "command", "frequency" ], "properties": { "name": { "type": "string", "description": "The name of the scheduled task." }, "command": { "type": "string", "description": "The command to execute." }, "frequency": { "type": "string", "description": "The frequency of the scheduled task." }, "container": { "type": "string", "nullable": true, "description": "The container where the command should be executed." }, "timeout": { "type": "integer", "description": "The timeout of the scheduled task in seconds.", "default": 300 }, "enabled": { "type": "boolean", "description": "The flag to indicate if the scheduled task is enabled.", "default": true } }, "type": "object" } } } }, "responses": { "201": { "description": "Scheduled task created.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/ScheduledTask" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/scheduled-tasks\/{task_uuid}": { "delete": { "tags": [ "Scheduled Tasks" ], "summary": "Delete Task", "description": "Delete a scheduled task for a service.", "operationId": "delete-scheduled-task-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } }, { "name": "task_uuid", "in": "path", "description": "UUID of the scheduled task.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Scheduled task deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Scheduled task deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Scheduled Tasks" ], "summary": "Update Task", "description": "Update a scheduled task for a service.", "operationId": "update-scheduled-task-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } }, { "name": "task_uuid", "in": "path", "description": "UUID of the scheduled task.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Scheduled task data", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The name of the scheduled task." }, "command": { "type": "string", "description": "The command to execute." }, "frequency": { "type": "string", "description": "The frequency of the scheduled task." }, "container": { "type": "string", "nullable": true, "description": "The container where the command should be executed." }, "timeout": { "type": "integer", "description": "The timeout of the scheduled task in seconds.", "default": 300 }, "enabled": { "type": "boolean", "description": "The flag to indicate if the scheduled task is enabled.", "default": true } }, "type": "object" } } } }, "responses": { "200": { "description": "Scheduled task updated.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/ScheduledTask" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/scheduled-tasks\/{task_uuid}\/executions": { "get": { "tags": [ "Scheduled Tasks" ], "summary": "List Executions", "description": "List all executions for a scheduled task on a service.", "operationId": "list-scheduled-task-executions-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } }, { "name": "task_uuid", "in": "path", "description": "UUID of the scheduled task.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all executions for a scheduled task.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/ScheduledTaskExecution" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/security\/keys": { "get": { "tags": [ "Private Keys" ], "summary": "List", "description": "List all private keys.", "operationId": "list-private-keys", "responses": { "200": { "description": "Get all private keys.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/PrivateKey" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Private Keys" ], "summary": "Create", "description": "Create a new private key.", "operationId": "create-private-key", "requestBody": { "required": true, "content": { "application\/json": { "schema": { "required": [ "private_key" ], "properties": { "name": { "type": "string" }, "description": { "type": "string" }, "private_key": { "type": "string" } }, "type": "object", "additionalProperties": false } } } }, "responses": { "201": { "description": "The created private key's UUID.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Private Keys" ], "summary": "Update", "description": "Update a private key.", "operationId": "update-private-key", "requestBody": { "required": true, "content": { "application\/json": { "schema": { "required": [ "private_key" ], "properties": { "name": { "type": "string" }, "description": { "type": "string" }, "private_key": { "type": "string" } }, "type": "object", "additionalProperties": false } } } }, "responses": { "201": { "description": "The updated private key's UUID.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/security\/keys\/{uuid}": { "get": { "tags": [ "Private Keys" ], "summary": "Get", "description": "Get key by UUID.", "operationId": "get-private-key-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Private Key UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get all private keys.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/PrivateKey" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "description": "Private Key not found." } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Private Keys" ], "summary": "Delete", "description": "Delete a private key.", "operationId": "delete-private-key-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Private Key UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Private Key deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Private Key deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "description": "Private Key not found." }, "422": { "description": "Private Key is in use and cannot be deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Private Key is in use and cannot be deleted." } }, "type": "object" } } } } }, "security": [ { "bearerAuth": [] } ] } }, "\/servers": { "get": { "tags": [ "Servers" ], "summary": "List", "description": "List all servers.", "operationId": "list-servers", "responses": { "200": { "description": "Get all servers.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/Server" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Servers" ], "summary": "Create", "description": "Create Server.", "operationId": "create-server", "requestBody": { "description": "Server created.", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "example": "My Server", "description": "The name of the server." }, "description": { "type": "string", "example": "My Server Description", "description": "The description of the server." }, "ip": { "type": "string", "example": "127.0.0.1", "description": "The IP of the server." }, "port": { "type": "integer", "example": 22, "description": "The port of the server." }, "user": { "type": "string", "example": "root", "description": "The user of the server." }, "private_key_uuid": { "type": "string", "example": "og888os", "description": "The UUID of the private key." }, "is_build_server": { "type": "boolean", "example": false, "description": "Is build server." }, "instant_validate": { "type": "boolean", "example": false, "description": "Instant validate." }, "proxy_type": { "type": "string", "enum": [ "traefik", "caddy", "none" ], "example": "traefik", "description": "The proxy type." } }, "type": "object" } } } }, "responses": { "201": { "description": "Server created.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "og888os", "description": "The UUID of the server." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/servers\/{uuid}": { "get": { "tags": [ "Servers" ], "summary": "Get", "description": "Get server by UUID.", "operationId": "get-server-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Server's UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get server by UUID", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Server" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Servers" ], "summary": "Delete", "description": "Delete server by UUID.", "operationId": "delete-server-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the server.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Server deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Server deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Servers" ], "summary": "Update", "description": "Update Server.", "operationId": "update-server-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Server UUID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Server updated.", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The name of the server." }, "description": { "type": "string", "description": "The description of the server." }, "ip": { "type": "string", "description": "The IP of the server." }, "port": { "type": "integer", "description": "The port of the server." }, "user": { "type": "string", "description": "The user of the server." }, "private_key_uuid": { "type": "string", "description": "The UUID of the private key." }, "is_build_server": { "type": "boolean", "description": "Is build server." }, "instant_validate": { "type": "boolean", "description": "Instant validate." }, "proxy_type": { "type": "string", "enum": [ "traefik", "caddy", "none" ], "description": "The proxy type." } }, "type": "object" } } } }, "responses": { "201": { "description": "Server updated.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Server" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/servers\/{uuid}\/resources": { "get": { "tags": [ "Servers" ], "summary": "Resources", "description": "Get resources by server.", "operationId": "get-resources-by-server-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Server's UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get resources by server", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "id": { "type": "integer" }, "uuid": { "type": "string" }, "name": { "type": "string" }, "type": { "type": "string" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "status": { "type": "string" } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/servers\/{uuid}\/domains": { "get": { "tags": [ "Servers" ], "summary": "Domains", "description": "Get domains by server.", "operationId": "get-domains-by-server-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Server's UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get domains by server", "content": { "application\/json": { "schema": { "type": "array", "items": { "properties": { "ip": { "type": "string" }, "domains": { "type": "array", "items": { "type": "string" } } }, "type": "object" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/servers\/{uuid}\/validate": { "get": { "tags": [ "Servers" ], "summary": "Validate", "description": "Validate server by UUID.", "operationId": "validate-server-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Server UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "201": { "description": "Server validation started.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Validation started." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services": { "get": { "tags": [ "Services" ], "summary": "List", "description": "List all services.", "operationId": "list-services", "responses": { "200": { "description": "Get all services", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/Service" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Services" ], "summary": "Create service", "description": "Create a one-click \/ custom service", "operationId": "create-service", "requestBody": { "required": true, "content": { "application\/json": { "schema": { "required": [ "server_uuid", "project_uuid", "environment_name", "environment_uuid" ], "properties": { "type": { "description": "The one-click service type (e.g. \"actualbudget\", \"calibre-web\", \"gitea-with-mysql\" ...)", "type": "string" }, "name": { "type": "string", "maxLength": 255, "description": "Name of the service." }, "description": { "type": "string", "nullable": true, "description": "Description of the service." }, "project_uuid": { "type": "string", "description": "Project UUID." }, "environment_name": { "type": "string", "description": "Environment name. You need to provide at least one of environment_name or environment_uuid." }, "environment_uuid": { "type": "string", "description": "Environment UUID. You need to provide at least one of environment_name or environment_uuid." }, "server_uuid": { "type": "string", "description": "Server UUID." }, "destination_uuid": { "type": "string", "description": "Destination UUID. Required if server has multiple destinations." }, "instant_deploy": { "type": "boolean", "default": false, "description": "Start the service immediately after creation." }, "docker_compose_raw": { "type": "string", "description": "The base64 encoded Docker Compose content." }, "urls": { "type": "array", "description": "Array of URLs to be applied to containers of a service.", "items": { "properties": { "name": { "type": "string", "description": "The service name as defined in docker-compose." }, "url": { "type": "string", "description": "Comma-separated list of URLs (e.g. \"http:\/\/app.coolify.io,https:\/\/app2.coolify.io\")." } }, "type": "object" } }, "force_domain_override": { "type": "boolean", "default": false, "description": "Force domain override even if conflicts are detected." } }, "type": "object" } } } }, "responses": { "201": { "description": "Service created successfully.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "description": "Service UUID." }, "domains": { "type": "array", "items": { "type": "string" }, "description": "Service domains." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}": { "get": { "tags": [ "Services" ], "summary": "Get", "description": "Get service by UUID.", "operationId": "get-service-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Service UUID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Get a service by UUID.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Service" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Services" ], "summary": "Delete", "description": "Delete service by UUID.", "operationId": "delete-service-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "Service UUID", "required": true, "schema": { "type": "string" } }, { "name": "delete_configurations", "in": "query", "description": "Delete configurations.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "delete_volumes", "in": "query", "description": "Delete volumes.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "docker_cleanup", "in": "query", "description": "Run docker cleanup.", "required": false, "schema": { "type": "boolean", "default": true } }, { "name": "delete_connected_networks", "in": "query", "description": "Delete connected networks.", "required": false, "schema": { "type": "boolean", "default": true } } ], "responses": { "200": { "description": "Delete a service by UUID", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Service deletion request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Services" ], "summary": "Update", "description": "Update service by UUID.", "operationId": "update-service-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Service updated.", "required": true, "content": { "application\/json": { "schema": { "properties": { "name": { "type": "string", "description": "The service name." }, "description": { "type": "string", "description": "The service description." }, "project_uuid": { "type": "string", "description": "The project UUID." }, "environment_name": { "type": "string", "description": "The environment name." }, "environment_uuid": { "type": "string", "description": "The environment UUID." }, "server_uuid": { "type": "string", "description": "The server UUID." }, "destination_uuid": { "type": "string", "description": "The destination UUID." }, "instant_deploy": { "type": "boolean", "description": "The flag to indicate if the service should be deployed instantly." }, "connect_to_docker_network": { "type": "boolean", "default": false, "description": "Connect the service to the predefined docker network." }, "docker_compose_raw": { "type": "string", "description": "The base64 encoded Docker Compose content." }, "urls": { "type": "array", "description": "Array of URLs to be applied to containers of a service.", "items": { "properties": { "name": { "type": "string", "description": "The service name as defined in docker-compose." }, "url": { "type": "string", "description": "Comma-separated list of URLs (e.g. \"http:\/\/app.coolify.io,https:\/\/app2.coolify.io\")." } }, "type": "object" } }, "force_domain_override": { "type": "boolean", "default": false, "description": "Force domain override even if conflicts are detected." } }, "type": "object" } } } }, "responses": { "200": { "description": "Service updated.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "description": "Service UUID." }, "domains": { "type": "array", "items": { "type": "string" }, "description": "Service domains." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "409": { "description": "Domain conflicts detected.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Domain conflicts detected. Use force_domain_override=true to proceed." }, "warning": { "type": "string", "example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior." }, "conflicts": { "type": "array", "items": { "properties": { "domain": { "type": "string", "example": "example.com" }, "resource_name": { "type": "string", "example": "My Application" }, "resource_uuid": { "type": "string", "nullable": true, "example": "abc123-def456" }, "resource_type": { "type": "string", "enum": [ "application", "service", "instance" ], "example": "application" }, "message": { "type": "string", "example": "Domain example.com is already in use by application 'My Application'" } }, "type": "object" } } }, "type": "object" } } } }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/envs": { "get": { "tags": [ "Services" ], "summary": "List Envs", "description": "List all envs by service UUID.", "operationId": "list-envs-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "All environment variables by service UUID.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/EnvironmentVariable" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Services" ], "summary": "Create Env", "description": "Create env by service UUID.", "operationId": "create-env-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Env created.", "required": true, "content": { "application\/json": { "schema": { "properties": { "key": { "type": "string", "description": "The key of the environment variable." }, "value": { "type": "string", "description": "The value of the environment variable." }, "is_preview": { "type": "boolean", "description": "The flag to indicate if the environment variable is used in preview deployments." }, "is_literal": { "type": "boolean", "description": "The flag to indicate if the environment variable is a literal, nothing espaced." }, "is_multiline": { "type": "boolean", "description": "The flag to indicate if the environment variable is multiline." }, "is_shown_once": { "type": "boolean", "description": "The flag to indicate if the environment variable's value is shown on the UI." } }, "type": "object" } } } }, "responses": { "201": { "description": "Environment variable created.", "content": { "application\/json": { "schema": { "properties": { "uuid": { "type": "string", "example": "nc0k04gk8g0cgsk440g0koko" } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] }, "patch": { "tags": [ "Services" ], "summary": "Update Env", "description": "Update env by service UUID.", "operationId": "update-env-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Env updated.", "required": true, "content": { "application\/json": { "schema": { "required": [ "key", "value" ], "properties": { "key": { "type": "string", "description": "The key of the environment variable." }, "value": { "type": "string", "description": "The value of the environment variable." }, "is_preview": { "type": "boolean", "description": "The flag to indicate if the environment variable is used in preview deployments." }, "is_literal": { "type": "boolean", "description": "The flag to indicate if the environment variable is a literal, nothing espaced." }, "is_multiline": { "type": "boolean", "description": "The flag to indicate if the environment variable is multiline." }, "is_shown_once": { "type": "boolean", "description": "The flag to indicate if the environment variable's value is shown on the UI." } }, "type": "object" } } } }, "responses": { "201": { "description": "Environment variable updated.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/EnvironmentVariable" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/envs\/bulk": { "patch": { "tags": [ "Services" ], "summary": "Update Envs (Bulk)", "description": "Update multiple envs by service UUID.", "operationId": "update-envs-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "requestBody": { "description": "Bulk envs updated.", "required": true, "content": { "application\/json": { "schema": { "required": [ "data" ], "properties": { "data": { "type": "array", "items": { "properties": { "key": { "type": "string", "description": "The key of the environment variable." }, "value": { "type": "string", "description": "The value of the environment variable." }, "is_preview": { "type": "boolean", "description": "The flag to indicate if the environment variable is used in preview deployments." }, "is_literal": { "type": "boolean", "description": "The flag to indicate if the environment variable is a literal, nothing espaced." }, "is_multiline": { "type": "boolean", "description": "The flag to indicate if the environment variable is multiline." }, "is_shown_once": { "type": "boolean", "description": "The flag to indicate if the environment variable's value is shown on the UI." } }, "type": "object" } } }, "type": "object" } } } }, "responses": { "201": { "description": "Environment variables updated.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/EnvironmentVariable" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" }, "422": { "$ref": "#\/components\/responses\/422" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/envs\/{env_uuid}": { "delete": { "tags": [ "Services" ], "summary": "Delete Env", "description": "Delete env by UUID.", "operationId": "delete-env-by-service-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } }, { "name": "env_uuid", "in": "path", "description": "UUID of the environment variable.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Environment variable deleted.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Environment variable deleted." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/start": { "get": { "tags": [ "Services" ], "summary": "Start", "description": "Start service. `Post` request is also accepted.", "operationId": "start-service-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Start service.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Service starting request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/stop": { "get": { "tags": [ "Services" ], "summary": "Stop", "description": "Stop service. `Post` request is also accepted.", "operationId": "stop-service-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } }, { "name": "docker_cleanup", "in": "query", "description": "Perform docker cleanup (prune networks, volumes, etc.).", "schema": { "type": "boolean", "default": true } } ], "responses": { "200": { "description": "Stop service.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Service stopping request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/services\/{uuid}\/restart": { "get": { "tags": [ "Services" ], "summary": "Restart", "description": "Restart service. `Post` request is also accepted.", "operationId": "restart-service-by-uuid", "parameters": [ { "name": "uuid", "in": "path", "description": "UUID of the service.", "required": true, "schema": { "type": "string" } }, { "name": "latest", "in": "query", "description": "Pull latest images.", "schema": { "type": "boolean", "default": false } } ], "responses": { "200": { "description": "Restart service.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Service restaring request queued." } }, "type": "object" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/teams": { "get": { "tags": [ "Teams" ], "summary": "List", "description": "Get all teams.", "operationId": "list-teams", "responses": { "200": { "description": "List of teams.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/Team" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/teams\/{id}": { "get": { "tags": [ "Teams" ], "summary": "Get", "description": "Get team by TeamId.", "operationId": "get-team-by-id", "parameters": [ { "name": "id", "in": "path", "description": "Team ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "List of teams.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Team" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/teams\/{id}\/members": { "get": { "tags": [ "Teams" ], "summary": "Members", "description": "Get members by TeamId.", "operationId": "get-members-by-team-id", "parameters": [ { "name": "id", "in": "path", "description": "Team ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "List of members.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/User" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" }, "404": { "$ref": "#\/components\/responses\/404" } }, "security": [ { "bearerAuth": [] } ] } }, "\/teams\/current": { "get": { "tags": [ "Teams" ], "summary": "Authenticated Team", "description": "Get currently authenticated team.", "operationId": "get-current-team", "responses": { "200": { "description": "Current Team.", "content": { "application\/json": { "schema": { "$ref": "#\/components\/schemas\/Team" } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } }, "\/teams\/current\/members": { "get": { "tags": [ "Teams" ], "summary": "Authenticated Team Members", "description": "Get currently authenticated team members.", "operationId": "get-current-team-members", "responses": { "200": { "description": "Currently authenticated team members.", "content": { "application\/json": { "schema": { "type": "array", "items": { "$ref": "#\/components\/schemas\/User" } } } } }, "401": { "$ref": "#\/components\/responses\/401" }, "400": { "$ref": "#\/components\/responses\/400" } }, "security": [ { "bearerAuth": [] } ] } } }, "components": { "schemas": { "Application": { "description": "Application model", "properties": { "id": { "type": "integer", "description": "The application identifier in the database." }, "description": { "type": "string", "nullable": true, "description": "The application description." }, "repository_project_id": { "type": "integer", "nullable": true, "description": "The repository project identifier." }, "uuid": { "type": "string", "description": "The application UUID." }, "name": { "type": "string", "description": "The application name." }, "fqdn": { "type": "string", "nullable": true, "description": "The application domains." }, "config_hash": { "type": "string", "description": "Configuration hash." }, "git_repository": { "type": "string", "description": "Git repository URL." }, "git_branch": { "type": "string", "description": "Git branch." }, "git_commit_sha": { "type": "string", "description": "Git commit SHA." }, "git_full_url": { "type": "string", "nullable": true, "description": "Git full URL." }, "docker_registry_image_name": { "type": "string", "nullable": true, "description": "Docker registry image name." }, "docker_registry_image_tag": { "type": "string", "nullable": true, "description": "Docker registry image tag." }, "build_pack": { "type": "string", "description": "Build pack.", "enum": [ "nixpacks", "static", "dockerfile", "dockercompose" ] }, "static_image": { "type": "string", "description": "Static image used when static site is deployed." }, "install_command": { "type": "string", "description": "Install command." }, "build_command": { "type": "string", "description": "Build command." }, "start_command": { "type": "string", "description": "Start command." }, "ports_exposes": { "type": "string", "description": "Ports exposes." }, "ports_mappings": { "type": "string", "nullable": true, "description": "Ports mappings." }, "custom_network_aliases": { "type": "string", "nullable": true, "description": "Network aliases for Docker container." }, "base_directory": { "type": "string", "description": "Base directory for all commands." }, "publish_directory": { "type": "string", "description": "Publish directory." }, "health_check_enabled": { "type": "boolean", "description": "Health check enabled." }, "health_check_path": { "type": "string", "description": "Health check path." }, "health_check_port": { "type": "string", "nullable": true, "description": "Health check port." }, "health_check_host": { "type": "string", "nullable": true, "description": "Health check host." }, "health_check_method": { "type": "string", "description": "Health check method." }, "health_check_return_code": { "type": "integer", "description": "Health check return code." }, "health_check_scheme": { "type": "string", "description": "Health check scheme." }, "health_check_response_text": { "type": "string", "nullable": true, "description": "Health check response text." }, "health_check_interval": { "type": "integer", "description": "Health check interval in seconds." }, "health_check_timeout": { "type": "integer", "description": "Health check timeout in seconds." }, "health_check_retries": { "type": "integer", "description": "Health check retries count." }, "health_check_start_period": { "type": "integer", "description": "Health check start period in seconds." }, "health_check_type": { "type": "string", "description": "Health check type: http or cmd.", "enum": [ "http", "cmd" ] }, "health_check_command": { "type": "string", "nullable": true, "description": "Health check command for CMD type." }, "limits_memory": { "type": "string", "description": "Memory limit." }, "limits_memory_swap": { "type": "string", "description": "Memory swap limit." }, "limits_memory_swappiness": { "type": "integer", "description": "Memory swappiness." }, "limits_memory_reservation": { "type": "string", "description": "Memory reservation." }, "limits_cpus": { "type": "string", "description": "CPU limit." }, "limits_cpuset": { "type": "string", "nullable": true, "description": "CPU set." }, "limits_cpu_shares": { "type": "integer", "description": "CPU shares." }, "status": { "type": "string", "description": "Application status." }, "preview_url_template": { "type": "string", "description": "Preview URL template." }, "destination_type": { "type": "string", "description": "Destination type." }, "destination_id": { "type": "integer", "description": "Destination identifier." }, "source_id": { "type": "integer", "nullable": true, "description": "Source identifier." }, "private_key_id": { "type": "integer", "nullable": true, "description": "Private key identifier." }, "environment_id": { "type": "integer", "description": "Environment identifier." }, "dockerfile": { "type": "string", "nullable": true, "description": "Dockerfile content. Used for dockerfile build pack." }, "dockerfile_location": { "type": "string", "description": "Dockerfile location." }, "custom_labels": { "type": "string", "nullable": true, "description": "Custom labels." }, "dockerfile_target_build": { "type": "string", "nullable": true, "description": "Dockerfile target build." }, "manual_webhook_secret_github": { "type": "string", "nullable": true, "description": "Manual webhook secret for GitHub." }, "manual_webhook_secret_gitlab": { "type": "string", "nullable": true, "description": "Manual webhook secret for GitLab." }, "manual_webhook_secret_bitbucket": { "type": "string", "nullable": true, "description": "Manual webhook secret for Bitbucket." }, "manual_webhook_secret_gitea": { "type": "string", "nullable": true, "description": "Manual webhook secret for Gitea." }, "docker_compose_location": { "type": "string", "description": "Docker compose location." }, "docker_compose": { "type": "string", "nullable": true, "description": "Docker compose content. Used for docker compose build pack." }, "docker_compose_raw": { "type": "string", "nullable": true, "description": "Docker compose raw content." }, "docker_compose_domains": { "type": "string", "nullable": true, "description": "Docker compose domains." }, "docker_compose_custom_start_command": { "type": "string", "nullable": true, "description": "Docker compose custom start command." }, "docker_compose_custom_build_command": { "type": "string", "nullable": true, "description": "Docker compose custom build command." }, "swarm_replicas": { "type": "integer", "nullable": true, "description": "Swarm replicas. Only used for swarm deployments." }, "swarm_placement_constraints": { "type": "string", "nullable": true, "description": "Swarm placement constraints. Only used for swarm deployments." }, "custom_docker_run_options": { "type": "string", "nullable": true, "description": "Custom docker run options." }, "post_deployment_command": { "type": "string", "nullable": true, "description": "Post deployment command." }, "post_deployment_command_container": { "type": "string", "nullable": true, "description": "Post deployment command container." }, "pre_deployment_command": { "type": "string", "nullable": true, "description": "Pre deployment command." }, "pre_deployment_command_container": { "type": "string", "nullable": true, "description": "Pre deployment command container." }, "watch_paths": { "type": "string", "nullable": true, "description": "Watch paths." }, "custom_healthcheck_found": { "type": "boolean", "description": "Custom healthcheck found." }, "redirect": { "type": "string", "nullable": true, "description": "How to set redirect with Traefik \/ Caddy. www<->non-www.", "enum": [ "www", "non-www", "both" ] }, "created_at": { "type": "string", "format": "date-time", "description": "The date and time when the application was created." }, "updated_at": { "type": "string", "format": "date-time", "description": "The date and time when the application was last updated." }, "deleted_at": { "type": "string", "format": "date-time", "nullable": true, "description": "The date and time when the application was deleted." }, "compose_parsing_version": { "type": "string", "description": "How Coolify parse the compose file." }, "custom_nginx_configuration": { "type": "string", "nullable": true, "description": "Custom Nginx configuration base64 encoded." }, "is_http_basic_auth_enabled": { "type": "boolean", "description": "HTTP Basic Authentication enabled." }, "http_basic_auth_username": { "type": "string", "nullable": true, "description": "Username for HTTP Basic Authentication" }, "http_basic_auth_password": { "type": "string", "nullable": true, "description": "Password for HTTP Basic Authentication" } }, "type": "object" }, "ApplicationDeploymentQueue": { "description": "Project model", "properties": { "id": { "type": "integer" }, "application_id": { "type": "string" }, "deployment_uuid": { "type": "string" }, "pull_request_id": { "type": "integer" }, "force_rebuild": { "type": "boolean" }, "commit": { "type": "string" }, "status": { "type": "string" }, "is_webhook": { "type": "boolean" }, "is_api": { "type": "boolean" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "logs": { "type": "string" }, "current_process_id": { "type": "string" }, "restart_only": { "type": "boolean" }, "git_type": { "type": "string" }, "server_id": { "type": "integer" }, "application_name": { "type": "string" }, "server_name": { "type": "string" }, "deployment_url": { "type": "string" }, "destination_id": { "type": "string" }, "only_this_server": { "type": "boolean" }, "rollback": { "type": "boolean" }, "commit_message": { "type": "string" } }, "type": "object" }, "Environment": { "description": "Environment model", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "project_id": { "type": "integer" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "description": { "type": "string" } }, "type": "object" }, "EnvironmentVariable": { "description": "Environment Variable model", "properties": { "id": { "type": "integer" }, "uuid": { "type": "string" }, "resourceable_type": { "type": "string" }, "resourceable_id": { "type": "integer" }, "is_literal": { "type": "boolean" }, "is_multiline": { "type": "boolean" }, "is_preview": { "type": "boolean" }, "is_runtime": { "type": "boolean" }, "is_buildtime": { "type": "boolean" }, "is_shared": { "type": "boolean" }, "is_shown_once": { "type": "boolean" }, "key": { "type": "string" }, "value": { "type": "string" }, "real_value": { "type": "string" }, "comment": { "type": "string", "nullable": true }, "version": { "type": "string" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "type": "object" }, "PrivateKey": { "description": "Private Key model", "properties": { "id": { "type": "integer" }, "uuid": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string" }, "private_key": { "type": "string", "format": "private-key" }, "public_key": { "type": "string", "description": "The public key of the private key." }, "fingerprint": { "type": "string", "description": "The fingerprint of the private key." }, "is_git_related": { "type": "boolean" }, "team_id": { "type": "integer" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "type": "object" }, "Project": { "description": "Project model", "properties": { "id": { "type": "integer" }, "uuid": { "type": "string" }, "name": { "type": "string" }, "description": { "type": "string" } }, "type": "object" }, "ScheduledTask": { "description": "Scheduled Task model", "properties": { "id": { "type": "integer", "description": "The unique identifier of the scheduled task in the database." }, "uuid": { "type": "string", "description": "The unique identifier of the scheduled task." }, "enabled": { "type": "boolean", "description": "The flag to indicate if the scheduled task is enabled." }, "name": { "type": "string", "description": "The name of the scheduled task." }, "command": { "type": "string", "description": "The command to execute." }, "frequency": { "type": "string", "description": "The frequency of the scheduled task." }, "container": { "type": "string", "nullable": true, "description": "The container where the command should be executed." }, "timeout": { "type": "integer", "description": "The timeout of the scheduled task in seconds." }, "created_at": { "type": "string", "format": "date-time", "description": "The date and time when the scheduled task was created." }, "updated_at": { "type": "string", "format": "date-time", "description": "The date and time when the scheduled task was last updated." } }, "type": "object" }, "ScheduledTaskExecution": { "description": "Scheduled Task Execution model", "properties": { "uuid": { "type": "string", "description": "The unique identifier of the execution." }, "status": { "type": "string", "enum": [ "success", "failed", "running" ], "description": "The status of the execution." }, "message": { "type": "string", "nullable": true, "description": "The output message of the execution." }, "retry_count": { "type": "integer", "description": "The number of retries." }, "duration": { "type": "number", "nullable": true, "description": "Duration in seconds." }, "started_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the execution started." }, "finished_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the execution finished." }, "created_at": { "type": "string", "format": "date-time", "description": "When the record was created." }, "updated_at": { "type": "string", "format": "date-time", "description": "When the record was last updated." } }, "type": "object" }, "Server": { "description": "Server model", "properties": { "id": { "type": "integer", "description": "The server ID." }, "uuid": { "type": "string", "description": "The server UUID." }, "name": { "type": "string", "description": "The server name." }, "description": { "type": "string", "description": "The server description." }, "ip": { "type": "string", "description": "The IP address." }, "user": { "type": "string", "description": "The user." }, "port": { "type": "integer", "description": "The port number." }, "proxy": { "type": "object", "description": "The proxy configuration." }, "proxy_type": { "type": "string", "enum": [ "traefik", "caddy", "none" ], "description": "The proxy type." }, "high_disk_usage_notification_sent": { "type": "boolean", "description": "The flag to indicate if the high disk usage notification has been sent." }, "unreachable_notification_sent": { "type": "boolean", "description": "The flag to indicate if the unreachable notification has been sent." }, "unreachable_count": { "type": "integer", "description": "The unreachable count for your server." }, "validation_logs": { "type": "string", "description": "The validation logs." }, "log_drain_notification_sent": { "type": "boolean", "description": "The flag to indicate if the log drain notification has been sent." }, "swarm_cluster": { "type": "string", "description": "The swarm cluster configuration." }, "settings": { "$ref": "#\/components\/schemas\/ServerSetting" } }, "type": "object" }, "ServerSetting": { "description": "Server Settings model", "properties": { "id": { "type": "integer" }, "concurrent_builds": { "type": "integer" }, "deployment_queue_limit": { "type": "integer" }, "dynamic_timeout": { "type": "integer" }, "force_disabled": { "type": "boolean" }, "force_server_cleanup": { "type": "boolean" }, "is_build_server": { "type": "boolean" }, "is_cloudflare_tunnel": { "type": "boolean" }, "is_jump_server": { "type": "boolean" }, "is_logdrain_axiom_enabled": { "type": "boolean" }, "is_logdrain_custom_enabled": { "type": "boolean" }, "is_logdrain_highlight_enabled": { "type": "boolean" }, "is_logdrain_newrelic_enabled": { "type": "boolean" }, "is_metrics_enabled": { "type": "boolean" }, "is_reachable": { "type": "boolean" }, "is_sentinel_enabled": { "type": "boolean" }, "is_swarm_manager": { "type": "boolean" }, "is_swarm_worker": { "type": "boolean" }, "is_terminal_enabled": { "type": "boolean" }, "is_usable": { "type": "boolean" }, "logdrain_axiom_api_key": { "type": "string" }, "logdrain_axiom_dataset_name": { "type": "string" }, "logdrain_custom_config": { "type": "string" }, "logdrain_custom_config_parser": { "type": "string" }, "logdrain_highlight_project_id": { "type": "string" }, "logdrain_newrelic_base_uri": { "type": "string" }, "logdrain_newrelic_license_key": { "type": "string" }, "sentinel_metrics_history_days": { "type": "integer" }, "sentinel_metrics_refresh_rate_seconds": { "type": "integer" }, "sentinel_token": { "type": "string" }, "docker_cleanup_frequency": { "type": "string" }, "docker_cleanup_threshold": { "type": "integer" }, "server_id": { "type": "integer" }, "wildcard_domain": { "type": "string" }, "created_at": { "type": "string" }, "updated_at": { "type": "string" }, "delete_unused_volumes": { "type": "boolean", "description": "The flag to indicate if the unused volumes should be deleted." }, "delete_unused_networks": { "type": "boolean", "description": "The flag to indicate if the unused networks should be deleted." } }, "type": "object" }, "Service": { "description": "Service model", "properties": { "id": { "type": "integer", "description": "The unique identifier of the service. Only used for database identification." }, "uuid": { "type": "string", "description": "The unique identifier of the service." }, "name": { "type": "string", "description": "The name of the service." }, "environment_id": { "type": "integer", "description": "The unique identifier of the environment where the service is attached to." }, "server_id": { "type": "integer", "description": "The unique identifier of the server where the service is running." }, "description": { "type": "string", "description": "The description of the service." }, "docker_compose_raw": { "type": "string", "description": "The raw docker-compose.yml file of the service." }, "docker_compose": { "type": "string", "description": "The docker-compose.yml file that is parsed and modified by Coolify." }, "destination_type": { "type": "string", "description": "Destination type." }, "destination_id": { "type": "integer", "description": "The unique identifier of the destination where the service is running." }, "connect_to_docker_network": { "type": "boolean", "description": "The flag to connect the service to the predefined Docker network." }, "is_container_label_escape_enabled": { "type": "boolean", "description": "The flag to enable the container label escape." }, "is_container_label_readonly_enabled": { "type": "boolean", "description": "The flag to enable the container label readonly." }, "config_hash": { "type": "string", "description": "The hash of the service configuration." }, "service_type": { "type": "string", "description": "The type of the service." }, "created_at": { "type": "string", "description": "The date and time when the service was created." }, "updated_at": { "type": "string", "description": "The date and time when the service was last updated." }, "deleted_at": { "type": "string", "description": "The date and time when the service was deleted." } }, "type": "object" }, "Team": { "description": "Team model", "properties": { "id": { "type": "integer", "description": "The unique identifier of the team." }, "name": { "type": "string", "description": "The name of the team." }, "description": { "type": "string", "description": "The description of the team." }, "personal_team": { "type": "boolean", "description": "Whether the team is personal or not." }, "created_at": { "type": "string", "description": "The date and time the team was created." }, "updated_at": { "type": "string", "description": "The date and time the team was last updated." }, "show_boarding": { "type": "boolean", "description": "Whether to show the boarding screen or not." }, "custom_server_limit": { "type": "string", "description": "The custom server limit." }, "members": { "description": "The members of the team.", "type": "array", "items": { "$ref": "#\/components\/schemas\/User" } } }, "type": "object" }, "User": { "description": "User model", "properties": { "id": { "type": "integer", "description": "The user identifier in the database." }, "name": { "type": "string", "description": "The user name." }, "email": { "type": "string", "description": "The user email." }, "email_verified_at": { "type": "string", "description": "The date when the user email was verified." }, "created_at": { "type": "string", "description": "The date when the user was created." }, "updated_at": { "type": "string", "description": "The date when the user was updated." }, "two_factor_confirmed_at": { "type": "string", "description": "The date when the user two factor was confirmed." }, "force_password_reset": { "type": "boolean", "description": "The flag to force the user to reset the password." }, "marketing_emails": { "type": "boolean", "description": "The flag to receive marketing emails." } }, "type": "object" } }, "responses": { "400": { "description": "Invalid token.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Invalid token." } }, "type": "object" } } } }, "401": { "description": "Unauthenticated.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Unauthenticated." } }, "type": "object" } } } }, "404": { "description": "Resource not found.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Resource not found." } }, "type": "object" } } } }, "422": { "description": "Validation error.", "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Validation error." }, "errors": { "type": "object", "example": { "name": [ "The name field is required." ], "api_url": [ "The api url field is required.", "The api url format is invalid." ] }, "additionalProperties": { "type": "array", "items": { "type": "string" } } } }, "type": "object" } } } }, "429": { "description": "Rate limit exceeded.", "headers": { "Retry-After": { "description": "Number of seconds to wait before retrying.", "schema": { "type": "integer", "example": 60 } } }, "content": { "application\/json": { "schema": { "properties": { "message": { "type": "string", "example": "Rate limit exceeded. Please try again later." } }, "type": "object" } } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Go to `Keys & Tokens` \/ `API tokens` and create a new token. Use the token as the bearer token.", "scheme": "bearer" } } }, "tags": [ { "name": "Applications", "description": "Applications" }, { "name": "Cloud Tokens", "description": "Cloud Tokens" }, { "name": "Databases", "description": "Databases" }, { "name": "Deployments", "description": "Deployments" }, { "name": "GitHub Apps", "description": "GitHub Apps" }, { "name": "Hetzner", "description": "Hetzner" }, { "name": "Projects", "description": "Projects" }, { "name": "Resources", "description": "Resources" }, { "name": "Scheduled Tasks", "description": "Scheduled Tasks" }, { "name": "Private Keys", "description": "Private Keys" }, { "name": "Servers", "description": "Servers" }, { "name": "Services", "description": "Services" }, { "name": "Teams", "description": "Teams" } ] } ================================================ FILE: openapi.yaml ================================================ openapi: 3.1.0 info: title: Coolify version: '0.1' servers: - url: 'https://app.coolify.io/api/v1' description: 'Coolify Cloud API. Change the host to your own instance if you are self-hosting.' paths: /applications: get: tags: - Applications summary: List description: 'List all applications.' operationId: list-applications parameters: - name: tag in: query description: 'Filter applications by tag name.' required: false schema: type: string responses: '200': description: 'Get all applications.' content: application/json: schema: type: array items: $ref: '#/components/schemas/Application' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] /applications/public: post: tags: - Applications summary: 'Create (Public)' description: 'Create new application based on a public git repository.' operationId: create-public-application requestBody: description: 'Application object that needs to be created.' required: true content: application/json: schema: required: - project_uuid - server_uuid - environment_name - environment_uuid - git_repository - git_branch - build_pack - ports_exposes properties: project_uuid: type: string description: 'The project UUID.' server_uuid: type: string description: 'The server UUID.' environment_name: type: string description: 'The environment name. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.' git_repository: type: string description: 'The git repository URL.' git_branch: type: string description: 'The git branch.' build_pack: type: string enum: [nixpacks, static, dockerfile, dockercompose] description: 'The build pack type.' ports_exposes: type: string description: 'The ports to expose.' destination_uuid: type: string description: 'The destination UUID.' name: type: string description: 'The application name.' description: type: string description: 'The application description.' domains: type: string description: 'The application URLs in a comma-separated list.' git_commit_sha: type: string description: 'The git commit SHA.' docker_registry_image_name: type: string description: 'The docker registry image name.' docker_registry_image_tag: type: string description: 'The docker registry image tag.' is_static: type: boolean description: 'The flag to indicate if the application is static.' is_spa: type: boolean description: 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.' is_auto_deploy_enabled: type: boolean description: 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.' is_force_https_enabled: type: boolean description: 'The flag to indicate if HTTPS is forced. Defaults to true.' static_image: type: string enum: ['nginx:alpine'] description: 'The static image.' install_command: type: string description: 'The install command.' build_command: type: string description: 'The build command.' start_command: type: string description: 'The start command.' ports_mappings: type: string description: 'The ports mappings.' base_directory: type: string description: 'The base directory for all commands.' publish_directory: type: string description: 'The publish directory.' health_check_enabled: type: boolean description: 'Health check enabled.' health_check_path: type: string description: 'Health check path.' health_check_port: type: string nullable: true description: 'Health check port.' health_check_host: type: string nullable: true description: 'Health check host.' health_check_method: type: string description: 'Health check method.' health_check_return_code: type: integer description: 'Health check return code.' health_check_scheme: type: string description: 'Health check scheme.' health_check_response_text: type: string nullable: true description: 'Health check response text.' health_check_interval: type: integer description: 'Health check interval in seconds.' health_check_timeout: type: integer description: 'Health check timeout in seconds.' health_check_retries: type: integer description: 'Health check retries count.' health_check_start_period: type: integer description: 'Health check start period in seconds.' limits_memory: type: string description: 'Memory limit.' limits_memory_swap: type: string description: 'Memory swap limit.' limits_memory_swappiness: type: integer description: 'Memory swappiness.' limits_memory_reservation: type: string description: 'Memory reservation.' limits_cpus: type: string description: 'CPU limit.' limits_cpuset: type: string nullable: true description: 'CPU set.' limits_cpu_shares: type: integer description: 'CPU shares.' custom_labels: type: string description: 'Custom labels.' custom_docker_run_options: type: string description: 'Custom docker run options.' post_deployment_command: type: string description: 'Post deployment command.' post_deployment_command_container: type: string description: 'Post deployment command container.' pre_deployment_command: type: string description: 'Pre deployment command.' pre_deployment_command_container: type: string description: 'Pre deployment command container.' manual_webhook_secret_github: type: string description: 'Manual webhook secret for Github.' manual_webhook_secret_gitlab: type: string description: 'Manual webhook secret for Gitlab.' manual_webhook_secret_bitbucket: type: string description: 'Manual webhook secret for Bitbucket.' manual_webhook_secret_gitea: type: string description: 'Manual webhook secret for Gitea.' redirect: type: string nullable: true description: 'How to set redirect with Traefik / Caddy. www<->non-www.' enum: [www, non-www, both] instant_deploy: type: boolean description: 'The flag to indicate if the application should be deployed instantly.' dockerfile: type: string description: 'The Dockerfile content.' dockerfile_location: type: string description: 'The Dockerfile location in the repository.' docker_compose_location: type: string description: 'The Docker Compose location.' docker_compose_custom_start_command: type: string description: 'The Docker Compose custom start command.' docker_compose_custom_build_command: type: string description: 'The Docker Compose custom build command.' docker_compose_domains: type: array description: 'Array of URLs to be applied to containers of a dockercompose application.' items: { properties: { name: { type: string, description: 'The service name as defined in docker-compose.' }, domain: { type: string, description: 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")' } }, type: object } watch_paths: type: string description: 'The watch paths.' use_build_server: type: boolean nullable: true description: 'Use build server.' is_http_basic_auth_enabled: type: boolean description: 'HTTP Basic Authentication enabled.' http_basic_auth_username: type: string nullable: true description: 'Username for HTTP Basic Authentication' http_basic_auth_password: type: string nullable: true description: 'Password for HTTP Basic Authentication' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' force_domain_override: type: boolean description: 'Force domain usage even if conflicts are detected. Default is false.' autogenerate_domain: type: boolean default: true description: "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." is_container_label_escape_enabled: type: boolean default: true description: 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.' type: object responses: '201': description: 'Application created successfully.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object security: - bearerAuth: [] /applications/private-github-app: post: tags: - Applications summary: 'Create (Private - GH App)' description: 'Create new application based on a private repository through a Github App.' operationId: create-private-github-app-application requestBody: description: 'Application object that needs to be created.' required: true content: application/json: schema: required: - project_uuid - server_uuid - environment_name - environment_uuid - github_app_uuid - git_repository - git_branch - build_pack - ports_exposes properties: project_uuid: type: string description: 'The project UUID.' server_uuid: type: string description: 'The server UUID.' environment_name: type: string description: 'The environment name. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.' github_app_uuid: type: string description: 'The Github App UUID.' git_repository: type: string description: 'The git repository URL.' git_branch: type: string description: 'The git branch.' ports_exposes: type: string description: 'The ports to expose.' destination_uuid: type: string description: 'The destination UUID.' build_pack: type: string enum: [nixpacks, static, dockerfile, dockercompose] description: 'The build pack type.' name: type: string description: 'The application name.' description: type: string description: 'The application description.' domains: type: string description: 'The application URLs in a comma-separated list.' git_commit_sha: type: string description: 'The git commit SHA.' docker_registry_image_name: type: string description: 'The docker registry image name.' docker_registry_image_tag: type: string description: 'The docker registry image tag.' is_static: type: boolean description: 'The flag to indicate if the application is static.' is_spa: type: boolean description: 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.' is_auto_deploy_enabled: type: boolean description: 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.' is_force_https_enabled: type: boolean description: 'The flag to indicate if HTTPS is forced. Defaults to true.' static_image: type: string enum: ['nginx:alpine'] description: 'The static image.' install_command: type: string description: 'The install command.' build_command: type: string description: 'The build command.' start_command: type: string description: 'The start command.' ports_mappings: type: string description: 'The ports mappings.' base_directory: type: string description: 'The base directory for all commands.' publish_directory: type: string description: 'The publish directory.' health_check_enabled: type: boolean description: 'Health check enabled.' health_check_path: type: string description: 'Health check path.' health_check_port: type: string nullable: true description: 'Health check port.' health_check_host: type: string nullable: true description: 'Health check host.' health_check_method: type: string description: 'Health check method.' health_check_return_code: type: integer description: 'Health check return code.' health_check_scheme: type: string description: 'Health check scheme.' health_check_response_text: type: string nullable: true description: 'Health check response text.' health_check_interval: type: integer description: 'Health check interval in seconds.' health_check_timeout: type: integer description: 'Health check timeout in seconds.' health_check_retries: type: integer description: 'Health check retries count.' health_check_start_period: type: integer description: 'Health check start period in seconds.' limits_memory: type: string description: 'Memory limit.' limits_memory_swap: type: string description: 'Memory swap limit.' limits_memory_swappiness: type: integer description: 'Memory swappiness.' limits_memory_reservation: type: string description: 'Memory reservation.' limits_cpus: type: string description: 'CPU limit.' limits_cpuset: type: string nullable: true description: 'CPU set.' limits_cpu_shares: type: integer description: 'CPU shares.' custom_labels: type: string description: 'Custom labels.' custom_docker_run_options: type: string description: 'Custom docker run options.' post_deployment_command: type: string description: 'Post deployment command.' post_deployment_command_container: type: string description: 'Post deployment command container.' pre_deployment_command: type: string description: 'Pre deployment command.' pre_deployment_command_container: type: string description: 'Pre deployment command container.' manual_webhook_secret_github: type: string description: 'Manual webhook secret for Github.' manual_webhook_secret_gitlab: type: string description: 'Manual webhook secret for Gitlab.' manual_webhook_secret_bitbucket: type: string description: 'Manual webhook secret for Bitbucket.' manual_webhook_secret_gitea: type: string description: 'Manual webhook secret for Gitea.' redirect: type: string nullable: true description: 'How to set redirect with Traefik / Caddy. www<->non-www.' enum: [www, non-www, both] instant_deploy: type: boolean description: 'The flag to indicate if the application should be deployed instantly.' dockerfile: type: string description: 'The Dockerfile content.' dockerfile_location: type: string description: 'The Dockerfile location in the repository' docker_compose_location: type: string description: 'The Docker Compose location.' docker_compose_custom_start_command: type: string description: 'The Docker Compose custom start command.' docker_compose_custom_build_command: type: string description: 'The Docker Compose custom build command.' docker_compose_domains: type: array description: 'Array of URLs to be applied to containers of a dockercompose application.' items: { properties: { name: { type: string, description: 'The service name as defined in docker-compose.' }, domain: { type: string, description: 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")' } }, type: object } watch_paths: type: string description: 'The watch paths.' use_build_server: type: boolean nullable: true description: 'Use build server.' is_http_basic_auth_enabled: type: boolean description: 'HTTP Basic Authentication enabled.' http_basic_auth_username: type: string nullable: true description: 'Username for HTTP Basic Authentication' http_basic_auth_password: type: string nullable: true description: 'Password for HTTP Basic Authentication' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' force_domain_override: type: boolean description: 'Force domain usage even if conflicts are detected. Default is false.' autogenerate_domain: type: boolean default: true description: "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." is_container_label_escape_enabled: type: boolean default: true description: 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.' type: object responses: '201': description: 'Application created successfully.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object security: - bearerAuth: [] /applications/private-deploy-key: post: tags: - Applications summary: 'Create (Private - Deploy Key)' description: 'Create new application based on a private repository through a Deploy Key.' operationId: create-private-deploy-key-application requestBody: description: 'Application object that needs to be created.' required: true content: application/json: schema: required: - project_uuid - server_uuid - environment_name - environment_uuid - private_key_uuid - git_repository - git_branch - build_pack - ports_exposes properties: project_uuid: type: string description: 'The project UUID.' server_uuid: type: string description: 'The server UUID.' environment_name: type: string description: 'The environment name. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.' private_key_uuid: type: string description: 'The private key UUID.' git_repository: type: string description: 'The git repository URL.' git_branch: type: string description: 'The git branch.' ports_exposes: type: string description: 'The ports to expose.' destination_uuid: type: string description: 'The destination UUID.' build_pack: type: string enum: [nixpacks, static, dockerfile, dockercompose] description: 'The build pack type.' name: type: string description: 'The application name.' description: type: string description: 'The application description.' domains: type: string description: 'The application URLs in a comma-separated list.' git_commit_sha: type: string description: 'The git commit SHA.' docker_registry_image_name: type: string description: 'The docker registry image name.' docker_registry_image_tag: type: string description: 'The docker registry image tag.' is_static: type: boolean description: 'The flag to indicate if the application is static.' is_spa: type: boolean description: 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.' is_auto_deploy_enabled: type: boolean description: 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.' is_force_https_enabled: type: boolean description: 'The flag to indicate if HTTPS is forced. Defaults to true.' static_image: type: string enum: ['nginx:alpine'] description: 'The static image.' install_command: type: string description: 'The install command.' build_command: type: string description: 'The build command.' start_command: type: string description: 'The start command.' ports_mappings: type: string description: 'The ports mappings.' base_directory: type: string description: 'The base directory for all commands.' publish_directory: type: string description: 'The publish directory.' health_check_enabled: type: boolean description: 'Health check enabled.' health_check_path: type: string description: 'Health check path.' health_check_port: type: string nullable: true description: 'Health check port.' health_check_host: type: string nullable: true description: 'Health check host.' health_check_method: type: string description: 'Health check method.' health_check_return_code: type: integer description: 'Health check return code.' health_check_scheme: type: string description: 'Health check scheme.' health_check_response_text: type: string nullable: true description: 'Health check response text.' health_check_interval: type: integer description: 'Health check interval in seconds.' health_check_timeout: type: integer description: 'Health check timeout in seconds.' health_check_retries: type: integer description: 'Health check retries count.' health_check_start_period: type: integer description: 'Health check start period in seconds.' limits_memory: type: string description: 'Memory limit.' limits_memory_swap: type: string description: 'Memory swap limit.' limits_memory_swappiness: type: integer description: 'Memory swappiness.' limits_memory_reservation: type: string description: 'Memory reservation.' limits_cpus: type: string description: 'CPU limit.' limits_cpuset: type: string nullable: true description: 'CPU set.' limits_cpu_shares: type: integer description: 'CPU shares.' custom_labels: type: string description: 'Custom labels.' custom_docker_run_options: type: string description: 'Custom docker run options.' post_deployment_command: type: string description: 'Post deployment command.' post_deployment_command_container: type: string description: 'Post deployment command container.' pre_deployment_command: type: string description: 'Pre deployment command.' pre_deployment_command_container: type: string description: 'Pre deployment command container.' manual_webhook_secret_github: type: string description: 'Manual webhook secret for Github.' manual_webhook_secret_gitlab: type: string description: 'Manual webhook secret for Gitlab.' manual_webhook_secret_bitbucket: type: string description: 'Manual webhook secret for Bitbucket.' manual_webhook_secret_gitea: type: string description: 'Manual webhook secret for Gitea.' redirect: type: string nullable: true description: 'How to set redirect with Traefik / Caddy. www<->non-www.' enum: [www, non-www, both] instant_deploy: type: boolean description: 'The flag to indicate if the application should be deployed instantly.' dockerfile: type: string description: 'The Dockerfile content.' dockerfile_location: type: string description: 'The Dockerfile location in the repository.' docker_compose_location: type: string description: 'The Docker Compose location.' docker_compose_custom_start_command: type: string description: 'The Docker Compose custom start command.' docker_compose_custom_build_command: type: string description: 'The Docker Compose custom build command.' docker_compose_domains: type: array description: 'Array of URLs to be applied to containers of a dockercompose application.' items: { properties: { name: { type: string, description: 'The service name as defined in docker-compose.' }, domain: { type: string, description: 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")' } }, type: object } watch_paths: type: string description: 'The watch paths.' use_build_server: type: boolean nullable: true description: 'Use build server.' is_http_basic_auth_enabled: type: boolean description: 'HTTP Basic Authentication enabled.' http_basic_auth_username: type: string nullable: true description: 'Username for HTTP Basic Authentication' http_basic_auth_password: type: string nullable: true description: 'Password for HTTP Basic Authentication' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' force_domain_override: type: boolean description: 'Force domain usage even if conflicts are detected. Default is false.' autogenerate_domain: type: boolean default: true description: "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." is_container_label_escape_enabled: type: boolean default: true description: 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.' type: object responses: '201': description: 'Application created successfully.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object security: - bearerAuth: [] /applications/dockerfile: post: tags: - Applications summary: 'Create (Dockerfile without git)' description: 'Create new application based on a simple Dockerfile (without git).' operationId: create-dockerfile-application requestBody: description: 'Application object that needs to be created.' required: true content: application/json: schema: required: - project_uuid - server_uuid - environment_name - environment_uuid - dockerfile properties: project_uuid: type: string description: 'The project UUID.' server_uuid: type: string description: 'The server UUID.' environment_name: type: string description: 'The environment name. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.' dockerfile: type: string description: 'The Dockerfile content.' build_pack: type: string enum: [nixpacks, static, dockerfile, dockercompose] description: 'The build pack type.' ports_exposes: type: string description: 'The ports to expose.' destination_uuid: type: string description: 'The destination UUID.' name: type: string description: 'The application name.' description: type: string description: 'The application description.' domains: type: string description: 'The application URLs in a comma-separated list.' docker_registry_image_name: type: string description: 'The docker registry image name.' docker_registry_image_tag: type: string description: 'The docker registry image tag.' ports_mappings: type: string description: 'The ports mappings.' base_directory: type: string description: 'The base directory for all commands.' health_check_enabled: type: boolean description: 'Health check enabled.' health_check_path: type: string description: 'Health check path.' health_check_port: type: string nullable: true description: 'Health check port.' health_check_host: type: string nullable: true description: 'Health check host.' health_check_method: type: string description: 'Health check method.' health_check_return_code: type: integer description: 'Health check return code.' health_check_scheme: type: string description: 'Health check scheme.' health_check_response_text: type: string nullable: true description: 'Health check response text.' health_check_interval: type: integer description: 'Health check interval in seconds.' health_check_timeout: type: integer description: 'Health check timeout in seconds.' health_check_retries: type: integer description: 'Health check retries count.' health_check_start_period: type: integer description: 'Health check start period in seconds.' limits_memory: type: string description: 'Memory limit.' limits_memory_swap: type: string description: 'Memory swap limit.' limits_memory_swappiness: type: integer description: 'Memory swappiness.' limits_memory_reservation: type: string description: 'Memory reservation.' limits_cpus: type: string description: 'CPU limit.' limits_cpuset: type: string nullable: true description: 'CPU set.' limits_cpu_shares: type: integer description: 'CPU shares.' custom_labels: type: string description: 'Custom labels.' custom_docker_run_options: type: string description: 'Custom docker run options.' post_deployment_command: type: string description: 'Post deployment command.' post_deployment_command_container: type: string description: 'Post deployment command container.' pre_deployment_command: type: string description: 'Pre deployment command.' pre_deployment_command_container: type: string description: 'Pre deployment command container.' manual_webhook_secret_github: type: string description: 'Manual webhook secret for Github.' manual_webhook_secret_gitlab: type: string description: 'Manual webhook secret for Gitlab.' manual_webhook_secret_bitbucket: type: string description: 'Manual webhook secret for Bitbucket.' manual_webhook_secret_gitea: type: string description: 'Manual webhook secret for Gitea.' redirect: type: string nullable: true description: 'How to set redirect with Traefik / Caddy. www<->non-www.' enum: [www, non-www, both] instant_deploy: type: boolean description: 'The flag to indicate if the application should be deployed instantly.' is_force_https_enabled: type: boolean description: 'The flag to indicate if HTTPS is forced. Defaults to true.' use_build_server: type: boolean nullable: true description: 'Use build server.' is_http_basic_auth_enabled: type: boolean description: 'HTTP Basic Authentication enabled.' http_basic_auth_username: type: string nullable: true description: 'Username for HTTP Basic Authentication' http_basic_auth_password: type: string nullable: true description: 'Password for HTTP Basic Authentication' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' force_domain_override: type: boolean description: 'Force domain usage even if conflicts are detected. Default is false.' autogenerate_domain: type: boolean default: true description: "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." is_container_label_escape_enabled: type: boolean default: true description: 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.' type: object responses: '201': description: 'Application created successfully.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object security: - bearerAuth: [] /applications/dockerimage: post: tags: - Applications summary: 'Create (Docker Image without git)' description: 'Create new application based on a prebuilt docker image (without git).' operationId: create-dockerimage-application requestBody: description: 'Application object that needs to be created.' required: true content: application/json: schema: required: - project_uuid - server_uuid - environment_name - environment_uuid - docker_registry_image_name - ports_exposes properties: project_uuid: type: string description: 'The project UUID.' server_uuid: type: string description: 'The server UUID.' environment_name: type: string description: 'The environment name. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.' docker_registry_image_name: type: string description: 'The docker registry image name.' docker_registry_image_tag: type: string description: 'The docker registry image tag.' ports_exposes: type: string description: 'The ports to expose.' destination_uuid: type: string description: 'The destination UUID.' name: type: string description: 'The application name.' description: type: string description: 'The application description.' domains: type: string description: 'The application URLs in a comma-separated list.' ports_mappings: type: string description: 'The ports mappings.' health_check_enabled: type: boolean description: 'Health check enabled.' health_check_path: type: string description: 'Health check path.' health_check_port: type: string nullable: true description: 'Health check port.' health_check_host: type: string nullable: true description: 'Health check host.' health_check_method: type: string description: 'Health check method.' health_check_return_code: type: integer description: 'Health check return code.' health_check_scheme: type: string description: 'Health check scheme.' health_check_response_text: type: string nullable: true description: 'Health check response text.' health_check_interval: type: integer description: 'Health check interval in seconds.' health_check_timeout: type: integer description: 'Health check timeout in seconds.' health_check_retries: type: integer description: 'Health check retries count.' health_check_start_period: type: integer description: 'Health check start period in seconds.' limits_memory: type: string description: 'Memory limit.' limits_memory_swap: type: string description: 'Memory swap limit.' limits_memory_swappiness: type: integer description: 'Memory swappiness.' limits_memory_reservation: type: string description: 'Memory reservation.' limits_cpus: type: string description: 'CPU limit.' limits_cpuset: type: string nullable: true description: 'CPU set.' limits_cpu_shares: type: integer description: 'CPU shares.' custom_labels: type: string description: 'Custom labels.' custom_docker_run_options: type: string description: 'Custom docker run options.' post_deployment_command: type: string description: 'Post deployment command.' post_deployment_command_container: type: string description: 'Post deployment command container.' pre_deployment_command: type: string description: 'Pre deployment command.' pre_deployment_command_container: type: string description: 'Pre deployment command container.' manual_webhook_secret_github: type: string description: 'Manual webhook secret for Github.' manual_webhook_secret_gitlab: type: string description: 'Manual webhook secret for Gitlab.' manual_webhook_secret_bitbucket: type: string description: 'Manual webhook secret for Bitbucket.' manual_webhook_secret_gitea: type: string description: 'Manual webhook secret for Gitea.' redirect: type: string nullable: true description: 'How to set redirect with Traefik / Caddy. www<->non-www.' enum: [www, non-www, both] instant_deploy: type: boolean description: 'The flag to indicate if the application should be deployed instantly.' is_force_https_enabled: type: boolean description: 'The flag to indicate if HTTPS is forced. Defaults to true.' use_build_server: type: boolean nullable: true description: 'Use build server.' is_http_basic_auth_enabled: type: boolean description: 'HTTP Basic Authentication enabled.' http_basic_auth_username: type: string nullable: true description: 'Username for HTTP Basic Authentication' http_basic_auth_password: type: string nullable: true description: 'Password for HTTP Basic Authentication' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' force_domain_override: type: boolean description: 'Force domain usage even if conflicts are detected. Default is false.' autogenerate_domain: type: boolean default: true description: "If true and domains is empty, auto-generate a domain using the server's wildcard domain or sslip.io fallback. Default: true." is_container_label_escape_enabled: type: boolean default: true description: 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.' type: object responses: '201': description: 'Application created successfully.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object security: - bearerAuth: [] /applications/dockercompose: post: tags: - Applications summary: 'Create (Docker Compose)' description: 'Deprecated: Use POST /api/v1/services instead.' operationId: create-dockercompose-application requestBody: description: 'Application object that needs to be created.' required: true content: application/json: schema: required: - project_uuid - server_uuid - environment_name - environment_uuid - docker_compose_raw properties: project_uuid: type: string description: 'The project UUID.' server_uuid: type: string description: 'The server UUID.' environment_name: type: string description: 'The environment name. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'The environment UUID. You need to provide at least one of environment_name or environment_uuid.' docker_compose_raw: type: string description: 'The Docker Compose raw content.' destination_uuid: type: string description: 'The destination UUID if the server has more than one destinations.' name: type: string description: 'The application name.' description: type: string description: 'The application description.' instant_deploy: type: boolean description: 'The flag to indicate if the application should be deployed instantly.' use_build_server: type: boolean nullable: true description: 'Use build server.' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' force_domain_override: type: boolean description: 'Force domain usage even if conflicts are detected. Default is false.' is_container_label_escape_enabled: type: boolean default: true description: 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.' type: object responses: '201': description: 'Application created successfully.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object deprecated: true security: - bearerAuth: [] '/applications/{uuid}': get: tags: - Applications summary: Get description: 'Get application by UUID.' operationId: get-application-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string responses: '200': description: 'Get application by UUID.' content: application/json: schema: $ref: '#/components/schemas/Application' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - Applications summary: Delete description: 'Delete application by UUID.' operationId: delete-application-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: delete_configurations in: query description: 'Delete configurations.' required: false schema: type: boolean default: true - name: delete_volumes in: query description: 'Delete volumes.' required: false schema: type: boolean default: true - name: docker_cleanup in: query description: 'Run docker cleanup.' required: false schema: type: boolean default: true - name: delete_connected_networks in: query description: 'Delete connected networks.' required: false schema: type: boolean default: true responses: '200': description: 'Application deleted.' content: application/json: schema: properties: message: { type: string, example: 'Application deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Applications summary: Update description: 'Update application by UUID.' operationId: update-application-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string requestBody: description: 'Application updated.' required: true content: application/json: schema: properties: project_uuid: type: string description: 'The project UUID.' server_uuid: type: string description: 'The server UUID.' environment_name: type: string description: 'The environment name.' github_app_uuid: type: string description: 'The Github App UUID.' git_repository: type: string description: 'The git repository URL.' git_branch: type: string description: 'The git branch.' ports_exposes: type: string description: 'The ports to expose.' destination_uuid: type: string description: 'The destination UUID.' build_pack: type: string enum: [nixpacks, static, dockerfile, dockercompose] description: 'The build pack type.' name: type: string description: 'The application name.' description: type: string description: 'The application description.' domains: type: string description: 'The application URLs in a comma-separated list.' git_commit_sha: type: string description: 'The git commit SHA.' docker_registry_image_name: type: string description: 'The docker registry image name.' docker_registry_image_tag: type: string description: 'The docker registry image tag.' is_static: type: boolean description: 'The flag to indicate if the application is static.' is_spa: type: boolean description: 'The flag to indicate if the application is a single-page application (SPA). Only relevant when is_static is true.' is_auto_deploy_enabled: type: boolean description: 'The flag to indicate if auto-deploy is enabled on git push. Defaults to true.' is_force_https_enabled: type: boolean description: 'The flag to indicate if HTTPS is forced. Defaults to true.' install_command: type: string description: 'The install command.' build_command: type: string description: 'The build command.' start_command: type: string description: 'The start command.' ports_mappings: type: string description: 'The ports mappings.' base_directory: type: string description: 'The base directory for all commands.' publish_directory: type: string description: 'The publish directory.' health_check_enabled: type: boolean description: 'Health check enabled.' health_check_path: type: string description: 'Health check path.' health_check_port: type: string nullable: true description: 'Health check port.' health_check_host: type: string nullable: true description: 'Health check host.' health_check_method: type: string description: 'Health check method.' health_check_return_code: type: integer description: 'Health check return code.' health_check_scheme: type: string description: 'Health check scheme.' health_check_response_text: type: string nullable: true description: 'Health check response text.' health_check_interval: type: integer description: 'Health check interval in seconds.' health_check_timeout: type: integer description: 'Health check timeout in seconds.' health_check_retries: type: integer description: 'Health check retries count.' health_check_start_period: type: integer description: 'Health check start period in seconds.' limits_memory: type: string description: 'Memory limit.' limits_memory_swap: type: string description: 'Memory swap limit.' limits_memory_swappiness: type: integer description: 'Memory swappiness.' limits_memory_reservation: type: string description: 'Memory reservation.' limits_cpus: type: string description: 'CPU limit.' limits_cpuset: type: string nullable: true description: 'CPU set.' limits_cpu_shares: type: integer description: 'CPU shares.' custom_labels: type: string description: 'Custom labels.' custom_docker_run_options: type: string description: 'Custom docker run options.' post_deployment_command: type: string description: 'Post deployment command.' post_deployment_command_container: type: string description: 'Post deployment command container.' pre_deployment_command: type: string description: 'Pre deployment command.' pre_deployment_command_container: type: string description: 'Pre deployment command container.' manual_webhook_secret_github: type: string description: 'Manual webhook secret for Github.' manual_webhook_secret_gitlab: type: string description: 'Manual webhook secret for Gitlab.' manual_webhook_secret_bitbucket: type: string description: 'Manual webhook secret for Bitbucket.' manual_webhook_secret_gitea: type: string description: 'Manual webhook secret for Gitea.' redirect: type: string nullable: true description: 'How to set redirect with Traefik / Caddy. www<->non-www.' enum: [www, non-www, both] instant_deploy: type: boolean description: 'The flag to indicate if the application should be deployed instantly.' dockerfile: type: string description: 'The Dockerfile content.' dockerfile_location: type: string description: 'The Dockerfile location in the repository.' docker_compose_location: type: string description: 'The Docker Compose location.' docker_compose_custom_start_command: type: string description: 'The Docker Compose custom start command.' docker_compose_custom_build_command: type: string description: 'The Docker Compose custom build command.' docker_compose_domains: type: array description: 'Array of URLs to be applied to containers of a dockercompose application.' items: { properties: { name: { type: string, description: 'The service name as defined in docker-compose.' }, domain: { type: string, description: 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io")' } }, type: object } watch_paths: type: string description: 'The watch paths.' use_build_server: type: boolean nullable: true description: 'Use build server.' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' force_domain_override: type: boolean description: 'Force domain usage even if conflicts are detected. Default is false.' is_container_label_escape_enabled: type: boolean default: true description: 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.' type: object responses: '200': description: 'Application updated.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object security: - bearerAuth: [] '/applications/{uuid}/logs': get: tags: - Applications summary: 'Get application logs.' description: 'Get application logs by UUID.' operationId: get-application-logs-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: lines in: query description: 'Number of lines to show from the end of the logs.' required: false schema: type: integer format: int32 default: 100 responses: '200': description: 'Get application logs by UUID.' content: application/json: schema: properties: logs: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/applications/{uuid}/envs': get: tags: - Applications summary: 'List Envs' description: 'List all envs by application UUID.' operationId: list-envs-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string responses: '200': description: 'All environment variables by application UUID.' content: application/json: schema: type: array items: $ref: '#/components/schemas/EnvironmentVariable' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] post: tags: - Applications summary: 'Create Env' description: 'Create env by application UUID.' operationId: create-env-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string requestBody: description: 'Env created.' required: true content: application/json: schema: properties: key: type: string description: 'The key of the environment variable.' value: type: string description: 'The value of the environment variable.' is_preview: type: boolean description: 'The flag to indicate if the environment variable is used in preview deployments.' is_literal: type: boolean description: 'The flag to indicate if the environment variable is a literal, nothing espaced.' is_multiline: type: boolean description: 'The flag to indicate if the environment variable is multiline.' is_shown_once: type: boolean description: "The flag to indicate if the environment variable's value is shown on the UI." type: object responses: '201': description: 'Environment variable created.' content: application/json: schema: properties: uuid: { type: string, example: nc0k04gk8g0cgsk440g0koko } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Applications summary: 'Update Env' description: 'Update env by application UUID.' operationId: update-env-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string requestBody: description: 'Env updated.' required: true content: application/json: schema: required: - key - value properties: key: type: string description: 'The key of the environment variable.' value: type: string description: 'The value of the environment variable.' is_preview: type: boolean description: 'The flag to indicate if the environment variable is used in preview deployments.' is_literal: type: boolean description: 'The flag to indicate if the environment variable is a literal, nothing espaced.' is_multiline: type: boolean description: 'The flag to indicate if the environment variable is multiline.' is_shown_once: type: boolean description: "The flag to indicate if the environment variable's value is shown on the UI." type: object responses: '201': description: 'Environment variable updated.' content: application/json: schema: $ref: '#/components/schemas/EnvironmentVariable' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/applications/{uuid}/envs/bulk': patch: tags: - Applications summary: 'Update Envs (Bulk)' description: 'Update multiple envs by application UUID.' operationId: update-envs-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string requestBody: description: 'Bulk envs updated.' required: true content: application/json: schema: required: - data properties: data: type: array items: { properties: { key: { type: string, description: 'The key of the environment variable.' }, value: { type: string, description: 'The value of the environment variable.' }, is_preview: { type: boolean, description: 'The flag to indicate if the environment variable is used in preview deployments.' }, is_literal: { type: boolean, description: 'The flag to indicate if the environment variable is a literal, nothing espaced.' }, is_multiline: { type: boolean, description: 'The flag to indicate if the environment variable is multiline.' }, is_shown_once: { type: boolean, description: "The flag to indicate if the environment variable's value is shown on the UI." } }, type: object } type: object responses: '201': description: 'Environment variables updated.' content: application/json: schema: type: array items: $ref: '#/components/schemas/EnvironmentVariable' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/applications/{uuid}/envs/{env_uuid}': delete: tags: - Applications summary: 'Delete Env' description: 'Delete env by UUID.' operationId: delete-env-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: env_uuid in: path description: 'UUID of the environment variable.' required: true schema: type: string responses: '200': description: 'Environment variable deleted.' content: application/json: schema: properties: message: { type: string, example: 'Environment variable deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/applications/{uuid}/start': get: tags: - Applications summary: Start description: 'Start application. `Post` request is also accepted.' operationId: start-application-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: force in: query description: 'Force rebuild.' schema: type: boolean default: false - name: instant_deploy in: query description: 'Instant deploy (skip queuing).' schema: type: boolean default: false responses: '200': description: 'Start application.' content: application/json: schema: properties: message: { type: string, example: 'Deployment request queued.', description: Message. } deployment_uuid: { type: string, example: doogksw, description: 'UUID of the deployment.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/applications/{uuid}/stop': get: tags: - Applications summary: Stop description: 'Stop application. `Post` request is also accepted.' operationId: stop-application-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: docker_cleanup in: query description: 'Perform docker cleanup (prune networks, volumes, etc.).' schema: type: boolean default: true responses: '200': description: 'Stop application.' content: application/json: schema: properties: message: { type: string, example: 'Application stopping request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/applications/{uuid}/restart': get: tags: - Applications summary: Restart description: 'Restart application. `Post` request is also accepted.' operationId: restart-application-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string responses: '200': description: 'Restart application.' content: application/json: schema: properties: message: { type: string, example: 'Restart request queued.' } deployment_uuid: { type: string, example: doogksw, description: 'UUID of the deployment.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /cloud-tokens: get: tags: - 'Cloud Tokens' summary: 'List Cloud Provider Tokens' description: 'List all cloud provider tokens for the authenticated team.' operationId: list-cloud-tokens responses: '200': description: 'Get all cloud provider tokens.' content: application/json: schema: type: array items: properties: { uuid: { type: string }, name: { type: string }, provider: { type: string, enum: [hetzner, digitalocean] }, team_id: { type: integer }, servers_count: { type: integer }, created_at: { type: string }, updated_at: { type: string } } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] post: tags: - 'Cloud Tokens' summary: 'Create Cloud Provider Token' description: 'Create a new cloud provider token. The token will be validated before being stored.' operationId: create-cloud-token requestBody: description: 'Cloud provider token details' required: true content: application/json: schema: required: - provider - token - name properties: provider: type: string enum: [hetzner, digitalocean] example: hetzner description: 'The cloud provider.' token: type: string example: your-api-token-here description: 'The API token for the cloud provider.' name: type: string example: 'My Hetzner Token' description: 'A friendly name for the token.' type: object responses: '201': description: 'Cloud provider token created.' content: application/json: schema: properties: uuid: { type: string, example: og888os, description: 'The UUID of the token.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/cloud-tokens/{uuid}': get: tags: - 'Cloud Tokens' summary: 'Get Cloud Provider Token' description: 'Get cloud provider token by UUID.' operationId: get-cloud-token-by-uuid parameters: - name: uuid in: path description: 'Token UUID' required: true schema: type: string responses: '200': description: 'Get cloud provider token by UUID' content: application/json: schema: properties: uuid: { type: string } name: { type: string } provider: { type: string } team_id: { type: integer } servers_count: { type: integer } created_at: { type: string } updated_at: { type: string } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - 'Cloud Tokens' summary: 'Delete Cloud Provider Token' description: 'Delete cloud provider token by UUID. Cannot delete if token is used by any servers.' operationId: delete-cloud-token-by-uuid parameters: - name: uuid in: path description: 'UUID of the cloud provider token.' required: true schema: type: string responses: '200': description: 'Cloud provider token deleted.' content: application/json: schema: properties: message: { type: string, example: 'Cloud provider token deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - 'Cloud Tokens' summary: 'Update Cloud Provider Token' description: 'Update cloud provider token name.' operationId: update-cloud-token-by-uuid parameters: - name: uuid in: path description: 'Token UUID' required: true schema: type: string requestBody: description: 'Cloud provider token updated.' required: true content: application/json: schema: properties: name: type: string description: 'The friendly name for the token.' type: object responses: '200': description: 'Cloud provider token updated.' content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/cloud-tokens/{uuid}/validate': post: tags: - 'Cloud Tokens' summary: 'Validate Cloud Provider Token' description: 'Validate a cloud provider token against the provider API.' operationId: validate-cloud-token-by-uuid parameters: - name: uuid in: path description: 'Token UUID' required: true schema: type: string responses: '200': description: 'Token validation result.' content: application/json: schema: properties: valid: { type: boolean, example: true } message: { type: string, example: 'Token is valid.' } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /databases: get: tags: - Databases summary: List description: 'List all databases.' operationId: list-databases responses: '200': description: 'Get all databases' content: application/json: schema: type: string example: 'Content is very complex. Will be implemented later.' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] '/databases/{uuid}/backups': get: tags: - Databases summary: Get description: 'Get backups details by database UUID.' operationId: get-database-backups-by-uuid parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string responses: '200': description: 'Get all backups for a database' content: application/json: schema: type: string example: 'Content is very complex. Will be implemented later.' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] post: tags: - Databases summary: 'Create Backup' description: 'Create a new scheduled backup configuration for a database' operationId: create-database-backup parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string requestBody: description: 'Backup configuration data' required: true content: application/json: schema: required: - frequency properties: frequency: type: string description: 'Backup frequency (cron expression or: every_minute, hourly, daily, weekly, monthly, yearly)' enabled: type: boolean description: 'Whether the backup is enabled' default: true save_s3: type: boolean description: 'Whether to save backups to S3' default: false s3_storage_uuid: type: string description: 'S3 storage UUID (required if save_s3 is true)' databases_to_backup: type: string description: 'Comma separated list of databases to backup' dump_all: type: boolean description: 'Whether to dump all databases' default: false backup_now: type: boolean description: 'Whether to trigger backup immediately after creation' database_backup_retention_amount_locally: type: integer description: 'Number of backups to retain locally' database_backup_retention_days_locally: type: integer description: 'Number of days to retain backups locally' database_backup_retention_max_storage_locally: type: integer description: 'Max storage (MB) for local backups' database_backup_retention_amount_s3: type: integer description: 'Number of backups to retain in S3' database_backup_retention_days_s3: type: integer description: 'Number of days to retain backups in S3' database_backup_retention_max_storage_s3: type: integer description: 'Max storage (MB) for S3 backups' type: object responses: '201': description: 'Backup configuration created successfully' content: application/json: schema: properties: uuid: { type: string, format: uuid, example: 550e8400-e29b-41d4-a716-446655440000 } message: { type: string, example: 'Backup configuration created successfully.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/databases/{uuid}': get: tags: - Databases summary: Get description: 'Get database by UUID.' operationId: get-database-by-uuid parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string responses: '200': description: 'Get all databases' content: application/json: schema: type: string example: 'Content is very complex. Will be implemented later.' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - Databases summary: Delete description: 'Delete database by UUID.' operationId: delete-database-by-uuid parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string - name: delete_configurations in: query description: 'Delete configurations.' required: false schema: type: boolean default: true - name: delete_volumes in: query description: 'Delete volumes.' required: false schema: type: boolean default: true - name: docker_cleanup in: query description: 'Run docker cleanup.' required: false schema: type: boolean default: true - name: delete_connected_networks in: query description: 'Delete connected networks.' required: false schema: type: boolean default: true responses: '200': description: 'Database deleted.' content: application/json: schema: properties: message: { type: string, example: 'Database deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Databases summary: Update description: 'Update database by UUID.' operationId: update-database-by-uuid parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string requestBody: description: 'Database data' required: true content: application/json: schema: properties: name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' postgres_user: type: string description: 'PostgreSQL user' postgres_password: type: string description: 'PostgreSQL password' postgres_db: type: string description: 'PostgreSQL database' postgres_initdb_args: type: string description: 'PostgreSQL initdb args' postgres_host_auth_method: type: string description: 'PostgreSQL host auth method' postgres_conf: type: string description: 'PostgreSQL conf' clickhouse_admin_user: type: string description: 'Clickhouse admin user' clickhouse_admin_password: type: string description: 'Clickhouse admin password' dragonfly_password: type: string description: 'DragonFly password' redis_password: type: string description: 'Redis password' redis_conf: type: string description: 'Redis conf' keydb_password: type: string description: 'KeyDB password' keydb_conf: type: string description: 'KeyDB conf' mariadb_conf: type: string description: 'MariaDB conf' mariadb_root_password: type: string description: 'MariaDB root password' mariadb_user: type: string description: 'MariaDB user' mariadb_password: type: string description: 'MariaDB password' mariadb_database: type: string description: 'MariaDB database' mongo_conf: type: string description: 'Mongo conf' mongo_initdb_root_username: type: string description: 'Mongo initdb root username' mongo_initdb_root_password: type: string description: 'Mongo initdb root password' mongo_initdb_database: type: string description: 'Mongo initdb init database' mysql_root_password: type: string description: 'MySQL root password' mysql_password: type: string description: 'MySQL password' mysql_user: type: string description: 'MySQL user' mysql_database: type: string description: 'MySQL database' mysql_conf: type: string description: 'MySQL conf' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/databases/{uuid}/backups/{scheduled_backup_uuid}': delete: tags: - Databases summary: 'Delete backup configuration' description: 'Deletes a backup configuration and all its executions.' operationId: delete-backup-configuration-by-uuid parameters: - name: uuid in: path description: 'UUID of the database' required: true schema: type: string - name: scheduled_backup_uuid in: path description: 'UUID of the backup configuration to delete' required: true schema: type: string - name: delete_s3 in: query description: 'Whether to delete all backup files from S3' required: false schema: type: boolean default: false responses: '200': description: 'Backup configuration deleted.' content: application/json: schema: properties: message: { type: string, example: 'Backup configuration and all executions deleted.' } type: object '404': description: 'Backup configuration not found.' content: application/json: schema: properties: message: { type: string, example: 'Backup configuration not found.' } type: object security: - bearerAuth: [] patch: tags: - Databases summary: Update description: 'Update a specific backup configuration for a given database, identified by its UUID and the backup ID' operationId: update-database-backup parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string - name: scheduled_backup_uuid in: path description: 'UUID of the backup configuration.' required: true schema: type: string requestBody: description: 'Database backup configuration data' required: true content: application/json: schema: properties: save_s3: type: boolean description: 'Whether data is saved in s3 or not' s3_storage_uuid: type: string description: 'S3 storage UUID' backup_now: type: boolean description: 'Whether to take a backup now or not' enabled: type: boolean description: 'Whether the backup is enabled or not' databases_to_backup: type: string description: 'Comma separated list of databases to backup' dump_all: type: boolean description: 'Whether all databases are dumped or not' frequency: type: string description: 'Frequency of the backup' database_backup_retention_amount_locally: type: integer description: 'Retention amount of the backup locally' database_backup_retention_days_locally: type: integer description: 'Retention days of the backup locally' database_backup_retention_max_storage_locally: type: integer description: 'Max storage of the backup locally' database_backup_retention_amount_s3: type: integer description: 'Retention amount of the backup in s3' database_backup_retention_days_s3: type: integer description: 'Retention days of the backup in s3' database_backup_retention_max_storage_s3: type: integer description: 'Max storage of the backup in S3' type: object responses: '200': description: 'Database backup configuration updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/postgresql: post: tags: - Databases summary: 'Create (PostgreSQL)' description: 'Create a new PostgreSQL database.' operationId: create-database-postgresql requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' postgres_user: type: string description: 'PostgreSQL user' postgres_password: type: string description: 'PostgreSQL password' postgres_db: type: string description: 'PostgreSQL database' postgres_initdb_args: type: string description: 'PostgreSQL initdb args' postgres_host_auth_method: type: string description: 'PostgreSQL host auth method' postgres_conf: type: string description: 'PostgreSQL conf' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/clickhouse: post: tags: - Databases summary: 'Create (Clickhouse)' description: 'Create a new Clickhouse database.' operationId: create-database-clickhouse requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' clickhouse_admin_user: type: string description: 'Clickhouse admin user' clickhouse_admin_password: type: string description: 'Clickhouse admin password' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/dragonfly: post: tags: - Databases summary: 'Create (DragonFly)' description: 'Create a new DragonFly database.' operationId: create-database-dragonfly requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' dragonfly_password: type: string description: 'DragonFly password' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/redis: post: tags: - Databases summary: 'Create (Redis)' description: 'Create a new Redis database.' operationId: create-database-redis requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' redis_password: type: string description: 'Redis password' redis_conf: type: string description: 'Redis conf' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/keydb: post: tags: - Databases summary: 'Create (KeyDB)' description: 'Create a new KeyDB database.' operationId: create-database-keydb requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' keydb_password: type: string description: 'KeyDB password' keydb_conf: type: string description: 'KeyDB conf' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/mariadb: post: tags: - Databases summary: 'Create (MariaDB)' description: 'Create a new MariaDB database.' operationId: create-database-mariadb requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' mariadb_conf: type: string description: 'MariaDB conf' mariadb_root_password: type: string description: 'MariaDB root password' mariadb_user: type: string description: 'MariaDB user' mariadb_password: type: string description: 'MariaDB password' mariadb_database: type: string description: 'MariaDB database' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/mysql: post: tags: - Databases summary: 'Create (MySQL)' description: 'Create a new MySQL database.' operationId: create-database-mysql requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' mysql_root_password: type: string description: 'MySQL root password' mysql_password: type: string description: 'MySQL password' mysql_user: type: string description: 'MySQL user' mysql_database: type: string description: 'MySQL database' mysql_conf: type: string description: 'MySQL conf' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /databases/mongodb: post: tags: - Databases summary: 'Create (MongoDB)' description: 'Create a new MongoDB database.' operationId: create-database-mongodb requestBody: description: 'Database data' required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: server_uuid: type: string description: 'UUID of the server' project_uuid: type: string description: 'UUID of the project' environment_name: type: string description: 'Name of the environment. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'UUID of the environment. You need to provide at least one of environment_name or environment_uuid.' destination_uuid: type: string description: 'UUID of the destination if the server has multiple destinations' mongo_conf: type: string description: 'MongoDB conf' mongo_initdb_root_username: type: string description: 'MongoDB initdb root username' name: type: string description: 'Name of the database' description: type: string description: 'Description of the database' image: type: string description: 'Docker Image of the database' is_public: type: boolean description: 'Is the database public?' public_port: type: integer description: 'Public port of the database' limits_memory: type: string description: 'Memory limit of the database' limits_memory_swap: type: string description: 'Memory swap limit of the database' limits_memory_swappiness: type: integer description: 'Memory swappiness of the database' limits_memory_reservation: type: string description: 'Memory reservation of the database' limits_cpus: type: string description: 'CPU limit of the database' limits_cpuset: type: string description: 'CPU set of the database' limits_cpu_shares: type: integer description: 'CPU shares of the database' instant_deploy: type: boolean description: 'Instant deploy the database' type: object responses: '200': description: 'Database updated' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/databases/{uuid}/backups/{scheduled_backup_uuid}/executions/{execution_uuid}': delete: tags: - Databases summary: 'Delete backup execution' description: 'Deletes a specific backup execution.' operationId: delete-backup-execution-by-uuid parameters: - name: uuid in: path description: 'UUID of the database' required: true schema: type: string - name: scheduled_backup_uuid in: path description: 'UUID of the backup configuration' required: true schema: type: string - name: execution_uuid in: path description: 'UUID of the backup execution to delete' required: true schema: type: string - name: delete_s3 in: query description: 'Whether to delete the backup from S3' required: false schema: type: boolean default: false responses: '200': description: 'Backup execution deleted.' content: application/json: schema: properties: message: { type: string, example: 'Backup execution deleted.' } type: object '404': description: 'Backup execution not found.' content: application/json: schema: properties: message: { type: string, example: 'Backup execution not found.' } type: object security: - bearerAuth: [] '/databases/{uuid}/backups/{scheduled_backup_uuid}/executions': get: tags: - Databases summary: 'List backup executions' description: 'Get all executions for a specific backup configuration.' operationId: list-backup-executions parameters: - name: uuid in: path description: 'UUID of the database' required: true schema: type: string - name: scheduled_backup_uuid in: path description: 'UUID of the backup configuration' required: true schema: type: string responses: '200': description: 'List of backup executions' content: application/json: schema: properties: executions: { type: array, items: { properties: { uuid: { type: string }, filename: { type: string }, size: { type: integer }, created_at: { type: string }, message: { type: string }, status: { type: string } }, type: object } } type: object '404': description: 'Backup configuration not found.' security: - bearerAuth: [] '/databases/{uuid}/start': get: tags: - Databases summary: Start description: 'Start database. `Post` request is also accepted.' operationId: start-database-by-uuid parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string responses: '200': description: 'Start database.' content: application/json: schema: properties: message: { type: string, example: 'Database starting request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/databases/{uuid}/stop': get: tags: - Databases summary: Stop description: 'Stop database. `Post` request is also accepted.' operationId: stop-database-by-uuid parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string - name: docker_cleanup in: query description: 'Perform docker cleanup (prune networks, volumes, etc.).' schema: type: boolean default: true responses: '200': description: 'Stop database.' content: application/json: schema: properties: message: { type: string, example: 'Database stopping request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/databases/{uuid}/restart': get: tags: - Databases summary: Restart description: 'Restart database. `Post` request is also accepted.' operationId: restart-database-by-uuid parameters: - name: uuid in: path description: 'UUID of the database.' required: true schema: type: string responses: '200': description: 'Restart database.' content: application/json: schema: properties: message: { type: string, example: 'Database restaring request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /deployments: get: tags: - Deployments summary: List description: 'List currently running deployments' operationId: list-deployments responses: '200': description: 'Get all currently running deployments.' content: application/json: schema: type: array items: $ref: '#/components/schemas/ApplicationDeploymentQueue' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] '/deployments/{uuid}': get: tags: - Deployments summary: Get description: 'Get deployment by UUID.' operationId: get-deployment-by-uuid parameters: - name: uuid in: path description: 'Deployment UUID' required: true schema: type: string responses: '200': description: 'Get deployment by UUID.' content: application/json: schema: $ref: '#/components/schemas/ApplicationDeploymentQueue' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/deployments/{uuid}/cancel': post: tags: - Deployments summary: Cancel description: 'Cancel a deployment by UUID.' operationId: cancel-deployment-by-uuid parameters: - name: uuid in: path description: 'Deployment UUID' required: true schema: type: string responses: '200': description: 'Deployment cancelled successfully.' content: application/json: schema: properties: message: { type: string, example: 'Deployment cancelled successfully.' } deployment_uuid: { type: string, example: cm37r6cqj000008jm0veg5tkm } status: { type: string, example: cancelled-by-user } type: object '400': description: 'Deployment cannot be cancelled (already finished/failed/cancelled).' content: application/json: schema: properties: message: { type: string, example: 'Deployment cannot be cancelled. Current status: finished' } type: object '401': $ref: '#/components/responses/401' '403': description: "User doesn't have permission to cancel this deployment." content: application/json: schema: properties: message: { type: string, example: 'You do not have permission to cancel this deployment.' } type: object '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /deploy: get: tags: - Deployments summary: Deploy description: 'Deploy by tag or uuid. `Post` request also accepted with `uuid` and `tag` json body.' operationId: deploy-by-tag-or-uuid parameters: - name: tag in: query description: 'Tag name(s). Comma separated list is also accepted.' schema: type: string - name: uuid in: query description: 'Resource UUID(s). Comma separated list is also accepted.' schema: type: string - name: force in: query description: 'Force rebuild (without cache)' schema: type: boolean - name: pr in: query description: 'Pull Request Id for deploying specific PR builds. Cannot be used with tag parameter.' schema: type: integer responses: '200': description: "Get deployment(s) UUID's" content: application/json: schema: properties: deployments: { type: array, items: { properties: { message: { type: string }, resource_uuid: { type: string }, deployment_uuid: { type: string } }, type: object } } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] '/deployments/applications/{uuid}': get: tags: - Deployments summary: 'List application deployments' description: 'List application deployments by using the app uuid' operationId: list-deployments-by-app-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: skip in: query description: 'Number of records to skip.' required: false schema: type: integer default: 0 minimum: 0 - name: take in: query description: 'Number of records to take.' required: false schema: type: integer default: 10 minimum: 1 responses: '200': description: 'List application deployments by using the app uuid.' content: application/json: schema: type: array items: $ref: '#/components/schemas/Application' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] /github-apps: get: tags: - 'GitHub Apps' summary: List description: 'List all GitHub apps.' operationId: list-github-apps responses: '200': description: 'List of GitHub apps.' content: application/json: schema: type: array items: properties: { id: { type: integer }, uuid: { type: string }, name: { type: string }, organization: { type: string, nullable: true }, api_url: { type: string }, html_url: { type: string }, custom_user: { type: string }, custom_port: { type: integer }, app_id: { type: integer }, installation_id: { type: integer }, client_id: { type: string }, private_key_id: { type: integer }, is_system_wide: { type: boolean }, is_public: { type: boolean }, team_id: { type: integer }, type: { type: string } } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] post: tags: - 'GitHub Apps' summary: 'Create GitHub App' description: 'Create a new GitHub app.' operationId: create-github-app requestBody: description: 'GitHub app creation payload.' required: true content: application/json: schema: required: - name - api_url - html_url - app_id - installation_id - client_id - client_secret - private_key_uuid properties: name: type: string description: 'Name of the GitHub app.' organization: type: string nullable: true description: 'Organization to associate the app with.' api_url: type: string description: 'API URL for the GitHub app (e.g., https://api.github.com).' html_url: type: string description: 'HTML URL for the GitHub app (e.g., https://github.com).' custom_user: type: string description: 'Custom user for SSH access (default: git).' custom_port: type: integer description: 'Custom port for SSH access (default: 22).' app_id: type: integer description: 'GitHub App ID from GitHub.' installation_id: type: integer description: 'GitHub Installation ID.' client_id: type: string description: 'GitHub OAuth App Client ID.' client_secret: type: string description: 'GitHub OAuth App Client Secret.' webhook_secret: type: string description: 'Webhook secret for GitHub webhooks.' private_key_uuid: type: string description: 'UUID of an existing private key for GitHub App authentication.' is_system_wide: type: boolean description: 'Is this app system-wide (cloud only).' type: object responses: '201': description: 'GitHub app created successfully.' content: application/json: schema: properties: id: { type: integer } uuid: { type: string } name: { type: string } organization: { type: string, nullable: true } api_url: { type: string } html_url: { type: string } custom_user: { type: string } custom_port: { type: integer } app_id: { type: integer } installation_id: { type: integer } client_id: { type: string } private_key_id: { type: integer } is_system_wide: { type: boolean } team_id: { type: integer } type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/github-apps/{github_app_id}/repositories': get: tags: - 'GitHub Apps' summary: 'Load Repositories for a GitHub App' description: 'Fetch repositories from GitHub for a given GitHub app.' operationId: load-repositories parameters: - name: github_app_id in: path description: 'GitHub App ID' required: true schema: type: integer responses: '200': description: 'Repositories loaded successfully.' content: application/json: schema: properties: repositories: { type: array, items: { type: object } } type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/github-apps/{github_app_id}/repositories/{owner}/{repo}/branches': get: tags: - 'GitHub Apps' summary: 'Load Branches for a GitHub Repository' description: 'Fetch branches from GitHub for a given repository.' operationId: load-branches parameters: - name: github_app_id in: path description: 'GitHub App ID' required: true schema: type: integer - name: owner in: path description: 'Repository owner' required: true schema: type: string - name: repo in: path description: 'Repository name' required: true schema: type: string responses: '200': description: 'Branches loaded successfully.' content: application/json: schema: properties: branches: { type: array, items: { type: object } } type: object '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/github-apps/{github_app_id}': delete: tags: - 'GitHub Apps' summary: 'Delete GitHub App' description: "Delete a GitHub app if it's not being used by any applications." operationId: deleteGithubApp parameters: - name: github_app_id in: path description: 'GitHub App ID' required: true schema: type: integer responses: '200': description: 'GitHub app deleted successfully' content: application/json: schema: properties: message: { type: string, example: 'GitHub app deleted successfully' } type: object '401': description: Unauthorized '404': description: 'GitHub app not found' '409': description: 'Conflict - GitHub app is in use' content: application/json: schema: properties: message: { type: string, example: 'This GitHub app is being used by 5 application(s). Please delete all applications first.' } type: object security: - bearerAuth: [] patch: tags: - 'GitHub Apps' summary: 'Update GitHub App' description: 'Update an existing GitHub app.' operationId: updateGithubApp parameters: - name: github_app_id in: path description: 'GitHub App ID' required: true schema: type: integer requestBody: required: true content: application/json: schema: properties: name: type: string description: 'GitHub App name' organization: type: string nullable: true description: 'GitHub organization' api_url: type: string description: 'GitHub API URL' html_url: type: string description: 'GitHub HTML URL' custom_user: type: string description: 'Custom user for SSH' custom_port: type: integer description: 'Custom port for SSH' app_id: type: integer description: 'GitHub App ID' installation_id: type: integer description: 'GitHub Installation ID' client_id: type: string description: 'GitHub Client ID' client_secret: type: string description: 'GitHub Client Secret' webhook_secret: type: string description: 'GitHub Webhook Secret' private_key_uuid: type: string description: 'Private key UUID' is_system_wide: type: boolean description: 'Is system wide (non-cloud instances only)' type: object responses: '200': description: 'GitHub app updated successfully' content: application/json: schema: properties: message: { type: string, example: 'GitHub app updated successfully' } data: { type: object, description: 'Updated GitHub app data' } type: object '401': description: Unauthorized '404': description: 'GitHub app not found' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /hetzner/locations: get: tags: - Hetzner summary: 'Get Hetzner Locations' description: 'Get all available Hetzner datacenter locations.' operationId: get-hetzner-locations parameters: - name: cloud_provider_token_uuid in: query description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.' required: false schema: type: string - name: cloud_provider_token_id in: query description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.' required: false deprecated: true schema: type: string responses: '200': description: 'List of Hetzner locations.' content: application/json: schema: type: array items: properties: { id: { type: integer }, name: { type: string }, description: { type: string }, country: { type: string }, city: { type: string }, latitude: { type: number }, longitude: { type: number } } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /hetzner/server-types: get: tags: - Hetzner summary: 'Get Hetzner Server Types' description: 'Get all available Hetzner server types (instance sizes).' operationId: get-hetzner-server-types parameters: - name: cloud_provider_token_uuid in: query description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.' required: false schema: type: string - name: cloud_provider_token_id in: query description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.' required: false deprecated: true schema: type: string responses: '200': description: 'List of Hetzner server types.' content: application/json: schema: type: array items: properties: { id: { type: integer }, name: { type: string }, description: { type: string }, cores: { type: integer }, memory: { type: number }, disk: { type: integer }, prices: { type: array, items: { type: object, properties: { location: { type: string, description: 'Datacenter location name' }, price_hourly: { type: object, properties: { net: { type: string }, gross: { type: string } } }, price_monthly: { type: object, properties: { net: { type: string }, gross: { type: string } } } } } } } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /hetzner/images: get: tags: - Hetzner summary: 'Get Hetzner Images' description: 'Get all available Hetzner system images (operating systems).' operationId: get-hetzner-images parameters: - name: cloud_provider_token_uuid in: query description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.' required: false schema: type: string - name: cloud_provider_token_id in: query description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.' required: false deprecated: true schema: type: string responses: '200': description: 'List of Hetzner images.' content: application/json: schema: type: array items: properties: { id: { type: integer }, name: { type: string }, description: { type: string }, type: { type: string }, os_flavor: { type: string }, os_version: { type: string }, architecture: { type: string } } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /hetzner/ssh-keys: get: tags: - Hetzner summary: 'Get Hetzner SSH Keys' description: 'Get all SSH keys stored in the Hetzner account.' operationId: get-hetzner-ssh-keys parameters: - name: cloud_provider_token_uuid in: query description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.' required: false schema: type: string - name: cloud_provider_token_id in: query description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.' required: false deprecated: true schema: type: string responses: '200': description: 'List of Hetzner SSH keys.' content: application/json: schema: type: array items: properties: { id: { type: integer }, name: { type: string }, fingerprint: { type: string }, public_key: { type: string } } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /servers/hetzner: post: tags: - Hetzner summary: 'Create Hetzner Server' description: 'Create a new server on Hetzner and register it in Coolify.' operationId: create-hetzner-server requestBody: description: 'Hetzner server creation parameters' required: true content: application/json: schema: required: - location - server_type - image - private_key_uuid properties: cloud_provider_token_uuid: type: string example: abc123 description: 'Cloud provider token UUID. Required if cloud_provider_token_id is not provided.' cloud_provider_token_id: type: string example: abc123 description: 'Deprecated: Use cloud_provider_token_uuid instead. Cloud provider token UUID.' deprecated: true location: type: string example: nbg1 description: 'Hetzner location name' server_type: type: string example: cx11 description: 'Hetzner server type name' image: type: integer example: 15512617 description: 'Hetzner image ID' name: type: string example: my-server description: 'Server name (auto-generated if not provided)' private_key_uuid: type: string example: xyz789 description: 'Private key UUID' enable_ipv4: type: boolean example: true description: 'Enable IPv4 (default: true)' enable_ipv6: type: boolean example: true description: 'Enable IPv6 (default: true)' hetzner_ssh_key_ids: type: array items: { type: integer } description: 'Additional Hetzner SSH key IDs' cloud_init_script: type: string description: 'Cloud-init YAML script (optional)' instant_validate: type: boolean example: false description: 'Validate server immediately after creation' type: object responses: '201': description: 'Hetzner server created.' content: application/json: schema: properties: uuid: { type: string, example: og888os, description: 'The UUID of the server.' } hetzner_server_id: { type: integer, description: 'The Hetzner server ID.' } ip: { type: string, description: 'The server IP address.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' '429': $ref: '#/components/responses/429' security: - bearerAuth: [] /version: get: summary: Version description: 'Get Coolify version.' operationId: version responses: '200': description: 'Returns the version of the application' content: text/html: schema: type: string example: v4.0.0 '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] /enable: get: summary: 'Enable API' description: 'Enable API (only with root permissions).' operationId: enable-api responses: '200': description: 'Enable API.' content: application/json: schema: properties: message: { type: string, example: 'API enabled.' } type: object '403': description: 'You are not allowed to enable the API.' content: application/json: schema: properties: message: { type: string, example: 'You are not allowed to enable the API.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] /disable: get: summary: 'Disable API' description: 'Disable API (only with root permissions).' operationId: disable-api responses: '200': description: 'Disable API.' content: application/json: schema: properties: message: { type: string, example: 'API disabled.' } type: object '403': description: 'You are not allowed to disable the API.' content: application/json: schema: properties: message: { type: string, example: 'You are not allowed to disable the API.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] /health: get: summary: Healthcheck description: 'Healthcheck endpoint.' operationId: healthcheck responses: '200': description: 'Healthcheck endpoint.' content: text/html: schema: type: string example: OK '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' /projects: get: tags: - Projects summary: List description: 'List projects.' operationId: list-projects responses: '200': description: 'Get all projects.' content: application/json: schema: type: array items: $ref: '#/components/schemas/Project' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] post: tags: - Projects summary: Create description: 'Create Project.' operationId: create-project requestBody: description: 'Project created.' required: true content: application/json: schema: properties: name: type: string description: 'The name of the project.' description: type: string description: 'The description of the project.' type: object responses: '201': description: 'Project created.' content: application/json: schema: properties: uuid: { type: string, example: og888os, description: 'The UUID of the project.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/projects/{uuid}': get: tags: - Projects summary: Get description: 'Get project by UUID.' operationId: get-project-by-uuid parameters: - name: uuid in: path description: 'Project UUID' required: true schema: type: string responses: '200': description: 'Project details' content: application/json: schema: $ref: '#/components/schemas/Project' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': description: 'Project not found.' security: - bearerAuth: [] delete: tags: - Projects summary: Delete description: 'Delete project by UUID.' operationId: delete-project-by-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string responses: '200': description: 'Project deleted.' content: application/json: schema: properties: message: { type: string, example: 'Project deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] patch: tags: - Projects summary: Update description: 'Update Project.' operationId: update-project-by-uuid parameters: - name: uuid in: path description: 'UUID of the project.' required: true schema: type: string requestBody: description: 'Project updated.' required: true content: application/json: schema: properties: name: type: string description: 'The name of the project.' description: type: string description: 'The description of the project.' type: object responses: '201': description: 'Project updated.' content: application/json: schema: properties: uuid: { type: string, example: og888os } name: { type: string, example: 'Project Name' } description: { type: string, example: 'Project Description' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/projects/{uuid}/{environment_name_or_uuid}': get: tags: - Projects summary: Environment description: 'Get environment by name or UUID.' operationId: get-environment-by-name-or-uuid parameters: - name: uuid in: path description: 'Project UUID' required: true schema: type: string - name: environment_name_or_uuid in: path description: 'Environment name or UUID' required: true schema: type: string responses: '200': description: 'Environment details' content: application/json: schema: $ref: '#/components/schemas/Environment' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/projects/{uuid}/environments': get: tags: - Projects summary: 'List Environments' description: 'List all environments in a project.' operationId: get-environments parameters: - name: uuid in: path description: 'Project UUID' required: true schema: type: string responses: '200': description: 'List of environments' content: application/json: schema: type: array items: $ref: '#/components/schemas/Environment' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': description: 'Project not found.' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] post: tags: - Projects summary: 'Create Environment' description: 'Create environment in project.' operationId: create-environment parameters: - name: uuid in: path description: 'Project UUID' required: true schema: type: string requestBody: description: 'Environment created.' required: true content: application/json: schema: properties: name: type: string description: 'The name of the environment.' type: object responses: '201': description: 'Environment created.' content: application/json: schema: properties: uuid: { type: string, example: env123, description: 'The UUID of the environment.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': description: 'Project not found.' '409': description: 'Environment with this name already exists.' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/projects/{uuid}/environments/{environment_name_or_uuid}': delete: tags: - Projects summary: 'Delete Environment' description: 'Delete environment by name or UUID. Environment must be empty.' operationId: delete-environment parameters: - name: uuid in: path description: 'Project UUID' required: true schema: type: string - name: environment_name_or_uuid in: path description: 'Environment name or UUID' required: true schema: type: string responses: '200': description: 'Environment deleted.' content: application/json: schema: properties: message: { type: string, example: 'Environment deleted.' } type: object '401': $ref: '#/components/responses/401' '400': description: 'Environment has resources, so it cannot be deleted.' '404': description: 'Project or environment not found.' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /resources: get: tags: - Resources summary: List description: 'Get all resources.' operationId: list-resources responses: '200': description: 'Get all resources' content: application/json: schema: type: string example: 'Content is very complex. Will be implemented later.' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] '/applications/{uuid}/scheduled-tasks': get: tags: - 'Scheduled Tasks' summary: 'List Tasks' description: 'List all scheduled tasks for an application.' operationId: list-scheduled-tasks-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string responses: '200': description: 'Get all scheduled tasks for an application.' content: application/json: schema: type: array items: $ref: '#/components/schemas/ScheduledTask' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] post: tags: - 'Scheduled Tasks' summary: 'Create Task' description: 'Create a new scheduled task for an application.' operationId: create-scheduled-task-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string requestBody: description: 'Scheduled task data' required: true content: application/json: schema: required: - name - command - frequency properties: name: type: string description: 'The name of the scheduled task.' command: type: string description: 'The command to execute.' frequency: type: string description: 'The frequency of the scheduled task.' container: type: string nullable: true description: 'The container where the command should be executed.' timeout: type: integer description: 'The timeout of the scheduled task in seconds.' default: 300 enabled: type: boolean description: 'The flag to indicate if the scheduled task is enabled.' default: true type: object responses: '201': description: 'Scheduled task created.' content: application/json: schema: $ref: '#/components/schemas/ScheduledTask' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/applications/{uuid}/scheduled-tasks/{task_uuid}': delete: tags: - 'Scheduled Tasks' summary: 'Delete Task' description: 'Delete a scheduled task for an application.' operationId: delete-scheduled-task-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: task_uuid in: path description: 'UUID of the scheduled task.' required: true schema: type: string responses: '200': description: 'Scheduled task deleted.' content: application/json: schema: properties: message: { type: string, example: 'Scheduled task deleted.' } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - 'Scheduled Tasks' summary: 'Update Task' description: 'Update a scheduled task for an application.' operationId: update-scheduled-task-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: task_uuid in: path description: 'UUID of the scheduled task.' required: true schema: type: string requestBody: description: 'Scheduled task data' required: true content: application/json: schema: properties: name: type: string description: 'The name of the scheduled task.' command: type: string description: 'The command to execute.' frequency: type: string description: 'The frequency of the scheduled task.' container: type: string nullable: true description: 'The container where the command should be executed.' timeout: type: integer description: 'The timeout of the scheduled task in seconds.' default: 300 enabled: type: boolean description: 'The flag to indicate if the scheduled task is enabled.' default: true type: object responses: '200': description: 'Scheduled task updated.' content: application/json: schema: $ref: '#/components/schemas/ScheduledTask' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/applications/{uuid}/scheduled-tasks/{task_uuid}/executions': get: tags: - 'Scheduled Tasks' summary: 'List Executions' description: 'List all executions for a scheduled task on an application.' operationId: list-scheduled-task-executions-by-application-uuid parameters: - name: uuid in: path description: 'UUID of the application.' required: true schema: type: string - name: task_uuid in: path description: 'UUID of the scheduled task.' required: true schema: type: string responses: '200': description: 'Get all executions for a scheduled task.' content: application/json: schema: type: array items: $ref: '#/components/schemas/ScheduledTaskExecution' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/services/{uuid}/scheduled-tasks': get: tags: - 'Scheduled Tasks' summary: 'List Tasks' description: 'List all scheduled tasks for a service.' operationId: list-scheduled-tasks-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string responses: '200': description: 'Get all scheduled tasks for a service.' content: application/json: schema: type: array items: $ref: '#/components/schemas/ScheduledTask' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] post: tags: - 'Scheduled Tasks' summary: 'Create Task' description: 'Create a new scheduled task for a service.' operationId: create-scheduled-task-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string requestBody: description: 'Scheduled task data' required: true content: application/json: schema: required: - name - command - frequency properties: name: type: string description: 'The name of the scheduled task.' command: type: string description: 'The command to execute.' frequency: type: string description: 'The frequency of the scheduled task.' container: type: string nullable: true description: 'The container where the command should be executed.' timeout: type: integer description: 'The timeout of the scheduled task in seconds.' default: 300 enabled: type: boolean description: 'The flag to indicate if the scheduled task is enabled.' default: true type: object responses: '201': description: 'Scheduled task created.' content: application/json: schema: $ref: '#/components/schemas/ScheduledTask' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/services/{uuid}/scheduled-tasks/{task_uuid}': delete: tags: - 'Scheduled Tasks' summary: 'Delete Task' description: 'Delete a scheduled task for a service.' operationId: delete-scheduled-task-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string - name: task_uuid in: path description: 'UUID of the scheduled task.' required: true schema: type: string responses: '200': description: 'Scheduled task deleted.' content: application/json: schema: properties: message: { type: string, example: 'Scheduled task deleted.' } type: object '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - 'Scheduled Tasks' summary: 'Update Task' description: 'Update a scheduled task for a service.' operationId: update-scheduled-task-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string - name: task_uuid in: path description: 'UUID of the scheduled task.' required: true schema: type: string requestBody: description: 'Scheduled task data' required: true content: application/json: schema: properties: name: type: string description: 'The name of the scheduled task.' command: type: string description: 'The command to execute.' frequency: type: string description: 'The frequency of the scheduled task.' container: type: string nullable: true description: 'The container where the command should be executed.' timeout: type: integer description: 'The timeout of the scheduled task in seconds.' default: 300 enabled: type: boolean description: 'The flag to indicate if the scheduled task is enabled.' default: true type: object responses: '200': description: 'Scheduled task updated.' content: application/json: schema: $ref: '#/components/schemas/ScheduledTask' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/services/{uuid}/scheduled-tasks/{task_uuid}/executions': get: tags: - 'Scheduled Tasks' summary: 'List Executions' description: 'List all executions for a scheduled task on a service.' operationId: list-scheduled-task-executions-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string - name: task_uuid in: path description: 'UUID of the scheduled task.' required: true schema: type: string responses: '200': description: 'Get all executions for a scheduled task.' content: application/json: schema: type: array items: $ref: '#/components/schemas/ScheduledTaskExecution' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /security/keys: get: tags: - 'Private Keys' summary: List description: 'List all private keys.' operationId: list-private-keys responses: '200': description: 'Get all private keys.' content: application/json: schema: type: array items: $ref: '#/components/schemas/PrivateKey' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] post: tags: - 'Private Keys' summary: Create description: 'Create a new private key.' operationId: create-private-key requestBody: required: true content: application/json: schema: required: - private_key properties: name: type: string description: type: string private_key: type: string type: object additionalProperties: false responses: '201': description: "The created private key's UUID." content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] patch: tags: - 'Private Keys' summary: Update description: 'Update a private key.' operationId: update-private-key requestBody: required: true content: application/json: schema: required: - private_key properties: name: type: string description: type: string private_key: type: string type: object additionalProperties: false responses: '201': description: "The updated private key's UUID." content: application/json: schema: properties: uuid: { type: string } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/security/keys/{uuid}': get: tags: - 'Private Keys' summary: Get description: 'Get key by UUID.' operationId: get-private-key-by-uuid parameters: - name: uuid in: path description: 'Private Key UUID' required: true schema: type: string responses: '200': description: 'Get all private keys.' content: application/json: schema: $ref: '#/components/schemas/PrivateKey' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': description: 'Private Key not found.' security: - bearerAuth: [] delete: tags: - 'Private Keys' summary: Delete description: 'Delete a private key.' operationId: delete-private-key-by-uuid parameters: - name: uuid in: path description: 'Private Key UUID' required: true schema: type: string responses: '200': description: 'Private Key deleted.' content: application/json: schema: properties: message: { type: string, example: 'Private Key deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': description: 'Private Key not found.' '422': description: 'Private Key is in use and cannot be deleted.' content: application/json: schema: properties: message: { type: string, example: 'Private Key is in use and cannot be deleted.' } type: object security: - bearerAuth: [] /servers: get: tags: - Servers summary: List description: 'List all servers.' operationId: list-servers responses: '200': description: 'Get all servers.' content: application/json: schema: type: array items: $ref: '#/components/schemas/Server' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] post: tags: - Servers summary: Create description: 'Create Server.' operationId: create-server requestBody: description: 'Server created.' required: true content: application/json: schema: properties: name: type: string example: 'My Server' description: 'The name of the server.' description: type: string example: 'My Server Description' description: 'The description of the server.' ip: type: string example: 127.0.0.1 description: 'The IP of the server.' port: type: integer example: 22 description: 'The port of the server.' user: type: string example: root description: 'The user of the server.' private_key_uuid: type: string example: og888os description: 'The UUID of the private key.' is_build_server: type: boolean example: false description: 'Is build server.' instant_validate: type: boolean example: false description: 'Instant validate.' proxy_type: type: string enum: [traefik, caddy, none] example: traefik description: 'The proxy type.' type: object responses: '201': description: 'Server created.' content: application/json: schema: properties: uuid: { type: string, example: og888os, description: 'The UUID of the server.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/servers/{uuid}': get: tags: - Servers summary: Get description: 'Get server by UUID.' operationId: get-server-by-uuid parameters: - name: uuid in: path description: "Server's UUID" required: true schema: type: string responses: '200': description: 'Get server by UUID' content: application/json: schema: $ref: '#/components/schemas/Server' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - Servers summary: Delete description: 'Delete server by UUID.' operationId: delete-server-by-uuid parameters: - name: uuid in: path description: 'UUID of the server.' required: true schema: type: string responses: '200': description: 'Server deleted.' content: application/json: schema: properties: message: { type: string, example: 'Server deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] patch: tags: - Servers summary: Update description: 'Update Server.' operationId: update-server-by-uuid parameters: - name: uuid in: path description: 'Server UUID' required: true schema: type: string requestBody: description: 'Server updated.' required: true content: application/json: schema: properties: name: type: string description: 'The name of the server.' description: type: string description: 'The description of the server.' ip: type: string description: 'The IP of the server.' port: type: integer description: 'The port of the server.' user: type: string description: 'The user of the server.' private_key_uuid: type: string description: 'The UUID of the private key.' is_build_server: type: boolean description: 'Is build server.' instant_validate: type: boolean description: 'Instant validate.' proxy_type: type: string enum: [traefik, caddy, none] description: 'The proxy type.' type: object responses: '201': description: 'Server updated.' content: application/json: schema: $ref: '#/components/schemas/Server' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/servers/{uuid}/resources': get: tags: - Servers summary: Resources description: 'Get resources by server.' operationId: get-resources-by-server-uuid parameters: - name: uuid in: path description: "Server's UUID" required: true schema: type: string responses: '200': description: 'Get resources by server' content: application/json: schema: type: array items: properties: { id: { type: integer }, uuid: { type: string }, name: { type: string }, type: { type: string }, created_at: { type: string }, updated_at: { type: string }, status: { type: string } } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] '/servers/{uuid}/domains': get: tags: - Servers summary: Domains description: 'Get domains by server.' operationId: get-domains-by-server-uuid parameters: - name: uuid in: path description: "Server's UUID" required: true schema: type: string responses: '200': description: 'Get domains by server' content: application/json: schema: type: array items: properties: { ip: { type: string }, domains: { type: array, items: { type: string } } } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] '/servers/{uuid}/validate': get: tags: - Servers summary: Validate description: 'Validate server by UUID.' operationId: validate-server-by-uuid parameters: - name: uuid in: path description: 'Server UUID' required: true schema: type: string responses: '201': description: 'Server validation started.' content: application/json: schema: properties: message: { type: string, example: 'Validation started.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] /services: get: tags: - Services summary: List description: 'List all services.' operationId: list-services responses: '200': description: 'Get all services' content: application/json: schema: type: array items: $ref: '#/components/schemas/Service' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] post: tags: - Services summary: 'Create service' description: 'Create a one-click / custom service' operationId: create-service requestBody: required: true content: application/json: schema: required: - server_uuid - project_uuid - environment_name - environment_uuid properties: type: description: 'The one-click service type (e.g. "actualbudget", "calibre-web", "gitea-with-mysql" ...)' type: string name: type: string maxLength: 255 description: 'Name of the service.' description: type: string nullable: true description: 'Description of the service.' project_uuid: type: string description: 'Project UUID.' environment_name: type: string description: 'Environment name. You need to provide at least one of environment_name or environment_uuid.' environment_uuid: type: string description: 'Environment UUID. You need to provide at least one of environment_name or environment_uuid.' server_uuid: type: string description: 'Server UUID.' destination_uuid: type: string description: 'Destination UUID. Required if server has multiple destinations.' instant_deploy: type: boolean default: false description: 'Start the service immediately after creation.' docker_compose_raw: type: string description: 'The base64 encoded Docker Compose content.' urls: type: array description: 'Array of URLs to be applied to containers of a service.' items: { properties: { name: { type: string, description: 'The service name as defined in docker-compose.' }, url: { type: string, description: 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io").' } }, type: object } force_domain_override: type: boolean default: false description: 'Force domain override even if conflicts are detected.' type: object responses: '201': description: 'Service created successfully.' content: application/json: schema: properties: uuid: { type: string, description: 'Service UUID.' } domains: { type: array, items: { type: string }, description: 'Service domains.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/services/{uuid}': get: tags: - Services summary: Get description: 'Get service by UUID.' operationId: get-service-by-uuid parameters: - name: uuid in: path description: 'Service UUID' required: true schema: type: string responses: '200': description: 'Get a service by UUID.' content: application/json: schema: $ref: '#/components/schemas/Service' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] delete: tags: - Services summary: Delete description: 'Delete service by UUID.' operationId: delete-service-by-uuid parameters: - name: uuid in: path description: 'Service UUID' required: true schema: type: string - name: delete_configurations in: query description: 'Delete configurations.' required: false schema: type: boolean default: true - name: delete_volumes in: query description: 'Delete volumes.' required: false schema: type: boolean default: true - name: docker_cleanup in: query description: 'Run docker cleanup.' required: false schema: type: boolean default: true - name: delete_connected_networks in: query description: 'Delete connected networks.' required: false schema: type: boolean default: true responses: '200': description: 'Delete a service by UUID' content: application/json: schema: properties: message: { type: string, example: 'Service deletion request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] patch: tags: - Services summary: Update description: 'Update service by UUID.' operationId: update-service-by-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string requestBody: description: 'Service updated.' required: true content: application/json: schema: properties: name: type: string description: 'The service name.' description: type: string description: 'The service description.' project_uuid: type: string description: 'The project UUID.' environment_name: type: string description: 'The environment name.' environment_uuid: type: string description: 'The environment UUID.' server_uuid: type: string description: 'The server UUID.' destination_uuid: type: string description: 'The destination UUID.' instant_deploy: type: boolean description: 'The flag to indicate if the service should be deployed instantly.' connect_to_docker_network: type: boolean default: false description: 'Connect the service to the predefined docker network.' docker_compose_raw: type: string description: 'The base64 encoded Docker Compose content.' urls: type: array description: 'Array of URLs to be applied to containers of a service.' items: { properties: { name: { type: string, description: 'The service name as defined in docker-compose.' }, url: { type: string, description: 'Comma-separated list of URLs (e.g. "http://app.coolify.io,https://app2.coolify.io").' } }, type: object } force_domain_override: type: boolean default: false description: 'Force domain override even if conflicts are detected.' type: object responses: '200': description: 'Service updated.' content: application/json: schema: properties: uuid: { type: string, description: 'Service UUID.' } domains: { type: array, items: { type: string }, description: 'Service domains.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '409': description: 'Domain conflicts detected.' content: application/json: schema: properties: message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' } warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' } conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } } type: object '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/services/{uuid}/envs': get: tags: - Services summary: 'List Envs' description: 'List all envs by service UUID.' operationId: list-envs-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string responses: '200': description: 'All environment variables by service UUID.' content: application/json: schema: type: array items: $ref: '#/components/schemas/EnvironmentVariable' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] post: tags: - Services summary: 'Create Env' description: 'Create env by service UUID.' operationId: create-env-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string requestBody: description: 'Env created.' required: true content: application/json: schema: properties: key: type: string description: 'The key of the environment variable.' value: type: string description: 'The value of the environment variable.' is_preview: type: boolean description: 'The flag to indicate if the environment variable is used in preview deployments.' is_literal: type: boolean description: 'The flag to indicate if the environment variable is a literal, nothing espaced.' is_multiline: type: boolean description: 'The flag to indicate if the environment variable is multiline.' is_shown_once: type: boolean description: "The flag to indicate if the environment variable's value is shown on the UI." type: object responses: '201': description: 'Environment variable created.' content: application/json: schema: properties: uuid: { type: string, example: nc0k04gk8g0cgsk440g0koko } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] patch: tags: - Services summary: 'Update Env' description: 'Update env by service UUID.' operationId: update-env-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string requestBody: description: 'Env updated.' required: true content: application/json: schema: required: - key - value properties: key: type: string description: 'The key of the environment variable.' value: type: string description: 'The value of the environment variable.' is_preview: type: boolean description: 'The flag to indicate if the environment variable is used in preview deployments.' is_literal: type: boolean description: 'The flag to indicate if the environment variable is a literal, nothing espaced.' is_multiline: type: boolean description: 'The flag to indicate if the environment variable is multiline.' is_shown_once: type: boolean description: "The flag to indicate if the environment variable's value is shown on the UI." type: object responses: '201': description: 'Environment variable updated.' content: application/json: schema: $ref: '#/components/schemas/EnvironmentVariable' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/services/{uuid}/envs/bulk': patch: tags: - Services summary: 'Update Envs (Bulk)' description: 'Update multiple envs by service UUID.' operationId: update-envs-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string requestBody: description: 'Bulk envs updated.' required: true content: application/json: schema: required: - data properties: data: type: array items: { properties: { key: { type: string, description: 'The key of the environment variable.' }, value: { type: string, description: 'The value of the environment variable.' }, is_preview: { type: boolean, description: 'The flag to indicate if the environment variable is used in preview deployments.' }, is_literal: { type: boolean, description: 'The flag to indicate if the environment variable is a literal, nothing espaced.' }, is_multiline: { type: boolean, description: 'The flag to indicate if the environment variable is multiline.' }, is_shown_once: { type: boolean, description: "The flag to indicate if the environment variable's value is shown on the UI." } }, type: object } type: object responses: '201': description: 'Environment variables updated.' content: application/json: schema: type: array items: $ref: '#/components/schemas/EnvironmentVariable' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '422': $ref: '#/components/responses/422' security: - bearerAuth: [] '/services/{uuid}/envs/{env_uuid}': delete: tags: - Services summary: 'Delete Env' description: 'Delete env by UUID.' operationId: delete-env-by-service-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string - name: env_uuid in: path description: 'UUID of the environment variable.' required: true schema: type: string responses: '200': description: 'Environment variable deleted.' content: application/json: schema: properties: message: { type: string, example: 'Environment variable deleted.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/services/{uuid}/start': get: tags: - Services summary: Start description: 'Start service. `Post` request is also accepted.' operationId: start-service-by-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string responses: '200': description: 'Start service.' content: application/json: schema: properties: message: { type: string, example: 'Service starting request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/services/{uuid}/stop': get: tags: - Services summary: Stop description: 'Stop service. `Post` request is also accepted.' operationId: stop-service-by-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string - name: docker_cleanup in: query description: 'Perform docker cleanup (prune networks, volumes, etc.).' schema: type: boolean default: true responses: '200': description: 'Stop service.' content: application/json: schema: properties: message: { type: string, example: 'Service stopping request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/services/{uuid}/restart': get: tags: - Services summary: Restart description: 'Restart service. `Post` request is also accepted.' operationId: restart-service-by-uuid parameters: - name: uuid in: path description: 'UUID of the service.' required: true schema: type: string - name: latest in: query description: 'Pull latest images.' schema: type: boolean default: false responses: '200': description: 'Restart service.' content: application/json: schema: properties: message: { type: string, example: 'Service restaring request queued.' } type: object '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /teams: get: tags: - Teams summary: List description: 'Get all teams.' operationId: list-teams responses: '200': description: 'List of teams.' content: application/json: schema: type: array items: $ref: '#/components/schemas/Team' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] '/teams/{id}': get: tags: - Teams summary: Get description: 'Get team by TeamId.' operationId: get-team-by-id parameters: - name: id in: path description: 'Team ID' required: true schema: type: integer responses: '200': description: 'List of teams.' content: application/json: schema: $ref: '#/components/schemas/Team' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] '/teams/{id}/members': get: tags: - Teams summary: Members description: 'Get members by TeamId.' operationId: get-members-by-team-id parameters: - name: id in: path description: 'Team ID' required: true schema: type: integer responses: '200': description: 'List of members.' content: application/json: schema: type: array items: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' security: - bearerAuth: [] /teams/current: get: tags: - Teams summary: 'Authenticated Team' description: 'Get currently authenticated team.' operationId: get-current-team responses: '200': description: 'Current Team.' content: application/json: schema: $ref: '#/components/schemas/Team' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] /teams/current/members: get: tags: - Teams summary: 'Authenticated Team Members' description: 'Get currently authenticated team members.' operationId: get-current-team-members responses: '200': description: 'Currently authenticated team members.' content: application/json: schema: type: array items: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/401' '400': $ref: '#/components/responses/400' security: - bearerAuth: [] components: schemas: Application: description: 'Application model' properties: id: type: integer description: 'The application identifier in the database.' description: type: string nullable: true description: 'The application description.' repository_project_id: type: integer nullable: true description: 'The repository project identifier.' uuid: type: string description: 'The application UUID.' name: type: string description: 'The application name.' fqdn: type: string nullable: true description: 'The application domains.' config_hash: type: string description: 'Configuration hash.' git_repository: type: string description: 'Git repository URL.' git_branch: type: string description: 'Git branch.' git_commit_sha: type: string description: 'Git commit SHA.' git_full_url: type: string nullable: true description: 'Git full URL.' docker_registry_image_name: type: string nullable: true description: 'Docker registry image name.' docker_registry_image_tag: type: string nullable: true description: 'Docker registry image tag.' build_pack: type: string description: 'Build pack.' enum: - nixpacks - static - dockerfile - dockercompose static_image: type: string description: 'Static image used when static site is deployed.' install_command: type: string description: 'Install command.' build_command: type: string description: 'Build command.' start_command: type: string description: 'Start command.' ports_exposes: type: string description: 'Ports exposes.' ports_mappings: type: string nullable: true description: 'Ports mappings.' custom_network_aliases: type: string nullable: true description: 'Network aliases for Docker container.' base_directory: type: string description: 'Base directory for all commands.' publish_directory: type: string description: 'Publish directory.' health_check_enabled: type: boolean description: 'Health check enabled.' health_check_path: type: string description: 'Health check path.' health_check_port: type: string nullable: true description: 'Health check port.' health_check_host: type: string nullable: true description: 'Health check host.' health_check_method: type: string description: 'Health check method.' health_check_return_code: type: integer description: 'Health check return code.' health_check_scheme: type: string description: 'Health check scheme.' health_check_response_text: type: string nullable: true description: 'Health check response text.' health_check_interval: type: integer description: 'Health check interval in seconds.' health_check_timeout: type: integer description: 'Health check timeout in seconds.' health_check_retries: type: integer description: 'Health check retries count.' health_check_start_period: type: integer description: 'Health check start period in seconds.' health_check_type: type: string description: 'Health check type: http or cmd.' enum: - http - cmd health_check_command: type: string nullable: true description: 'Health check command for CMD type.' limits_memory: type: string description: 'Memory limit.' limits_memory_swap: type: string description: 'Memory swap limit.' limits_memory_swappiness: type: integer description: 'Memory swappiness.' limits_memory_reservation: type: string description: 'Memory reservation.' limits_cpus: type: string description: 'CPU limit.' limits_cpuset: type: string nullable: true description: 'CPU set.' limits_cpu_shares: type: integer description: 'CPU shares.' status: type: string description: 'Application status.' preview_url_template: type: string description: 'Preview URL template.' destination_type: type: string description: 'Destination type.' destination_id: type: integer description: 'Destination identifier.' source_id: type: integer nullable: true description: 'Source identifier.' private_key_id: type: integer nullable: true description: 'Private key identifier.' environment_id: type: integer description: 'Environment identifier.' dockerfile: type: string nullable: true description: 'Dockerfile content. Used for dockerfile build pack.' dockerfile_location: type: string description: 'Dockerfile location.' custom_labels: type: string nullable: true description: 'Custom labels.' dockerfile_target_build: type: string nullable: true description: 'Dockerfile target build.' manual_webhook_secret_github: type: string nullable: true description: 'Manual webhook secret for GitHub.' manual_webhook_secret_gitlab: type: string nullable: true description: 'Manual webhook secret for GitLab.' manual_webhook_secret_bitbucket: type: string nullable: true description: 'Manual webhook secret for Bitbucket.' manual_webhook_secret_gitea: type: string nullable: true description: 'Manual webhook secret for Gitea.' docker_compose_location: type: string description: 'Docker compose location.' docker_compose: type: string nullable: true description: 'Docker compose content. Used for docker compose build pack.' docker_compose_raw: type: string nullable: true description: 'Docker compose raw content.' docker_compose_domains: type: string nullable: true description: 'Docker compose domains.' docker_compose_custom_start_command: type: string nullable: true description: 'Docker compose custom start command.' docker_compose_custom_build_command: type: string nullable: true description: 'Docker compose custom build command.' swarm_replicas: type: integer nullable: true description: 'Swarm replicas. Only used for swarm deployments.' swarm_placement_constraints: type: string nullable: true description: 'Swarm placement constraints. Only used for swarm deployments.' custom_docker_run_options: type: string nullable: true description: 'Custom docker run options.' post_deployment_command: type: string nullable: true description: 'Post deployment command.' post_deployment_command_container: type: string nullable: true description: 'Post deployment command container.' pre_deployment_command: type: string nullable: true description: 'Pre deployment command.' pre_deployment_command_container: type: string nullable: true description: 'Pre deployment command container.' watch_paths: type: string nullable: true description: 'Watch paths.' custom_healthcheck_found: type: boolean description: 'Custom healthcheck found.' redirect: type: string nullable: true description: 'How to set redirect with Traefik / Caddy. www<->non-www.' enum: - www - non-www - both created_at: type: string format: date-time description: 'The date and time when the application was created.' updated_at: type: string format: date-time description: 'The date and time when the application was last updated.' deleted_at: type: string format: date-time nullable: true description: 'The date and time when the application was deleted.' compose_parsing_version: type: string description: 'How Coolify parse the compose file.' custom_nginx_configuration: type: string nullable: true description: 'Custom Nginx configuration base64 encoded.' is_http_basic_auth_enabled: type: boolean description: 'HTTP Basic Authentication enabled.' http_basic_auth_username: type: string nullable: true description: 'Username for HTTP Basic Authentication' http_basic_auth_password: type: string nullable: true description: 'Password for HTTP Basic Authentication' type: object ApplicationDeploymentQueue: description: 'Project model' properties: id: type: integer application_id: type: string deployment_uuid: type: string pull_request_id: type: integer force_rebuild: type: boolean commit: type: string status: type: string is_webhook: type: boolean is_api: type: boolean created_at: type: string updated_at: type: string logs: type: string current_process_id: type: string restart_only: type: boolean git_type: type: string server_id: type: integer application_name: type: string server_name: type: string deployment_url: type: string destination_id: type: string only_this_server: type: boolean rollback: type: boolean commit_message: type: string type: object Environment: description: 'Environment model' properties: id: type: integer name: type: string project_id: type: integer created_at: type: string updated_at: type: string description: type: string type: object EnvironmentVariable: description: 'Environment Variable model' properties: id: type: integer uuid: type: string resourceable_type: type: string resourceable_id: type: integer is_literal: type: boolean is_multiline: type: boolean is_preview: type: boolean is_runtime: type: boolean is_buildtime: type: boolean is_shared: type: boolean is_shown_once: type: boolean key: type: string value: type: string real_value: type: string comment: type: string nullable: true version: type: string created_at: type: string updated_at: type: string type: object PrivateKey: description: 'Private Key model' properties: id: type: integer uuid: type: string name: type: string description: type: string private_key: type: string format: private-key public_key: type: string description: 'The public key of the private key.' fingerprint: type: string description: 'The fingerprint of the private key.' is_git_related: type: boolean team_id: type: integer created_at: type: string updated_at: type: string type: object Project: description: 'Project model' properties: id: type: integer uuid: type: string name: type: string description: type: string type: object ScheduledTask: description: 'Scheduled Task model' properties: id: type: integer description: 'The unique identifier of the scheduled task in the database.' uuid: type: string description: 'The unique identifier of the scheduled task.' enabled: type: boolean description: 'The flag to indicate if the scheduled task is enabled.' name: type: string description: 'The name of the scheduled task.' command: type: string description: 'The command to execute.' frequency: type: string description: 'The frequency of the scheduled task.' container: type: string nullable: true description: 'The container where the command should be executed.' timeout: type: integer description: 'The timeout of the scheduled task in seconds.' created_at: type: string format: date-time description: 'The date and time when the scheduled task was created.' updated_at: type: string format: date-time description: 'The date and time when the scheduled task was last updated.' type: object ScheduledTaskExecution: description: 'Scheduled Task Execution model' properties: uuid: type: string description: 'The unique identifier of the execution.' status: type: string enum: - success - failed - running description: 'The status of the execution.' message: type: string nullable: true description: 'The output message of the execution.' retry_count: type: integer description: 'The number of retries.' duration: type: number nullable: true description: 'Duration in seconds.' started_at: type: string format: date-time nullable: true description: 'When the execution started.' finished_at: type: string format: date-time nullable: true description: 'When the execution finished.' created_at: type: string format: date-time description: 'When the record was created.' updated_at: type: string format: date-time description: 'When the record was last updated.' type: object Server: description: 'Server model' properties: id: type: integer description: 'The server ID.' uuid: type: string description: 'The server UUID.' name: type: string description: 'The server name.' description: type: string description: 'The server description.' ip: type: string description: 'The IP address.' user: type: string description: 'The user.' port: type: integer description: 'The port number.' proxy: type: object description: 'The proxy configuration.' proxy_type: type: string enum: - traefik - caddy - none description: 'The proxy type.' high_disk_usage_notification_sent: type: boolean description: 'The flag to indicate if the high disk usage notification has been sent.' unreachable_notification_sent: type: boolean description: 'The flag to indicate if the unreachable notification has been sent.' unreachable_count: type: integer description: 'The unreachable count for your server.' validation_logs: type: string description: 'The validation logs.' log_drain_notification_sent: type: boolean description: 'The flag to indicate if the log drain notification has been sent.' swarm_cluster: type: string description: 'The swarm cluster configuration.' settings: $ref: '#/components/schemas/ServerSetting' type: object ServerSetting: description: 'Server Settings model' properties: id: type: integer concurrent_builds: type: integer deployment_queue_limit: type: integer dynamic_timeout: type: integer force_disabled: type: boolean force_server_cleanup: type: boolean is_build_server: type: boolean is_cloudflare_tunnel: type: boolean is_jump_server: type: boolean is_logdrain_axiom_enabled: type: boolean is_logdrain_custom_enabled: type: boolean is_logdrain_highlight_enabled: type: boolean is_logdrain_newrelic_enabled: type: boolean is_metrics_enabled: type: boolean is_reachable: type: boolean is_sentinel_enabled: type: boolean is_swarm_manager: type: boolean is_swarm_worker: type: boolean is_terminal_enabled: type: boolean is_usable: type: boolean logdrain_axiom_api_key: type: string logdrain_axiom_dataset_name: type: string logdrain_custom_config: type: string logdrain_custom_config_parser: type: string logdrain_highlight_project_id: type: string logdrain_newrelic_base_uri: type: string logdrain_newrelic_license_key: type: string sentinel_metrics_history_days: type: integer sentinel_metrics_refresh_rate_seconds: type: integer sentinel_token: type: string docker_cleanup_frequency: type: string docker_cleanup_threshold: type: integer server_id: type: integer wildcard_domain: type: string created_at: type: string updated_at: type: string delete_unused_volumes: type: boolean description: 'The flag to indicate if the unused volumes should be deleted.' delete_unused_networks: type: boolean description: 'The flag to indicate if the unused networks should be deleted.' type: object Service: description: 'Service model' properties: id: type: integer description: 'The unique identifier of the service. Only used for database identification.' uuid: type: string description: 'The unique identifier of the service.' name: type: string description: 'The name of the service.' environment_id: type: integer description: 'The unique identifier of the environment where the service is attached to.' server_id: type: integer description: 'The unique identifier of the server where the service is running.' description: type: string description: 'The description of the service.' docker_compose_raw: type: string description: 'The raw docker-compose.yml file of the service.' docker_compose: type: string description: 'The docker-compose.yml file that is parsed and modified by Coolify.' destination_type: type: string description: 'Destination type.' destination_id: type: integer description: 'The unique identifier of the destination where the service is running.' connect_to_docker_network: type: boolean description: 'The flag to connect the service to the predefined Docker network.' is_container_label_escape_enabled: type: boolean description: 'The flag to enable the container label escape.' is_container_label_readonly_enabled: type: boolean description: 'The flag to enable the container label readonly.' config_hash: type: string description: 'The hash of the service configuration.' service_type: type: string description: 'The type of the service.' created_at: type: string description: 'The date and time when the service was created.' updated_at: type: string description: 'The date and time when the service was last updated.' deleted_at: type: string description: 'The date and time when the service was deleted.' type: object Team: description: 'Team model' properties: id: type: integer description: 'The unique identifier of the team.' name: type: string description: 'The name of the team.' description: type: string description: 'The description of the team.' personal_team: type: boolean description: 'Whether the team is personal or not.' created_at: type: string description: 'The date and time the team was created.' updated_at: type: string description: 'The date and time the team was last updated.' show_boarding: type: boolean description: 'Whether to show the boarding screen or not.' custom_server_limit: type: string description: 'The custom server limit.' members: description: 'The members of the team.' type: array items: $ref: '#/components/schemas/User' type: object User: description: 'User model' properties: id: type: integer description: 'The user identifier in the database.' name: type: string description: 'The user name.' email: type: string description: 'The user email.' email_verified_at: type: string description: 'The date when the user email was verified.' created_at: type: string description: 'The date when the user was created.' updated_at: type: string description: 'The date when the user was updated.' two_factor_confirmed_at: type: string description: 'The date when the user two factor was confirmed.' force_password_reset: type: boolean description: 'The flag to force the user to reset the password.' marketing_emails: type: boolean description: 'The flag to receive marketing emails.' type: object responses: '400': description: 'Invalid token.' content: application/json: schema: properties: message: type: string example: 'Invalid token.' type: object '401': description: Unauthenticated. content: application/json: schema: properties: message: type: string example: Unauthenticated. type: object '404': description: 'Resource not found.' content: application/json: schema: properties: message: type: string example: 'Resource not found.' type: object '422': description: 'Validation error.' content: application/json: schema: properties: message: type: string example: 'Validation error.' errors: type: object example: name: ['The name field is required.'] api_url: ['The api url field is required.', 'The api url format is invalid.'] additionalProperties: type: array items: { type: string } type: object '429': description: 'Rate limit exceeded.' headers: Retry-After: description: 'Number of seconds to wait before retrying.' schema: type: integer example: 60 content: application/json: schema: properties: message: type: string example: 'Rate limit exceeded. Please try again later.' type: object securitySchemes: bearerAuth: type: http description: 'Go to `Keys & Tokens` / `API tokens` and create a new token. Use the token as the bearer token.' scheme: bearer tags: - name: Applications description: Applications - name: 'Cloud Tokens' description: 'Cloud Tokens' - name: Databases description: Databases - name: Deployments description: Deployments - name: 'GitHub Apps' description: 'GitHub Apps' - name: Hetzner description: Hetzner - name: Projects description: Projects - name: Resources description: Resources - name: 'Scheduled Tasks' description: 'Scheduled Tasks' - name: 'Private Keys' description: 'Private Keys' - name: Servers description: Servers - name: Services description: Services - name: Teams description: Teams ================================================ FILE: opencode.json ================================================ { "$schema": "https://opencode.ai/config.json", "mcp": { "laravel-boost": { "type": "local", "enabled": true, "command": [ "php", "artisan", "boost:mcp" ] } } } ================================================ FILE: other/nightly/docker-compose.prod.yml ================================================ services: coolify: image: "${REGISTRY_URL:-ghcr.io}/coollabsio/coolify:${LATEST_IMAGE:-latest}" volumes: - type: bind source: /data/coolify/source/.env target: /var/www/html/.env read_only: true - /data/coolify/ssh:/var/www/html/storage/app/ssh - /data/coolify/applications:/var/www/html/storage/app/applications - /data/coolify/databases:/var/www/html/storage/app/databases - /data/coolify/services:/var/www/html/storage/app/services - /data/coolify/backups:/var/www/html/storage/app/backups environment: - APP_ENV=${APP_ENV:-production} - PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-256M} - PHP_FPM_PM_CONTROL=${PHP_FPM_PM_CONTROL:-dynamic} - PHP_FPM_PM_START_SERVERS=${PHP_FPM_PM_START_SERVERS:-1} - PHP_FPM_PM_MIN_SPARE_SERVERS=${PHP_FPM_PM_MIN_SPARE_SERVERS:-1} - PHP_FPM_PM_MAX_SPARE_SERVERS=${PHP_FPM_PM_MAX_SPARE_SERVERS:-10} env_file: - /data/coolify/source/.env ports: - "${APP_PORT:-8000}:8080" expose: - "${APP_PORT:-8000}" healthcheck: test: curl --fail http://127.0.0.1:8080/api/health || exit 1 interval: 5s retries: 10 timeout: 2s depends_on: postgres: condition: service_healthy redis: condition: service_healthy soketi: condition: service_healthy postgres: volumes: - coolify-db:/var/lib/postgresql/data environment: POSTGRES_USER: "${DB_USERNAME}" POSTGRES_PASSWORD: "${DB_PASSWORD}" POSTGRES_DB: "${DB_DATABASE:-coolify}" healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${DB_USERNAME}", "-d", "${DB_DATABASE:-coolify}" ] interval: 5s retries: 10 timeout: 2s redis: command: redis-server --save 20 1 --loglevel warning --requirepass ${REDIS_PASSWORD} environment: REDIS_PASSWORD: "${REDIS_PASSWORD}" volumes: - coolify-redis:/data healthcheck: test: redis-cli ping interval: 5s retries: 10 timeout: 2s soketi: image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.10' ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" volumes: - /data/coolify/ssh:/var/www/html/storage/app/ssh environment: APP_NAME: "${APP_NAME:-Coolify}" SOKETI_DEBUG: "${SOKETI_DEBUG:-false}" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}" SOKETI_HOST: "${SOKETI_HOST:-0.0.0.0}" healthcheck: test: [ "CMD-SHELL", "wget -qO- http://127.0.0.1:6001/ready && wget -qO- http://127.0.0.1:6002/ready || exit 1" ] interval: 5s retries: 10 timeout: 2s volumes: coolify-db: name: coolify-db coolify-redis: name: coolify-redis networks: coolify: external: true ================================================ FILE: other/nightly/docker-compose.windows.yml ================================================ services: coolify-testing-host: init: true image: "ghcr.io/coollabsio/coolify-testing-host:latest" pull_policy: always container_name: coolify-testing-host volumes: - //var/run/docker.sock://var/run/docker.sock - ./:/data/coolify coolify: image: "ghcr.io/coollabsio/coolify:latest" pull_policy: always container_name: coolify restart: always working_dir: /var/www/html extra_hosts: - 'host.docker.internal:host-gateway' volumes: - type: bind source: .env target: /var/www/html/.env read_only: true - ./ssh:/var/www/html/storage/app/ssh - ./applications:/var/www/html/storage/app/applications - ./databases:/var/www/html/storage/app/databases - ./services:/var/www/html/storage/app/services - ./backups:/var/www/html/storage/app/backups env_file: - .env environment: - APP_ID - APP_ENV=production - APP_NAME - APP_KEY - DB_PASSWORD - REDIS_PASSWORD - SSL_MODE=off - PHP_PM_CONTROL=dynamic - PHP_PM_START_SERVERS=1 - PHP_PM_MIN_SPARE_SERVERS=1 - PHP_PM_MAX_SPARE_SERVERS=10 - PUSHER_APP_ID - PUSHER_APP_KEY - PUSHER_APP_SECRET - AUTOUPDATE=true - SELF_HOSTED=true - SSH_MUX_ENABLED=false - IS_WINDOWS_DOCKER_DESKTOP=true ports: - "${APP_PORT:-8000}:8080" expose: - "${APP_PORT:-8000}" healthcheck: test: curl --fail http://localhost:8080/api/health || exit 1 interval: 5s retries: 10 timeout: 2s depends_on: postgres: condition: service_healthy redis: condition: service_healthy postgres: image: postgres:15-alpine pull_policy: always container_name: coolify-db restart: always env_file: - .env volumes: - coolify-db:/var/lib/postgresql/data environment: POSTGRES_USER: "${DB_USERNAME}" POSTGRES_PASSWORD: "${DB_PASSWORD}" POSTGRES_DB: "${DB_DATABASE:-coolify}" healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${DB_USERNAME}", "-d", "${DB_DATABASE:-coolify}" ] interval: 5s retries: 10 timeout: 2s redis: image: redis:alpine pull_policy: always container_name: coolify-redis restart: always command: redis-server --save 20 1 --loglevel warning --requirepass ${REDIS_PASSWORD} env_file: - .env environment: REDIS_PASSWORD: "${REDIS_PASSWORD}" volumes: - coolify-redis:/data healthcheck: test: redis-cli ping interval: 5s retries: 10 timeout: 2s soketi: image: 'ghcr.io/coollabsio/coolify-realtime:1.0.10' pull_policy: always container_name: coolify-realtime restart: always env_file: - .env ports: - "${SOKETI_PORT:-6001}:6001" - "6002:6002" volumes: - ./ssh:/var/www/html/storage/app/ssh environment: APP_NAME: "${APP_NAME:-Coolify}" SOKETI_DEBUG: "${SOKETI_DEBUG:-false}" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}" SOKETI_HOST: "${SOKETI_HOST:-0.0.0.0}" healthcheck: test: [ "CMD-SHELL", "wget -qO- http://127.0.0.1:6001/ready && wget -qO- http://127.0.0.1:6002/ready || exit 1" ] interval: 5s retries: 10 timeout: 2s volumes: coolify-db: name: coolify-db coolify-redis: name: coolify-redis ================================================ FILE: other/nightly/docker-compose.yml ================================================ services: coolify: container_name: coolify restart: always working_dir: /var/www/html extra_hosts: - 'host.docker.internal:host-gateway' networks: - coolify depends_on: - postgres - redis - soketi postgres: image: postgres:15-alpine container_name: coolify-db restart: always networks: - coolify redis: image: redis:alpine container_name: coolify-redis restart: always networks: - coolify soketi: container_name: coolify-realtime extra_hosts: - 'host.docker.internal:host-gateway' restart: always networks: - coolify networks: coolify: name: coolify driver: bridge external: false ================================================ FILE: other/nightly/install.sh ================================================ #!/bin/bash ## Do not modify this file. You will lose the ability to install and auto-update! ## Environment variables that can be set: ## ROOT_USERNAME - Predefined root username ## ROOT_USER_EMAIL - Predefined root user email ## ROOT_USER_PASSWORD - Predefined root user password ## DOCKER_ADDRESS_POOL_BASE - Custom Docker address pool base (default: 10.0.0.0/8) ## DOCKER_ADDRESS_POOL_SIZE - Custom Docker address pool size (default: 24) ## DOCKER_POOL_FORCE_OVERRIDE - Force override Docker address pool configuration (default: false) ## AUTOUPDATE - Set to "false" to disable auto-updates ## REGISTRY_URL - Custom registry URL for Docker images (default: ghcr.io) set -e # Exit immediately if a command exits with a non-zero status ## $1 could be empty, so we need to disable this check #set -u # Treat unset variables as an error and exit set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status CDN="https://cdn.coollabs.io/coolify-nightly" DATE=$(date +"%Y%m%d-%H%M%S") OS_TYPE=$(grep -w "ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') ENV_FILE="/data/coolify/source/.env" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER if [ $EUID != 0 ]; then echo "Please run this script as root or with sudo" exit fi echo "" echo "==========================================" echo " Coolify Installation - ${DATE}" echo "==========================================" echo "" echo "Welcome to Coolify Installer!" echo "This script will install everything for you. Sit back and relax." echo "Source code: https://github.com/coollabsio/coolify/blob/v4.x/scripts/install.sh" # Predefined root user ROOT_USERNAME=${ROOT_USERNAME:-} ROOT_USER_EMAIL=${ROOT_USER_EMAIL:-} ROOT_USER_PASSWORD=${ROOT_USER_PASSWORD:-} if [ -n "${REGISTRY_URL+x}" ]; then echo "Using registry URL from environment variable: $REGISTRY_URL" else if [ -f "$ENV_FILE" ] && grep -q "^REGISTRY_URL=" "$ENV_FILE"; then REGISTRY_URL=$(grep "^REGISTRY_URL=" "$ENV_FILE" | cut -d '=' -f2) echo "Using registry URL from .env: $REGISTRY_URL" else REGISTRY_URL="ghcr.io" echo "Using default registry URL: $REGISTRY_URL" fi fi # Docker address pool configuration defaults DOCKER_ADDRESS_POOL_BASE_DEFAULT="10.0.0.0/8" DOCKER_ADDRESS_POOL_SIZE_DEFAULT=24 # Check if environment variables were explicitly provided DOCKER_POOL_BASE_PROVIDED=false DOCKER_POOL_SIZE_PROVIDED=false DOCKER_POOL_FORCE_OVERRIDE=${DOCKER_POOL_FORCE_OVERRIDE:-false} if [ -n "${DOCKER_ADDRESS_POOL_BASE+x}" ]; then DOCKER_POOL_BASE_PROVIDED=true fi if [ -n "${DOCKER_ADDRESS_POOL_SIZE+x}" ]; then DOCKER_POOL_SIZE_PROVIDED=true fi restart_docker_service() { # Check if systemctl is available if command -v systemctl >/dev/null 2>&1; then systemctl restart docker if [ $? -eq 0 ]; then echo " - Docker daemon restarted successfully" else echo " - Failed to restart Docker daemon" return 1 fi # Check if service command is available elif command -v service >/dev/null 2>&1; then service docker restart if [ $? -eq 0 ]; then echo " - Docker daemon restarted successfully" else echo " - Failed to restart Docker daemon" return 1 fi # If neither systemctl nor service is available else echo " - Error: No service management system found" return 1 fi } # Function to compare address pools compare_address_pools() { local base1="$1" local size1="$2" local base2="$3" local size2="$4" # Normalize CIDR notation for comparison local ip1=$(echo "$base1" | cut -d'/' -f1) local prefix1=$(echo "$base1" | cut -d'/' -f2) local ip2=$(echo "$base2" | cut -d'/' -f1) local prefix2=$(echo "$base2" | cut -d'/' -f2) # Compare IPs and prefixes if [ "$ip1" = "$ip2" ] && [ "$prefix1" = "$prefix2" ] && [ "$size1" = "$size2" ]; then return 0 # Pools are the same else return 1 # Pools are different fi } # Docker address pool configuration DOCKER_ADDRESS_POOL_BASE=${DOCKER_ADDRESS_POOL_BASE:-"$DOCKER_ADDRESS_POOL_BASE_DEFAULT"} DOCKER_ADDRESS_POOL_SIZE=${DOCKER_ADDRESS_POOL_SIZE:-$DOCKER_ADDRESS_POOL_SIZE_DEFAULT} # Load Docker address pool configuration from .env file if it exists and environment variables were not provided if [ -f "/data/coolify/source/.env" ] && [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then ENV_DOCKER_ADDRESS_POOL_BASE=$(grep -E "^DOCKER_ADDRESS_POOL_BASE=" /data/coolify/source/.env | cut -d '=' -f2 || true) ENV_DOCKER_ADDRESS_POOL_SIZE=$(grep -E "^DOCKER_ADDRESS_POOL_SIZE=" /data/coolify/source/.env | cut -d '=' -f2 || true) if [ -n "$ENV_DOCKER_ADDRESS_POOL_BASE" ]; then DOCKER_ADDRESS_POOL_BASE="$ENV_DOCKER_ADDRESS_POOL_BASE" fi if [ -n "$ENV_DOCKER_ADDRESS_POOL_SIZE" ]; then DOCKER_ADDRESS_POOL_SIZE="$ENV_DOCKER_ADDRESS_POOL_SIZE" fi fi # Check if daemon.json exists and extract existing address pool configuration EXISTING_POOL_CONFIGURED=false if [ -f /etc/docker/daemon.json ]; then if jq -e '.["default-address-pools"]' /etc/docker/daemon.json >/dev/null 2>&1; then EXISTING_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null || true) EXISTING_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null || true) if [ -n "$EXISTING_POOL_BASE" ] && [ -n "$EXISTING_POOL_SIZE" ] && [ "$EXISTING_POOL_BASE" != "null" ] && [ "$EXISTING_POOL_SIZE" != "null" ]; then echo "Found existing Docker network pool: $EXISTING_POOL_BASE/$EXISTING_POOL_SIZE" EXISTING_POOL_CONFIGURED=true # Check if environment variables were explicitly provided if [ "$DOCKER_POOL_BASE_PROVIDED" = false ] && [ "$DOCKER_POOL_SIZE_PROVIDED" = false ]; then DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" else # Check if force override is enabled if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ]; then echo "Force override enabled - network pool will be updated with $DOCKER_ADDRESS_POOL_BASE/$DOCKER_ADDRESS_POOL_SIZE." else echo "Custom pool provided but force override not enabled - using existing configuration." echo "To force override, set DOCKER_POOL_FORCE_OVERRIDE=true" echo "This won't change the existing docker networks, only the pool configuration for the newly created networks." DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" DOCKER_POOL_BASE_PROVIDED=false DOCKER_POOL_SIZE_PROVIDED=false fi fi fi fi fi # Validate Docker address pool configuration if ! [[ $DOCKER_ADDRESS_POOL_BASE =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then echo "Warning: Invalid network pool base format: $DOCKER_ADDRESS_POOL_BASE" if [ "$EXISTING_POOL_CONFIGURED" = true ]; then echo "Using existing configuration: $EXISTING_POOL_BASE" DOCKER_ADDRESS_POOL_BASE="$EXISTING_POOL_BASE" else echo "Using default configuration: $DOCKER_ADDRESS_POOL_BASE_DEFAULT" DOCKER_ADDRESS_POOL_BASE="$DOCKER_ADDRESS_POOL_BASE_DEFAULT" fi fi if ! [[ $DOCKER_ADDRESS_POOL_SIZE =~ ^[0-9]+$ ]] || [ "$DOCKER_ADDRESS_POOL_SIZE" -lt 16 ] || [ "$DOCKER_ADDRESS_POOL_SIZE" -gt 28 ]; then echo "Warning: Invalid network pool size: $DOCKER_ADDRESS_POOL_SIZE (must be 16-28)" if [ "$EXISTING_POOL_CONFIGURED" = true ]; then echo "Using existing configuration: $EXISTING_POOL_SIZE" DOCKER_ADDRESS_POOL_SIZE="$EXISTING_POOL_SIZE" else echo "Using default configuration: $DOCKER_ADDRESS_POOL_SIZE_DEFAULT" DOCKER_ADDRESS_POOL_SIZE=$DOCKER_ADDRESS_POOL_SIZE_DEFAULT fi fi TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') REQUIRED_TOTAL_SPACE=30 REQUIRED_AVAILABLE_SPACE=20 WARNING_SPACE=false if [ "$TOTAL_SPACE" -lt "$REQUIRED_TOTAL_SPACE" ]; then WARNING_SPACE=true cat < >(tee -a $INSTALLATION_LOG_WITH_DATE) 2>&1 getAJoke() { JOKES=$(curl -s --max-time 2 "https://v2.jokeapi.dev/joke/Programming?blacklistFlags=nsfw,religious,political,racist,sexist,explicit&format=txt&type=single" || true) if [ "$JOKES" != "" ]; then echo -e " - Until then, here's a joke for you:\n" echo -e "$JOKES\n" fi } # Helper function to log with timestamp log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" } # Helper function to log section headers log_section() { echo "" echo "============================================================" echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" echo "============================================================" } # Helper function to check if all required packages are installed all_packages_installed() { for pkg in curl wget git jq openssl; do if ! command -v "$pkg" >/dev/null 2>&1; then return 1 fi done return 0 } # Check if the OS is manjaro, if so, change it to arch if [ "$OS_TYPE" = "manjaro" ] || [ "$OS_TYPE" = "manjaro-arm" ]; then OS_TYPE="arch" fi # Check if the OS is Endeavour OS, if so, change it to arch if [ "$OS_TYPE" = "endeavouros" ]; then OS_TYPE="arch" fi # Check if the OS is Cachy OS, if so, change it to arch if [ "$OS_TYPE" = "cachyos" ]; then OS_TYPE="arch" fi # Check if the OS is Asahi Linux, if so, change it to fedora if [ "$OS_TYPE" = "fedora-asahi-remix" ]; then OS_TYPE="fedora" fi # Check if the OS is popOS, if so, change it to ubuntu if [ "$OS_TYPE" = "pop" ]; then OS_TYPE="ubuntu" fi # Check if the OS is linuxmint, if so, change it to ubuntu if [ "$OS_TYPE" = "linuxmint" ]; then OS_TYPE="ubuntu" fi #Check if the OS is zorin, if so, change it to ubuntu if [ "$OS_TYPE" = "zorin" ]; then OS_TYPE="ubuntu" fi if [ "$OS_TYPE" = "arch" ] || [ "$OS_TYPE" = "archarm" ]; then OS_VERSION="rolling" else OS_VERSION=$(grep -w "VERSION_ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') fi # Install xargs on Amazon Linux 2023 - lol if [ "$OS_TYPE" = 'amzn' ]; then dnf install -y findutils >/dev/null fi # Fetch versions.json once and parse all values from it VERSIONS_JSON=$(curl -L --silent $CDN/versions.json) LATEST_VERSION=$(echo "$VERSIONS_JSON" | grep -i version | xargs | awk '{print $2}' | tr -d ',') LATEST_HELPER_VERSION=$(echo "$VERSIONS_JSON" | grep -i version | xargs | awk '{print $6}' | tr -d ',') LATEST_REALTIME_VERSION=$(echo "$VERSIONS_JSON" | grep -i version | xargs | awk '{print $8}' | tr -d ',') if [ -z "$LATEST_HELPER_VERSION" ]; then LATEST_HELPER_VERSION=latest fi if [ -z "$LATEST_REALTIME_VERSION" ]; then LATEST_REALTIME_VERSION=latest fi case "$OS_TYPE" in arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | opensuse-leap | opensuse-tumbleweed | almalinux | amzn | alpine | postmarketos | tencentos) ;; *) echo "This script only supports Debian, Redhat, Arch Linux, Alpine Linux, or SLES based operating systems for now." exit ;; esac # Overwrite LATEST_VERSION if user pass a version number if [ "$1" != "" ]; then LATEST_VERSION=$1 LATEST_VERSION="${LATEST_VERSION,,}" LATEST_VERSION="${LATEST_VERSION#v}" fi echo "---------------------------------------------" echo "| Operating System | $OS_TYPE $OS_VERSION" echo "| Docker | $DOCKER_VERSION" echo "| Coolify | $LATEST_VERSION" echo "| Helper | $LATEST_HELPER_VERSION" echo "| Realtime | $LATEST_REALTIME_VERSION" echo "| Docker Pool | $DOCKER_ADDRESS_POOL_BASE (size $DOCKER_ADDRESS_POOL_SIZE)" echo "| Registry URL | $REGISTRY_URL" echo "---------------------------------------------" echo "" log_section "Step 1/9: Installing required packages" echo "1/9 Installing required packages (curl, wget, git, jq, openssl)..." # Track if apt-get update was run to avoid redundant calls later APT_UPDATED=false if all_packages_installed; then log "All required packages already installed, skipping installation" echo " - All required packages already installed." else case "$OS_TYPE" in arch) pacman -Sy --noconfirm --needed curl wget git jq openssl >/dev/null || true ;; alpine | postmarketos) sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories apk update >/dev/null apk add curl wget git jq openssl >/dev/null ;; ubuntu | debian | raspbian) apt-get update -y >/dev/null APT_UPDATED=true apt-get install -y curl wget git jq openssl >/dev/null ;; centos | fedora | rhel | ol | rocky | almalinux | amzn | tencentos) if [ "$OS_TYPE" = "amzn" ]; then dnf install -y wget git jq openssl >/dev/null else if ! command -v dnf >/dev/null; then yum install -y dnf >/dev/null fi if ! command -v curl >/dev/null; then dnf install -y curl >/dev/null fi dnf install -y wget git jq openssl >/dev/null fi ;; sles | opensuse-leap | opensuse-tumbleweed) zypper refresh >/dev/null zypper install -y curl wget git jq openssl >/dev/null ;; *) echo "This script only supports Debian, Redhat, Arch Linux, or SLES based operating systems for now." exit ;; esac log "Required packages installed successfully" fi echo " Done." log_section "Step 2/9: Checking OpenSSH server configuration" echo "2/9 Checking OpenSSH server configuration..." # Detect OpenSSH server SSH_DETECTED=false if [ -x "$(command -v systemctl)" ]; then if systemctl status sshd >/dev/null 2>&1; then echo " - OpenSSH server is installed." SSH_DETECTED=true elif systemctl status ssh >/dev/null 2>&1; then echo " - OpenSSH server is installed." SSH_DETECTED=true fi elif [ -x "$(command -v service)" ]; then if service sshd status >/dev/null 2>&1; then echo " - OpenSSH server is installed." SSH_DETECTED=true elif service ssh status >/dev/null 2>&1; then echo " - OpenSSH server is installed." SSH_DETECTED=true fi fi if [ "$SSH_DETECTED" = "false" ]; then echo " - OpenSSH server not detected. Installing OpenSSH server." case "$OS_TYPE" in arch) pacman -Sy --noconfirm openssh >/dev/null systemctl enable sshd >/dev/null 2>&1 systemctl start sshd >/dev/null 2>&1 ;; alpine | postmarketos) apk add openssh >/dev/null rc-update add sshd default >/dev/null 2>&1 service sshd start >/dev/null 2>&1 ;; ubuntu | debian | raspbian) if [ "$APT_UPDATED" = false ]; then apt-get update -y >/dev/null APT_UPDATED=true fi apt-get install -y openssh-server >/dev/null systemctl enable ssh >/dev/null 2>&1 systemctl start ssh >/dev/null 2>&1 ;; centos | fedora | rhel | ol | rocky | almalinux | amzn | tencentos) if [ "$OS_TYPE" = "amzn" ]; then dnf install -y openssh-server >/dev/null else dnf install -y openssh-server >/dev/null fi systemctl enable sshd >/dev/null 2>&1 systemctl start sshd >/dev/null 2>&1 ;; sles | opensuse-leap | opensuse-tumbleweed) zypper install -y openssh >/dev/null systemctl enable sshd >/dev/null 2>&1 systemctl start sshd >/dev/null 2>&1 ;; *) echo "###############################################################################" echo "WARNING: Could not detect and install OpenSSH server - this does not mean that it is not installed or not running, just that we could not detect it." echo -e "Please make sure it is installed and running, otherwise Coolify cannot connect to the host system. \n" echo "###############################################################################" exit 1 ;; esac echo " - OpenSSH server installed successfully." SSH_DETECTED=true fi # Detect SSH PermitRootLogin SSH_PERMIT_ROOT_LOGIN=$(sshd -T | grep -i "permitrootlogin" | awk '{print $2}') || true if [ "$SSH_PERMIT_ROOT_LOGIN" = "yes" ] || [ "$SSH_PERMIT_ROOT_LOGIN" = "without-password" ] || [ "$SSH_PERMIT_ROOT_LOGIN" = "prohibit-password" ]; then echo " - SSH PermitRootLogin is enabled." else echo " - SSH PermitRootLogin is disabled." echo " If you have problems with SSH, please read this: https://coolify.io/docs/knowledge-base/server/openssh" fi # Detect if docker is installed via snap if [ -x "$(command -v snap)" ]; then SNAP_DOCKER_INSTALLED=$(snap list docker >/dev/null 2>&1 && echo "true" || echo "false") if [ "$SNAP_DOCKER_INSTALLED" = "true" ]; then echo "Docker is installed via snap." echo " Please note that Coolify does not support Docker installed via snap." echo " Please remove Docker with snap (snap remove docker) and reexecute this script." exit 1 fi fi install_docker() { set +e curl -s https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh 2>&1 || true if ! [ -x "$(command -v docker)" ]; then curl -s https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} 2>&1 if ! [ -x "$(command -v docker)" ]; then echo "Automated Docker installation failed. Trying manual installation." install_docker_manually fi fi set -e } install_docker_manually() { case "$OS_TYPE" in "ubuntu" | "debian" | "raspbian") if [ "$APT_UPDATED" = false ]; then apt-get update APT_UPDATED=true fi apt-get install -y ca-certificates curl install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/$OS_TYPE/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$OS_TYPE \ $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | tee /etc/apt/sources.list.d/docker.list apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ;; *) exit 1 ;; esac if ! [ -x "$(command -v docker)" ]; then echo "Docker installation failed." echo " Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." exit 1 else echo "Docker installed successfully." fi } log_section "Step 3/9: Checking Docker installation" echo "3/9 Checking Docker installation..." if ! [ -x "$(command -v docker)" ]; then echo " - Docker is not installed. Installing Docker. It may take a while." getAJoke case "$OS_TYPE" in "almalinux") dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo >/dev/null 2>&1 dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 if ! [ -x "$(command -v docker)" ]; then echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." exit 1 fi systemctl start docker >/dev/null 2>&1 systemctl enable docker >/dev/null 2>&1 ;; "alpine" | "postmarketos") apk add docker docker-cli-compose >/dev/null 2>&1 rc-update add docker default >/dev/null 2>&1 service docker start >/dev/null 2>&1 if ! [ -x "$(command -v docker)" ]; then echo " - Failed to install Docker with apk. Try to install it manually." echo " Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." exit 1 fi ;; "arch") pacman -Sy docker docker-compose --noconfirm >/dev/null 2>&1 systemctl enable docker.service >/dev/null 2>&1 if ! [ -x "$(command -v docker)" ]; then echo " - Failed to install Docker with pacman. Try to install it manually." echo " Please visit https://wiki.archlinux.org/title/docker for more information." exit 1 fi ;; "amzn") dnf install docker -y >/dev/null 2>&1 DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} mkdir -p $DOCKER_CONFIG/cli-plugins >/dev/null 2>&1 curl -sL "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose >/dev/null 2>&1 systemctl start docker >/dev/null 2>&1 systemctl enable docker >/dev/null 2>&1 if ! [ -x "$(command -v docker)" ]; then echo " - Failed to install Docker with dnf. Try to install it manually." echo " Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." exit 1 fi ;; "centos" | "fedora" | "rhel" | "tencentos") if [ -x "$(command -v dnf5)" ]; then # dnf5 is available dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1 else # dnf5 is not available, use dnf dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1 fi dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null 2>&1 if ! [ -x "$(command -v docker)" ]; then echo " - Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." exit 1 fi systemctl start docker >/dev/null 2>&1 systemctl enable docker >/dev/null 2>&1 ;; "ubuntu" | "debian" | "raspbian") install_docker if ! [ -x "$(command -v docker)" ]; then echo " - Automated Docker installation failed. Trying manual installation." install_docker_manually fi ;; *) install_docker if ! [ -x "$(command -v docker)" ]; then echo " - Automated Docker installation failed. Trying manual installation." install_docker_manually fi ;; esac echo " - Docker installed successfully." else echo " - Docker is installed." fi log_section "Step 4/9: Checking Docker configuration" echo "4/9 Checking Docker configuration..." echo " - Network pool configuration: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" echo " - To override existing configuration: DOCKER_POOL_FORCE_OVERRIDE=true" mkdir -p /etc/docker # Backup original daemon.json if it exists if [ -f /etc/docker/daemon.json ]; then cp /etc/docker/daemon.json /etc/docker/daemon.json.original-"$DATE" fi # Create coolify configuration with or without address pools based on whether they were explicitly provided if [ "$DOCKER_POOL_FORCE_OVERRIDE" = true ] || [ "$EXISTING_POOL_CONFIGURED" = false ]; then # First check if the configuration would actually change anything if [ -f /etc/docker/daemon.json ]; then CURRENT_POOL_BASE=$(jq -r '.["default-address-pools"][0].base' /etc/docker/daemon.json 2>/dev/null) CURRENT_POOL_SIZE=$(jq -r '.["default-address-pools"][0].size' /etc/docker/daemon.json 2>/dev/null) if [ "$CURRENT_POOL_BASE" = "$DOCKER_ADDRESS_POOL_BASE" ] && [ "$CURRENT_POOL_SIZE" = "$DOCKER_ADDRESS_POOL_SIZE" ]; then echo " - Network pool configuration unchanged, skipping update" NEED_MERGE=false else # If force override is enabled or no existing configuration exists, # create a new configuration with the specified address pools echo " - Creating new Docker configuration with network pool: ${DOCKER_ADDRESS_POOL_BASE}/${DOCKER_ADDRESS_POOL_SIZE}" cat >/etc/docker/daemon.json </etc/docker/daemon.json </dev/null 2>&1; then echo " - Log configuration is up to date" NEED_MERGE=false else # Create a configuration without address pools to preserve existing ones cat >/etc/docker/daemon.json.coolify </etc/docker/daemon.json < "$ENV_FILE.tmp" && mv "$ENV_FILE.tmp" "$ENV_FILE" echo " - .env file merged successfully" else # If no .env exists, copy .env.production to .env echo " - No .env file found, copying .env.production to .env" cp "/data/coolify/source/.env.production" "$ENV_FILE" fi log "Environment file setup completed" echo " Done." log_section "Step 7/9: Checking and updating environment variables" echo "7/9 Checking and updating environment variables..." update_env_var() { local key="$1" local value="$2" # If variable "key=" exists but has no value, update the value of the existing line if grep -q "^${key}=$" "$ENV_FILE"; then sed -i "s|^${key}=$|${key}=${value}|" "$ENV_FILE" echo " - Updated value of ${key} as the current value was empty" # If variable "key=" doesn't exist, append it to the file with value elif ! grep -q "^${key}=" "$ENV_FILE"; then printf '%s=%s\n' "$key" "$value" >>"$ENV_FILE" echo " - Added ${key} and it's value as the variable was missing" fi } update_env_var "APP_ID" "$(openssl rand -hex 16)" update_env_var "APP_KEY" "base64:$(openssl rand -base64 32)" # update_env_var "DB_USERNAME" "$(openssl rand -hex 16)" # Causes issues: database "random-user" does not exist update_env_var "DB_PASSWORD" "$(openssl rand -base64 32)" update_env_var "REDIS_PASSWORD" "$(openssl rand -base64 32)" update_env_var "PUSHER_APP_ID" "$(openssl rand -hex 32)" update_env_var "PUSHER_APP_KEY" "$(openssl rand -hex 32)" update_env_var "PUSHER_APP_SECRET" "$(openssl rand -hex 32)" # Add default root user credentials from environment variables if [ -n "$ROOT_USERNAME" ] && [ -n "$ROOT_USER_EMAIL" ] && [ -n "$ROOT_USER_PASSWORD" ]; then echo " - Setting predefined root user credentials from environment" update_env_var "ROOT_USERNAME" "$ROOT_USERNAME" update_env_var "ROOT_USER_EMAIL" "$ROOT_USER_EMAIL" update_env_var "ROOT_USER_PASSWORD" "$ROOT_USER_PASSWORD" fi if [ -n "${REGISTRY_URL+x}" ]; then # Only update if REGISTRY_URL was explicitly provided update_env_var "REGISTRY_URL" "$REGISTRY_URL" fi if [ "$AUTOUPDATE" = "false" ]; then update_env_var "AUTOUPDATE" "false" fi if [ "$DOCKER_POOL_BASE_PROVIDED" = true ]; then update_env_var "DOCKER_ADDRESS_POOL_BASE" "$DOCKER_ADDRESS_POOL_BASE" else # Add with default value if missing if ! grep -q "^DOCKER_ADDRESS_POOL_BASE=" "$ENV_FILE"; then update_env_var "DOCKER_ADDRESS_POOL_BASE" "$DOCKER_ADDRESS_POOL_BASE" fi fi if [ "$DOCKER_POOL_SIZE_PROVIDED" = true ]; then update_env_var "DOCKER_ADDRESS_POOL_SIZE" "$DOCKER_ADDRESS_POOL_SIZE" else # Add with default value if missing if ! grep -q "^DOCKER_ADDRESS_POOL_SIZE=" "$ENV_FILE"; then update_env_var "DOCKER_ADDRESS_POOL_SIZE" "$DOCKER_ADDRESS_POOL_SIZE" fi fi log "Environment variables check completed" echo " Done." log_section "Step 8/9: Checking SSH key for localhost access" echo "8/9 Checking SSH key for localhost access..." if [ ! -f ~/.ssh/authorized_keys ]; then mkdir -p ~/.ssh chmod 700 ~/.ssh touch ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys fi set +e IS_COOLIFY_VOLUME_EXISTS=$(docker volume ls | grep coolify-db | wc -l) set -e if [ "$IS_COOLIFY_VOLUME_EXISTS" -eq 0 ]; then echo " - Generating SSH key." test -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal && rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal test -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub && rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub ssh-keygen -t ed25519 -a 100 -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal -q -N "" -C coolify chown 9999 /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal sed -i "/coolify/d" ~/.ssh/authorized_keys cat /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub >>~/.ssh/authorized_keys rm -f /data/coolify/ssh/keys/id.$CURRENT_USER@host.docker.internal.pub fi chown -R 9999:root /data/coolify chmod -R 700 /data/coolify log "SSH key check completed" echo " Done." log_section "Step 9/9: Installing Coolify" echo "9/9 Installing Coolify ($LATEST_VERSION)..." echo -e " - It could take a while based on your server's performance, network speed, stars, etc." echo -e " - Please wait." getAJoke if [[ $- == *x* ]]; then bash -x /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" "${REGISTRY_URL:-ghcr.io}" "true" else bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" "${REGISTRY_URL:-ghcr.io}" "true" fi echo " - Coolify installed successfully." echo " - Waiting for Coolify to be ready..." # Wait for upgrade.sh background process to complete # upgrade.sh writes status to /data/coolify/source/.upgrade-status # Status file format: step|message|timestamp # Step 6 = "Upgrade complete", file deleted 10 seconds after UPGRADE_STATUS_FILE="/data/coolify/source/.upgrade-status" MAX_WAIT=180 WAITED=0 SEEN_STATUS_FILE=false while [ $WAITED -lt $MAX_WAIT ]; do if [ -f "$UPGRADE_STATUS_FILE" ]; then SEEN_STATUS_FILE=true STATUS=$(cat "$UPGRADE_STATUS_FILE" 2>/dev/null | cut -d'|' -f1) MESSAGE=$(cat "$UPGRADE_STATUS_FILE" 2>/dev/null | cut -d'|' -f2) if [ "$STATUS" = "6" ]; then log "Upgrade completed: $MESSAGE" echo " - Upgrade complete!" break elif [ "$STATUS" = "error" ]; then echo " - ERROR: Upgrade failed: $MESSAGE" echo " - Please check the upgrade logs: /data/coolify/source/upgrade-*.log" exit 1 else if [ $((WAITED % 10)) -eq 0 ]; then echo " - Upgrade in progress: $MESSAGE (${WAITED}s)" fi fi else # Status file doesn't exist if [ "$SEEN_STATUS_FILE" = true ]; then # We saw the file before, now it's gone = upgrade completed and cleaned up log "Upgrade status file cleaned up - upgrade complete" echo " - Upgrade complete!" break fi # Haven't seen status file yet - either very early or upgrade.sh hasn't started if [ $((WAITED % 10)) -eq 0 ] && [ $WAITED -gt 0 ]; then echo " - Waiting for upgrade process to start... (${WAITED}s)" fi fi sleep 2 WAITED=$((WAITED + 2)) done if [ $WAITED -ge $MAX_WAIT ]; then if [ "$SEEN_STATUS_FILE" = false ]; then # Never saw status file - fallback to old behavior (wait 20s + health check) log "Status file not found, using fallback wait" echo " - Status file not found, waiting 20 seconds..." sleep 20 else echo " - ERROR: Upgrade timed out after ${MAX_WAIT}s" echo " - Please check the upgrade logs: /data/coolify/source/upgrade-*.log" exit 1 fi fi # Final health verification - wait for container to be healthy echo " - Verifying Coolify is healthy..." HEALTH_WAIT=60 HEALTH_WAITED=0 while [ $HEALTH_WAITED -lt $HEALTH_WAIT ]; do HEALTH=$(docker inspect --format='{{.State.Health.Status}}' coolify 2>/dev/null || echo "unknown") if [ "$HEALTH" = "healthy" ]; then log "Coolify container is healthy" echo " - Coolify is ready!" break fi sleep 2 HEALTH_WAITED=$((HEALTH_WAITED + 2)) done if [ "$HEALTH" != "healthy" ]; then echo " - ERROR: Coolify container is not healthy after ${HEALTH_WAIT}s. Status: $HEALTH" echo " - Please check: docker logs coolify" exit 1 fi echo -e "\033[0;35m ____ _ _ _ _ _ / ___|___ _ __ __ _ _ __ __ _| |_ _ _| | __ _| |_(_) ___ _ __ ___| | | | / _ \| '_ \ / _\` | '__/ _\` | __| | | | |/ _\` | __| |/ _ \| '_ \/ __| | | |__| (_) | | | | (_| | | | (_| | |_| |_| | | (_| | |_| | (_) | | | \__ \_| \____\___/|_| |_|\__, |_| \__,_|\__|\__,_|_|\__,_|\__|_|\___/|_| |_|___(_) |___/ \033[0m" # Fetch public IPs in parallel for faster completion IPV4_TMP=$(mktemp) IPV6_TMP=$(mktemp) curl -4s --max-time 5 https://ifconfig.io > "$IPV4_TMP" 2>/dev/null & IPV4_PID=$! curl -6s --max-time 5 https://ifconfig.io > "$IPV6_TMP" 2>/dev/null & IPV6_PID=$! wait $IPV4_PID 2>/dev/null || true wait $IPV6_PID 2>/dev/null || true IPV4_PUBLIC_IP=$(cat "$IPV4_TMP" 2>/dev/null || true) IPV6_PUBLIC_IP=$(cat "$IPV6_TMP" 2>/dev/null || true) rm -f "$IPV4_TMP" "$IPV6_TMP" echo -e "\nYour instance is ready to use!\n" if [ -n "$IPV4_PUBLIC_IP" ]; then echo -e "You can access Coolify through your Public IPV4: http://$IPV4_PUBLIC_IP:8000" fi if [ -n "$IPV6_PUBLIC_IP" ]; then echo -e "You can access Coolify through your Public IPv6: http://[$IPV6_PUBLIC_IP]:8000" fi set +e DEFAULT_PRIVATE_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p') PRIVATE_IPS=$(hostname -I 2>/dev/null || ip -o addr show scope global | awk '{print $4}' | cut -d/ -f1) set -e if [ -n "$PRIVATE_IPS" ]; then echo -e "\nIf your Public IP is not accessible, you can use the following Private IPs:\n" for IP in $PRIVATE_IPS; do if [ "$IP" != "$DEFAULT_PRIVATE_IP" ]; then echo -e "http://$IP:8000" fi done fi echo -e "\nWARNING: It is highly recommended to backup your Environment variables file (/data/coolify/source/.env) to a safe location, outside of this server (e.g. into a Password Manager).\n" log_section "Installation Complete" log "Coolify installation completed successfully" log "Version: ${LATEST_VERSION}" log "Log file: ${INSTALLATION_LOG_WITH_DATE}" ================================================ FILE: other/nightly/upgrade.sh ================================================ #!/bin/bash ## Do not modify this file. You will lose the ability to autoupdate! CDN="https://cdn.coollabs.io/coolify-nightly" LATEST_IMAGE=${1:-latest} LATEST_HELPER_VERSION=${2:-latest} REGISTRY_URL=${3:-ghcr.io} SKIP_BACKUP=${4:-false} ENV_FILE="/data/coolify/source/.env" STATUS_FILE="/data/coolify/source/.upgrade-status" DATE=$(date +%Y-%m-%d-%H-%M-%S) LOGFILE="/data/coolify/source/upgrade-${DATE}.log" # Helper function to log with timestamp log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >>"$LOGFILE" } # Helper function to log section headers log_section() { echo "" >>"$LOGFILE" echo "============================================================" >>"$LOGFILE" echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >>"$LOGFILE" echo "============================================================" >>"$LOGFILE" } # Helper function to write upgrade status for API polling write_status() { local step="$1" local message="$2" echo "${step}|${message}|$(date -Iseconds)" > "$STATUS_FILE" } echo "" echo "==========================================" echo " Coolify Upgrade - ${DATE}" echo "==========================================" echo "" # Initialize log file with header echo "============================================================" >>"$LOGFILE" echo "Coolify Upgrade Log" >>"$LOGFILE" echo "Started: $(date '+%Y-%m-%d %H:%M:%S')" >>"$LOGFILE" echo "Target Version: ${LATEST_IMAGE}" >>"$LOGFILE" echo "Helper Version: ${LATEST_HELPER_VERSION}" >>"$LOGFILE" echo "Registry URL: ${REGISTRY_URL}" >>"$LOGFILE" echo "============================================================" >>"$LOGFILE" log_section "Step 1/6: Downloading configuration files" write_status "1" "Downloading configuration files" echo "1/6 Downloading latest configuration files..." log "Downloading docker-compose.yml from ${CDN}/docker-compose.yml" curl -fsSL -L $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml log "Downloading docker-compose.prod.yml from ${CDN}/docker-compose.prod.yml" curl -fsSL -L $CDN/docker-compose.prod.yml -o /data/coolify/source/docker-compose.prod.yml log "Downloading .env.production from ${CDN}/.env.production" curl -fsSL -L $CDN/.env.production -o /data/coolify/source/.env.production log "Configuration files downloaded successfully" echo " Done." # Extract all images from docker-compose configuration log "Extracting all images from docker-compose configuration..." COMPOSE_FILES="-f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml" # Check if custom compose file exists if [ -f /data/coolify/source/docker-compose.custom.yml ]; then COMPOSE_FILES="$COMPOSE_FILES -f /data/coolify/source/docker-compose.custom.yml" log "Including custom docker-compose.yml in image extraction" fi # Get all unique images from docker compose config # LATEST_IMAGE env var is needed for image substitution in compose files IMAGES=$(LATEST_IMAGE=${LATEST_IMAGE} docker compose --env-file "$ENV_FILE" $COMPOSE_FILES config --images 2>/dev/null | sort -u) if [ -z "$IMAGES" ]; then log "ERROR: Failed to extract images from docker-compose files" write_status "error" "Failed to parse docker-compose configuration" echo " ERROR: Failed to parse docker-compose configuration. Aborting upgrade." exit 1 fi log "Images to pull:" echo "$IMAGES" | while read img; do log " - $img"; done # Backup existing .env file before making any changes if [ "$SKIP_BACKUP" != "true" ]; then if [ -f "$ENV_FILE" ]; then echo " Creating backup of .env file..." log "Creating backup of .env file to .env-$DATE" cp "$ENV_FILE" "$ENV_FILE-$DATE" log "Backup created: ${ENV_FILE}-${DATE}" else log "WARNING: No existing .env file found to backup" fi fi log_section "Step 2/6: Updating environment configuration" write_status "2" "Updating environment configuration" echo "" echo "2/6 Updating environment configuration..." log "Merging .env.production values into .env" awk -F '=' '!seen[$1]++' "$ENV_FILE" /data/coolify/source/.env.production > "$ENV_FILE.tmp" && mv "$ENV_FILE.tmp" "$ENV_FILE" log "Environment file merged successfully" update_env_var() { local key="$1" local value="$2" # If variable "key=" exists but has no value, update the value of the existing line if grep -q "^${key}=$" "$ENV_FILE"; then sed -i "s|^${key}=$|${key}=${value}|" "$ENV_FILE" log "Updated ${key} (was empty)" # If variable "key=" doesn't exist, append it to the file with value elif ! grep -q "^${key}=" "$ENV_FILE"; then printf '%s=%s\n' "$key" "$value" >>"$ENV_FILE" log "Added ${key} (was missing)" fi } log "Checking environment variables..." update_env_var "PUSHER_APP_ID" "$(openssl rand -hex 32)" update_env_var "PUSHER_APP_KEY" "$(openssl rand -hex 32)" update_env_var "PUSHER_APP_SECRET" "$(openssl rand -hex 32)" log "Environment variables check complete" echo " Done." # Make sure coolify network exists # It is created when starting Coolify with docker compose log "Checking Docker network 'coolify'..." if ! docker network inspect coolify >/dev/null 2>&1; then log "Network 'coolify' does not exist, creating..." if ! docker network create --attachable --ipv6 coolify 2>/dev/null; then log "Failed to create network with IPv6, trying without IPv6..." docker network create --attachable coolify 2>/dev/null log "Network 'coolify' created without IPv6" else log "Network 'coolify' created with IPv6 support" fi else log "Network 'coolify' already exists" fi # Check if Docker config file exists DOCKER_CONFIG_MOUNT="" if [ -f /root/.docker/config.json ]; then DOCKER_CONFIG_MOUNT="-v /root/.docker/config.json:/root/.docker/config.json" log "Docker config mount enabled: /root/.docker/config.json" fi log_section "Step 3/6: Pulling Docker images" write_status "3" "Pulling Docker images" echo "" echo "3/6 Pulling Docker images..." echo " This may take a few minutes depending on your connection." # Also pull the helper image (not in compose files but needed for upgrade) HELPER_IMAGE="${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-helper:${LATEST_HELPER_VERSION}" echo " - Pulling $HELPER_IMAGE..." log "Pulling image: $HELPER_IMAGE" if docker pull "$HELPER_IMAGE" >>"$LOGFILE" 2>&1; then log "Successfully pulled $HELPER_IMAGE" else log "ERROR: Failed to pull $HELPER_IMAGE" write_status "error" "Failed to pull $HELPER_IMAGE" echo " ERROR: Failed to pull $HELPER_IMAGE. Aborting upgrade." exit 1 fi # Pull all images from compose config # Using a for loop to avoid subshell issues with exit for IMAGE in $IMAGES; do if [ -n "$IMAGE" ]; then echo " - Pulling $IMAGE..." log "Pulling image: $IMAGE" if docker pull "$IMAGE" >>"$LOGFILE" 2>&1; then log "Successfully pulled $IMAGE" else log "ERROR: Failed to pull $IMAGE" write_status "error" "Failed to pull $IMAGE" echo " ERROR: Failed to pull $IMAGE. Aborting upgrade." exit 1 fi fi done log "All images pulled successfully" echo " All images pulled successfully." log_section "Step 4/6: Stopping and restarting containers" write_status "4" "Stopping containers" echo "" echo "4/6 Stopping containers and starting new ones..." echo " This step will restart all Coolify containers." echo " Check the log file for details: ${LOGFILE}" # From this point forward, we need to ensure the script continues even if # the SSH connection is lost (which happens when coolify container stops) # We use a subshell with nohup to ensure completion log "Starting container restart sequence (detached)..." nohup bash -c " LOGFILE='$LOGFILE' STATUS_FILE='$STATUS_FILE' DOCKER_CONFIG_MOUNT='$DOCKER_CONFIG_MOUNT' REGISTRY_URL='$REGISTRY_URL' LATEST_HELPER_VERSION='$LATEST_HELPER_VERSION' LATEST_IMAGE='$LATEST_IMAGE' log() { echo \"[\$(date '+%Y-%m-%d %H:%M:%S')] \$1\" >>\"\$LOGFILE\" } write_status() { echo \"\$1|\$2|\$(date -Iseconds)\" > \"\$STATUS_FILE\" } # Stop and remove containers for container in coolify coolify-db coolify-redis coolify-realtime; do if docker ps -a --format '{{.Names}}' | grep -q \"^\${container}\$\"; then log \"Stopping container: \${container}\" docker stop \"\$container\" >>\"\$LOGFILE\" 2>&1 || true log \"Removing container: \${container}\" docker rm \"\$container\" >>\"\$LOGFILE\" 2>&1 || true log \"Container \${container} stopped and removed\" else log \"Container \${container} not found (skipping)\" fi done log \"Container cleanup complete\" # Start new containers echo '' >>\"\$LOGFILE\" echo '============================================================' >>\"\$LOGFILE\" log 'Step 5/6: Starting new containers' echo '============================================================' >>\"\$LOGFILE\" write_status '5' 'Starting new containers' if [ -f /data/coolify/source/docker-compose.custom.yml ]; then log 'Using custom docker-compose.yml' log 'Running docker compose up with custom configuration...' docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock \${DOCKER_CONFIG_MOUNT} --rm \${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-helper:\${LATEST_HELPER_VERSION} bash -c \"LATEST_IMAGE=\${LATEST_IMAGE} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml -f /data/coolify/source/docker-compose.custom.yml up -d --remove-orphans --wait --wait-timeout 60\" >>\"\$LOGFILE\" 2>&1 else log 'Using standard docker-compose configuration' log 'Running docker compose up...' docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock \${DOCKER_CONFIG_MOUNT} --rm \${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-helper:\${LATEST_HELPER_VERSION} bash -c \"LATEST_IMAGE=\${LATEST_IMAGE} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml up -d --remove-orphans --wait --wait-timeout 60\" >>\"\$LOGFILE\" 2>&1 fi log 'Docker compose up completed' # Final log entry echo '' >>\"\$LOGFILE\" echo '============================================================' >>\"\$LOGFILE\" log 'Step 6/6: Upgrade complete' echo '============================================================' >>\"\$LOGFILE\" write_status '6' 'Upgrade complete' log 'Coolify upgrade completed successfully' log \"Version: \${LATEST_IMAGE}\" echo '' >>\"\$LOGFILE\" echo '============================================================' >>\"\$LOGFILE\" echo \"Upgrade completed: \$(date '+%Y-%m-%d %H:%M:%S')\" >>\"\$LOGFILE\" echo '============================================================' >>\"\$LOGFILE\" # Clean up status file after a short delay to allow frontend to read completion sleep 10 rm -f \"\$STATUS_FILE\" log 'Status file cleaned up' " >>"$LOGFILE" 2>&1 & # Give the background process a moment to start sleep 2 log "Container restart sequence started in background (PID: $!)" echo "" echo "5/6 Containers are being restarted in the background..." echo "6/6 Upgrade process initiated!" echo "" echo "==========================================" echo " Coolify upgrade to ${LATEST_IMAGE} in progress" echo "==========================================" echo "" echo " The upgrade will continue in the background." echo " Coolify will be available again shortly." echo " Log file: ${LOGFILE}" ================================================ FILE: other/nightly/versions.json ================================================ { "coolify": { "v4": { "version": "4.0.0-beta.468" }, "nightly": { "version": "4.0.0-beta.469" }, "helper": { "version": "1.0.12" }, "realtime": { "version": "1.0.11" }, "sentinel": { "version": "0.0.19" } }, "traefik": { "v3.6": "3.6.5", "v3.5": "3.5.6", "v3.4": "3.4.5", "v3.3": "3.3.7", "v3.2": "3.2.5", "v3.1": "3.1.7", "v3.0": "3.0.4", "v2.11": "2.11.32" } } ================================================ FILE: package.json ================================================ { "name": "coolify", "private": true, "type": "module", "scripts": { "dev": "vite", "build": "vite build" }, "devDependencies": { "@tailwindcss/postcss": "4.1.18", "@vitejs/plugin-vue": "6.0.3", "axios": "1.13.2", "laravel-echo": "2.2.7", "laravel-vite-plugin": "2.0.1", "postcss": "8.5.6", "pusher-js": "8.4.0", "tailwind-scrollbar": "4.0.2", "tailwindcss": "4.1.18", "vite": "7.3.0", "vue": "3.5.26" }, "dependencies": { "@tailwindcss/forms": "0.5.10", "@tailwindcss/typography": "0.5.16", "@xterm/addon-fit": "0.10.0", "@xterm/xterm": "5.5.0", "ioredis": "5.6.1", "playwright": "^1.58.2" } } ================================================ FILE: phpunit.dusk.xml ================================================ ./tests/Browser ================================================ FILE: phpunit.xml ================================================ ./tests/Unit ./tests/Feature ./tests/v4 ./app ================================================ FILE: pint.json ================================================ { "preset": "laravel" } ================================================ FILE: postcss.config.cjs ================================================ module.exports = { plugins: { '@tailwindcss/postcss': {}, }, } ================================================ FILE: public/index.php ================================================ make(Kernel::class); $response = $kernel->handle( $request = Request::capture() )->send(); $kernel->terminate($request, $response); ================================================ FILE: public/js/apexcharts.js ================================================ /*! * ApexCharts v3.49.1 * (c) 2018-2024 ApexCharts * Released under the MIT License. */ !function (t, e) { "object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).ApexCharts = e() }(this, (function () { "use strict"; function t(t, e) { var i = Object.keys(t); if (Object.getOwnPropertySymbols) { var a = Object.getOwnPropertySymbols(t); e && (a = a.filter((function (e) { return Object.getOwnPropertyDescriptor(t, e).enumerable }))), i.push.apply(i, a) } return i } function e(e) { for (var i = 1; i < arguments.length; i++) { var a = null != arguments[i] ? arguments[i] : {}; i % 2 ? t(Object(a), !0).forEach((function (t) { o(e, t, a[t]) })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(a)) : t(Object(a)).forEach((function (t) { Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(a, t)) })) } return e } function i(t) { return i = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (t) { return typeof t } : function (t) { return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t }, i(t) } function a(t, e) { if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function") } function s(t, e) { for (var i = 0; i < e.length; i++) { var a = e[i]; a.enumerable = a.enumerable || !1, a.configurable = !0, "value" in a && (a.writable = !0), Object.defineProperty(t, a.key, a) } } function r(t, e, i) { return e && s(t.prototype, e), i && s(t, i), t } function o(t, e, i) { return e in t ? Object.defineProperty(t, e, { value: i, enumerable: !0, configurable: !0, writable: !0 }) : t[e] = i, t } function n(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), e && h(t, e) } function l(t) { return l = Object.setPrototypeOf ? Object.getPrototypeOf : function (t) { return t.__proto__ || Object.getPrototypeOf(t) }, l(t) } function h(t, e) { return h = Object.setPrototypeOf || function (t, e) { return t.__proto__ = e, t }, h(t, e) } function c(t) { if (void 0 === t) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return t } function d(t) { var e = function () { if ("undefined" == typeof Reflect || !Reflect.construct) return !1; if (Reflect.construct.sham) return !1; if ("function" == typeof Proxy) return !0; try { return Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], (function () { }))), !0 } catch (t) { return !1 } }(); return function () { var i, a = l(t); if (e) { var s = l(this).constructor; i = Reflect.construct(a, arguments, s) } else i = a.apply(this, arguments); return function (t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return c(t) }(this, i) } } function g(t, e) { return function (t) { if (Array.isArray(t)) return t }(t) || function (t, e) { var i = null == t ? null : "undefined" != typeof Symbol && t[Symbol.iterator] || t["@@iterator"]; if (null == i) return; var a, s, r = [], o = !0, n = !1; try { for (i = i.call(t); !(o = (a = i.next()).done) && (r.push(a.value), !e || r.length !== e); o = !0); } catch (t) { n = !0, s = t } finally { try { o || null == i.return || i.return() } finally { if (n) throw s } } return r }(t, e) || p(t, e) || function () { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") }() } function u(t) { return function (t) { if (Array.isArray(t)) return f(t) }(t) || function (t) { if ("undefined" != typeof Symbol && null != t[Symbol.iterator] || null != t["@@iterator"]) return Array.from(t) }(t) || p(t) || function () { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") }() } function p(t, e) { if (t) { if ("string" == typeof t) return f(t, e); var i = Object.prototype.toString.call(t).slice(8, -1); return "Object" === i && t.constructor && (i = t.constructor.name), "Map" === i || "Set" === i ? Array.from(t) : "Arguments" === i || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i) ? f(t, e) : void 0 } } function f(t, e) { (null == e || e > t.length) && (e = t.length); for (var i = 0, a = new Array(e); i < e; i++)a[i] = t[i]; return a } var x = function () { function t() { a(this, t) } return r(t, [{ key: "shadeRGBColor", value: function (t, e) { var i = e.split(","), a = t < 0 ? 0 : 255, s = t < 0 ? -1 * t : t, r = parseInt(i[0].slice(4), 10), o = parseInt(i[1], 10), n = parseInt(i[2], 10); return "rgb(" + (Math.round((a - r) * s) + r) + "," + (Math.round((a - o) * s) + o) + "," + (Math.round((a - n) * s) + n) + ")" } }, { key: "shadeHexColor", value: function (t, e) { var i = parseInt(e.slice(1), 16), a = t < 0 ? 0 : 255, s = t < 0 ? -1 * t : t, r = i >> 16, o = i >> 8 & 255, n = 255 & i; return "#" + (16777216 + 65536 * (Math.round((a - r) * s) + r) + 256 * (Math.round((a - o) * s) + o) + (Math.round((a - n) * s) + n)).toString(16).slice(1) } }, { key: "shadeColor", value: function (e, i) { return t.isColorHex(i) ? this.shadeHexColor(e, i) : this.shadeRGBColor(e, i) } }], [{ key: "bind", value: function (t, e) { return function () { return t.apply(e, arguments) } } }, { key: "isObject", value: function (t) { return t && "object" === i(t) && !Array.isArray(t) && null != t } }, { key: "is", value: function (t, e) { return Object.prototype.toString.call(e) === "[object " + t + "]" } }, { key: "listToArray", value: function (t) { var e, i = []; for (e = 0; e < t.length; e++)i[e] = t[e]; return i } }, { key: "extend", value: function (t, e) { var i = this; "function" != typeof Object.assign && (Object.assign = function (t) { if (null == t) throw new TypeError("Cannot convert undefined or null to object"); for (var e = Object(t), i = 1; i < arguments.length; i++) { var a = arguments[i]; if (null != a) for (var s in a) a.hasOwnProperty(s) && (e[s] = a[s]) } return e }); var a = Object.assign({}, t); return this.isObject(t) && this.isObject(e) && Object.keys(e).forEach((function (s) { i.isObject(e[s]) && s in t ? a[s] = i.extend(t[s], e[s]) : Object.assign(a, o({}, s, e[s])) })), a } }, { key: "extendArray", value: function (e, i) { var a = []; return e.map((function (e) { a.push(t.extend(i, e)) })), e = a } }, { key: "monthMod", value: function (t) { return t % 12 } }, { key: "clone", value: function (e) { if (t.is("Array", e)) { for (var a = [], s = 0; s < e.length; s++)a[s] = this.clone(e[s]); return a } if (t.is("Null", e)) return null; if (t.is("Date", e)) return e; if ("object" === i(e)) { var r = {}; for (var o in e) e.hasOwnProperty(o) && (r[o] = this.clone(e[o])); return r } return e } }, { key: "log10", value: function (t) { return Math.log(t) / Math.LN10 } }, { key: "roundToBase10", value: function (t) { return Math.pow(10, Math.floor(Math.log10(t))) } }, { key: "roundToBase", value: function (t, e) { return Math.pow(e, Math.floor(Math.log(t) / Math.log(e))) } }, { key: "parseNumber", value: function (t) { return null === t ? t : parseFloat(t) } }, { key: "stripNumber", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 2; return Number.isInteger(t) ? t : parseFloat(t.toPrecision(e)) } }, { key: "randomId", value: function () { return (Math.random() + 1).toString(36).substring(4) } }, { key: "noExponents", value: function (t) { var e = String(t).split(/[eE]/); if (1 === e.length) return e[0]; var i = "", a = t < 0 ? "-" : "", s = e[0].replace(".", ""), r = Number(e[1]) + 1; if (r < 0) { for (i = a + "0."; r++;)i += "0"; return i + s.replace(/^-/, "") } for (r -= s.length; r--;)i += "0"; return s + i } }, { key: "getDimensions", value: function (t) { var e = getComputedStyle(t, null), i = t.clientHeight, a = t.clientWidth; return i -= parseFloat(e.paddingTop) + parseFloat(e.paddingBottom), [a -= parseFloat(e.paddingLeft) + parseFloat(e.paddingRight), i] } }, { key: "getBoundingClientRect", value: function (t) { var e = t.getBoundingClientRect(); return { top: e.top, right: e.right, bottom: e.bottom, left: e.left, width: t.clientWidth, height: t.clientHeight, x: e.left, y: e.top } } }, { key: "getLargestStringFromArr", value: function (t) { return t.reduce((function (t, e) { return Array.isArray(e) && (e = e.reduce((function (t, e) { return t.length > e.length ? t : e }))), t.length > e.length ? t : e }), 0) } }, { key: "hexToRgba", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "#999999", e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : .6; "#" !== t.substring(0, 1) && (t = "#999999"); var i = t.replace("#", ""); i = i.match(new RegExp("(.{" + i.length / 3 + "})", "g")); for (var a = 0; a < i.length; a++)i[a] = parseInt(1 === i[a].length ? i[a] + i[a] : i[a], 16); return void 0 !== e && i.push(e), "rgba(" + i.join(",") + ")" } }, { key: "getOpacityFromRGBA", value: function (t) { return parseFloat(t.replace(/^.*,(.+)\)/, "$1")) } }, { key: "rgb2hex", value: function (t) { return (t = t.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i)) && 4 === t.length ? "#" + ("0" + parseInt(t[1], 10).toString(16)).slice(-2) + ("0" + parseInt(t[2], 10).toString(16)).slice(-2) + ("0" + parseInt(t[3], 10).toString(16)).slice(-2) : "" } }, { key: "isColorHex", value: function (t) { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)|(^#[0-9A-F]{8}$)/i.test(t) } }, { key: "getPolygonPos", value: function (t, e) { for (var i = [], a = 2 * Math.PI / e, s = 0; s < e; s++) { var r = {}; r.x = t * Math.sin(s * a), r.y = -t * Math.cos(s * a), i.push(r) } return i } }, { key: "polarToCartesian", value: function (t, e, i, a) { var s = (a - 90) * Math.PI / 180; return { x: t + i * Math.cos(s), y: e + i * Math.sin(s) } } }, { key: "escapeString", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "x", i = t.toString().slice(); return i = i.replace(/[` ~!@#$%^&*()|+\=?;:'",.<>{}[\]\\/]/gi, e) } }, { key: "negToZero", value: function (t) { return t < 0 ? 0 : t } }, { key: "moveIndexInArray", value: function (t, e, i) { if (i >= t.length) for (var a = i - t.length + 1; a--;)t.push(void 0); return t.splice(i, 0, t.splice(e, 1)[0]), t } }, { key: "extractNumber", value: function (t) { return parseFloat(t.replace(/[^\d.]*/g, "")) } }, { key: "findAncestor", value: function (t, e) { for (; (t = t.parentElement) && !t.classList.contains(e);); return t } }, { key: "setELstyles", value: function (t, e) { for (var i in e) e.hasOwnProperty(i) && (t.style.key = e[i]) } }, { key: "isNumber", value: function (t) { return !isNaN(t) && parseFloat(Number(t)) === t && !isNaN(parseInt(t, 10)) } }, { key: "isFloat", value: function (t) { return Number(t) === t && t % 1 != 0 } }, { key: "isSafari", value: function () { return /^((?!chrome|android).)*safari/i.test(navigator.userAgent) } }, { key: "isFirefox", value: function () { return navigator.userAgent.toLowerCase().indexOf("firefox") > -1 } }, { key: "isIE11", value: function () { if (-1 !== window.navigator.userAgent.indexOf("MSIE") || window.navigator.appVersion.indexOf("Trident/") > -1) return !0 } }, { key: "isIE", value: function () { var t = window.navigator.userAgent, e = t.indexOf("MSIE "); if (e > 0) return parseInt(t.substring(e + 5, t.indexOf(".", e)), 10); if (t.indexOf("Trident/") > 0) { var i = t.indexOf("rv:"); return parseInt(t.substring(i + 3, t.indexOf(".", i)), 10) } var a = t.indexOf("Edge/"); return a > 0 && parseInt(t.substring(a + 5, t.indexOf(".", a)), 10) } }, { key: "getGCD", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 7, a = Math.pow(10, i - Math.floor(Math.log10(Math.max(t, e)))); for (t = Math.round(Math.abs(t) * a), e = Math.round(Math.abs(e) * a); e;) { var s = e; e = t % e, t = s } return t / a } }, { key: "getPrimeFactors", value: function (t) { for (var e = [], i = 2; t >= 2;)t % i == 0 ? (e.push(i), t /= i) : i++; return e } }, { key: "mod", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 7, a = Math.pow(10, i - Math.floor(Math.log10(Math.max(t, e)))); return (t = Math.round(Math.abs(t) * a)) % (e = Math.round(Math.abs(e) * a)) / a } }]), t }(), b = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.setEasingFunctions() } return r(t, [{ key: "setEasingFunctions", value: function () { var t; if (!this.w.globals.easing) { switch (this.w.config.chart.animations.easing) { case "linear": t = "-"; break; case "easein": t = "<"; break; case "easeout": t = ">"; break; case "easeinout": default: t = "<>"; break; case "swing": t = function (t) { var e = 1.70158; return (t -= 1) * t * ((e + 1) * t + e) + 1 }; break; case "bounce": t = function (t) { return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375 }; break; case "elastic": t = function (t) { return t === !!t ? t : Math.pow(2, -10 * t) * Math.sin((t - .075) * (2 * Math.PI) / .3) + 1 } }this.w.globals.easing = t } } }, { key: "animateLine", value: function (t, e, i, a) { t.attr(e).animate(a).attr(i) } }, { key: "animateMarker", value: function (t, e, i, a, s, r) { e || (e = 0), t.attr({ r: e, width: e, height: e }).animate(a, s).attr({ r: i, width: i.width, height: i.height }).afterAll((function () { r() })) } }, { key: "animateCircle", value: function (t, e, i, a, s) { t.attr({ r: e.r, cx: e.cx, cy: e.cy }).animate(a, s).attr({ r: i.r, cx: i.cx, cy: i.cy }) } }, { key: "animateRect", value: function (t, e, i, a, s) { t.attr(e).animate(a).attr(i).afterAll((function () { return s() })) } }, { key: "animatePathsGradually", value: function (t) { var e = t.el, i = t.realIndex, a = t.j, s = t.fill, r = t.pathFrom, o = t.pathTo, n = t.speed, l = t.delay, h = this.w, c = 0; h.config.chart.animations.animateGradually.enabled && (c = h.config.chart.animations.animateGradually.delay), h.config.chart.animations.dynamicAnimation.enabled && h.globals.dataChanged && "bar" !== h.config.chart.type && (c = 0), this.morphSVG(e, i, a, "line" !== h.config.chart.type || h.globals.comboCharts ? s : "stroke", r, o, n, l * c) } }, { key: "showDelayedElements", value: function () { this.w.globals.delayedElements.forEach((function (t) { var e = t.el; e.classList.remove("apexcharts-element-hidden"), e.classList.add("apexcharts-hidden-element-shown") })) } }, { key: "animationCompleted", value: function (t) { var e = this.w; e.globals.animationEnded || (e.globals.animationEnded = !0, this.showDelayedElements(), "function" == typeof e.config.chart.events.animationEnd && e.config.chart.events.animationEnd(this.ctx, { el: t, w: e })) } }, { key: "morphSVG", value: function (t, e, i, a, s, r, o, n) { var l = this, h = this.w; s || (s = t.attr("pathFrom")), r || (r = t.attr("pathTo")); var c = function (t) { return "radar" === h.config.chart.type && (o = 1), "M 0 ".concat(h.globals.gridHeight) }; (!s || s.indexOf("undefined") > -1 || s.indexOf("NaN") > -1) && (s = c()), (!r || r.indexOf("undefined") > -1 || r.indexOf("NaN") > -1) && (r = c()), h.globals.shouldAnimate || (o = 1), t.plot(s).animate(1, h.globals.easing, n).plot(s).animate(o, h.globals.easing, n).plot(r).afterAll((function () { x.isNumber(i) ? i === h.globals.series[h.globals.maxValsInArrayIndex].length - 2 && h.globals.shouldAnimate && l.animationCompleted(t) : "none" !== a && h.globals.shouldAnimate && (!h.globals.comboCharts && e === h.globals.series.length - 1 || h.globals.comboCharts) && l.animationCompleted(t), l.showDelayedElements() })) } }]), t }(), v = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "getDefaultFilter", value: function (t, e) { var i = this.w; t.unfilter(!0), (new window.SVG.Filter).size("120%", "180%", "-5%", "-40%"), "none" !== i.config.states.normal.filter ? this.applyFilter(t, e, i.config.states.normal.filter.type, i.config.states.normal.filter.value) : i.config.chart.dropShadow.enabled && this.dropShadow(t, i.config.chart.dropShadow, e) } }, { key: "addNormalFilter", value: function (t, e) { var i = this.w; i.config.chart.dropShadow.enabled && !t.node.classList.contains("apexcharts-marker") && this.dropShadow(t, i.config.chart.dropShadow, e) } }, { key: "addLightenFilter", value: function (t, e, i) { var a = this, s = this.w, r = i.intensity; t.unfilter(!0); new window.SVG.Filter; t.filter((function (t) { var i = s.config.chart.dropShadow; (i.enabled ? a.addShadow(t, e, i) : t).componentTransfer({ rgb: { type: "linear", slope: 1.5, intercept: r } }) })), t.filterer.node.setAttribute("filterUnits", "userSpaceOnUse"), this._scaleFilterSize(t.filterer.node) } }, { key: "addDarkenFilter", value: function (t, e, i) { var a = this, s = this.w, r = i.intensity; t.unfilter(!0); new window.SVG.Filter; t.filter((function (t) { var i = s.config.chart.dropShadow; (i.enabled ? a.addShadow(t, e, i) : t).componentTransfer({ rgb: { type: "linear", slope: r } }) })), t.filterer.node.setAttribute("filterUnits", "userSpaceOnUse"), this._scaleFilterSize(t.filterer.node) } }, { key: "applyFilter", value: function (t, e, i) { var a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : .5; switch (i) { case "none": this.addNormalFilter(t, e); break; case "lighten": this.addLightenFilter(t, e, { intensity: a }); break; case "darken": this.addDarkenFilter(t, e, { intensity: a }) } } }, { key: "addShadow", value: function (t, e, i) { var a, s = this.w, r = i.blur, o = i.top, n = i.left, l = i.color, h = i.opacity; if ((null === (a = s.config.chart.dropShadow.enabledOnSeries) || void 0 === a ? void 0 : a.length) > 0 && -1 === s.config.chart.dropShadow.enabledOnSeries.indexOf(e)) return t; var c = t.flood(Array.isArray(l) ? l[e] : l, h).composite(t.sourceAlpha, "in").offset(n, o).gaussianBlur(r).merge(t.source); return t.blend(t.source, c) } }, { key: "dropShadow", value: function (t, e) { var i, a, s = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 0, r = e.top, o = e.left, n = e.blur, l = e.color, h = e.opacity, c = e.noUserSpaceOnUse, d = this.w; if (t.unfilter(!0), x.isIE() && "radialBar" === d.config.chart.type) return t; if ((null === (i = d.config.chart.dropShadow.enabledOnSeries) || void 0 === i ? void 0 : i.length) > 0 && -1 === (null === (a = d.config.chart.dropShadow.enabledOnSeries) || void 0 === a ? void 0 : a.indexOf(s))) return t; return l = Array.isArray(l) ? l[s] : l, t.filter((function (t) { var e = null; e = x.isSafari() || x.isFirefox() || x.isIE() ? t.flood(l, h).composite(t.sourceAlpha, "in").offset(o, r).gaussianBlur(n) : t.flood(l, h).composite(t.sourceAlpha, "in").offset(o, r).gaussianBlur(n).merge(t.source), t.blend(t.source, e) })), c || t.filterer.node.setAttribute("filterUnits", "userSpaceOnUse"), this._scaleFilterSize(t.filterer.node), t } }, { key: "setSelectionFilter", value: function (t, e, i) { var a = this.w; if (void 0 !== a.globals.selectedDataPoints[e] && a.globals.selectedDataPoints[e].indexOf(i) > -1) { t.node.setAttribute("selected", !0); var s = a.config.states.active.filter; "none" !== s && this.applyFilter(t, e, s.type, s.value) } } }, { key: "_scaleFilterSize", value: function (t) { !function (e) { for (var i in e) e.hasOwnProperty(i) && t.setAttribute(i, e[i]) }({ width: "200%", height: "200%", x: "-50%", y: "-50%" }) } }]), t }(), m = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "roundPathCorners", value: function (t, e) { function i(t, e, i) { var s = e.x - t.x, r = e.y - t.y, o = Math.sqrt(s * s + r * r); return a(t, e, Math.min(1, i / o)) } function a(t, e, i) { return { x: t.x + (e.x - t.x) * i, y: t.y + (e.y - t.y) * i } } function s(t, e) { t.length > 2 && (t[t.length - 2] = e.x, t[t.length - 1] = e.y) } function r(t) { return { x: parseFloat(t[t.length - 2]), y: parseFloat(t[t.length - 1]) } } t.indexOf("NaN") > -1 && (t = ""); var o = t.split(/[,\s]/).reduce((function (t, e) { var i = e.match("([a-zA-Z])(.+)"); return i ? (t.push(i[1]), t.push(i[2])) : t.push(e), t }), []).reduce((function (t, e) { return parseFloat(e) == e && t.length ? t[t.length - 1].push(e) : t.push([e]), t }), []), n = []; if (o.length > 1) { var l = r(o[0]), h = null; "Z" == o[o.length - 1][0] && o[0].length > 2 && (h = ["L", l.x, l.y], o[o.length - 1] = h), n.push(o[0]); for (var c = 1; c < o.length; c++) { var d = n[n.length - 1], g = o[c], u = g == h ? o[1] : o[c + 1]; if (u && d && d.length > 2 && "L" == g[0] && u.length > 2 && "L" == u[0]) { var p, f, x = r(d), b = r(g), v = r(u); p = i(b, x, e), f = i(b, v, e), s(g, p), g.origPoint = b, n.push(g); var m = a(p, b, .5), y = a(b, f, .5), w = ["C", m.x, m.y, y.x, y.y, f.x, f.y]; w.origPoint = b, n.push(w) } else n.push(g) } if (h) { var k = r(n[n.length - 1]); n.push(["Z"]), s(n[0], k) } } else n = o; return n.reduce((function (t, e) { return t + e.join(" ") + " " }), "") } }, { key: "drawLine", value: function (t, e, i, a) { var s = arguments.length > 4 && void 0 !== arguments[4] ? arguments[4] : "#a8a8a8", r = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : 0, o = arguments.length > 6 && void 0 !== arguments[6] ? arguments[6] : null, n = arguments.length > 7 && void 0 !== arguments[7] ? arguments[7] : "butt"; return this.w.globals.dom.Paper.line().attr({ x1: t, y1: e, x2: i, y2: a, stroke: s, "stroke-dasharray": r, "stroke-width": o, "stroke-linecap": n }) } }, { key: "drawRect", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 0, e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0, i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 0, a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : 0, s = arguments.length > 4 && void 0 !== arguments[4] ? arguments[4] : 0, r = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : "#fefefe", o = arguments.length > 6 && void 0 !== arguments[6] ? arguments[6] : 1, n = arguments.length > 7 && void 0 !== arguments[7] ? arguments[7] : null, l = arguments.length > 8 && void 0 !== arguments[8] ? arguments[8] : null, h = arguments.length > 9 && void 0 !== arguments[9] ? arguments[9] : 0, c = this.w.globals.dom.Paper.rect(); return c.attr({ x: t, y: e, width: i > 0 ? i : 0, height: a > 0 ? a : 0, rx: s, ry: s, opacity: o, "stroke-width": null !== n ? n : 0, stroke: null !== l ? l : "none", "stroke-dasharray": h }), c.node.setAttribute("fill", r), c } }, { key: "drawPolygon", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "#e1e1e1", i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1, a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : "none"; return this.w.globals.dom.Paper.polygon(t).attr({ fill: a, stroke: e, "stroke-width": i }) } }, { key: "drawCircle", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null; t < 0 && (t = 0); var i = this.w.globals.dom.Paper.circle(2 * t); return null !== e && i.attr(e), i } }, { key: "drawPath", value: function (t) { var e = t.d, i = void 0 === e ? "" : e, a = t.stroke, s = void 0 === a ? "#a8a8a8" : a, r = t.strokeWidth, o = void 0 === r ? 1 : r, n = t.fill, l = t.fillOpacity, h = void 0 === l ? 1 : l, c = t.strokeOpacity, d = void 0 === c ? 1 : c, g = t.classes, u = t.strokeLinecap, p = void 0 === u ? null : u, f = t.strokeDashArray, x = void 0 === f ? 0 : f, b = this.w; return null === p && (p = b.config.stroke.lineCap), (i.indexOf("undefined") > -1 || i.indexOf("NaN") > -1) && (i = "M 0 ".concat(b.globals.gridHeight)), b.globals.dom.Paper.path(i).attr({ fill: n, "fill-opacity": h, stroke: s, "stroke-opacity": d, "stroke-linecap": p, "stroke-width": o, "stroke-dasharray": x, class: g }) } }, { key: "group", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : null, e = this.w.globals.dom.Paper.group(); return null !== t && e.attr(t), e } }, { key: "move", value: function (t, e) { var i = ["M", t, e].join(" "); return i } }, { key: "line", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : null, a = null; return null === i ? a = [" L", t, e].join(" ") : "H" === i ? a = [" H", t].join(" ") : "V" === i && (a = [" V", e].join(" ")), a } }, { key: "curve", value: function (t, e, i, a, s, r) { var o = ["C", t, e, i, a, s, r].join(" "); return o } }, { key: "quadraticCurve", value: function (t, e, i, a) { return ["Q", t, e, i, a].join(" ") } }, { key: "arc", value: function (t, e, i, a, s, r, o) { var n = "A"; arguments.length > 7 && void 0 !== arguments[7] && arguments[7] && (n = "a"); var l = [n, t, e, i, a, s, r, o].join(" "); return l } }, { key: "renderPaths", value: function (t) { var i, a = t.j, s = t.realIndex, r = t.pathFrom, o = t.pathTo, n = t.stroke, l = t.strokeWidth, h = t.strokeLinecap, c = t.fill, d = t.animationDelay, g = t.initialSpeed, u = t.dataChangeSpeed, p = t.className, f = t.shouldClipToGrid, x = void 0 === f || f, m = t.bindEventsOnPaths, y = void 0 === m || m, w = t.drawShadow, k = void 0 === w || w, A = this.w, S = new v(this.ctx), C = new b(this.ctx), L = this.w.config.chart.animations.enabled, P = L && this.w.config.chart.animations.dynamicAnimation.enabled, M = !!(L && !A.globals.resized || P && A.globals.dataChanged && A.globals.shouldAnimate); M ? i = r : (i = o, A.globals.animationEnded = !0); var I = A.config.stroke.dashArray, T = 0; T = Array.isArray(I) ? I[s] : A.config.stroke.dashArray; var z = this.drawPath({ d: i, stroke: n, strokeWidth: l, fill: c, fillOpacity: 1, classes: p, strokeLinecap: h, strokeDashArray: T }); if (z.attr("index", s), x && z.attr({ "clip-path": "url(#gridRectMask".concat(A.globals.cuid, ")") }), "none" !== A.config.states.normal.filter.type) S.getDefaultFilter(z, s); else if (A.config.chart.dropShadow.enabled && k) { var X = A.config.chart.dropShadow; S.dropShadow(z, X, s) } y && (z.node.addEventListener("mouseenter", this.pathMouseEnter.bind(this, z)), z.node.addEventListener("mouseleave", this.pathMouseLeave.bind(this, z)), z.node.addEventListener("mousedown", this.pathMouseDown.bind(this, z))), z.attr({ pathTo: o, pathFrom: r }); var E = { el: z, j: a, realIndex: s, pathFrom: r, pathTo: o, fill: c, strokeWidth: l, delay: d }; return !L || A.globals.resized || A.globals.dataChanged ? !A.globals.resized && A.globals.dataChanged || C.showDelayedElements() : C.animatePathsGradually(e(e({}, E), {}, { speed: g })), A.globals.dataChanged && P && M && C.animatePathsGradually(e(e({}, E), {}, { speed: u })), z } }, { key: "drawPattern", value: function (t, e, i) { var a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : "#a8a8a8", s = arguments.length > 4 && void 0 !== arguments[4] ? arguments[4] : 0; return this.w.globals.dom.Paper.pattern(e, i, (function (r) { "horizontalLines" === t ? r.line(0, 0, i, 0).stroke({ color: a, width: s + 1 }) : "verticalLines" === t ? r.line(0, 0, 0, e).stroke({ color: a, width: s + 1 }) : "slantedLines" === t ? r.line(0, 0, e, i).stroke({ color: a, width: s }) : "squares" === t ? r.rect(e, i).fill("none").stroke({ color: a, width: s }) : "circles" === t && r.circle(e).fill("none").stroke({ color: a, width: s }) })) } }, { key: "drawGradient", value: function (t, e, i, a, s) { var r, o = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : null, n = arguments.length > 6 && void 0 !== arguments[6] ? arguments[6] : null, l = arguments.length > 7 && void 0 !== arguments[7] ? arguments[7] : null, h = arguments.length > 8 && void 0 !== arguments[8] ? arguments[8] : 0, c = this.w; e.length < 9 && 0 === e.indexOf("#") && (e = x.hexToRgba(e, a)), i.length < 9 && 0 === i.indexOf("#") && (i = x.hexToRgba(i, s)); var d = 0, g = 1, u = 1, p = null; null !== n && (d = void 0 !== n[0] ? n[0] / 100 : 0, g = void 0 !== n[1] ? n[1] / 100 : 1, u = void 0 !== n[2] ? n[2] / 100 : 1, p = void 0 !== n[3] ? n[3] / 100 : null); var f = !("donut" !== c.config.chart.type && "pie" !== c.config.chart.type && "polarArea" !== c.config.chart.type && "bubble" !== c.config.chart.type); if (r = null === l || 0 === l.length ? c.globals.dom.Paper.gradient(f ? "radial" : "linear", (function (t) { t.at(d, e, a), t.at(g, i, s), t.at(u, i, s), null !== p && t.at(p, e, a) })) : c.globals.dom.Paper.gradient(f ? "radial" : "linear", (function (t) { (Array.isArray(l[h]) ? l[h] : l).forEach((function (e) { t.at(e.offset / 100, e.color, e.opacity) })) })), f) { var b = c.globals.gridWidth / 2, v = c.globals.gridHeight / 2; "bubble" !== c.config.chart.type ? r.attr({ gradientUnits: "userSpaceOnUse", cx: b, cy: v, r: o }) : r.attr({ cx: .5, cy: .5, r: .8, fx: .2, fy: .2 }) } else "vertical" === t ? r.from(0, 0).to(0, 1) : "diagonal" === t ? r.from(0, 0).to(1, 1) : "horizontal" === t ? r.from(0, 1).to(1, 1) : "diagonal2" === t && r.from(1, 0).to(0, 1); return r } }, { key: "getTextBasedOnMaxWidth", value: function (t) { var e = t.text, i = t.maxWidth, a = t.fontSize, s = t.fontFamily, r = this.getTextRects(e, a, s), o = r.width / e.length, n = Math.floor(i / o); return i < r.width ? e.slice(0, n - 3) + "..." : e } }, { key: "drawText", value: function (t) { var i = this, a = t.x, s = t.y, r = t.text, o = t.textAnchor, n = t.fontSize, l = t.fontFamily, h = t.fontWeight, c = t.foreColor, d = t.opacity, g = t.maxWidth, u = t.cssClass, p = void 0 === u ? "" : u, f = t.isPlainText, x = void 0 === f || f, b = t.dominantBaseline, v = void 0 === b ? "auto" : b, m = this.w; void 0 === r && (r = ""); var y = r; o || (o = "start"), c && c.length || (c = m.config.chart.foreColor), l = l || m.config.chart.fontFamily, h = h || "regular"; var w, k = { maxWidth: g, fontSize: n = n || "11px", fontFamily: l }; return Array.isArray(r) ? w = m.globals.dom.Paper.text((function (t) { for (var a = 0; a < r.length; a++)y = r[a], g && (y = i.getTextBasedOnMaxWidth(e({ text: r[a] }, k))), 0 === a ? t.tspan(y) : t.tspan(y).newLine() })) : (g && (y = this.getTextBasedOnMaxWidth(e({ text: r }, k))), w = x ? m.globals.dom.Paper.plain(r) : m.globals.dom.Paper.text((function (t) { return t.tspan(y) }))), w.attr({ x: a, y: s, "text-anchor": o, "dominant-baseline": v, "font-size": n, "font-family": l, "font-weight": h, fill: c, class: "apexcharts-text " + p }), w.node.style.fontFamily = l, w.node.style.opacity = d, w } }, { key: "createGroupWithAttributes", value: function (t, e, i, a) { var s = this.group(); return i.forEach((function (t) { return s.add(t) })), s.attr({ class: a.class ? a.class : "", cy: e, cx: t }), s } }, { key: "drawPlus", value: function (t, e, i, a) { var s = i / 2, r = this.drawLine(t, e - s, t, e + s, a.pointStrokeColor, a.pointStrokeDashArray, a.pointStrokeWidth, a.pointStrokeLineCap), o = this.drawLine(t - s, e, t + s, e, a.pointStrokeColor, a.pointStrokeDashArray, a.pointStrokeWidth, a.pointStrokeLineCap); return this.createGroupWithAttributes(t, e, [r, o], a) } }, { key: "drawX", value: function (t, e, i, a) { var s = i / 2, r = this.drawLine(t - s, e - s, t + s, e + s, a.pointStrokeColor, a.pointStrokeDashArray, a.pointStrokeWidth, a.pointStrokeLineCap), o = this.drawLine(t - s, e + s, t + s, e - s, a.pointStrokeColor, a.pointStrokeDashArray, a.pointStrokeWidth, a.pointStrokeLineCap); return this.createGroupWithAttributes(t, e, [r, o], a) } }, { key: "drawMarker", value: function (t, e, i) { t = t || 0; var a = i.pSize || 0, s = null; if ("X" === (null == i ? void 0 : i.shape) || "x" === (null == i ? void 0 : i.shape)) s = this.drawX(t, e, a, i); else if ("plus" === (null == i ? void 0 : i.shape) || "+" === (null == i ? void 0 : i.shape)) s = this.drawPlus(t, e, a, i); else if ("square" === i.shape || "rect" === i.shape) { var r = void 0 === i.pRadius ? a / 2 : i.pRadius; null !== e && a || (a = 0, r = 0); var o = 1.2 * a + r, n = this.drawRect(o, o, o, o, r); n.attr({ x: t - o / 2, y: e - o / 2, cx: t, cy: e, class: i.class ? i.class : "", fill: i.pointFillColor, "fill-opacity": i.pointFillOpacity ? i.pointFillOpacity : 1, stroke: i.pointStrokeColor, "stroke-width": i.pointStrokeWidth ? i.pointStrokeWidth : 0, "stroke-opacity": i.pointStrokeOpacity ? i.pointStrokeOpacity : 1 }), s = n } else "circle" !== i.shape && i.shape || (x.isNumber(e) || (a = 0, e = 0), s = this.drawCircle(a, { cx: t, cy: e, class: i.class ? i.class : "", stroke: i.pointStrokeColor, fill: i.pointFillColor, "fill-opacity": i.pointFillOpacity ? i.pointFillOpacity : 1, "stroke-width": i.pointStrokeWidth ? i.pointStrokeWidth : 0, "stroke-opacity": i.pointStrokeOpacity ? i.pointStrokeOpacity : 1 })); return s } }, { key: "pathMouseEnter", value: function (t, e) { var i = this.w, a = new v(this.ctx), s = parseInt(t.node.getAttribute("index"), 10), r = parseInt(t.node.getAttribute("j"), 10); if ("function" == typeof i.config.chart.events.dataPointMouseEnter && i.config.chart.events.dataPointMouseEnter(e, this.ctx, { seriesIndex: s, dataPointIndex: r, w: i }), this.ctx.events.fireEvent("dataPointMouseEnter", [e, this.ctx, { seriesIndex: s, dataPointIndex: r, w: i }]), ("none" === i.config.states.active.filter.type || "true" !== t.node.getAttribute("selected")) && "none" !== i.config.states.hover.filter.type && !i.globals.isTouchDevice) { var o = i.config.states.hover.filter; a.applyFilter(t, s, o.type, o.value) } } }, { key: "pathMouseLeave", value: function (t, e) { var i = this.w, a = new v(this.ctx), s = parseInt(t.node.getAttribute("index"), 10), r = parseInt(t.node.getAttribute("j"), 10); "function" == typeof i.config.chart.events.dataPointMouseLeave && i.config.chart.events.dataPointMouseLeave(e, this.ctx, { seriesIndex: s, dataPointIndex: r, w: i }), this.ctx.events.fireEvent("dataPointMouseLeave", [e, this.ctx, { seriesIndex: s, dataPointIndex: r, w: i }]), "none" !== i.config.states.active.filter.type && "true" === t.node.getAttribute("selected") || "none" !== i.config.states.hover.filter.type && a.getDefaultFilter(t, s) } }, { key: "pathMouseDown", value: function (t, e) { var i = this.w, a = new v(this.ctx), s = parseInt(t.node.getAttribute("index"), 10), r = parseInt(t.node.getAttribute("j"), 10), o = "false"; if ("true" === t.node.getAttribute("selected")) { if (t.node.setAttribute("selected", "false"), i.globals.selectedDataPoints[s].indexOf(r) > -1) { var n = i.globals.selectedDataPoints[s].indexOf(r); i.globals.selectedDataPoints[s].splice(n, 1) } } else { if (!i.config.states.active.allowMultipleDataPointsSelection && i.globals.selectedDataPoints.length > 0) { i.globals.selectedDataPoints = []; var l = i.globals.dom.Paper.select(".apexcharts-series path").members, h = i.globals.dom.Paper.select(".apexcharts-series circle, .apexcharts-series rect").members, c = function (t) { Array.prototype.forEach.call(t, (function (t) { t.node.setAttribute("selected", "false"), a.getDefaultFilter(t, s) })) }; c(l), c(h) } t.node.setAttribute("selected", "true"), o = "true", void 0 === i.globals.selectedDataPoints[s] && (i.globals.selectedDataPoints[s] = []), i.globals.selectedDataPoints[s].push(r) } if ("true" === o) { var d = i.config.states.active.filter; if ("none" !== d) a.applyFilter(t, s, d.type, d.value); else if ("none" !== i.config.states.hover.filter && !i.globals.isTouchDevice) { var g = i.config.states.hover.filter; a.applyFilter(t, s, g.type, g.value) } } else if ("none" !== i.config.states.active.filter.type) if ("none" === i.config.states.hover.filter.type || i.globals.isTouchDevice) a.getDefaultFilter(t, s); else { g = i.config.states.hover.filter; a.applyFilter(t, s, g.type, g.value) } "function" == typeof i.config.chart.events.dataPointSelection && i.config.chart.events.dataPointSelection(e, this.ctx, { selectedDataPoints: i.globals.selectedDataPoints, seriesIndex: s, dataPointIndex: r, w: i }), e && this.ctx.events.fireEvent("dataPointSelection", [e, this.ctx, { selectedDataPoints: i.globals.selectedDataPoints, seriesIndex: s, dataPointIndex: r, w: i }]) } }, { key: "rotateAroundCenter", value: function (t) { var e = {}; return t && "function" == typeof t.getBBox && (e = t.getBBox()), { x: e.x + e.width / 2, y: e.y + e.height / 2 } } }, { key: "getTextRects", value: function (t, e, i, a) { var s = !(arguments.length > 4 && void 0 !== arguments[4]) || arguments[4], r = this.w, o = this.drawText({ x: -200, y: -200, text: t, textAnchor: "start", fontSize: e, fontFamily: i, foreColor: "#fff", opacity: 0 }); a && o.attr("transform", a), r.globals.dom.Paper.add(o); var n = o.bbox(); return s || (n = o.node.getBoundingClientRect()), o.remove(), { width: n.width, height: n.height } } }, { key: "placeTextWithEllipsis", value: function (t, e, i) { if ("function" == typeof t.getComputedTextLength && (t.textContent = e, e.length > 0 && t.getComputedTextLength() >= i / 1.1)) { for (var a = e.length - 3; a > 0; a -= 3)if (t.getSubStringLength(0, a) <= i / 1.1) return void (t.textContent = e.substring(0, a) + "..."); t.textContent = "." } } }], [{ key: "setAttrs", value: function (t, e) { for (var i in e) e.hasOwnProperty(i) && t.setAttribute(i, e[i]) } }]), t }(), y = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "getStackedSeriesTotals", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : [], e = this.w, i = []; if (0 === e.globals.series.length) return i; for (var a = 0; a < e.globals.series[e.globals.maxValsInArrayIndex].length; a++) { for (var s = 0, r = 0; r < e.globals.series.length; r++)void 0 !== e.globals.series[r][a] && -1 === t.indexOf(r) && (s += e.globals.series[r][a]); i.push(s) } return i } }, { key: "getSeriesTotalByIndex", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : null; return null === t ? this.w.config.series.reduce((function (t, e) { return t + e }), 0) : this.w.globals.series[t].reduce((function (t, e) { return t + e }), 0) } }, { key: "getStackedSeriesTotalsByGroups", value: function () { var t = this, e = this.w, i = []; return e.globals.seriesGroups.forEach((function (a) { var s = []; e.config.series.forEach((function (t, i) { a.indexOf(e.globals.seriesNames[i]) > -1 && s.push(i) })); var r = e.globals.series.map((function (t, e) { return -1 === s.indexOf(e) ? e : -1 })).filter((function (t) { return -1 !== t })); i.push(t.getStackedSeriesTotals(r)) })), i } }, { key: "setSeriesYAxisMappings", value: function () { var t = this.w.globals, e = this.w.config, i = [], a = [], s = [], r = t.series.length > e.yaxis.length || e.yaxis.some((function (t) { return Array.isArray(t.seriesName) })); e.series.forEach((function (t, e) { s.push(e), a.push(null) })), e.yaxis.forEach((function (t, e) { i[e] = [] })); var o = []; e.yaxis.forEach((function (t, a) { var n = !1; if (t.seriesName) { var l = []; Array.isArray(t.seriesName) ? l = t.seriesName : l.push(t.seriesName), l.forEach((function (t) { e.series.forEach((function (e, o) { if (e.name === t) { var l = o; a === o || r ? !r || s.indexOf(o) > -1 ? i[a].push([a, o]) : console.warn("Series '" + e.name + "' referenced more than once in what looks like the new style. That is, when using either seriesName: [], or when there are more series than yaxes.") : (i[o].push([o, a]), l = a), n = !0, -1 !== (l = s.indexOf(l)) && s.splice(l, 1) } })) })) } n || o.push(a) })), i = i.map((function (t, e) { var i = []; return t.forEach((function (t) { a[t[1]] = t[0], i.push(t[1]) })), i })); for (var n = e.yaxis.length - 1, l = 0; l < o.length && (n = o[l], i[n] = [], s); l++) { var h = s[0]; s.shift(), i[n].push(h), a[h] = n } s.forEach((function (t) { i[n].push(t), a[t] = n })), t.seriesYAxisMap = i.map((function (t) { return t })), t.seriesYAxisReverseMap = a.map((function (t) { return t })), t.seriesYAxisMap.forEach((function (t, i) { t.forEach((function (t) { e.series[t] && void 0 === e.series[t].group && (e.series[t].group = "apexcharts-axis-".concat(i.toString())) })) })) } }, { key: "isSeriesNull", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : null; return 0 === (null === t ? this.w.config.series.filter((function (t) { return null !== t })) : this.w.config.series[t].data.filter((function (t) { return null !== t }))).length } }, { key: "seriesHaveSameValues", value: function (t) { return this.w.globals.series[t].every((function (t, e, i) { return t === i[0] })) } }, { key: "getCategoryLabels", value: function (t) { var e = this.w, i = t.slice(); return e.config.xaxis.convertedCatToNumeric && (i = t.map((function (t, i) { return e.config.xaxis.labels.formatter(t - e.globals.minX + 1) }))), i } }, { key: "getLargestSeries", value: function () { var t = this.w; t.globals.maxValsInArrayIndex = t.globals.series.map((function (t) { return t.length })).indexOf(Math.max.apply(Math, t.globals.series.map((function (t) { return t.length })))) } }, { key: "getLargestMarkerSize", value: function () { var t = this.w, e = 0; return t.globals.markers.size.forEach((function (t) { e = Math.max(e, t) })), t.config.markers.discrete && t.config.markers.discrete.length && t.config.markers.discrete.forEach((function (t) { e = Math.max(e, t.size) })), e > 0 && (e += t.config.markers.hover.sizeOffset + 1), t.globals.markers.largestSize = e, e } }, { key: "getSeriesTotals", value: function () { var t = this.w; t.globals.seriesTotals = t.globals.series.map((function (t, e) { var i = 0; if (Array.isArray(t)) for (var a = 0; a < t.length; a++)i += t[a]; else i += t; return i })) } }, { key: "getSeriesTotalsXRange", value: function (t, e) { var i = this.w; return i.globals.series.map((function (a, s) { for (var r = 0, o = 0; o < a.length; o++)i.globals.seriesX[s][o] > t && i.globals.seriesX[s][o] < e && (r += a[o]); return r })) } }, { key: "getPercentSeries", value: function () { var t = this.w; t.globals.seriesPercent = t.globals.series.map((function (e, i) { var a = []; if (Array.isArray(e)) for (var s = 0; s < e.length; s++) { var r = t.globals.stackedSeriesTotals[s], o = 0; r && (o = 100 * e[s] / r), a.push(o) } else { var n = 100 * e / t.globals.seriesTotals.reduce((function (t, e) { return t + e }), 0); a.push(n) } return a })) } }, { key: "getCalculatedRatios", value: function () { var t, e, i, a = this, s = this.w, r = s.globals, o = [], n = 0, l = [], h = .1, c = 0; if (r.yRange = [], r.isMultipleYAxis) for (var d = 0; d < r.minYArr.length; d++)r.yRange.push(Math.abs(r.minYArr[d] - r.maxYArr[d])), l.push(0); else r.yRange.push(Math.abs(r.minY - r.maxY)); r.xRange = Math.abs(r.maxX - r.minX), r.zRange = Math.abs(r.maxZ - r.minZ); for (var g = 0; g < r.yRange.length; g++)o.push(r.yRange[g] / r.gridHeight); if (e = r.xRange / r.gridWidth, t = r.yRange / r.gridWidth, i = r.xRange / r.gridHeight, (n = r.zRange / r.gridHeight * 16) || (n = 1), r.minY !== Number.MIN_VALUE && 0 !== Math.abs(r.minY) && (r.hasNegs = !0), s.globals.seriesYAxisReverseMap.length > 0) { var u = function (t, e) { var i = s.config.yaxis[s.globals.seriesYAxisReverseMap[e]], r = t < 0 ? -1 : 1; return t = Math.abs(t), i.logarithmic && (t = a.getBaseLog(i.logBase, t)), -r * t / o[e] }; if (r.isMultipleYAxis) { l = []; for (var p = 0; p < o.length; p++)l.push(u(r.minYArr[p], p)) } else (l = []).push(u(r.minY, 0)), r.minY !== Number.MIN_VALUE && 0 !== Math.abs(r.minY) && (h = -r.minY / t, c = r.minX / e) } else (l = []).push(0), h = 0, c = 0; return { yRatio: o, invertedYRatio: t, zRatio: n, xRatio: e, invertedXRatio: i, baseLineInvertedY: h, baseLineY: l, baseLineX: c } } }, { key: "getLogSeries", value: function (t) { var e = this, i = this.w; return i.globals.seriesLog = t.map((function (t, a) { var s = i.globals.seriesYAxisReverseMap[a]; return i.config.yaxis[s] && i.config.yaxis[s].logarithmic ? t.map((function (t) { return null === t ? null : e.getLogVal(i.config.yaxis[s].logBase, t, a) })) : t })), i.globals.invalidLogScale ? t : i.globals.seriesLog } }, { key: "getBaseLog", value: function (t, e) { return Math.log(e) / Math.log(t) } }, { key: "getLogVal", value: function (t, e, i) { if (e <= 0) return 0; var a = this.w, s = 0 === a.globals.minYArr[i] ? -1 : this.getBaseLog(t, a.globals.minYArr[i]), r = (0 === a.globals.maxYArr[i] ? 0 : this.getBaseLog(t, a.globals.maxYArr[i])) - s; return e < 1 ? e / r : (this.getBaseLog(t, e) - s) / r } }, { key: "getLogYRatios", value: function (t) { var e = this, i = this.w, a = this.w.globals; return a.yLogRatio = t.slice(), a.logYRange = a.yRange.map((function (t, s) { var r = i.globals.seriesYAxisReverseMap[s]; if (i.config.yaxis[r] && e.w.config.yaxis[r].logarithmic) { var o, n = -Number.MAX_VALUE, l = Number.MIN_VALUE; return a.seriesLog.forEach((function (t, e) { t.forEach((function (t) { i.config.yaxis[e] && i.config.yaxis[e].logarithmic && (n = Math.max(t, n), l = Math.min(t, l)) })) })), o = Math.pow(a.yRange[s], Math.abs(l - n) / a.yRange[s]), a.yLogRatio[s] = o / a.gridHeight, o } })), a.invalidLogScale ? t.slice() : a.yLogRatio } }, { key: "drawSeriesByGroup", value: function (t, e, i, a) { var s = this.w, r = []; return t.series.length > 0 && e.forEach((function (e) { var o = [], n = []; t.i.forEach((function (i, a) { s.config.series[i].group === e && (o.push(t.series[a]), n.push(i)) })), o.length > 0 && r.push(a.draw(o, i, n)) })), r } }], [{ key: "checkComboSeries", value: function (t, e) { var i = !1, a = 0, s = 0; return void 0 === e && (e = "line"), t.length && void 0 !== t[0].type && t.forEach((function (t) { "bar" !== t.type && "column" !== t.type && "candlestick" !== t.type && "boxPlot" !== t.type || a++, void 0 !== t.type && t.type !== e && s++ })), s > 0 && (i = !0), { comboBarCount: a, comboCharts: i } } }, { key: "extendArrayProps", value: function (t, e, i) { var a, s, r, o, n, l; (null !== (a = e) && void 0 !== a && a.yaxis && (e = t.extendYAxis(e, i)), null !== (s = e) && void 0 !== s && s.annotations) && (e.annotations.yaxis && (e = t.extendYAxisAnnotations(e)), null !== (r = e) && void 0 !== r && null !== (o = r.annotations) && void 0 !== o && o.xaxis && (e = t.extendXAxisAnnotations(e)), null !== (n = e) && void 0 !== n && null !== (l = n.annotations) && void 0 !== l && l.points && (e = t.extendPointAnnotations(e))); return e } }]), t }(), w = function () { function t(e) { a(this, t), this.w = e.w, this.annoCtx = e } return r(t, [{ key: "setOrientations", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null, i = this.w; if ("vertical" === t.label.orientation) { var a = null !== e ? e : 0, s = i.globals.dom.baseEl.querySelector(".apexcharts-xaxis-annotations .apexcharts-xaxis-annotation-label[rel='".concat(a, "']")); if (null !== s) { var r = s.getBoundingClientRect(); s.setAttribute("x", parseFloat(s.getAttribute("x")) - r.height + 4), "top" === t.label.position ? s.setAttribute("y", parseFloat(s.getAttribute("y")) + r.width) : s.setAttribute("y", parseFloat(s.getAttribute("y")) - r.width); var o = this.annoCtx.graphics.rotateAroundCenter(s), n = o.x, l = o.y; s.setAttribute("transform", "rotate(-90 ".concat(n, " ").concat(l, ")")) } } } }, { key: "addBackgroundToAnno", value: function (t, e) { var i = this.w; if (!t || void 0 === e.label.text || void 0 !== e.label.text && !String(e.label.text).trim()) return null; var a = i.globals.dom.baseEl.querySelector(".apexcharts-grid").getBoundingClientRect(), s = t.getBoundingClientRect(), r = e.label.style.padding.left, o = e.label.style.padding.right, n = e.label.style.padding.top, l = e.label.style.padding.bottom; "vertical" === e.label.orientation && (n = e.label.style.padding.left, l = e.label.style.padding.right, r = e.label.style.padding.top, o = e.label.style.padding.bottom); var h = s.left - a.left - r, c = s.top - a.top - n, d = this.annoCtx.graphics.drawRect(h - i.globals.barPadForNumericAxis, c, s.width + r + o, s.height + n + l, e.label.borderRadius, e.label.style.background, 1, e.label.borderWidth, e.label.borderColor, 0); return e.id && d.node.classList.add(e.id), d } }, { key: "annotationsBackground", value: function () { var t = this, e = this.w, i = function (i, a, s) { var r = e.globals.dom.baseEl.querySelector(".apexcharts-".concat(s, "-annotations .apexcharts-").concat(s, "-annotation-label[rel='").concat(a, "']")); if (r) { var o = r.parentNode, n = t.addBackgroundToAnno(r, i); n && (o.insertBefore(n.node, r), i.label.mouseEnter && n.node.addEventListener("mouseenter", i.label.mouseEnter.bind(t, i)), i.label.mouseLeave && n.node.addEventListener("mouseleave", i.label.mouseLeave.bind(t, i)), i.label.click && n.node.addEventListener("click", i.label.click.bind(t, i))) } }; e.config.annotations.xaxis.map((function (t, e) { i(t, e, "xaxis") })), e.config.annotations.yaxis.map((function (t, e) { i(t, e, "yaxis") })), e.config.annotations.points.map((function (t, e) { i(t, e, "point") })) } }, { key: "getY1Y2", value: function (t, e) { var i, a = "y1" === t ? e.y : e.y2, s = !1, r = this.w; if (this.annoCtx.invertAxis) { var o = r.globals.labels; r.config.xaxis.convertedCatToNumeric && (o = r.globals.categoryLabels); var n = o.indexOf(a), l = r.globals.dom.baseEl.querySelector(".apexcharts-yaxis-texts-g text:nth-child(" + (n + 1) + ")"); i = l ? parseFloat(l.getAttribute("y")) : (r.globals.gridHeight / o.length - 1) * (n + 1) - r.globals.barHeight, void 0 !== e.seriesIndex && r.globals.barHeight && (i = i - r.globals.barHeight / 2 * (r.globals.series.length - 1) + r.globals.barHeight * e.seriesIndex) } else { var h, c = r.globals.seriesYAxisMap[e.yAxisIndex][0]; if (r.config.yaxis[e.yAxisIndex].logarithmic) h = (a = new y(this.annoCtx.ctx).getLogVal(r.config.yaxis[e.yAxisIndex].logBase, a, c)) / r.globals.yLogRatio[c]; else h = (a - r.globals.minYArr[c]) / (r.globals.yRange[c] / r.globals.gridHeight); h > r.globals.gridHeight ? (h = r.globals.gridHeight, s = !0) : h < 0 && (h = 0, s = !0), i = r.globals.gridHeight - h, !e.marker || void 0 !== e.y && null !== e.y || (i = 0), r.config.yaxis[e.yAxisIndex] && r.config.yaxis[e.yAxisIndex].reversed && (i = h) } return "string" == typeof a && a.indexOf("px") > -1 && (i = parseFloat(a)), { yP: i, clipped: s } } }, { key: "getX1X2", value: function (t, e) { var i, a = "x1" === t ? e.x : e.x2, s = this.w, r = this.annoCtx.invertAxis ? s.globals.minY : s.globals.minX, o = this.annoCtx.invertAxis ? s.globals.maxY : s.globals.maxX, n = this.annoCtx.invertAxis ? s.globals.yRange[0] : s.globals.xRange, l = !1; return i = this.annoCtx.inversedReversedAxis ? (o - a) / (n / s.globals.gridWidth) : (a - r) / (n / s.globals.gridWidth), "category" !== s.config.xaxis.type && !s.config.xaxis.convertedCatToNumeric || this.annoCtx.invertAxis || s.globals.dataFormatXNumeric || s.config.chart.sparkline.enabled || (i = this.getStringX(a)), "string" == typeof a && a.indexOf("px") > -1 && (i = parseFloat(a)), null == a && e.marker && (i = s.globals.gridWidth), void 0 !== e.seriesIndex && s.globals.barWidth && !this.annoCtx.invertAxis && (i = i - s.globals.barWidth / 2 * (s.globals.series.length - 1) + s.globals.barWidth * e.seriesIndex), i > s.globals.gridWidth ? (i = s.globals.gridWidth, l = !0) : i < 0 && (i = 0, l = !0), { x: i, clipped: l } } }, { key: "getStringX", value: function (t) { var e = this.w, i = t; e.config.xaxis.convertedCatToNumeric && e.globals.categoryLabels.length && (t = e.globals.categoryLabels.indexOf(t) + 1); var a = e.globals.labels.indexOf(t), s = e.globals.dom.baseEl.querySelector(".apexcharts-xaxis-texts-g text:nth-child(" + (a + 1) + ")"); return s && (i = parseFloat(s.getAttribute("x"))), i } }]), t }(), k = function () { function t(e) { a(this, t), this.w = e.w, this.annoCtx = e, this.invertAxis = this.annoCtx.invertAxis, this.helpers = new w(this.annoCtx) } return r(t, [{ key: "addXaxisAnnotation", value: function (t, e, i) { var a, s = this.w, r = this.helpers.getX1X2("x1", t), o = r.x, n = r.clipped, l = !0, h = t.label.text, c = t.strokeDashArray; if (x.isNumber(o)) { if (null === t.x2 || void 0 === t.x2) { if (!n) { var d = this.annoCtx.graphics.drawLine(o + t.offsetX, 0 + t.offsetY, o + t.offsetX, s.globals.gridHeight + t.offsetY, t.borderColor, c, t.borderWidth); e.appendChild(d.node), t.id && d.node.classList.add(t.id) } } else { var g = this.helpers.getX1X2("x2", t); if (a = g.x, l = g.clipped, !n || !l) { if (a < o) { var u = o; o = a, a = u } var p = this.annoCtx.graphics.drawRect(o + t.offsetX, 0 + t.offsetY, a - o, s.globals.gridHeight + t.offsetY, 0, t.fillColor, t.opacity, 1, t.borderColor, c); p.node.classList.add("apexcharts-annotation-rect"), p.attr("clip-path", "url(#gridRectMask".concat(s.globals.cuid, ")")), e.appendChild(p.node), t.id && p.node.classList.add(t.id) } } if (!n || !l) { var f = this.annoCtx.graphics.getTextRects(h, parseFloat(t.label.style.fontSize)), b = "top" === t.label.position ? 4 : "center" === t.label.position ? s.globals.gridHeight / 2 + ("vertical" === t.label.orientation ? f.width / 2 : 0) : s.globals.gridHeight, v = this.annoCtx.graphics.drawText({ x: o + t.label.offsetX, y: b + t.label.offsetY - ("vertical" === t.label.orientation ? "top" === t.label.position ? f.width / 2 - 12 : -f.width / 2 : 0), text: h, textAnchor: t.label.textAnchor, fontSize: t.label.style.fontSize, fontFamily: t.label.style.fontFamily, fontWeight: t.label.style.fontWeight, foreColor: t.label.style.color, cssClass: "apexcharts-xaxis-annotation-label ".concat(t.label.style.cssClass, " ").concat(t.id ? t.id : "") }); v.attr({ rel: i }), e.appendChild(v.node), this.annoCtx.helpers.setOrientations(t, i) } } } }, { key: "drawXAxisAnnotations", value: function () { var t = this, e = this.w, i = this.annoCtx.graphics.group({ class: "apexcharts-xaxis-annotations" }); return e.config.annotations.xaxis.map((function (e, a) { t.addXaxisAnnotation(e, i.node, a) })), i } }]), t }(), A = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.months31 = [1, 3, 5, 7, 8, 10, 12], this.months30 = [2, 4, 6, 9, 11], this.daysCntOfYear = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334] } return r(t, [{ key: "isValidDate", value: function (t) { return "number" != typeof t && !isNaN(this.parseDate(t)) } }, { key: "getTimeStamp", value: function (t) { return Date.parse(t) ? this.w.config.xaxis.labels.datetimeUTC ? new Date(new Date(t).toISOString().substr(0, 25)).getTime() : new Date(t).getTime() : t } }, { key: "getDate", value: function (t) { return this.w.config.xaxis.labels.datetimeUTC ? new Date(new Date(t).toUTCString()) : new Date(t) } }, { key: "parseDate", value: function (t) { var e = Date.parse(t); if (!isNaN(e)) return this.getTimeStamp(t); var i = Date.parse(t.replace(/-/g, "/").replace(/[a-z]+/gi, " ")); return i = this.getTimeStamp(i) } }, { key: "parseDateWithTimezone", value: function (t) { return Date.parse(t.replace(/-/g, "/").replace(/[a-z]+/gi, " ")) } }, { key: "formatDate", value: function (t, e) { var i = this.w.globals.locale, a = this.w.config.xaxis.labels.datetimeUTC, s = ["\0"].concat(u(i.months)), r = ["\x01"].concat(u(i.shortMonths)), o = ["\x02"].concat(u(i.days)), n = ["\x03"].concat(u(i.shortDays)); function l(t, e) { var i = t + ""; for (e = e || 2; i.length < e;)i = "0" + i; return i } var h = a ? t.getUTCFullYear() : t.getFullYear(); e = (e = (e = e.replace(/(^|[^\\])yyyy+/g, "$1" + h)).replace(/(^|[^\\])yy/g, "$1" + h.toString().substr(2, 2))).replace(/(^|[^\\])y/g, "$1" + h); var c = (a ? t.getUTCMonth() : t.getMonth()) + 1; e = (e = (e = (e = e.replace(/(^|[^\\])MMMM+/g, "$1" + s[0])).replace(/(^|[^\\])MMM/g, "$1" + r[0])).replace(/(^|[^\\])MM/g, "$1" + l(c))).replace(/(^|[^\\])M/g, "$1" + c); var d = a ? t.getUTCDate() : t.getDate(); e = (e = (e = (e = e.replace(/(^|[^\\])dddd+/g, "$1" + o[0])).replace(/(^|[^\\])ddd/g, "$1" + n[0])).replace(/(^|[^\\])dd/g, "$1" + l(d))).replace(/(^|[^\\])d/g, "$1" + d); var g = a ? t.getUTCHours() : t.getHours(), p = g > 12 ? g - 12 : 0 === g ? 12 : g; e = (e = (e = (e = e.replace(/(^|[^\\])HH+/g, "$1" + l(g))).replace(/(^|[^\\])H/g, "$1" + g)).replace(/(^|[^\\])hh+/g, "$1" + l(p))).replace(/(^|[^\\])h/g, "$1" + p); var f = a ? t.getUTCMinutes() : t.getMinutes(); e = (e = e.replace(/(^|[^\\])mm+/g, "$1" + l(f))).replace(/(^|[^\\])m/g, "$1" + f); var x = a ? t.getUTCSeconds() : t.getSeconds(); e = (e = e.replace(/(^|[^\\])ss+/g, "$1" + l(x))).replace(/(^|[^\\])s/g, "$1" + x); var b = a ? t.getUTCMilliseconds() : t.getMilliseconds(); e = e.replace(/(^|[^\\])fff+/g, "$1" + l(b, 3)), b = Math.round(b / 10), e = e.replace(/(^|[^\\])ff/g, "$1" + l(b)), b = Math.round(b / 10); var v = g < 12 ? "AM" : "PM"; e = (e = (e = e.replace(/(^|[^\\])f/g, "$1" + b)).replace(/(^|[^\\])TT+/g, "$1" + v)).replace(/(^|[^\\])T/g, "$1" + v.charAt(0)); var m = v.toLowerCase(); e = (e = e.replace(/(^|[^\\])tt+/g, "$1" + m)).replace(/(^|[^\\])t/g, "$1" + m.charAt(0)); var y = -t.getTimezoneOffset(), w = a || !y ? "Z" : y > 0 ? "+" : "-"; if (!a) { var k = (y = Math.abs(y)) % 60; w += l(Math.floor(y / 60)) + ":" + l(k) } e = e.replace(/(^|[^\\])K/g, "$1" + w); var A = (a ? t.getUTCDay() : t.getDay()) + 1; return e = (e = (e = (e = (e = e.replace(new RegExp(o[0], "g"), o[A])).replace(new RegExp(n[0], "g"), n[A])).replace(new RegExp(s[0], "g"), s[c])).replace(new RegExp(r[0], "g"), r[c])).replace(/\\(.)/g, "$1") } }, { key: "getTimeUnitsfromTimestamp", value: function (t, e, i) { var a = this.w; void 0 !== a.config.xaxis.min && (t = a.config.xaxis.min), void 0 !== a.config.xaxis.max && (e = a.config.xaxis.max); var s = this.getDate(t), r = this.getDate(e), o = this.formatDate(s, "yyyy MM dd HH mm ss fff").split(" "), n = this.formatDate(r, "yyyy MM dd HH mm ss fff").split(" "); return { minMillisecond: parseInt(o[6], 10), maxMillisecond: parseInt(n[6], 10), minSecond: parseInt(o[5], 10), maxSecond: parseInt(n[5], 10), minMinute: parseInt(o[4], 10), maxMinute: parseInt(n[4], 10), minHour: parseInt(o[3], 10), maxHour: parseInt(n[3], 10), minDate: parseInt(o[2], 10), maxDate: parseInt(n[2], 10), minMonth: parseInt(o[1], 10) - 1, maxMonth: parseInt(n[1], 10) - 1, minYear: parseInt(o[0], 10), maxYear: parseInt(n[0], 10) } } }, { key: "isLeapYear", value: function (t) { return t % 4 == 0 && t % 100 != 0 || t % 400 == 0 } }, { key: "calculcateLastDaysOfMonth", value: function (t, e, i) { return this.determineDaysOfMonths(t, e) - i } }, { key: "determineDaysOfYear", value: function (t) { var e = 365; return this.isLeapYear(t) && (e = 366), e } }, { key: "determineRemainingDaysOfYear", value: function (t, e, i) { var a = this.daysCntOfYear[e] + i; return e > 1 && this.isLeapYear() && a++, a } }, { key: "determineDaysOfMonths", value: function (t, e) { var i = 30; switch (t = x.monthMod(t), !0) { case this.months30.indexOf(t) > -1: 2 === t && (i = this.isLeapYear(e) ? 29 : 28); break; case this.months31.indexOf(t) > -1: default: i = 31 }return i } }]), t }(), S = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.tooltipKeyFormat = "dd MMM" } return r(t, [{ key: "xLabelFormat", value: function (t, e, i, a) { var s = this.w; if ("datetime" === s.config.xaxis.type && void 0 === s.config.xaxis.labels.formatter && void 0 === s.config.tooltip.x.formatter) { var r = new A(this.ctx); return r.formatDate(r.getDate(e), s.config.tooltip.x.format) } return t(e, i, a) } }, { key: "defaultGeneralFormatter", value: function (t) { return Array.isArray(t) ? t.map((function (t) { return t })) : t } }, { key: "defaultYFormatter", value: function (t, e, i) { var a = this.w; if (x.isNumber(t)) if (0 !== a.globals.yValueDecimal) t = t.toFixed(void 0 !== e.decimalsInFloat ? e.decimalsInFloat : a.globals.yValueDecimal); else { var s = t.toFixed(0); t = t == s ? s : t.toFixed(1) } return t } }, { key: "setLabelFormatters", value: function () { var t = this, e = this.w; return e.globals.xaxisTooltipFormatter = function (e) { return t.defaultGeneralFormatter(e) }, e.globals.ttKeyFormatter = function (e) { return t.defaultGeneralFormatter(e) }, e.globals.ttZFormatter = function (t) { return t }, e.globals.legendFormatter = function (e) { return t.defaultGeneralFormatter(e) }, void 0 !== e.config.xaxis.labels.formatter ? e.globals.xLabelFormatter = e.config.xaxis.labels.formatter : e.globals.xLabelFormatter = function (t) { if (x.isNumber(t)) { if (!e.config.xaxis.convertedCatToNumeric && "numeric" === e.config.xaxis.type) { if (x.isNumber(e.config.xaxis.decimalsInFloat)) return t.toFixed(e.config.xaxis.decimalsInFloat); var i = e.globals.maxX - e.globals.minX; return i > 0 && i < 100 ? t.toFixed(1) : t.toFixed(0) } if (e.globals.isBarHorizontal) if (e.globals.maxY - e.globals.minYArr < 4) return t.toFixed(1); return t.toFixed(0) } return t }, "function" == typeof e.config.tooltip.x.formatter ? e.globals.ttKeyFormatter = e.config.tooltip.x.formatter : e.globals.ttKeyFormatter = e.globals.xLabelFormatter, "function" == typeof e.config.xaxis.tooltip.formatter && (e.globals.xaxisTooltipFormatter = e.config.xaxis.tooltip.formatter), (Array.isArray(e.config.tooltip.y) || void 0 !== e.config.tooltip.y.formatter) && (e.globals.ttVal = e.config.tooltip.y), void 0 !== e.config.tooltip.z.formatter && (e.globals.ttZFormatter = e.config.tooltip.z.formatter), void 0 !== e.config.legend.formatter && (e.globals.legendFormatter = e.config.legend.formatter), e.config.yaxis.forEach((function (i, a) { void 0 !== i.labels.formatter ? e.globals.yLabelFormatters[a] = i.labels.formatter : e.globals.yLabelFormatters[a] = function (s) { return e.globals.xyCharts ? Array.isArray(s) ? s.map((function (e) { return t.defaultYFormatter(e, i, a) })) : t.defaultYFormatter(s, i, a) : s } })), e.globals } }, { key: "heatmapLabelFormatters", value: function () { var t = this.w; if ("heatmap" === t.config.chart.type) { t.globals.yAxisScale[0].result = t.globals.seriesNames.slice(); var e = t.globals.seriesNames.reduce((function (t, e) { return t.length > e.length ? t : e }), 0); t.globals.yAxisScale[0].niceMax = e, t.globals.yAxisScale[0].niceMin = e } } }]), t }(), C = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "getLabel", value: function (t, e, i, a) { var s = arguments.length > 4 && void 0 !== arguments[4] ? arguments[4] : [], r = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : "12px", o = !(arguments.length > 6 && void 0 !== arguments[6]) || arguments[6], n = this.w, l = void 0 === t[a] ? "" : t[a], h = l, c = n.globals.xLabelFormatter, d = n.config.xaxis.labels.formatter, g = !1, u = new S(this.ctx), p = l; o && (h = u.xLabelFormat(c, l, p, { i: a, dateFormatter: new A(this.ctx).formatDate, w: n }), void 0 !== d && (h = d(l, t[a], { i: a, dateFormatter: new A(this.ctx).formatDate, w: n }))); var f, x; e.length > 0 ? (f = e[a].unit, x = null, e.forEach((function (t) { "month" === t.unit ? x = "year" : "day" === t.unit ? x = "month" : "hour" === t.unit ? x = "day" : "minute" === t.unit && (x = "hour") })), g = x === f, i = e[a].position, h = e[a].value) : "datetime" === n.config.xaxis.type && void 0 === d && (h = ""), void 0 === h && (h = ""), h = Array.isArray(h) ? h : h.toString(); var b = new m(this.ctx), v = {}; v = n.globals.rotateXLabels && o ? b.getTextRects(h, parseInt(r, 10), null, "rotate(".concat(n.config.xaxis.labels.rotate, " 0 0)"), !1) : b.getTextRects(h, parseInt(r, 10)); var y = !n.config.xaxis.labels.showDuplicates && this.ctx.timeScale; return !Array.isArray(h) && ("NaN" === String(h) || s.indexOf(h) >= 0 && y) && (h = ""), { x: i, text: h, textRect: v, isBold: g } } }, { key: "checkLabelBasedOnTickamount", value: function (t, e, i) { var a = this.w, s = a.config.xaxis.tickAmount; return "dataPoints" === s && (s = Math.round(a.globals.gridWidth / 120)), s > i || t % Math.round(i / (s + 1)) == 0 || (e.text = ""), e } }, { key: "checkForOverflowingLabels", value: function (t, e, i, a, s) { var r = this.w; if (0 === t && r.globals.skipFirstTimelinelabel && (e.text = ""), t === i - 1 && r.globals.skipLastTimelinelabel && (e.text = ""), r.config.xaxis.labels.hideOverlappingLabels && a.length > 0) { var o = s[s.length - 1]; e.x < o.textRect.width / (r.globals.rotateXLabels ? Math.abs(r.config.xaxis.labels.rotate) / 12 : 1.01) + o.x && (e.text = "") } return e } }, { key: "checkForReversedLabels", value: function (t, e) { var i = this.w; return i.config.yaxis[t] && i.config.yaxis[t].reversed && e.reverse(), e } }, { key: "yAxisAllSeriesCollapsed", value: function (t) { var e = this.w.globals; return !e.seriesYAxisMap[t].some((function (t) { return -1 === e.collapsedSeriesIndices.indexOf(t) })) } }, { key: "translateYAxisIndex", value: function (t) { var e = this.w, i = e.globals, a = e.config.yaxis; return i.series.length > a.length || a.some((function (t) { return Array.isArray(t.seriesName) })) ? t : i.seriesYAxisReverseMap[t] } }, { key: "isYAxisHidden", value: function (t) { var e = this.w, i = e.config.yaxis[t]; if (!i.show || this.yAxisAllSeriesCollapsed(t)) return !0; if (!i.showForNullSeries) { var a = e.globals.seriesYAxisMap[t], s = new y(this.ctx); return a.every((function (t) { return s.isSeriesNull(t) })) } return !1 } }, { key: "getYAxisForeColor", value: function (t, e) { var i = this.w; return Array.isArray(t) && i.globals.yAxisScale[e] && this.ctx.theme.pushExtraColors(t, i.globals.yAxisScale[e].result.length, !1), t } }, { key: "drawYAxisTicks", value: function (t, e, i, a, s, r, o) { var n = this.w, l = new m(this.ctx), h = n.globals.translateY + n.config.yaxis[s].labels.offsetY; if (n.globals.isBarHorizontal ? h = 0 : "heatmap" === n.config.chart.type && (h += r / 2), a.show && e > 0) { !0 === n.config.yaxis[s].opposite && (t += a.width); for (var c = e; c >= 0; c--) { var d = l.drawLine(t + i.offsetX - a.width + a.offsetX, h + a.offsetY, t + i.offsetX + a.offsetX, h + a.offsetY, a.color); o.add(d), h += r } } } }]), t }(), L = function () { function t(e) { a(this, t), this.w = e.w, this.annoCtx = e, this.helpers = new w(this.annoCtx), this.axesUtils = new C(this.annoCtx) } return r(t, [{ key: "addYaxisAnnotation", value: function (t, e, i) { var a, s = this.w, r = t.strokeDashArray, o = this.helpers.getY1Y2("y1", t), n = o.yP, l = o.clipped, h = !0, c = !1, d = t.label.text; if (null === t.y2 || void 0 === t.y2) { if (!l) { c = !0; var g = this.annoCtx.graphics.drawLine(0 + t.offsetX, n + t.offsetY, this._getYAxisAnnotationWidth(t), n + t.offsetY, t.borderColor, r, t.borderWidth); e.appendChild(g.node), t.id && g.node.classList.add(t.id) } } else { if (a = (o = this.helpers.getY1Y2("y2", t)).yP, h = o.clipped, a > n) { var u = n; n = a, a = u } if (!l || !h) { c = !0; var p = this.annoCtx.graphics.drawRect(0 + t.offsetX, a + t.offsetY, this._getYAxisAnnotationWidth(t), n - a, 0, t.fillColor, t.opacity, 1, t.borderColor, r); p.node.classList.add("apexcharts-annotation-rect"), p.attr("clip-path", "url(#gridRectMask".concat(s.globals.cuid, ")")), e.appendChild(p.node), t.id && p.node.classList.add(t.id) } } if (c) { var f = "right" === t.label.position ? s.globals.gridWidth : "center" === t.label.position ? s.globals.gridWidth / 2 : 0, x = this.annoCtx.graphics.drawText({ x: f + t.label.offsetX, y: (null != a ? a : n) + t.label.offsetY - 3, text: d, textAnchor: t.label.textAnchor, fontSize: t.label.style.fontSize, fontFamily: t.label.style.fontFamily, fontWeight: t.label.style.fontWeight, foreColor: t.label.style.color, cssClass: "apexcharts-yaxis-annotation-label ".concat(t.label.style.cssClass, " ").concat(t.id ? t.id : "") }); x.attr({ rel: i }), e.appendChild(x.node) } } }, { key: "_getYAxisAnnotationWidth", value: function (t) { var e = this.w; e.globals.gridWidth; return (t.width.indexOf("%") > -1 ? e.globals.gridWidth * parseInt(t.width, 10) / 100 : parseInt(t.width, 10)) + t.offsetX } }, { key: "drawYAxisAnnotations", value: function () { var t = this, e = this.w, i = this.annoCtx.graphics.group({ class: "apexcharts-yaxis-annotations" }); return e.config.annotations.yaxis.forEach((function (e, a) { e.yAxisIndex = t.axesUtils.translateYAxisIndex(e.yAxisIndex), t.axesUtils.isYAxisHidden(e.yAxisIndex) && t.axesUtils.yAxisAllSeriesCollapsed(e.yAxisIndex) || t.addYaxisAnnotation(e, i.node, a) })), i } }]), t }(), P = function () { function t(e) { a(this, t), this.w = e.w, this.annoCtx = e, this.helpers = new w(this.annoCtx) } return r(t, [{ key: "addPointAnnotation", value: function (t, e, i) { if (!(this.w.globals.collapsedSeriesIndices.indexOf(t.seriesIndex) > -1)) { var a = this.helpers.getX1X2("x1", t), s = a.x, r = a.clipped, o = (a = this.helpers.getY1Y2("y1", t)).yP, n = a.clipped; if (x.isNumber(s) && !n && !r) { var l = { pSize: t.marker.size, pointStrokeWidth: t.marker.strokeWidth, pointFillColor: t.marker.fillColor, pointStrokeColor: t.marker.strokeColor, shape: t.marker.shape, pRadius: t.marker.radius, class: "apexcharts-point-annotation-marker ".concat(t.marker.cssClass, " ").concat(t.id ? t.id : "") }, h = this.annoCtx.graphics.drawMarker(s + t.marker.offsetX, o + t.marker.offsetY, l); e.appendChild(h.node); var c = t.label.text ? t.label.text : "", d = this.annoCtx.graphics.drawText({ x: s + t.label.offsetX, y: o + t.label.offsetY - t.marker.size - parseFloat(t.label.style.fontSize) / 1.6, text: c, textAnchor: t.label.textAnchor, fontSize: t.label.style.fontSize, fontFamily: t.label.style.fontFamily, fontWeight: t.label.style.fontWeight, foreColor: t.label.style.color, cssClass: "apexcharts-point-annotation-label ".concat(t.label.style.cssClass, " ").concat(t.id ? t.id : "") }); if (d.attr({ rel: i }), e.appendChild(d.node), t.customSVG.SVG) { var g = this.annoCtx.graphics.group({ class: "apexcharts-point-annotations-custom-svg " + t.customSVG.cssClass }); g.attr({ transform: "translate(".concat(s + t.customSVG.offsetX, ", ").concat(o + t.customSVG.offsetY, ")") }), g.node.innerHTML = t.customSVG.SVG, e.appendChild(g.node) } if (t.image.path) { var u = t.image.width ? t.image.width : 20, p = t.image.height ? t.image.height : 20; h = this.annoCtx.addImage({ x: s + t.image.offsetX - u / 2, y: o + t.image.offsetY - p / 2, width: u, height: p, path: t.image.path, appendTo: ".apexcharts-point-annotations" }) } t.mouseEnter && h.node.addEventListener("mouseenter", t.mouseEnter.bind(this, t)), t.mouseLeave && h.node.addEventListener("mouseleave", t.mouseLeave.bind(this, t)), t.click && h.node.addEventListener("click", t.click.bind(this, t)) } } } }, { key: "drawPointAnnotations", value: function () { var t = this, e = this.w, i = this.annoCtx.graphics.group({ class: "apexcharts-point-annotations" }); return e.config.annotations.points.map((function (e, a) { t.addPointAnnotation(e, i.node, a) })), i } }]), t }(); var M = { name: "en", options: { months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], toolbar: { exportToSVG: "Download SVG", exportToPNG: "Download PNG", exportToCSV: "Download CSV", menu: "Menu", selection: "Selection", selectionZoom: "Selection Zoom", zoomIn: "Zoom In", zoomOut: "Zoom Out", pan: "Panning", reset: "Reset Zoom" } } }, I = function () { function t() { a(this, t), this.yAxis = { show: !0, showAlways: !1, showForNullSeries: !0, seriesName: void 0, opposite: !1, reversed: !1, logarithmic: !1, logBase: 10, tickAmount: void 0, stepSize: void 0, forceNiceScale: !1, max: void 0, min: void 0, floating: !1, decimalsInFloat: void 0, labels: { show: !0, minWidth: 0, maxWidth: 160, offsetX: 0, offsetY: 0, align: void 0, rotate: 0, padding: 20, style: { colors: [], fontSize: "11px", fontWeight: 400, fontFamily: void 0, cssClass: "" }, formatter: void 0 }, axisBorder: { show: !1, color: "#e0e0e0", width: 1, offsetX: 0, offsetY: 0 }, axisTicks: { show: !1, color: "#e0e0e0", width: 6, offsetX: 0, offsetY: 0 }, title: { text: void 0, rotate: -90, offsetY: 0, offsetX: 0, style: { color: void 0, fontSize: "11px", fontWeight: 900, fontFamily: void 0, cssClass: "" } }, tooltip: { enabled: !1, offsetX: 0 }, crosshairs: { show: !0, position: "front", stroke: { color: "#b6b6b6", width: 1, dashArray: 0 } } }, this.pointAnnotation = { id: void 0, x: 0, y: null, yAxisIndex: 0, seriesIndex: void 0, mouseEnter: void 0, mouseLeave: void 0, click: void 0, marker: { size: 4, fillColor: "#fff", strokeWidth: 2, strokeColor: "#333", shape: "circle", offsetX: 0, offsetY: 0, radius: 2, cssClass: "" }, label: { borderColor: "#c2c2c2", borderWidth: 1, borderRadius: 2, text: void 0, textAnchor: "middle", offsetX: 0, offsetY: 0, mouseEnter: void 0, mouseLeave: void 0, click: void 0, style: { background: "#fff", color: void 0, fontSize: "11px", fontFamily: void 0, fontWeight: 400, cssClass: "", padding: { left: 5, right: 5, top: 2, bottom: 2 } } }, customSVG: { SVG: void 0, cssClass: void 0, offsetX: 0, offsetY: 0 }, image: { path: void 0, width: 20, height: 20, offsetX: 0, offsetY: 0 } }, this.yAxisAnnotation = { id: void 0, y: 0, y2: null, strokeDashArray: 1, fillColor: "#c2c2c2", borderColor: "#c2c2c2", borderWidth: 1, opacity: .3, offsetX: 0, offsetY: 0, width: "100%", yAxisIndex: 0, label: { borderColor: "#c2c2c2", borderWidth: 1, borderRadius: 2, text: void 0, textAnchor: "end", position: "right", offsetX: 0, offsetY: -3, mouseEnter: void 0, mouseLeave: void 0, click: void 0, style: { background: "#fff", color: void 0, fontSize: "11px", fontFamily: void 0, fontWeight: 400, cssClass: "", padding: { left: 5, right: 5, top: 2, bottom: 2 } } } }, this.xAxisAnnotation = { id: void 0, x: 0, x2: null, strokeDashArray: 1, fillColor: "#c2c2c2", borderColor: "#c2c2c2", borderWidth: 1, opacity: .3, offsetX: 0, offsetY: 0, label: { borderColor: "#c2c2c2", borderWidth: 1, borderRadius: 2, text: void 0, textAnchor: "middle", orientation: "vertical", position: "top", offsetX: 0, offsetY: 0, mouseEnter: void 0, mouseLeave: void 0, click: void 0, style: { background: "#fff", color: void 0, fontSize: "11px", fontFamily: void 0, fontWeight: 400, cssClass: "", padding: { left: 5, right: 5, top: 2, bottom: 2 } } } }, this.text = { x: 0, y: 0, text: "", textAnchor: "start", foreColor: void 0, fontSize: "13px", fontFamily: void 0, fontWeight: 400, appendTo: ".apexcharts-annotations", backgroundColor: "transparent", borderColor: "#c2c2c2", borderRadius: 0, borderWidth: 0, paddingLeft: 4, paddingRight: 4, paddingTop: 2, paddingBottom: 2 } } return r(t, [{ key: "init", value: function () { return { annotations: { yaxis: [this.yAxisAnnotation], xaxis: [this.xAxisAnnotation], points: [this.pointAnnotation], texts: [], images: [], shapes: [] }, chart: { animations: { enabled: !0, easing: "easeinout", speed: 800, animateGradually: { delay: 150, enabled: !0 }, dynamicAnimation: { enabled: !0, speed: 350 } }, background: "transparent", locales: [M], defaultLocale: "en", dropShadow: { enabled: !1, enabledOnSeries: void 0, top: 2, left: 2, blur: 4, color: "#000", opacity: .35 }, events: { animationEnd: void 0, beforeMount: void 0, mounted: void 0, updated: void 0, click: void 0, mouseMove: void 0, mouseLeave: void 0, xAxisLabelClick: void 0, legendClick: void 0, markerClick: void 0, selection: void 0, dataPointSelection: void 0, dataPointMouseEnter: void 0, dataPointMouseLeave: void 0, beforeZoom: void 0, beforeResetZoom: void 0, zoomed: void 0, scrolled: void 0, brushScrolled: void 0 }, foreColor: "#373d3f", fontFamily: "Helvetica, Arial, sans-serif", height: "auto", parentHeightOffset: 15, redrawOnParentResize: !0, redrawOnWindowResize: !0, id: void 0, group: void 0, nonce: void 0, offsetX: 0, offsetY: 0, selection: { enabled: !1, type: "x", fill: { color: "#24292e", opacity: .1 }, stroke: { width: 1, color: "#24292e", opacity: .4, dashArray: 3 }, xaxis: { min: void 0, max: void 0 }, yaxis: { min: void 0, max: void 0 } }, sparkline: { enabled: !1 }, brush: { enabled: !1, autoScaleYaxis: !0, target: void 0, targets: void 0 }, stacked: !1, stackOnlyBar: !0, stackType: "normal", toolbar: { show: !0, offsetX: 0, offsetY: 0, tools: { download: !0, selection: !0, zoom: !0, zoomin: !0, zoomout: !0, pan: !0, reset: !0, customIcons: [] }, export: { csv: { filename: void 0, columnDelimiter: ",", headerCategory: "category", headerValue: "value", dateFormatter: function (t) { return new Date(t).toDateString() } }, png: { filename: void 0 }, svg: { filename: void 0 } }, autoSelected: "zoom" }, type: "line", width: "100%", zoom: { enabled: !0, type: "x", autoScaleYaxis: !1, zoomedArea: { fill: { color: "#90CAF9", opacity: .4 }, stroke: { color: "#0D47A1", opacity: .4, width: 1 } } } }, plotOptions: { line: { isSlopeChart: !1 }, area: { fillTo: "origin" }, bar: { horizontal: !1, columnWidth: "70%", barHeight: "70%", distributed: !1, borderRadius: 0, borderRadiusApplication: "around", borderRadiusWhenStacked: "last", rangeBarOverlap: !0, rangeBarGroupRows: !1, hideZeroBarsWhenGrouped: !1, isDumbbell: !1, dumbbellColors: void 0, isFunnel: !1, isFunnel3d: !0, colors: { ranges: [], backgroundBarColors: [], backgroundBarOpacity: 1, backgroundBarRadius: 0 }, dataLabels: { position: "top", maxItems: 100, hideOverflowingLabels: !0, orientation: "horizontal", total: { enabled: !1, formatter: void 0, offsetX: 0, offsetY: 0, style: { color: "#373d3f", fontSize: "12px", fontFamily: void 0, fontWeight: 600 } } } }, bubble: { zScaling: !0, minBubbleRadius: void 0, maxBubbleRadius: void 0 }, candlestick: { colors: { upward: "#00B746", downward: "#EF403C" }, wick: { useFillColor: !0 } }, boxPlot: { colors: { upper: "#00E396", lower: "#008FFB" } }, heatmap: { radius: 2, enableShades: !0, shadeIntensity: .5, reverseNegativeShade: !1, distributed: !1, useFillColorAsStroke: !1, colorScale: { inverse: !1, ranges: [], min: void 0, max: void 0 } }, treemap: { enableShades: !0, shadeIntensity: .5, distributed: !1, reverseNegativeShade: !1, useFillColorAsStroke: !1, borderRadius: 4, dataLabels: { format: "scale" }, colorScale: { inverse: !1, ranges: [], min: void 0, max: void 0 } }, radialBar: { inverseOrder: !1, startAngle: 0, endAngle: 360, offsetX: 0, offsetY: 0, hollow: { margin: 5, size: "50%", background: "transparent", image: void 0, imageWidth: 150, imageHeight: 150, imageOffsetX: 0, imageOffsetY: 0, imageClipped: !0, position: "front", dropShadow: { enabled: !1, top: 0, left: 0, blur: 3, color: "#000", opacity: .5 } }, track: { show: !0, startAngle: void 0, endAngle: void 0, background: "#f2f2f2", strokeWidth: "97%", opacity: 1, margin: 5, dropShadow: { enabled: !1, top: 0, left: 0, blur: 3, color: "#000", opacity: .5 } }, dataLabels: { show: !0, name: { show: !0, fontSize: "16px", fontFamily: void 0, fontWeight: 600, color: void 0, offsetY: 0, formatter: function (t) { return t } }, value: { show: !0, fontSize: "14px", fontFamily: void 0, fontWeight: 400, color: void 0, offsetY: 16, formatter: function (t) { return t + "%" } }, total: { show: !1, label: "Total", fontSize: "16px", fontWeight: 600, fontFamily: void 0, color: void 0, formatter: function (t) { return t.globals.seriesTotals.reduce((function (t, e) { return t + e }), 0) / t.globals.series.length + "%" } } }, barLabels: { enabled: !1, margin: 5, useSeriesColors: !0, fontFamily: void 0, fontWeight: 600, fontSize: "16px", formatter: function (t) { return t }, onClick: void 0 } }, pie: { customScale: 1, offsetX: 0, offsetY: 0, startAngle: 0, endAngle: 360, expandOnClick: !0, dataLabels: { offset: 0, minAngleToShowLabel: 10 }, donut: { size: "65%", background: "transparent", labels: { show: !1, name: { show: !0, fontSize: "16px", fontFamily: void 0, fontWeight: 600, color: void 0, offsetY: -10, formatter: function (t) { return t } }, value: { show: !0, fontSize: "20px", fontFamily: void 0, fontWeight: 400, color: void 0, offsetY: 10, formatter: function (t) { return t } }, total: { show: !1, showAlways: !1, label: "Total", fontSize: "16px", fontWeight: 400, fontFamily: void 0, color: void 0, formatter: function (t) { return t.globals.seriesTotals.reduce((function (t, e) { return t + e }), 0) } } } } }, polarArea: { rings: { strokeWidth: 1, strokeColor: "#e8e8e8" }, spokes: { strokeWidth: 1, connectorColors: "#e8e8e8" } }, radar: { size: void 0, offsetX: 0, offsetY: 0, polygons: { strokeWidth: 1, strokeColors: "#e8e8e8", connectorColors: "#e8e8e8", fill: { colors: void 0 } } } }, colors: void 0, dataLabels: { enabled: !0, enabledOnSeries: void 0, formatter: function (t) { return null !== t ? t : "" }, textAnchor: "middle", distributed: !1, offsetX: 0, offsetY: 0, style: { fontSize: "12px", fontFamily: void 0, fontWeight: 600, colors: void 0 }, background: { enabled: !0, foreColor: "#fff", borderRadius: 2, padding: 4, opacity: .9, borderWidth: 1, borderColor: "#fff", dropShadow: { enabled: !1, top: 1, left: 1, blur: 1, color: "#000", opacity: .45 } }, dropShadow: { enabled: !1, top: 1, left: 1, blur: 1, color: "#000", opacity: .45 } }, fill: { type: "solid", colors: void 0, opacity: .85, gradient: { shade: "dark", type: "horizontal", shadeIntensity: .5, gradientToColors: void 0, inverseColors: !0, opacityFrom: 1, opacityTo: 1, stops: [0, 50, 100], colorStops: [] }, image: { src: [], width: void 0, height: void 0 }, pattern: { style: "squares", width: 6, height: 6, strokeWidth: 2 } }, forecastDataPoints: { count: 0, fillOpacity: .5, strokeWidth: void 0, dashArray: 4 }, grid: { show: !0, borderColor: "#e0e0e0", strokeDashArray: 0, position: "back", xaxis: { lines: { show: !1 } }, yaxis: { lines: { show: !0 } }, row: { colors: void 0, opacity: .5 }, column: { colors: void 0, opacity: .5 }, padding: { top: 0, right: 10, bottom: 0, left: 12 } }, labels: [], legend: { show: !0, showForSingleSeries: !1, showForNullSeries: !0, showForZeroSeries: !0, floating: !1, position: "bottom", horizontalAlign: "center", inverseOrder: !1, fontSize: "12px", fontFamily: void 0, fontWeight: 400, width: void 0, height: void 0, formatter: void 0, tooltipHoverFormatter: void 0, offsetX: -20, offsetY: 4, customLegendItems: [], labels: { colors: void 0, useSeriesColors: !1 }, markers: { width: 12, height: 12, strokeWidth: 0, fillColors: void 0, strokeColor: "#fff", radius: 12, customHTML: void 0, offsetX: 0, offsetY: 0, onClick: void 0 }, itemMargin: { horizontal: 5, vertical: 2 }, onItemClick: { toggleDataSeries: !0 }, onItemHover: { highlightDataSeries: !0 } }, markers: { discrete: [], size: 0, colors: void 0, strokeColors: "#fff", strokeWidth: 2, strokeOpacity: .9, strokeDashArray: 0, fillOpacity: 1, shape: "circle", width: 8, height: 8, radius: 2, offsetX: 0, offsetY: 0, onClick: void 0, onDblClick: void 0, showNullDataPoints: !0, hover: { size: void 0, sizeOffset: 3 } }, noData: { text: void 0, align: "center", verticalAlign: "middle", offsetX: 0, offsetY: 0, style: { color: void 0, fontSize: "14px", fontFamily: void 0 } }, responsive: [], series: void 0, states: { normal: { filter: { type: "none", value: 0 } }, hover: { filter: { type: "lighten", value: .1 } }, active: { allowMultipleDataPointsSelection: !1, filter: { type: "darken", value: .5 } } }, title: { text: void 0, align: "left", margin: 5, offsetX: 0, offsetY: 0, floating: !1, style: { fontSize: "14px", fontWeight: 900, fontFamily: void 0, color: void 0 } }, subtitle: { text: void 0, align: "left", margin: 5, offsetX: 0, offsetY: 30, floating: !1, style: { fontSize: "12px", fontWeight: 400, fontFamily: void 0, color: void 0 } }, stroke: { show: !0, curve: "smooth", lineCap: "butt", width: 2, colors: void 0, dashArray: 0, fill: { type: "solid", colors: void 0, opacity: .85, gradient: { shade: "dark", type: "horizontal", shadeIntensity: .5, gradientToColors: void 0, inverseColors: !0, opacityFrom: 1, opacityTo: 1, stops: [0, 50, 100], colorStops: [] } } }, tooltip: { enabled: !0, enabledOnSeries: void 0, shared: !0, hideEmptySeries: !1, followCursor: !1, intersect: !1, inverseOrder: !1, custom: void 0, fillSeriesColor: !1, theme: "light", cssClass: "", style: { fontSize: "12px", fontFamily: void 0 }, onDatasetHover: { highlightDataSeries: !1 }, x: { show: !0, format: "dd MMM", formatter: void 0 }, y: { formatter: void 0, title: { formatter: function (t) { return t ? t + ": " : "" } } }, z: { formatter: void 0, title: "Size: " }, marker: { show: !0, fillColors: void 0 }, items: { display: "flex" }, fixed: { enabled: !1, position: "topRight", offsetX: 0, offsetY: 0 } }, xaxis: { type: "category", categories: [], convertedCatToNumeric: !1, offsetX: 0, offsetY: 0, overwriteCategories: void 0, labels: { show: !0, rotate: -45, rotateAlways: !1, hideOverlappingLabels: !0, trim: !1, minHeight: void 0, maxHeight: 120, showDuplicates: !0, style: { colors: [], fontSize: "12px", fontWeight: 400, fontFamily: void 0, cssClass: "" }, offsetX: 0, offsetY: 0, format: void 0, formatter: void 0, datetimeUTC: !0, datetimeFormatter: { year: "yyyy", month: "MMM 'yy", day: "dd MMM", hour: "HH:mm", minute: "HH:mm:ss", second: "HH:mm:ss" } }, group: { groups: [], style: { colors: [], fontSize: "12px", fontWeight: 400, fontFamily: void 0, cssClass: "" } }, axisBorder: { show: !0, color: "#e0e0e0", width: "100%", height: 1, offsetX: 0, offsetY: 0 }, axisTicks: { show: !0, color: "#e0e0e0", height: 6, offsetX: 0, offsetY: 0 }, stepSize: void 0, tickAmount: void 0, tickPlacement: "on", min: void 0, max: void 0, range: void 0, floating: !1, decimalsInFloat: void 0, position: "bottom", title: { text: void 0, offsetX: 0, offsetY: 0, style: { color: void 0, fontSize: "12px", fontWeight: 900, fontFamily: void 0, cssClass: "" } }, crosshairs: { show: !0, width: 1, position: "back", opacity: .9, stroke: { color: "#b6b6b6", width: 1, dashArray: 3 }, fill: { type: "solid", color: "#B1B9C4", gradient: { colorFrom: "#D8E3F0", colorTo: "#BED1E6", stops: [0, 100], opacityFrom: .4, opacityTo: .5 } }, dropShadow: { enabled: !1, left: 0, top: 0, blur: 1, opacity: .4 } }, tooltip: { enabled: !0, offsetY: 0, formatter: void 0, style: { fontSize: "12px", fontFamily: void 0 } } }, yaxis: this.yAxis, theme: { mode: "light", palette: "palette1", monochrome: { enabled: !1, color: "#008FFB", shadeTo: "light", shadeIntensity: .65 } } } } }]), t }(), T = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.graphics = new m(this.ctx), this.w.globals.isBarHorizontal && (this.invertAxis = !0), this.helpers = new w(this), this.xAxisAnnotations = new k(this), this.yAxisAnnotations = new L(this), this.pointsAnnotations = new P(this), this.w.globals.isBarHorizontal && this.w.config.yaxis[0].reversed && (this.inversedReversedAxis = !0), this.xDivision = this.w.globals.gridWidth / this.w.globals.dataPoints } return r(t, [{ key: "drawAxesAnnotations", value: function () { var t = this.w; if (t.globals.axisCharts) { for (var e = this.yAxisAnnotations.drawYAxisAnnotations(), i = this.xAxisAnnotations.drawXAxisAnnotations(), a = this.pointsAnnotations.drawPointAnnotations(), s = t.config.chart.animations.enabled, r = [e, i, a], o = [i.node, e.node, a.node], n = 0; n < 3; n++)t.globals.dom.elGraphical.add(r[n]), !s || t.globals.resized || t.globals.dataChanged || "scatter" !== t.config.chart.type && "bubble" !== t.config.chart.type && t.globals.dataPoints > 1 && o[n].classList.add("apexcharts-element-hidden"), t.globals.delayedElements.push({ el: o[n], index: 0 }); this.helpers.annotationsBackground() } } }, { key: "drawImageAnnos", value: function () { var t = this; this.w.config.annotations.images.map((function (e, i) { t.addImage(e, i) })) } }, { key: "drawTextAnnos", value: function () { var t = this; this.w.config.annotations.texts.map((function (e, i) { t.addText(e, i) })) } }, { key: "addXaxisAnnotation", value: function (t, e, i) { this.xAxisAnnotations.addXaxisAnnotation(t, e, i) } }, { key: "addYaxisAnnotation", value: function (t, e, i) { this.yAxisAnnotations.addYaxisAnnotation(t, e, i) } }, { key: "addPointAnnotation", value: function (t, e, i) { this.pointsAnnotations.addPointAnnotation(t, e, i) } }, { key: "addText", value: function (t, e) { var i = t.x, a = t.y, s = t.text, r = t.textAnchor, o = t.foreColor, n = t.fontSize, l = t.fontFamily, h = t.fontWeight, c = t.cssClass, d = t.backgroundColor, g = t.borderWidth, u = t.strokeDashArray, p = t.borderRadius, f = t.borderColor, x = t.appendTo, b = void 0 === x ? ".apexcharts-svg" : x, v = t.paddingLeft, m = void 0 === v ? 4 : v, y = t.paddingRight, w = void 0 === y ? 4 : y, k = t.paddingBottom, A = void 0 === k ? 2 : k, S = t.paddingTop, C = void 0 === S ? 2 : S, L = this.w, P = this.graphics.drawText({ x: i, y: a, text: s, textAnchor: r || "start", fontSize: n || "12px", fontWeight: h || "regular", fontFamily: l || L.config.chart.fontFamily, foreColor: o || L.config.chart.foreColor, cssClass: c }), M = L.globals.dom.baseEl.querySelector(b); M && M.appendChild(P.node); var I = P.bbox(); if (s) { var T = this.graphics.drawRect(I.x - m, I.y - C, I.width + m + w, I.height + A + C, p, d || "transparent", 1, g, f, u); M.insertBefore(T.node, P.node) } } }, { key: "addImage", value: function (t, e) { var i = this.w, a = t.path, s = t.x, r = void 0 === s ? 0 : s, o = t.y, n = void 0 === o ? 0 : o, l = t.width, h = void 0 === l ? 20 : l, c = t.height, d = void 0 === c ? 20 : c, g = t.appendTo, u = void 0 === g ? ".apexcharts-svg" : g, p = i.globals.dom.Paper.image(a); p.size(h, d).move(r, n); var f = i.globals.dom.baseEl.querySelector(u); return f && f.appendChild(p.node), p } }, { key: "addXaxisAnnotationExternal", value: function (t, e, i) { return this.addAnnotationExternal({ params: t, pushToMemory: e, context: i, type: "xaxis", contextMethod: i.addXaxisAnnotation }), i } }, { key: "addYaxisAnnotationExternal", value: function (t, e, i) { return this.addAnnotationExternal({ params: t, pushToMemory: e, context: i, type: "yaxis", contextMethod: i.addYaxisAnnotation }), i } }, { key: "addPointAnnotationExternal", value: function (t, e, i) { return void 0 === this.invertAxis && (this.invertAxis = i.w.globals.isBarHorizontal), this.addAnnotationExternal({ params: t, pushToMemory: e, context: i, type: "point", contextMethod: i.addPointAnnotation }), i } }, { key: "addAnnotationExternal", value: function (t) { var e = t.params, i = t.pushToMemory, a = t.context, s = t.type, r = t.contextMethod, o = a, n = o.w, l = n.globals.dom.baseEl.querySelector(".apexcharts-".concat(s, "-annotations")), h = l.childNodes.length + 1, c = new I, d = Object.assign({}, "xaxis" === s ? c.xAxisAnnotation : "yaxis" === s ? c.yAxisAnnotation : c.pointAnnotation), g = x.extend(d, e); switch (s) { case "xaxis": this.addXaxisAnnotation(g, l, h); break; case "yaxis": this.addYaxisAnnotation(g, l, h); break; case "point": this.addPointAnnotation(g, l, h) }var u = n.globals.dom.baseEl.querySelector(".apexcharts-".concat(s, "-annotations .apexcharts-").concat(s, "-annotation-label[rel='").concat(h, "']")), p = this.helpers.addBackgroundToAnno(u, g); return p && l.insertBefore(p.node, u), i && n.globals.memory.methodsToExec.push({ context: o, id: g.id ? g.id : x.randomId(), method: r, label: "addAnnotation", params: e }), a } }, { key: "clearAnnotations", value: function (t) { var e = t.w, i = e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis-annotations, .apexcharts-xaxis-annotations, .apexcharts-point-annotations"); e.globals.memory.methodsToExec.map((function (t, i) { "addText" !== t.label && "addAnnotation" !== t.label || e.globals.memory.methodsToExec.splice(i, 1) })), i = x.listToArray(i), Array.prototype.forEach.call(i, (function (t) { for (; t.firstChild;)t.removeChild(t.firstChild) })) } }, { key: "removeAnnotation", value: function (t, e) { var i = t.w, a = i.globals.dom.baseEl.querySelectorAll(".".concat(e)); a && (i.globals.memory.methodsToExec.map((function (t, a) { t.id === e && i.globals.memory.methodsToExec.splice(a, 1) })), Array.prototype.forEach.call(a, (function (t) { t.parentElement.removeChild(t) }))) } }]), t }(), z = function (t) { var e, i = t.isTimeline, a = t.ctx, s = t.seriesIndex, r = t.dataPointIndex, o = t.y1, n = t.y2, l = t.w, h = l.globals.seriesRangeStart[s][r], c = l.globals.seriesRangeEnd[s][r], d = l.globals.labels[r], g = l.config.series[s].name ? l.config.series[s].name : "", u = l.globals.ttKeyFormatter, p = l.config.tooltip.y.title.formatter, f = { w: l, seriesIndex: s, dataPointIndex: r, start: h, end: c }; ("function" == typeof p && (g = p(g, f)), null !== (e = l.config.series[s].data[r]) && void 0 !== e && e.x && (d = l.config.series[s].data[r].x), i) || "datetime" === l.config.xaxis.type && (d = new S(a).xLabelFormat(l.globals.ttKeyFormatter, d, d, { i: void 0, dateFormatter: new A(a).formatDate, w: l })); "function" == typeof u && (d = u(d, f)), Number.isFinite(o) && Number.isFinite(n) && (h = o, c = n); var x = "", b = "", v = l.globals.colors[s]; if (void 0 === l.config.tooltip.x.formatter) if ("datetime" === l.config.xaxis.type) { var m = new A(a); x = m.formatDate(m.getDate(h), l.config.tooltip.x.format), b = m.formatDate(m.getDate(c), l.config.tooltip.x.format) } else x = h, b = c; else x = l.config.tooltip.x.formatter(h), b = l.config.tooltip.x.formatter(c); return { start: h, end: c, startVal: x, endVal: b, ylabel: d, color: v, seriesName: g } }, X = function (t) { var e = t.color, i = t.seriesName, a = t.ylabel, s = t.start, r = t.end, o = t.seriesIndex, n = t.dataPointIndex, l = t.ctx.tooltip.tooltipLabels.getFormatters(o); s = l.yLbFormatter(s), r = l.yLbFormatter(r); var h = l.yLbFormatter(t.w.globals.series[o][n]), c = '\n '.concat(s, '\n - \n ').concat(r, "\n "); return '
      ' + (i || "") + '
      ' + a + ": " + (t.w.globals.comboCharts ? "rangeArea" === t.w.config.series[o].type || "rangeBar" === t.w.config.series[o].type ? c : "".concat(h, "") : c) + "
      " }, E = function () { function t(e) { a(this, t), this.opts = e } return r(t, [{ key: "hideYAxis", value: function () { this.opts.yaxis[0].show = !1, this.opts.yaxis[0].title.text = "", this.opts.yaxis[0].axisBorder.show = !1, this.opts.yaxis[0].axisTicks.show = !1, this.opts.yaxis[0].floating = !0 } }, { key: "line", value: function () { return { chart: { animations: { easing: "swing" } }, dataLabels: { enabled: !1 }, stroke: { width: 5, curve: "straight" }, markers: { size: 0, hover: { sizeOffset: 6 } }, xaxis: { crosshairs: { width: 1 } } } } }, { key: "sparkline", value: function (t) { this.hideYAxis(); return x.extend(t, { grid: { show: !1, padding: { left: 0, right: 0, top: 0, bottom: 0 } }, legend: { show: !1 }, xaxis: { labels: { show: !1 }, tooltip: { enabled: !1 }, axisBorder: { show: !1 }, axisTicks: { show: !1 } }, chart: { toolbar: { show: !1 }, zoom: { enabled: !1 } }, dataLabels: { enabled: !1 } }) } }, { key: "slope", value: function () { return this.hideYAxis(), { chart: { toolbar: { show: !1 }, zoom: { enabled: !1 } }, dataLabels: { enabled: !0, formatter: function (t, e) { var i = e.w.config.series[e.seriesIndex].name; return null !== t ? i + ": " + t : "" }, background: { enabled: !1 }, offsetX: -5 }, grid: { xaxis: { lines: { show: !0 } }, yaxis: { lines: { show: !1 } } }, xaxis: { position: "top", labels: { style: { fontSize: 14, fontWeight: 900 } }, tooltip: { enabled: !1 }, crosshairs: { show: !1 } }, markers: { size: 8, hover: { sizeOffset: 1 } }, legend: { show: !1 }, tooltip: { shared: !1, intersect: !0, followCursor: !0 }, stroke: { width: 5, curve: "straight" } } } }, { key: "bar", value: function () { return { chart: { stacked: !1, animations: { easing: "swing" } }, plotOptions: { bar: { dataLabels: { position: "center" } } }, dataLabels: { style: { colors: ["#fff"] }, background: { enabled: !1 } }, stroke: { width: 0, lineCap: "round" }, fill: { opacity: .85 }, legend: { markers: { shape: "square", radius: 2, size: 8 } }, tooltip: { shared: !1, intersect: !0 }, xaxis: { tooltip: { enabled: !1 }, tickPlacement: "between", crosshairs: { width: "barWidth", position: "back", fill: { type: "gradient" }, dropShadow: { enabled: !1 }, stroke: { width: 0 } } } } } }, { key: "funnel", value: function () { return this.hideYAxis(), e(e({}, this.bar()), {}, { chart: { animations: { easing: "linear", speed: 800, animateGradually: { enabled: !1 } } }, plotOptions: { bar: { horizontal: !0, borderRadiusApplication: "around", borderRadius: 0, dataLabels: { position: "center" } } }, grid: { show: !1, padding: { left: 0, right: 0 } }, xaxis: { labels: { show: !1 }, tooltip: { enabled: !1 }, axisBorder: { show: !1 }, axisTicks: { show: !1 } } }) } }, { key: "candlestick", value: function () { var t = this; return { stroke: { width: 1, colors: ["#333"] }, fill: { opacity: 1 }, dataLabels: { enabled: !1 }, tooltip: { shared: !0, custom: function (e) { var i = e.seriesIndex, a = e.dataPointIndex, s = e.w; return t._getBoxTooltip(s, i, a, ["Open", "High", "", "Low", "Close"], "candlestick") } }, states: { active: { filter: { type: "none" } } }, xaxis: { crosshairs: { width: 1 } } } } }, { key: "boxPlot", value: function () { var t = this; return { chart: { animations: { dynamicAnimation: { enabled: !1 } } }, stroke: { width: 1, colors: ["#24292e"] }, dataLabels: { enabled: !1 }, tooltip: { shared: !0, custom: function (e) { var i = e.seriesIndex, a = e.dataPointIndex, s = e.w; return t._getBoxTooltip(s, i, a, ["Minimum", "Q1", "Median", "Q3", "Maximum"], "boxPlot") } }, markers: { size: 5, strokeWidth: 1, strokeColors: "#111" }, xaxis: { crosshairs: { width: 1 } } } } }, { key: "rangeBar", value: function () { return { chart: { animations: { animateGradually: !1 } }, stroke: { width: 0, lineCap: "square" }, plotOptions: { bar: { borderRadius: 0, dataLabels: { position: "center" } } }, dataLabels: { enabled: !1, formatter: function (t, e) { e.ctx; var i = e.seriesIndex, a = e.dataPointIndex, s = e.w, r = function () { var t = s.globals.seriesRangeStart[i][a]; return s.globals.seriesRangeEnd[i][a] - t }; return s.globals.comboCharts ? "rangeBar" === s.config.series[i].type || "rangeArea" === s.config.series[i].type ? r() : t : r() }, background: { enabled: !1 }, style: { colors: ["#fff"] } }, markers: { size: 10 }, tooltip: { shared: !1, followCursor: !0, custom: function (t) { return t.w.config.plotOptions && t.w.config.plotOptions.bar && t.w.config.plotOptions.bar.horizontal ? function (t) { var i = z(e(e({}, t), {}, { isTimeline: !0 })), a = i.color, s = i.seriesName, r = i.ylabel, o = i.startVal, n = i.endVal; return X(e(e({}, t), {}, { color: a, seriesName: s, ylabel: r, start: o, end: n })) }(t) : function (t) { var i = z(t), a = i.color, s = i.seriesName, r = i.ylabel, o = i.start, n = i.end; return X(e(e({}, t), {}, { color: a, seriesName: s, ylabel: r, start: o, end: n })) }(t) } }, xaxis: { tickPlacement: "between", tooltip: { enabled: !1 }, crosshairs: { stroke: { width: 0 } } } } } }, { key: "dumbbell", value: function (t) { var e, i; return null !== (e = t.plotOptions.bar) && void 0 !== e && e.barHeight || (t.plotOptions.bar.barHeight = 2), null !== (i = t.plotOptions.bar) && void 0 !== i && i.columnWidth || (t.plotOptions.bar.columnWidth = 2), t } }, { key: "area", value: function () { return { stroke: { width: 4, fill: { type: "solid", gradient: { inverseColors: !1, shade: "light", type: "vertical", opacityFrom: .65, opacityTo: .5, stops: [0, 100, 100] } } }, fill: { type: "gradient", gradient: { inverseColors: !1, shade: "light", type: "vertical", opacityFrom: .65, opacityTo: .5, stops: [0, 100, 100] } }, markers: { size: 0, hover: { sizeOffset: 6 } }, tooltip: { followCursor: !1 } } } }, { key: "rangeArea", value: function () { return { stroke: { curve: "straight", width: 0 }, fill: { type: "solid", opacity: .6 }, markers: { size: 0 }, states: { hover: { filter: { type: "none" } }, active: { filter: { type: "none" } } }, tooltip: { intersect: !1, shared: !0, followCursor: !0, custom: function (t) { return function (t) { var i = z(t), a = i.color, s = i.seriesName, r = i.ylabel, o = i.start, n = i.end; return X(e(e({}, t), {}, { color: a, seriesName: s, ylabel: r, start: o, end: n })) }(t) } } } } }, { key: "brush", value: function (t) { return x.extend(t, { chart: { toolbar: { autoSelected: "selection", show: !1 }, zoom: { enabled: !1 } }, dataLabels: { enabled: !1 }, stroke: { width: 1 }, tooltip: { enabled: !1 }, xaxis: { tooltip: { enabled: !1 } } }) } }, { key: "stacked100", value: function (t) { t.dataLabels = t.dataLabels || {}, t.dataLabels.formatter = t.dataLabels.formatter || void 0; var e = t.dataLabels.formatter; return t.yaxis.forEach((function (e, i) { t.yaxis[i].min = 0, t.yaxis[i].max = 100 })), "bar" === t.chart.type && (t.dataLabels.formatter = e || function (t) { return "number" == typeof t && t ? t.toFixed(0) + "%" : t }), t } }, { key: "stackedBars", value: function () { var t = this.bar(); return e(e({}, t), {}, { plotOptions: e(e({}, t.plotOptions), {}, { bar: e(e({}, t.plotOptions.bar), {}, { borderRadiusApplication: "end", borderRadiusWhenStacked: "last" }) }) }) } }, { key: "convertCatToNumeric", value: function (t) { return t.xaxis.convertedCatToNumeric = !0, t } }, { key: "convertCatToNumericXaxis", value: function (t, e, i) { t.xaxis.type = "numeric", t.xaxis.labels = t.xaxis.labels || {}, t.xaxis.labels.formatter = t.xaxis.labels.formatter || function (t) { return x.isNumber(t) ? Math.floor(t) : t }; var a = t.xaxis.labels.formatter, s = t.xaxis.categories && t.xaxis.categories.length ? t.xaxis.categories : t.labels; return i && i.length && (s = i.map((function (t) { return Array.isArray(t) ? t : String(t) }))), s && s.length && (t.xaxis.labels.formatter = function (t) { return x.isNumber(t) ? a(s[Math.floor(t) - 1]) : a(t) }), t.xaxis.categories = [], t.labels = [], t.xaxis.tickAmount = t.xaxis.tickAmount || "dataPoints", t } }, { key: "bubble", value: function () { return { dataLabels: { style: { colors: ["#fff"] } }, tooltip: { shared: !1, intersect: !0 }, xaxis: { crosshairs: { width: 0 } }, fill: { type: "solid", gradient: { shade: "light", inverse: !0, shadeIntensity: .55, opacityFrom: .4, opacityTo: .8 } } } } }, { key: "scatter", value: function () { return { dataLabels: { enabled: !1 }, tooltip: { shared: !1, intersect: !0 }, markers: { size: 6, strokeWidth: 1, hover: { sizeOffset: 2 } } } } }, { key: "heatmap", value: function () { return { chart: { stacked: !1 }, fill: { opacity: 1 }, dataLabels: { style: { colors: ["#fff"] } }, stroke: { colors: ["#fff"] }, tooltip: { followCursor: !0, marker: { show: !1 }, x: { show: !1 } }, legend: { position: "top", markers: { shape: "square", size: 10, offsetY: 2 } }, grid: { padding: { right: 20 } } } } }, { key: "treemap", value: function () { return { chart: { zoom: { enabled: !1 } }, dataLabels: { style: { fontSize: 14, fontWeight: 600, colors: ["#fff"] } }, stroke: { show: !0, width: 2, colors: ["#fff"] }, legend: { show: !1 }, fill: { gradient: { stops: [0, 100] } }, tooltip: { followCursor: !0, x: { show: !1 } }, grid: { padding: { left: 0, right: 0 } }, xaxis: { crosshairs: { show: !1 }, tooltip: { enabled: !1 } } } } }, { key: "pie", value: function () { return { chart: { toolbar: { show: !1 } }, plotOptions: { pie: { donut: { labels: { show: !1 } } } }, dataLabels: { formatter: function (t) { return t.toFixed(1) + "%" }, style: { colors: ["#fff"] }, background: { enabled: !1 }, dropShadow: { enabled: !0 } }, stroke: { colors: ["#fff"] }, fill: { opacity: 1, gradient: { shade: "light", stops: [0, 100] } }, tooltip: { theme: "dark", fillSeriesColor: !0 }, legend: { position: "right" } } } }, { key: "donut", value: function () { return { chart: { toolbar: { show: !1 } }, dataLabels: { formatter: function (t) { return t.toFixed(1) + "%" }, style: { colors: ["#fff"] }, background: { enabled: !1 }, dropShadow: { enabled: !0 } }, stroke: { colors: ["#fff"] }, fill: { opacity: 1, gradient: { shade: "light", shadeIntensity: .35, stops: [80, 100], opacityFrom: 1, opacityTo: 1 } }, tooltip: { theme: "dark", fillSeriesColor: !0 }, legend: { position: "right" } } } }, { key: "polarArea", value: function () { return { chart: { toolbar: { show: !1 } }, dataLabels: { formatter: function (t) { return t.toFixed(1) + "%" }, enabled: !1 }, stroke: { show: !0, width: 2 }, fill: { opacity: .7 }, tooltip: { theme: "dark", fillSeriesColor: !0 }, legend: { position: "right" } } } }, { key: "radar", value: function () { return this.opts.yaxis[0].labels.offsetY = this.opts.yaxis[0].labels.offsetY ? this.opts.yaxis[0].labels.offsetY : 6, { dataLabels: { enabled: !1, style: { fontSize: "11px" } }, stroke: { width: 2 }, markers: { size: 3, strokeWidth: 1, strokeOpacity: 1 }, fill: { opacity: .2 }, tooltip: { shared: !1, intersect: !0, followCursor: !0 }, grid: { show: !1 }, xaxis: { labels: { formatter: function (t) { return t }, style: { colors: ["#a8a8a8"], fontSize: "11px" } }, tooltip: { enabled: !1 }, crosshairs: { show: !1 } } } } }, { key: "radialBar", value: function () { return { chart: { animations: { dynamicAnimation: { enabled: !0, speed: 800 } }, toolbar: { show: !1 } }, fill: { gradient: { shade: "dark", shadeIntensity: .4, inverseColors: !1, type: "diagonal2", opacityFrom: 1, opacityTo: 1, stops: [70, 98, 100] } }, legend: { show: !1, position: "right" }, tooltip: { enabled: !1, fillSeriesColor: !0 } } } }, { key: "_getBoxTooltip", value: function (t, e, i, a, s) { var r = t.globals.seriesCandleO[e][i], o = t.globals.seriesCandleH[e][i], n = t.globals.seriesCandleM[e][i], l = t.globals.seriesCandleL[e][i], h = t.globals.seriesCandleC[e][i]; return t.config.series[e].type && t.config.series[e].type !== s ? '
      \n '.concat(t.config.series[e].name ? t.config.series[e].name : "series-" + (e + 1), ": ").concat(t.globals.series[e][i], "\n
      ") : '
      ') + "
      ".concat(a[0], ': ') + r + "
      " + "
      ".concat(a[1], ': ') + o + "
      " + (n ? "
      ".concat(a[2], ': ') + n + "
      " : "") + "
      ".concat(a[3], ': ') + l + "
      " + "
      ".concat(a[4], ': ') + h + "
      " } }]), t }(), Y = function () { function t(e) { a(this, t), this.opts = e } return r(t, [{ key: "init", value: function (t) { var e = t.responsiveOverride, a = this.opts, s = new I, r = new E(a); this.chartType = a.chart.type, a = this.extendYAxis(a), a = this.extendAnnotations(a); var o = s.init(), n = {}; if (a && "object" === i(a)) { var l, h, c, d, g, u, p, f, b, v, m = {}; m = -1 !== ["line", "area", "bar", "candlestick", "boxPlot", "rangeBar", "rangeArea", "bubble", "scatter", "heatmap", "treemap", "pie", "polarArea", "donut", "radar", "radialBar"].indexOf(a.chart.type) ? r[a.chart.type]() : r.line(), null !== (l = a.plotOptions) && void 0 !== l && null !== (h = l.bar) && void 0 !== h && h.isFunnel && (m = r.funnel()), a.chart.stacked && "bar" === a.chart.type && (m = r.stackedBars()), null !== (c = a.chart.brush) && void 0 !== c && c.enabled && (m = r.brush(m)), null !== (d = a.plotOptions) && void 0 !== d && null !== (g = d.line) && void 0 !== g && g.isSlopeChart && (m = r.slope()), a.chart.stacked && "100%" === a.chart.stackType && (a = r.stacked100(a)), null !== (u = a.plotOptions) && void 0 !== u && null !== (p = u.bar) && void 0 !== p && p.isDumbbell && (a = r.dumbbell(a)), this.checkForDarkTheme(window.Apex), this.checkForDarkTheme(a), a.xaxis = a.xaxis || window.Apex.xaxis || {}, e || (a.xaxis.convertedCatToNumeric = !1), (null !== (f = (a = this.checkForCatToNumericXAxis(this.chartType, m, a)).chart.sparkline) && void 0 !== f && f.enabled || null !== (b = window.Apex.chart) && void 0 !== b && null !== (v = b.sparkline) && void 0 !== v && v.enabled) && (m = r.sparkline(m)), n = x.extend(o, m) } var y = x.extend(n, window.Apex); return o = x.extend(y, a), o = this.handleUserInputErrors(o) } }, { key: "checkForCatToNumericXAxis", value: function (t, e, i) { var a, s, r = new E(i), o = ("bar" === t || "boxPlot" === t) && (null === (a = i.plotOptions) || void 0 === a || null === (s = a.bar) || void 0 === s ? void 0 : s.horizontal), n = "pie" === t || "polarArea" === t || "donut" === t || "radar" === t || "radialBar" === t || "heatmap" === t, l = "datetime" !== i.xaxis.type && "numeric" !== i.xaxis.type, h = i.xaxis.tickPlacement ? i.xaxis.tickPlacement : e.xaxis && e.xaxis.tickPlacement; return o || n || !l || "between" === h || (i = r.convertCatToNumeric(i)), i } }, { key: "extendYAxis", value: function (t, e) { var i = new I; (void 0 === t.yaxis || !t.yaxis || Array.isArray(t.yaxis) && 0 === t.yaxis.length) && (t.yaxis = {}), t.yaxis.constructor !== Array && window.Apex.yaxis && window.Apex.yaxis.constructor !== Array && (t.yaxis = x.extend(t.yaxis, window.Apex.yaxis)), t.yaxis.constructor !== Array ? t.yaxis = [x.extend(i.yAxis, t.yaxis)] : t.yaxis = x.extendArray(t.yaxis, i.yAxis); var a = !1; t.yaxis.forEach((function (t) { t.logarithmic && (a = !0) })); var s = t.series; return e && !s && (s = e.config.series), a && s.length !== t.yaxis.length && s.length && (t.yaxis = s.map((function (e, a) { if (e.name || (s[a].name = "series-".concat(a + 1)), t.yaxis[a]) return t.yaxis[a].seriesName = s[a].name, t.yaxis[a]; var r = x.extend(i.yAxis, t.yaxis[0]); return r.show = !1, r }))), a && s.length > 1 && s.length !== t.yaxis.length && console.warn("A multi-series logarithmic chart should have equal number of series and y-axes"), t } }, { key: "extendAnnotations", value: function (t) { return void 0 === t.annotations && (t.annotations = {}, t.annotations.yaxis = [], t.annotations.xaxis = [], t.annotations.points = []), t = this.extendYAxisAnnotations(t), t = this.extendXAxisAnnotations(t), t = this.extendPointAnnotations(t) } }, { key: "extendYAxisAnnotations", value: function (t) { var e = new I; return t.annotations.yaxis = x.extendArray(void 0 !== t.annotations.yaxis ? t.annotations.yaxis : [], e.yAxisAnnotation), t } }, { key: "extendXAxisAnnotations", value: function (t) { var e = new I; return t.annotations.xaxis = x.extendArray(void 0 !== t.annotations.xaxis ? t.annotations.xaxis : [], e.xAxisAnnotation), t } }, { key: "extendPointAnnotations", value: function (t) { var e = new I; return t.annotations.points = x.extendArray(void 0 !== t.annotations.points ? t.annotations.points : [], e.pointAnnotation), t } }, { key: "checkForDarkTheme", value: function (t) { t.theme && "dark" === t.theme.mode && (t.tooltip || (t.tooltip = {}), "light" !== t.tooltip.theme && (t.tooltip.theme = "dark"), t.chart.foreColor || (t.chart.foreColor = "#f6f7f8"), t.chart.background || (t.chart.background = "#424242"), t.theme.palette || (t.theme.palette = "palette4")) } }, { key: "handleUserInputErrors", value: function (t) { var e = t; if (e.tooltip.shared && e.tooltip.intersect) throw new Error("tooltip.shared cannot be enabled when tooltip.intersect is true. Turn off any other option by setting it to false."); if ("bar" === e.chart.type && e.plotOptions.bar.horizontal) { if (e.yaxis.length > 1) throw new Error("Multiple Y Axis for bars are not supported. Switch to column chart by setting plotOptions.bar.horizontal=false"); e.yaxis[0].reversed && (e.yaxis[0].opposite = !0), e.xaxis.tooltip.enabled = !1, e.yaxis[0].tooltip.enabled = !1, e.chart.zoom.enabled = !1 } return "bar" !== e.chart.type && "rangeBar" !== e.chart.type || e.tooltip.shared && "barWidth" === e.xaxis.crosshairs.width && e.series.length > 1 && (e.xaxis.crosshairs.width = "tickWidth"), "candlestick" !== e.chart.type && "boxPlot" !== e.chart.type || e.yaxis[0].reversed && (console.warn("Reversed y-axis in ".concat(e.chart.type, " chart is not supported.")), e.yaxis[0].reversed = !1), e } }]), t }(), F = function () { function t() { a(this, t) } return r(t, [{ key: "initGlobalVars", value: function (t) { t.series = [], t.seriesCandleO = [], t.seriesCandleH = [], t.seriesCandleM = [], t.seriesCandleL = [], t.seriesCandleC = [], t.seriesRangeStart = [], t.seriesRangeEnd = [], t.seriesRange = [], t.seriesPercent = [], t.seriesGoals = [], t.seriesX = [], t.seriesZ = [], t.seriesNames = [], t.seriesTotals = [], t.seriesLog = [], t.seriesColors = [], t.stackedSeriesTotals = [], t.seriesXvalues = [], t.seriesYvalues = [], t.labels = [], t.hasXaxisGroups = !1, t.groups = [], t.barGroups = [], t.lineGroups = [], t.areaGroups = [], t.hasSeriesGroups = !1, t.seriesGroups = [], t.categoryLabels = [], t.timescaleLabels = [], t.noLabelsProvided = !1, t.resizeTimer = null, t.selectionResizeTimer = null, t.delayedElements = [], t.pointsArray = [], t.dataLabelsRects = [], t.isXNumeric = !1, t.skipLastTimelinelabel = !1, t.skipFirstTimelinelabel = !1, t.isDataXYZ = !1, t.isMultiLineX = !1, t.isMultipleYAxis = !1, t.maxY = -Number.MAX_VALUE, t.minY = Number.MIN_VALUE, t.minYArr = [], t.maxYArr = [], t.maxX = -Number.MAX_VALUE, t.minX = Number.MAX_VALUE, t.initialMaxX = -Number.MAX_VALUE, t.initialMinX = Number.MAX_VALUE, t.maxDate = 0, t.minDate = Number.MAX_VALUE, t.minZ = Number.MAX_VALUE, t.maxZ = -Number.MAX_VALUE, t.minXDiff = Number.MAX_VALUE, t.yAxisScale = [], t.xAxisScale = null, t.xAxisTicksPositions = [], t.yLabelsCoords = [], t.yTitleCoords = [], t.barPadForNumericAxis = 0, t.padHorizontal = 0, t.xRange = 0, t.yRange = [], t.zRange = 0, t.dataPoints = 0, t.xTickAmount = 0, t.multiAxisTickAmount = 0 } }, { key: "globalVars", value: function (t) { return { chartID: null, cuid: null, events: { beforeMount: [], mounted: [], updated: [], clicked: [], selection: [], dataPointSelection: [], zoomed: [], scrolled: [] }, colors: [], clientX: null, clientY: null, fill: { colors: [] }, stroke: { colors: [] }, dataLabels: { style: { colors: [] } }, radarPolygons: { fill: { colors: [] } }, markers: { colors: [], size: t.markers.size, largestSize: 0 }, animationEnded: !1, isTouchDevice: "ontouchstart" in window || navigator.msMaxTouchPoints, isDirty: !1, isExecCalled: !1, initialConfig: null, initialSeries: [], lastXAxis: [], lastYAxis: [], columnSeries: null, labels: [], timescaleLabels: [], noLabelsProvided: !1, allSeriesCollapsed: !1, collapsedSeries: [], collapsedSeriesIndices: [], ancillaryCollapsedSeries: [], ancillaryCollapsedSeriesIndices: [], risingSeries: [], dataFormatXNumeric: !1, capturedSeriesIndex: -1, capturedDataPointIndex: -1, selectedDataPoints: [], goldenPadding: 35, invalidLogScale: !1, ignoreYAxisIndexes: [], maxValsInArrayIndex: 0, radialSize: 0, selection: void 0, zoomEnabled: "zoom" === t.chart.toolbar.autoSelected && t.chart.toolbar.tools.zoom && t.chart.zoom.enabled, panEnabled: "pan" === t.chart.toolbar.autoSelected && t.chart.toolbar.tools.pan, selectionEnabled: "selection" === t.chart.toolbar.autoSelected && t.chart.toolbar.tools.selection, yaxis: null, mousedown: !1, lastClientPosition: {}, visibleXRange: void 0, yValueDecimal: 0, total: 0, SVGNS: "http://www.w3.org/2000/svg", svgWidth: 0, svgHeight: 0, noData: !1, locale: {}, dom: {}, memory: { methodsToExec: [] }, shouldAnimate: !0, skipLastTimelinelabel: !1, skipFirstTimelinelabel: !1, delayedElements: [], axisCharts: !0, isDataXYZ: !1, isSlopeChart: t.plotOptions.line.isSlopeChart, resized: !1, resizeTimer: null, comboCharts: !1, dataChanged: !1, previousPaths: [], allSeriesHasEqualX: !0, pointsArray: [], dataLabelsRects: [], lastDrawnDataLabelsIndexes: [], hasNullValues: !1, easing: null, zoomed: !1, gridWidth: 0, gridHeight: 0, rotateXLabels: !1, defaultLabels: !1, xLabelFormatter: void 0, yLabelFormatters: [], xaxisTooltipFormatter: void 0, ttKeyFormatter: void 0, ttVal: void 0, ttZFormatter: void 0, LINE_HEIGHT_RATIO: 1.618, xAxisLabelsHeight: 0, xAxisGroupLabelsHeight: 0, xAxisLabelsWidth: 0, yAxisLabelsWidth: 0, scaleX: 1, scaleY: 1, translateX: 0, translateY: 0, translateYAxisX: [], yAxisWidths: [], translateXAxisY: 0, translateXAxisX: 0, tooltip: null, niceScaleAllowedMagMsd: [[1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10], [1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10]], niceScaleDefaultTicks: [1, 2, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24], seriesYAxisMap: [], seriesYAxisReverseMap: [] } } }, { key: "init", value: function (t) { var e = this.globalVars(t); return this.initGlobalVars(e), e.initialConfig = x.extend({}, t), e.initialSeries = x.clone(t.series), e.lastXAxis = x.clone(e.initialConfig.xaxis), e.lastYAxis = x.clone(e.initialConfig.yaxis), e } }]), t }(), R = function () { function t(e) { a(this, t), this.opts = e } return r(t, [{ key: "init", value: function () { var t = new Y(this.opts).init({ responsiveOverride: !1 }); return { config: t, globals: (new F).init(t) } } }]), t }(), H = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.opts = null, this.seriesIndex = 0 } return r(t, [{ key: "clippedImgArea", value: function (t) { var e = this.w, i = e.config, a = parseInt(e.globals.gridWidth, 10), s = parseInt(e.globals.gridHeight, 10), r = a > s ? a : s, o = t.image, n = 0, l = 0; void 0 === t.width && void 0 === t.height ? void 0 !== i.fill.image.width && void 0 !== i.fill.image.height ? (n = i.fill.image.width + 1, l = i.fill.image.height) : (n = r + 1, l = r) : (n = t.width, l = t.height); var h = document.createElementNS(e.globals.SVGNS, "pattern"); m.setAttrs(h, { id: t.patternID, patternUnits: t.patternUnits ? t.patternUnits : "userSpaceOnUse", width: n + "px", height: l + "px" }); var c = document.createElementNS(e.globals.SVGNS, "image"); h.appendChild(c), c.setAttributeNS(window.SVG.xlink, "href", o), m.setAttrs(c, { x: 0, y: 0, preserveAspectRatio: "none", width: n + "px", height: l + "px" }), c.style.opacity = t.opacity, e.globals.dom.elDefs.node.appendChild(h) } }, { key: "getSeriesIndex", value: function (t) { var e = this.w, i = e.config.chart.type; return ("bar" === i || "rangeBar" === i) && e.config.plotOptions.bar.distributed || "heatmap" === i || "treemap" === i ? this.seriesIndex = t.seriesNumber : this.seriesIndex = t.seriesNumber % e.globals.series.length, this.seriesIndex } }, { key: "fillPath", value: function (t) { var e = this.w; this.opts = t; var i, a, s, r = this.w.config; this.seriesIndex = this.getSeriesIndex(t); var o = this.getFillColors()[this.seriesIndex]; void 0 !== e.globals.seriesColors[this.seriesIndex] && (o = e.globals.seriesColors[this.seriesIndex]), "function" == typeof o && (o = o({ seriesIndex: this.seriesIndex, dataPointIndex: t.dataPointIndex, value: t.value, w: e })); var n = t.fillType ? t.fillType : this.getFillType(this.seriesIndex), l = Array.isArray(r.fill.opacity) ? r.fill.opacity[this.seriesIndex] : r.fill.opacity; t.color && (o = t.color), o || (o = "#fff", console.warn("undefined color - ApexCharts")); var h = o; if (-1 === o.indexOf("rgb") ? o.length < 9 && (h = x.hexToRgba(o, l)) : o.indexOf("rgba") > -1 && (l = x.getOpacityFromRGBA(o)), t.opacity && (l = t.opacity), "pattern" === n && (a = this.handlePatternFill({ fillConfig: t.fillConfig, patternFill: a, fillColor: o, fillOpacity: l, defaultColor: h })), "gradient" === n && (s = this.handleGradientFill({ fillConfig: t.fillConfig, fillColor: o, fillOpacity: l, i: this.seriesIndex })), "image" === n) { var c = r.fill.image.src, d = t.patternID ? t.patternID : ""; this.clippedImgArea({ opacity: l, image: Array.isArray(c) ? t.seriesNumber < c.length ? c[t.seriesNumber] : c[0] : c, width: t.width ? t.width : void 0, height: t.height ? t.height : void 0, patternUnits: t.patternUnits, patternID: "pattern".concat(e.globals.cuid).concat(t.seriesNumber + 1).concat(d) }), i = "url(#pattern".concat(e.globals.cuid).concat(t.seriesNumber + 1).concat(d, ")") } else i = "gradient" === n ? s : "pattern" === n ? a : h; return t.solid && (i = h), i } }, { key: "getFillType", value: function (t) { var e = this.w; return Array.isArray(e.config.fill.type) ? e.config.fill.type[t] : e.config.fill.type } }, { key: "getFillColors", value: function () { var t = this.w, e = t.config, i = this.opts, a = []; return t.globals.comboCharts ? "line" === t.config.series[this.seriesIndex].type ? Array.isArray(t.globals.stroke.colors) ? a = t.globals.stroke.colors : a.push(t.globals.stroke.colors) : Array.isArray(t.globals.fill.colors) ? a = t.globals.fill.colors : a.push(t.globals.fill.colors) : "line" === e.chart.type ? Array.isArray(t.globals.stroke.colors) ? a = t.globals.stroke.colors : a.push(t.globals.stroke.colors) : Array.isArray(t.globals.fill.colors) ? a = t.globals.fill.colors : a.push(t.globals.fill.colors), void 0 !== i.fillColors && (a = [], Array.isArray(i.fillColors) ? a = i.fillColors.slice() : a.push(i.fillColors)), a } }, { key: "handlePatternFill", value: function (t) { var e = t.fillConfig, i = t.patternFill, a = t.fillColor, s = t.fillOpacity, r = t.defaultColor, o = this.w.config.fill; e && (o = e); var n = this.opts, l = new m(this.ctx), h = Array.isArray(o.pattern.strokeWidth) ? o.pattern.strokeWidth[this.seriesIndex] : o.pattern.strokeWidth, c = a; Array.isArray(o.pattern.style) ? i = void 0 !== o.pattern.style[n.seriesNumber] ? l.drawPattern(o.pattern.style[n.seriesNumber], o.pattern.width, o.pattern.height, c, h, s) : r : i = l.drawPattern(o.pattern.style, o.pattern.width, o.pattern.height, c, h, s); return i } }, { key: "handleGradientFill", value: function (t) { var i = t.fillColor, a = t.fillOpacity, s = t.fillConfig, r = t.i, o = this.w.config.fill; s && (o = e(e({}, o), s)); var n, l = this.opts, h = new m(this.ctx), c = new x, d = o.gradient.type, g = i, u = void 0 === o.gradient.opacityFrom ? a : Array.isArray(o.gradient.opacityFrom) ? o.gradient.opacityFrom[r] : o.gradient.opacityFrom; g.indexOf("rgba") > -1 && (u = x.getOpacityFromRGBA(g)); var p = void 0 === o.gradient.opacityTo ? a : Array.isArray(o.gradient.opacityTo) ? o.gradient.opacityTo[r] : o.gradient.opacityTo; if (void 0 === o.gradient.gradientToColors || 0 === o.gradient.gradientToColors.length) n = "dark" === o.gradient.shade ? c.shadeColor(-1 * parseFloat(o.gradient.shadeIntensity), i.indexOf("rgb") > -1 ? x.rgb2hex(i) : i) : c.shadeColor(parseFloat(o.gradient.shadeIntensity), i.indexOf("rgb") > -1 ? x.rgb2hex(i) : i); else if (o.gradient.gradientToColors[l.seriesNumber]) { var f = o.gradient.gradientToColors[l.seriesNumber]; n = f, f.indexOf("rgba") > -1 && (p = x.getOpacityFromRGBA(f)) } else n = i; if (o.gradient.gradientFrom && (g = o.gradient.gradientFrom), o.gradient.gradientTo && (n = o.gradient.gradientTo), o.gradient.inverseColors) { var b = g; g = n, n = b } return g.indexOf("rgb") > -1 && (g = x.rgb2hex(g)), n.indexOf("rgb") > -1 && (n = x.rgb2hex(n)), h.drawGradient(d, g, n, u, p, l.size, o.gradient.stops, o.gradient.colorStops, r) } }]), t }(), D = function () { function t(e, i) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "setGlobalMarkerSize", value: function () { var t = this.w; if (t.globals.markers.size = Array.isArray(t.config.markers.size) ? t.config.markers.size : [t.config.markers.size], t.globals.markers.size.length > 0) { if (t.globals.markers.size.length < t.globals.series.length + 1) for (var e = 0; e <= t.globals.series.length; e++)void 0 === t.globals.markers.size[e] && t.globals.markers.size.push(t.globals.markers.size[0]) } else t.globals.markers.size = t.config.series.map((function (e) { return t.config.markers.size })) } }, { key: "plotChartMarkers", value: function (t, e, i, a) { var s, r = arguments.length > 4 && void 0 !== arguments[4] && arguments[4], o = this.w, n = e, l = t, h = null, c = new m(this.ctx), d = o.config.markers.discrete && o.config.markers.discrete.length; if ((o.globals.markers.size[e] > 0 || r || d) && (h = c.group({ class: r || d ? "" : "apexcharts-series-markers" })).attr("clip-path", "url(#gridRectMarkerMask".concat(o.globals.cuid, ")")), Array.isArray(l.x)) for (var g = 0; g < l.x.length; g++) { var u = i; 1 === i && 0 === g && (u = 0), 1 === i && 1 === g && (u = 1); var p = "apexcharts-marker"; if ("line" !== o.config.chart.type && "area" !== o.config.chart.type || o.globals.comboCharts || o.config.tooltip.intersect || (p += " no-pointer-events"), (Array.isArray(o.config.markers.size) ? o.globals.markers.size[e] > 0 : o.config.markers.size > 0) || r || d) { x.isNumber(l.y[g]) ? p += " w".concat(x.randomId()) : p = "apexcharts-nullpoint"; var f = this.getMarkerConfig({ cssClass: p, seriesIndex: e, dataPointIndex: u }); o.config.series[n].data[u] && (o.config.series[n].data[u].fillColor && (f.pointFillColor = o.config.series[n].data[u].fillColor), o.config.series[n].data[u].strokeColor && (f.pointStrokeColor = o.config.series[n].data[u].strokeColor)), a && (f.pSize = a), (l.x[g] < -o.globals.markers.largestSize || l.x[g] > o.globals.gridWidth + o.globals.markers.largestSize || l.y[g] < -o.globals.markers.largestSize || l.y[g] > o.globals.gridHeight + o.globals.markers.largestSize) && (f.pSize = 0), (s = c.drawMarker(l.x[g], l.y[g], f)).attr("rel", u), s.attr("j", u), s.attr("index", e), s.node.setAttribute("default-marker-size", f.pSize), new v(this.ctx).setSelectionFilter(s, e, u), this.addEvents(s), h && h.add(s) } else void 0 === o.globals.pointsArray[e] && (o.globals.pointsArray[e] = []), o.globals.pointsArray[e].push([l.x[g], l.y[g]]) } return h } }, { key: "getMarkerConfig", value: function (t) { var e = t.cssClass, i = t.seriesIndex, a = t.dataPointIndex, s = void 0 === a ? null : a, r = t.finishRadius, o = void 0 === r ? null : r, n = this.w, l = this.getMarkerStyle(i), h = n.globals.markers.size[i], c = n.config.markers; return null !== s && c.discrete.length && c.discrete.map((function (t) { t.seriesIndex === i && t.dataPointIndex === s && (l.pointStrokeColor = t.strokeColor, l.pointFillColor = t.fillColor, h = t.size, l.pointShape = t.shape) })), { pSize: null === o ? h : o, pRadius: c.radius, width: Array.isArray(c.width) ? c.width[i] : c.width, height: Array.isArray(c.height) ? c.height[i] : c.height, pointStrokeWidth: Array.isArray(c.strokeWidth) ? c.strokeWidth[i] : c.strokeWidth, pointStrokeColor: l.pointStrokeColor, pointFillColor: l.pointFillColor, shape: l.pointShape || (Array.isArray(c.shape) ? c.shape[i] : c.shape), class: e, pointStrokeOpacity: Array.isArray(c.strokeOpacity) ? c.strokeOpacity[i] : c.strokeOpacity, pointStrokeDashArray: Array.isArray(c.strokeDashArray) ? c.strokeDashArray[i] : c.strokeDashArray, pointFillOpacity: Array.isArray(c.fillOpacity) ? c.fillOpacity[i] : c.fillOpacity, seriesIndex: i } } }, { key: "addEvents", value: function (t) { var e = this.w, i = new m(this.ctx); t.node.addEventListener("mouseenter", i.pathMouseEnter.bind(this.ctx, t)), t.node.addEventListener("mouseleave", i.pathMouseLeave.bind(this.ctx, t)), t.node.addEventListener("mousedown", i.pathMouseDown.bind(this.ctx, t)), t.node.addEventListener("click", e.config.markers.onClick), t.node.addEventListener("dblclick", e.config.markers.onDblClick), t.node.addEventListener("touchstart", i.pathMouseDown.bind(this.ctx, t), { passive: !0 }) } }, { key: "getMarkerStyle", value: function (t) { var e = this.w, i = e.globals.markers.colors, a = e.config.markers.strokeColor || e.config.markers.strokeColors; return { pointStrokeColor: Array.isArray(a) ? a[t] : a, pointFillColor: Array.isArray(i) ? i[t] : i } } }]), t }(), O = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.initialAnim = this.w.config.chart.animations.enabled, this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled } return r(t, [{ key: "draw", value: function (t, e, i) { var a = this.w, s = new m(this.ctx), r = i.realIndex, o = i.pointsPos, n = i.zRatio, l = i.elParent, h = s.group({ class: "apexcharts-series-markers apexcharts-series-".concat(a.config.chart.type) }); if (h.attr("clip-path", "url(#gridRectMarkerMask".concat(a.globals.cuid, ")")), Array.isArray(o.x)) for (var c = 0; c < o.x.length; c++) { var d = e + 1, g = !0; 0 === e && 0 === c && (d = 0), 0 === e && 1 === c && (d = 1); var u = 0, p = a.globals.markers.size[r]; if (n !== 1 / 0) { var f = a.config.plotOptions.bubble; p = a.globals.seriesZ[r][d], f.zScaling && (p /= n), f.minBubbleRadius && p < f.minBubbleRadius && (p = f.minBubbleRadius), f.maxBubbleRadius && p > f.maxBubbleRadius && (p = f.maxBubbleRadius) } a.config.chart.animations.enabled || (u = p); var x = o.x[c], b = o.y[c]; if (u = u || 0, null !== b && void 0 !== a.globals.series[r][d] || (g = !1), g) { var v = this.drawPoint(x, b, u, p, r, d, e); h.add(v) } l.add(h) } } }, { key: "drawPoint", value: function (t, e, i, a, s, r, o) { var n = this.w, l = s, h = new b(this.ctx), c = new v(this.ctx), d = new H(this.ctx), g = new D(this.ctx), u = new m(this.ctx), p = g.getMarkerConfig({ cssClass: "apexcharts-marker", seriesIndex: l, dataPointIndex: r, finishRadius: "bubble" === n.config.chart.type || n.globals.comboCharts && n.config.series[s] && "bubble" === n.config.series[s].type ? a : null }); a = p.pSize; var f, x = d.fillPath({ seriesNumber: s, dataPointIndex: r, color: p.pointFillColor, patternUnits: "objectBoundingBox", value: n.globals.series[s][o] }); if ("circle" === p.shape ? f = u.drawCircle(i) : "square" !== p.shape && "rect" !== p.shape || (f = u.drawRect(0, 0, p.width - p.pointStrokeWidth / 2, p.height - p.pointStrokeWidth / 2, p.pRadius)), n.config.series[l].data[r] && n.config.series[l].data[r].fillColor && (x = n.config.series[l].data[r].fillColor), f.attr({ x: t - p.width / 2 - p.pointStrokeWidth / 2, y: e - p.height / 2 - p.pointStrokeWidth / 2, cx: t, cy: e, fill: x, "fill-opacity": p.pointFillOpacity, stroke: p.pointStrokeColor, r: a, "stroke-width": p.pointStrokeWidth, "stroke-dasharray": p.pointStrokeDashArray, "stroke-opacity": p.pointStrokeOpacity }), n.config.chart.dropShadow.enabled) { var y = n.config.chart.dropShadow; c.dropShadow(f, y, s) } if (!this.initialAnim || n.globals.dataChanged || n.globals.resized) n.globals.animationEnded = !0; else { var w = n.config.chart.animations.speed; h.animateMarker(f, 0, "circle" === p.shape ? a : { width: p.width, height: p.height }, w, n.globals.easing, (function () { window.setTimeout((function () { h.animationCompleted(f) }), 100) })) } if (n.globals.dataChanged && "circle" === p.shape) if (this.dynamicAnim) { var k, A, S, C, L = n.config.chart.animations.dynamicAnimation.speed; null != (C = n.globals.previousPaths[s] && n.globals.previousPaths[s][o]) && (k = C.x, A = C.y, S = void 0 !== C.r ? C.r : a); for (var P = 0; P < n.globals.collapsedSeries.length; P++)n.globals.collapsedSeries[P].index === s && (L = 1, a = 0); 0 === t && 0 === e && (a = 0), h.animateCircle(f, { cx: k, cy: A, r: S }, { cx: t, cy: e, r: a }, L, n.globals.easing) } else f.attr({ r: a }); return f.attr({ rel: r, j: r, index: s, "default-marker-size": a }), c.setSelectionFilter(f, s, r), g.addEvents(f), f.node.classList.add("apexcharts-marker"), f } }, { key: "centerTextInBubble", value: function (t) { var e = this.w; return { y: t += parseInt(e.config.dataLabels.style.fontSize, 10) / 4 } } }]), t }(), N = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "dataLabelsCorrection", value: function (t, e, i, a, s, r, o) { var n = this.w, l = !1, h = new m(this.ctx).getTextRects(i, o), c = h.width, d = h.height; e < 0 && (e = 0), e > n.globals.gridHeight + d && (e = n.globals.gridHeight + d / 2), void 0 === n.globals.dataLabelsRects[a] && (n.globals.dataLabelsRects[a] = []), n.globals.dataLabelsRects[a].push({ x: t, y: e, width: c, height: d }); var g = n.globals.dataLabelsRects[a].length - 2, u = void 0 !== n.globals.lastDrawnDataLabelsIndexes[a] ? n.globals.lastDrawnDataLabelsIndexes[a][n.globals.lastDrawnDataLabelsIndexes[a].length - 1] : 0; if (void 0 !== n.globals.dataLabelsRects[a][g]) { var p = n.globals.dataLabelsRects[a][u]; (t > p.x + p.width || e > p.y + p.height || e + d < p.y || t + c < p.x) && (l = !0) } return (0 === s || r) && (l = !0), { x: t, y: e, textRects: h, drawnextLabel: l } } }, { key: "drawDataLabel", value: function (t) { var e = this, i = t.type, a = t.pos, s = t.i, r = t.j, o = t.isRangeStart, n = t.strokeWidth, l = void 0 === n ? 2 : n, h = this.w, c = new m(this.ctx), d = h.config.dataLabels, g = 0, u = 0, p = r, f = null; if (-1 !== h.globals.collapsedSeriesIndices.indexOf(s) || !d.enabled || !Array.isArray(a.x)) return f; f = c.group({ class: "apexcharts-data-labels" }); for (var x = 0; x < a.x.length; x++)if (g = a.x[x] + d.offsetX, u = a.y[x] + d.offsetY + l, !isNaN(g)) { 1 === r && 0 === x && (p = 0), 1 === r && 1 === x && (p = 1); var b = h.globals.series[s][p]; "rangeArea" === i && (b = o ? h.globals.seriesRangeStart[s][p] : h.globals.seriesRangeEnd[s][p]); var v = "", y = function (t) { return h.config.dataLabels.formatter(t, { ctx: e.ctx, seriesIndex: s, dataPointIndex: p, w: h }) }; if ("bubble" === h.config.chart.type) v = y(b = h.globals.seriesZ[s][p]), u = a.y[x], u = new O(this.ctx).centerTextInBubble(u, s, p).y; else void 0 !== b && (v = y(b)); var w = h.config.dataLabels.textAnchor; h.globals.isSlopeChart && (w = 0 === p ? "end" : p === h.config.series[s].data.length - 1 ? "start" : "middle"), this.plotDataLabelsText({ x: g, y: u, text: v, i: s, j: p, parent: f, offsetCorrection: !0, dataLabelsConfig: h.config.dataLabels, textAnchor: w }) } return f } }, { key: "plotDataLabelsText", value: function (t) { var e = this.w, i = new m(this.ctx), a = t.x, s = t.y, r = t.i, o = t.j, n = t.text, l = t.textAnchor, h = t.fontSize, c = t.parent, d = t.dataLabelsConfig, g = t.color, u = t.alwaysDrawDataLabel, p = t.offsetCorrection; if (!(Array.isArray(e.config.dataLabels.enabledOnSeries) && e.config.dataLabels.enabledOnSeries.indexOf(r) < 0)) { var f = { x: a, y: s, drawnextLabel: !0, textRects: null }; p && (f = this.dataLabelsCorrection(a, s, n, r, o, u, parseInt(d.style.fontSize, 10))), e.globals.zoomed || (a = f.x, s = f.y), f.textRects && (a < -20 - f.textRects.width || a > e.globals.gridWidth + f.textRects.width + 30) && (n = ""); var x = e.globals.dataLabels.style.colors[r]; (("bar" === e.config.chart.type || "rangeBar" === e.config.chart.type) && e.config.plotOptions.bar.distributed || e.config.dataLabels.distributed) && (x = e.globals.dataLabels.style.colors[o]), "function" == typeof x && (x = x({ series: e.globals.series, seriesIndex: r, dataPointIndex: o, w: e })), g && (x = g); var b = d.offsetX, y = d.offsetY; if ("bar" !== e.config.chart.type && "rangeBar" !== e.config.chart.type || (b = 0, y = 0), e.globals.isSlopeChart && (0 !== o && (b = -2 * d.offsetX + 5), 0 !== o && o !== e.config.series[r].data.length - 1 && (b = 0)), f.drawnextLabel) { var w = i.drawText({ width: 100, height: parseInt(d.style.fontSize, 10), x: a + b, y: s + y, foreColor: x, textAnchor: l || d.textAnchor, text: n, fontSize: h || d.style.fontSize, fontFamily: d.style.fontFamily, fontWeight: d.style.fontWeight || "normal" }); if (w.attr({ class: "apexcharts-datalabel", cx: a, cy: s }), d.dropShadow.enabled) { var k = d.dropShadow; new v(this.ctx).dropShadow(w, k) } c.add(w), void 0 === e.globals.lastDrawnDataLabelsIndexes[r] && (e.globals.lastDrawnDataLabelsIndexes[r] = []), e.globals.lastDrawnDataLabelsIndexes[r].push(o) } } } }, { key: "addBackgroundToDataLabel", value: function (t, e) { var i = this.w, a = i.config.dataLabels.background, s = a.padding, r = a.padding / 2, o = e.width, n = e.height, l = new m(this.ctx).drawRect(e.x - s, e.y - r / 2, o + 2 * s, n + r, a.borderRadius, "transparent" === i.config.chart.background ? "#fff" : i.config.chart.background, a.opacity, a.borderWidth, a.borderColor); a.dropShadow.enabled && new v(this.ctx).dropShadow(l, a.dropShadow); return l } }, { key: "dataLabelsBackground", value: function () { var t = this.w; if ("bubble" !== t.config.chart.type) for (var e = t.globals.dom.baseEl.querySelectorAll(".apexcharts-datalabels text"), i = 0; i < e.length; i++) { var a = e[i], s = a.getBBox(), r = null; if (s.width && s.height && (r = this.addBackgroundToDataLabel(a, s)), r) { a.parentNode.insertBefore(r.node, a); var o = a.getAttribute("fill"); t.config.chart.animations.enabled && !t.globals.resized && !t.globals.dataChanged ? r.animate().attr({ fill: o }) : r.attr({ fill: o }), a.setAttribute("fill", t.config.dataLabels.background.foreColor) } } } }, { key: "bringForward", value: function () { for (var t = this.w, e = t.globals.dom.baseEl.querySelectorAll(".apexcharts-datalabels"), i = t.globals.dom.baseEl.querySelector(".apexcharts-plot-series:last-child"), a = 0; a < e.length; a++)i && i.insertBefore(e[a], i.nextSibling) } }]), t }(), W = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.legendInactiveClass = "legend-mouseover-inactive" } return r(t, [{ key: "getAllSeriesEls", value: function () { return this.w.globals.dom.baseEl.getElementsByClassName("apexcharts-series") } }, { key: "getSeriesByName", value: function (t) { return this.w.globals.dom.baseEl.querySelector(".apexcharts-inner .apexcharts-series[seriesName='".concat(x.escapeString(t), "']")) } }, { key: "isSeriesHidden", value: function (t) { var e = this.getSeriesByName(t), i = parseInt(e.getAttribute("data:realIndex"), 10); return { isHidden: e.classList.contains("apexcharts-series-collapsed"), realIndex: i } } }, { key: "addCollapsedClassToSeries", value: function (t, e) { var i = this.w; function a(i) { for (var a = 0; a < i.length; a++)i[a].index === e && t.node.classList.add("apexcharts-series-collapsed") } a(i.globals.collapsedSeries), a(i.globals.ancillaryCollapsedSeries) } }, { key: "toggleSeries", value: function (t) { var e = this.isSeriesHidden(t); return this.ctx.legend.legendHelpers.toggleDataSeries(e.realIndex, e.isHidden), e.isHidden } }, { key: "showSeries", value: function (t) { var e = this.isSeriesHidden(t); e.isHidden && this.ctx.legend.legendHelpers.toggleDataSeries(e.realIndex, !0) } }, { key: "hideSeries", value: function (t) { var e = this.isSeriesHidden(t); e.isHidden || this.ctx.legend.legendHelpers.toggleDataSeries(e.realIndex, !1) } }, { key: "resetSeries", value: function () { var t = !(arguments.length > 0 && void 0 !== arguments[0]) || arguments[0], e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1], i = !(arguments.length > 2 && void 0 !== arguments[2]) || arguments[2], a = this.w, s = x.clone(a.globals.initialSeries); a.globals.previousPaths = [], i ? (a.globals.collapsedSeries = [], a.globals.ancillaryCollapsedSeries = [], a.globals.collapsedSeriesIndices = [], a.globals.ancillaryCollapsedSeriesIndices = []) : s = this.emptyCollapsedSeries(s), a.config.series = s, t && (e && (a.globals.zoomed = !1, this.ctx.updateHelpers.revertDefaultAxisMinMax()), this.ctx.updateHelpers._updateSeries(s, a.config.chart.animations.dynamicAnimation.enabled)) } }, { key: "emptyCollapsedSeries", value: function (t) { for (var e = this.w, i = 0; i < t.length; i++)e.globals.collapsedSeriesIndices.indexOf(i) > -1 && (t[i].data = []); return t } }, { key: "toggleSeriesOnHover", value: function (t, e) { var i = this.w; e || (e = t.target); var a = i.globals.dom.baseEl.querySelectorAll(".apexcharts-series, .apexcharts-datalabels, .apexcharts-yaxis"); if ("mousemove" === t.type) { var s = parseInt(e.getAttribute("rel"), 10) - 1, r = null, o = null, n = null; if (i.globals.axisCharts || "radialBar" === i.config.chart.type) if (i.globals.axisCharts) { r = i.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(s, "']")), o = i.globals.dom.baseEl.querySelector(".apexcharts-datalabels[data\\:realIndex='".concat(s, "']")); var l = i.globals.seriesYAxisReverseMap[s]; n = i.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(l, "']")) } else r = i.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(s + 1, "']")); else r = i.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(s + 1, "'] path")); for (var h = 0; h < a.length; h++)a[h].classList.add(this.legendInactiveClass); null !== r && (i.globals.axisCharts || r.parentNode.classList.remove(this.legendInactiveClass), r.classList.remove(this.legendInactiveClass), null !== o && o.classList.remove(this.legendInactiveClass), null !== n && n.classList.remove(this.legendInactiveClass)) } else if ("mouseout" === t.type) for (var c = 0; c < a.length; c++)a[c].classList.remove(this.legendInactiveClass) } }, { key: "highlightRangeInSeries", value: function (t, e) { var i = this, a = this.w, s = a.globals.dom.baseEl.getElementsByClassName("apexcharts-heatmap-rect"), r = function (t) { for (var e = 0; e < s.length; e++)s[e].classList[t](i.legendInactiveClass) }; if ("mousemove" === t.type) { var o = parseInt(e.getAttribute("rel"), 10) - 1; r("add"), function (t) { for (var e = 0; e < s.length; e++) { var a = parseInt(s[e].getAttribute("val"), 10); a >= t.from && a <= t.to && s[e].classList.remove(i.legendInactiveClass) } }(a.config.plotOptions.heatmap.colorScale.ranges[o]) } else "mouseout" === t.type && r("remove") } }, { key: "getActiveConfigSeriesIndex", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "asc", e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : [], i = this.w, a = 0; if (i.config.series.length > 1) for (var s = i.config.series.map((function (t, a) { return t.data && t.data.length > 0 && -1 === i.globals.collapsedSeriesIndices.indexOf(a) && (!i.globals.comboCharts || 0 === e.length || e.length && e.indexOf(i.config.series[a].type) > -1) ? a : -1 })), r = "asc" === t ? 0 : s.length - 1; "asc" === t ? r < s.length : r >= 0; "asc" === t ? r++ : r--)if (-1 !== s[r]) { a = s[r]; break } return a } }, { key: "getBarSeriesIndices", value: function () { return this.w.globals.comboCharts ? this.w.config.series.map((function (t, e) { return "bar" === t.type || "column" === t.type ? e : -1 })).filter((function (t) { return -1 !== t })) : this.w.config.series.map((function (t, e) { return e })) } }, { key: "getPreviousPaths", value: function () { var t = this.w; function e(e, i, a) { for (var s = e[i].childNodes, r = { type: a, paths: [], realIndex: e[i].getAttribute("data:realIndex") }, o = 0; o < s.length; o++)if (s[o].hasAttribute("pathTo")) { var n = s[o].getAttribute("pathTo"); r.paths.push({ d: n }) } t.globals.previousPaths.push(r) } t.globals.previousPaths = [];["line", "area", "bar", "rangebar", "rangeArea", "candlestick", "radar"].forEach((function (i) { for (var a, s = (a = i, t.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(a, "-series .apexcharts-series"))), r = 0; r < s.length; r++)e(s, r, i) })), this.handlePrevBubbleScatterPaths("bubble"), this.handlePrevBubbleScatterPaths("scatter"); var i = t.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(t.config.chart.type, " .apexcharts-series")); if (i.length > 0) for (var a = function (e) { for (var i = t.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(t.config.chart.type, " .apexcharts-series[data\\:realIndex='").concat(e, "'] rect")), a = [], s = function (t) { var e = function (e) { return i[t].getAttribute(e) }, s = { x: parseFloat(e("x")), y: parseFloat(e("y")), width: parseFloat(e("width")), height: parseFloat(e("height")) }; a.push({ rect: s, color: i[t].getAttribute("color") }) }, r = 0; r < i.length; r++)s(r); t.globals.previousPaths.push(a) }, s = 0; s < i.length; s++)a(s); t.globals.axisCharts || (t.globals.previousPaths = t.globals.series) } }, { key: "handlePrevBubbleScatterPaths", value: function (t) { var e = this.w, i = e.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(t, "-series .apexcharts-series")); if (i.length > 0) for (var a = 0; a < i.length; a++) { for (var s = e.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(t, "-series .apexcharts-series[data\\:realIndex='").concat(a, "'] circle")), r = [], o = 0; o < s.length; o++)r.push({ x: s[o].getAttribute("cx"), y: s[o].getAttribute("cy"), r: s[o].getAttribute("r") }); e.globals.previousPaths.push(r) } } }, { key: "clearPreviousPaths", value: function () { var t = this.w; t.globals.previousPaths = [], t.globals.allSeriesCollapsed = !1 } }, { key: "handleNoData", value: function () { var t = this.w, e = t.config.noData, i = new m(this.ctx), a = t.globals.svgWidth / 2, s = t.globals.svgHeight / 2, r = "middle"; if (t.globals.noData = !0, t.globals.animationEnded = !0, "left" === e.align ? (a = 10, r = "start") : "right" === e.align && (a = t.globals.svgWidth - 10, r = "end"), "top" === e.verticalAlign ? s = 50 : "bottom" === e.verticalAlign && (s = t.globals.svgHeight - 50), a += e.offsetX, s = s + parseInt(e.style.fontSize, 10) + 2 + e.offsetY, void 0 !== e.text && "" !== e.text) { var o = i.drawText({ x: a, y: s, text: e.text, textAnchor: r, fontSize: e.style.fontSize, fontFamily: e.style.fontFamily, foreColor: e.style.color, opacity: 1, class: "apexcharts-text-nodata" }); t.globals.dom.Paper.add(o) } } }, { key: "setNullSeriesToZeroValues", value: function (t) { for (var e = this.w, i = 0; i < t.length; i++)if (0 === t[i].length) for (var a = 0; a < t[e.globals.maxValsInArrayIndex].length; a++)t[i].push(0); return t } }, { key: "hasAllSeriesEqualX", value: function () { for (var t = !0, e = this.w, i = this.filteredSeriesX(), a = 0; a < i.length - 1; a++)if (i[a][0] !== i[a + 1][0]) { t = !1; break } return e.globals.allSeriesHasEqualX = t, t } }, { key: "filteredSeriesX", value: function () { var t = this.w.globals.seriesX.map((function (t) { return t.length > 0 ? t : [] })); return t } }]), t }(), B = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.twoDSeries = [], this.threeDSeries = [], this.twoDSeriesX = [], this.seriesGoals = [], this.coreUtils = new y(this.ctx) } return r(t, [{ key: "isMultiFormat", value: function () { return this.isFormatXY() || this.isFormat2DArray() } }, { key: "isFormatXY", value: function () { var t = this.w.config.series.slice(), e = new W(this.ctx); if (this.activeSeriesIndex = e.getActiveConfigSeriesIndex(), void 0 !== t[this.activeSeriesIndex].data && t[this.activeSeriesIndex].data.length > 0 && null !== t[this.activeSeriesIndex].data[0] && void 0 !== t[this.activeSeriesIndex].data[0].x && null !== t[this.activeSeriesIndex].data[0]) return !0 } }, { key: "isFormat2DArray", value: function () { var t = this.w.config.series.slice(), e = new W(this.ctx); if (this.activeSeriesIndex = e.getActiveConfigSeriesIndex(), void 0 !== t[this.activeSeriesIndex].data && t[this.activeSeriesIndex].data.length > 0 && void 0 !== t[this.activeSeriesIndex].data[0] && null !== t[this.activeSeriesIndex].data[0] && t[this.activeSeriesIndex].data[0].constructor === Array) return !0 } }, { key: "handleFormat2DArray", value: function (t, e) { for (var i = this.w.config, a = this.w.globals, s = "boxPlot" === i.chart.type || "boxPlot" === i.series[e].type, r = 0; r < t[e].data.length; r++)if (void 0 !== t[e].data[r][1] && (Array.isArray(t[e].data[r][1]) && 4 === t[e].data[r][1].length && !s ? this.twoDSeries.push(x.parseNumber(t[e].data[r][1][3])) : t[e].data[r].length >= 5 ? this.twoDSeries.push(x.parseNumber(t[e].data[r][4])) : this.twoDSeries.push(x.parseNumber(t[e].data[r][1])), a.dataFormatXNumeric = !0), "datetime" === i.xaxis.type) { var o = new Date(t[e].data[r][0]); o = new Date(o).getTime(), this.twoDSeriesX.push(o) } else this.twoDSeriesX.push(t[e].data[r][0]); for (var n = 0; n < t[e].data.length; n++)void 0 !== t[e].data[n][2] && (this.threeDSeries.push(t[e].data[n][2]), a.isDataXYZ = !0) } }, { key: "handleFormatXY", value: function (t, e) { var i = this.w.config, a = this.w.globals, s = new A(this.ctx), r = e; a.collapsedSeriesIndices.indexOf(e) > -1 && (r = this.activeSeriesIndex); for (var o = 0; o < t[e].data.length; o++)void 0 !== t[e].data[o].y && (Array.isArray(t[e].data[o].y) ? this.twoDSeries.push(x.parseNumber(t[e].data[o].y[t[e].data[o].y.length - 1])) : this.twoDSeries.push(x.parseNumber(t[e].data[o].y))), void 0 !== t[e].data[o].goals && Array.isArray(t[e].data[o].goals) ? (void 0 === this.seriesGoals[e] && (this.seriesGoals[e] = []), this.seriesGoals[e].push(t[e].data[o].goals)) : (void 0 === this.seriesGoals[e] && (this.seriesGoals[e] = []), this.seriesGoals[e].push(null)); for (var n = 0; n < t[r].data.length; n++) { var l = "string" == typeof t[r].data[n].x, h = Array.isArray(t[r].data[n].x), c = !h && !!s.isValidDate(t[r].data[n].x); if (l || c) if (l || i.xaxis.convertedCatToNumeric) { var d = a.isBarHorizontal && a.isRangeData; "datetime" !== i.xaxis.type || d ? (this.fallbackToCategory = !0, this.twoDSeriesX.push(t[r].data[n].x), isNaN(t[r].data[n].x) || "category" === this.w.config.xaxis.type || "string" == typeof t[r].data[n].x || (a.isXNumeric = !0)) : this.twoDSeriesX.push(s.parseDate(t[r].data[n].x)) } else "datetime" === i.xaxis.type ? this.twoDSeriesX.push(s.parseDate(t[r].data[n].x.toString())) : (a.dataFormatXNumeric = !0, a.isXNumeric = !0, this.twoDSeriesX.push(parseFloat(t[r].data[n].x))); else h ? (this.fallbackToCategory = !0, this.twoDSeriesX.push(t[r].data[n].x)) : (a.isXNumeric = !0, a.dataFormatXNumeric = !0, this.twoDSeriesX.push(t[r].data[n].x)) } if (t[e].data[0] && void 0 !== t[e].data[0].z) { for (var g = 0; g < t[e].data.length; g++)this.threeDSeries.push(t[e].data[g].z); a.isDataXYZ = !0 } } }, { key: "handleRangeData", value: function (t, e) { var i = this.w.globals, a = {}; return this.isFormat2DArray() ? a = this.handleRangeDataFormat("array", t, e) : this.isFormatXY() && (a = this.handleRangeDataFormat("xy", t, e)), i.seriesRangeStart.push(void 0 === a.start ? [] : a.start), i.seriesRangeEnd.push(void 0 === a.end ? [] : a.end), i.seriesRange.push(a.rangeUniques), i.seriesRange.forEach((function (t, e) { t && t.forEach((function (t, e) { t.y.forEach((function (e, i) { for (var a = 0; a < t.y.length; a++)if (i !== a) { var s = e.y1, r = e.y2, o = t.y[a].y1; s <= t.y[a].y2 && o <= r && (t.overlaps.indexOf(e.rangeName) < 0 && t.overlaps.push(e.rangeName), t.overlaps.indexOf(t.y[a].rangeName) < 0 && t.overlaps.push(t.y[a].rangeName)) } })) })) })), a } }, { key: "handleCandleStickBoxData", value: function (t, e) { var i = this.w.globals, a = {}; return this.isFormat2DArray() ? a = this.handleCandleStickBoxDataFormat("array", t, e) : this.isFormatXY() && (a = this.handleCandleStickBoxDataFormat("xy", t, e)), i.seriesCandleO[e] = a.o, i.seriesCandleH[e] = a.h, i.seriesCandleM[e] = a.m, i.seriesCandleL[e] = a.l, i.seriesCandleC[e] = a.c, a } }, { key: "handleRangeDataFormat", value: function (t, e, i) { var a = [], s = [], r = e[i].data.filter((function (t, e, i) { return e === i.findIndex((function (e) { return e.x === t.x })) })).map((function (t, e) { return { x: t.x, overlaps: [], y: [] } })); if ("array" === t) for (var o = 0; o < e[i].data.length; o++)Array.isArray(e[i].data[o]) ? (a.push(e[i].data[o][1][0]), s.push(e[i].data[o][1][1])) : (a.push(e[i].data[o]), s.push(e[i].data[o])); else if ("xy" === t) for (var n = function (t) { var o = Array.isArray(e[i].data[t].y), n = x.randomId(), l = e[i].data[t].x, h = { y1: o ? e[i].data[t].y[0] : e[i].data[t].y, y2: o ? e[i].data[t].y[1] : e[i].data[t].y, rangeName: n }; e[i].data[t].rangeName = n; var c = r.findIndex((function (t) { return t.x === l })); r[c].y.push(h), a.push(h.y1), s.push(h.y2) }, l = 0; l < e[i].data.length; l++)n(l); return { start: a, end: s, rangeUniques: r } } }, { key: "handleCandleStickBoxDataFormat", value: function (t, e, i) { var a = this.w, s = "boxPlot" === a.config.chart.type || "boxPlot" === a.config.series[i].type, r = [], o = [], n = [], l = [], h = []; if ("array" === t) if (s && 6 === e[i].data[0].length || !s && 5 === e[i].data[0].length) for (var c = 0; c < e[i].data.length; c++)r.push(e[i].data[c][1]), o.push(e[i].data[c][2]), s ? (n.push(e[i].data[c][3]), l.push(e[i].data[c][4]), h.push(e[i].data[c][5])) : (l.push(e[i].data[c][3]), h.push(e[i].data[c][4])); else for (var d = 0; d < e[i].data.length; d++)Array.isArray(e[i].data[d][1]) && (r.push(e[i].data[d][1][0]), o.push(e[i].data[d][1][1]), s ? (n.push(e[i].data[d][1][2]), l.push(e[i].data[d][1][3]), h.push(e[i].data[d][1][4])) : (l.push(e[i].data[d][1][2]), h.push(e[i].data[d][1][3]))); else if ("xy" === t) for (var g = 0; g < e[i].data.length; g++)Array.isArray(e[i].data[g].y) && (r.push(e[i].data[g].y[0]), o.push(e[i].data[g].y[1]), s ? (n.push(e[i].data[g].y[2]), l.push(e[i].data[g].y[3]), h.push(e[i].data[g].y[4])) : (l.push(e[i].data[g].y[2]), h.push(e[i].data[g].y[3]))); return { o: r, h: o, m: n, l: l, c: h } } }, { key: "parseDataAxisCharts", value: function (t) { var e = this, i = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : this.ctx, a = this.w.config, s = this.w.globals, r = new A(i), o = a.labels.length > 0 ? a.labels.slice() : a.xaxis.categories.slice(); s.isRangeBar = "rangeBar" === a.chart.type && s.isBarHorizontal, s.hasXaxisGroups = "category" === a.xaxis.type && a.xaxis.group.groups.length > 0, s.hasXaxisGroups && (s.groups = a.xaxis.group.groups), t.forEach((function (t, e) { void 0 !== t.name ? s.seriesNames.push(t.name) : s.seriesNames.push("series-" + parseInt(e + 1, 10)) })), this.coreUtils.setSeriesYAxisMappings(); var n = [], l = u(new Set(a.series.map((function (t) { return t.group })))); a.series.forEach((function (t, e) { var i = l.indexOf(t.group); n[i] || (n[i] = []), n[i].push(s.seriesNames[e]) })), s.seriesGroups = n; for (var h = function () { for (var t = 0; t < o.length; t++)if ("string" == typeof o[t]) { if (!r.isValidDate(o[t])) throw new Error("You have provided invalid Date format. Please provide a valid JavaScript Date"); e.twoDSeriesX.push(r.parseDate(o[t])) } else e.twoDSeriesX.push(o[t]) }, c = 0; c < t.length; c++) { if (this.twoDSeries = [], this.twoDSeriesX = [], this.threeDSeries = [], void 0 === t[c].data) return void console.error("It is a possibility that you may have not included 'data' property in series."); if ("rangeBar" !== a.chart.type && "rangeArea" !== a.chart.type && "rangeBar" !== t[c].type && "rangeArea" !== t[c].type || (s.isRangeData = !0, "rangeBar" !== a.chart.type && "rangeArea" !== a.chart.type || this.handleRangeData(t, c)), this.isMultiFormat()) this.isFormat2DArray() ? this.handleFormat2DArray(t, c) : this.isFormatXY() && this.handleFormatXY(t, c), "candlestick" !== a.chart.type && "candlestick" !== t[c].type && "boxPlot" !== a.chart.type && "boxPlot" !== t[c].type || this.handleCandleStickBoxData(t, c), s.series.push(this.twoDSeries), s.labels.push(this.twoDSeriesX), s.seriesX.push(this.twoDSeriesX), s.seriesGoals = this.seriesGoals, c !== this.activeSeriesIndex || this.fallbackToCategory || (s.isXNumeric = !0); else { "datetime" === a.xaxis.type ? (s.isXNumeric = !0, h(), s.seriesX.push(this.twoDSeriesX)) : "numeric" === a.xaxis.type && (s.isXNumeric = !0, o.length > 0 && (this.twoDSeriesX = o, s.seriesX.push(this.twoDSeriesX))), s.labels.push(this.twoDSeriesX); var d = t[c].data.map((function (t) { return x.parseNumber(t) })); s.series.push(d) } s.seriesZ.push(this.threeDSeries), void 0 !== t[c].color ? s.seriesColors.push(t[c].color) : s.seriesColors.push(void 0) } return this.w } }, { key: "parseDataNonAxisCharts", value: function (t) { var e = this.w.globals, i = this.w.config; e.series = t.slice(), e.seriesNames = i.labels.slice(); for (var a = 0; a < e.series.length; a++)void 0 === e.seriesNames[a] && e.seriesNames.push("series-" + (a + 1)); return this.w } }, { key: "handleExternalLabelsData", value: function (t) { var e = this.w.config, i = this.w.globals; if (e.xaxis.categories.length > 0) i.labels = e.xaxis.categories; else if (e.labels.length > 0) i.labels = e.labels.slice(); else if (this.fallbackToCategory) { if (i.labels = i.labels[0], i.seriesRange.length && (i.seriesRange.map((function (t) { t.forEach((function (t) { i.labels.indexOf(t.x) < 0 && t.x && i.labels.push(t.x) })) })), i.labels = Array.from(new Set(i.labels.map(JSON.stringify)), JSON.parse)), e.xaxis.convertedCatToNumeric) new E(e).convertCatToNumericXaxis(e, this.ctx, i.seriesX[0]), this._generateExternalLabels(t) } else this._generateExternalLabels(t) } }, { key: "_generateExternalLabels", value: function (t) { var e = this.w.globals, i = this.w.config, a = []; if (e.axisCharts) { if (e.series.length > 0) if (this.isFormatXY()) for (var s = i.series.map((function (t, e) { return t.data.filter((function (t, e, i) { return i.findIndex((function (e) { return e.x === t.x })) === e })) })), r = s.reduce((function (t, e, i, a) { return a[t].length > e.length ? t : i }), 0), o = 0; o < s[r].length; o++)a.push(o + 1); else for (var n = 0; n < e.series[e.maxValsInArrayIndex].length; n++)a.push(n + 1); e.seriesX = []; for (var l = 0; l < t.length; l++)e.seriesX.push(a); this.w.globals.isBarHorizontal || (e.isXNumeric = !0) } if (0 === a.length) { a = e.axisCharts ? [] : e.series.map((function (t, e) { return e + 1 })); for (var h = 0; h < t.length; h++)e.seriesX.push(a) } e.labels = a, i.xaxis.convertedCatToNumeric && (e.categoryLabels = a.map((function (t) { return i.xaxis.labels.formatter(t) }))), e.noLabelsProvided = !0 } }, { key: "parseData", value: function (t) { var e = this.w, i = e.config, a = e.globals; if (this.excludeCollapsedSeriesInYAxis(), this.fallbackToCategory = !1, this.ctx.core.resetGlobals(), this.ctx.core.isMultipleY(), a.axisCharts ? (this.parseDataAxisCharts(t), this.coreUtils.getLargestSeries()) : this.parseDataNonAxisCharts(t), i.chart.stacked) { var s = new W(this.ctx); a.series = s.setNullSeriesToZeroValues(a.series) } this.coreUtils.getSeriesTotals(), a.axisCharts && (a.stackedSeriesTotals = this.coreUtils.getStackedSeriesTotals(), a.stackedSeriesTotalsByGroups = this.coreUtils.getStackedSeriesTotalsByGroups()), this.coreUtils.getPercentSeries(), a.dataFormatXNumeric || a.isXNumeric && ("numeric" !== i.xaxis.type || 0 !== i.labels.length || 0 !== i.xaxis.categories.length) || this.handleExternalLabelsData(t); for (var r = this.coreUtils.getCategoryLabels(a.labels), o = 0; o < r.length; o++)if (Array.isArray(r[o])) { a.isMultiLineX = !0; break } } }, { key: "excludeCollapsedSeriesInYAxis", value: function () { var t = this.w, e = []; t.globals.seriesYAxisMap.forEach((function (i, a) { var s = 0; i.forEach((function (e) { -1 !== t.globals.collapsedSeriesIndices.indexOf(e) && s++ })), s > 0 && s == i.length && e.push(a) })), t.globals.ignoreYAxisIndexes = e.map((function (t) { return t })) } }]), t }(), G = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "scaleSvgNode", value: function (t, e) { var i = parseFloat(t.getAttributeNS(null, "width")), a = parseFloat(t.getAttributeNS(null, "height")); t.setAttributeNS(null, "width", i * e), t.setAttributeNS(null, "height", a * e), t.setAttributeNS(null, "viewBox", "0 0 " + i + " " + a) } }, { key: "fixSvgStringForIe11", value: function (t) { if (!x.isIE11()) return t.replace(/ /g, " "); var e = 0, i = t.replace(/xmlns="http:\/\/www.w3.org\/2000\/svg"/g, (function (t) { return 2 === ++e ? 'xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev"' : t })); return i = (i = i.replace(/xmlns:NS\d+=""/g, "")).replace(/NS\d+:(\w+:\w+=")/g, "$1") } }, { key: "getSvgString", value: function (t) { null == t && (t = 1); var e = this.w.globals.dom.Paper.svg(); if (1 !== t) { var i = this.w.globals.dom.Paper.node.cloneNode(!0); this.scaleSvgNode(i, t), e = (new XMLSerializer).serializeToString(i) } return this.fixSvgStringForIe11(e) } }, { key: "cleanup", value: function () { var t = this.w, e = t.globals.dom.baseEl.getElementsByClassName("apexcharts-xcrosshairs"), i = t.globals.dom.baseEl.getElementsByClassName("apexcharts-ycrosshairs"), a = t.globals.dom.baseEl.querySelectorAll(".apexcharts-zoom-rect, .apexcharts-selection-rect"); Array.prototype.forEach.call(a, (function (t) { t.setAttribute("width", 0) })), e && e[0] && (e[0].setAttribute("x", -500), e[0].setAttribute("x1", -500), e[0].setAttribute("x2", -500)), i && i[0] && (i[0].setAttribute("y", -100), i[0].setAttribute("y1", -100), i[0].setAttribute("y2", -100)) } }, { key: "svgUrl", value: function () { this.cleanup(); var t = this.getSvgString(), e = new Blob([t], { type: "image/svg+xml;charset=utf-8" }); return URL.createObjectURL(e) } }, { key: "dataURI", value: function (t) { var e = this; return new Promise((function (i) { var a = e.w, s = t ? t.scale || t.width / a.globals.svgWidth : 1; e.cleanup(); var r = document.createElement("canvas"); r.width = a.globals.svgWidth * s, r.height = parseInt(a.globals.dom.elWrap.style.height, 10) * s; var o = "transparent" === a.config.chart.background ? "#fff" : a.config.chart.background, n = r.getContext("2d"); n.fillStyle = o, n.fillRect(0, 0, r.width * s, r.height * s); var l = e.getSvgString(s); if (window.canvg && x.isIE11()) { var h = window.canvg.Canvg.fromString(n, l, { ignoreClear: !0, ignoreDimensions: !0 }); h.start(); var c = r.msToBlob(); h.stop(), i({ blob: c }) } else { var d = "data:image/svg+xml," + encodeURIComponent(l), g = new Image; g.crossOrigin = "anonymous", g.onload = function () { if (n.drawImage(g, 0, 0), r.msToBlob) { var t = r.msToBlob(); i({ blob: t }) } else { var e = r.toDataURL("image/png"); i({ imgURI: e }) } }, g.src = d } })) } }, { key: "exportToSVG", value: function () { this.triggerDownload(this.svgUrl(), this.w.config.chart.toolbar.export.svg.filename, ".svg") } }, { key: "exportToPng", value: function () { var t = this; this.dataURI().then((function (e) { var i = e.imgURI, a = e.blob; a ? navigator.msSaveOrOpenBlob(a, t.w.globals.chartID + ".png") : t.triggerDownload(i, t.w.config.chart.toolbar.export.png.filename, ".png") })) } }, { key: "exportToCSV", value: function (t) { var e = this, i = t.series, a = t.fileName, s = t.columnDelimiter, r = void 0 === s ? "," : s, o = t.lineDelimiter, n = void 0 === o ? "\n" : o, l = this.w; i || (i = l.config.series); var h, c, d = [], g = [], p = "", f = l.globals.series.map((function (t, e) { return -1 === l.globals.collapsedSeriesIndices.indexOf(e) ? t : [] })), b = function (t) { return "datetime" === l.config.xaxis.type && String(t).length >= 10 }, v = Math.max.apply(Math, u(i.map((function (t) { return t.data ? t.data.length : 0 })))), m = new B(this.ctx), y = new C(this.ctx), w = function (t) { var i = ""; if (l.globals.axisCharts) { if ("category" === l.config.xaxis.type || l.config.xaxis.convertedCatToNumeric) if (l.globals.isBarHorizontal) { var a = l.globals.yLabelFormatters[0], s = new W(e.ctx).getActiveConfigSeriesIndex(); i = a(l.globals.labels[t], { seriesIndex: s, dataPointIndex: t, w: l }) } else i = y.getLabel(l.globals.labels, l.globals.timescaleLabels, 0, t).text; "datetime" === l.config.xaxis.type && (l.config.xaxis.categories.length ? i = l.config.xaxis.categories[t] : l.config.labels.length && (i = l.config.labels[t])) } else i = l.config.labels[t]; return null === i ? "nullvalue" : (Array.isArray(i) && (i = i.join(" ")), x.isNumber(i) ? i : i.split(r).join("")) }, k = function (t, e) { if (d.length && 0 === e && g.push(d.join(r)), t.data) { t.data = t.data.length && t.data || u(Array(v)).map((function () { return "" })); for (var a = 0; a < t.data.length; a++) { d = []; var s = w(a); if ("nullvalue" !== s) { if (s || (m.isFormatXY() ? s = i[e].data[a].x : m.isFormat2DArray() && (s = i[e].data[a] ? i[e].data[a][0] : "")), 0 === e) { d.push(b(s) ? l.config.chart.toolbar.export.csv.dateFormatter(s) : x.isNumber(s) ? s : s.split(r).join("")); for (var o = 0; o < l.globals.series.length; o++) { var n; if (m.isFormatXY()) d.push(null === (n = i[o].data[a]) || void 0 === n ? void 0 : n.y); else d.push(f[o][a]) } } ("candlestick" === l.config.chart.type || t.type && "candlestick" === t.type) && (d.pop(), d.push(l.globals.seriesCandleO[e][a]), d.push(l.globals.seriesCandleH[e][a]), d.push(l.globals.seriesCandleL[e][a]), d.push(l.globals.seriesCandleC[e][a])), ("boxPlot" === l.config.chart.type || t.type && "boxPlot" === t.type) && (d.pop(), d.push(l.globals.seriesCandleO[e][a]), d.push(l.globals.seriesCandleH[e][a]), d.push(l.globals.seriesCandleM[e][a]), d.push(l.globals.seriesCandleL[e][a]), d.push(l.globals.seriesCandleC[e][a])), "rangeBar" === l.config.chart.type && (d.pop(), d.push(l.globals.seriesRangeStart[e][a]), d.push(l.globals.seriesRangeEnd[e][a])), d.length && g.push(d.join(r)) } } } }; d.push(l.config.chart.toolbar.export.csv.headerCategory), "boxPlot" === l.config.chart.type ? (d.push("minimum"), d.push("q1"), d.push("median"), d.push("q3"), d.push("maximum")) : "candlestick" === l.config.chart.type ? (d.push("open"), d.push("high"), d.push("low"), d.push("close")) : "rangeBar" === l.config.chart.type ? (d.push("minimum"), d.push("maximum")) : i.map((function (t, e) { var i = (t.name ? t.name : "series-".concat(e)) + ""; l.globals.axisCharts && d.push(i.split(r).join("") ? i.split(r).join("") : "series-".concat(e)) })), l.globals.axisCharts || (d.push(l.config.chart.toolbar.export.csv.headerValue), g.push(d.join(r))), l.globals.allSeriesHasEqualX || !l.globals.axisCharts || l.config.xaxis.categories.length || l.config.labels.length ? i.map((function (t, e) { l.globals.axisCharts ? k(t, e) : ((d = []).push(l.globals.labels[e].split(r).join("")), d.push(f[e]), g.push(d.join(r))) })) : (h = new Set, c = {}, i.forEach((function (t, e) { null == t || t.data.forEach((function (t) { var a, s; if (m.isFormatXY()) a = t.x, s = t.y; else { if (!m.isFormat2DArray()) return; a = t[0], s = t[1] } c[a] || (c[a] = Array(i.length).fill("")), c[a][e] = s, h.add(a) })) })), d.length && g.push(d.join(r)), Array.from(h).sort().forEach((function (t) { g.push([b(t) && "datetime" === l.config.xaxis.type ? l.config.chart.toolbar.export.csv.dateFormatter(t) : x.isNumber(t) ? t : t.split(r).join(""), c[t].join(r)]) }))), p += g.join(n), this.triggerDownload("data:text/csv; charset=utf-8," + encodeURIComponent("\ufeff" + p), a || l.config.chart.toolbar.export.csv.filename, ".csv") } }, { key: "triggerDownload", value: function (t, e, i) { var a = document.createElement("a"); a.href = t, a.download = (e || this.w.globals.chartID) + i, document.body.appendChild(a), a.click(), document.body.removeChild(a) } }]), t }(), V = function () { function t(e, i) { a(this, t), this.ctx = e, this.elgrid = i, this.w = e.w; var s = this.w; this.axesUtils = new C(e), this.xaxisLabels = s.globals.labels.slice(), s.globals.timescaleLabels.length > 0 && !s.globals.isBarHorizontal && (this.xaxisLabels = s.globals.timescaleLabels.slice()), s.config.xaxis.overwriteCategories && (this.xaxisLabels = s.config.xaxis.overwriteCategories), this.drawnLabels = [], this.drawnLabelsRects = [], "top" === s.config.xaxis.position ? this.offY = 0 : this.offY = s.globals.gridHeight, this.offY = this.offY + s.config.xaxis.axisBorder.offsetY, this.isCategoryBarHorizontal = "bar" === s.config.chart.type && s.config.plotOptions.bar.horizontal, this.xaxisFontSize = s.config.xaxis.labels.style.fontSize, this.xaxisFontFamily = s.config.xaxis.labels.style.fontFamily, this.xaxisForeColors = s.config.xaxis.labels.style.colors, this.xaxisBorderWidth = s.config.xaxis.axisBorder.width, this.isCategoryBarHorizontal && (this.xaxisBorderWidth = s.config.yaxis[0].axisBorder.width.toString()), this.xaxisBorderWidth.indexOf("%") > -1 ? this.xaxisBorderWidth = s.globals.gridWidth * parseInt(this.xaxisBorderWidth, 10) / 100 : this.xaxisBorderWidth = parseInt(this.xaxisBorderWidth, 10), this.xaxisBorderHeight = s.config.xaxis.axisBorder.height, this.yaxis = s.config.yaxis[0] } return r(t, [{ key: "drawXaxis", value: function () { var t = this.w, e = new m(this.ctx), i = e.group({ class: "apexcharts-xaxis", transform: "translate(".concat(t.config.xaxis.offsetX, ", ").concat(t.config.xaxis.offsetY, ")") }), a = e.group({ class: "apexcharts-xaxis-texts-g", transform: "translate(".concat(t.globals.translateXAxisX, ", ").concat(t.globals.translateXAxisY, ")") }); i.add(a); for (var s = [], r = 0; r < this.xaxisLabels.length; r++)s.push(this.xaxisLabels[r]); if (this.drawXAxisLabelAndGroup(!0, e, a, s, t.globals.isXNumeric, (function (t, e) { return e })), t.globals.hasXaxisGroups) { var o = t.globals.groups; s = []; for (var n = 0; n < o.length; n++)s.push(o[n].title); var l = {}; t.config.xaxis.group.style && (l.xaxisFontSize = t.config.xaxis.group.style.fontSize, l.xaxisFontFamily = t.config.xaxis.group.style.fontFamily, l.xaxisForeColors = t.config.xaxis.group.style.colors, l.fontWeight = t.config.xaxis.group.style.fontWeight, l.cssClass = t.config.xaxis.group.style.cssClass), this.drawXAxisLabelAndGroup(!1, e, a, s, !1, (function (t, e) { return o[t].cols * e }), l) } if (void 0 !== t.config.xaxis.title.text) { var h = e.group({ class: "apexcharts-xaxis-title" }), c = e.drawText({ x: t.globals.gridWidth / 2 + t.config.xaxis.title.offsetX, y: this.offY + parseFloat(this.xaxisFontSize) + ("bottom" === t.config.xaxis.position ? t.globals.xAxisLabelsHeight : -t.globals.xAxisLabelsHeight - 10) + t.config.xaxis.title.offsetY, text: t.config.xaxis.title.text, textAnchor: "middle", fontSize: t.config.xaxis.title.style.fontSize, fontFamily: t.config.xaxis.title.style.fontFamily, fontWeight: t.config.xaxis.title.style.fontWeight, foreColor: t.config.xaxis.title.style.color, cssClass: "apexcharts-xaxis-title-text " + t.config.xaxis.title.style.cssClass }); h.add(c), i.add(h) } if (t.config.xaxis.axisBorder.show) { var d = t.globals.barPadForNumericAxis, g = e.drawLine(t.globals.padHorizontal + t.config.xaxis.axisBorder.offsetX - d, this.offY, this.xaxisBorderWidth + d, this.offY, t.config.xaxis.axisBorder.color, 0, this.xaxisBorderHeight); this.elgrid && this.elgrid.elGridBorders && t.config.grid.show ? this.elgrid.elGridBorders.add(g) : i.add(g) } return i } }, { key: "drawXAxisLabelAndGroup", value: function (t, e, i, a, s, r) { var o, n = this, l = arguments.length > 6 && void 0 !== arguments[6] ? arguments[6] : {}, h = [], c = [], d = this.w, g = l.xaxisFontSize || this.xaxisFontSize, u = l.xaxisFontFamily || this.xaxisFontFamily, p = l.xaxisForeColors || this.xaxisForeColors, f = l.fontWeight || d.config.xaxis.labels.style.fontWeight, x = l.cssClass || d.config.xaxis.labels.style.cssClass, b = d.globals.padHorizontal, v = a.length, m = "category" === d.config.xaxis.type ? d.globals.dataPoints : v; if (0 === m && v > m && (m = v), s) { var y = m > 1 ? m - 1 : m; o = d.globals.gridWidth / Math.min(y, v - 1), b = b + r(0, o) / 2 + d.config.xaxis.labels.offsetX } else o = d.globals.gridWidth / m, b = b + r(0, o) + d.config.xaxis.labels.offsetX; for (var w = function (s) { var l = b - r(s, o) / 2 + d.config.xaxis.labels.offsetX; 0 === s && 1 === v && o / 2 === b && 1 === m && (l = d.globals.gridWidth / 2); var y = n.axesUtils.getLabel(a, d.globals.timescaleLabels, l, s, h, g, t), w = 28; d.globals.rotateXLabels && t && (w = 22), d.config.xaxis.title.text && "top" === d.config.xaxis.position && (w += parseFloat(d.config.xaxis.title.style.fontSize) + 2), t || (w = w + parseFloat(g) + (d.globals.xAxisLabelsHeight - d.globals.xAxisGroupLabelsHeight) + (d.globals.rotateXLabels ? 10 : 0)), y = void 0 !== d.config.xaxis.tickAmount && "dataPoints" !== d.config.xaxis.tickAmount && "datetime" !== d.config.xaxis.type ? n.axesUtils.checkLabelBasedOnTickamount(s, y, v) : n.axesUtils.checkForOverflowingLabels(s, y, v, h, c); if (d.config.xaxis.labels.show) { var k = e.drawText({ x: y.x, y: n.offY + d.config.xaxis.labels.offsetY + w - ("top" === d.config.xaxis.position ? d.globals.xAxisHeight + d.config.xaxis.axisTicks.height - 2 : 0), text: y.text, textAnchor: "middle", fontWeight: y.isBold ? 600 : f, fontSize: g, fontFamily: u, foreColor: Array.isArray(p) ? t && d.config.xaxis.convertedCatToNumeric ? p[d.globals.minX + s - 1] : p[s] : p, isPlainText: !1, cssClass: (t ? "apexcharts-xaxis-label " : "apexcharts-xaxis-group-label ") + x }); if (i.add(k), k.on("click", (function (t) { if ("function" == typeof d.config.chart.events.xAxisLabelClick) { var e = Object.assign({}, d, { labelIndex: s }); d.config.chart.events.xAxisLabelClick(t, n.ctx, e) } })), t) { var A = document.createElementNS(d.globals.SVGNS, "title"); A.textContent = Array.isArray(y.text) ? y.text.join(" ") : y.text, k.node.appendChild(A), "" !== y.text && (h.push(y.text), c.push(y)) } } s < v - 1 && (b += r(s + 1, o)) }, k = 0; k <= v - 1; k++)w(k) } }, { key: "drawXaxisInversed", value: function (t) { var e, i, a = this, s = this.w, r = new m(this.ctx), o = s.config.yaxis[0].opposite ? s.globals.translateYAxisX[t] : 0, n = r.group({ class: "apexcharts-yaxis apexcharts-xaxis-inversed", rel: t }), l = r.group({ class: "apexcharts-yaxis-texts-g apexcharts-xaxis-inversed-texts-g", transform: "translate(" + o + ", 0)" }); n.add(l); var h = []; if (s.config.yaxis[t].show) for (var c = 0; c < this.xaxisLabels.length; c++)h.push(this.xaxisLabels[c]); e = s.globals.gridHeight / h.length, i = -e / 2.2; var d = s.globals.yLabelFormatters[0], g = s.config.yaxis[0].labels; if (g.show) for (var u = function (o) { var n = void 0 === h[o] ? "" : h[o]; n = d(n, { seriesIndex: t, dataPointIndex: o, w: s }); var c = a.axesUtils.getYAxisForeColor(g.style.colors, t), u = 0; Array.isArray(n) && (u = n.length / 2 * parseInt(g.style.fontSize, 10)); var p = g.offsetX - 15, f = "end"; a.yaxis.opposite && (f = "start"), "left" === s.config.yaxis[0].labels.align ? (p = g.offsetX, f = "start") : "center" === s.config.yaxis[0].labels.align ? (p = g.offsetX, f = "middle") : "right" === s.config.yaxis[0].labels.align && (f = "end"); var x = r.drawText({ x: p, y: i + e + g.offsetY - u, text: n, textAnchor: f, foreColor: Array.isArray(c) ? c[o] : c, fontSize: g.style.fontSize, fontFamily: g.style.fontFamily, fontWeight: g.style.fontWeight, isPlainText: !1, cssClass: "apexcharts-yaxis-label " + g.style.cssClass, maxWidth: g.maxWidth }); l.add(x), x.on("click", (function (t) { if ("function" == typeof s.config.chart.events.xAxisLabelClick) { var e = Object.assign({}, s, { labelIndex: o }); s.config.chart.events.xAxisLabelClick(t, a.ctx, e) } })); var b = document.createElementNS(s.globals.SVGNS, "title"); if (b.textContent = Array.isArray(n) ? n.join(" ") : n, x.node.appendChild(b), 0 !== s.config.yaxis[t].labels.rotate) { var v = r.rotateAroundCenter(x.node); x.node.setAttribute("transform", "rotate(".concat(s.config.yaxis[t].labels.rotate, " 0 ").concat(v.y, ")")) } i += e }, p = 0; p <= h.length - 1; p++)u(p); if (void 0 !== s.config.yaxis[0].title.text) { var f = r.group({ class: "apexcharts-yaxis-title apexcharts-xaxis-title-inversed", transform: "translate(" + o + ", 0)" }), x = r.drawText({ x: s.config.yaxis[0].title.offsetX, y: s.globals.gridHeight / 2 + s.config.yaxis[0].title.offsetY, text: s.config.yaxis[0].title.text, textAnchor: "middle", foreColor: s.config.yaxis[0].title.style.color, fontSize: s.config.yaxis[0].title.style.fontSize, fontWeight: s.config.yaxis[0].title.style.fontWeight, fontFamily: s.config.yaxis[0].title.style.fontFamily, cssClass: "apexcharts-yaxis-title-text " + s.config.yaxis[0].title.style.cssClass }); f.add(x), n.add(f) } var b = 0; this.isCategoryBarHorizontal && s.config.yaxis[0].opposite && (b = s.globals.gridWidth); var v = s.config.xaxis.axisBorder; if (v.show) { var y = r.drawLine(s.globals.padHorizontal + v.offsetX + b, 1 + v.offsetY, s.globals.padHorizontal + v.offsetX + b, s.globals.gridHeight + v.offsetY, v.color, 0); this.elgrid && this.elgrid.elGridBorders && s.config.grid.show ? this.elgrid.elGridBorders.add(y) : n.add(y) } return s.config.yaxis[0].axisTicks.show && this.axesUtils.drawYAxisTicks(b, h.length, s.config.yaxis[0].axisBorder, s.config.yaxis[0].axisTicks, 0, e, n), n } }, { key: "drawXaxisTicks", value: function (t, e, i) { var a = this.w, s = t; if (!(t < 0 || t - 2 > a.globals.gridWidth)) { var r = this.offY + a.config.xaxis.axisTicks.offsetY; if (e = e + r + a.config.xaxis.axisTicks.height, "top" === a.config.xaxis.position && (e = r - a.config.xaxis.axisTicks.height), a.config.xaxis.axisTicks.show) { var o = new m(this.ctx).drawLine(t + a.config.xaxis.axisTicks.offsetX, r + a.config.xaxis.offsetY, s + a.config.xaxis.axisTicks.offsetX, e + a.config.xaxis.offsetY, a.config.xaxis.axisTicks.color); i.add(o), o.node.classList.add("apexcharts-xaxis-tick") } } } }, { key: "getXAxisTicksPositions", value: function () { var t = this.w, e = [], i = this.xaxisLabels.length, a = t.globals.padHorizontal; if (t.globals.timescaleLabels.length > 0) for (var s = 0; s < i; s++)a = this.xaxisLabels[s].position, e.push(a); else for (var r = i, o = 0; o < r; o++) { var n = r; t.globals.isXNumeric && "bar" !== t.config.chart.type && (n -= 1), a += t.globals.gridWidth / n, e.push(a) } return e } }, { key: "xAxisLabelCorrections", value: function () { var t = this.w, e = new m(this.ctx), i = t.globals.dom.baseEl.querySelector(".apexcharts-xaxis-texts-g"), a = t.globals.dom.baseEl.querySelectorAll(".apexcharts-xaxis-texts-g text:not(.apexcharts-xaxis-group-label)"), s = t.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis-inversed text"), r = t.globals.dom.baseEl.querySelectorAll(".apexcharts-xaxis-inversed-texts-g text tspan"); if (t.globals.rotateXLabels || t.config.xaxis.labels.rotateAlways) for (var o = 0; o < a.length; o++) { var n = e.rotateAroundCenter(a[o]); n.y = n.y - 1, n.x = n.x + 1, a[o].setAttribute("transform", "rotate(".concat(t.config.xaxis.labels.rotate, " ").concat(n.x, " ").concat(n.y, ")")), a[o].setAttribute("text-anchor", "end"); i.setAttribute("transform", "translate(0, ".concat(-10, ")")); var l = a[o].childNodes; t.config.xaxis.labels.trim && Array.prototype.forEach.call(l, (function (i) { e.placeTextWithEllipsis(i, i.textContent, t.globals.xAxisLabelsHeight - ("bottom" === t.config.legend.position ? 20 : 10)) })) } else !function () { for (var i = t.globals.gridWidth / (t.globals.labels.length + 1), s = 0; s < a.length; s++) { var r = a[s].childNodes; t.config.xaxis.labels.trim && "datetime" !== t.config.xaxis.type && Array.prototype.forEach.call(r, (function (t) { e.placeTextWithEllipsis(t, t.textContent, i) })) } }(); if (s.length > 0) { var h = s[s.length - 1].getBBox(), c = s[0].getBBox(); h.x < -20 && s[s.length - 1].parentNode.removeChild(s[s.length - 1]), c.x + c.width > t.globals.gridWidth && !t.globals.isBarHorizontal && s[0].parentNode.removeChild(s[0]); for (var d = 0; d < r.length; d++)e.placeTextWithEllipsis(r[d], r[d].textContent, t.config.yaxis[0].labels.maxWidth - (t.config.yaxis[0].title.text ? 2 * parseFloat(t.config.yaxis[0].title.style.fontSize) : 0) - 15) } } }]), t }(), j = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w; var i = this.w; this.xaxisLabels = i.globals.labels.slice(), this.axesUtils = new C(e), this.isRangeBar = i.globals.seriesRange.length && i.globals.isBarHorizontal, i.globals.timescaleLabels.length > 0 && (this.xaxisLabels = i.globals.timescaleLabels.slice()) } return r(t, [{ key: "drawGridArea", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : null, e = this.w, i = new m(this.ctx); null === t && (t = i.group({ class: "apexcharts-grid" })); var a = i.drawLine(e.globals.padHorizontal, 1, e.globals.padHorizontal, e.globals.gridHeight, "transparent"), s = i.drawLine(e.globals.padHorizontal, e.globals.gridHeight, e.globals.gridWidth, e.globals.gridHeight, "transparent"); return t.add(s), t.add(a), t } }, { key: "drawGrid", value: function () { var t = null; return this.w.globals.axisCharts && (t = this.renderGrid(), this.drawGridArea(t.el)), t } }, { key: "createGridMask", value: function () { var t = this.w, e = t.globals, i = new m(this.ctx), a = Array.isArray(t.config.stroke.width) ? 0 : t.config.stroke.width; if (Array.isArray(t.config.stroke.width)) { var s = 0; t.config.stroke.width.forEach((function (t) { s = Math.max(s, t) })), a = s } e.dom.elGridRectMask = document.createElementNS(e.SVGNS, "clipPath"), e.dom.elGridRectMask.setAttribute("id", "gridRectMask".concat(e.cuid)), e.dom.elGridRectMarkerMask = document.createElementNS(e.SVGNS, "clipPath"), e.dom.elGridRectMarkerMask.setAttribute("id", "gridRectMarkerMask".concat(e.cuid)), e.dom.elForecastMask = document.createElementNS(e.SVGNS, "clipPath"), e.dom.elForecastMask.setAttribute("id", "forecastMask".concat(e.cuid)), e.dom.elNonForecastMask = document.createElementNS(e.SVGNS, "clipPath"), e.dom.elNonForecastMask.setAttribute("id", "nonForecastMask".concat(e.cuid)); var r = t.config.chart.type, o = 0, n = 0; ("bar" === r || "rangeBar" === r || "candlestick" === r || "boxPlot" === r || t.globals.comboBarCount > 0) && t.globals.isXNumeric && !t.globals.isBarHorizontal && (o = t.config.grid.padding.left, n = t.config.grid.padding.right, e.barPadForNumericAxis > o && (o = e.barPadForNumericAxis, n = e.barPadForNumericAxis)), e.dom.elGridRect = i.drawRect(-a / 2 - o - 2, -a / 2 - 2, e.gridWidth + a + n + o + 4, e.gridHeight + a + 4, 0, "#fff"); var l = t.globals.markers.largestSize + 1; e.dom.elGridRectMarker = i.drawRect(2 * -l, 2 * -l, e.gridWidth + 4 * l, e.gridHeight + 4 * l, 0, "#fff"), e.dom.elGridRectMask.appendChild(e.dom.elGridRect.node), e.dom.elGridRectMarkerMask.appendChild(e.dom.elGridRectMarker.node); var h = e.dom.baseEl.querySelector("defs"); h.appendChild(e.dom.elGridRectMask), h.appendChild(e.dom.elForecastMask), h.appendChild(e.dom.elNonForecastMask), h.appendChild(e.dom.elGridRectMarkerMask) } }, { key: "_drawGridLines", value: function (t) { var e = t.i, i = t.x1, a = t.y1, s = t.x2, r = t.y2, o = t.xCount, n = t.parent, l = this.w; if (!(0 === e && l.globals.skipFirstTimelinelabel || e === o - 1 && l.globals.skipLastTimelinelabel && !l.config.xaxis.labels.formatter || "radar" === l.config.chart.type)) { l.config.grid.xaxis.lines.show && this._drawGridLine({ i: e, x1: i, y1: a, x2: s, y2: r, xCount: o, parent: n }); var h = 0; if (l.globals.hasXaxisGroups && "between" === l.config.xaxis.tickPlacement) { var c = l.globals.groups; if (c) { for (var d = 0, g = 0; d < e && g < c.length; g++)d += c[g].cols; d === e && (h = .6 * l.globals.xAxisLabelsHeight) } } new V(this.ctx).drawXaxisTicks(i, h, l.globals.dom.elGraphical) } } }, { key: "_drawGridLine", value: function (t) { var e = t.i, i = t.x1, a = t.y1, s = t.x2, r = t.y2, o = t.xCount, n = t.parent, l = this.w, h = !1, c = n.node.classList.contains("apexcharts-gridlines-horizontal"), d = l.config.grid.strokeDashArray, g = l.globals.barPadForNumericAxis; (0 === a && 0 === r || 0 === i && 0 === s) && (h = !0), a === l.globals.gridHeight && r === l.globals.gridHeight && (h = !0), !l.globals.isBarHorizontal || 0 !== e && e !== o - 1 || (h = !0); var u = new m(this).drawLine(i - (c ? g : 0), a, s + (c ? g : 0), r, l.config.grid.borderColor, d); u.node.classList.add("apexcharts-gridline"), h && l.config.grid.show ? this.elGridBorders.add(u) : n.add(u) } }, { key: "_drawGridBandRect", value: function (t) { var e = t.c, i = t.x1, a = t.y1, s = t.x2, r = t.y2, o = t.type, n = this.w, l = new m(this.ctx), h = n.globals.barPadForNumericAxis; if ("column" !== o || "datetime" !== n.config.xaxis.type) { var c = n.config.grid[o].colors[e], d = l.drawRect(i - ("row" === o ? h : 0), a, s + ("row" === o ? 2 * h : 0), r, 0, c, n.config.grid[o].opacity); this.elg.add(d), d.attr("clip-path", "url(#gridRectMask".concat(n.globals.cuid, ")")), d.node.classList.add("apexcharts-grid-".concat(o)) } } }, { key: "_drawXYLines", value: function (t) { var e = this, i = t.xCount, a = t.tickAmount, s = this.w; if (s.config.grid.xaxis.lines.show || s.config.xaxis.axisTicks.show) { var r, o = s.globals.padHorizontal, n = s.globals.gridHeight; s.globals.timescaleLabels.length ? function (t) { for (var a = t.xC, s = t.x1, r = t.y1, o = t.x2, n = t.y2, l = 0; l < a; l++)s = e.xaxisLabels[l].position, o = e.xaxisLabels[l].position, e._drawGridLines({ i: l, x1: s, y1: r, x2: o, y2: n, xCount: i, parent: e.elgridLinesV }) }({ xC: i, x1: o, y1: 0, x2: r, y2: n }) : (s.globals.isXNumeric && (i = s.globals.xAxisScale.result.length), function (t) { for (var a = t.xC, r = t.x1, o = t.y1, n = t.x2, l = t.y2, h = 0; h < a + (s.globals.isXNumeric ? 0 : 1); h++)0 === h && 1 === a && 1 === s.globals.dataPoints && (n = r = s.globals.gridWidth / 2), e._drawGridLines({ i: h, x1: r, y1: o, x2: n, y2: l, xCount: i, parent: e.elgridLinesV }), n = r += s.globals.gridWidth / (s.globals.isXNumeric ? a - 1 : a) }({ xC: i, x1: o, y1: 0, x2: r, y2: n })) } if (s.config.grid.yaxis.lines.show) { var l = 0, h = 0, c = s.globals.gridWidth, d = a + 1; this.isRangeBar && (d = s.globals.labels.length); for (var g = 0; g < d + (this.isRangeBar ? 1 : 0); g++)this._drawGridLine({ i: g, xCount: d + (this.isRangeBar ? 1 : 0), x1: 0, y1: l, x2: c, y2: h, parent: this.elgridLinesH }), h = l += s.globals.gridHeight / (this.isRangeBar ? d : a) } } }, { key: "_drawInvertedXYLines", value: function (t) { var e = t.xCount, i = this.w; if (i.config.grid.xaxis.lines.show || i.config.xaxis.axisTicks.show) for (var a, s = i.globals.padHorizontal, r = i.globals.gridHeight, o = 0; o < e + 1; o++) { i.config.grid.xaxis.lines.show && this._drawGridLine({ i: o, xCount: e + 1, x1: s, y1: 0, x2: a, y2: r, parent: this.elgridLinesV }), new V(this.ctx).drawXaxisTicks(s, 0, i.globals.dom.elGraphical), a = s += i.globals.gridWidth / e } if (i.config.grid.yaxis.lines.show) for (var n = 0, l = 0, h = i.globals.gridWidth, c = 0; c < i.globals.dataPoints + 1; c++)this._drawGridLine({ i: c, xCount: i.globals.dataPoints + 1, x1: 0, y1: n, x2: h, y2: l, parent: this.elgridLinesH }), l = n += i.globals.gridHeight / i.globals.dataPoints } }, { key: "renderGrid", value: function () { var t = this.w, e = t.globals, i = new m(this.ctx); this.elg = i.group({ class: "apexcharts-grid" }), this.elgridLinesH = i.group({ class: "apexcharts-gridlines-horizontal" }), this.elgridLinesV = i.group({ class: "apexcharts-gridlines-vertical" }), this.elGridBorders = i.group({ class: "apexcharts-grid-borders" }), this.elg.add(this.elgridLinesH), this.elg.add(this.elgridLinesV), t.config.grid.show || (this.elgridLinesV.hide(), this.elgridLinesH.hide(), this.elGridBorders.hide()); for (var a = 0; a < e.seriesYAxisMap.length && -1 !== e.ignoreYAxisIndexes.indexOf(a);)a++; a === e.seriesYAxisMap.length && (a = 0); var s, r = e.yAxisScale[a].result.length - 1; if (!e.isBarHorizontal || this.isRangeBar) { var o, n, l; if (s = this.xaxisLabels.length, this.isRangeBar) r = e.labels.length, t.config.xaxis.tickAmount && t.config.xaxis.labels.formatter && (s = t.config.xaxis.tickAmount), (null === (o = e.yAxisScale) || void 0 === o || null === (n = o[a]) || void 0 === n || null === (l = n.result) || void 0 === l ? void 0 : l.length) > 0 && "datetime" !== t.config.xaxis.type && (s = e.yAxisScale[a].result.length - 1); this._drawXYLines({ xCount: s, tickAmount: r }) } else s = r, r = e.xTickAmount, this._drawInvertedXYLines({ xCount: s, tickAmount: r }); return this.drawGridBands(s, r), { el: this.elg, elGridBorders: this.elGridBorders, xAxisTickWidth: e.gridWidth / s } } }, { key: "drawGridBands", value: function (t, e) { var i = this.w; if (void 0 !== i.config.grid.row.colors && i.config.grid.row.colors.length > 0) for (var a = 0, s = i.globals.gridHeight / e, r = i.globals.gridWidth, o = 0, n = 0; o < e; o++, n++)n >= i.config.grid.row.colors.length && (n = 0), this._drawGridBandRect({ c: n, x1: 0, y1: a, x2: r, y2: s, type: "row" }), a += i.globals.gridHeight / e; if (void 0 !== i.config.grid.column.colors && i.config.grid.column.colors.length > 0) for (var l = i.globals.isBarHorizontal || "on" !== i.config.xaxis.tickPlacement || "category" !== i.config.xaxis.type && !i.config.xaxis.convertedCatToNumeric ? t : t - 1, h = i.globals.padHorizontal, c = i.globals.padHorizontal + i.globals.gridWidth / l, d = i.globals.gridHeight, g = 0, u = 0; g < t; g++, u++)u >= i.config.grid.column.colors.length && (u = 0), this._drawGridBandRect({ c: u, x1: h, y1: 0, x2: c, y2: d, type: "column" }), h += i.globals.gridWidth / l } }]), t }(), _ = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "niceScale", value: function (t, e) { var i, a, s, r, o = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 0, n = 1e-11, l = this.w, h = l.globals; h.isBarHorizontal ? (i = l.config.xaxis, a = Math.max((h.svgWidth - 100) / 25, 2)) : (i = l.config.yaxis[o], a = Math.max((h.svgHeight - 100) / 15, 2)), s = void 0 !== i.min && null !== i.min, r = void 0 !== i.max && null !== i.min; var c = void 0 !== i.stepSize && null !== i.stepSize, d = void 0 !== i.tickAmount && null !== i.tickAmount, g = d ? i.tickAmount : i.forceNiceScale ? h.niceScaleDefaultTicks[Math.min(Math.round(a / 2), h.niceScaleDefaultTicks.length - 1)] : 10; if (h.isMultipleYAxis && !d && h.multiAxisTickAmount > 0 && (g = h.multiAxisTickAmount, d = !0), g = "dataPoints" === g ? h.dataPoints - 1 : Math.abs(Math.round(g)), (t === Number.MIN_VALUE && 0 === e || !x.isNumber(t) && !x.isNumber(e) || t === Number.MIN_VALUE && e === -Number.MAX_VALUE) && (t = x.isNumber(i.min) ? i.min : 0, e = x.isNumber(i.max) ? i.max : t + g, h.allSeriesCollapsed = !1), t > e) { console.warn("axis.min cannot be greater than axis.max: swapping min and max"); var u = e; e = t, t = u } else t === e && (t = 0 === t ? 0 : t - 1, e = 0 === e ? 2 : e + 1); var p = []; g < 1 && (g = 1); var f = g, b = Math.abs(e - t); if (i.forceNiceScale) { !s && t > 0 && t / b < .15 && (t = 0, s = !0), !r && e < 0 && -e / b < .15 && (e = 0, r = !0), b = Math.abs(e - t) } var v = b / f, m = v, y = Math.floor(Math.log10(m)), w = Math.pow(10, y), k = Math.ceil(m / w); if (v = m = (k = h.niceScaleAllowedMagMsd[0 === h.yValueDecimal ? 0 : 1][k]) * w, h.isBarHorizontal && i.stepSize && "datetime" !== i.type ? (v = i.stepSize, c = !0) : c && (v = i.stepSize), c && i.forceNiceScale) { var A = Math.floor(Math.log10(v)); v *= Math.pow(10, y - A) } if (s && r) { var S = b / f; if (d) if (c) if (0 != x.mod(b, v)) { var C = x.getGCD(v, S); v = S / C < 10 ? C : S } else 0 == x.mod(v, S) ? v = S : (S = v, d = !1); else v = S; else if (c) 0 == x.mod(b, v) ? S = v : v = S; else if (0 == x.mod(b, v)) S = v; else { S = b / (f = Math.ceil(b / v)); var L = x.getGCD(b, v); b / L < a && (S = L), v = S } f = Math.round(b / v) } else { if (s || r) { if (r) if (d) t = e - v * f; else { var P = t; t = v * Math.floor(t / v), Math.abs(e - t) / x.getGCD(b, v) > a && (t = e - v * g, t += v * Math.floor((P - t) / v)) } else if (s) if (d) e = t + v * f; else { var M = e; e = v * Math.ceil(e / v), Math.abs(e - t) / x.getGCD(b, v) > a && (e = t + v * g, e += v * Math.ceil((M - e) / v)) } } else if (d) { var I = v / (e - t > e ? 1 : 2), T = I * Math.floor(t / I); Math.abs(T - t) <= I / 2 ? e = (t = T) + v * f : t = (e = I * Math.ceil(e / I)) - v * f } else t = v * Math.floor(t / v), e = v * Math.ceil(e / v); b = Math.abs(e - t), v = x.getGCD(b, v), f = Math.round(b / v) } if (d || s || r || (f = Math.ceil((b - n) / (v + n))) > 16 && x.getPrimeFactors(f).length < 2 && f++, !d && i.forceNiceScale && 0 === h.yValueDecimal && f > b && (f = b, v = Math.round(b / f)), f > a && (!d && !c || i.forceNiceScale)) { var z = x.getPrimeFactors(f), X = z.length - 1, E = f; t: for (var Y = 0; Y < X; Y++)for (var F = 0; F <= X - Y; F++) { for (var R = Math.min(F + Y, X), H = E, D = 1, O = F; O <= R; O++)D *= z[O]; if ((H /= D) < a) { E = H; break t } } v = E === f ? b : b / E, f = Math.round(b / v) } h.isMultipleYAxis && 0 == h.multiAxisTickAmount && h.ignoreYAxisIndexes.indexOf(o) < 0 && (h.multiAxisTickAmount = f); var N = t - v, W = v * n; do { N += v, p.push(x.stripNumber(N, 7)) } while (e - N > W); return { result: p, niceMin: p[0], niceMax: p[p.length - 1] } } }, { key: "linearScale", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 10, a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : 0, s = arguments.length > 4 && void 0 !== arguments[4] ? arguments[4] : void 0, r = Math.abs(e - t); "dataPoints" === (i = this._adjustTicksForSmallRange(i, a, r)) && (i = this.w.globals.dataPoints - 1), s || (s = r / i), i === Number.MAX_VALUE && (i = 5, s = 1); for (var o = [], n = t; i >= 0;)o.push(n), n += s, i -= 1; return { result: o, niceMin: o[0], niceMax: o[o.length - 1] } } }, { key: "logarithmicScaleNice", value: function (t, e, i) { e <= 0 && (e = Math.max(t, i)), t <= 0 && (t = Math.min(e, i)); for (var a = [], s = Math.ceil(Math.log(e) / Math.log(i) + 1), r = Math.floor(Math.log(t) / Math.log(i)); r < s; r++)a.push(Math.pow(i, r)); return { result: a, niceMin: a[0], niceMax: a[a.length - 1] } } }, { key: "logarithmicScale", value: function (t, e, i) { e <= 0 && (e = Math.max(t, i)), t <= 0 && (t = Math.min(e, i)); for (var a = [], s = Math.log(e) / Math.log(i), r = Math.log(t) / Math.log(i), o = s - r, n = Math.round(o), l = o / n, h = 0, c = r; h < n; h++, c += l)a.push(Math.pow(i, c)); return a.push(Math.pow(i, s)), { result: a, niceMin: t, niceMax: e } } }, { key: "_adjustTicksForSmallRange", value: function (t, e, i) { var a = t; if (void 0 !== e && this.w.config.yaxis[e].labels.formatter && void 0 === this.w.config.yaxis[e].tickAmount) { var s = Number(this.w.config.yaxis[e].labels.formatter(1)); x.isNumber(s) && 0 === this.w.globals.yValueDecimal && (a = Math.ceil(i)) } return a < t ? a : t } }, { key: "setYScaleForIndex", value: function (t, e, i) { var a = this.w.globals, s = this.w.config, r = a.isBarHorizontal ? s.xaxis : s.yaxis[t]; void 0 === a.yAxisScale[t] && (a.yAxisScale[t] = []); var o = Math.abs(i - e); r.logarithmic && o <= 5 && (a.invalidLogScale = !0), r.logarithmic && o > 5 ? (a.allSeriesCollapsed = !1, a.yAxisScale[t] = r.forceNiceScale ? this.logarithmicScaleNice(e, i, r.logBase) : this.logarithmicScale(e, i, r.logBase)) : i !== -Number.MAX_VALUE && x.isNumber(i) && e !== Number.MAX_VALUE && x.isNumber(e) ? (a.allSeriesCollapsed = !1, a.yAxisScale[t] = this.niceScale(e, i, t)) : a.yAxisScale[t] = this.niceScale(Number.MIN_VALUE, 0, t) } }, { key: "setXScale", value: function (t, e) { var i = this.w, a = i.globals, s = Math.abs(e - t); return e !== -Number.MAX_VALUE && x.isNumber(e) ? a.xAxisScale = this.linearScale(t, e, i.config.xaxis.tickAmount ? i.config.xaxis.tickAmount : s < 10 && s > 1 ? s + 1 : 10, 0, i.config.xaxis.stepSize) : a.xAxisScale = this.linearScale(0, 10, 10), a.xAxisScale } }, { key: "setSeriesYAxisMappings", value: function () { var t = this.w.globals, e = this.w.config; t.minYArr, t.maxYArr; var i = [], a = [], s = [], r = t.series.length > e.yaxis.length || e.yaxis.some((function (t) { return Array.isArray(t.seriesName) })); e.series.forEach((function (t, e) { s.push(e), a.push(null) })), e.yaxis.forEach((function (t, e) { i[e] = [] })); var o = []; e.yaxis.forEach((function (t, a) { var n = !1; if (t.seriesName) { var l = []; Array.isArray(t.seriesName) ? l = t.seriesName : l.push(t.seriesName), l.forEach((function (t) { e.series.forEach((function (e, o) { if (e.name === t) { var l = o; a === o || r ? !r || s.indexOf(o) > -1 ? i[a].push([a, o]) : console.warn("Series '" + e.name + "' referenced more than once in what looks like the new style. That is, when using either seriesName: [], or when there are more series than yaxes.") : (i[o].push([o, a]), l = a), n = !0, -1 !== (l = s.indexOf(l)) && s.splice(l, 1) } })) })) } n || o.push(a) })), i = i.map((function (t, e) { var i = []; return t.forEach((function (t) { a[t[1]] = t[0], i.push(t[1]) })), i })); for (var n = e.yaxis.length - 1, l = 0; l < o.length && (n = o[l], i[n] = [], s); l++) { var h = s[0]; s.shift(), i[n].push(h), a[h] = n } s.forEach((function (t) { i[n].push(t), a[t] = n })), t.seriesYAxisMap = i.map((function (t) { return t })), t.seriesYAxisReverseMap = a.map((function (t) { return t })) } }, { key: "scaleMultipleYAxes", value: function () { var t = this, e = this.w.config, i = this.w.globals; this.setSeriesYAxisMappings(); var a = i.seriesYAxisMap, s = i.minYArr, r = i.maxYArr; i.allSeriesCollapsed = !0, i.barGroups = [], a.forEach((function (a, o) { var n = []; a.forEach((function (t) { var i = e.series[t].group; n.indexOf(i) < 0 && n.push(i) })), a.length > 0 ? function () { var l, h, c = Number.MAX_VALUE, d = -Number.MAX_VALUE, g = c, u = d; if (e.chart.stacked) !function () { var t = i.seriesX[a[0]], s = [], r = [], p = []; n.forEach((function () { s.push(t.map((function () { return Number.MIN_VALUE }))), r.push(t.map((function () { return Number.MIN_VALUE }))), p.push(t.map((function () { return Number.MIN_VALUE }))) })); for (var f = function (t) { !l && e.series[a[t]].type && (l = e.series[a[t]].type); var c = a[t]; h = e.series[c].group ? e.series[c].group : "axis-".concat(o), !(i.collapsedSeriesIndices.indexOf(c) < 0 && i.ancillaryCollapsedSeriesIndices.indexOf(c) < 0) || (i.allSeriesCollapsed = !1, n.forEach((function (t, a) { if (e.series[c].group === t) for (var o = 0; o < i.series[c].length; o++) { var n = i.series[c][o]; n >= 0 ? r[a][o] += n : p[a][o] += n, s[a][o] += n, g = Math.min(g, n), u = Math.max(u, n) } }))), "bar" !== l && "column" !== l || i.barGroups.push(h) }, x = 0; x < a.length; x++)f(x); l || (l = e.chart.type), "bar" === l || "column" === l ? n.forEach((function (t, e) { c = Math.min(c, Math.min.apply(null, p[e])), d = Math.max(d, Math.max.apply(null, r[e])) })) : (n.forEach((function (t, e) { g = Math.min(g, Math.min.apply(null, s[e])), u = Math.max(u, Math.max.apply(null, s[e])) })), c = g, d = u), c === Number.MIN_VALUE && d === Number.MIN_VALUE && (d = -Number.MAX_VALUE) }(); else for (var p = 0; p < a.length; p++) { var f = a[p]; c = Math.min(c, s[f]), d = Math.max(d, r[f]), !(i.collapsedSeriesIndices.indexOf(f) < 0 && i.ancillaryCollapsedSeriesIndices.indexOf(f) < 0) || (i.allSeriesCollapsed = !1) } void 0 !== e.yaxis[o].min && (c = "function" == typeof e.yaxis[o].min ? e.yaxis[o].min(c) : e.yaxis[o].min), void 0 !== e.yaxis[o].max && (d = "function" == typeof e.yaxis[o].max ? e.yaxis[o].max(d) : e.yaxis[o].max), i.barGroups = i.barGroups.filter((function (t, e, i) { return i.indexOf(t) === e })), t.setYScaleForIndex(o, c, d), a.forEach((function (t) { s[t] = i.yAxisScale[o].niceMin, r[t] = i.yAxisScale[o].niceMax })) }() : t.setYScaleForIndex(o, 0, -Number.MAX_VALUE) })) } }]), t }(), U = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.scales = new _(e) } return r(t, [{ key: "init", value: function () { this.setYRange(), this.setXRange(), this.setZRange() } }, { key: "getMinYMaxY", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : Number.MAX_VALUE, i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : -Number.MAX_VALUE, a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : null, s = this.w.config, r = this.w.globals, o = -Number.MAX_VALUE, n = Number.MIN_VALUE; null === a && (a = t + 1); var l = 0, h = 0, c = void 0; if (r.seriesX.length >= a) { var d, g; l = 0, h = (c = u(new Set((d = []).concat.apply(d, u(r.seriesX.slice(t, a)))))).length - 1; var p = null === (g = r.brushSource) || void 0 === g ? void 0 : g.w.config.chart.brush; if (s.chart.zoom.enabled && s.chart.zoom.autoScaleYaxis || null != p && p.enabled && null != p && p.autoScaleYaxis) { if (s.xaxis.min) for (l = 0; l < h && c[l] < s.xaxis.min; l++); if (s.xaxis.max) for (; h > l && c[h] > s.xaxis.max; h--); } } var f = r.series, b = f, v = f; "candlestick" === s.chart.type ? (b = r.seriesCandleL, v = r.seriesCandleH) : "boxPlot" === s.chart.type ? (b = r.seriesCandleO, v = r.seriesCandleC) : r.isRangeData && (b = r.seriesRangeStart, v = r.seriesRangeEnd); for (var m = t; m < a; m++) { r.dataPoints = Math.max(r.dataPoints, f[m].length); var y = s.series[m].type; r.categoryLabels.length && (r.dataPoints = r.categoryLabels.filter((function (t) { return void 0 !== t })).length), r.labels.length && "datetime" !== s.xaxis.type && 0 !== r.series.reduce((function (t, e) { return t + e.length }), 0) && (r.dataPoints = Math.max(r.dataPoints, r.labels.length)), c || (l = 0, h = r.series[m].length); for (var w = l; w <= h && w < r.series[m].length; w++) { var k = f[m][w]; if (null !== k && x.isNumber(k)) { switch (void 0 !== v[m][w] && (o = Math.max(o, v[m][w]), e = Math.min(e, v[m][w])), void 0 !== b[m][w] && (e = Math.min(e, b[m][w]), i = Math.max(i, b[m][w])), y) { case "candlestick": void 0 !== r.seriesCandleC[m][w] && (o = Math.max(o, r.seriesCandleH[m][w]), e = Math.min(e, r.seriesCandleL[m][w])); break; case "boxPlot": void 0 !== r.seriesCandleC[m][w] && (o = Math.max(o, r.seriesCandleC[m][w]), e = Math.min(e, r.seriesCandleO[m][w])) }y && "candlestick" !== y && "boxPlot" !== y && "rangeArea" !== y && "rangeBar" !== y && (o = Math.max(o, r.series[m][w]), e = Math.min(e, r.series[m][w])), i = o, r.seriesGoals[m] && r.seriesGoals[m][w] && Array.isArray(r.seriesGoals[m][w]) && r.seriesGoals[m][w].forEach((function (t) { n !== Number.MIN_VALUE && (n = Math.min(n, t.value), e = n), o = Math.max(o, t.value), i = o })), x.isFloat(k) && (k = x.noExponents(k), r.yValueDecimal = Math.max(r.yValueDecimal, k.toString().split(".")[1].length)), n > b[m][w] && b[m][w] < 0 && (n = b[m][w]) } else r.hasNullValues = !0 } "bar" !== y && "column" !== y || (n < 0 && o < 0 && (o = 0, i = Math.max(i, 0)), n === Number.MIN_VALUE && (n = 0, e = Math.min(e, 0))) } return "rangeBar" === s.chart.type && r.seriesRangeStart.length && r.isBarHorizontal && (n = e), "bar" === s.chart.type && (n < 0 && o < 0 && (o = 0), n === Number.MIN_VALUE && (n = 0)), { minY: n, maxY: o, lowestY: e, highestY: i } } }, { key: "setYRange", value: function () { var t = this.w.globals, e = this.w.config; t.maxY = -Number.MAX_VALUE, t.minY = Number.MIN_VALUE; var i, a = Number.MAX_VALUE; if (t.isMultipleYAxis) { a = Number.MAX_VALUE; for (var s = 0; s < t.series.length; s++)i = this.getMinYMaxY(s), t.minYArr[s] = i.lowestY, t.maxYArr[s] = i.highestY, a = Math.min(a, i.lowestY) } if (i = this.getMinYMaxY(0, a, null, t.series.length), "bar" === e.chart.type ? (t.minY = i.minY, t.maxY = i.maxY) : (t.minY = i.lowestY, t.maxY = i.highestY), a = i.lowestY, e.chart.stacked && this._setStackedMinMax(), "line" === e.chart.type || "area" === e.chart.type || "scatter" === e.chart.type || "candlestick" === e.chart.type || "boxPlot" === e.chart.type || "rangeBar" === e.chart.type && !t.isBarHorizontal ? t.minY === Number.MIN_VALUE && a !== -Number.MAX_VALUE && a !== t.maxY && (t.minY = a) : t.minY = i.minY, e.yaxis.forEach((function (e, i) { void 0 !== e.max && ("number" == typeof e.max ? t.maxYArr[i] = e.max : "function" == typeof e.max && (t.maxYArr[i] = e.max(t.isMultipleYAxis ? t.maxYArr[i] : t.maxY)), t.maxY = t.maxYArr[i]), void 0 !== e.min && ("number" == typeof e.min ? t.minYArr[i] = e.min : "function" == typeof e.min && (t.minYArr[i] = e.min(t.isMultipleYAxis ? t.minYArr[i] === Number.MIN_VALUE ? 0 : t.minYArr[i] : t.minY)), t.minY = t.minYArr[i]) })), t.isBarHorizontal) { ["min", "max"].forEach((function (i) { void 0 !== e.xaxis[i] && "number" == typeof e.xaxis[i] && ("min" === i ? t.minY = e.xaxis[i] : t.maxY = e.xaxis[i]) })) } return t.isMultipleYAxis ? (this.scales.scaleMultipleYAxes(), t.minY = a) : (this.scales.setYScaleForIndex(0, t.minY, t.maxY), t.minY = t.yAxisScale[0].niceMin, t.maxY = t.yAxisScale[0].niceMax, t.minYArr[0] = t.minY, t.maxYArr[0] = t.maxY), t.barGroups = [], t.lineGroups = [], t.areaGroups = [], e.series.forEach((function (i) { switch (i.type || e.chart.type) { case "bar": case "column": t.barGroups.push(i.group); break; case "line": t.lineGroups.push(i.group); break; case "area": t.areaGroups.push(i.group) } })), t.barGroups = t.barGroups.filter((function (t, e, i) { return i.indexOf(t) === e })), t.lineGroups = t.lineGroups.filter((function (t, e, i) { return i.indexOf(t) === e })), t.areaGroups = t.areaGroups.filter((function (t, e, i) { return i.indexOf(t) === e })), { minY: t.minY, maxY: t.maxY, minYArr: t.minYArr, maxYArr: t.maxYArr, yAxisScale: t.yAxisScale } } }, { key: "setXRange", value: function () { var t = this.w.globals, e = this.w.config, i = "numeric" === e.xaxis.type || "datetime" === e.xaxis.type || "category" === e.xaxis.type && !t.noLabelsProvided || t.noLabelsProvided || t.isXNumeric; if (t.isXNumeric && function () { for (var e = 0; e < t.series.length; e++)if (t.labels[e]) for (var i = 0; i < t.labels[e].length; i++)null !== t.labels[e][i] && x.isNumber(t.labels[e][i]) && (t.maxX = Math.max(t.maxX, t.labels[e][i]), t.initialMaxX = Math.max(t.maxX, t.labels[e][i]), t.minX = Math.min(t.minX, t.labels[e][i]), t.initialMinX = Math.min(t.minX, t.labels[e][i])) }(), t.noLabelsProvided && 0 === e.xaxis.categories.length && (t.maxX = t.labels[t.labels.length - 1], t.initialMaxX = t.labels[t.labels.length - 1], t.minX = 1, t.initialMinX = 1), t.isXNumeric || t.noLabelsProvided || t.dataFormatXNumeric) { var a; if (void 0 === e.xaxis.tickAmount ? (a = Math.round(t.svgWidth / 150), "numeric" === e.xaxis.type && t.dataPoints < 30 && (a = t.dataPoints - 1), a > t.dataPoints && 0 !== t.dataPoints && (a = t.dataPoints - 1)) : "dataPoints" === e.xaxis.tickAmount ? (t.series.length > 1 && (a = t.series[t.maxValsInArrayIndex].length - 1), t.isXNumeric && (a = t.maxX - t.minX - 1)) : a = e.xaxis.tickAmount, t.xTickAmount = a, void 0 !== e.xaxis.max && "number" == typeof e.xaxis.max && (t.maxX = e.xaxis.max), void 0 !== e.xaxis.min && "number" == typeof e.xaxis.min && (t.minX = e.xaxis.min), void 0 !== e.xaxis.range && (t.minX = t.maxX - e.xaxis.range), t.minX !== Number.MAX_VALUE && t.maxX !== -Number.MAX_VALUE) if (e.xaxis.convertedCatToNumeric && !t.dataFormatXNumeric) { for (var s = [], r = t.minX - 1; r < t.maxX; r++)s.push(r + 1); t.xAxisScale = { result: s, niceMin: s[0], niceMax: s[s.length - 1] } } else t.xAxisScale = this.scales.setXScale(t.minX, t.maxX); else t.xAxisScale = this.scales.linearScale(0, a, a, 0, e.xaxis.stepSize), t.noLabelsProvided && t.labels.length > 0 && (t.xAxisScale = this.scales.linearScale(1, t.labels.length, a - 1, 0, e.xaxis.stepSize), t.seriesX = t.labels.slice()); i && (t.labels = t.xAxisScale.result.slice()) } return t.isBarHorizontal && t.labels.length && (t.xTickAmount = t.labels.length), this._handleSingleDataPoint(), this._getMinXDiff(), { minX: t.minX, maxX: t.maxX } } }, { key: "setZRange", value: function () { var t = this.w.globals; if (t.isDataXYZ) for (var e = 0; e < t.series.length; e++)if (void 0 !== t.seriesZ[e]) for (var i = 0; i < t.seriesZ[e].length; i++)null !== t.seriesZ[e][i] && x.isNumber(t.seriesZ[e][i]) && (t.maxZ = Math.max(t.maxZ, t.seriesZ[e][i]), t.minZ = Math.min(t.minZ, t.seriesZ[e][i])) } }, { key: "_handleSingleDataPoint", value: function () { var t = this.w.globals, e = this.w.config; if (t.minX === t.maxX) { var i = new A(this.ctx); if ("datetime" === e.xaxis.type) { var a = i.getDate(t.minX); e.xaxis.labels.datetimeUTC ? a.setUTCDate(a.getUTCDate() - 2) : a.setDate(a.getDate() - 2), t.minX = new Date(a).getTime(); var s = i.getDate(t.maxX); e.xaxis.labels.datetimeUTC ? s.setUTCDate(s.getUTCDate() + 2) : s.setDate(s.getDate() + 2), t.maxX = new Date(s).getTime() } else ("numeric" === e.xaxis.type || "category" === e.xaxis.type && !t.noLabelsProvided) && (t.minX = t.minX - 2, t.initialMinX = t.minX, t.maxX = t.maxX + 2, t.initialMaxX = t.maxX) } } }, { key: "_getMinXDiff", value: function () { var t = this.w.globals; t.isXNumeric && t.seriesX.forEach((function (e, i) { 1 === e.length && e.push(t.seriesX[t.maxValsInArrayIndex][t.seriesX[t.maxValsInArrayIndex].length - 1]); var a = e.slice(); a.sort((function (t, e) { return t - e })), a.forEach((function (e, i) { if (i > 0) { var s = e - a[i - 1]; s > 0 && (t.minXDiff = Math.min(s, t.minXDiff)) } })), 1 !== t.dataPoints && t.minXDiff !== Number.MAX_VALUE || (t.minXDiff = .5) })) } }, { key: "_setStackedMinMax", value: function () { var t = this, e = this.w.globals; if (e.series.length) { var i = e.seriesGroups; i.length || (i = [this.w.globals.seriesNames.map((function (t) { return t }))]); var a = {}, s = {}; i.forEach((function (i) { a[i] = [], s[i] = [], t.w.config.series.map((function (t, a) { return i.indexOf(e.seriesNames[a]) > -1 ? a : null })).filter((function (t) { return null !== t })).forEach((function (r) { for (var o = 0; o < e.series[e.maxValsInArrayIndex].length; o++) { var n, l, h, c; void 0 === a[i][o] && (a[i][o] = 0, s[i][o] = 0), (t.w.config.chart.stacked && !e.comboCharts || t.w.config.chart.stacked && e.comboCharts && (!t.w.config.chart.stackOnlyBar || "bar" === (null === (n = t.w.config.series) || void 0 === n || null === (l = n[r]) || void 0 === l ? void 0 : l.type) || "column" === (null === (h = t.w.config.series) || void 0 === h || null === (c = h[r]) || void 0 === c ? void 0 : c.type))) && null !== e.series[r][o] && x.isNumber(e.series[r][o]) && (e.series[r][o] > 0 ? a[i][o] += parseFloat(e.series[r][o]) + 1e-4 : s[i][o] += parseFloat(e.series[r][o])) } })) })), Object.entries(a).forEach((function (t) { var i = g(t, 1)[0]; a[i].forEach((function (t, r) { e.maxY = Math.max(e.maxY, a[i][r]), e.minY = Math.min(e.minY, s[i][r]) })) })) } } }]), t }(), q = function () { function t(e, i) { a(this, t), this.ctx = e, this.elgrid = i, this.w = e.w; var s = this.w; this.xaxisFontSize = s.config.xaxis.labels.style.fontSize, this.axisFontFamily = s.config.xaxis.labels.style.fontFamily, this.xaxisForeColors = s.config.xaxis.labels.style.colors, this.isCategoryBarHorizontal = "bar" === s.config.chart.type && s.config.plotOptions.bar.horizontal, this.xAxisoffX = 0, "bottom" === s.config.xaxis.position && (this.xAxisoffX = s.globals.gridHeight), this.drawnLabels = [], this.axesUtils = new C(e) } return r(t, [{ key: "drawYaxis", value: function (t) { var e = this, i = this.w, a = new m(this.ctx), s = i.config.yaxis[t].labels.style, r = s.fontSize, o = s.fontFamily, n = s.fontWeight, l = a.group({ class: "apexcharts-yaxis", rel: t, transform: "translate(" + i.globals.translateYAxisX[t] + ", 0)" }); if (this.axesUtils.isYAxisHidden(t)) return l; var h = a.group({ class: "apexcharts-yaxis-texts-g" }); l.add(h); var c = i.globals.yAxisScale[t].result.length - 1, d = i.globals.gridHeight / c, g = i.globals.yLabelFormatters[t], u = i.globals.yAxisScale[t].result.slice(); u = this.axesUtils.checkForReversedLabels(t, u); var p = ""; if (i.config.yaxis[t].labels.show) { var f = i.globals.translateY + i.config.yaxis[t].labels.offsetY; i.globals.isBarHorizontal ? f = 0 : "heatmap" === i.config.chart.type && (f -= d / 2), f += parseInt(i.config.yaxis[t].labels.style.fontSize, 10) / 3; for (var x = function (l) { var x = u[l]; x = g(x, l, i); var b = i.config.yaxis[t].labels.padding; i.config.yaxis[t].opposite && 0 !== i.config.yaxis.length && (b *= -1); var v = "end"; i.config.yaxis[t].opposite && (v = "start"), "left" === i.config.yaxis[t].labels.align ? v = "start" : "center" === i.config.yaxis[t].labels.align ? v = "middle" : "right" === i.config.yaxis[t].labels.align && (v = "end"); var m = e.axesUtils.getYAxisForeColor(s.colors, t), y = a.drawText({ x: b, y: f, text: x, textAnchor: v, fontSize: r, fontFamily: o, fontWeight: n, maxWidth: i.config.yaxis[t].labels.maxWidth, foreColor: Array.isArray(m) ? m[l] : m, isPlainText: !1, cssClass: "apexcharts-yaxis-label " + s.cssClass }); l === c && (p = y), h.add(y); var w = document.createElementNS(i.globals.SVGNS, "title"); if (w.textContent = Array.isArray(x) ? x.join(" ") : x, y.node.appendChild(w), 0 !== i.config.yaxis[t].labels.rotate) { var k = a.rotateAroundCenter(p.node), A = a.rotateAroundCenter(y.node); y.node.setAttribute("transform", "rotate(".concat(i.config.yaxis[t].labels.rotate, " ").concat(k.x, " ").concat(A.y, ")")) } f += d }, b = c; b >= 0; b--)x(b) } if (void 0 !== i.config.yaxis[t].title.text) { var v = a.group({ class: "apexcharts-yaxis-title" }), y = 0; i.config.yaxis[t].opposite && (y = i.globals.translateYAxisX[t]); var w = a.drawText({ x: y, y: i.globals.gridHeight / 2 + i.globals.translateY + i.config.yaxis[t].title.offsetY, text: i.config.yaxis[t].title.text, textAnchor: "end", foreColor: i.config.yaxis[t].title.style.color, fontSize: i.config.yaxis[t].title.style.fontSize, fontWeight: i.config.yaxis[t].title.style.fontWeight, fontFamily: i.config.yaxis[t].title.style.fontFamily, cssClass: "apexcharts-yaxis-title-text " + i.config.yaxis[t].title.style.cssClass }); v.add(w), l.add(v) } var k = i.config.yaxis[t].axisBorder, A = 31 + k.offsetX; if (i.config.yaxis[t].opposite && (A = -31 - k.offsetX), k.show) { var S = a.drawLine(A, i.globals.translateY + k.offsetY - 2, A, i.globals.gridHeight + i.globals.translateY + k.offsetY + 2, k.color, 0, k.width); l.add(S) } return i.config.yaxis[t].axisTicks.show && this.axesUtils.drawYAxisTicks(A, c, k, i.config.yaxis[t].axisTicks, t, d, l), l } }, { key: "drawYaxisInversed", value: function (t) { var e = this.w, i = new m(this.ctx), a = i.group({ class: "apexcharts-xaxis apexcharts-yaxis-inversed" }), s = i.group({ class: "apexcharts-xaxis-texts-g", transform: "translate(".concat(e.globals.translateXAxisX, ", ").concat(e.globals.translateXAxisY, ")") }); a.add(s); var r = e.globals.yAxisScale[t].result.length - 1, o = e.globals.gridWidth / r + .1, n = o + e.config.xaxis.labels.offsetX, l = e.globals.xLabelFormatter, h = e.globals.yAxisScale[t].result.slice(), c = e.globals.timescaleLabels; c.length > 0 && (this.xaxisLabels = c.slice(), r = (h = c.slice()).length), h = this.axesUtils.checkForReversedLabels(t, h); var d = c.length; if (e.config.xaxis.labels.show) for (var g = d ? 0 : r; d ? g < d : g >= 0; d ? g++ : g--) { var u = h[g]; u = l(u, g, e); var p = e.globals.gridWidth + e.globals.padHorizontal - (n - o + e.config.xaxis.labels.offsetX); if (c.length) { var f = this.axesUtils.getLabel(h, c, p, g, this.drawnLabels, this.xaxisFontSize); p = f.x, u = f.text, this.drawnLabels.push(f.text), 0 === g && e.globals.skipFirstTimelinelabel && (u = ""), g === h.length - 1 && e.globals.skipLastTimelinelabel && (u = "") } var x = i.drawText({ x: p, y: this.xAxisoffX + e.config.xaxis.labels.offsetY + 30 - ("top" === e.config.xaxis.position ? e.globals.xAxisHeight + e.config.xaxis.axisTicks.height - 2 : 0), text: u, textAnchor: "middle", foreColor: Array.isArray(this.xaxisForeColors) ? this.xaxisForeColors[t] : this.xaxisForeColors, fontSize: this.xaxisFontSize, fontFamily: this.xaxisFontFamily, fontWeight: e.config.xaxis.labels.style.fontWeight, isPlainText: !1, cssClass: "apexcharts-xaxis-label " + e.config.xaxis.labels.style.cssClass }); s.add(x), x.tspan(u); var b = document.createElementNS(e.globals.SVGNS, "title"); b.textContent = u, x.node.appendChild(b), n += o } return this.inversedYAxisTitleText(a), this.inversedYAxisBorder(a), a } }, { key: "inversedYAxisBorder", value: function (t) { var e = this.w, i = new m(this.ctx), a = e.config.xaxis.axisBorder; if (a.show) { var s = 0; "bar" === e.config.chart.type && e.globals.isXNumeric && (s -= 15); var r = i.drawLine(e.globals.padHorizontal + s + a.offsetX, this.xAxisoffX, e.globals.gridWidth, this.xAxisoffX, a.color, 0, a.height); this.elgrid && this.elgrid.elGridBorders && e.config.grid.show ? this.elgrid.elGridBorders.add(r) : t.add(r) } } }, { key: "inversedYAxisTitleText", value: function (t) { var e = this.w, i = new m(this.ctx); if (void 0 !== e.config.xaxis.title.text) { var a = i.group({ class: "apexcharts-xaxis-title apexcharts-yaxis-title-inversed" }), s = i.drawText({ x: e.globals.gridWidth / 2 + e.config.xaxis.title.offsetX, y: this.xAxisoffX + parseFloat(this.xaxisFontSize) + parseFloat(e.config.xaxis.title.style.fontSize) + e.config.xaxis.title.offsetY + 20, text: e.config.xaxis.title.text, textAnchor: "middle", fontSize: e.config.xaxis.title.style.fontSize, fontFamily: e.config.xaxis.title.style.fontFamily, fontWeight: e.config.xaxis.title.style.fontWeight, foreColor: e.config.xaxis.title.style.color, cssClass: "apexcharts-xaxis-title-text " + e.config.xaxis.title.style.cssClass }); a.add(s), t.add(a) } } }, { key: "yAxisTitleRotate", value: function (t, e) { var i = this.w, a = new m(this.ctx), s = { width: 0, height: 0 }, r = { width: 0, height: 0 }, o = i.globals.dom.baseEl.querySelector(" .apexcharts-yaxis[rel='".concat(t, "'] .apexcharts-yaxis-texts-g")); null !== o && (s = o.getBoundingClientRect()); var n = i.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(t, "'] .apexcharts-yaxis-title text")); if (null !== n && (r = n.getBoundingClientRect()), null !== n) { var l = this.xPaddingForYAxisTitle(t, s, r, e); n.setAttribute("x", l.xPos - (e ? 10 : 0)) } if (null !== n) { var h = a.rotateAroundCenter(n); n.setAttribute("transform", "rotate(".concat(e ? -1 * i.config.yaxis[t].title.rotate : i.config.yaxis[t].title.rotate, " ").concat(h.x, " ").concat(h.y, ")")) } } }, { key: "xPaddingForYAxisTitle", value: function (t, e, i, a) { var s = this.w, r = 0, o = 0, n = 10; return void 0 === s.config.yaxis[t].title.text || t < 0 ? { xPos: o, padd: 0 } : (a ? (o = e.width + s.config.yaxis[t].title.offsetX + i.width / 2 + n / 2, 0 === (r += 1) && (o -= n / 2)) : (o = -1 * e.width + s.config.yaxis[t].title.offsetX + n / 2 + i.width / 2, s.globals.isBarHorizontal && (n = 25, o = -1 * e.width - s.config.yaxis[t].title.offsetX - n)), { xPos: o, padd: n }) } }, { key: "setYAxisXPosition", value: function (t, e) { var i = this.w, a = 0, s = 0, r = 18, o = 1; i.config.yaxis.length > 1 && (this.multipleYs = !0), i.config.yaxis.map((function (n, l) { var h = i.globals.ignoreYAxisIndexes.indexOf(l) > -1 || !n.show || n.floating || 0 === t[l].width, c = t[l].width + e[l].width; n.opposite ? i.globals.isBarHorizontal ? (s = i.globals.gridWidth + i.globals.translateX - 1, i.globals.translateYAxisX[l] = s - n.labels.offsetX) : (s = i.globals.gridWidth + i.globals.translateX + o, h || (o = o + c + 20), i.globals.translateYAxisX[l] = s - n.labels.offsetX + 20) : (a = i.globals.translateX - r, h || (r = r + c + 20), i.globals.translateYAxisX[l] = a + n.labels.offsetX) })) } }, { key: "setYAxisTextAlignments", value: function () { var t = this.w, e = t.globals.dom.baseEl.getElementsByClassName("apexcharts-yaxis"); (e = x.listToArray(e)).forEach((function (e, i) { var a = t.config.yaxis[i]; if (a && !a.floating && void 0 !== a.labels.align) { var s = t.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(i, "'] .apexcharts-yaxis-texts-g")), r = t.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis[rel='".concat(i, "'] .apexcharts-yaxis-label")); r = x.listToArray(r); var o = s.getBoundingClientRect(); "left" === a.labels.align ? (r.forEach((function (t, e) { t.setAttribute("text-anchor", "start") })), a.opposite || s.setAttribute("transform", "translate(-".concat(o.width, ", 0)"))) : "center" === a.labels.align ? (r.forEach((function (t, e) { t.setAttribute("text-anchor", "middle") })), s.setAttribute("transform", "translate(".concat(o.width / 2 * (a.opposite ? 1 : -1), ", 0)"))) : "right" === a.labels.align && (r.forEach((function (t, e) { t.setAttribute("text-anchor", "end") })), a.opposite && s.setAttribute("transform", "translate(".concat(o.width, ", 0)"))) } })) } }]), t }(), Z = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.documentEvent = x.bind(this.documentEvent, this) } return r(t, [{ key: "addEventListener", value: function (t, e) { var i = this.w; i.globals.events.hasOwnProperty(t) ? i.globals.events[t].push(e) : i.globals.events[t] = [e] } }, { key: "removeEventListener", value: function (t, e) { var i = this.w; if (i.globals.events.hasOwnProperty(t)) { var a = i.globals.events[t].indexOf(e); -1 !== a && i.globals.events[t].splice(a, 1) } } }, { key: "fireEvent", value: function (t, e) { var i = this.w; if (i.globals.events.hasOwnProperty(t)) { e && e.length || (e = []); for (var a = i.globals.events[t], s = a.length, r = 0; r < s; r++)a[r].apply(null, e) } } }, { key: "setupEventHandlers", value: function () { var t = this, e = this.w, i = this.ctx, a = e.globals.dom.baseEl.querySelector(e.globals.chartClass); this.ctx.eventList.forEach((function (t) { a.addEventListener(t, (function (t) { var a = Object.assign({}, e, { seriesIndex: e.globals.axisCharts ? e.globals.capturedSeriesIndex : 0, dataPointIndex: e.globals.capturedDataPointIndex }); "mousemove" === t.type || "touchmove" === t.type ? "function" == typeof e.config.chart.events.mouseMove && e.config.chart.events.mouseMove(t, i, a) : "mouseleave" === t.type || "touchleave" === t.type ? "function" == typeof e.config.chart.events.mouseLeave && e.config.chart.events.mouseLeave(t, i, a) : ("mouseup" === t.type && 1 === t.which || "touchend" === t.type) && ("function" == typeof e.config.chart.events.click && e.config.chart.events.click(t, i, a), i.ctx.events.fireEvent("click", [t, i, a])) }), { capture: !1, passive: !0 }) })), this.ctx.eventList.forEach((function (i) { e.globals.dom.baseEl.addEventListener(i, t.documentEvent, { passive: !0 }) })), this.ctx.core.setupBrushHandler() } }, { key: "documentEvent", value: function (t) { var e = this.w, i = t.target.className; if ("click" === t.type) { var a = e.globals.dom.baseEl.querySelector(".apexcharts-menu"); a && a.classList.contains("apexcharts-menu-open") && "apexcharts-menu-icon" !== i && a.classList.remove("apexcharts-menu-open") } e.globals.clientX = "touchmove" === t.type ? t.touches[0].clientX : t.clientX, e.globals.clientY = "touchmove" === t.type ? t.touches[0].clientY : t.clientY } }]), t }(), $ = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "setCurrentLocaleValues", value: function (t) { var e = this.w.config.chart.locales; window.Apex.chart && window.Apex.chart.locales && window.Apex.chart.locales.length > 0 && (e = this.w.config.chart.locales.concat(window.Apex.chart.locales)); var i = e.filter((function (e) { return e.name === t }))[0]; if (!i) throw new Error("Wrong locale name provided. Please make sure you set the correct locale name in options"); var a = x.extend(M, i); this.w.globals.locale = a.options } }]), t }(), J = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "drawAxis", value: function (t, e) { var i, a, s = this, r = this.w.globals, o = this.w.config, n = new V(this.ctx, e), l = new q(this.ctx, e); r.axisCharts && "radar" !== t && (r.isBarHorizontal ? (a = l.drawYaxisInversed(0), i = n.drawXaxisInversed(0), r.dom.elGraphical.add(i), r.dom.elGraphical.add(a)) : (i = n.drawXaxis(), r.dom.elGraphical.add(i), o.yaxis.map((function (t, e) { if (-1 === r.ignoreYAxisIndexes.indexOf(e) && (a = l.drawYaxis(e), r.dom.Paper.add(a), "back" === s.w.config.grid.position)) { var i = r.dom.Paper.children()[1]; i.remove(), r.dom.Paper.add(i) } })))) } }]), t }(), Q = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "drawXCrosshairs", value: function () { var t = this.w, e = new m(this.ctx), i = new v(this.ctx), a = t.config.xaxis.crosshairs.fill.gradient, s = t.config.xaxis.crosshairs.dropShadow, r = t.config.xaxis.crosshairs.fill.type, o = a.colorFrom, n = a.colorTo, l = a.opacityFrom, h = a.opacityTo, c = a.stops, d = s.enabled, g = s.left, u = s.top, p = s.blur, f = s.color, b = s.opacity, y = t.config.xaxis.crosshairs.fill.color; if (t.config.xaxis.crosshairs.show) { "gradient" === r && (y = e.drawGradient("vertical", o, n, l, h, null, c, null)); var w = e.drawRect(); 1 === t.config.xaxis.crosshairs.width && (w = e.drawLine()); var k = t.globals.gridHeight; (!x.isNumber(k) || k < 0) && (k = 0); var A = t.config.xaxis.crosshairs.width; (!x.isNumber(A) || A < 0) && (A = 0), w.attr({ class: "apexcharts-xcrosshairs", x: 0, y: 0, y2: k, width: A, height: k, fill: y, filter: "none", "fill-opacity": t.config.xaxis.crosshairs.opacity, stroke: t.config.xaxis.crosshairs.stroke.color, "stroke-width": t.config.xaxis.crosshairs.stroke.width, "stroke-dasharray": t.config.xaxis.crosshairs.stroke.dashArray }), d && (w = i.dropShadow(w, { left: g, top: u, blur: p, color: f, opacity: b })), t.globals.dom.elGraphical.add(w) } } }, { key: "drawYCrosshairs", value: function () { var t = this.w, e = new m(this.ctx), i = t.config.yaxis[0].crosshairs, a = t.globals.barPadForNumericAxis; if (t.config.yaxis[0].crosshairs.show) { var s = e.drawLine(-a, 0, t.globals.gridWidth + a, 0, i.stroke.color, i.stroke.dashArray, i.stroke.width); s.attr({ class: "apexcharts-ycrosshairs" }), t.globals.dom.elGraphical.add(s) } var r = e.drawLine(-a, 0, t.globals.gridWidth + a, 0, i.stroke.color, 0, 0); r.attr({ class: "apexcharts-ycrosshairs-hidden" }), t.globals.dom.elGraphical.add(r) } }]), t }(), K = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "checkResponsiveConfig", value: function (t) { var e = this, i = this.w, a = i.config; if (0 !== a.responsive.length) { var s = a.responsive.slice(); s.sort((function (t, e) { return t.breakpoint > e.breakpoint ? 1 : e.breakpoint > t.breakpoint ? -1 : 0 })).reverse(); var r = new Y({}), o = function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, a = s[0].breakpoint, o = window.innerWidth > 0 ? window.innerWidth : screen.width; if (o > a) { var n = x.clone(i.globals.initialConfig); n.series = x.clone(i.config.series); var l = y.extendArrayProps(r, n, i); t = x.extend(l, t), t = x.extend(i.config, t), e.overrideResponsiveOptions(t) } else for (var h = 0; h < s.length; h++)if (o < s[h].breakpoint) { var c = y.extendArrayProps(r, s[h].options, i); t = x.extend(c, t), t = x.extend(i.config, t), e.overrideResponsiveOptions(t) } }; if (t) { var n = y.extendArrayProps(r, t, i); n = x.extend(i.config, n), o(n = x.extend(n, t)) } else o({}) } } }, { key: "overrideResponsiveOptions", value: function (t) { var e = new Y(t).init({ responsiveOverride: !0 }); this.w.config = e } }]), t }(), tt = function () { function t(e) { a(this, t), this.ctx = e, this.colors = [], this.w = e.w; var i = this.w; this.isColorFn = !1, this.isHeatmapDistributed = "treemap" === i.config.chart.type && i.config.plotOptions.treemap.distributed || "heatmap" === i.config.chart.type && i.config.plotOptions.heatmap.distributed, this.isBarDistributed = i.config.plotOptions.bar.distributed && ("bar" === i.config.chart.type || "rangeBar" === i.config.chart.type) } return r(t, [{ key: "init", value: function () { this.setDefaultColors() } }, { key: "setDefaultColors", value: function () { var t, e = this, i = this.w, a = new x; if (i.globals.dom.elWrap.classList.add("apexcharts-theme-".concat(i.config.theme.mode)), void 0 === i.config.colors || 0 === (null === (t = i.config.colors) || void 0 === t ? void 0 : t.length) ? i.globals.colors = this.predefined() : (i.globals.colors = i.config.colors, Array.isArray(i.config.colors) && i.config.colors.length > 0 && "function" == typeof i.config.colors[0] && (i.globals.colors = i.config.series.map((function (t, a) { var s = i.config.colors[a]; return s || (s = i.config.colors[0]), "function" == typeof s ? (e.isColorFn = !0, s({ value: i.globals.axisCharts ? i.globals.series[a][0] ? i.globals.series[a][0] : 0 : i.globals.series[a], seriesIndex: a, dataPointIndex: a, w: i })) : s })))), i.globals.seriesColors.map((function (t, e) { t && (i.globals.colors[e] = t) })), i.config.theme.monochrome.enabled) { var s = [], r = i.globals.series.length; (this.isBarDistributed || this.isHeatmapDistributed) && (r = i.globals.series[0].length * i.globals.series.length); for (var o = i.config.theme.monochrome.color, n = 1 / (r / i.config.theme.monochrome.shadeIntensity), l = i.config.theme.monochrome.shadeTo, h = 0, c = 0; c < r; c++) { var d = void 0; "dark" === l ? (d = a.shadeColor(-1 * h, o), h += n) : (d = a.shadeColor(h, o), h += n), s.push(d) } i.globals.colors = s.slice() } var g = i.globals.colors.slice(); this.pushExtraColors(i.globals.colors);["fill", "stroke"].forEach((function (t) { void 0 === i.config[t].colors ? i.globals[t].colors = e.isColorFn ? i.config.colors : g : i.globals[t].colors = i.config[t].colors.slice(), e.pushExtraColors(i.globals[t].colors) })), void 0 === i.config.dataLabels.style.colors ? i.globals.dataLabels.style.colors = g : i.globals.dataLabels.style.colors = i.config.dataLabels.style.colors.slice(), this.pushExtraColors(i.globals.dataLabels.style.colors, 50), void 0 === i.config.plotOptions.radar.polygons.fill.colors ? i.globals.radarPolygons.fill.colors = ["dark" === i.config.theme.mode ? "#424242" : "none"] : i.globals.radarPolygons.fill.colors = i.config.plotOptions.radar.polygons.fill.colors.slice(), this.pushExtraColors(i.globals.radarPolygons.fill.colors, 20), void 0 === i.config.markers.colors ? i.globals.markers.colors = g : i.globals.markers.colors = i.config.markers.colors.slice(), this.pushExtraColors(i.globals.markers.colors) } }, { key: "pushExtraColors", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : null, a = this.w, s = e || a.globals.series.length; if (null === i && (i = this.isBarDistributed || this.isHeatmapDistributed || "heatmap" === a.config.chart.type && a.config.plotOptions.heatmap.colorScale.inverse), i && a.globals.series.length && (s = a.globals.series[a.globals.maxValsInArrayIndex].length * a.globals.series.length), t.length < s) for (var r = s - t.length, o = 0; o < r; o++)t.push(t[o]) } }, { key: "updateThemeOptions", value: function (t) { t.chart = t.chart || {}, t.tooltip = t.tooltip || {}; var e = t.theme.mode || "light", i = t.theme.palette ? t.theme.palette : "dark" === e ? "palette4" : "palette1", a = t.chart.foreColor ? t.chart.foreColor : "dark" === e ? "#f6f7f8" : "#373d3f"; return t.tooltip.theme = e, t.chart.foreColor = a, t.theme.palette = i, t } }, { key: "predefined", value: function () { switch (this.w.config.theme.palette) { case "palette1": default: this.colors = ["#008FFB", "#00E396", "#FEB019", "#FF4560", "#775DD0"]; break; case "palette2": this.colors = ["#3f51b5", "#03a9f4", "#4caf50", "#f9ce1d", "#FF9800"]; break; case "palette3": this.colors = ["#33b2df", "#546E7A", "#d4526e", "#13d8aa", "#A5978B"]; break; case "palette4": this.colors = ["#4ecdc4", "#c7f464", "#81D4FA", "#fd6a6a", "#546E7A"]; break; case "palette5": this.colors = ["#2b908f", "#f9a3a4", "#90ee7e", "#fa4443", "#69d2e7"]; break; case "palette6": this.colors = ["#449DD1", "#F86624", "#EA3546", "#662E9B", "#C5D86D"]; break; case "palette7": this.colors = ["#D7263D", "#1B998B", "#2E294E", "#F46036", "#E2C044"]; break; case "palette8": this.colors = ["#662E9B", "#F86624", "#F9C80E", "#EA3546", "#43BCCD"]; break; case "palette9": this.colors = ["#5C4742", "#A5978B", "#8D5B4C", "#5A2A27", "#C4BBAF"]; break; case "palette10": this.colors = ["#A300D6", "#7D02EB", "#5653FE", "#2983FF", "#00B1F2"] }return this.colors } }]), t }(), et = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "draw", value: function () { this.drawTitleSubtitle("title"), this.drawTitleSubtitle("subtitle") } }, { key: "drawTitleSubtitle", value: function (t) { var e = this.w, i = "title" === t ? e.config.title : e.config.subtitle, a = e.globals.svgWidth / 2, s = i.offsetY, r = "middle"; if ("left" === i.align ? (a = 10, r = "start") : "right" === i.align && (a = e.globals.svgWidth - 10, r = "end"), a += i.offsetX, s = s + parseInt(i.style.fontSize, 10) + i.margin / 2, void 0 !== i.text) { var o = new m(this.ctx).drawText({ x: a, y: s, text: i.text, textAnchor: r, fontSize: i.style.fontSize, fontFamily: i.style.fontFamily, fontWeight: i.style.fontWeight, foreColor: i.style.color, opacity: 1 }); o.node.setAttribute("class", "apexcharts-".concat(t, "-text")), e.globals.dom.Paper.add(o) } } }]), t }(), it = function () { function t(e) { a(this, t), this.w = e.w, this.dCtx = e } return r(t, [{ key: "getTitleSubtitleCoords", value: function (t) { var e = this.w, i = 0, a = 0, s = "title" === t ? e.config.title.floating : e.config.subtitle.floating, r = e.globals.dom.baseEl.querySelector(".apexcharts-".concat(t, "-text")); if (null !== r && !s) { var o = r.getBoundingClientRect(); i = o.width, a = e.globals.axisCharts ? o.height + 5 : o.height } return { width: i, height: a } } }, { key: "getLegendsRect", value: function () { var t = this.w, e = t.globals.dom.elLegendWrap; t.config.legend.height || "top" !== t.config.legend.position && "bottom" !== t.config.legend.position || (e.style.maxHeight = t.globals.svgHeight / 2 + "px"); var i = Object.assign({}, x.getBoundingClientRect(e)); return null !== e && !t.config.legend.floating && t.config.legend.show ? this.dCtx.lgRect = { x: i.x, y: i.y, height: i.height, width: 0 === i.height ? 0 : i.width } : this.dCtx.lgRect = { x: 0, y: 0, height: 0, width: 0 }, "left" !== t.config.legend.position && "right" !== t.config.legend.position || 1.5 * this.dCtx.lgRect.width > t.globals.svgWidth && (this.dCtx.lgRect.width = t.globals.svgWidth / 1.5), this.dCtx.lgRect } }, { key: "getDatalabelsRect", value: function () { var t = this, e = this.w, i = []; e.config.series.forEach((function (s, r) { s.data.forEach((function (s, o) { var n; n = e.globals.series[r][o], a = e.config.dataLabels.formatter(n, { ctx: t.dCtx.ctx, seriesIndex: r, dataPointIndex: o, w: e }), i.push(a) })) })); var a = x.getLargestStringFromArr(i), s = new m(this.dCtx.ctx), r = e.config.dataLabels.style, o = s.getTextRects(a, parseInt(r.fontSize), r.fontFamily); return { width: 1.05 * o.width, height: o.height } } }, { key: "getLargestStringFromMultiArr", value: function (t, e) { var i = t; if (this.w.globals.isMultiLineX) { var a = e.map((function (t, e) { return Array.isArray(t) ? t.length : 1 })), s = Math.max.apply(Math, u(a)); i = e[a.indexOf(s)] } return i } }]), t }(), at = function () { function t(e) { a(this, t), this.w = e.w, this.dCtx = e } return r(t, [{ key: "getxAxisLabelsCoords", value: function () { var t, e = this.w, i = e.globals.labels.slice(); if (e.config.xaxis.convertedCatToNumeric && 0 === i.length && (i = e.globals.categoryLabels), e.globals.timescaleLabels.length > 0) { var a = this.getxAxisTimeScaleLabelsCoords(); t = { width: a.width, height: a.height }, e.globals.rotateXLabels = !1 } else { this.dCtx.lgWidthForSideLegends = "left" !== e.config.legend.position && "right" !== e.config.legend.position || e.config.legend.floating ? 0 : this.dCtx.lgRect.width; var s = e.globals.xLabelFormatter, r = x.getLargestStringFromArr(i), o = this.dCtx.dimHelpers.getLargestStringFromMultiArr(r, i); e.globals.isBarHorizontal && (o = r = e.globals.yAxisScale[0].result.reduce((function (t, e) { return t.length > e.length ? t : e }), 0)); var n = new S(this.dCtx.ctx), l = r; r = n.xLabelFormat(s, r, l, { i: void 0, dateFormatter: new A(this.dCtx.ctx).formatDate, w: e }), o = n.xLabelFormat(s, o, l, { i: void 0, dateFormatter: new A(this.dCtx.ctx).formatDate, w: e }), (e.config.xaxis.convertedCatToNumeric && void 0 === r || "" === String(r).trim()) && (o = r = "1"); var h = new m(this.dCtx.ctx), c = h.getTextRects(r, e.config.xaxis.labels.style.fontSize), d = c; if (r !== o && (d = h.getTextRects(o, e.config.xaxis.labels.style.fontSize)), (t = { width: c.width >= d.width ? c.width : d.width, height: c.height >= d.height ? c.height : d.height }).width * i.length > e.globals.svgWidth - this.dCtx.lgWidthForSideLegends - this.dCtx.yAxisWidth - this.dCtx.gridPad.left - this.dCtx.gridPad.right && 0 !== e.config.xaxis.labels.rotate || e.config.xaxis.labels.rotateAlways) { if (!e.globals.isBarHorizontal) { e.globals.rotateXLabels = !0; var g = function (t) { return h.getTextRects(t, e.config.xaxis.labels.style.fontSize, e.config.xaxis.labels.style.fontFamily, "rotate(".concat(e.config.xaxis.labels.rotate, " 0 0)"), !1) }; c = g(r), r !== o && (d = g(o)), t.height = (c.height > d.height ? c.height : d.height) / 1.5, t.width = c.width > d.width ? c.width : d.width } } else e.globals.rotateXLabels = !1 } return e.config.xaxis.labels.show || (t = { width: 0, height: 0 }), { width: t.width, height: t.height } } }, { key: "getxAxisGroupLabelsCoords", value: function () { var t, e = this.w; if (!e.globals.hasXaxisGroups) return { width: 0, height: 0 }; var i, a = (null === (t = e.config.xaxis.group.style) || void 0 === t ? void 0 : t.fontSize) || e.config.xaxis.labels.style.fontSize, s = e.globals.groups.map((function (t) { return t.title })), r = x.getLargestStringFromArr(s), o = this.dCtx.dimHelpers.getLargestStringFromMultiArr(r, s), n = new m(this.dCtx.ctx), l = n.getTextRects(r, a), h = l; return r !== o && (h = n.getTextRects(o, a)), i = { width: l.width >= h.width ? l.width : h.width, height: l.height >= h.height ? l.height : h.height }, e.config.xaxis.labels.show || (i = { width: 0, height: 0 }), { width: i.width, height: i.height } } }, { key: "getxAxisTitleCoords", value: function () { var t = this.w, e = 0, i = 0; if (void 0 !== t.config.xaxis.title.text) { var a = new m(this.dCtx.ctx).getTextRects(t.config.xaxis.title.text, t.config.xaxis.title.style.fontSize); e = a.width, i = a.height } return { width: e, height: i } } }, { key: "getxAxisTimeScaleLabelsCoords", value: function () { var t, e = this.w; this.dCtx.timescaleLabels = e.globals.timescaleLabels.slice(); var i = this.dCtx.timescaleLabels.map((function (t) { return t.value })), a = i.reduce((function (t, e) { return void 0 === t ? (console.error("You have possibly supplied invalid Date format. Please supply a valid JavaScript Date"), 0) : t.length > e.length ? t : e }), 0); return 1.05 * (t = new m(this.dCtx.ctx).getTextRects(a, e.config.xaxis.labels.style.fontSize)).width * i.length > e.globals.gridWidth && 0 !== e.config.xaxis.labels.rotate && (e.globals.overlappingXLabels = !0), t } }, { key: "additionalPaddingXLabels", value: function (t) { var e = this, i = this.w, a = i.globals, s = i.config, r = s.xaxis.type, o = t.width; a.skipLastTimelinelabel = !1, a.skipFirstTimelinelabel = !1; var n = i.config.yaxis[0].opposite && i.globals.isBarHorizontal, l = function (t, n) { s.yaxis.length > 1 && function (t) { return -1 !== a.collapsedSeriesIndices.indexOf(t) }(n) || function (t) { if (e.dCtx.timescaleLabels && e.dCtx.timescaleLabels.length) { var n = e.dCtx.timescaleLabels[0], l = e.dCtx.timescaleLabels[e.dCtx.timescaleLabels.length - 1].position + o / 1.75 - e.dCtx.yAxisWidthRight, h = n.position - o / 1.75 + e.dCtx.yAxisWidthLeft, c = "right" === i.config.legend.position && e.dCtx.lgRect.width > 0 ? e.dCtx.lgRect.width : 0; l > a.svgWidth - a.translateX - c && (a.skipLastTimelinelabel = !0), h < -(t.show && !t.floating || "bar" !== s.chart.type && "candlestick" !== s.chart.type && "rangeBar" !== s.chart.type && "boxPlot" !== s.chart.type ? 10 : o / 1.75) && (a.skipFirstTimelinelabel = !0) } else "datetime" === r ? e.dCtx.gridPad.right < o && !a.rotateXLabels && (a.skipLastTimelinelabel = !0) : "datetime" !== r && e.dCtx.gridPad.right < o / 2 - e.dCtx.yAxisWidthRight && !a.rotateXLabels && !i.config.xaxis.labels.trim && ("between" !== i.config.xaxis.tickPlacement || i.globals.isBarHorizontal) && (e.dCtx.xPadRight = o / 2 + 1) }(t) }; s.yaxis.forEach((function (t, i) { n ? (e.dCtx.gridPad.left < o && (e.dCtx.xPadLeft = o / 2 + 1), e.dCtx.xPadRight = o / 2 + 1) : l(t, i) })) } }]), t }(), st = function () { function t(e) { a(this, t), this.w = e.w, this.dCtx = e } return r(t, [{ key: "getyAxisLabelsCoords", value: function () { var t = this, e = this.w, i = [], a = 10, s = new C(this.dCtx.ctx); return e.config.yaxis.map((function (r, o) { var n = { seriesIndex: o, dataPointIndex: -1, w: e }, l = e.globals.yAxisScale[o], h = 0; if (!s.isYAxisHidden(o) && r.labels.show && void 0 !== r.labels.minWidth && (h = r.labels.minWidth), !s.isYAxisHidden(o) && r.labels.show && l.result.length) { var c = e.globals.yLabelFormatters[o], d = l.niceMin === Number.MIN_VALUE ? 0 : l.niceMin, g = l.result.reduce((function (t, e) { var i, a; return (null === (i = String(c(t, n))) || void 0 === i ? void 0 : i.length) > (null === (a = String(c(e, n))) || void 0 === a ? void 0 : a.length) ? t : e }), d), u = g = c(g, n); if (void 0 !== g && 0 !== g.length || (g = l.niceMax), e.globals.isBarHorizontal) { a = 0; var p = e.globals.labels.slice(); g = x.getLargestStringFromArr(p), g = c(g, { seriesIndex: o, dataPointIndex: -1, w: e }), u = t.dCtx.dimHelpers.getLargestStringFromMultiArr(g, p) } var f = new m(t.dCtx.ctx), b = "rotate(".concat(r.labels.rotate, " 0 0)"), v = f.getTextRects(g, r.labels.style.fontSize, r.labels.style.fontFamily, b, !1), y = v; g !== u && (y = f.getTextRects(u, r.labels.style.fontSize, r.labels.style.fontFamily, b, !1)), i.push({ width: (h > y.width || h > v.width ? h : y.width > v.width ? y.width : v.width) + a, height: y.height > v.height ? y.height : v.height }) } else i.push({ width: 0, height: 0 }) })), i } }, { key: "getyAxisTitleCoords", value: function () { var t = this, e = this.w, i = []; return e.config.yaxis.map((function (e, a) { if (e.show && void 0 !== e.title.text) { var s = new m(t.dCtx.ctx), r = "rotate(".concat(e.title.rotate, " 0 0)"), o = s.getTextRects(e.title.text, e.title.style.fontSize, e.title.style.fontFamily, r, !1); i.push({ width: o.width, height: o.height }) } else i.push({ width: 0, height: 0 }) })), i } }, { key: "getTotalYAxisWidth", value: function () { var t = this.w, e = 0, i = 0, a = 0, s = t.globals.yAxisScale.length > 1 ? 10 : 0, r = new C(this.dCtx.ctx), o = function (o, n) { var l = t.config.yaxis[n].floating, h = 0; o.width > 0 && !l ? (h = o.width + s, function (e) { return t.globals.ignoreYAxisIndexes.indexOf(e) > -1 }(n) && (h = h - o.width - s)) : h = l || r.isYAxisHidden(n) ? 0 : 5, t.config.yaxis[n].opposite ? a += h : i += h, e += h }; return t.globals.yLabelsCoords.map((function (t, e) { o(t, e) })), t.globals.yTitleCoords.map((function (t, e) { o(t, e) })), t.globals.isBarHorizontal && !t.config.yaxis[0].floating && (e = t.globals.yLabelsCoords[0].width + t.globals.yTitleCoords[0].width + 15), this.dCtx.yAxisWidthLeft = i, this.dCtx.yAxisWidthRight = a, e } }]), t }(), rt = function () { function t(e) { a(this, t), this.w = e.w, this.dCtx = e } return r(t, [{ key: "gridPadForColumnsInNumericAxis", value: function (t) { var e = this.w, i = e.config, a = e.globals; if (a.noData || a.collapsedSeries.length + a.ancillaryCollapsedSeries.length === i.series.length) return 0; var s = function (t) { return "bar" === t || "rangeBar" === t || "candlestick" === t || "boxPlot" === t }, r = i.chart.type, o = 0, n = s(r) ? i.series.length : 1; if (a.comboBarCount > 0 && (n = a.comboBarCount), a.collapsedSeries.forEach((function (t) { s(t.type) && (n -= 1) })), i.chart.stacked && (n = 1), (s(r) || a.comboBarCount > 0) && a.isXNumeric && !a.isBarHorizontal && n > 0) { var l, h, c = Math.abs(a.initialMaxX - a.initialMinX); c <= 3 && (c = a.dataPoints), l = c / t, a.minXDiff && a.minXDiff / l > 0 && (h = a.minXDiff / l), h > t / 2 && (h /= 2), (o = h * parseInt(i.plotOptions.bar.columnWidth, 10) / 100) < 1 && (o = 1), a.barPadForNumericAxis = o } return o } }, { key: "gridPadFortitleSubtitle", value: function () { var t = this, e = this.w, i = e.globals, a = this.dCtx.isSparkline || !e.globals.axisCharts ? 0 : 10;["title", "subtitle"].forEach((function (i) { void 0 !== e.config[i].text ? a += e.config[i].margin : a += t.dCtx.isSparkline || !e.globals.axisCharts ? 0 : 5 })), !e.config.legend.show || "bottom" !== e.config.legend.position || e.config.legend.floating || e.globals.axisCharts || (a += 10); var s = this.dCtx.dimHelpers.getTitleSubtitleCoords("title"), r = this.dCtx.dimHelpers.getTitleSubtitleCoords("subtitle"); i.gridHeight = i.gridHeight - s.height - r.height - a, i.translateY = i.translateY + s.height + r.height + a } }, { key: "setGridXPosForDualYAxis", value: function (t, e) { var i = this.w, a = new C(this.dCtx.ctx); i.config.yaxis.map((function (s, r) { -1 !== i.globals.ignoreYAxisIndexes.indexOf(r) || s.floating || a.isYAxisHidden(r) || (s.opposite && (i.globals.translateX = i.globals.translateX - (e[r].width + t[r].width) - parseInt(i.config.yaxis[r].labels.style.fontSize, 10) / 1.2 - 12), i.globals.translateX < 2 && (i.globals.translateX = 2)) })) } }]), t }(), ot = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.lgRect = {}, this.yAxisWidth = 0, this.yAxisWidthLeft = 0, this.yAxisWidthRight = 0, this.xAxisHeight = 0, this.isSparkline = this.w.config.chart.sparkline.enabled, this.dimHelpers = new it(this), this.dimYAxis = new st(this), this.dimXAxis = new at(this), this.dimGrid = new rt(this), this.lgWidthForSideLegends = 0, this.gridPad = this.w.config.grid.padding, this.xPadRight = 0, this.xPadLeft = 0 } return r(t, [{ key: "plotCoords", value: function () { var t = this, e = this.w, i = e.globals; this.lgRect = this.dimHelpers.getLegendsRect(), this.datalabelsCoords = { width: 0, height: 0 }; var a = Array.isArray(e.config.stroke.width) ? Math.max.apply(Math, u(e.config.stroke.width)) : e.config.stroke.width; this.isSparkline && ((e.config.markers.discrete.length > 0 || e.config.markers.size > 0) && Object.entries(this.gridPad).forEach((function (e) { var i = g(e, 2), a = i[0], s = i[1]; t.gridPad[a] = Math.max(s, t.w.globals.markers.largestSize / 1.5) })), this.gridPad.top = Math.max(a / 2, this.gridPad.top), this.gridPad.bottom = Math.max(a / 2, this.gridPad.bottom)), i.axisCharts ? this.setDimensionsForAxisCharts() : this.setDimensionsForNonAxisCharts(), this.dimGrid.gridPadFortitleSubtitle(), i.gridHeight = i.gridHeight - this.gridPad.top - this.gridPad.bottom, i.gridWidth = i.gridWidth - this.gridPad.left - this.gridPad.right - this.xPadRight - this.xPadLeft; var s = this.dimGrid.gridPadForColumnsInNumericAxis(i.gridWidth); i.gridWidth = i.gridWidth - 2 * s, i.translateX = i.translateX + this.gridPad.left + this.xPadLeft + (s > 0 ? s : 0), i.translateY = i.translateY + this.gridPad.top } }, { key: "setDimensionsForAxisCharts", value: function () { var t = this, e = this.w, i = e.globals, a = this.dimYAxis.getyAxisLabelsCoords(), s = this.dimYAxis.getyAxisTitleCoords(); i.isSlopeChart && (this.datalabelsCoords = this.dimHelpers.getDatalabelsRect()), e.globals.yLabelsCoords = [], e.globals.yTitleCoords = [], e.config.yaxis.map((function (t, i) { e.globals.yLabelsCoords.push({ width: a[i].width, index: i }), e.globals.yTitleCoords.push({ width: s[i].width, index: i }) })), this.yAxisWidth = this.dimYAxis.getTotalYAxisWidth(); var r = this.dimXAxis.getxAxisLabelsCoords(), o = this.dimXAxis.getxAxisGroupLabelsCoords(), n = this.dimXAxis.getxAxisTitleCoords(); this.conditionalChecksForAxisCoords(r, n, o), i.translateXAxisY = e.globals.rotateXLabels ? this.xAxisHeight / 8 : -4, i.translateXAxisX = e.globals.rotateXLabels && e.globals.isXNumeric && e.config.xaxis.labels.rotate <= -45 ? -this.xAxisWidth / 4 : 0, e.globals.isBarHorizontal && (i.rotateXLabels = !1, i.translateXAxisY = parseInt(e.config.xaxis.labels.style.fontSize, 10) / 1.5 * -1), i.translateXAxisY = i.translateXAxisY + e.config.xaxis.labels.offsetY, i.translateXAxisX = i.translateXAxisX + e.config.xaxis.labels.offsetX; var l = this.yAxisWidth, h = this.xAxisHeight; i.xAxisLabelsHeight = this.xAxisHeight - n.height, i.xAxisGroupLabelsHeight = i.xAxisLabelsHeight - r.height, i.xAxisLabelsWidth = this.xAxisWidth, i.xAxisHeight = this.xAxisHeight; var c = 10; ("radar" === e.config.chart.type || this.isSparkline) && (l = 0, h = i.goldenPadding), this.isSparkline && (this.lgRect = { height: 0, width: 0 }), (this.isSparkline || "treemap" === e.config.chart.type) && (l = 0, h = 0, c = 0), this.isSparkline || this.dimXAxis.additionalPaddingXLabels(r); var d = function () { i.translateX = l + t.datalabelsCoords.width, i.gridHeight = i.svgHeight - t.lgRect.height - h - (t.isSparkline || "treemap" === e.config.chart.type ? 0 : e.globals.rotateXLabels ? 10 : 15), i.gridWidth = i.svgWidth - l - 2 * t.datalabelsCoords.width }; switch ("top" === e.config.xaxis.position && (c = i.xAxisHeight - e.config.xaxis.axisTicks.height - 5), e.config.legend.position) { case "bottom": i.translateY = c, d(); break; case "top": i.translateY = this.lgRect.height + c, d(); break; case "left": i.translateY = c, i.translateX = this.lgRect.width + l + this.datalabelsCoords.width, i.gridHeight = i.svgHeight - h - 12, i.gridWidth = i.svgWidth - this.lgRect.width - l - 2 * this.datalabelsCoords.width; break; case "right": i.translateY = c, i.translateX = l + this.datalabelsCoords.width, i.gridHeight = i.svgHeight - h - 12, i.gridWidth = i.svgWidth - this.lgRect.width - l - 2 * this.datalabelsCoords.width - 5; break; default: throw new Error("Legend position not supported") }this.dimGrid.setGridXPosForDualYAxis(s, a), new q(this.ctx).setYAxisXPosition(a, s) } }, { key: "setDimensionsForNonAxisCharts", value: function () { var t = this.w, e = t.globals, i = t.config, a = 0; t.config.legend.show && !t.config.legend.floating && (a = 20); var s = "pie" === i.chart.type || "polarArea" === i.chart.type || "donut" === i.chart.type ? "pie" : "radialBar", r = i.plotOptions[s].offsetY, o = i.plotOptions[s].offsetX; if (!i.legend.show || i.legend.floating) return e.gridHeight = e.svgHeight - i.grid.padding.left + i.grid.padding.right, e.gridWidth = Math.min(e.svgWidth, e.gridHeight), e.translateY = r, void (e.translateX = o + (e.svgWidth - e.gridWidth) / 2); switch (i.legend.position) { case "bottom": e.gridHeight = e.svgHeight - this.lgRect.height - e.goldenPadding, e.gridWidth = e.svgWidth, e.translateY = r - 10, e.translateX = o + (e.svgWidth - e.gridWidth) / 2; break; case "top": e.gridHeight = e.svgHeight - this.lgRect.height - e.goldenPadding, e.gridWidth = e.svgWidth, e.translateY = this.lgRect.height + r + 10, e.translateX = o + (e.svgWidth - e.gridWidth) / 2; break; case "left": e.gridWidth = e.svgWidth - this.lgRect.width - a, e.gridHeight = "auto" !== i.chart.height ? e.svgHeight : e.gridWidth, e.translateY = r, e.translateX = o + this.lgRect.width + a; break; case "right": e.gridWidth = e.svgWidth - this.lgRect.width - a - 5, e.gridHeight = "auto" !== i.chart.height ? e.svgHeight : e.gridWidth, e.translateY = r, e.translateX = o + 10; break; default: throw new Error("Legend position not supported") } } }, { key: "conditionalChecksForAxisCoords", value: function (t, e, i) { var a = this.w, s = a.globals.hasXaxisGroups ? 2 : 1, r = i.height + t.height + e.height, o = a.globals.isMultiLineX ? 1.2 : a.globals.LINE_HEIGHT_RATIO, n = a.globals.rotateXLabels ? 22 : 10, l = a.globals.rotateXLabels && "bottom" === a.config.legend.position ? 10 : 0; this.xAxisHeight = r * o + s * n + l, this.xAxisWidth = t.width, this.xAxisHeight - e.height > a.config.xaxis.labels.maxHeight && (this.xAxisHeight = a.config.xaxis.labels.maxHeight), a.config.xaxis.labels.minHeight && this.xAxisHeight < a.config.xaxis.labels.minHeight && (this.xAxisHeight = a.config.xaxis.labels.minHeight), a.config.xaxis.floating && (this.xAxisHeight = 0); var h = 0, c = 0; a.config.yaxis.forEach((function (t) { h += t.labels.minWidth, c += t.labels.maxWidth })), this.yAxisWidth < h && (this.yAxisWidth = h), this.yAxisWidth > c && (this.yAxisWidth = c) } }]), t }(), nt = function () { function t(e) { a(this, t), this.w = e.w, this.lgCtx = e } return r(t, [{ key: "getLegendStyles", value: function () { var t, e, i, a = document.createElement("style"); a.setAttribute("type", "text/css"); var s = (null === (t = this.lgCtx.ctx) || void 0 === t || null === (e = t.opts) || void 0 === e || null === (i = e.chart) || void 0 === i ? void 0 : i.nonce) || this.w.config.chart.nonce; s && a.setAttribute("nonce", s); var r = document.createTextNode("\n .apexcharts-legend {\n display: flex;\n overflow: auto;\n padding: 0 10px;\n }\n .apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top {\n flex-wrap: wrap\n }\n .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\n flex-direction: column;\n bottom: 0;\n }\n .apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\n justify-content: flex-start;\n }\n .apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center {\n justify-content: center;\n }\n .apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right {\n justify-content: flex-end;\n }\n .apexcharts-legend-series {\n cursor: pointer;\n line-height: normal;\n }\n .apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series, .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series{\n display: flex;\n align-items: center;\n }\n .apexcharts-legend-text {\n position: relative;\n font-size: 14px;\n }\n .apexcharts-legend-text *, .apexcharts-legend-marker * {\n pointer-events: none;\n }\n .apexcharts-legend-marker {\n position: relative;\n display: inline-block;\n cursor: pointer;\n margin-right: 3px;\n border-style: solid;\n }\n\n .apexcharts-legend.apexcharts-align-right .apexcharts-legend-series, .apexcharts-legend.apexcharts-align-left .apexcharts-legend-series{\n display: inline-block;\n }\n .apexcharts-legend-series.apexcharts-no-click {\n cursor: auto;\n }\n .apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {\n display: none !important;\n }\n .apexcharts-inactive-legend {\n opacity: 0.45;\n }"); return a.appendChild(r), a } }, { key: "getLegendBBox", value: function () { var t = this.w.globals.dom.baseEl.querySelector(".apexcharts-legend").getBoundingClientRect(), e = t.width; return { clwh: t.height, clww: e } } }, { key: "appendToForeignObject", value: function () { this.w.globals.dom.elLegendForeign.appendChild(this.getLegendStyles()) } }, { key: "toggleDataSeries", value: function (t, e) { var i = this, a = this.w; if (a.globals.axisCharts || "radialBar" === a.config.chart.type) { a.globals.resized = !0; var s = null, r = null; if (a.globals.risingSeries = [], a.globals.axisCharts ? (s = a.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(t, "']")), r = parseInt(s.getAttribute("data:realIndex"), 10)) : (s = a.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(t + 1, "']")), r = parseInt(s.getAttribute("rel"), 10) - 1), e) [{ cs: a.globals.collapsedSeries, csi: a.globals.collapsedSeriesIndices }, { cs: a.globals.ancillaryCollapsedSeries, csi: a.globals.ancillaryCollapsedSeriesIndices }].forEach((function (t) { i.riseCollapsedSeries(t.cs, t.csi, r) })); else this.hideSeries({ seriesEl: s, realIndex: r }) } else { var o = a.globals.dom.Paper.select(" .apexcharts-series[rel='".concat(t + 1, "'] path")), n = a.config.chart.type; if ("pie" === n || "polarArea" === n || "donut" === n) { var l = a.config.plotOptions.pie.donut.labels; new m(this.lgCtx.ctx).pathMouseDown(o.members[0], null), this.lgCtx.ctx.pie.printDataLabelsInner(o.members[0].node, l) } o.fire("click") } } }, { key: "hideSeries", value: function (t) { var e = t.seriesEl, i = t.realIndex, a = this.w, s = a.globals, r = x.clone(a.config.series); if (s.axisCharts) { var o = a.config.yaxis[s.seriesYAxisReverseMap[i]]; if (o && o.show && o.showAlways) s.ancillaryCollapsedSeriesIndices.indexOf(i) < 0 && (s.ancillaryCollapsedSeries.push({ index: i, data: r[i].data.slice(), type: e.parentNode.className.baseVal.split("-")[1] }), s.ancillaryCollapsedSeriesIndices.push(i)); else if (s.collapsedSeriesIndices.indexOf(i) < 0) { s.collapsedSeries.push({ index: i, data: r[i].data.slice(), type: e.parentNode.className.baseVal.split("-")[1] }), s.collapsedSeriesIndices.push(i); var n = s.risingSeries.indexOf(i); s.risingSeries.splice(n, 1) } } else s.collapsedSeries.push({ index: i, data: r[i] }), s.collapsedSeriesIndices.push(i); for (var l = e.childNodes, h = 0; h < l.length; h++)l[h].classList.contains("apexcharts-series-markers-wrap") && (l[h].classList.contains("apexcharts-hide") ? l[h].classList.remove("apexcharts-hide") : l[h].classList.add("apexcharts-hide")); s.allSeriesCollapsed = s.collapsedSeries.length + s.ancillaryCollapsedSeries.length === a.config.series.length, r = this._getSeriesBasedOnCollapsedState(r), this.lgCtx.ctx.updateHelpers._updateSeries(r, a.config.chart.animations.dynamicAnimation.enabled) } }, { key: "riseCollapsedSeries", value: function (t, e, i) { var a = this.w, s = x.clone(a.config.series); if (t.length > 0) { for (var r = 0; r < t.length; r++)t[r].index === i && (a.globals.axisCharts ? (s[i].data = t[r].data.slice(), t.splice(r, 1), e.splice(r, 1), a.globals.risingSeries.push(i)) : (s[i] = t[r].data, t.splice(r, 1), e.splice(r, 1), a.globals.risingSeries.push(i))); s = this._getSeriesBasedOnCollapsedState(s), this.lgCtx.ctx.updateHelpers._updateSeries(s, a.config.chart.animations.dynamicAnimation.enabled) } } }, { key: "_getSeriesBasedOnCollapsedState", value: function (t) { var e = this.w, i = 0; return e.globals.axisCharts ? t.forEach((function (a, s) { e.globals.collapsedSeriesIndices.indexOf(s) < 0 && e.globals.ancillaryCollapsedSeriesIndices.indexOf(s) < 0 || (t[s].data = [], i++) })) : t.forEach((function (a, s) { !e.globals.collapsedSeriesIndices.indexOf(s) < 0 && (t[s] = 0, i++) })), e.globals.allSeriesCollapsed = i === t.length, t } }]), t }(), lt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.onLegendClick = this.onLegendClick.bind(this), this.onLegendHovered = this.onLegendHovered.bind(this), this.isBarsDistributed = "bar" === this.w.config.chart.type && this.w.config.plotOptions.bar.distributed && 1 === this.w.config.series.length, this.legendHelpers = new nt(this) } return r(t, [{ key: "init", value: function () { var t = this.w, e = t.globals, i = t.config; if ((i.legend.showForSingleSeries && 1 === e.series.length || this.isBarsDistributed || e.series.length > 1 || !e.axisCharts) && i.legend.show) { for (; e.dom.elLegendWrap.firstChild;)e.dom.elLegendWrap.removeChild(e.dom.elLegendWrap.firstChild); this.drawLegends(), x.isIE11() ? document.getElementsByTagName("head")[0].appendChild(this.legendHelpers.getLegendStyles()) : this.legendHelpers.appendToForeignObject(), "bottom" === i.legend.position || "top" === i.legend.position ? this.legendAlignHorizontal() : "right" !== i.legend.position && "left" !== i.legend.position || this.legendAlignVertical() } } }, { key: "drawLegends", value: function () { var t = this, e = this.w, i = e.config.legend.fontFamily, a = e.globals.seriesNames, s = e.globals.colors.slice(); if ("heatmap" === e.config.chart.type) { var r = e.config.plotOptions.heatmap.colorScale.ranges; a = r.map((function (t) { return t.name ? t.name : t.from + " - " + t.to })), s = r.map((function (t) { return t.color })) } else this.isBarsDistributed && (a = e.globals.labels.slice()); e.config.legend.customLegendItems.length && (a = e.config.legend.customLegendItems); for (var o = e.globals.legendFormatter, n = e.config.legend.inverseOrder, l = n ? a.length - 1 : 0; n ? l >= 0 : l <= a.length - 1; n ? l-- : l++) { var h, c = o(a[l], { seriesIndex: l, w: e }), d = !1, g = !1; if (e.globals.collapsedSeries.length > 0) for (var u = 0; u < e.globals.collapsedSeries.length; u++)e.globals.collapsedSeries[u].index === l && (d = !0); if (e.globals.ancillaryCollapsedSeriesIndices.length > 0) for (var p = 0; p < e.globals.ancillaryCollapsedSeriesIndices.length; p++)e.globals.ancillaryCollapsedSeriesIndices[p] === l && (g = !0); var f = document.createElement("span"); f.classList.add("apexcharts-legend-marker"); var b = e.config.legend.markers.offsetX, v = e.config.legend.markers.offsetY, w = e.config.legend.markers.height, k = e.config.legend.markers.width, A = e.config.legend.markers.strokeWidth, S = e.config.legend.markers.strokeColor, C = e.config.legend.markers.radius, L = f.style; L.background = s[l], L.color = s[l], L.setProperty("background", s[l], "important"), e.config.legend.markers.fillColors && e.config.legend.markers.fillColors[l] && (L.background = e.config.legend.markers.fillColors[l]), void 0 !== e.globals.seriesColors[l] && (L.background = e.globals.seriesColors[l], L.color = e.globals.seriesColors[l]), L.height = Array.isArray(w) ? parseFloat(w[l]) + "px" : parseFloat(w) + "px", L.width = Array.isArray(k) ? parseFloat(k[l]) + "px" : parseFloat(k) + "px", L.left = (Array.isArray(b) ? parseFloat(b[l]) : parseFloat(b)) + "px", L.top = (Array.isArray(v) ? parseFloat(v[l]) : parseFloat(v)) + "px", L.borderWidth = Array.isArray(A) ? A[l] : A, L.borderColor = Array.isArray(S) ? S[l] : S, L.borderRadius = Array.isArray(C) ? parseFloat(C[l]) + "px" : parseFloat(C) + "px", e.config.legend.markers.customHTML && (Array.isArray(e.config.legend.markers.customHTML) ? e.config.legend.markers.customHTML[l] && (f.innerHTML = e.config.legend.markers.customHTML[l]()) : f.innerHTML = e.config.legend.markers.customHTML()), m.setAttrs(f, { rel: l + 1, "data:collapsed": d || g }), (d || g) && f.classList.add("apexcharts-inactive-legend"); var P = document.createElement("div"), M = document.createElement("span"); M.classList.add("apexcharts-legend-text"), M.innerHTML = Array.isArray(c) ? c.join(" ") : c; var I = e.config.legend.labels.useSeriesColors ? e.globals.colors[l] : Array.isArray(e.config.legend.labels.colors) ? null === (h = e.config.legend.labels.colors) || void 0 === h ? void 0 : h[l] : e.config.legend.labels.colors; I || (I = e.config.chart.foreColor), M.style.color = I, M.style.fontSize = parseFloat(e.config.legend.fontSize) + "px", M.style.fontWeight = e.config.legend.fontWeight, M.style.fontFamily = i || e.config.chart.fontFamily, m.setAttrs(M, { rel: l + 1, i: l, "data:default-text": encodeURIComponent(c), "data:collapsed": d || g }), P.appendChild(f), P.appendChild(M); var T = new y(this.ctx); if (!e.config.legend.showForZeroSeries) 0 === T.getSeriesTotalByIndex(l) && T.seriesHaveSameValues(l) && !T.isSeriesNull(l) && -1 === e.globals.collapsedSeriesIndices.indexOf(l) && -1 === e.globals.ancillaryCollapsedSeriesIndices.indexOf(l) && P.classList.add("apexcharts-hidden-zero-series"); e.config.legend.showForNullSeries || T.isSeriesNull(l) && -1 === e.globals.collapsedSeriesIndices.indexOf(l) && -1 === e.globals.ancillaryCollapsedSeriesIndices.indexOf(l) && P.classList.add("apexcharts-hidden-null-series"), e.globals.dom.elLegendWrap.appendChild(P), e.globals.dom.elLegendWrap.classList.add("apexcharts-align-".concat(e.config.legend.horizontalAlign)), e.globals.dom.elLegendWrap.classList.add("apx-legend-position-" + e.config.legend.position), P.classList.add("apexcharts-legend-series"), P.style.margin = "".concat(e.config.legend.itemMargin.vertical, "px ").concat(e.config.legend.itemMargin.horizontal, "px"), e.globals.dom.elLegendWrap.style.width = e.config.legend.width ? e.config.legend.width + "px" : "", e.globals.dom.elLegendWrap.style.height = e.config.legend.height ? e.config.legend.height + "px" : "", m.setAttrs(P, { rel: l + 1, seriesName: x.escapeString(a[l]), "data:collapsed": d || g }), (d || g) && P.classList.add("apexcharts-inactive-legend"), e.config.legend.onItemClick.toggleDataSeries || P.classList.add("apexcharts-no-click") } e.globals.dom.elWrap.addEventListener("click", t.onLegendClick, !0), e.config.legend.onItemHover.highlightDataSeries && 0 === e.config.legend.customLegendItems.length && (e.globals.dom.elWrap.addEventListener("mousemove", t.onLegendHovered, !0), e.globals.dom.elWrap.addEventListener("mouseout", t.onLegendHovered, !0)) } }, { key: "setLegendWrapXY", value: function (t, e) { var i = this.w, a = i.globals.dom.elLegendWrap, s = a.getBoundingClientRect(), r = 0, o = 0; if ("bottom" === i.config.legend.position) o += i.globals.svgHeight - s.height / 2; else if ("top" === i.config.legend.position) { var n = new ot(this.ctx), l = n.dimHelpers.getTitleSubtitleCoords("title").height, h = n.dimHelpers.getTitleSubtitleCoords("subtitle").height; o = o + (l > 0 ? l - 10 : 0) + (h > 0 ? h - 10 : 0) } a.style.position = "absolute", r = r + t + i.config.legend.offsetX, o = o + e + i.config.legend.offsetY, a.style.left = r + "px", a.style.top = o + "px", "bottom" === i.config.legend.position ? (a.style.top = "auto", a.style.bottom = 5 - i.config.legend.offsetY + "px") : "right" === i.config.legend.position && (a.style.left = "auto", a.style.right = 25 + i.config.legend.offsetX + "px");["width", "height"].forEach((function (t) { a.style[t] && (a.style[t] = parseInt(i.config.legend[t], 10) + "px") })) } }, { key: "legendAlignHorizontal", value: function () { var t = this.w; t.globals.dom.elLegendWrap.style.right = 0; var e = this.legendHelpers.getLegendBBox(), i = new ot(this.ctx), a = i.dimHelpers.getTitleSubtitleCoords("title"), s = i.dimHelpers.getTitleSubtitleCoords("subtitle"), r = 0; "bottom" === t.config.legend.position ? r = -e.clwh / 1.8 : "top" === t.config.legend.position && (r = a.height + s.height + t.config.title.margin + t.config.subtitle.margin - 10), this.setLegendWrapXY(20, r) } }, { key: "legendAlignVertical", value: function () { var t = this.w, e = this.legendHelpers.getLegendBBox(), i = 0; "left" === t.config.legend.position && (i = 20), "right" === t.config.legend.position && (i = t.globals.svgWidth - e.clww - 10), this.setLegendWrapXY(i, 20) } }, { key: "onLegendHovered", value: function (t) { var e = this.w, i = t.target.classList.contains("apexcharts-legend-series") || t.target.classList.contains("apexcharts-legend-text") || t.target.classList.contains("apexcharts-legend-marker"); if ("heatmap" === e.config.chart.type || this.isBarsDistributed) { if (i) { var a = parseInt(t.target.getAttribute("rel"), 10) - 1; this.ctx.events.fireEvent("legendHover", [this.ctx, a, this.w]), new W(this.ctx).highlightRangeInSeries(t, t.target) } } else !t.target.classList.contains("apexcharts-inactive-legend") && i && new W(this.ctx).toggleSeriesOnHover(t, t.target) } }, { key: "onLegendClick", value: function (t) { var e = this.w; if (!e.config.legend.customLegendItems.length && (t.target.classList.contains("apexcharts-legend-series") || t.target.classList.contains("apexcharts-legend-text") || t.target.classList.contains("apexcharts-legend-marker"))) { var i = parseInt(t.target.getAttribute("rel"), 10) - 1, a = "true" === t.target.getAttribute("data:collapsed"), s = this.w.config.chart.events.legendClick; "function" == typeof s && s(this.ctx, i, this.w), this.ctx.events.fireEvent("legendClick", [this.ctx, i, this.w]); var r = this.w.config.legend.markers.onClick; "function" == typeof r && t.target.classList.contains("apexcharts-legend-marker") && (r(this.ctx, i, this.w), this.ctx.events.fireEvent("legendMarkerClick", [this.ctx, i, this.w])), "treemap" !== e.config.chart.type && "heatmap" !== e.config.chart.type && !this.isBarsDistributed && e.config.legend.onItemClick.toggleDataSeries && this.legendHelpers.toggleDataSeries(i, a) } } }]), t }(), ht = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w; var i = this.w; this.ev = this.w.config.chart.events, this.selectedClass = "apexcharts-selected", this.localeValues = this.w.globals.locale.toolbar, this.minX = i.globals.minX, this.maxX = i.globals.maxX } return r(t, [{ key: "createToolbar", value: function () { var t = this, e = this.w, i = function () { return document.createElement("div") }, a = i(); if (a.setAttribute("class", "apexcharts-toolbar"), a.style.top = e.config.chart.toolbar.offsetY + "px", a.style.right = 3 - e.config.chart.toolbar.offsetX + "px", e.globals.dom.elWrap.appendChild(a), this.elZoom = i(), this.elZoomIn = i(), this.elZoomOut = i(), this.elPan = i(), this.elSelection = i(), this.elZoomReset = i(), this.elMenuIcon = i(), this.elMenu = i(), this.elCustomIcons = [], this.t = e.config.chart.toolbar.tools, Array.isArray(this.t.customIcons)) for (var s = 0; s < this.t.customIcons.length; s++)this.elCustomIcons.push(i()); var r = [], o = function (i, a, s) { var o = i.toLowerCase(); t.t[o] && e.config.chart.zoom.enabled && r.push({ el: a, icon: "string" == typeof t.t[o] ? t.t[o] : s, title: t.localeValues[i], class: "apexcharts-".concat(o, "-icon") }) }; o("zoomIn", this.elZoomIn, '\n \n \n\n'), o("zoomOut", this.elZoomOut, '\n \n \n\n'); var n = function (i) { t.t[i] && e.config.chart[i].enabled && r.push({ el: "zoom" === i ? t.elZoom : t.elSelection, icon: "string" == typeof t.t[i] ? t.t[i] : "zoom" === i ? '\n \n \n \n' : '\n \n \n', title: t.localeValues["zoom" === i ? "selectionZoom" : "selection"], class: e.globals.isTouchDevice ? "apexcharts-element-hidden" : "apexcharts-".concat(i, "-icon") }) }; n("zoom"), n("selection"), this.t.pan && e.config.chart.zoom.enabled && r.push({ el: this.elPan, icon: "string" == typeof this.t.pan ? this.t.pan : '\n \n \n \n \n \n \n \n', title: this.localeValues.pan, class: e.globals.isTouchDevice ? "apexcharts-element-hidden" : "apexcharts-pan-icon" }), o("reset", this.elZoomReset, '\n \n \n'), this.t.download && r.push({ el: this.elMenuIcon, icon: "string" == typeof this.t.download ? this.t.download : '', title: this.localeValues.menu, class: "apexcharts-menu-icon" }); for (var l = 0; l < this.elCustomIcons.length; l++)r.push({ el: this.elCustomIcons[l], icon: this.t.customIcons[l].icon, title: this.t.customIcons[l].title, index: this.t.customIcons[l].index, class: "apexcharts-toolbar-custom-icon " + this.t.customIcons[l].class }); r.forEach((function (t, e) { t.index && x.moveIndexInArray(r, e, t.index) })); for (var h = 0; h < r.length; h++)m.setAttrs(r[h].el, { class: r[h].class, title: r[h].title }), r[h].el.innerHTML = r[h].icon, a.appendChild(r[h].el); this._createHamburgerMenu(a), e.globals.zoomEnabled ? this.elZoom.classList.add(this.selectedClass) : e.globals.panEnabled ? this.elPan.classList.add(this.selectedClass) : e.globals.selectionEnabled && this.elSelection.classList.add(this.selectedClass), this.addToolbarEventListeners() } }, { key: "_createHamburgerMenu", value: function (t) { this.elMenuItems = [], t.appendChild(this.elMenu), m.setAttrs(this.elMenu, { class: "apexcharts-menu" }); for (var e = [{ name: "exportSVG", title: this.localeValues.exportToSVG }, { name: "exportPNG", title: this.localeValues.exportToPNG }, { name: "exportCSV", title: this.localeValues.exportToCSV }], i = 0; i < e.length; i++)this.elMenuItems.push(document.createElement("div")), this.elMenuItems[i].innerHTML = e[i].title, m.setAttrs(this.elMenuItems[i], { class: "apexcharts-menu-item ".concat(e[i].name), title: e[i].title }), this.elMenu.appendChild(this.elMenuItems[i]) } }, { key: "addToolbarEventListeners", value: function () { var t = this; this.elZoomReset.addEventListener("click", this.handleZoomReset.bind(this)), this.elSelection.addEventListener("click", this.toggleZoomSelection.bind(this, "selection")), this.elZoom.addEventListener("click", this.toggleZoomSelection.bind(this, "zoom")), this.elZoomIn.addEventListener("click", this.handleZoomIn.bind(this)), this.elZoomOut.addEventListener("click", this.handleZoomOut.bind(this)), this.elPan.addEventListener("click", this.togglePanning.bind(this)), this.elMenuIcon.addEventListener("click", this.toggleMenu.bind(this)), this.elMenuItems.forEach((function (e) { e.classList.contains("exportSVG") ? e.addEventListener("click", t.handleDownload.bind(t, "svg")) : e.classList.contains("exportPNG") ? e.addEventListener("click", t.handleDownload.bind(t, "png")) : e.classList.contains("exportCSV") && e.addEventListener("click", t.handleDownload.bind(t, "csv")) })); for (var e = 0; e < this.t.customIcons.length; e++)this.elCustomIcons[e].addEventListener("click", this.t.customIcons[e].click.bind(this, this.ctx, this.ctx.w)) } }, { key: "toggleZoomSelection", value: function (t) { this.ctx.getSyncedCharts().forEach((function (e) { e.ctx.toolbar.toggleOtherControls(); var i = "selection" === t ? e.ctx.toolbar.elSelection : e.ctx.toolbar.elZoom, a = "selection" === t ? "selectionEnabled" : "zoomEnabled"; e.w.globals[a] = !e.w.globals[a], i.classList.contains(e.ctx.toolbar.selectedClass) ? i.classList.remove(e.ctx.toolbar.selectedClass) : i.classList.add(e.ctx.toolbar.selectedClass) })) } }, { key: "getToolbarIconsReference", value: function () { var t = this.w; this.elZoom || (this.elZoom = t.globals.dom.baseEl.querySelector(".apexcharts-zoom-icon")), this.elPan || (this.elPan = t.globals.dom.baseEl.querySelector(".apexcharts-pan-icon")), this.elSelection || (this.elSelection = t.globals.dom.baseEl.querySelector(".apexcharts-selection-icon")) } }, { key: "enableZoomPanFromToolbar", value: function (t) { this.toggleOtherControls(), "pan" === t ? this.w.globals.panEnabled = !0 : this.w.globals.zoomEnabled = !0; var e = "pan" === t ? this.elPan : this.elZoom, i = "pan" === t ? this.elZoom : this.elPan; e && e.classList.add(this.selectedClass), i && i.classList.remove(this.selectedClass) } }, { key: "togglePanning", value: function () { this.ctx.getSyncedCharts().forEach((function (t) { t.ctx.toolbar.toggleOtherControls(), t.w.globals.panEnabled = !t.w.globals.panEnabled, t.ctx.toolbar.elPan.classList.contains(t.ctx.toolbar.selectedClass) ? t.ctx.toolbar.elPan.classList.remove(t.ctx.toolbar.selectedClass) : t.ctx.toolbar.elPan.classList.add(t.ctx.toolbar.selectedClass) })) } }, { key: "toggleOtherControls", value: function () { var t = this, e = this.w; e.globals.panEnabled = !1, e.globals.zoomEnabled = !1, e.globals.selectionEnabled = !1, this.getToolbarIconsReference(), [this.elPan, this.elSelection, this.elZoom].forEach((function (e) { e && e.classList.remove(t.selectedClass) })) } }, { key: "handleZoomIn", value: function () { var t = this.w; t.globals.isRangeBar && (this.minX = t.globals.minY, this.maxX = t.globals.maxY); var e = (this.minX + this.maxX) / 2, i = (this.minX + e) / 2, a = (this.maxX + e) / 2, s = this._getNewMinXMaxX(i, a); t.globals.disableZoomIn || this.zoomUpdateOptions(s.minX, s.maxX) } }, { key: "handleZoomOut", value: function () { var t = this.w; if (t.globals.isRangeBar && (this.minX = t.globals.minY, this.maxX = t.globals.maxY), !("datetime" === t.config.xaxis.type && new Date(this.minX).getUTCFullYear() < 1e3)) { var e = (this.minX + this.maxX) / 2, i = this.minX - (e - this.minX), a = this.maxX - (e - this.maxX), s = this._getNewMinXMaxX(i, a); t.globals.disableZoomOut || this.zoomUpdateOptions(s.minX, s.maxX) } } }, { key: "_getNewMinXMaxX", value: function (t, e) { var i = this.w.config.xaxis.convertedCatToNumeric; return { minX: i ? Math.floor(t) : t, maxX: i ? Math.floor(e) : e } } }, { key: "zoomUpdateOptions", value: function (t, e) { var i = this.w; if (void 0 !== t || void 0 !== e) { if (!(i.config.xaxis.convertedCatToNumeric && (t < 1 && (t = 1, e = i.globals.dataPoints), e - t < 2))) { var a = { min: t, max: e }, s = this.getBeforeZoomRange(a); s && (a = s.xaxis); var r = { xaxis: a }, o = x.clone(i.globals.initialConfig.yaxis); i.config.chart.group || (r.yaxis = o), this.w.globals.zoomed = !0, this.ctx.updateHelpers._updateOptions(r, !1, this.w.config.chart.animations.dynamicAnimation.enabled), this.zoomCallback(a, o) } } else this.handleZoomReset() } }, { key: "zoomCallback", value: function (t, e) { "function" == typeof this.ev.zoomed && this.ev.zoomed(this.ctx, { xaxis: t, yaxis: e }) } }, { key: "getBeforeZoomRange", value: function (t, e) { var i = null; return "function" == typeof this.ev.beforeZoom && (i = this.ev.beforeZoom(this, { xaxis: t, yaxis: e })), i } }, { key: "toggleMenu", value: function () { var t = this; window.setTimeout((function () { t.elMenu.classList.contains("apexcharts-menu-open") ? t.elMenu.classList.remove("apexcharts-menu-open") : t.elMenu.classList.add("apexcharts-menu-open") }), 0) } }, { key: "handleDownload", value: function (t) { var e = this.w, i = new G(this.ctx); switch (t) { case "svg": i.exportToSVG(this.ctx); break; case "png": i.exportToPng(this.ctx); break; case "csv": i.exportToCSV({ series: e.config.series, columnDelimiter: e.config.chart.toolbar.export.csv.columnDelimiter }) } } }, { key: "handleZoomReset", value: function (t) { this.ctx.getSyncedCharts().forEach((function (t) { var e = t.w; if (e.globals.lastXAxis.min = e.globals.initialConfig.xaxis.min, e.globals.lastXAxis.max = e.globals.initialConfig.xaxis.max, t.updateHelpers.revertDefaultAxisMinMax(), "function" == typeof e.config.chart.events.beforeResetZoom) { var i = e.config.chart.events.beforeResetZoom(t, e); i && t.updateHelpers.revertDefaultAxisMinMax(i) } "function" == typeof e.config.chart.events.zoomed && t.ctx.toolbar.zoomCallback({ min: e.config.xaxis.min, max: e.config.xaxis.max }), e.globals.zoomed = !1; var a = t.ctx.series.emptyCollapsedSeries(x.clone(e.globals.initialSeries)); t.updateHelpers._updateSeries(a, e.config.chart.animations.dynamicAnimation.enabled) })) } }, { key: "destroy", value: function () { this.elZoom = null, this.elZoomIn = null, this.elZoomOut = null, this.elPan = null, this.elSelection = null, this.elZoomReset = null, this.elMenuIcon = null } }]), t }(), ct = function (t) { n(i, t); var e = d(i); function i(t) { var s; return a(this, i), (s = e.call(this, t)).ctx = t, s.w = t.w, s.dragged = !1, s.graphics = new m(s.ctx), s.eventList = ["mousedown", "mouseleave", "mousemove", "touchstart", "touchmove", "mouseup", "touchend"], s.clientX = 0, s.clientY = 0, s.startX = 0, s.endX = 0, s.dragX = 0, s.startY = 0, s.endY = 0, s.dragY = 0, s.moveDirection = "none", s } return r(i, [{ key: "init", value: function (t) { var e = this, i = t.xyRatios, a = this.w, s = this; this.xyRatios = i, this.zoomRect = this.graphics.drawRect(0, 0, 0, 0), this.selectionRect = this.graphics.drawRect(0, 0, 0, 0), this.gridRect = a.globals.dom.baseEl.querySelector(".apexcharts-grid"), this.zoomRect.node.classList.add("apexcharts-zoom-rect"), this.selectionRect.node.classList.add("apexcharts-selection-rect"), a.globals.dom.elGraphical.add(this.zoomRect), a.globals.dom.elGraphical.add(this.selectionRect), "x" === a.config.chart.selection.type ? this.slDraggableRect = this.selectionRect.draggable({ minX: 0, minY: 0, maxX: a.globals.gridWidth, maxY: a.globals.gridHeight }).on("dragmove", this.selectionDragging.bind(this, "dragging")) : "y" === a.config.chart.selection.type ? this.slDraggableRect = this.selectionRect.draggable({ minX: 0, maxX: a.globals.gridWidth }).on("dragmove", this.selectionDragging.bind(this, "dragging")) : this.slDraggableRect = this.selectionRect.draggable().on("dragmove", this.selectionDragging.bind(this, "dragging")), this.preselectedSelection(), this.hoverArea = a.globals.dom.baseEl.querySelector("".concat(a.globals.chartClass, " .apexcharts-svg")), this.hoverArea.classList.add("apexcharts-zoomable"), this.eventList.forEach((function (t) { e.hoverArea.addEventListener(t, s.svgMouseEvents.bind(s, i), { capture: !1, passive: !0 }) })) } }, { key: "destroy", value: function () { this.slDraggableRect && (this.slDraggableRect.draggable(!1), this.slDraggableRect.off(), this.selectionRect.off()), this.selectionRect = null, this.zoomRect = null, this.gridRect = null } }, { key: "svgMouseEvents", value: function (t, e) { var i = this.w, a = this, s = this.ctx.toolbar, r = i.globals.zoomEnabled ? i.config.chart.zoom.type : i.config.chart.selection.type, o = i.config.chart.toolbar.autoSelected; if (e.shiftKey ? (this.shiftWasPressed = !0, s.enableZoomPanFromToolbar("pan" === o ? "zoom" : "pan")) : this.shiftWasPressed && (s.enableZoomPanFromToolbar(o), this.shiftWasPressed = !1), e.target) { var n, l = e.target.classList; if (e.target.parentNode && null !== e.target.parentNode && (n = e.target.parentNode.classList), !(l.contains("apexcharts-selection-rect") || l.contains("apexcharts-legend-marker") || l.contains("apexcharts-legend-text") || n && n.contains("apexcharts-toolbar"))) { if (a.clientX = "touchmove" === e.type || "touchstart" === e.type ? e.touches[0].clientX : "touchend" === e.type ? e.changedTouches[0].clientX : e.clientX, a.clientY = "touchmove" === e.type || "touchstart" === e.type ? e.touches[0].clientY : "touchend" === e.type ? e.changedTouches[0].clientY : e.clientY, "mousedown" === e.type && 1 === e.which) { var h = a.gridRect.getBoundingClientRect(); a.startX = a.clientX - h.left, a.startY = a.clientY - h.top, a.dragged = !1, a.w.globals.mousedown = !0 } if (("mousemove" === e.type && 1 === e.which || "touchmove" === e.type) && (a.dragged = !0, i.globals.panEnabled ? (i.globals.selection = null, a.w.globals.mousedown && a.panDragging({ context: a, zoomtype: r, xyRatios: t })) : (a.w.globals.mousedown && i.globals.zoomEnabled || a.w.globals.mousedown && i.globals.selectionEnabled) && (a.selection = a.selectionDrawing({ context: a, zoomtype: r }))), "mouseup" === e.type || "touchend" === e.type || "mouseleave" === e.type) { var c = a.gridRect.getBoundingClientRect(); a.w.globals.mousedown && (a.endX = a.clientX - c.left, a.endY = a.clientY - c.top, a.dragX = Math.abs(a.endX - a.startX), a.dragY = Math.abs(a.endY - a.startY), (i.globals.zoomEnabled || i.globals.selectionEnabled) && a.selectionDrawn({ context: a, zoomtype: r }), i.globals.panEnabled && i.config.xaxis.convertedCatToNumeric && a.delayedPanScrolled()), i.globals.zoomEnabled && a.hideSelectionRect(this.selectionRect), a.dragged = !1, a.w.globals.mousedown = !1 } this.makeSelectionRectDraggable() } } } }, { key: "makeSelectionRectDraggable", value: function () { var t = this.w; if (this.selectionRect) { var e = this.selectionRect.node.getBoundingClientRect(); e.width > 0 && e.height > 0 && this.slDraggableRect.selectize({ points: "l, r", pointSize: 8, pointType: "rect" }).resize({ constraint: { minX: 0, minY: 0, maxX: t.globals.gridWidth, maxY: t.globals.gridHeight } }).on("resizing", this.selectionDragging.bind(this, "resizing")) } } }, { key: "preselectedSelection", value: function () { var t = this.w, e = this.xyRatios; if (!t.globals.zoomEnabled) if (void 0 !== t.globals.selection && null !== t.globals.selection) this.drawSelectionRect(t.globals.selection); else if (void 0 !== t.config.chart.selection.xaxis.min && void 0 !== t.config.chart.selection.xaxis.max) { var i = (t.config.chart.selection.xaxis.min - t.globals.minX) / e.xRatio, a = t.globals.gridWidth - (t.globals.maxX - t.config.chart.selection.xaxis.max) / e.xRatio - i; t.globals.isRangeBar && (i = (t.config.chart.selection.xaxis.min - t.globals.yAxisScale[0].niceMin) / e.invertedYRatio, a = (t.config.chart.selection.xaxis.max - t.config.chart.selection.xaxis.min) / e.invertedYRatio); var s = { x: i, y: 0, width: a, height: t.globals.gridHeight, translateX: 0, translateY: 0, selectionEnabled: !0 }; this.drawSelectionRect(s), this.makeSelectionRectDraggable(), "function" == typeof t.config.chart.events.selection && t.config.chart.events.selection(this.ctx, { xaxis: { min: t.config.chart.selection.xaxis.min, max: t.config.chart.selection.xaxis.max }, yaxis: {} }) } } }, { key: "drawSelectionRect", value: function (t) { var e = t.x, i = t.y, a = t.width, s = t.height, r = t.translateX, o = void 0 === r ? 0 : r, n = t.translateY, l = void 0 === n ? 0 : n, h = this.w, c = this.zoomRect, d = this.selectionRect; if (this.dragged || null !== h.globals.selection) { var g = { transform: "translate(" + o + ", " + l + ")" }; h.globals.zoomEnabled && this.dragged && (a < 0 && (a = 1), c.attr({ x: e, y: i, width: a, height: s, fill: h.config.chart.zoom.zoomedArea.fill.color, "fill-opacity": h.config.chart.zoom.zoomedArea.fill.opacity, stroke: h.config.chart.zoom.zoomedArea.stroke.color, "stroke-width": h.config.chart.zoom.zoomedArea.stroke.width, "stroke-opacity": h.config.chart.zoom.zoomedArea.stroke.opacity }), m.setAttrs(c.node, g)), h.globals.selectionEnabled && (d.attr({ x: e, y: i, width: a > 0 ? a : 0, height: s > 0 ? s : 0, fill: h.config.chart.selection.fill.color, "fill-opacity": h.config.chart.selection.fill.opacity, stroke: h.config.chart.selection.stroke.color, "stroke-width": h.config.chart.selection.stroke.width, "stroke-dasharray": h.config.chart.selection.stroke.dashArray, "stroke-opacity": h.config.chart.selection.stroke.opacity }), m.setAttrs(d.node, g)) } } }, { key: "hideSelectionRect", value: function (t) { t && t.attr({ x: 0, y: 0, width: 0, height: 0 }) } }, { key: "selectionDrawing", value: function (t) { var e = t.context, i = t.zoomtype, a = this.w, s = e, r = this.gridRect.getBoundingClientRect(), o = s.startX - 1, n = s.startY, l = !1, h = !1, c = s.clientX - r.left - o, d = s.clientY - r.top - n, g = {}; return Math.abs(c + o) > a.globals.gridWidth ? c = a.globals.gridWidth - o : s.clientX - r.left < 0 && (c = o), o > s.clientX - r.left && (l = !0, c = Math.abs(c)), n > s.clientY - r.top && (h = !0, d = Math.abs(d)), g = "x" === i ? { x: l ? o - c : o, y: 0, width: c, height: a.globals.gridHeight } : "y" === i ? { x: 0, y: h ? n - d : n, width: a.globals.gridWidth, height: d } : { x: l ? o - c : o, y: h ? n - d : n, width: c, height: d }, s.drawSelectionRect(g), s.selectionDragging("resizing"), g } }, { key: "selectionDragging", value: function (t, e) { var i = this, a = this.w, s = this.xyRatios, r = this.selectionRect, o = 0; "resizing" === t && (o = 30); var n = function (t) { return parseFloat(r.node.getAttribute(t)) }, l = { x: n("x"), y: n("y"), width: n("width"), height: n("height") }; a.globals.selection = l, "function" == typeof a.config.chart.events.selection && a.globals.selectionEnabled && (clearTimeout(this.w.globals.selectionResizeTimer), this.w.globals.selectionResizeTimer = window.setTimeout((function () { var t, e, o, n, l = i.gridRect.getBoundingClientRect(), h = r.node.getBoundingClientRect(); a.globals.isRangeBar ? (t = a.globals.yAxisScale[0].niceMin + (h.left - l.left) * s.invertedYRatio, e = a.globals.yAxisScale[0].niceMin + (h.right - l.left) * s.invertedYRatio, o = 0, n = 1) : (t = a.globals.xAxisScale.niceMin + (h.left - l.left) * s.xRatio, e = a.globals.xAxisScale.niceMin + (h.right - l.left) * s.xRatio, o = a.globals.yAxisScale[0].niceMin + (l.bottom - h.bottom) * s.yRatio[0], n = a.globals.yAxisScale[0].niceMax - (h.top - l.top) * s.yRatio[0]); var c = { xaxis: { min: t, max: e }, yaxis: { min: o, max: n } }; a.config.chart.events.selection(i.ctx, c), a.config.chart.brush.enabled && void 0 !== a.config.chart.events.brushScrolled && a.config.chart.events.brushScrolled(i.ctx, c) }), o)) } }, { key: "selectionDrawn", value: function (t) { var e = t.context, i = t.zoomtype, a = this.w, s = e, r = this.xyRatios, o = this.ctx.toolbar; if (s.startX > s.endX) { var n = s.startX; s.startX = s.endX, s.endX = n } if (s.startY > s.endY) { var l = s.startY; s.startY = s.endY, s.endY = l } var h = void 0, c = void 0; a.globals.isRangeBar ? (h = a.globals.yAxisScale[0].niceMin + s.startX * r.invertedYRatio, c = a.globals.yAxisScale[0].niceMin + s.endX * r.invertedYRatio) : (h = a.globals.xAxisScale.niceMin + s.startX * r.xRatio, c = a.globals.xAxisScale.niceMin + s.endX * r.xRatio); var d = [], g = []; if (a.config.yaxis.forEach((function (t, e) { if (a.globals.seriesYAxisMap[e].length > 0) { var i = a.globals.seriesYAxisMap[e][0]; d.push(a.globals.yAxisScale[e].niceMax - r.yRatio[i] * s.startY), g.push(a.globals.yAxisScale[e].niceMax - r.yRatio[i] * s.endY) } })), s.dragged && (s.dragX > 10 || s.dragY > 10) && h !== c) if (a.globals.zoomEnabled) { var u = x.clone(a.globals.initialConfig.yaxis), p = x.clone(a.globals.initialConfig.xaxis); if (a.globals.zoomed = !0, a.config.xaxis.convertedCatToNumeric && (h = Math.floor(h), c = Math.floor(c), h < 1 && (h = 1, c = a.globals.dataPoints), c - h < 2 && (c = h + 1)), "xy" !== i && "x" !== i || (p = { min: h, max: c }), "xy" !== i && "y" !== i || u.forEach((function (t, e) { u[e].min = g[e], u[e].max = d[e] })), o) { var f = o.getBeforeZoomRange(p, u); f && (p = f.xaxis ? f.xaxis : p, u = f.yaxis ? f.yaxis : u) } var b = { xaxis: p }; a.config.chart.group || (b.yaxis = u), s.ctx.updateHelpers._updateOptions(b, !1, s.w.config.chart.animations.dynamicAnimation.enabled), "function" == typeof a.config.chart.events.zoomed && o.zoomCallback(p, u) } else if (a.globals.selectionEnabled) { var v, m = null; v = { min: h, max: c }, "xy" !== i && "y" !== i || (m = x.clone(a.config.yaxis)).forEach((function (t, e) { m[e].min = g[e], m[e].max = d[e] })), a.globals.selection = s.selection, "function" == typeof a.config.chart.events.selection && a.config.chart.events.selection(s.ctx, { xaxis: v, yaxis: m }) } } }, { key: "panDragging", value: function (t) { var e = t.context, i = this.w, a = e; if (void 0 !== i.globals.lastClientPosition.x) { var s = i.globals.lastClientPosition.x - a.clientX, r = i.globals.lastClientPosition.y - a.clientY; Math.abs(s) > Math.abs(r) && s > 0 ? this.moveDirection = "left" : Math.abs(s) > Math.abs(r) && s < 0 ? this.moveDirection = "right" : Math.abs(r) > Math.abs(s) && r > 0 ? this.moveDirection = "up" : Math.abs(r) > Math.abs(s) && r < 0 && (this.moveDirection = "down") } i.globals.lastClientPosition = { x: a.clientX, y: a.clientY }; var o = i.globals.isRangeBar ? i.globals.minY : i.globals.minX, n = i.globals.isRangeBar ? i.globals.maxY : i.globals.maxX; i.config.xaxis.convertedCatToNumeric || a.panScrolled(o, n) } }, { key: "delayedPanScrolled", value: function () { var t = this.w, e = t.globals.minX, i = t.globals.maxX, a = (t.globals.maxX - t.globals.minX) / 2; "left" === this.moveDirection ? (e = t.globals.minX + a, i = t.globals.maxX + a) : "right" === this.moveDirection && (e = t.globals.minX - a, i = t.globals.maxX - a), e = Math.floor(e), i = Math.floor(i), this.updateScrolledChart({ xaxis: { min: e, max: i } }, e, i) } }, { key: "panScrolled", value: function (t, e) { var i = this.w, a = this.xyRatios, s = x.clone(i.globals.initialConfig.yaxis), r = a.xRatio, o = i.globals.minX, n = i.globals.maxX; i.globals.isRangeBar && (r = a.invertedYRatio, o = i.globals.minY, n = i.globals.maxY), "left" === this.moveDirection ? (t = o + i.globals.gridWidth / 15 * r, e = n + i.globals.gridWidth / 15 * r) : "right" === this.moveDirection && (t = o - i.globals.gridWidth / 15 * r, e = n - i.globals.gridWidth / 15 * r), i.globals.isRangeBar || (t < i.globals.initialMinX || e > i.globals.initialMaxX) && (t = o, e = n); var l = { xaxis: { min: t, max: e } }; i.config.chart.group || (l.yaxis = s), this.updateScrolledChart(l, t, e) } }, { key: "updateScrolledChart", value: function (t, e, i) { var a = this.w; this.ctx.updateHelpers._updateOptions(t, !1, !1), "function" == typeof a.config.chart.events.scrolled && a.config.chart.events.scrolled(this.ctx, { xaxis: { min: e, max: i } }) } }]), i }(ht), dt = function () { function t(e) { a(this, t), this.w = e.w, this.ttCtx = e, this.ctx = e.ctx } return r(t, [{ key: "getNearestValues", value: function (t) { var e = t.hoverArea, i = t.elGrid, a = t.clientX, s = t.clientY, r = this.w, o = i.getBoundingClientRect(), n = o.width, l = o.height, h = n / (r.globals.dataPoints - 1), c = l / r.globals.dataPoints, d = this.hasBars(); !r.globals.comboCharts && !d || r.config.xaxis.convertedCatToNumeric || (h = n / r.globals.dataPoints); var g = a - o.left - r.globals.barPadForNumericAxis, u = s - o.top; g < 0 || u < 0 || g > n || u > l ? (e.classList.remove("hovering-zoom"), e.classList.remove("hovering-pan")) : r.globals.zoomEnabled ? (e.classList.remove("hovering-pan"), e.classList.add("hovering-zoom")) : r.globals.panEnabled && (e.classList.remove("hovering-zoom"), e.classList.add("hovering-pan")); var p = Math.round(g / h), f = Math.floor(u / c); d && !r.config.xaxis.convertedCatToNumeric && (p = Math.ceil(g / h), p -= 1); var b = null, v = null, m = r.globals.seriesXvalues.map((function (t) { return t.filter((function (t) { return x.isNumber(t) })) })), y = r.globals.seriesYvalues.map((function (t) { return t.filter((function (t) { return x.isNumber(t) })) })); if (r.globals.isXNumeric) { var w = this.ttCtx.getElGrid().getBoundingClientRect(), k = g * (w.width / n), A = u * (w.height / l); b = (v = this.closestInMultiArray(k, A, m, y)).index, p = v.j, null !== b && (m = r.globals.seriesXvalues[b], p = (v = this.closestInArray(k, m)).index) } return r.globals.capturedSeriesIndex = null === b ? -1 : b, (!p || p < 1) && (p = 0), r.globals.isBarHorizontal ? r.globals.capturedDataPointIndex = f : r.globals.capturedDataPointIndex = p, { capturedSeries: b, j: r.globals.isBarHorizontal ? f : p, hoverX: g, hoverY: u } } }, { key: "closestInMultiArray", value: function (t, e, i, a) { var s = this.w, r = 0, o = null, n = -1; s.globals.series.length > 1 ? r = this.getFirstActiveXArray(i) : o = 0; var l = i[r][0], h = Math.abs(t - l); if (i.forEach((function (e) { e.forEach((function (e, i) { var a = Math.abs(t - e); a <= h && (h = a, n = i) })) })), -1 !== n) { var c = a[r][n], d = Math.abs(e - c); o = r, a.forEach((function (t, i) { var a = Math.abs(e - t[n]); a <= d && (d = a, o = i) })) } return { index: o, j: n } } }, { key: "getFirstActiveXArray", value: function (t) { for (var e = this.w, i = 0, a = t.map((function (t, e) { return t.length > 0 ? e : -1 })), s = 0; s < a.length; s++)if (-1 !== a[s] && -1 === e.globals.collapsedSeriesIndices.indexOf(s) && -1 === e.globals.ancillaryCollapsedSeriesIndices.indexOf(s)) { i = a[s]; break } return i } }, { key: "closestInArray", value: function (t, e) { for (var i = e[0], a = null, s = Math.abs(t - i), r = 0; r < e.length; r++) { var o = Math.abs(t - e[r]); o < s && (s = o, a = r) } return { index: a } } }, { key: "isXoverlap", value: function (t) { var e = [], i = this.w.globals.seriesX.filter((function (t) { return void 0 !== t[0] })); if (i.length > 0) for (var a = 0; a < i.length - 1; a++)void 0 !== i[a][t] && void 0 !== i[a + 1][t] && i[a][t] !== i[a + 1][t] && e.push("unEqual"); return 0 === e.length } }, { key: "isInitialSeriesSameLen", value: function () { for (var t = !0, e = this.w.globals.initialSeries, i = 0; i < e.length - 1; i++)if (e[i].data.length !== e[i + 1].data.length) { t = !1; break } return t } }, { key: "getBarsHeight", value: function (t) { return u(t).reduce((function (t, e) { return t + e.getBBox().height }), 0) } }, { key: "getElMarkers", value: function (t) { return "number" == typeof t ? this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series[data\\:realIndex='".concat(t, "'] .apexcharts-series-markers-wrap > *")) : this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers-wrap > *") } }, { key: "getAllMarkers", value: function () { var t = this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers-wrap"); (t = u(t)).sort((function (t, e) { var i = Number(t.getAttribute("data:realIndex")), a = Number(e.getAttribute("data:realIndex")); return a < i ? 1 : a > i ? -1 : 0 })); var e = []; return t.forEach((function (t) { e.push(t.querySelector(".apexcharts-marker")) })), e } }, { key: "hasMarkers", value: function (t) { return this.getElMarkers(t).length > 0 } }, { key: "getElBars", value: function () { return this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-bar-series, .apexcharts-candlestick-series, .apexcharts-boxPlot-series, .apexcharts-rangebar-series") } }, { key: "hasBars", value: function () { return this.getElBars().length > 0 } }, { key: "getHoverMarkerSize", value: function (t) { var e = this.w, i = e.config.markers.hover.size; return void 0 === i && (i = e.globals.markers.size[t] + e.config.markers.hover.sizeOffset), i } }, { key: "toggleAllTooltipSeriesGroups", value: function (t) { var e = this.w, i = this.ttCtx; 0 === i.allTooltipSeriesGroups.length && (i.allTooltipSeriesGroups = e.globals.dom.baseEl.querySelectorAll(".apexcharts-tooltip-series-group")); for (var a = i.allTooltipSeriesGroups, s = 0; s < a.length; s++)"enable" === t ? (a[s].classList.add("apexcharts-active"), a[s].style.display = e.config.tooltip.items.display) : (a[s].classList.remove("apexcharts-active"), a[s].style.display = "none") } }]), t }(), gt = function () { function t(e) { a(this, t), this.w = e.w, this.ctx = e.ctx, this.ttCtx = e, this.tooltipUtil = new dt(e) } return r(t, [{ key: "drawSeriesTexts", value: function (t) { var e = t.shared, i = void 0 === e || e, a = t.ttItems, s = t.i, r = void 0 === s ? 0 : s, o = t.j, n = void 0 === o ? null : o, l = t.y1, h = t.y2, c = t.e, d = this.w; void 0 !== d.config.tooltip.custom ? this.handleCustomTooltip({ i: r, j: n, y1: l, y2: h, w: d }) : this.toggleActiveInactiveSeries(i); var g = this.getValuesToPrint({ i: r, j: n }); this.printLabels({ i: r, j: n, values: g, ttItems: a, shared: i, e: c }); var u = this.ttCtx.getElTooltip(); this.ttCtx.tooltipRect.ttWidth = u.getBoundingClientRect().width, this.ttCtx.tooltipRect.ttHeight = u.getBoundingClientRect().height } }, { key: "printLabels", value: function (t) { var i, a = this, s = t.i, r = t.j, o = t.values, n = t.ttItems, l = t.shared, h = t.e, c = this.w, d = [], g = function (t) { return c.globals.seriesGoals[t] && c.globals.seriesGoals[t][r] && Array.isArray(c.globals.seriesGoals[t][r]) }, u = o.xVal, p = o.zVal, f = o.xAxisTTVal, x = "", b = c.globals.colors[s]; null !== r && c.config.plotOptions.bar.distributed && (b = c.globals.colors[r]); for (var v = function (t, o) { var v = a.getFormatters(s); x = a.getSeriesName({ fn: v.yLbTitleFormatter, index: s, seriesIndex: s, j: r }), "treemap" === c.config.chart.type && (x = v.yLbTitleFormatter(String(c.config.series[s].data[r].x), { series: c.globals.series, seriesIndex: s, dataPointIndex: r, w: c })); var m = c.config.tooltip.inverseOrder ? o : t; if (c.globals.axisCharts) { var y = function (t) { var e, i, a, s; return c.globals.isRangeData ? v.yLbFormatter(null === (e = c.globals.seriesRangeStart) || void 0 === e || null === (i = e[t]) || void 0 === i ? void 0 : i[r], { series: c.globals.seriesRangeStart, seriesIndex: t, dataPointIndex: r, w: c }) + " - " + v.yLbFormatter(null === (a = c.globals.seriesRangeEnd) || void 0 === a || null === (s = a[t]) || void 0 === s ? void 0 : s[r], { series: c.globals.seriesRangeEnd, seriesIndex: t, dataPointIndex: r, w: c }) : v.yLbFormatter(c.globals.series[t][r], { series: c.globals.series, seriesIndex: t, dataPointIndex: r, w: c }) }; if (l) v = a.getFormatters(m), x = a.getSeriesName({ fn: v.yLbTitleFormatter, index: m, seriesIndex: s, j: r }), b = c.globals.colors[m], i = y(m), g(m) && (d = c.globals.seriesGoals[m][r].map((function (t) { return { attrs: t, val: v.yLbFormatter(t.value, { seriesIndex: m, dataPointIndex: r, w: c }) } }))); else { var w, k = null == h || null === (w = h.target) || void 0 === w ? void 0 : w.getAttribute("fill"); k && (b = -1 !== k.indexOf("url") ? document.querySelector(k.substr(4).slice(0, -1)).childNodes[0].getAttribute("stroke") : k), i = y(s), g(s) && Array.isArray(c.globals.seriesGoals[s][r]) && (d = c.globals.seriesGoals[s][r].map((function (t) { return { attrs: t, val: v.yLbFormatter(t.value, { seriesIndex: s, dataPointIndex: r, w: c }) } }))) } } null === r && (i = v.yLbFormatter(c.globals.series[s], e(e({}, c), {}, { seriesIndex: s, dataPointIndex: s }))), a.DOMHandling({ i: s, t: m, j: r, ttItems: n, values: { val: i, goalVals: d, xVal: u, xAxisTTVal: f, zVal: p }, seriesName: x, shared: l, pColor: b }) }, m = 0, y = c.globals.series.length - 1; m < c.globals.series.length; m++, y--)v(m, y) } }, { key: "getFormatters", value: function (t) { var e, i = this.w, a = i.globals.yLabelFormatters[t]; return void 0 !== i.globals.ttVal ? Array.isArray(i.globals.ttVal) ? (a = i.globals.ttVal[t] && i.globals.ttVal[t].formatter, e = i.globals.ttVal[t] && i.globals.ttVal[t].title && i.globals.ttVal[t].title.formatter) : (a = i.globals.ttVal.formatter, "function" == typeof i.globals.ttVal.title.formatter && (e = i.globals.ttVal.title.formatter)) : e = i.config.tooltip.y.title.formatter, "function" != typeof a && (a = i.globals.yLabelFormatters[0] ? i.globals.yLabelFormatters[0] : function (t) { return t }), "function" != typeof e && (e = function (t) { return t }), { yLbFormatter: a, yLbTitleFormatter: e } } }, { key: "getSeriesName", value: function (t) { var e = t.fn, i = t.index, a = t.seriesIndex, s = t.j, r = this.w; return e(String(r.globals.seriesNames[i]), { series: r.globals.series, seriesIndex: a, dataPointIndex: s, w: r }) } }, { key: "DOMHandling", value: function (t) { t.i; var e = t.t, i = t.j, a = t.ttItems, s = t.values, r = t.seriesName, o = t.shared, n = t.pColor, l = this.w, h = this.ttCtx, c = s.val, d = s.goalVals, g = s.xVal, u = s.xAxisTTVal, p = s.zVal, f = null; f = a[e].children, l.config.tooltip.fillSeriesColor && (a[e].style.backgroundColor = n, f[0].style.display = "none"), h.showTooltipTitle && (null === h.tooltipTitle && (h.tooltipTitle = l.globals.dom.baseEl.querySelector(".apexcharts-tooltip-title")), h.tooltipTitle.innerHTML = g), h.isXAxisTooltipEnabled && (h.xaxisTooltipText.innerHTML = "" !== u ? u : g); var x = a[e].querySelector(".apexcharts-tooltip-text-y-label"); x && (x.innerHTML = r || ""); var b = a[e].querySelector(".apexcharts-tooltip-text-y-value"); b && (b.innerHTML = void 0 !== c ? c : ""), f[0] && f[0].classList.contains("apexcharts-tooltip-marker") && (l.config.tooltip.marker.fillColors && Array.isArray(l.config.tooltip.marker.fillColors) && (n = l.config.tooltip.marker.fillColors[e]), f[0].style.backgroundColor = n), l.config.tooltip.marker.show || (f[0].style.display = "none"); var v = a[e].querySelector(".apexcharts-tooltip-text-goals-label"), m = a[e].querySelector(".apexcharts-tooltip-text-goals-value"); if (d.length && l.globals.seriesGoals[e]) { var y = function () { var t = "
      ", e = "
      "; d.forEach((function (i, a) { t += '
      ').concat(i.attrs.name, "
      "), e += "
      ".concat(i.val, "
      ") })), v.innerHTML = t + "
      ", m.innerHTML = e + "
      " }; o ? l.globals.seriesGoals[e][i] && Array.isArray(l.globals.seriesGoals[e][i]) ? y() : (v.innerHTML = "", m.innerHTML = "") : y() } else v.innerHTML = "", m.innerHTML = ""; null !== p && (a[e].querySelector(".apexcharts-tooltip-text-z-label").innerHTML = l.config.tooltip.z.title, a[e].querySelector(".apexcharts-tooltip-text-z-value").innerHTML = void 0 !== p ? p : ""); if (o && f[0]) { if (l.config.tooltip.hideEmptySeries) { var w = a[e].querySelector(".apexcharts-tooltip-marker"), k = a[e].querySelector(".apexcharts-tooltip-text"); 0 == parseFloat(c) ? (w.style.display = "none", k.style.display = "none") : (w.style.display = "block", k.style.display = "block") } null == c || l.globals.ancillaryCollapsedSeriesIndices.indexOf(e) > -1 || l.globals.collapsedSeriesIndices.indexOf(e) > -1 ? f[0].parentNode.style.display = "none" : f[0].parentNode.style.display = l.config.tooltip.items.display } } }, { key: "toggleActiveInactiveSeries", value: function (t) { var e = this.w; if (t) this.tooltipUtil.toggleAllTooltipSeriesGroups("enable"); else { this.tooltipUtil.toggleAllTooltipSeriesGroups("disable"); var i = e.globals.dom.baseEl.querySelector(".apexcharts-tooltip-series-group"); i && (i.classList.add("apexcharts-active"), i.style.display = e.config.tooltip.items.display) } } }, { key: "getValuesToPrint", value: function (t) { var e = t.i, i = t.j, a = this.w, s = this.ctx.series.filteredSeriesX(), r = "", o = "", n = null, l = null, h = { series: a.globals.series, seriesIndex: e, dataPointIndex: i, w: a }, c = a.globals.ttZFormatter; null === i ? l = a.globals.series[e] : a.globals.isXNumeric && "treemap" !== a.config.chart.type ? (r = s[e][i], 0 === s[e].length && (r = s[this.tooltipUtil.getFirstActiveXArray(s)][i])) : r = void 0 !== a.globals.labels[i] ? a.globals.labels[i] : ""; var d = r; a.globals.isXNumeric && "datetime" === a.config.xaxis.type ? r = new S(this.ctx).xLabelFormat(a.globals.ttKeyFormatter, d, d, { i: void 0, dateFormatter: new A(this.ctx).formatDate, w: this.w }) : r = a.globals.isBarHorizontal ? a.globals.yLabelFormatters[0](d, h) : a.globals.xLabelFormatter(d, h); return void 0 !== a.config.tooltip.x.formatter && (r = a.globals.ttKeyFormatter(d, h)), a.globals.seriesZ.length > 0 && a.globals.seriesZ[e].length > 0 && (n = c(a.globals.seriesZ[e][i], a)), o = "function" == typeof a.config.xaxis.tooltip.formatter ? a.globals.xaxisTooltipFormatter(d, h) : r, { val: Array.isArray(l) ? l.join(" ") : l, xVal: Array.isArray(r) ? r.join(" ") : r, xAxisTTVal: Array.isArray(o) ? o.join(" ") : o, zVal: n } } }, { key: "handleCustomTooltip", value: function (t) { var e = t.i, i = t.j, a = t.y1, s = t.y2, r = t.w, o = this.ttCtx.getElTooltip(), n = r.config.tooltip.custom; Array.isArray(n) && n[e] && (n = n[e]), o.innerHTML = n({ ctx: this.ctx, series: r.globals.series, seriesIndex: e, dataPointIndex: i, y1: a, y2: s, w: r }) } }]), t }(), ut = function () { function t(e) { a(this, t), this.ttCtx = e, this.ctx = e.ctx, this.w = e.w } return r(t, [{ key: "moveXCrosshairs", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null, i = this.ttCtx, a = this.w, s = i.getElXCrosshairs(), r = t - i.xcrosshairsWidth / 2, o = a.globals.labels.slice().length; if (null !== e && (r = a.globals.gridWidth / o * e), null === s || a.globals.isBarHorizontal || (s.setAttribute("x", r), s.setAttribute("x1", r), s.setAttribute("x2", r), s.setAttribute("y2", a.globals.gridHeight), s.classList.add("apexcharts-active")), r < 0 && (r = 0), r > a.globals.gridWidth && (r = a.globals.gridWidth), i.isXAxisTooltipEnabled) { var n = r; "tickWidth" !== a.config.xaxis.crosshairs.width && "barWidth" !== a.config.xaxis.crosshairs.width || (n = r + i.xcrosshairsWidth / 2), this.moveXAxisTooltip(n) } } }, { key: "moveYCrosshairs", value: function (t) { var e = this.ttCtx; null !== e.ycrosshairs && m.setAttrs(e.ycrosshairs, { y1: t, y2: t }), null !== e.ycrosshairsHidden && m.setAttrs(e.ycrosshairsHidden, { y1: t, y2: t }) } }, { key: "moveXAxisTooltip", value: function (t) { var e = this.w, i = this.ttCtx; if (null !== i.xaxisTooltip && 0 !== i.xcrosshairsWidth) { i.xaxisTooltip.classList.add("apexcharts-active"); var a = i.xaxisOffY + e.config.xaxis.tooltip.offsetY + e.globals.translateY + 1 + e.config.xaxis.offsetY; if (t -= i.xaxisTooltip.getBoundingClientRect().width / 2, !isNaN(t)) { t += e.globals.translateX; var s; s = new m(this.ctx).getTextRects(i.xaxisTooltipText.innerHTML), i.xaxisTooltipText.style.minWidth = s.width + "px", i.xaxisTooltip.style.left = t + "px", i.xaxisTooltip.style.top = a + "px" } } } }, { key: "moveYAxisTooltip", value: function (t) { var e = this.w, i = this.ttCtx; null === i.yaxisTTEls && (i.yaxisTTEls = e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip")); var a = parseInt(i.ycrosshairsHidden.getAttribute("y1"), 10), s = e.globals.translateY + a, r = i.yaxisTTEls[t].getBoundingClientRect().height, o = e.globals.translateYAxisX[t] - 2; e.config.yaxis[t].opposite && (o -= 26), s -= r / 2, -1 === e.globals.ignoreYAxisIndexes.indexOf(t) ? (i.yaxisTTEls[t].classList.add("apexcharts-active"), i.yaxisTTEls[t].style.top = s + "px", i.yaxisTTEls[t].style.left = o + e.config.yaxis[t].tooltip.offsetX + "px") : i.yaxisTTEls[t].classList.remove("apexcharts-active") } }, { key: "moveTooltip", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : null, a = this.w, s = this.ttCtx, r = s.getElTooltip(), o = s.tooltipRect, n = null !== i ? parseFloat(i) : 1, l = parseFloat(t) + n + 5, h = parseFloat(e) + n / 2; if (l > a.globals.gridWidth / 2 && (l = l - o.ttWidth - n - 10), l > a.globals.gridWidth - o.ttWidth - 10 && (l = a.globals.gridWidth - o.ttWidth), l < -20 && (l = -20), a.config.tooltip.followCursor) { var c = s.getElGrid().getBoundingClientRect(); (l = s.e.clientX - c.left) > a.globals.gridWidth / 2 && (l -= s.tooltipRect.ttWidth), (h = s.e.clientY + a.globals.translateY - c.top) > a.globals.gridHeight / 2 && (h -= s.tooltipRect.ttHeight) } else a.globals.isBarHorizontal || o.ttHeight / 2 + h > a.globals.gridHeight && (h = a.globals.gridHeight - o.ttHeight + a.globals.translateY); isNaN(l) || (l += a.globals.translateX, r.style.left = l + "px", r.style.top = h + "px") } }, { key: "moveMarkers", value: function (t, e) { var i = this.w, a = this.ttCtx; if (i.globals.markers.size[t] > 0) for (var s = i.globals.dom.baseEl.querySelectorAll(" .apexcharts-series[data\\:realIndex='".concat(t, "'] .apexcharts-marker")), r = 0; r < s.length; r++)parseInt(s[r].getAttribute("rel"), 10) === e && (a.marker.resetPointsSize(), a.marker.enlargeCurrentPoint(e, s[r])); else a.marker.resetPointsSize(), this.moveDynamicPointOnHover(e, t) } }, { key: "moveDynamicPointOnHover", value: function (t, e) { var i, a, s = this.w, r = this.ttCtx, o = s.globals.pointsArray, n = r.tooltipUtil.getHoverMarkerSize(e), l = s.config.series[e].type; if (!l || "column" !== l && "candlestick" !== l && "boxPlot" !== l) { i = o[e][t][0], a = o[e][t][1] ? o[e][t][1] : 0; var h = s.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(e, "'] .apexcharts-series-markers circle")); h && a < s.globals.gridHeight && a > 0 && (h.setAttribute("r", n), h.setAttribute("cx", i), h.setAttribute("cy", a)), this.moveXCrosshairs(i), r.fixedTooltip || this.moveTooltip(i, a, n) } } }, { key: "moveDynamicPointsOnHover", value: function (t) { var e, i = this.ttCtx, a = i.w, s = 0, r = 0, o = a.globals.pointsArray; e = new W(this.ctx).getActiveConfigSeriesIndex("asc", ["line", "area", "scatter", "bubble"]); var n = i.tooltipUtil.getHoverMarkerSize(e); o[e] && (s = o[e][t][0], r = o[e][t][1]); var l = i.tooltipUtil.getAllMarkers(); if (null !== l) for (var h = 0; h < a.globals.series.length; h++) { var c = o[h]; if (a.globals.comboCharts && void 0 === c && l.splice(h, 0, null), c && c.length) { var d = o[h][t][1], g = void 0; if (l[h].setAttribute("cx", s), "rangeArea" === a.config.chart.type && !a.globals.comboCharts) { var u = t + a.globals.series[h].length; g = o[h][u][1], d -= Math.abs(d - g) / 2 } null !== d && !isNaN(d) && d < a.globals.gridHeight + n && d + n > 0 ? (l[h] && l[h].setAttribute("r", n), l[h] && l[h].setAttribute("cy", d)) : l[h] && l[h].setAttribute("r", 0) } } this.moveXCrosshairs(s), i.fixedTooltip || this.moveTooltip(s, r || a.globals.gridHeight, n) } }, { key: "moveStickyTooltipOverBars", value: function (t, e) { var i = this.w, a = this.ttCtx, s = i.globals.columnSeries ? i.globals.columnSeries.length : i.globals.series.length, r = s >= 2 && s % 2 == 0 ? Math.floor(s / 2) : Math.floor(s / 2) + 1; i.globals.isBarHorizontal && (r = new W(this.ctx).getActiveConfigSeriesIndex("desc") + 1); var o = i.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[rel='".concat(r, "'] path[j='").concat(t, "'], .apexcharts-candlestick-series .apexcharts-series[rel='").concat(r, "'] path[j='").concat(t, "'], .apexcharts-boxPlot-series .apexcharts-series[rel='").concat(r, "'] path[j='").concat(t, "'], .apexcharts-rangebar-series .apexcharts-series[rel='").concat(r, "'] path[j='").concat(t, "']")); o || "number" != typeof e || (o = i.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[data\\:realIndex='".concat(e, "'] path[j='").concat(t, "'],\n .apexcharts-candlestick-series .apexcharts-series[data\\:realIndex='").concat(e, "'] path[j='").concat(t, "'],\n .apexcharts-boxPlot-series .apexcharts-series[data\\:realIndex='").concat(e, "'] path[j='").concat(t, "'],\n .apexcharts-rangebar-series .apexcharts-series[data\\:realIndex='").concat(e, "'] path[j='").concat(t, "']"))); var n = o ? parseFloat(o.getAttribute("cx")) : 0, l = o ? parseFloat(o.getAttribute("cy")) : 0, h = o ? parseFloat(o.getAttribute("barWidth")) : 0, c = a.getElGrid().getBoundingClientRect(), d = o && (o.classList.contains("apexcharts-candlestick-area") || o.classList.contains("apexcharts-boxPlot-area")); i.globals.isXNumeric ? (o && !d && (n -= s % 2 != 0 ? h / 2 : 0), o && d && i.globals.comboCharts && (n -= h / 2)) : i.globals.isBarHorizontal || (n = a.xAxisTicksPositions[t - 1] + a.dataPointsDividedWidth / 2, isNaN(n) && (n = a.xAxisTicksPositions[t] - a.dataPointsDividedWidth / 2)), i.globals.isBarHorizontal ? l -= a.tooltipRect.ttHeight : i.config.tooltip.followCursor ? l = a.e.clientY - c.top - a.tooltipRect.ttHeight / 2 : l + a.tooltipRect.ttHeight + 15 > i.globals.gridHeight && (l = i.globals.gridHeight), i.globals.isBarHorizontal || this.moveXCrosshairs(n), a.fixedTooltip || this.moveTooltip(n, l || i.globals.gridHeight) } }]), t }(), pt = function () { function t(e) { a(this, t), this.w = e.w, this.ttCtx = e, this.ctx = e.ctx, this.tooltipPosition = new ut(e) } return r(t, [{ key: "drawDynamicPoints", value: function () { var t = this.w, e = new m(this.ctx), i = new D(this.ctx), a = t.globals.dom.baseEl.querySelectorAll(".apexcharts-series"); a = u(a), t.config.chart.stacked && a.sort((function (t, e) { return parseFloat(t.getAttribute("data:realIndex")) - parseFloat(e.getAttribute("data:realIndex")) })); for (var s = 0; s < a.length; s++) { var r = a[s].querySelector(".apexcharts-series-markers-wrap"); if (null !== r) { var o = void 0, n = "apexcharts-marker w".concat((Math.random() + 1).toString(36).substring(4)); "line" !== t.config.chart.type && "area" !== t.config.chart.type || t.globals.comboCharts || t.config.tooltip.intersect || (n += " no-pointer-events"); var l = i.getMarkerConfig({ cssClass: n, seriesIndex: Number(r.getAttribute("data:realIndex")) }); (o = e.drawMarker(0, 0, l)).node.setAttribute("default-marker-size", 0); var h = document.createElementNS(t.globals.SVGNS, "g"); h.classList.add("apexcharts-series-markers"), h.appendChild(o.node), r.appendChild(h) } } } }, { key: "enlargeCurrentPoint", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : null, a = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : null, s = this.w; "bubble" !== s.config.chart.type && this.newPointSize(t, e); var r = e.getAttribute("cx"), o = e.getAttribute("cy"); if (null !== i && null !== a && (r = i, o = a), this.tooltipPosition.moveXCrosshairs(r), !this.fixedTooltip) { if ("radar" === s.config.chart.type) { var n = this.ttCtx.getElGrid().getBoundingClientRect(); r = this.ttCtx.e.clientX - n.left } this.tooltipPosition.moveTooltip(r, o, s.config.markers.hover.size) } } }, { key: "enlargePoints", value: function (t) { for (var e = this.w, i = this, a = this.ttCtx, s = t, r = e.globals.dom.baseEl.querySelectorAll(".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"), o = e.config.markers.hover.size, n = 0; n < r.length; n++) { var l = r[n].getAttribute("rel"), h = r[n].getAttribute("index"); if (void 0 === o && (o = e.globals.markers.size[h] + e.config.markers.hover.sizeOffset), s === parseInt(l, 10)) { i.newPointSize(s, r[n]); var c = r[n].getAttribute("cx"), d = r[n].getAttribute("cy"); i.tooltipPosition.moveXCrosshairs(c), a.fixedTooltip || i.tooltipPosition.moveTooltip(c, d, o) } else i.oldPointSize(r[n]) } } }, { key: "newPointSize", value: function (t, e) { var i = this.w, a = i.config.markers.hover.size, s = 0 === t ? e.parentNode.firstChild : e.parentNode.lastChild; if ("0" !== s.getAttribute("default-marker-size")) { var r = parseInt(s.getAttribute("index"), 10); void 0 === a && (a = i.globals.markers.size[r] + i.config.markers.hover.sizeOffset), a < 0 && (a = 0), s.setAttribute("r", a) } } }, { key: "oldPointSize", value: function (t) { var e = parseFloat(t.getAttribute("default-marker-size")); t.setAttribute("r", e) } }, { key: "resetPointsSize", value: function () { for (var t = this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"), e = 0; e < t.length; e++) { var i = parseFloat(t[e].getAttribute("default-marker-size")); x.isNumber(i) && i >= 0 ? t[e].setAttribute("r", i) : t[e].setAttribute("r", 0) } } }]), t }(), ft = function () { function t(e) { a(this, t), this.w = e.w; var i = this.w; this.ttCtx = e, this.isVerticalGroupedRangeBar = !i.globals.isBarHorizontal && "rangeBar" === i.config.chart.type && i.config.plotOptions.bar.rangeBarGroupRows } return r(t, [{ key: "getAttr", value: function (t, e) { return parseFloat(t.target.getAttribute(e)) } }, { key: "handleHeatTreeTooltip", value: function (t) { var e = t.e, i = t.opt, a = t.x, s = t.y, r = t.type, o = this.ttCtx, n = this.w; if (e.target.classList.contains("apexcharts-".concat(r, "-rect"))) { var l = this.getAttr(e, "i"), h = this.getAttr(e, "j"), c = this.getAttr(e, "cx"), d = this.getAttr(e, "cy"), g = this.getAttr(e, "width"), u = this.getAttr(e, "height"); if (o.tooltipLabels.drawSeriesTexts({ ttItems: i.ttItems, i: l, j: h, shared: !1, e: e }), n.globals.capturedSeriesIndex = l, n.globals.capturedDataPointIndex = h, a = c + o.tooltipRect.ttWidth / 2 + g, s = d + o.tooltipRect.ttHeight / 2 - u / 2, o.tooltipPosition.moveXCrosshairs(c + g / 2), a > n.globals.gridWidth / 2 && (a = c - o.tooltipRect.ttWidth / 2 + g), o.w.config.tooltip.followCursor) { var p = n.globals.dom.elWrap.getBoundingClientRect(); a = n.globals.clientX - p.left - (a > n.globals.gridWidth / 2 ? o.tooltipRect.ttWidth : 0), s = n.globals.clientY - p.top - (s > n.globals.gridHeight / 2 ? o.tooltipRect.ttHeight : 0) } } return { x: a, y: s } } }, { key: "handleMarkerTooltip", value: function (t) { var e, i, a = t.e, s = t.opt, r = t.x, o = t.y, n = this.w, l = this.ttCtx; if (a.target.classList.contains("apexcharts-marker")) { var h = parseInt(s.paths.getAttribute("cx"), 10), c = parseInt(s.paths.getAttribute("cy"), 10), d = parseFloat(s.paths.getAttribute("val")); if (i = parseInt(s.paths.getAttribute("rel"), 10), e = parseInt(s.paths.parentNode.parentNode.parentNode.getAttribute("rel"), 10) - 1, l.intersect) { var g = x.findAncestor(s.paths, "apexcharts-series"); g && (e = parseInt(g.getAttribute("data:realIndex"), 10)) } if (l.tooltipLabels.drawSeriesTexts({ ttItems: s.ttItems, i: e, j: i, shared: !l.showOnIntersect && n.config.tooltip.shared, e: a }), "mouseup" === a.type && l.markerClick(a, e, i), n.globals.capturedSeriesIndex = e, n.globals.capturedDataPointIndex = i, r = h, o = c + n.globals.translateY - 1.4 * l.tooltipRect.ttHeight, l.w.config.tooltip.followCursor) { var u = l.getElGrid().getBoundingClientRect(); o = l.e.clientY + n.globals.translateY - u.top } d < 0 && (o = c), l.marker.enlargeCurrentPoint(i, s.paths, r, o) } return { x: r, y: o } } }, { key: "handleBarTooltip", value: function (t) { var e, i, a = t.e, s = t.opt, r = this.w, o = this.ttCtx, n = o.getElTooltip(), l = 0, h = 0, c = 0, d = this.getBarTooltipXY({ e: a, opt: s }); e = d.i; var g = d.barHeight, u = d.j; r.globals.capturedSeriesIndex = e, r.globals.capturedDataPointIndex = u, r.globals.isBarHorizontal && o.tooltipUtil.hasBars() || !r.config.tooltip.shared ? (h = d.x, c = d.y, i = Array.isArray(r.config.stroke.width) ? r.config.stroke.width[e] : r.config.stroke.width, l = h) : r.globals.comboCharts || r.config.tooltip.shared || (l /= 2), isNaN(c) && (c = r.globals.svgHeight - o.tooltipRect.ttHeight); var p = parseInt(s.paths.parentNode.getAttribute("data:realIndex"), 10), f = r.globals.isMultipleYAxis ? r.config.yaxis[p] && r.config.yaxis[p].reversed : r.config.yaxis[0].reversed; if (h + o.tooltipRect.ttWidth > r.globals.gridWidth && !f ? h -= o.tooltipRect.ttWidth : h < 0 && (h = 0), o.w.config.tooltip.followCursor) { var x = o.getElGrid().getBoundingClientRect(); c = o.e.clientY - x.top } null === o.tooltip && (o.tooltip = r.globals.dom.baseEl.querySelector(".apexcharts-tooltip")), r.config.tooltip.shared || (r.globals.comboBarCount > 0 ? o.tooltipPosition.moveXCrosshairs(l + i / 2) : o.tooltipPosition.moveXCrosshairs(l)), !o.fixedTooltip && (!r.config.tooltip.shared || r.globals.isBarHorizontal && o.tooltipUtil.hasBars()) && (f && (h -= o.tooltipRect.ttWidth) < 0 && (h = 0), !f || r.globals.isBarHorizontal && o.tooltipUtil.hasBars() || (c = c + g - 2 * (r.globals.series[e][u] < 0 ? g : 0)), c = c + r.globals.translateY - o.tooltipRect.ttHeight / 2, n.style.left = h + r.globals.translateX + "px", n.style.top = c + "px") } }, { key: "getBarTooltipXY", value: function (t) { var e = this, i = t.e, a = t.opt, s = this.w, r = null, o = this.ttCtx, n = 0, l = 0, h = 0, c = 0, d = 0, g = i.target.classList; if (g.contains("apexcharts-bar-area") || g.contains("apexcharts-candlestick-area") || g.contains("apexcharts-boxPlot-area") || g.contains("apexcharts-rangebar-area")) { var u = i.target, p = u.getBoundingClientRect(), f = a.elGrid.getBoundingClientRect(), x = p.height; d = p.height; var b = p.width, v = parseInt(u.getAttribute("cx"), 10), m = parseInt(u.getAttribute("cy"), 10); c = parseFloat(u.getAttribute("barWidth")); var y = "touchmove" === i.type ? i.touches[0].clientX : i.clientX; r = parseInt(u.getAttribute("j"), 10), n = parseInt(u.parentNode.getAttribute("rel"), 10) - 1; var w = u.getAttribute("data-range-y1"), k = u.getAttribute("data-range-y2"); s.globals.comboCharts && (n = parseInt(u.parentNode.getAttribute("data:realIndex"), 10)); var A = function (t) { return s.globals.isXNumeric ? v - b / 2 : e.isVerticalGroupedRangeBar ? v + b / 2 : v - o.dataPointsDividedWidth + b / 2 }, S = function () { return m - o.dataPointsDividedHeight + x / 2 - o.tooltipRect.ttHeight / 2 }; o.tooltipLabels.drawSeriesTexts({ ttItems: a.ttItems, i: n, j: r, y1: w ? parseInt(w, 10) : null, y2: k ? parseInt(k, 10) : null, shared: !o.showOnIntersect && s.config.tooltip.shared, e: i }), s.config.tooltip.followCursor ? s.globals.isBarHorizontal ? (l = y - f.left + 15, h = S()) : (l = A(), h = i.clientY - f.top - o.tooltipRect.ttHeight / 2 - 15) : s.globals.isBarHorizontal ? ((l = v) < o.xyRatios.baseLineInvertedY && (l = v - o.tooltipRect.ttWidth), h = S()) : (l = A(), h = m) } return { x: l, y: h, barHeight: d, barWidth: c, i: n, j: r } } }]), t }(), xt = function () { function t(e) { a(this, t), this.w = e.w, this.ttCtx = e } return r(t, [{ key: "drawXaxisTooltip", value: function () { var t = this.w, e = this.ttCtx, i = "bottom" === t.config.xaxis.position; e.xaxisOffY = i ? t.globals.gridHeight + 1 : -t.globals.xAxisHeight - t.config.xaxis.axisTicks.height + 3; var a = i ? "apexcharts-xaxistooltip apexcharts-xaxistooltip-bottom" : "apexcharts-xaxistooltip apexcharts-xaxistooltip-top", s = t.globals.dom.elWrap; e.isXAxisTooltipEnabled && (null === t.globals.dom.baseEl.querySelector(".apexcharts-xaxistooltip") && (e.xaxisTooltip = document.createElement("div"), e.xaxisTooltip.setAttribute("class", a + " apexcharts-theme-" + t.config.tooltip.theme), s.appendChild(e.xaxisTooltip), e.xaxisTooltipText = document.createElement("div"), e.xaxisTooltipText.classList.add("apexcharts-xaxistooltip-text"), e.xaxisTooltipText.style.fontFamily = t.config.xaxis.tooltip.style.fontFamily || t.config.chart.fontFamily, e.xaxisTooltipText.style.fontSize = t.config.xaxis.tooltip.style.fontSize, e.xaxisTooltip.appendChild(e.xaxisTooltipText))) } }, { key: "drawYaxisTooltip", value: function () { for (var t = this.w, e = this.ttCtx, i = 0; i < t.config.yaxis.length; i++) { var a = t.config.yaxis[i].opposite || t.config.yaxis[i].crosshairs.opposite; e.yaxisOffX = a ? t.globals.gridWidth + 1 : 1; var s = "apexcharts-yaxistooltip apexcharts-yaxistooltip-".concat(i, a ? " apexcharts-yaxistooltip-right" : " apexcharts-yaxistooltip-left"), r = t.globals.dom.elWrap; null === t.globals.dom.baseEl.querySelector(".apexcharts-yaxistooltip apexcharts-yaxistooltip-".concat(i)) && (e.yaxisTooltip = document.createElement("div"), e.yaxisTooltip.setAttribute("class", s + " apexcharts-theme-" + t.config.tooltip.theme), r.appendChild(e.yaxisTooltip), 0 === i && (e.yaxisTooltipText = []), e.yaxisTooltipText[i] = document.createElement("div"), e.yaxisTooltipText[i].classList.add("apexcharts-yaxistooltip-text"), e.yaxisTooltip.appendChild(e.yaxisTooltipText[i])) } } }, { key: "setXCrosshairWidth", value: function () { var t = this.w, e = this.ttCtx, i = e.getElXCrosshairs(); if (e.xcrosshairsWidth = parseInt(t.config.xaxis.crosshairs.width, 10), t.globals.comboCharts) { var a = t.globals.dom.baseEl.querySelector(".apexcharts-bar-area"); if (null !== a && "barWidth" === t.config.xaxis.crosshairs.width) { var s = parseFloat(a.getAttribute("barWidth")); e.xcrosshairsWidth = s } else if ("tickWidth" === t.config.xaxis.crosshairs.width) { var r = t.globals.labels.length; e.xcrosshairsWidth = t.globals.gridWidth / r } } else if ("tickWidth" === t.config.xaxis.crosshairs.width) { var o = t.globals.labels.length; e.xcrosshairsWidth = t.globals.gridWidth / o } else if ("barWidth" === t.config.xaxis.crosshairs.width) { var n = t.globals.dom.baseEl.querySelector(".apexcharts-bar-area"); if (null !== n) { var l = parseFloat(n.getAttribute("barWidth")); e.xcrosshairsWidth = l } else e.xcrosshairsWidth = 1 } t.globals.isBarHorizontal && (e.xcrosshairsWidth = 0), null !== i && e.xcrosshairsWidth > 0 && i.setAttribute("width", e.xcrosshairsWidth) } }, { key: "handleYCrosshair", value: function () { var t = this.w, e = this.ttCtx; e.ycrosshairs = t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs"), e.ycrosshairsHidden = t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs-hidden") } }, { key: "drawYaxisTooltipText", value: function (t, e, i) { var a = this.ttCtx, s = this.w, r = s.globals, o = r.seriesYAxisMap[t]; if (a.yaxisTooltips[t] && o.length > 0) { var n = r.yLabelFormatters[t], l = a.getElGrid().getBoundingClientRect(), h = o[0]; i.yRatio.length > 1 && function (t) { throw new TypeError('"' + t + '" is read-only') }("translationsIndex"); var c = (e - l.top) * i.yRatio[0], d = r.maxYArr[h] - r.minYArr[h], g = r.minYArr[h] + (d - c); s.config.yaxis[t].reversed && (g = r.maxYArr[h] - (d - c)), a.tooltipPosition.moveYCrosshairs(e - l.top), a.yaxisTooltipText[t].innerHTML = n(g), a.tooltipPosition.moveYAxisTooltip(t) } } }]), t }(), bt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w; var i = this.w; this.tConfig = i.config.tooltip, this.tooltipUtil = new dt(this), this.tooltipLabels = new gt(this), this.tooltipPosition = new ut(this), this.marker = new pt(this), this.intersect = new ft(this), this.axesTooltip = new xt(this), this.showOnIntersect = this.tConfig.intersect, this.showTooltipTitle = this.tConfig.x.show, this.fixedTooltip = this.tConfig.fixed.enabled, this.xaxisTooltip = null, this.yaxisTTEls = null, this.isBarShared = !i.globals.isBarHorizontal && this.tConfig.shared, this.lastHoverTime = Date.now() } return r(t, [{ key: "getElTooltip", value: function (t) { return t || (t = this), t.w.globals.dom.baseEl ? t.w.globals.dom.baseEl.querySelector(".apexcharts-tooltip") : null } }, { key: "getElXCrosshairs", value: function () { return this.w.globals.dom.baseEl.querySelector(".apexcharts-xcrosshairs") } }, { key: "getElGrid", value: function () { return this.w.globals.dom.baseEl.querySelector(".apexcharts-grid") } }, { key: "drawTooltip", value: function (t) { var e = this.w; this.xyRatios = t, this.isXAxisTooltipEnabled = e.config.xaxis.tooltip.enabled && e.globals.axisCharts, this.yaxisTooltips = e.config.yaxis.map((function (t, i) { return !!(t.show && t.tooltip.enabled && e.globals.axisCharts) })), this.allTooltipSeriesGroups = [], e.globals.axisCharts || (this.showTooltipTitle = !1); var i = document.createElement("div"); if (i.classList.add("apexcharts-tooltip"), e.config.tooltip.cssClass && i.classList.add(e.config.tooltip.cssClass), i.classList.add("apexcharts-theme-".concat(this.tConfig.theme)), e.globals.dom.elWrap.appendChild(i), e.globals.axisCharts) { this.axesTooltip.drawXaxisTooltip(), this.axesTooltip.drawYaxisTooltip(), this.axesTooltip.setXCrosshairWidth(), this.axesTooltip.handleYCrosshair(); var a = new V(this.ctx); this.xAxisTicksPositions = a.getXAxisTicksPositions() } if (!e.globals.comboCharts && !this.tConfig.intersect && "rangeBar" !== e.config.chart.type || this.tConfig.shared || (this.showOnIntersect = !0), 0 !== e.config.markers.size && 0 !== e.globals.markers.largestSize || this.marker.drawDynamicPoints(this), e.globals.collapsedSeries.length !== e.globals.series.length) { this.dataPointsDividedHeight = e.globals.gridHeight / e.globals.dataPoints, this.dataPointsDividedWidth = e.globals.gridWidth / e.globals.dataPoints, this.showTooltipTitle && (this.tooltipTitle = document.createElement("div"), this.tooltipTitle.classList.add("apexcharts-tooltip-title"), this.tooltipTitle.style.fontFamily = this.tConfig.style.fontFamily || e.config.chart.fontFamily, this.tooltipTitle.style.fontSize = this.tConfig.style.fontSize, i.appendChild(this.tooltipTitle)); var s = e.globals.series.length; (e.globals.xyCharts || e.globals.comboCharts) && this.tConfig.shared && (s = this.showOnIntersect ? 1 : e.globals.series.length), this.legendLabels = e.globals.dom.baseEl.querySelectorAll(".apexcharts-legend-text"), this.ttItems = this.createTTElements(s), this.addSVGEvents() } } }, { key: "createTTElements", value: function (t) { for (var e = this, i = this.w, a = [], s = this.getElTooltip(), r = function (r) { var o = document.createElement("div"); o.classList.add("apexcharts-tooltip-series-group"), o.style.order = i.config.tooltip.inverseOrder ? t - r : r + 1, e.tConfig.shared && e.tConfig.enabledOnSeries && Array.isArray(e.tConfig.enabledOnSeries) && e.tConfig.enabledOnSeries.indexOf(r) < 0 && o.classList.add("apexcharts-tooltip-series-group-hidden"); var n = document.createElement("span"); n.classList.add("apexcharts-tooltip-marker"), n.style.backgroundColor = i.globals.colors[r], o.appendChild(n); var l = document.createElement("div"); l.classList.add("apexcharts-tooltip-text"), l.style.fontFamily = e.tConfig.style.fontFamily || i.config.chart.fontFamily, l.style.fontSize = e.tConfig.style.fontSize, ["y", "goals", "z"].forEach((function (t) { var e = document.createElement("div"); e.classList.add("apexcharts-tooltip-".concat(t, "-group")); var i = document.createElement("span"); i.classList.add("apexcharts-tooltip-text-".concat(t, "-label")), e.appendChild(i); var a = document.createElement("span"); a.classList.add("apexcharts-tooltip-text-".concat(t, "-value")), e.appendChild(a), l.appendChild(e) })), o.appendChild(l), s.appendChild(o), a.push(o) }, o = 0; o < t; o++)r(o); return a } }, { key: "addSVGEvents", value: function () { var t = this.w, e = t.config.chart.type, i = this.getElTooltip(), a = !("bar" !== e && "candlestick" !== e && "boxPlot" !== e && "rangeBar" !== e), s = "area" === e || "line" === e || "scatter" === e || "bubble" === e || "radar" === e, r = t.globals.dom.Paper.node, o = this.getElGrid(); o && (this.seriesBound = o.getBoundingClientRect()); var n, l = [], h = [], c = { hoverArea: r, elGrid: o, tooltipEl: i, tooltipY: l, tooltipX: h, ttItems: this.ttItems }; if (t.globals.axisCharts && (s ? n = t.globals.dom.baseEl.querySelectorAll(".apexcharts-series[data\\:longestSeries='true'] .apexcharts-marker") : a ? n = t.globals.dom.baseEl.querySelectorAll(".apexcharts-series .apexcharts-bar-area, .apexcharts-series .apexcharts-candlestick-area, .apexcharts-series .apexcharts-boxPlot-area, .apexcharts-series .apexcharts-rangebar-area") : "heatmap" !== e && "treemap" !== e || (n = t.globals.dom.baseEl.querySelectorAll(".apexcharts-series .apexcharts-heatmap, .apexcharts-series .apexcharts-treemap")), n && n.length)) for (var d = 0; d < n.length; d++)l.push(n[d].getAttribute("cy")), h.push(n[d].getAttribute("cx")); if (t.globals.xyCharts && !this.showOnIntersect || t.globals.comboCharts && !this.showOnIntersect || a && this.tooltipUtil.hasBars() && this.tConfig.shared) this.addPathsEventListeners([r], c); else if (a && !t.globals.comboCharts || s && this.showOnIntersect) this.addDatapointEventsListeners(c); else if (!t.globals.axisCharts || "heatmap" === e || "treemap" === e) { var g = t.globals.dom.baseEl.querySelectorAll(".apexcharts-series"); this.addPathsEventListeners(g, c) } if (this.showOnIntersect) { var u = t.globals.dom.baseEl.querySelectorAll(".apexcharts-line-series .apexcharts-marker, .apexcharts-area-series .apexcharts-marker"); u.length > 0 && this.addPathsEventListeners(u, c), this.tooltipUtil.hasBars() && !this.tConfig.shared && this.addDatapointEventsListeners(c) } } }, { key: "drawFixedTooltipRect", value: function () { var t = this.w, e = this.getElTooltip(), i = e.getBoundingClientRect(), a = i.width + 10, s = i.height + 10, r = this.tConfig.fixed.offsetX, o = this.tConfig.fixed.offsetY, n = this.tConfig.fixed.position.toLowerCase(); return n.indexOf("right") > -1 && (r = r + t.globals.svgWidth - a + 10), n.indexOf("bottom") > -1 && (o = o + t.globals.svgHeight - s - 10), e.style.left = r + "px", e.style.top = o + "px", { x: r, y: o, ttWidth: a, ttHeight: s } } }, { key: "addDatapointEventsListeners", value: function (t) { var e = this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers .apexcharts-marker, .apexcharts-bar-area, .apexcharts-candlestick-area, .apexcharts-boxPlot-area, .apexcharts-rangebar-area"); this.addPathsEventListeners(e, t) } }, { key: "addPathsEventListeners", value: function (t, e) { for (var i = this, a = function (a) { var s = { paths: t[a], tooltipEl: e.tooltipEl, tooltipY: e.tooltipY, tooltipX: e.tooltipX, elGrid: e.elGrid, hoverArea: e.hoverArea, ttItems: e.ttItems };["mousemove", "mouseup", "touchmove", "mouseout", "touchend"].map((function (e) { return t[a].addEventListener(e, i.onSeriesHover.bind(i, s), { capture: !1, passive: !0 }) })) }, s = 0; s < t.length; s++)a(s) } }, { key: "onSeriesHover", value: function (t, e) { var i = this, a = Date.now() - this.lastHoverTime; a >= 100 ? this.seriesHover(t, e) : (clearTimeout(this.seriesHoverTimeout), this.seriesHoverTimeout = setTimeout((function () { i.seriesHover(t, e) }), 100 - a)) } }, { key: "seriesHover", value: function (t, e) { var i = this; this.lastHoverTime = Date.now(); var a = [], s = this.w; s.config.chart.group && (a = this.ctx.getGroupedCharts()), s.globals.axisCharts && (s.globals.minX === -1 / 0 && s.globals.maxX === 1 / 0 || 0 === s.globals.dataPoints) || (a.length ? a.forEach((function (a) { var s = i.getElTooltip(a), r = { paths: t.paths, tooltipEl: s, tooltipY: t.tooltipY, tooltipX: t.tooltipX, elGrid: t.elGrid, hoverArea: t.hoverArea, ttItems: a.w.globals.tooltip.ttItems }; a.w.globals.minX === i.w.globals.minX && a.w.globals.maxX === i.w.globals.maxX && a.w.globals.tooltip.seriesHoverByContext({ chartCtx: a, ttCtx: a.w.globals.tooltip, opt: r, e: e }) })) : this.seriesHoverByContext({ chartCtx: this.ctx, ttCtx: this.w.globals.tooltip, opt: t, e: e })) } }, { key: "seriesHoverByContext", value: function (t) { var e = t.chartCtx, i = t.ttCtx, a = t.opt, s = t.e, r = e.w, o = this.getElTooltip(); if (o) { if (i.tooltipRect = { x: 0, y: 0, ttWidth: o.getBoundingClientRect().width, ttHeight: o.getBoundingClientRect().height }, i.e = s, i.tooltipUtil.hasBars() && !r.globals.comboCharts && !i.isBarShared) if (this.tConfig.onDatasetHover.highlightDataSeries) new W(e).toggleSeriesOnHover(s, s.target.parentNode); i.fixedTooltip && i.drawFixedTooltipRect(), r.globals.axisCharts ? i.axisChartsTooltips({ e: s, opt: a, tooltipRect: i.tooltipRect }) : i.nonAxisChartsTooltips({ e: s, opt: a, tooltipRect: i.tooltipRect }) } } }, { key: "axisChartsTooltips", value: function (t) { var e, i, a = t.e, s = t.opt, r = this.w, o = s.elGrid.getBoundingClientRect(), n = "touchmove" === a.type ? a.touches[0].clientX : a.clientX, l = "touchmove" === a.type ? a.touches[0].clientY : a.clientY; if (this.clientY = l, this.clientX = n, r.globals.capturedSeriesIndex = -1, r.globals.capturedDataPointIndex = -1, l < o.top || l > o.top + o.height) this.handleMouseOut(s); else { if (Array.isArray(this.tConfig.enabledOnSeries) && !r.config.tooltip.shared) { var h = parseInt(s.paths.getAttribute("index"), 10); if (this.tConfig.enabledOnSeries.indexOf(h) < 0) return void this.handleMouseOut(s) } var c = this.getElTooltip(), d = this.getElXCrosshairs(), g = r.globals.xyCharts || "bar" === r.config.chart.type && !r.globals.isBarHorizontal && this.tooltipUtil.hasBars() && this.tConfig.shared || r.globals.comboCharts && this.tooltipUtil.hasBars(); if ("mousemove" === a.type || "touchmove" === a.type || "mouseup" === a.type) { if (r.globals.collapsedSeries.length + r.globals.ancillaryCollapsedSeries.length === r.globals.series.length) return; null !== d && d.classList.add("apexcharts-active"); var u = this.yaxisTooltips.filter((function (t) { return !0 === t })); if (null !== this.ycrosshairs && u.length && this.ycrosshairs.classList.add("apexcharts-active"), g && !this.showOnIntersect) this.handleStickyTooltip(a, n, l, s); else if ("heatmap" === r.config.chart.type || "treemap" === r.config.chart.type) { var p = this.intersect.handleHeatTreeTooltip({ e: a, opt: s, x: e, y: i, type: r.config.chart.type }); e = p.x, i = p.y, c.style.left = e + "px", c.style.top = i + "px" } else this.tooltipUtil.hasBars() && this.intersect.handleBarTooltip({ e: a, opt: s }), this.tooltipUtil.hasMarkers() && this.intersect.handleMarkerTooltip({ e: a, opt: s, x: e, y: i }); if (this.yaxisTooltips.length) for (var f = 0; f < r.config.yaxis.length; f++)this.axesTooltip.drawYaxisTooltipText(f, l, this.xyRatios); s.tooltipEl.classList.add("apexcharts-active") } else "mouseout" !== a.type && "touchend" !== a.type || this.handleMouseOut(s) } } }, { key: "nonAxisChartsTooltips", value: function (t) { var e = t.e, i = t.opt, a = t.tooltipRect, s = this.w, r = i.paths.getAttribute("rel"), o = this.getElTooltip(), n = s.globals.dom.elWrap.getBoundingClientRect(); if ("mousemove" === e.type || "touchmove" === e.type) { o.classList.add("apexcharts-active"), this.tooltipLabels.drawSeriesTexts({ ttItems: i.ttItems, i: parseInt(r, 10) - 1, shared: !1 }); var l = s.globals.clientX - n.left - a.ttWidth / 2, h = s.globals.clientY - n.top - a.ttHeight - 10; if (o.style.left = l + "px", o.style.top = h + "px", s.config.legend.tooltipHoverFormatter) { var c = r - 1, d = (0, s.config.legend.tooltipHoverFormatter)(this.legendLabels[c].getAttribute("data:default-text"), { seriesIndex: c, dataPointIndex: c, w: s }); this.legendLabels[c].innerHTML = d } } else "mouseout" !== e.type && "touchend" !== e.type || (o.classList.remove("apexcharts-active"), s.config.legend.tooltipHoverFormatter && this.legendLabels.forEach((function (t) { var e = t.getAttribute("data:default-text"); t.innerHTML = decodeURIComponent(e) }))) } }, { key: "handleStickyTooltip", value: function (t, e, i, a) { var s = this.w, r = this.tooltipUtil.getNearestValues({ context: this, hoverArea: a.hoverArea, elGrid: a.elGrid, clientX: e, clientY: i }), o = r.j, n = r.capturedSeries; s.globals.collapsedSeriesIndices.includes(n) && (n = null); var l = a.elGrid.getBoundingClientRect(); if (r.hoverX < 0 || r.hoverX > l.width) this.handleMouseOut(a); else if (null !== n) this.handleStickyCapturedSeries(t, n, a, o); else if (this.tooltipUtil.isXoverlap(o) || s.globals.isBarHorizontal) { var h = s.globals.series.findIndex((function (t, e) { return !s.globals.collapsedSeriesIndices.includes(e) })); this.create(t, this, h, o, a.ttItems) } } }, { key: "handleStickyCapturedSeries", value: function (t, e, i, a) { var s = this.w; if (!this.tConfig.shared && null === s.globals.series[e][a]) return void this.handleMouseOut(i); if (void 0 !== s.globals.series[e][a]) this.tConfig.shared && this.tooltipUtil.isXoverlap(a) && this.tooltipUtil.isInitialSeriesSameLen() ? this.create(t, this, e, a, i.ttItems) : this.create(t, this, e, a, i.ttItems, !1); else if (this.tooltipUtil.isXoverlap(a)) { var r = s.globals.series.findIndex((function (t, e) { return !s.globals.collapsedSeriesIndices.includes(e) })); this.create(t, this, r, a, i.ttItems) } } }, { key: "deactivateHoverFilter", value: function () { for (var t = this.w, e = new m(this.ctx), i = t.globals.dom.Paper.select(".apexcharts-bar-area"), a = 0; a < i.length; a++)e.pathMouseLeave(i[a]) } }, { key: "handleMouseOut", value: function (t) { var e = this.w, i = this.getElXCrosshairs(); if (t.tooltipEl.classList.remove("apexcharts-active"), this.deactivateHoverFilter(), "bubble" !== e.config.chart.type && this.marker.resetPointsSize(), null !== i && i.classList.remove("apexcharts-active"), null !== this.ycrosshairs && this.ycrosshairs.classList.remove("apexcharts-active"), this.isXAxisTooltipEnabled && this.xaxisTooltip.classList.remove("apexcharts-active"), this.yaxisTooltips.length) { null === this.yaxisTTEls && (this.yaxisTTEls = e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip")); for (var a = 0; a < this.yaxisTTEls.length; a++)this.yaxisTTEls[a].classList.remove("apexcharts-active") } e.config.legend.tooltipHoverFormatter && this.legendLabels.forEach((function (t) { var e = t.getAttribute("data:default-text"); t.innerHTML = decodeURIComponent(e) })) } }, { key: "markerClick", value: function (t, e, i) { var a = this.w; "function" == typeof a.config.chart.events.markerClick && a.config.chart.events.markerClick(t, this.ctx, { seriesIndex: e, dataPointIndex: i, w: a }), this.ctx.events.fireEvent("markerClick", [t, this.ctx, { seriesIndex: e, dataPointIndex: i, w: a }]) } }, { key: "create", value: function (t, i, a, s, r) { var o, n, l, h, c, d, g, u, p, f, x, b, v, y, w, k, A = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : null, S = this.w, C = i; "mouseup" === t.type && this.markerClick(t, a, s), null === A && (A = this.tConfig.shared); var L = this.tooltipUtil.hasMarkers(a), P = this.tooltipUtil.getElBars(); if (S.config.legend.tooltipHoverFormatter) { var M = S.config.legend.tooltipHoverFormatter, I = Array.from(this.legendLabels); I.forEach((function (t) { var e = t.getAttribute("data:default-text"); t.innerHTML = decodeURIComponent(e) })); for (var T = 0; T < I.length; T++) { var z = I[T], X = parseInt(z.getAttribute("i"), 10), E = decodeURIComponent(z.getAttribute("data:default-text")), Y = M(E, { seriesIndex: A ? X : a, dataPointIndex: s, w: S }); if (A) z.innerHTML = S.globals.collapsedSeriesIndices.indexOf(X) < 0 ? Y : E; else if (z.innerHTML = X === a ? Y : E, a === X) break } } var F = e(e({ ttItems: r, i: a, j: s }, void 0 !== (null === (o = S.globals.seriesRange) || void 0 === o || null === (n = o[a]) || void 0 === n || null === (l = n[s]) || void 0 === l || null === (h = l.y[0]) || void 0 === h ? void 0 : h.y1) && { y1: null === (c = S.globals.seriesRange) || void 0 === c || null === (d = c[a]) || void 0 === d || null === (g = d[s]) || void 0 === g || null === (u = g.y[0]) || void 0 === u ? void 0 : u.y1 }), void 0 !== (null === (p = S.globals.seriesRange) || void 0 === p || null === (f = p[a]) || void 0 === f || null === (x = f[s]) || void 0 === x || null === (b = x.y[0]) || void 0 === b ? void 0 : b.y2) && { y2: null === (v = S.globals.seriesRange) || void 0 === v || null === (y = v[a]) || void 0 === y || null === (w = y[s]) || void 0 === w || null === (k = w.y[0]) || void 0 === k ? void 0 : k.y2 }); if (A) { if (C.tooltipLabels.drawSeriesTexts(e(e({}, F), {}, { shared: !this.showOnIntersect && this.tConfig.shared })), L) S.globals.markers.largestSize > 0 ? C.marker.enlargePoints(s) : C.tooltipPosition.moveDynamicPointsOnHover(s); else if (this.tooltipUtil.hasBars() && (this.barSeriesHeight = this.tooltipUtil.getBarsHeight(P), this.barSeriesHeight > 0)) { var R = new m(this.ctx), H = S.globals.dom.Paper.select(".apexcharts-bar-area[j='".concat(s, "']")); this.deactivateHoverFilter(), this.tooltipPosition.moveStickyTooltipOverBars(s, a); for (var D = 0; D < H.length; D++)R.pathMouseEnter(H[D]) } } else C.tooltipLabels.drawSeriesTexts(e({ shared: !1 }, F)), this.tooltipUtil.hasBars() && C.tooltipPosition.moveStickyTooltipOverBars(s, a), L && C.tooltipPosition.moveMarkers(a, s) } }]), t }(), vt = function () { function t(e) { a(this, t), this.w = e.w, this.barCtx = e, this.totalFormatter = this.w.config.plotOptions.bar.dataLabels.total.formatter, this.totalFormatter || (this.totalFormatter = this.w.config.dataLabels.formatter) } return r(t, [{ key: "handleBarDataLabels", value: function (t) { var e, i, a = t.x, s = t.y, r = t.y1, o = t.y2, n = t.i, l = t.j, h = t.realIndex, c = t.columnGroupIndex, d = t.series, g = t.barHeight, u = t.barWidth, p = t.barXPosition, f = t.barYPosition, x = t.visibleSeries, b = t.renderedPath, v = this.w, y = new m(this.barCtx.ctx), w = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[h] : this.barCtx.strokeWidth; v.globals.isXNumeric && !v.globals.isBarHorizontal ? (e = a + parseFloat(u * (x + 1)), i = s + parseFloat(g * (x + 1)) - w) : (e = a + parseFloat(u * x), i = s + parseFloat(g * x)); var k, A = null, S = a, C = s, L = {}, P = v.config.dataLabels, M = this.barCtx.barOptions.dataLabels, I = this.barCtx.barOptions.dataLabels.total; void 0 !== f && this.barCtx.isRangeBar && (i = f, C = f), void 0 !== p && this.barCtx.isVerticalGroupedRangeBar && (e = p, S = p); var T = P.offsetX, z = P.offsetY, X = { width: 0, height: 0 }; if (v.config.dataLabels.enabled) { var E = this.barCtx.series[n][l]; X = y.getTextRects(v.globals.yLabelFormatters[0](E), parseFloat(P.style.fontSize)) } var Y = { x: a, y: s, i: n, j: l, realIndex: h, columnGroupIndex: c, renderedPath: b, bcx: e, bcy: i, barHeight: g, barWidth: u, textRects: X, strokeWidth: w, dataLabelsX: S, dataLabelsY: C, dataLabelsConfig: P, barDataLabelsConfig: M, barTotalDataLabelsConfig: I, offX: T, offY: z }; return L = this.barCtx.isHorizontal ? this.calculateBarsDataLabelsPosition(Y) : this.calculateColumnsDataLabelsPosition(Y), b.attr({ cy: L.bcy, cx: L.bcx, j: l, val: d[n][l], barHeight: g, barWidth: u }), k = this.drawCalculatedDataLabels({ x: L.dataLabelsX, y: L.dataLabelsY, val: this.barCtx.isRangeBar ? [r, o] : d[n][l], i: h, j: l, barWidth: u, barHeight: g, textRects: X, dataLabelsConfig: P }), v.config.chart.stacked && I.enabled && (A = this.drawTotalDataLabels({ x: L.totalDataLabelsX, y: L.totalDataLabelsY, barWidth: u, barHeight: g, realIndex: h, textAnchor: L.totalDataLabelsAnchor, val: this.getStackedTotalDataLabel({ realIndex: h, j: l }), dataLabelsConfig: P, barTotalDataLabelsConfig: I })), { dataLabels: k, totalDataLabels: A } } }, { key: "getStackedTotalDataLabel", value: function (t) { var i = t.realIndex, a = t.j, s = this.w, r = this.barCtx.stackedSeriesTotals[a]; return this.totalFormatter && (r = this.totalFormatter(r, e(e({}, s), {}, { seriesIndex: i, dataPointIndex: a, w: s }))), r } }, { key: "calculateColumnsDataLabelsPosition", value: function (t) { var e, i, a = this.w, s = t.i, r = t.j, o = t.realIndex, n = t.columnGroupIndex, l = t.y, h = t.bcx, c = t.barWidth, d = t.barHeight, g = t.textRects, u = t.dataLabelsX, p = t.dataLabelsY, f = t.dataLabelsConfig, x = t.barDataLabelsConfig, b = t.barTotalDataLabelsConfig, v = t.strokeWidth, y = t.offX, w = t.offY, k = h; d = Math.abs(d); var A = "vertical" === a.config.plotOptions.bar.dataLabels.orientation, S = this.barCtx.barHelpers.getZeroValueEncounters({ i: s, j: r }).zeroEncounters; h = h - v / 2 + n * c; var C = a.globals.gridWidth / a.globals.dataPoints; if (this.barCtx.isVerticalGroupedRangeBar ? u += c / 2 : (u = a.globals.isXNumeric ? h - c / 2 + y : h - C + c / 2 + y, S > 0 && a.config.plotOptions.bar.hideZeroBarsWhenGrouped && (u -= c * S)), A) { u = u + g.height / 2 - v / 2 - 2 } var L = this.barCtx.series[s][r] < 0, P = l; switch (this.barCtx.isReversed && (P = l + (L ? d : -d), l -= d), x.position) { case "center": p = A ? L ? P - d / 2 + w : P + d / 2 - w : L ? P - d / 2 + g.height / 2 + w : P + d / 2 + g.height / 2 - w; break; case "bottom": p = A ? L ? P - d + w : P + d - w : L ? P - d + g.height + v + w : P + d - g.height / 2 + v - w; break; case "top": p = A ? L ? P + w : P - w : L ? P - g.height / 2 - w : P + g.height + w }if (this.barCtx.lastActiveBarSerieIndex === o && b.enabled) { var M = new m(this.barCtx.ctx).getTextRects(this.getStackedTotalDataLabel({ realIndex: o, j: r }), f.fontSize); e = L ? P - M.height / 2 - w - b.offsetY + 18 : P + M.height + w + b.offsetY - 18, i = k + (a.globals.isXNumeric ? c * (a.globals.barGroups.length - 1) - c / 2 : -(c * a.globals.barGroups.length - c / 2 - 2 * v)) + b.offsetX } return a.config.chart.stacked || (p < 0 ? p = 0 + v : p + g.height / 3 > a.globals.gridHeight && (p = a.globals.gridHeight - v)), { bcx: h, bcy: l, dataLabelsX: u, dataLabelsY: p, totalDataLabelsX: i, totalDataLabelsY: e, totalDataLabelsAnchor: "middle" } } }, { key: "calculateBarsDataLabelsPosition", value: function (t) { var e = this.w, i = t.x, a = t.i, s = t.j, r = t.realIndex, o = t.columnGroupIndex, n = t.bcy, l = t.barHeight, h = t.barWidth, c = t.textRects, d = t.dataLabelsX, g = t.strokeWidth, u = t.dataLabelsConfig, p = t.barDataLabelsConfig, f = t.barTotalDataLabelsConfig, x = t.offX, b = t.offY, v = e.globals.gridHeight / e.globals.dataPoints; h = Math.abs(h); var y, w, k = (n += o * l) - (this.barCtx.isRangeBar ? 0 : v) + l / 2 + c.height / 2 + b - 3, A = "start", S = this.barCtx.series[a][s] < 0, C = i; switch (this.barCtx.isReversed && (C = i + (S ? -h : h), i = e.globals.gridWidth - h, A = S ? "start" : "end"), p.position) { case "center": d = S ? C + h / 2 - x : Math.max(c.width / 2, C - h / 2) + x; break; case "bottom": d = S ? C + h - g - Math.round(c.width / 2) - x : C - h + g + Math.round(c.width / 2) + x; break; case "top": d = S ? C - g + Math.round(c.width / 2) - x : C - g - Math.round(c.width / 2) + x }if (this.barCtx.lastActiveBarSerieIndex === r && f.enabled) { var L = new m(this.barCtx.ctx).getTextRects(this.getStackedTotalDataLabel({ realIndex: r, j: s }), u.fontSize); S ? (y = C - g - x - f.offsetX, A = "end") : y = C + x + f.offsetX + (this.barCtx.isReversed ? -(h + g) : g), w = k - c.height / 2 + L.height / 2 + f.offsetY + g } return e.config.chart.stacked || (d < 0 ? d = d + c.width + g : d + c.width / 2 > e.globals.gridWidth && (d = e.globals.gridWidth - c.width - g)), { bcx: i, bcy: n, dataLabelsX: d, dataLabelsY: k, totalDataLabelsX: y, totalDataLabelsY: w, totalDataLabelsAnchor: A } } }, { key: "drawCalculatedDataLabels", value: function (t) { var i = t.x, a = t.y, s = t.val, r = t.i, o = t.j, n = t.textRects, l = t.barHeight, h = t.barWidth, c = t.dataLabelsConfig, d = this.w, g = "rotate(0)"; "vertical" === d.config.plotOptions.bar.dataLabels.orientation && (g = "rotate(-90, ".concat(i, ", ").concat(a, ")")); var u = new N(this.barCtx.ctx), p = new m(this.barCtx.ctx), f = c.formatter, x = null, b = d.globals.collapsedSeriesIndices.indexOf(r) > -1; if (c.enabled && !b) { x = p.group({ class: "apexcharts-data-labels", transform: g }); var v = ""; void 0 !== s && (v = f(s, e(e({}, d), {}, { seriesIndex: r, dataPointIndex: o, w: d }))), !s && d.config.plotOptions.bar.hideZeroBarsWhenGrouped && (v = ""); var y = d.globals.series[r][o] < 0, w = d.config.plotOptions.bar.dataLabels.position; if ("vertical" === d.config.plotOptions.bar.dataLabels.orientation && ("top" === w && (c.textAnchor = y ? "end" : "start"), "center" === w && (c.textAnchor = "middle"), "bottom" === w && (c.textAnchor = y ? "end" : "start")), this.barCtx.isRangeBar && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) h < p.getTextRects(v, parseFloat(c.style.fontSize)).width && (v = ""); d.config.chart.stacked && this.barCtx.barOptions.dataLabels.hideOverflowingLabels && (this.barCtx.isHorizontal ? n.width / 1.6 > Math.abs(h) && (v = "") : n.height / 1.6 > Math.abs(l) && (v = "")); var k = e({}, c); this.barCtx.isHorizontal && s < 0 && ("start" === c.textAnchor ? k.textAnchor = "end" : "end" === c.textAnchor && (k.textAnchor = "start")), u.plotDataLabelsText({ x: i, y: a, text: v, i: r, j: o, parent: x, dataLabelsConfig: k, alwaysDrawDataLabel: !0, offsetCorrection: !0 }) } return x } }, { key: "drawTotalDataLabels", value: function (t) { var e, i = t.x, a = t.y, s = t.val, r = t.barWidth, o = t.barHeight, n = t.realIndex, l = t.textAnchor, h = t.barTotalDataLabelsConfig, c = this.w, d = new m(this.barCtx.ctx); return h.enabled && void 0 !== i && void 0 !== a && this.barCtx.lastActiveBarSerieIndex === n && (e = d.drawText({ x: i - (!c.globals.isBarHorizontal && c.globals.barGroups.length ? r * (c.globals.barGroups.length - 1) / 2 : 0), y: a - (c.globals.isBarHorizontal && c.globals.barGroups.length ? o * (c.globals.barGroups.length - 1) / 2 : 0), foreColor: h.style.color, text: s, textAnchor: l, fontFamily: h.style.fontFamily, fontSize: h.style.fontSize, fontWeight: h.style.fontWeight })), e } }]), t }(), mt = function () { function t(e) { a(this, t), this.w = e.w, this.barCtx = e } return r(t, [{ key: "initVariables", value: function (t) { var e = this.w; this.barCtx.series = t, this.barCtx.totalItems = 0, this.barCtx.seriesLen = 0, this.barCtx.visibleI = -1, this.barCtx.visibleItems = 1; for (var i = 0; i < t.length; i++)if (t[i].length > 0 && (this.barCtx.seriesLen = this.barCtx.seriesLen + 1, this.barCtx.totalItems += t[i].length), e.globals.isXNumeric) for (var a = 0; a < t[i].length; a++)e.globals.seriesX[i][a] > e.globals.minX && e.globals.seriesX[i][a] < e.globals.maxX && this.barCtx.visibleItems++; else this.barCtx.visibleItems = e.globals.dataPoints; 0 === this.barCtx.seriesLen && (this.barCtx.seriesLen = 1), this.barCtx.zeroSerieses = [], e.globals.comboCharts || this.checkZeroSeries({ series: t }) } }, { key: "initialPositions", value: function () { var t, e, i, a, s, r, o, n, l = this.w, h = l.globals.dataPoints; this.barCtx.isRangeBar && (h = l.globals.labels.length); var c = this.barCtx.seriesLen; if (l.config.plotOptions.bar.rangeBarGroupRows && (c = 1), this.barCtx.isHorizontal) s = (i = l.globals.gridHeight / h) / c, l.globals.isXNumeric && (s = (i = l.globals.gridHeight / this.barCtx.totalItems) / this.barCtx.seriesLen), s = s * parseInt(this.barCtx.barOptions.barHeight, 10) / 100, -1 === String(this.barCtx.barOptions.barHeight).indexOf("%") && (s = parseInt(this.barCtx.barOptions.barHeight, 10)), n = this.barCtx.baseLineInvertedY + l.globals.padHorizontal + (this.barCtx.isReversed ? l.globals.gridWidth : 0) - (this.barCtx.isReversed ? 2 * this.barCtx.baseLineInvertedY : 0), this.barCtx.isFunnel && (n = l.globals.gridWidth / 2), e = (i - s * this.barCtx.seriesLen) / 2; else { if (a = l.globals.gridWidth / this.barCtx.visibleItems, l.config.xaxis.convertedCatToNumeric && (a = l.globals.gridWidth / l.globals.dataPoints), r = a / c * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100, l.globals.isXNumeric) { var d = this.barCtx.xRatio; l.globals.minXDiff && .5 !== l.globals.minXDiff && l.globals.minXDiff / d > 0 && (a = l.globals.minXDiff / d), (r = a / c * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100) < 1 && (r = 1) } -1 === String(this.barCtx.barOptions.columnWidth).indexOf("%") && (r = parseInt(this.barCtx.barOptions.columnWidth, 10)), o = l.globals.gridHeight - this.barCtx.baseLineY[this.barCtx.translationsIndex] - (this.barCtx.isReversed ? l.globals.gridHeight : 0) + (this.barCtx.isReversed ? 2 * this.barCtx.baseLineY[this.barCtx.translationsIndex] : 0), t = l.globals.padHorizontal + (a - r * this.barCtx.seriesLen) / 2 } return l.globals.barHeight = s, l.globals.barWidth = r, { x: t, y: e, yDivision: i, xDivision: a, barHeight: s, barWidth: r, zeroH: o, zeroW: n } } }, { key: "initializeStackedPrevVars", value: function (t) { t.w.globals.seriesGroups.forEach((function (e) { t[e] || (t[e] = {}), t[e].prevY = [], t[e].prevX = [], t[e].prevYF = [], t[e].prevXF = [], t[e].prevYVal = [], t[e].prevXVal = [] })) } }, { key: "initializeStackedXYVars", value: function (t) { t.w.globals.seriesGroups.forEach((function (e) { t[e] || (t[e] = {}), t[e].xArrj = [], t[e].xArrjF = [], t[e].xArrjVal = [], t[e].yArrj = [], t[e].yArrjF = [], t[e].yArrjVal = [] })) } }, { key: "getPathFillColor", value: function (t, e, i, a) { var s, r, o, n, l = this.w, h = new H(this.barCtx.ctx), c = null, d = this.barCtx.barOptions.distributed ? i : e; this.barCtx.barOptions.colors.ranges.length > 0 && this.barCtx.barOptions.colors.ranges.map((function (a) { t[e][i] >= a.from && t[e][i] <= a.to && (c = a.color) })); return l.config.series[e].data[i] && l.config.series[e].data[i].fillColor && (c = l.config.series[e].data[i].fillColor), h.fillPath({ seriesNumber: this.barCtx.barOptions.distributed ? d : a, dataPointIndex: i, color: c, value: t[e][i], fillConfig: null === (s = l.config.series[e].data[i]) || void 0 === s ? void 0 : s.fill, fillType: null !== (r = l.config.series[e].data[i]) && void 0 !== r && null !== (o = r.fill) && void 0 !== o && o.type ? null === (n = l.config.series[e].data[i]) || void 0 === n ? void 0 : n.fill.type : Array.isArray(l.config.fill.type) ? l.config.fill.type[e] : l.config.fill.type }) } }, { key: "getStrokeWidth", value: function (t, e, i) { var a = 0, s = this.w; return void 0 === this.barCtx.series[t][e] || null === this.barCtx.series[t][e] ? this.barCtx.isNullValue = !0 : this.barCtx.isNullValue = !1, s.config.stroke.show && (this.barCtx.isNullValue || (a = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[i] : this.barCtx.strokeWidth)), a } }, { key: "shouldApplyRadius", value: function (t) { var e = this.w, i = !1; return e.config.plotOptions.bar.borderRadius > 0 && (e.config.chart.stacked && "last" === e.config.plotOptions.bar.borderRadiusWhenStacked ? this.barCtx.lastActiveBarSerieIndex === t && (i = !0) : i = !0), i } }, { key: "barBackground", value: function (t) { var e = t.j, i = t.i, a = t.x1, s = t.x2, r = t.y1, o = t.y2, n = t.elSeries, l = this.w, h = new m(this.barCtx.ctx), c = new W(this.barCtx.ctx).getActiveConfigSeriesIndex(); if (this.barCtx.barOptions.colors.backgroundBarColors.length > 0 && c === i) { e >= this.barCtx.barOptions.colors.backgroundBarColors.length && (e %= this.barCtx.barOptions.colors.backgroundBarColors.length); var d = this.barCtx.barOptions.colors.backgroundBarColors[e], g = h.drawRect(void 0 !== a ? a : 0, void 0 !== r ? r : 0, void 0 !== s ? s : l.globals.gridWidth, void 0 !== o ? o : l.globals.gridHeight, this.barCtx.barOptions.colors.backgroundBarRadius, d, this.barCtx.barOptions.colors.backgroundBarOpacity); n.add(g), g.node.classList.add("apexcharts-backgroundBar") } } }, { key: "getColumnPaths", value: function (t) { var e, i = t.barWidth, a = t.barXPosition, s = t.y1, r = t.y2, o = t.strokeWidth, n = t.seriesGroup, l = t.realIndex, h = t.i, c = t.j, d = t.w, g = new m(this.barCtx.ctx); (o = Array.isArray(o) ? o[l] : o) || (o = 0); var u = i, p = a; null !== (e = d.config.series[l].data[c]) && void 0 !== e && e.columnWidthOffset && (p = a - d.config.series[l].data[c].columnWidthOffset / 2, u = i + d.config.series[l].data[c].columnWidthOffset); var f = o / 2, x = p + f, b = p + u - f; s += .001 - f, r += .001 + f; var v = g.move(x, s), y = g.move(x, s), w = g.line(b, s); if (d.globals.previousPaths.length > 0 && (y = this.barCtx.getPreviousPath(l, c, !1)), v = v + g.line(x, r) + g.line(b, r) + g.line(b, s) + ("around" === d.config.plotOptions.bar.borderRadiusApplication ? " Z" : " z"), y = y + g.line(x, s) + w + w + w + w + w + g.line(x, s) + ("around" === d.config.plotOptions.bar.borderRadiusApplication ? " Z" : " z"), this.shouldApplyRadius(l) && (v = g.roundPathCorners(v, d.config.plotOptions.bar.borderRadius)), d.config.chart.stacked) { var k = this.barCtx; (k = this.barCtx[n]).yArrj.push(r - f), k.yArrjF.push(Math.abs(s - r + o)), k.yArrjVal.push(this.barCtx.series[h][c]) } return { pathTo: v, pathFrom: y } } }, { key: "getBarpaths", value: function (t) { var e, i = t.barYPosition, a = t.barHeight, s = t.x1, r = t.x2, o = t.strokeWidth, n = t.seriesGroup, l = t.realIndex, h = t.i, c = t.j, d = t.w, g = new m(this.barCtx.ctx); (o = Array.isArray(o) ? o[l] : o) || (o = 0); var u = i, p = a; null !== (e = d.config.series[l].data[c]) && void 0 !== e && e.barHeightOffset && (u = i - d.config.series[l].data[c].barHeightOffset / 2, p = a + d.config.series[l].data[c].barHeightOffset); var f = o / 2, x = u + f, b = u + p - f; s += .001 - f, r += .001 + f; var v = g.move(s, x), y = g.move(s, x); d.globals.previousPaths.length > 0 && (y = this.barCtx.getPreviousPath(l, c, !1)); var w = g.line(s, b); if (v = v + g.line(r, x) + g.line(r, b) + w + ("around" === d.config.plotOptions.bar.borderRadiusApplication ? " Z" : " z"), y = y + g.line(s, x) + w + w + w + w + w + g.line(s, x) + ("around" === d.config.plotOptions.bar.borderRadiusApplication ? " Z" : " z"), this.shouldApplyRadius(l) && (v = g.roundPathCorners(v, d.config.plotOptions.bar.borderRadius)), d.config.chart.stacked) { var k = this.barCtx; (k = this.barCtx[n]).xArrj.push(r + f), k.xArrjF.push(Math.abs(s - r)), k.xArrjVal.push(this.barCtx.series[h][c]) } return { pathTo: v, pathFrom: y } } }, { key: "checkZeroSeries", value: function (t) { for (var e = t.series, i = this.w, a = 0; a < e.length; a++) { for (var s = 0, r = 0; r < e[i.globals.maxValsInArrayIndex].length; r++)s += e[a][r]; 0 === s && this.barCtx.zeroSerieses.push(a) } } }, { key: "getXForValue", value: function (t, e) { var i = !(arguments.length > 2 && void 0 !== arguments[2]) || arguments[2] ? e : null; return null != t && (i = e + t / this.barCtx.invertedYRatio - 2 * (this.barCtx.isReversed ? t / this.barCtx.invertedYRatio : 0)), i } }, { key: "getYForValue", value: function (t, e, i) { var a = !(arguments.length > 3 && void 0 !== arguments[3]) || arguments[3] ? e : null; return null != t && (a = e - t / this.barCtx.yRatio[i] + 2 * (this.barCtx.isReversed ? t / this.barCtx.yRatio[i] : 0)), a } }, { key: "getGoalValues", value: function (t, i, a, s, r, n) { var l = this, h = this.w, c = [], d = function (e, s) { var r; c.push((o(r = {}, t, "x" === t ? l.getXForValue(e, i, !1) : l.getYForValue(e, a, n, !1)), o(r, "attrs", s), r)) }; if (h.globals.seriesGoals[s] && h.globals.seriesGoals[s][r] && Array.isArray(h.globals.seriesGoals[s][r]) && h.globals.seriesGoals[s][r].forEach((function (t) { d(t.value, t) })), this.barCtx.barOptions.isDumbbell && h.globals.seriesRange.length) { var g = this.barCtx.barOptions.dumbbellColors ? this.barCtx.barOptions.dumbbellColors : h.globals.colors, u = { strokeHeight: "x" === t ? 0 : h.globals.markers.size[s], strokeWidth: "x" === t ? h.globals.markers.size[s] : 0, strokeDashArray: 0, strokeLineCap: "round", strokeColor: Array.isArray(g[s]) ? g[s][0] : g[s] }; d(h.globals.seriesRangeStart[s][r], u), d(h.globals.seriesRangeEnd[s][r], e(e({}, u), {}, { strokeColor: Array.isArray(g[s]) ? g[s][1] : g[s] })) } return c } }, { key: "drawGoalLine", value: function (t) { var e = t.barXPosition, i = t.barYPosition, a = t.goalX, s = t.goalY, r = t.barWidth, o = t.barHeight, n = new m(this.barCtx.ctx), l = n.group({ className: "apexcharts-bar-goals-groups" }); l.node.classList.add("apexcharts-element-hidden"), this.barCtx.w.globals.delayedElements.push({ el: l.node }), l.attr("clip-path", "url(#gridRectMarkerMask".concat(this.barCtx.w.globals.cuid, ")")); var h = null; return this.barCtx.isHorizontal ? Array.isArray(a) && a.forEach((function (t) { if (t.x >= -1 && t.x <= n.w.globals.gridWidth + 1) { var e = void 0 !== t.attrs.strokeHeight ? t.attrs.strokeHeight : o / 2, a = i + e + o / 2; h = n.drawLine(t.x, a - 2 * e, t.x, a, t.attrs.strokeColor ? t.attrs.strokeColor : void 0, t.attrs.strokeDashArray, t.attrs.strokeWidth ? t.attrs.strokeWidth : 2, t.attrs.strokeLineCap), l.add(h) } })) : Array.isArray(s) && s.forEach((function (t) { if (t.y >= -1 && t.y <= n.w.globals.gridHeight + 1) { var i = void 0 !== t.attrs.strokeWidth ? t.attrs.strokeWidth : r / 2, a = e + i + r / 2; h = n.drawLine(a - 2 * i, t.y, a, t.y, t.attrs.strokeColor ? t.attrs.strokeColor : void 0, t.attrs.strokeDashArray, t.attrs.strokeHeight ? t.attrs.strokeHeight : 2, t.attrs.strokeLineCap), l.add(h) } })), l } }, { key: "drawBarShadow", value: function (t) { var e = t.prevPaths, i = t.currPaths, a = t.color, s = this.w, r = e.x, o = e.x1, n = e.barYPosition, l = i.x, h = i.x1, c = i.barYPosition, d = n + i.barHeight, g = new m(this.barCtx.ctx), u = new x, p = g.move(o, d) + g.line(r, d) + g.line(l, c) + g.line(h, c) + g.line(o, d) + ("around" === s.config.plotOptions.bar.borderRadiusApplication ? " Z" : " z"); return g.drawPath({ d: p, fill: u.shadeColor(.5, x.rgb2hex(a)), stroke: "none", strokeWidth: 0, fillOpacity: 1, classes: "apexcharts-bar-shadows" }) } }, { key: "getZeroValueEncounters", value: function (t) { var e, i = t.i, a = t.j, s = this.w, r = 0, o = 0; return (s.config.plotOptions.bar.horizontal ? s.globals.series.map((function (t, e) { return e })) : (null === (e = s.globals.columnSeries) || void 0 === e ? void 0 : e.i.map((function (t) { return t }))) || []).forEach((function (t) { var e = s.globals.seriesPercent[t][a]; e && r++, t < i && 0 === e && o++ })), { nonZeroColumns: r, zeroEncounters: o } } }, { key: "getGroupIndex", value: function (t) { var e = this.w, i = e.globals.seriesGroups.findIndex((function (i) { return i.indexOf(e.globals.seriesNames[t]) > -1 })), a = this.barCtx.columnGroupIndices, s = a.indexOf(i); return s < 0 && (a.push(i), s = a.length - 1), { groupIndex: i, columnGroupIndex: s } } }]), t }(), yt = function () { function t(e, i) { a(this, t), this.ctx = e, this.w = e.w; var s = this.w; this.barOptions = s.config.plotOptions.bar, this.isHorizontal = this.barOptions.horizontal, this.strokeWidth = s.config.stroke.width, this.isNullValue = !1, this.isRangeBar = s.globals.seriesRange.length && this.isHorizontal, this.isVerticalGroupedRangeBar = !s.globals.isBarHorizontal && s.globals.seriesRange.length && s.config.plotOptions.bar.rangeBarGroupRows, this.isFunnel = this.barOptions.isFunnel, this.xyRatios = i, null !== this.xyRatios && (this.xRatio = i.xRatio, this.yRatio = i.yRatio, this.invertedXRatio = i.invertedXRatio, this.invertedYRatio = i.invertedYRatio, this.baseLineY = i.baseLineY, this.baseLineInvertedY = i.baseLineInvertedY), this.yaxisIndex = 0, this.translationsIndex = 0, this.seriesLen = 0, this.pathArr = []; var r = new W(this.ctx); this.lastActiveBarSerieIndex = r.getActiveConfigSeriesIndex("desc", ["bar", "column"]), this.columnGroupIndices = []; var o = r.getBarSeriesIndices(), n = new y(this.ctx); this.stackedSeriesTotals = n.getStackedSeriesTotals(this.w.config.series.map((function (t, e) { return -1 === o.indexOf(e) ? e : -1 })).filter((function (t) { return -1 !== t }))), this.barHelpers = new mt(this) } return r(t, [{ key: "draw", value: function (t, i) { var a = this.w, s = new m(this.ctx), r = new y(this.ctx, a); t = r.getLogSeries(t), this.series = t, this.yRatio = r.getLogYRatios(this.yRatio), this.barHelpers.initVariables(t); var o = s.group({ class: "apexcharts-bar-series apexcharts-plot-series" }); a.config.dataLabels.enabled && this.totalItems > this.barOptions.dataLabels.maxItems && console.warn("WARNING: DataLabels are enabled but there are too many to display. This may cause performance issue when rendering - ApexCharts"); for (var n = 0, l = 0; n < t.length; n++, l++) { var h, c, d, g, u = void 0, p = void 0, f = [], b = [], v = a.globals.comboCharts ? i[n] : n, w = this.barHelpers.getGroupIndex(v).columnGroupIndex, k = s.group({ class: "apexcharts-series", rel: n + 1, seriesName: x.escapeString(a.globals.seriesNames[v]), "data:realIndex": v }); this.ctx.series.addCollapsedClassToSeries(k, v), t[n].length > 0 && (this.visibleI = this.visibleI + 1); var A = 0, S = 0; this.yRatio.length > 1 && (this.yaxisIndex = a.globals.seriesYAxisReverseMap[v], this.translationsIndex = v); var C = this.translationsIndex; this.isReversed = a.config.yaxis[this.yaxisIndex] && a.config.yaxis[this.yaxisIndex].reversed; var L = this.barHelpers.initialPositions(); p = L.y, A = L.barHeight, c = L.yDivision, g = L.zeroW, u = L.x, S = L.barWidth, h = L.xDivision, d = L.zeroH, this.horizontal || b.push(u + S / 2); var P = s.group({ class: "apexcharts-datalabels", "data:realIndex": v }); a.globals.delayedElements.push({ el: P.node }), P.node.classList.add("apexcharts-element-hidden"); var M = s.group({ class: "apexcharts-bar-goals-markers" }), I = s.group({ class: "apexcharts-bar-shadows" }); a.globals.delayedElements.push({ el: I.node }), I.node.classList.add("apexcharts-element-hidden"); for (var T = 0; T < t[n].length; T++) { var z = this.barHelpers.getStrokeWidth(n, T, v), X = null, E = { indexes: { i: n, j: T, realIndex: v, translationsIndex: C, bc: l }, x: u, y: p, strokeWidth: z, elSeries: k }; this.isHorizontal ? (X = this.drawBarPaths(e(e({}, E), {}, { barHeight: A, zeroW: g, yDivision: c })), S = this.series[n][T] / this.invertedYRatio) : (X = this.drawColumnPaths(e(e({}, E), {}, { xDivision: h, barWidth: S, zeroH: d })), A = this.series[n][T] / this.yRatio[C]); var Y = this.barHelpers.getPathFillColor(t, n, T, v); if (this.isFunnel && this.barOptions.isFunnel3d && this.pathArr.length && T > 0) { var F = this.barHelpers.drawBarShadow({ color: "string" == typeof Y && -1 === (null == Y ? void 0 : Y.indexOf("url")) ? Y : x.hexToRgba(a.globals.colors[n]), prevPaths: this.pathArr[this.pathArr.length - 1], currPaths: X }); F && I.add(F) } this.pathArr.push(X); var R = this.barHelpers.drawGoalLine({ barXPosition: X.barXPosition, barYPosition: X.barYPosition, goalX: X.goalX, goalY: X.goalY, barHeight: A, barWidth: S }); R && M.add(R), p = X.y, u = X.x, T > 0 && b.push(u + S / 2), f.push(p), this.renderSeries({ realIndex: v, pathFill: Y, j: T, i: n, columnGroupIndex: w, pathFrom: X.pathFrom, pathTo: X.pathTo, strokeWidth: z, elSeries: k, x: u, y: p, series: t, barHeight: X.barHeight ? X.barHeight : A, barWidth: X.barWidth ? X.barWidth : S, elDataLabelsWrap: P, elGoalsMarkers: M, elBarShadows: I, visibleSeries: this.visibleI, type: "bar" }) } a.globals.seriesXvalues[v] = b, a.globals.seriesYvalues[v] = f, o.add(k) } return o } }, { key: "renderSeries", value: function (t) { var e = t.realIndex, i = t.pathFill, a = t.lineFill, s = t.j, r = t.i, o = t.columnGroupIndex, n = t.pathFrom, l = t.pathTo, h = t.strokeWidth, c = t.elSeries, d = t.x, g = t.y, u = t.y1, p = t.y2, f = t.series, x = t.barHeight, b = t.barWidth, y = t.barXPosition, w = t.barYPosition, k = t.elDataLabelsWrap, A = t.elGoalsMarkers, S = t.elBarShadows, C = t.visibleSeries, L = t.type, P = this.w, M = new m(this.ctx); if (!a) { var I = "function" == typeof P.globals.stroke.colors[e] ? function (t) { var e, i = P.config.stroke.colors; return Array.isArray(i) && i.length > 0 && ((e = i[t]) || (e = ""), "function" == typeof e) ? e({ value: P.globals.series[t][s], dataPointIndex: s, w: P }) : e }(e) : P.globals.stroke.colors[e]; a = this.barOptions.distributed ? P.globals.stroke.colors[s] : I } P.config.series[r].data[s] && P.config.series[r].data[s].strokeColor && (a = P.config.series[r].data[s].strokeColor), this.isNullValue && (i = "none"); var T = s / P.config.chart.animations.animateGradually.delay * (P.config.chart.animations.speed / P.globals.dataPoints) / 2.4, z = M.renderPaths({ i: r, j: s, realIndex: e, pathFrom: n, pathTo: l, stroke: a, strokeWidth: h, strokeLineCap: P.config.stroke.lineCap, fill: i, animationDelay: T, initialSpeed: P.config.chart.animations.speed, dataChangeSpeed: P.config.chart.animations.dynamicAnimation.speed, className: "apexcharts-".concat(L, "-area") }); z.attr("clip-path", "url(#gridRectMask".concat(P.globals.cuid, ")")); var X = P.config.forecastDataPoints; X.count > 0 && s >= P.globals.dataPoints - X.count && (z.node.setAttribute("stroke-dasharray", X.dashArray), z.node.setAttribute("stroke-width", X.strokeWidth), z.node.setAttribute("fill-opacity", X.fillOpacity)), void 0 !== u && void 0 !== p && (z.attr("data-range-y1", u), z.attr("data-range-y2", p)), new v(this.ctx).setSelectionFilter(z, e, s), c.add(z); var E = new vt(this).handleBarDataLabels({ x: d, y: g, y1: u, y2: p, i: r, j: s, series: f, realIndex: e, columnGroupIndex: o, barHeight: x, barWidth: b, barXPosition: y, barYPosition: w, renderedPath: z, visibleSeries: C }); return null !== E.dataLabels && k.add(E.dataLabels), E.totalDataLabels && k.add(E.totalDataLabels), c.add(k), A && c.add(A), S && c.add(S), c } }, { key: "drawBarPaths", value: function (t) { var e, i = t.indexes, a = t.barHeight, s = t.strokeWidth, r = t.zeroW, o = t.x, n = t.y, l = t.yDivision, h = t.elSeries, c = this.w, d = i.i, g = i.j; if (c.globals.isXNumeric) e = (n = (c.globals.seriesX[d][g] - c.globals.minX) / this.invertedXRatio - a) + a * this.visibleI; else if (c.config.plotOptions.bar.hideZeroBarsWhenGrouped) { var u = 0, p = 0; c.globals.seriesPercent.forEach((function (t, e) { t[g] && u++, e < d && 0 === t[g] && p++ })), u > 0 && (a = this.seriesLen * a / u), e = n + a * this.visibleI, e -= a * p } else e = n + a * this.visibleI; this.isFunnel && (r -= (this.barHelpers.getXForValue(this.series[d][g], r) - r) / 2), o = this.barHelpers.getXForValue(this.series[d][g], r); var f = this.barHelpers.getBarpaths({ barYPosition: e, barHeight: a, x1: r, x2: o, strokeWidth: s, series: this.series, realIndex: i.realIndex, i: d, j: g, w: c }); return c.globals.isXNumeric || (n += l), this.barHelpers.barBackground({ j: g, i: d, y1: e - a * this.visibleI, y2: a * this.seriesLen, elSeries: h }), { pathTo: f.pathTo, pathFrom: f.pathFrom, x1: r, x: o, y: n, goalX: this.barHelpers.getGoalValues("x", r, null, d, g), barYPosition: e, barHeight: a } } }, { key: "drawColumnPaths", value: function (t) { var e, i = t.indexes, a = t.x, s = t.y, r = t.xDivision, o = t.barWidth, n = t.zeroH, l = t.strokeWidth, h = t.elSeries, c = this.w, d = i.realIndex, g = i.translationsIndex, u = i.i, p = i.j, f = i.bc; if (c.globals.isXNumeric) { var x = this.getBarXForNumericXAxis({ x: a, j: p, realIndex: d, barWidth: o }); a = x.x, e = x.barXPosition } else if (c.config.plotOptions.bar.hideZeroBarsWhenGrouped) { var b = this.barHelpers.getZeroValueEncounters({ i: u, j: p }), v = b.nonZeroColumns, m = b.zeroEncounters; v > 0 && (o = this.seriesLen * o / v), e = a + o * this.visibleI, e -= o * m } else e = a + o * this.visibleI; s = this.barHelpers.getYForValue(this.series[u][p], n, g); var y = this.barHelpers.getColumnPaths({ barXPosition: e, barWidth: o, y1: n, y2: s, strokeWidth: l, series: this.series, realIndex: d, i: u, j: p, w: c }); return c.globals.isXNumeric || (a += r), this.barHelpers.barBackground({ bc: f, j: p, i: u, x1: e - l / 2 - o * this.visibleI, x2: o * this.seriesLen + l / 2, elSeries: h }), { pathTo: y.pathTo, pathFrom: y.pathFrom, x: a, y: s, goalY: this.barHelpers.getGoalValues("y", null, n, u, p, g), barXPosition: e, barWidth: o } } }, { key: "getBarXForNumericXAxis", value: function (t) { var e = t.x, i = t.barWidth, a = t.realIndex, s = t.j, r = this.w, o = a; return r.globals.seriesX[a].length || (o = r.globals.maxValsInArrayIndex), r.globals.seriesX[o][s] && (e = (r.globals.seriesX[o][s] - r.globals.minX) / this.xRatio - i * this.seriesLen / 2), { barXPosition: e + i * this.visibleI, x: e } } }, { key: "getPreviousPath", value: function (t, e) { for (var i, a = this.w, s = 0; s < a.globals.previousPaths.length; s++) { var r = a.globals.previousPaths[s]; r.paths && r.paths.length > 0 && parseInt(r.realIndex, 10) === parseInt(t, 10) && void 0 !== a.globals.previousPaths[s].paths[e] && (i = a.globals.previousPaths[s].paths[e].d) } return i } }]), t }(), wt = function (t) { n(s, t); var i = d(s); function s() { return a(this, s), i.apply(this, arguments) } return r(s, [{ key: "draw", value: function (t, i) { var a = this, s = this.w; this.graphics = new m(this.ctx), this.bar = new yt(this.ctx, this.xyRatios); var r = new y(this.ctx, s); t = r.getLogSeries(t), this.yRatio = r.getLogYRatios(this.yRatio), this.barHelpers.initVariables(t), "100%" === s.config.chart.stackType && (t = s.globals.comboCharts ? i.map((function (t) { return s.globals.seriesPercent[t] })) : s.globals.seriesPercent.slice()), this.series = t, this.barHelpers.initializeStackedPrevVars(this); for (var o = this.graphics.group({ class: "apexcharts-bar-series apexcharts-plot-series" }), n = 0, l = 0, h = function (r, h) { var c = void 0, d = void 0, g = void 0, u = void 0, p = s.globals.comboCharts ? i[r] : r, f = a.barHelpers.getGroupIndex(p), b = f.groupIndex, v = f.columnGroupIndex; a.groupCtx = a[s.globals.seriesGroups[b]]; var m = [], y = [], w = 0; a.yRatio.length > 1 && (a.yaxisIndex = s.globals.seriesYAxisReverseMap[p][0], w = p), a.isReversed = s.config.yaxis[a.yaxisIndex] && s.config.yaxis[a.yaxisIndex].reversed; var k = a.graphics.group({ class: "apexcharts-series", seriesName: x.escapeString(s.globals.seriesNames[p]), rel: r + 1, "data:realIndex": p }); a.ctx.series.addCollapsedClassToSeries(k, p); var A = a.graphics.group({ class: "apexcharts-datalabels", "data:realIndex": p }), S = a.graphics.group({ class: "apexcharts-bar-goals-markers" }), C = 0, L = 0, P = a.initialPositions(n, l, c, d, g, u, w); l = P.y, C = P.barHeight, d = P.yDivision, u = P.zeroW, n = P.x, L = P.barWidth, c = P.xDivision, g = P.zeroH, s.globals.barHeight = C, s.globals.barWidth = L, a.barHelpers.initializeStackedXYVars(a), 1 === a.groupCtx.prevY.length && a.groupCtx.prevY[0].every((function (t) { return isNaN(t) })) && (a.groupCtx.prevY[0] = a.groupCtx.prevY[0].map((function () { return g })), a.groupCtx.prevYF[0] = a.groupCtx.prevYF[0].map((function () { return 0 }))); for (var M = 0; M < s.globals.dataPoints; M++) { var I = a.barHelpers.getStrokeWidth(r, M, p), T = { indexes: { i: r, j: M, realIndex: p, translationsIndex: w, bc: h }, strokeWidth: I, x: n, y: l, elSeries: k, columnGroupIndex: v, seriesGroup: s.globals.seriesGroups[b] }, z = null; a.isHorizontal ? (z = a.drawStackedBarPaths(e(e({}, T), {}, { zeroW: u, barHeight: C, yDivision: d })), L = a.series[r][M] / a.invertedYRatio) : (z = a.drawStackedColumnPaths(e(e({}, T), {}, { xDivision: c, barWidth: L, zeroH: g })), C = a.series[r][M] / a.yRatio[w]); var X = a.barHelpers.drawGoalLine({ barXPosition: z.barXPosition, barYPosition: z.barYPosition, goalX: z.goalX, goalY: z.goalY, barHeight: C, barWidth: L }); X && S.add(X), l = z.y, n = z.x, m.push(n), y.push(l); var E = a.barHelpers.getPathFillColor(t, r, M, p); k = a.renderSeries({ realIndex: p, pathFill: E, j: M, i: r, columnGroupIndex: v, pathFrom: z.pathFrom, pathTo: z.pathTo, strokeWidth: I, elSeries: k, x: n, y: l, series: t, barHeight: C, barWidth: L, elDataLabelsWrap: A, elGoalsMarkers: S, type: "bar", visibleSeries: 0 }) } s.globals.seriesXvalues[p] = m, s.globals.seriesYvalues[p] = y, a.groupCtx.prevY.push(a.groupCtx.yArrj), a.groupCtx.prevYF.push(a.groupCtx.yArrjF), a.groupCtx.prevYVal.push(a.groupCtx.yArrjVal), a.groupCtx.prevX.push(a.groupCtx.xArrj), a.groupCtx.prevXF.push(a.groupCtx.xArrjF), a.groupCtx.prevXVal.push(a.groupCtx.xArrjVal), o.add(k) }, c = 0, d = 0; c < t.length; c++, d++)h(c, d); return o } }, { key: "initialPositions", value: function (t, e, i, a, s, r, o) { var n, l, h = this.w; if (this.isHorizontal) { a = h.globals.gridHeight / h.globals.dataPoints; var c = h.config.plotOptions.bar.barHeight; n = -1 === String(c).indexOf("%") ? parseInt(c, 10) : a * parseInt(c, 10) / 100, r = h.globals.padHorizontal + (this.isReversed ? h.globals.gridWidth - this.baseLineInvertedY : this.baseLineInvertedY), e = (a - n) / 2 } else { l = i = h.globals.gridWidth / h.globals.dataPoints; var d = h.config.plotOptions.bar.columnWidth; h.globals.isXNumeric && h.globals.dataPoints > 1 ? l = (i = h.globals.minXDiff / this.xRatio) * parseInt(this.barOptions.columnWidth, 10) / 100 : -1 === String(d).indexOf("%") ? l = parseInt(d, 10) : l *= parseInt(d, 10) / 100, s = h.globals.gridHeight - this.baseLineY[o] - (this.isReversed ? h.globals.gridHeight : 0), t = h.globals.padHorizontal + (i - l) / 2 } var g = h.globals.barGroups.length || 1; return { x: t, y: e, yDivision: a, xDivision: i, barHeight: n / g, barWidth: l / g, zeroH: s, zeroW: r } } }, { key: "drawStackedBarPaths", value: function (t) { for (var e, i = t.indexes, a = t.barHeight, s = t.strokeWidth, r = t.zeroW, o = t.x, n = t.y, l = t.columnGroupIndex, h = t.seriesGroup, c = t.yDivision, d = t.elSeries, g = this.w, u = n + l * a, p = i.i, f = i.j, x = i.realIndex, b = i.translationsIndex, v = 0, m = 0; m < this.groupCtx.prevXF.length; m++)v += this.groupCtx.prevXF[m][f]; var y; if ((y = h.indexOf(g.config.series[x].name)) > 0) { var w = r; this.groupCtx.prevXVal[y - 1][f] < 0 ? w = this.series[p][f] >= 0 ? this.groupCtx.prevX[y - 1][f] + v - 2 * (this.isReversed ? v : 0) : this.groupCtx.prevX[y - 1][f] : this.groupCtx.prevXVal[y - 1][f] >= 0 && (w = this.series[p][f] >= 0 ? this.groupCtx.prevX[y - 1][f] : this.groupCtx.prevX[y - 1][f] - v + 2 * (this.isReversed ? v : 0)), e = w } else e = r; o = null === this.series[p][f] ? e : e + this.series[p][f] / this.invertedYRatio - 2 * (this.isReversed ? this.series[p][f] / this.invertedYRatio : 0); var k = this.barHelpers.getBarpaths({ barYPosition: u, barHeight: a, x1: e, x2: o, strokeWidth: s, series: this.series, realIndex: i.realIndex, seriesGroup: h, i: p, j: f, w: g }); return this.barHelpers.barBackground({ j: f, i: p, y1: u, y2: a, elSeries: d }), n += c, { pathTo: k.pathTo, pathFrom: k.pathFrom, goalX: this.barHelpers.getGoalValues("x", r, null, p, f, b), barXPosition: e, barYPosition: u, x: o, y: n } } }, { key: "drawStackedColumnPaths", value: function (t) { var e = t.indexes, i = t.x, a = t.y, s = t.xDivision, r = t.barWidth, o = t.zeroH, n = t.columnGroupIndex, l = t.seriesGroup, h = t.elSeries, c = this.w, d = e.i, g = e.j, u = e.bc, p = e.realIndex, f = e.translationsIndex; if (c.globals.isXNumeric) { var x = c.globals.seriesX[p][g]; x || (x = 0), i = (x - c.globals.minX) / this.xRatio - r / 2 * c.globals.barGroups.length } for (var b, v = i + n * r, m = 0, y = 0; y < this.groupCtx.prevYF.length; y++)m += isNaN(this.groupCtx.prevYF[y][g]) ? 0 : this.groupCtx.prevYF[y][g]; var w = d; if (l && (w = l.indexOf(c.globals.seriesNames[p])), w > 0 && !c.globals.isXNumeric || w > 0 && c.globals.isXNumeric && c.globals.seriesX[p - 1][g] === c.globals.seriesX[p][g]) { var k, A, S, C = Math.min(this.yRatio.length + 1, p + 1); if (void 0 !== this.groupCtx.prevY[w - 1] && this.groupCtx.prevY[w - 1].length) for (var L = 1; L < C; L++) { var P; if (!isNaN(null === (P = this.groupCtx.prevY[w - L]) || void 0 === P ? void 0 : P[g])) { S = this.groupCtx.prevY[w - L][g]; break } } for (var M = 1; M < C; M++) { var I, T; if ((null === (I = this.groupCtx.prevYVal[w - M]) || void 0 === I ? void 0 : I[g]) < 0) { A = this.series[d][g] >= 0 ? S - m + 2 * (this.isReversed ? m : 0) : S; break } if ((null === (T = this.groupCtx.prevYVal[w - M]) || void 0 === T ? void 0 : T[g]) >= 0) { A = this.series[d][g] >= 0 ? S : S + m - 2 * (this.isReversed ? m : 0); break } } void 0 === A && (A = c.globals.gridHeight), b = null !== (k = this.groupCtx.prevYF[0]) && void 0 !== k && k.every((function (t) { return 0 === t })) && this.groupCtx.prevYF.slice(1, w).every((function (t) { return t.every((function (t) { return isNaN(t) })) })) ? o : A } else b = o; a = this.series[d][g] ? b - this.series[d][g] / this.yRatio[f] + 2 * (this.isReversed ? this.series[d][g] / this.yRatio[f] : 0) : b; var z = this.barHelpers.getColumnPaths({ barXPosition: v, barWidth: r, y1: b, y2: a, yRatio: this.yRatio[f], strokeWidth: this.strokeWidth, series: this.series, seriesGroup: l, realIndex: e.realIndex, i: d, j: g, w: c }); return this.barHelpers.barBackground({ bc: u, j: g, i: d, x1: v, x2: r, elSeries: h }), i += s, { pathTo: z.pathTo, pathFrom: z.pathFrom, goalY: this.barHelpers.getGoalValues("y", null, o, d, g), barXPosition: v, x: c.globals.isXNumeric ? i - s : i, y: a } } }]), s }(yt), kt = function (t) { n(s, t); var i = d(s); function s() { return a(this, s), i.apply(this, arguments) } return r(s, [{ key: "draw", value: function (t, i, a) { var s = this, r = this.w, o = new m(this.ctx), n = r.globals.comboCharts ? i : r.config.chart.type, l = new H(this.ctx); this.candlestickOptions = this.w.config.plotOptions.candlestick, this.boxOptions = this.w.config.plotOptions.boxPlot, this.isHorizontal = r.config.plotOptions.bar.horizontal; var h = new y(this.ctx, r); t = h.getLogSeries(t), this.series = t, this.yRatio = h.getLogYRatios(this.yRatio), this.barHelpers.initVariables(t); for (var c = o.group({ class: "apexcharts-".concat(n, "-series apexcharts-plot-series") }), d = function (i) { s.isBoxPlot = "boxPlot" === r.config.chart.type || "boxPlot" === r.config.series[i].type; var n, h, d, g, u = void 0, p = void 0, f = [], b = [], v = r.globals.comboCharts ? a[i] : i, m = s.barHelpers.getGroupIndex(v).columnGroupIndex, y = o.group({ class: "apexcharts-series", seriesName: x.escapeString(r.globals.seriesNames[v]), rel: i + 1, "data:realIndex": v }); s.ctx.series.addCollapsedClassToSeries(y, v), t[i].length > 0 && (s.visibleI = s.visibleI + 1); var w, k, A = 0; s.yRatio.length > 1 && (s.yaxisIndex = r.globals.seriesYAxisReverseMap[v][0], A = v); var S = s.barHelpers.initialPositions(); p = S.y, w = S.barHeight, h = S.yDivision, g = S.zeroW, u = S.x, k = S.barWidth, n = S.xDivision, d = S.zeroH, b.push(u + k / 2); for (var C = o.group({ class: "apexcharts-datalabels", "data:realIndex": v }), L = function (a) { var o = s.barHelpers.getStrokeWidth(i, a, v), c = null, x = { indexes: { i: i, j: a, realIndex: v, translationsIndex: A }, x: u, y: p, strokeWidth: o, elSeries: y }; c = s.isHorizontal ? s.drawHorizontalBoxPaths(e(e({}, x), {}, { yDivision: h, barHeight: w, zeroW: g })) : s.drawVerticalBoxPaths(e(e({}, x), {}, { xDivision: n, barWidth: k, zeroH: d })), p = c.y, u = c.x, a > 0 && b.push(u + k / 2), f.push(p), c.pathTo.forEach((function (e, n) { var h = !s.isBoxPlot && s.candlestickOptions.wick.useFillColor ? c.color[n] : r.globals.stroke.colors[i], d = l.fillPath({ seriesNumber: v, dataPointIndex: a, color: c.color[n], value: t[i][a] }); s.renderSeries({ realIndex: v, pathFill: d, lineFill: h, j: a, i: i, pathFrom: c.pathFrom, pathTo: e, strokeWidth: o, elSeries: y, x: u, y: p, series: t, columnGroupIndex: m, barHeight: w, barWidth: k, elDataLabelsWrap: C, visibleSeries: s.visibleI, type: r.config.chart.type }) })) }, P = 0; P < r.globals.dataPoints; P++)L(P); r.globals.seriesXvalues[v] = b, r.globals.seriesYvalues[v] = f, c.add(y) }, g = 0; g < t.length; g++)d(g); return c } }, { key: "drawVerticalBoxPaths", value: function (t) { var e = t.indexes, i = t.x; t.y; var a = t.xDivision, s = t.barWidth, r = t.zeroH, o = t.strokeWidth, n = this.w, l = new m(this.ctx), h = e.i, c = e.j, d = !0, g = n.config.plotOptions.candlestick.colors.upward, u = n.config.plotOptions.candlestick.colors.downward, p = ""; this.isBoxPlot && (p = [this.boxOptions.colors.lower, this.boxOptions.colors.upper]); var f = this.yRatio[e.translationsIndex], x = e.realIndex, b = this.getOHLCValue(x, c), v = r, y = r; b.o > b.c && (d = !1); var w = Math.min(b.o, b.c), k = Math.max(b.o, b.c), A = b.m; n.globals.isXNumeric && (i = (n.globals.seriesX[x][c] - n.globals.minX) / this.xRatio - s / 2); var S = i + s * this.visibleI; void 0 === this.series[h][c] || null === this.series[h][c] ? (w = r, k = r) : (w = r - w / f, k = r - k / f, v = r - b.h / f, y = r - b.l / f, A = r - b.m / f); var C = l.move(S, r), L = l.move(S + s / 2, w); return n.globals.previousPaths.length > 0 && (L = this.getPreviousPath(x, c, !0)), C = this.isBoxPlot ? [l.move(S, w) + l.line(S + s / 2, w) + l.line(S + s / 2, v) + l.line(S + s / 4, v) + l.line(S + s - s / 4, v) + l.line(S + s / 2, v) + l.line(S + s / 2, w) + l.line(S + s, w) + l.line(S + s, A) + l.line(S, A) + l.line(S, w + o / 2), l.move(S, A) + l.line(S + s, A) + l.line(S + s, k) + l.line(S + s / 2, k) + l.line(S + s / 2, y) + l.line(S + s - s / 4, y) + l.line(S + s / 4, y) + l.line(S + s / 2, y) + l.line(S + s / 2, k) + l.line(S, k) + l.line(S, A) + "z"] : [l.move(S, k) + l.line(S + s / 2, k) + l.line(S + s / 2, v) + l.line(S + s / 2, k) + l.line(S + s, k) + l.line(S + s, w) + l.line(S + s / 2, w) + l.line(S + s / 2, y) + l.line(S + s / 2, w) + l.line(S, w) + l.line(S, k - o / 2)], L += l.move(S, w), n.globals.isXNumeric || (i += a), { pathTo: C, pathFrom: L, x: i, y: k, barXPosition: S, color: this.isBoxPlot ? p : d ? [g] : [u] } } }, { key: "drawHorizontalBoxPaths", value: function (t) { var e = t.indexes; t.x; var i = t.y, a = t.yDivision, s = t.barHeight, r = t.zeroW, o = t.strokeWidth, n = this.w, l = new m(this.ctx), h = e.i, c = e.j, d = this.boxOptions.colors.lower; this.isBoxPlot && (d = [this.boxOptions.colors.lower, this.boxOptions.colors.upper]); var g = this.invertedYRatio, u = e.realIndex, p = this.getOHLCValue(u, c), f = r, x = r, b = Math.min(p.o, p.c), v = Math.max(p.o, p.c), y = p.m; n.globals.isXNumeric && (i = (n.globals.seriesX[u][c] - n.globals.minX) / this.invertedXRatio - s / 2); var w = i + s * this.visibleI; void 0 === this.series[h][c] || null === this.series[h][c] ? (b = r, v = r) : (b = r + b / g, v = r + v / g, f = r + p.h / g, x = r + p.l / g, y = r + p.m / g); var k = l.move(r, w), A = l.move(b, w + s / 2); return n.globals.previousPaths.length > 0 && (A = this.getPreviousPath(u, c, !0)), k = [l.move(b, w) + l.line(b, w + s / 2) + l.line(f, w + s / 2) + l.line(f, w + s / 2 - s / 4) + l.line(f, w + s / 2 + s / 4) + l.line(f, w + s / 2) + l.line(b, w + s / 2) + l.line(b, w + s) + l.line(y, w + s) + l.line(y, w) + l.line(b + o / 2, w), l.move(y, w) + l.line(y, w + s) + l.line(v, w + s) + l.line(v, w + s / 2) + l.line(x, w + s / 2) + l.line(x, w + s - s / 4) + l.line(x, w + s / 4) + l.line(x, w + s / 2) + l.line(v, w + s / 2) + l.line(v, w) + l.line(y, w) + "z"], A += l.move(b, w), n.globals.isXNumeric || (i += a), { pathTo: k, pathFrom: A, x: v, y: i, barYPosition: w, color: d } } }, { key: "getOHLCValue", value: function (t, e) { var i = this.w; return { o: this.isBoxPlot ? i.globals.seriesCandleH[t][e] : i.globals.seriesCandleO[t][e], h: this.isBoxPlot ? i.globals.seriesCandleO[t][e] : i.globals.seriesCandleH[t][e], m: i.globals.seriesCandleM[t][e], l: this.isBoxPlot ? i.globals.seriesCandleC[t][e] : i.globals.seriesCandleL[t][e], c: this.isBoxPlot ? i.globals.seriesCandleL[t][e] : i.globals.seriesCandleC[t][e] } } }]), s }(yt), At = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "checkColorRange", value: function () { var t = this.w, e = !1, i = t.config.plotOptions[t.config.chart.type]; return i.colorScale.ranges.length > 0 && i.colorScale.ranges.map((function (t, i) { t.from <= 0 && (e = !0) })), e } }, { key: "getShadeColor", value: function (t, e, i, a) { var s = this.w, r = 1, o = s.config.plotOptions[t].shadeIntensity, n = this.determineColor(t, e, i); s.globals.hasNegs || a ? r = s.config.plotOptions[t].reverseNegativeShade ? n.percent < 0 ? n.percent / 100 * (1.25 * o) : (1 - n.percent / 100) * (1.25 * o) : n.percent <= 0 ? 1 - (1 + n.percent / 100) * o : (1 - n.percent / 100) * o : (r = 1 - n.percent / 100, "treemap" === t && (r = (1 - n.percent / 100) * (1.25 * o))); var l = n.color, h = new x; return s.config.plotOptions[t].enableShades && (l = "dark" === this.w.config.theme.mode ? x.hexToRgba(h.shadeColor(-1 * r, n.color), s.config.fill.opacity) : x.hexToRgba(h.shadeColor(r, n.color), s.config.fill.opacity)), { color: l, colorProps: n } } }, { key: "determineColor", value: function (t, e, i) { var a = this.w, s = a.globals.series[e][i], r = a.config.plotOptions[t], o = r.colorScale.inverse ? i : e; r.distributed && "treemap" === a.config.chart.type && (o = i); var n = a.globals.colors[o], l = null, h = Math.min.apply(Math, u(a.globals.series[e])), c = Math.max.apply(Math, u(a.globals.series[e])); r.distributed || "heatmap" !== t || (h = a.globals.minY, c = a.globals.maxY), void 0 !== r.colorScale.min && (h = r.colorScale.min < a.globals.minY ? r.colorScale.min : a.globals.minY, c = r.colorScale.max > a.globals.maxY ? r.colorScale.max : a.globals.maxY); var d = Math.abs(c) + Math.abs(h), g = 100 * s / (0 === d ? d - 1e-6 : d); r.colorScale.ranges.length > 0 && r.colorScale.ranges.map((function (t, e) { if (s >= t.from && s <= t.to) { n = t.color, l = t.foreColor ? t.foreColor : null, h = t.from, c = t.to; var i = Math.abs(c) + Math.abs(h); g = 100 * s / (0 === i ? i - 1e-6 : i) } })); return { color: n, foreColor: l, percent: g } } }, { key: "calculateDataLabels", value: function (t) { var e = t.text, i = t.x, a = t.y, s = t.i, r = t.j, o = t.colorProps, n = t.fontSize, l = this.w.config.dataLabels, h = new m(this.ctx), c = new N(this.ctx), d = null; if (l.enabled) { d = h.group({ class: "apexcharts-data-labels" }); var g = l.offsetX, u = l.offsetY, p = i + g, f = a + parseFloat(l.style.fontSize) / 3 + u; c.plotDataLabelsText({ x: p, y: f, text: e, i: s, j: r, color: o.foreColor, parent: d, fontSize: n, dataLabelsConfig: l }) } return d } }, { key: "addListeners", value: function (t) { var e = new m(this.ctx); t.node.addEventListener("mouseenter", e.pathMouseEnter.bind(this, t)), t.node.addEventListener("mouseleave", e.pathMouseLeave.bind(this, t)), t.node.addEventListener("mousedown", e.pathMouseDown.bind(this, t)) } }]), t }(), St = function () { function t(e, i) { a(this, t), this.ctx = e, this.w = e.w, this.xRatio = i.xRatio, this.yRatio = i.yRatio, this.dynamicAnim = this.w.config.chart.animations.dynamicAnimation, this.helpers = new At(e), this.rectRadius = this.w.config.plotOptions.heatmap.radius, this.strokeWidth = this.w.config.stroke.show ? this.w.config.stroke.width : 0 } return r(t, [{ key: "draw", value: function (t) { var e = this.w, i = new m(this.ctx), a = i.group({ class: "apexcharts-heatmap" }); a.attr("clip-path", "url(#gridRectMask".concat(e.globals.cuid, ")")); var s = e.globals.gridWidth / e.globals.dataPoints, r = e.globals.gridHeight / e.globals.series.length, o = 0, n = !1; this.negRange = this.helpers.checkColorRange(); var l = t.slice(); e.config.yaxis[0].reversed && (n = !0, l.reverse()); for (var h = n ? 0 : l.length - 1; n ? h < l.length : h >= 0; n ? h++ : h--) { var c = i.group({ class: "apexcharts-series apexcharts-heatmap-series", seriesName: x.escapeString(e.globals.seriesNames[h]), rel: h + 1, "data:realIndex": h }); if (this.ctx.series.addCollapsedClassToSeries(c, h), e.config.chart.dropShadow.enabled) { var d = e.config.chart.dropShadow; new v(this.ctx).dropShadow(c, d, h) } for (var g = 0, u = e.config.plotOptions.heatmap.shadeIntensity, p = 0; p < l[h].length; p++) { var f = this.helpers.getShadeColor(e.config.chart.type, h, p, this.negRange), b = f.color, y = f.colorProps; if ("image" === e.config.fill.type) b = new H(this.ctx).fillPath({ seriesNumber: h, dataPointIndex: p, opacity: e.globals.hasNegs ? y.percent < 0 ? 1 - (1 + y.percent / 100) : u + y.percent / 100 : y.percent / 100, patternID: x.randomId(), width: e.config.fill.image.width ? e.config.fill.image.width : s, height: e.config.fill.image.height ? e.config.fill.image.height : r }); var w = this.rectRadius, k = i.drawRect(g, o, s, r, w); if (k.attr({ cx: g, cy: o }), k.node.classList.add("apexcharts-heatmap-rect"), c.add(k), k.attr({ fill: b, i: h, index: h, j: p, val: t[h][p], "stroke-width": this.strokeWidth, stroke: e.config.plotOptions.heatmap.useFillColorAsStroke ? b : e.globals.stroke.colors[0], color: b }), this.helpers.addListeners(k), e.config.chart.animations.enabled && !e.globals.dataChanged) { var A = 1; e.globals.resized || (A = e.config.chart.animations.speed), this.animateHeatMap(k, g, o, s, r, A) } if (e.globals.dataChanged) { var S = 1; if (this.dynamicAnim.enabled && e.globals.shouldAnimate) { S = this.dynamicAnim.speed; var C = e.globals.previousPaths[h] && e.globals.previousPaths[h][p] && e.globals.previousPaths[h][p].color; C || (C = "rgba(255, 255, 255, 0)"), this.animateHeatColor(k, x.isColorHex(C) ? C : x.rgb2hex(C), x.isColorHex(b) ? b : x.rgb2hex(b), S) } } var L = (0, e.config.dataLabels.formatter)(e.globals.series[h][p], { value: e.globals.series[h][p], seriesIndex: h, dataPointIndex: p, w: e }), P = this.helpers.calculateDataLabels({ text: L, x: g + s / 2, y: o + r / 2, i: h, j: p, colorProps: y, series: l }); null !== P && c.add(P), g += s } o += r, a.add(c) } var M = e.globals.yAxisScale[0].result.slice(); return e.config.yaxis[0].reversed ? M.unshift("") : M.push(""), e.globals.yAxisScale[0].result = M, a } }, { key: "animateHeatMap", value: function (t, e, i, a, s, r) { var o = new b(this.ctx); o.animateRect(t, { x: e + a / 2, y: i + s / 2, width: 0, height: 0 }, { x: e, y: i, width: a, height: s }, r, (function () { o.animationCompleted(t) })) } }, { key: "animateHeatColor", value: function (t, e, i, a) { t.attr({ fill: e }).animate(a).attr({ fill: i }) } }]), t }(), Ct = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "drawYAxisTexts", value: function (t, e, i, a) { var s = this.w, r = s.config.yaxis[0], o = s.globals.yLabelFormatters[0]; return new m(this.ctx).drawText({ x: t + r.labels.offsetX, y: e + r.labels.offsetY, text: o(a, i), textAnchor: "middle", fontSize: r.labels.style.fontSize, fontFamily: r.labels.style.fontFamily, foreColor: Array.isArray(r.labels.style.colors) ? r.labels.style.colors[i] : r.labels.style.colors }) } }]), t }(), Lt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w; var i = this.w; this.chartType = this.w.config.chart.type, this.initialAnim = this.w.config.chart.animations.enabled, this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled, this.animBeginArr = [0], this.animDur = 0, this.donutDataLabels = this.w.config.plotOptions.pie.donut.labels, this.lineColorArr = void 0 !== i.globals.stroke.colors ? i.globals.stroke.colors : i.globals.colors, this.defaultSize = Math.min(i.globals.gridWidth, i.globals.gridHeight), this.centerY = this.defaultSize / 2, this.centerX = i.globals.gridWidth / 2, "radialBar" === i.config.chart.type ? this.fullAngle = 360 : this.fullAngle = Math.abs(i.config.plotOptions.pie.endAngle - i.config.plotOptions.pie.startAngle), this.initialAngle = i.config.plotOptions.pie.startAngle % this.fullAngle, i.globals.radialSize = this.defaultSize / 2.05 - i.config.stroke.width - (i.config.chart.sparkline.enabled ? 0 : i.config.chart.dropShadow.blur), this.donutSize = i.globals.radialSize * parseInt(i.config.plotOptions.pie.donut.size, 10) / 100, this.maxY = 0, this.sliceLabels = [], this.sliceSizes = [], this.prevSectorAngleArr = [] } return r(t, [{ key: "draw", value: function (t) { var e = this, i = this.w, a = new m(this.ctx); if (this.ret = a.group({ class: "apexcharts-pie" }), i.globals.noData) return this.ret; for (var s = 0, r = 0; r < t.length; r++)s += x.negToZero(t[r]); var o = [], n = a.group(); 0 === s && (s = 1e-5), t.forEach((function (t) { e.maxY = Math.max(e.maxY, t) })), i.config.yaxis[0].max && (this.maxY = i.config.yaxis[0].max), "back" === i.config.grid.position && "polarArea" === this.chartType && this.drawPolarElements(this.ret); for (var l = 0; l < t.length; l++) { var h = this.fullAngle * x.negToZero(t[l]) / s; o.push(h), "polarArea" === this.chartType ? (o[l] = this.fullAngle / t.length, this.sliceSizes.push(i.globals.radialSize * t[l] / this.maxY)) : this.sliceSizes.push(i.globals.radialSize) } if (i.globals.dataChanged) { for (var c, d = 0, g = 0; g < i.globals.previousPaths.length; g++)d += x.negToZero(i.globals.previousPaths[g]); for (var u = 0; u < i.globals.previousPaths.length; u++)c = this.fullAngle * x.negToZero(i.globals.previousPaths[u]) / d, this.prevSectorAngleArr.push(c) } this.donutSize < 0 && (this.donutSize = 0); var p = i.config.plotOptions.pie.customScale, f = i.globals.gridWidth / 2, b = i.globals.gridHeight / 2, v = f - i.globals.gridWidth / 2 * p, y = b - i.globals.gridHeight / 2 * p; if ("donut" === this.chartType) { var w = a.drawCircle(this.donutSize); w.attr({ cx: this.centerX, cy: this.centerY, fill: i.config.plotOptions.pie.donut.background ? i.config.plotOptions.pie.donut.background : "transparent" }), n.add(w) } var k = this.drawArcs(o, t); if (this.sliceLabels.forEach((function (t) { k.add(t) })), n.attr({ transform: "translate(".concat(v, ", ").concat(y, ") scale(").concat(p, ")") }), n.add(k), this.ret.add(n), this.donutDataLabels.show) { var A = this.renderInnerDataLabels(this.donutDataLabels, { hollowSize: this.donutSize, centerX: this.centerX, centerY: this.centerY, opacity: this.donutDataLabels.show, translateX: v, translateY: y }); this.ret.add(A) } return "front" === i.config.grid.position && "polarArea" === this.chartType && this.drawPolarElements(this.ret), this.ret } }, { key: "drawArcs", value: function (t, e) { var i = this.w, a = new v(this.ctx), s = new m(this.ctx), r = new H(this.ctx), o = s.group({ class: "apexcharts-slices" }), n = this.initialAngle, l = this.initialAngle, h = this.initialAngle, c = this.initialAngle; this.strokeWidth = i.config.stroke.show ? i.config.stroke.width : 0; for (var d = 0; d < t.length; d++) { var g = s.group({ class: "apexcharts-series apexcharts-pie-series", seriesName: x.escapeString(i.globals.seriesNames[d]), rel: d + 1, "data:realIndex": d }); o.add(g), l = c, h = (n = h) + t[d], c = l + this.prevSectorAngleArr[d]; var u = h < n ? this.fullAngle + h - n : h - n, p = r.fillPath({ seriesNumber: d, size: this.sliceSizes[d], value: e[d] }), f = this.getChangedPath(l, c), b = s.drawPath({ d: f, stroke: Array.isArray(this.lineColorArr) ? this.lineColorArr[d] : this.lineColorArr, strokeWidth: 0, fill: p, fillOpacity: i.config.fill.opacity, classes: "apexcharts-pie-area apexcharts-".concat(this.chartType.toLowerCase(), "-slice-").concat(d) }); if (b.attr({ index: 0, j: d }), a.setSelectionFilter(b, 0, d), i.config.chart.dropShadow.enabled) { var y = i.config.chart.dropShadow; a.dropShadow(b, y, d) } this.addListeners(b, this.donutDataLabels), m.setAttrs(b.node, { "data:angle": u, "data:startAngle": n, "data:strokeWidth": this.strokeWidth, "data:value": e[d] }); var w = { x: 0, y: 0 }; "pie" === this.chartType || "polarArea" === this.chartType ? w = x.polarToCartesian(this.centerX, this.centerY, i.globals.radialSize / 1.25 + i.config.plotOptions.pie.dataLabels.offset, (n + u / 2) % this.fullAngle) : "donut" === this.chartType && (w = x.polarToCartesian(this.centerX, this.centerY, (i.globals.radialSize + this.donutSize) / 2 + i.config.plotOptions.pie.dataLabels.offset, (n + u / 2) % this.fullAngle)), g.add(b); var k = 0; if (!this.initialAnim || i.globals.resized || i.globals.dataChanged ? this.animBeginArr.push(0) : (0 === (k = u / this.fullAngle * i.config.chart.animations.speed) && (k = 1), this.animDur = k + this.animDur, this.animBeginArr.push(this.animDur)), this.dynamicAnim && i.globals.dataChanged ? this.animatePaths(b, { size: this.sliceSizes[d], endAngle: h, startAngle: n, prevStartAngle: l, prevEndAngle: c, animateStartingPos: !0, i: d, animBeginArr: this.animBeginArr, shouldSetPrevPaths: !0, dur: i.config.chart.animations.dynamicAnimation.speed }) : this.animatePaths(b, { size: this.sliceSizes[d], endAngle: h, startAngle: n, i: d, totalItems: t.length - 1, animBeginArr: this.animBeginArr, dur: k }), i.config.plotOptions.pie.expandOnClick && "polarArea" !== this.chartType && b.node.addEventListener("mouseup", this.pieClicked.bind(this, d)), void 0 !== i.globals.selectedDataPoints[0] && i.globals.selectedDataPoints[0].indexOf(d) > -1 && this.pieClicked(d), i.config.dataLabels.enabled) { var A = w.x, S = w.y, C = 100 * u / this.fullAngle + "%"; if (0 !== u && i.config.plotOptions.pie.dataLabels.minAngleToShowLabel < t[d]) { var L = i.config.dataLabels.formatter; void 0 !== L && (C = L(i.globals.seriesPercent[d][0], { seriesIndex: d, w: i })); var P = i.globals.dataLabels.style.colors[d], M = s.group({ class: "apexcharts-datalabels" }), I = s.drawText({ x: A, y: S, text: C, textAnchor: "middle", fontSize: i.config.dataLabels.style.fontSize, fontFamily: i.config.dataLabels.style.fontFamily, fontWeight: i.config.dataLabels.style.fontWeight, foreColor: P }); if (M.add(I), i.config.dataLabels.dropShadow.enabled) { var T = i.config.dataLabels.dropShadow; a.dropShadow(I, T) } I.node.classList.add("apexcharts-pie-label"), i.config.chart.animations.animate && !1 === i.globals.resized && (I.node.classList.add("apexcharts-pie-label-delay"), I.node.style.animationDelay = i.config.chart.animations.speed / 940 + "s"), this.sliceLabels.push(M) } } } return o } }, { key: "addListeners", value: function (t, e) { var i = new m(this.ctx); t.node.addEventListener("mouseenter", i.pathMouseEnter.bind(this, t)), t.node.addEventListener("mouseleave", i.pathMouseLeave.bind(this, t)), t.node.addEventListener("mouseleave", this.revertDataLabelsInner.bind(this, t.node, e)), t.node.addEventListener("mousedown", i.pathMouseDown.bind(this, t)), this.donutDataLabels.total.showAlways || (t.node.addEventListener("mouseenter", this.printDataLabelsInner.bind(this, t.node, e)), t.node.addEventListener("mousedown", this.printDataLabelsInner.bind(this, t.node, e))) } }, { key: "animatePaths", value: function (t, e) { var i = this.w, a = e.endAngle < e.startAngle ? this.fullAngle + e.endAngle - e.startAngle : e.endAngle - e.startAngle, s = a, r = e.startAngle, o = e.startAngle; void 0 !== e.prevStartAngle && void 0 !== e.prevEndAngle && (r = e.prevEndAngle, s = e.prevEndAngle < e.prevStartAngle ? this.fullAngle + e.prevEndAngle - e.prevStartAngle : e.prevEndAngle - e.prevStartAngle), e.i === i.config.series.length - 1 && (a + o > this.fullAngle ? e.endAngle = e.endAngle - (a + o) : a + o < this.fullAngle && (e.endAngle = e.endAngle + (this.fullAngle - (a + o)))), a === this.fullAngle && (a = this.fullAngle - .01), this.animateArc(t, r, o, a, s, e) } }, { key: "animateArc", value: function (t, e, i, a, s, r) { var o, n = this, l = this.w, h = new b(this.ctx), c = r.size; (isNaN(e) || isNaN(s)) && (e = i, s = a, r.dur = 0); var d = a, g = i, u = e < i ? this.fullAngle + e - i : e - i; l.globals.dataChanged && r.shouldSetPrevPaths && r.prevEndAngle && (o = n.getPiePath({ me: n, startAngle: r.prevStartAngle, angle: r.prevEndAngle < r.prevStartAngle ? this.fullAngle + r.prevEndAngle - r.prevStartAngle : r.prevEndAngle - r.prevStartAngle, size: c }), t.attr({ d: o })), 0 !== r.dur ? t.animate(r.dur, l.globals.easing, r.animBeginArr[r.i]).afterAll((function () { "pie" !== n.chartType && "donut" !== n.chartType && "polarArea" !== n.chartType || this.animate(l.config.chart.animations.dynamicAnimation.speed).attr({ "stroke-width": n.strokeWidth }), r.i === l.config.series.length - 1 && h.animationCompleted(t) })).during((function (l) { d = u + (a - u) * l, r.animateStartingPos && (d = s + (a - s) * l, g = e - s + (i - (e - s)) * l), o = n.getPiePath({ me: n, startAngle: g, angle: d, size: c }), t.node.setAttribute("data:pathOrig", o), t.attr({ d: o }) })) : (o = n.getPiePath({ me: n, startAngle: g, angle: a, size: c }), r.isTrack || (l.globals.animationEnded = !0), t.node.setAttribute("data:pathOrig", o), t.attr({ d: o, "stroke-width": n.strokeWidth })) } }, { key: "pieClicked", value: function (t) { var e, i = this.w, a = this, s = a.sliceSizes[t] + (i.config.plotOptions.pie.expandOnClick ? 4 : 0), r = i.globals.dom.Paper.select(".apexcharts-".concat(a.chartType.toLowerCase(), "-slice-").concat(t)).members[0]; if ("true" !== r.attr("data:pieClicked")) { var o = i.globals.dom.baseEl.getElementsByClassName("apexcharts-pie-area"); Array.prototype.forEach.call(o, (function (t) { t.setAttribute("data:pieClicked", "false"); var e = t.getAttribute("data:pathOrig"); e && t.setAttribute("d", e) })), i.globals.capturedDataPointIndex = t, r.attr("data:pieClicked", "true"); var n = parseInt(r.attr("data:startAngle"), 10), l = parseInt(r.attr("data:angle"), 10); e = a.getPiePath({ me: a, startAngle: n, angle: l, size: s }), 360 !== l && r.plot(e) } else { r.attr({ "data:pieClicked": "false" }), this.revertDataLabelsInner(r.node, this.donutDataLabels); var h = r.attr("data:pathOrig"); r.attr({ d: h }) } } }, { key: "getChangedPath", value: function (t, e) { var i = ""; return this.dynamicAnim && this.w.globals.dataChanged && (i = this.getPiePath({ me: this, startAngle: t, angle: e - t, size: this.size })), i } }, { key: "getPiePath", value: function (t) { var e, i = t.me, a = t.startAngle, s = t.angle, r = t.size, o = new m(this.ctx), n = a, l = Math.PI * (n - 90) / 180, h = s + a; Math.ceil(h) >= this.fullAngle + this.w.config.plotOptions.pie.startAngle % this.fullAngle && (h = this.fullAngle + this.w.config.plotOptions.pie.startAngle % this.fullAngle - .01), Math.ceil(h) > this.fullAngle && (h -= this.fullAngle); var c = Math.PI * (h - 90) / 180, d = i.centerX + r * Math.cos(l), g = i.centerY + r * Math.sin(l), u = i.centerX + r * Math.cos(c), p = i.centerY + r * Math.sin(c), f = x.polarToCartesian(i.centerX, i.centerY, i.donutSize, h), b = x.polarToCartesian(i.centerX, i.centerY, i.donutSize, n), v = s > 180 ? 1 : 0, y = ["M", d, g, "A", r, r, 0, v, 1, u, p]; return e = "donut" === i.chartType ? [].concat(y, ["L", f.x, f.y, "A", i.donutSize, i.donutSize, 0, v, 0, b.x, b.y, "L", d, g, "z"]).join(" ") : "pie" === i.chartType || "polarArea" === i.chartType ? [].concat(y, ["L", i.centerX, i.centerY, "L", d, g]).join(" ") : [].concat(y).join(" "), o.roundPathCorners(e, 2 * this.strokeWidth) } }, { key: "drawPolarElements", value: function (t) { var e = this.w, i = new _(this.ctx), a = new m(this.ctx), s = new Ct(this.ctx), r = a.group(), o = a.group(), n = i.niceScale(0, Math.ceil(this.maxY), 0), l = n.result.reverse(), h = n.result.length; this.maxY = n.niceMax; for (var c = e.globals.radialSize, d = c / (h - 1), g = 0; g < h - 1; g++) { var u = a.drawCircle(c); if (u.attr({ cx: this.centerX, cy: this.centerY, fill: "none", "stroke-width": e.config.plotOptions.polarArea.rings.strokeWidth, stroke: e.config.plotOptions.polarArea.rings.strokeColor }), e.config.yaxis[0].show) { var p = s.drawYAxisTexts(this.centerX, this.centerY - c + parseInt(e.config.yaxis[0].labels.style.fontSize, 10) / 2, g, l[g]); o.add(p) } r.add(u), c -= d } this.drawSpokes(t), t.add(r), t.add(o) } }, { key: "renderInnerDataLabels", value: function (t, e) { var i = this.w, a = new m(this.ctx), s = a.group({ class: "apexcharts-datalabels-group", transform: "translate(".concat(e.translateX ? e.translateX : 0, ", ").concat(e.translateY ? e.translateY : 0, ") scale(").concat(i.config.plotOptions.pie.customScale, ")") }), r = t.total.show; s.node.style.opacity = e.opacity; var o, n, l = e.centerX, h = e.centerY; o = void 0 === t.name.color ? i.globals.colors[0] : t.name.color; var c = t.name.fontSize, d = t.name.fontFamily, g = t.name.fontWeight; n = void 0 === t.value.color ? i.config.chart.foreColor : t.value.color; var u = t.value.formatter, p = "", f = ""; if (r ? (o = t.total.color, c = t.total.fontSize, d = t.total.fontFamily, g = t.total.fontWeight, f = t.total.label, p = t.total.formatter(i)) : 1 === i.globals.series.length && (p = u(i.globals.series[0], i), f = i.globals.seriesNames[0]), f && (f = t.name.formatter(f, t.total.show, i)), t.name.show) { var x = a.drawText({ x: l, y: h + parseFloat(t.name.offsetY), text: f, textAnchor: "middle", foreColor: o, fontSize: c, fontWeight: g, fontFamily: d }); x.node.classList.add("apexcharts-datalabel-label"), s.add(x) } if (t.value.show) { var b = t.name.show ? parseFloat(t.value.offsetY) + 16 : t.value.offsetY, v = a.drawText({ x: l, y: h + b, text: p, textAnchor: "middle", foreColor: n, fontWeight: t.value.fontWeight, fontSize: t.value.fontSize, fontFamily: t.value.fontFamily }); v.node.classList.add("apexcharts-datalabel-value"), s.add(v) } return s } }, { key: "printInnerLabels", value: function (t, e, i, a) { var s, r = this.w; a ? s = void 0 === t.name.color ? r.globals.colors[parseInt(a.parentNode.getAttribute("rel"), 10) - 1] : t.name.color : r.globals.series.length > 1 && t.total.show && (s = t.total.color); var o = r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-label"), n = r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-value"); i = (0, t.value.formatter)(i, r), a || "function" != typeof t.total.formatter || (i = t.total.formatter(r)); var l = e === t.total.label; e = t.name.formatter(e, l, r), null !== o && (o.textContent = e), null !== n && (n.textContent = i), null !== o && (o.style.fill = s) } }, { key: "printDataLabelsInner", value: function (t, e) { var i = this.w, a = t.getAttribute("data:value"), s = i.globals.seriesNames[parseInt(t.parentNode.getAttribute("rel"), 10) - 1]; i.globals.series.length > 1 && this.printInnerLabels(e, s, a, t); var r = i.globals.dom.baseEl.querySelector(".apexcharts-datalabels-group"); null !== r && (r.style.opacity = 1) } }, { key: "drawSpokes", value: function (t) { var e = this, i = this.w, a = new m(this.ctx), s = i.config.plotOptions.polarArea.spokes; if (0 !== s.strokeWidth) { for (var r = [], o = 360 / i.globals.series.length, n = 0; n < i.globals.series.length; n++)r.push(x.polarToCartesian(this.centerX, this.centerY, i.globals.radialSize, i.config.plotOptions.pie.startAngle + o * n)); r.forEach((function (i, r) { var o = a.drawLine(i.x, i.y, e.centerX, e.centerY, Array.isArray(s.connectorColors) ? s.connectorColors[r] : s.connectorColors); t.add(o) })) } } }, { key: "revertDataLabelsInner", value: function (t, e, i) { var a = this, s = this.w, r = s.globals.dom.baseEl.querySelector(".apexcharts-datalabels-group"), o = !1, n = s.globals.dom.baseEl.getElementsByClassName("apexcharts-pie-area"), l = function (t) { var i = t.makeSliceOut, s = t.printLabel; Array.prototype.forEach.call(n, (function (t) { "true" === t.getAttribute("data:pieClicked") && (i && (o = !0), s && a.printDataLabelsInner(t, e)) })) }; if (l({ makeSliceOut: !0, printLabel: !1 }), e.total.show && s.globals.series.length > 1) o && !e.total.showAlways ? l({ makeSliceOut: !1, printLabel: !0 }) : this.printInnerLabels(e, e.total.label, e.total.formatter(s)); else if (l({ makeSliceOut: !1, printLabel: !0 }), !o) if (s.globals.selectedDataPoints.length && s.globals.series.length > 1) if (s.globals.selectedDataPoints[0].length > 0) { var h = s.globals.selectedDataPoints[0], c = s.globals.dom.baseEl.querySelector(".apexcharts-".concat(this.chartType.toLowerCase(), "-slice-").concat(h)); this.printDataLabelsInner(c, e) } else r && s.globals.selectedDataPoints.length && 0 === s.globals.selectedDataPoints[0].length && (r.style.opacity = 0); else r && s.globals.series.length > 1 && (r.style.opacity = 0) } }]), t }(), Pt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.chartType = this.w.config.chart.type, this.initialAnim = this.w.config.chart.animations.enabled, this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled, this.animDur = 0; var i = this.w; this.graphics = new m(this.ctx), this.lineColorArr = void 0 !== i.globals.stroke.colors ? i.globals.stroke.colors : i.globals.colors, this.defaultSize = i.globals.svgHeight < i.globals.svgWidth ? i.globals.gridHeight + 1.5 * i.globals.goldenPadding : i.globals.gridWidth, this.isLog = i.config.yaxis[0].logarithmic, this.logBase = i.config.yaxis[0].logBase, this.coreUtils = new y(this.ctx), this.maxValue = this.isLog ? this.coreUtils.getLogVal(this.logBase, i.globals.maxY, 0) : i.globals.maxY, this.minValue = this.isLog ? this.coreUtils.getLogVal(this.logBase, this.w.globals.minY, 0) : i.globals.minY, this.polygons = i.config.plotOptions.radar.polygons, this.strokeWidth = i.config.stroke.show ? i.config.stroke.width : 0, this.size = this.defaultSize / 2.1 - this.strokeWidth - i.config.chart.dropShadow.blur, i.config.xaxis.labels.show && (this.size = this.size - i.globals.xAxisLabelsWidth / 1.75), void 0 !== i.config.plotOptions.radar.size && (this.size = i.config.plotOptions.radar.size), this.dataRadiusOfPercent = [], this.dataRadius = [], this.angleArr = [], this.yaxisLabelsTextsPos = [] } return r(t, [{ key: "draw", value: function (t) { var i = this, a = this.w, s = new H(this.ctx), r = [], o = new N(this.ctx); t.length && (this.dataPointsLen = t[a.globals.maxValsInArrayIndex].length), this.disAngle = 2 * Math.PI / this.dataPointsLen; var n = a.globals.gridWidth / 2, l = a.globals.gridHeight / 2, h = n + a.config.plotOptions.radar.offsetX, c = l + a.config.plotOptions.radar.offsetY, d = this.graphics.group({ class: "apexcharts-radar-series apexcharts-plot-series", transform: "translate(".concat(h || 0, ", ").concat(c || 0, ")") }), g = [], u = null, p = null; if (this.yaxisLabels = this.graphics.group({ class: "apexcharts-yaxis" }), t.forEach((function (t, n) { var l = t.length === a.globals.dataPoints, h = i.graphics.group().attr({ class: "apexcharts-series", "data:longestSeries": l, seriesName: x.escapeString(a.globals.seriesNames[n]), rel: n + 1, "data:realIndex": n }); i.dataRadiusOfPercent[n] = [], i.dataRadius[n] = [], i.angleArr[n] = [], t.forEach((function (t, e) { var a = Math.abs(i.maxValue - i.minValue); t -= i.minValue, i.isLog && (t = i.coreUtils.getLogVal(i.logBase, t, 0)), i.dataRadiusOfPercent[n][e] = t / a, i.dataRadius[n][e] = i.dataRadiusOfPercent[n][e] * i.size, i.angleArr[n][e] = e * i.disAngle })), g = i.getDataPointsPos(i.dataRadius[n], i.angleArr[n]); var c = i.createPaths(g, { x: 0, y: 0 }); u = i.graphics.group({ class: "apexcharts-series-markers-wrap apexcharts-element-hidden" }), p = i.graphics.group({ class: "apexcharts-datalabels", "data:realIndex": n }), a.globals.delayedElements.push({ el: u.node, index: n }); var d = { i: n, realIndex: n, animationDelay: n, initialSpeed: a.config.chart.animations.speed, dataChangeSpeed: a.config.chart.animations.dynamicAnimation.speed, className: "apexcharts-radar", shouldClipToGrid: !1, bindEventsOnPaths: !1, stroke: a.globals.stroke.colors[n], strokeLineCap: a.config.stroke.lineCap }, f = null; a.globals.previousPaths.length > 0 && (f = i.getPreviousPath(n)); for (var b = 0; b < c.linePathsTo.length; b++) { var m = i.graphics.renderPaths(e(e({}, d), {}, { pathFrom: null === f ? c.linePathsFrom[b] : f, pathTo: c.linePathsTo[b], strokeWidth: Array.isArray(i.strokeWidth) ? i.strokeWidth[n] : i.strokeWidth, fill: "none", drawShadow: !1 })); h.add(m); var y = s.fillPath({ seriesNumber: n }), w = i.graphics.renderPaths(e(e({}, d), {}, { pathFrom: null === f ? c.areaPathsFrom[b] : f, pathTo: c.areaPathsTo[b], strokeWidth: 0, fill: y, drawShadow: !1 })); if (a.config.chart.dropShadow.enabled) { var k = new v(i.ctx), A = a.config.chart.dropShadow; k.dropShadow(w, Object.assign({}, A, { noUserSpaceOnUse: !0 }), n) } h.add(w) } t.forEach((function (t, s) { var r = new D(i.ctx).getMarkerConfig({ cssClass: "apexcharts-marker", seriesIndex: n, dataPointIndex: s }), l = i.graphics.drawMarker(g[s].x, g[s].y, r); l.attr("rel", s), l.attr("j", s), l.attr("index", n), l.node.setAttribute("default-marker-size", r.pSize); var c = i.graphics.group({ class: "apexcharts-series-markers" }); c && c.add(l), u.add(c), h.add(u); var d = a.config.dataLabels; if (d.enabled) { var f = d.formatter(a.globals.series[n][s], { seriesIndex: n, dataPointIndex: s, w: a }); o.plotDataLabelsText({ x: g[s].x, y: g[s].y, text: f, textAnchor: "middle", i: n, j: n, parent: p, offsetCorrection: !1, dataLabelsConfig: e({}, d) }) } h.add(p) })), r.push(h) })), this.drawPolygons({ parent: d }), a.config.xaxis.labels.show) { var f = this.drawXAxisTexts(); d.add(f) } return r.forEach((function (t) { d.add(t) })), d.add(this.yaxisLabels), d } }, { key: "drawPolygons", value: function (t) { for (var e = this, i = this.w, a = t.parent, s = new Ct(this.ctx), r = i.globals.yAxisScale[0].result.reverse(), o = r.length, n = [], l = this.size / (o - 1), h = 0; h < o; h++)n[h] = l * h; n.reverse(); var c = [], d = []; n.forEach((function (t, i) { var a = x.getPolygonPos(t, e.dataPointsLen), s = ""; a.forEach((function (t, a) { if (0 === i) { var r = e.graphics.drawLine(t.x, t.y, 0, 0, Array.isArray(e.polygons.connectorColors) ? e.polygons.connectorColors[a] : e.polygons.connectorColors); d.push(r) } 0 === a && e.yaxisLabelsTextsPos.push({ x: t.x, y: t.y }), s += t.x + "," + t.y + " " })), c.push(s) })), c.forEach((function (t, s) { var r = e.polygons.strokeColors, o = e.polygons.strokeWidth, n = e.graphics.drawPolygon(t, Array.isArray(r) ? r[s] : r, Array.isArray(o) ? o[s] : o, i.globals.radarPolygons.fill.colors[s]); a.add(n) })), d.forEach((function (t) { a.add(t) })), i.config.yaxis[0].show && this.yaxisLabelsTextsPos.forEach((function (t, i) { var a = s.drawYAxisTexts(t.x, t.y, i, r[i]); e.yaxisLabels.add(a) })) } }, { key: "drawXAxisTexts", value: function () { var t = this, i = this.w, a = i.config.xaxis.labels, s = this.graphics.group({ class: "apexcharts-xaxis" }), r = x.getPolygonPos(this.size, this.dataPointsLen); return i.globals.labels.forEach((function (o, n) { var l = i.config.xaxis.labels.formatter, h = new N(t.ctx); if (r[n]) { var c = t.getTextPos(r[n], t.size), d = l(o, { seriesIndex: -1, dataPointIndex: n, w: i }); h.plotDataLabelsText({ x: c.newX, y: c.newY, text: d, textAnchor: c.textAnchor, i: n, j: n, parent: s, color: Array.isArray(a.style.colors) && a.style.colors[n] ? a.style.colors[n] : "#a8a8a8", dataLabelsConfig: e({ textAnchor: c.textAnchor, dropShadow: { enabled: !1 } }, a), offsetCorrection: !1 }) } })), s } }, { key: "createPaths", value: function (t, e) { var i = this, a = [], s = [], r = [], o = []; if (t.length) { s = [this.graphics.move(e.x, e.y)], o = [this.graphics.move(e.x, e.y)]; var n = this.graphics.move(t[0].x, t[0].y), l = this.graphics.move(t[0].x, t[0].y); t.forEach((function (e, a) { n += i.graphics.line(e.x, e.y), l += i.graphics.line(e.x, e.y), a === t.length - 1 && (n += "Z", l += "Z") })), a.push(n), r.push(l) } return { linePathsFrom: s, linePathsTo: a, areaPathsFrom: o, areaPathsTo: r } } }, { key: "getTextPos", value: function (t, e) { var i = "middle", a = t.x, s = t.y; return Math.abs(t.x) >= 10 ? t.x > 0 ? (i = "start", a += 10) : t.x < 0 && (i = "end", a -= 10) : i = "middle", Math.abs(t.y) >= e - 10 && (t.y < 0 ? s -= 10 : t.y > 0 && (s += 10)), { textAnchor: i, newX: a, newY: s } } }, { key: "getPreviousPath", value: function (t) { for (var e = this.w, i = null, a = 0; a < e.globals.previousPaths.length; a++) { var s = e.globals.previousPaths[a]; s.paths.length > 0 && parseInt(s.realIndex, 10) === parseInt(t, 10) && void 0 !== e.globals.previousPaths[a].paths[0] && (i = e.globals.previousPaths[a].paths[0].d) } return i } }, { key: "getDataPointsPos", value: function (t, e) { var i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : this.dataPointsLen; t = t || [], e = e || []; for (var a = [], s = 0; s < i; s++) { var r = {}; r.x = t[s] * Math.sin(e[s]), r.y = -t[s] * Math.cos(e[s]), a.push(r) } return a } }]), t }(), Mt = function (t) { n(i, t); var e = d(i); function i(t) { var s; a(this, i), (s = e.call(this, t)).ctx = t, s.w = t.w, s.animBeginArr = [0], s.animDur = 0; var r = s.w; return s.startAngle = r.config.plotOptions.radialBar.startAngle, s.endAngle = r.config.plotOptions.radialBar.endAngle, s.totalAngle = Math.abs(r.config.plotOptions.radialBar.endAngle - r.config.plotOptions.radialBar.startAngle), s.trackStartAngle = r.config.plotOptions.radialBar.track.startAngle, s.trackEndAngle = r.config.plotOptions.radialBar.track.endAngle, s.barLabels = s.w.config.plotOptions.radialBar.barLabels, s.donutDataLabels = s.w.config.plotOptions.radialBar.dataLabels, s.radialDataLabels = s.donutDataLabels, s.trackStartAngle || (s.trackStartAngle = s.startAngle), s.trackEndAngle || (s.trackEndAngle = s.endAngle), 360 === s.endAngle && (s.endAngle = 359.99), s.margin = parseInt(r.config.plotOptions.radialBar.track.margin, 10), s.onBarLabelClick = s.onBarLabelClick.bind(c(s)), s } return r(i, [{ key: "draw", value: function (t) { var e = this.w, i = new m(this.ctx), a = i.group({ class: "apexcharts-radialbar" }); if (e.globals.noData) return a; var s = i.group(), r = this.defaultSize / 2, o = e.globals.gridWidth / 2, n = this.defaultSize / 2.05; e.config.chart.sparkline.enabled || (n = n - e.config.stroke.width - e.config.chart.dropShadow.blur); var l = e.globals.fill.colors; if (e.config.plotOptions.radialBar.track.show) { var h = this.drawTracks({ size: n, centerX: o, centerY: r, colorArr: l, series: t }); s.add(h) } var c = this.drawArcs({ size: n, centerX: o, centerY: r, colorArr: l, series: t }), d = 360; e.config.plotOptions.radialBar.startAngle < 0 && (d = this.totalAngle); var g = (360 - d) / 360; if (e.globals.radialSize = n - n * g, this.radialDataLabels.value.show) { var u = Math.max(this.radialDataLabels.value.offsetY, this.radialDataLabels.name.offsetY); e.globals.radialSize += u * g } return s.add(c.g), "front" === e.config.plotOptions.radialBar.hollow.position && (c.g.add(c.elHollow), c.dataLabels && c.g.add(c.dataLabels)), a.add(s), a } }, { key: "drawTracks", value: function (t) { var e = this.w, i = new m(this.ctx), a = i.group({ class: "apexcharts-tracks" }), s = new v(this.ctx), r = new H(this.ctx), o = this.getStrokeWidth(t); t.size = t.size - o / 2; for (var n = 0; n < t.series.length; n++) { var l = i.group({ class: "apexcharts-radialbar-track apexcharts-track" }); a.add(l), l.attr({ rel: n + 1 }), t.size = t.size - o - this.margin; var h = e.config.plotOptions.radialBar.track, c = r.fillPath({ seriesNumber: 0, size: t.size, fillColors: Array.isArray(h.background) ? h.background[n] : h.background, solid: !0 }), d = this.trackStartAngle, g = this.trackEndAngle; Math.abs(g) + Math.abs(d) >= 360 && (g = 360 - Math.abs(this.startAngle) - .1); var u = i.drawPath({ d: "", stroke: c, strokeWidth: o * parseInt(h.strokeWidth, 10) / 100, fill: "none", strokeOpacity: h.opacity, classes: "apexcharts-radialbar-area" }); if (h.dropShadow.enabled) { var p = h.dropShadow; s.dropShadow(u, p) } l.add(u), u.attr("id", "apexcharts-radialbarTrack-" + n), this.animatePaths(u, { centerX: t.centerX, centerY: t.centerY, endAngle: g, startAngle: d, size: t.size, i: n, totalItems: 2, animBeginArr: 0, dur: 0, isTrack: !0, easing: e.globals.easing }) } return a } }, { key: "drawArcs", value: function (t) { var e = this.w, i = new m(this.ctx), a = new H(this.ctx), s = new v(this.ctx), r = i.group(), o = this.getStrokeWidth(t); t.size = t.size - o / 2; var n = e.config.plotOptions.radialBar.hollow.background, l = t.size - o * t.series.length - this.margin * t.series.length - o * parseInt(e.config.plotOptions.radialBar.track.strokeWidth, 10) / 100 / 2, h = l - e.config.plotOptions.radialBar.hollow.margin; void 0 !== e.config.plotOptions.radialBar.hollow.image && (n = this.drawHollowImage(t, r, l, n)); var c = this.drawHollow({ size: h, centerX: t.centerX, centerY: t.centerY, fill: n || "transparent" }); if (e.config.plotOptions.radialBar.hollow.dropShadow.enabled) { var d = e.config.plotOptions.radialBar.hollow.dropShadow; s.dropShadow(c, d) } var g = 1; !this.radialDataLabels.total.show && e.globals.series.length > 1 && (g = 0); var u = null; this.radialDataLabels.show && (u = this.renderInnerDataLabels(this.radialDataLabels, { hollowSize: l, centerX: t.centerX, centerY: t.centerY, opacity: g })), "back" === e.config.plotOptions.radialBar.hollow.position && (r.add(c), u && r.add(u)); var p = !1; e.config.plotOptions.radialBar.inverseOrder && (p = !0); for (var f = p ? t.series.length - 1 : 0; p ? f >= 0 : f < t.series.length; p ? f-- : f++) { var b = i.group({ class: "apexcharts-series apexcharts-radial-series", seriesName: x.escapeString(e.globals.seriesNames[f]) }); r.add(b), b.attr({ rel: f + 1, "data:realIndex": f }), this.ctx.series.addCollapsedClassToSeries(b, f), t.size = t.size - o - this.margin; var y = a.fillPath({ seriesNumber: f, size: t.size, value: t.series[f] }), w = this.startAngle, k = void 0, A = x.negToZero(t.series[f] > 100 ? 100 : t.series[f]) / 100, S = Math.round(this.totalAngle * A) + this.startAngle, C = void 0; e.globals.dataChanged && (k = this.startAngle, C = Math.round(this.totalAngle * x.negToZero(e.globals.previousPaths[f]) / 100) + k), Math.abs(S) + Math.abs(w) >= 360 && (S -= .01), Math.abs(C) + Math.abs(k) >= 360 && (C -= .01); var L = S - w, P = Array.isArray(e.config.stroke.dashArray) ? e.config.stroke.dashArray[f] : e.config.stroke.dashArray, M = i.drawPath({ d: "", stroke: y, strokeWidth: o, fill: "none", fillOpacity: e.config.fill.opacity, classes: "apexcharts-radialbar-area apexcharts-radialbar-slice-" + f, strokeDashArray: P }); if (m.setAttrs(M.node, { "data:angle": L, "data:value": t.series[f] }), e.config.chart.dropShadow.enabled) { var I = e.config.chart.dropShadow; s.dropShadow(M, I, f) } if (s.setSelectionFilter(M, 0, f), this.addListeners(M, this.radialDataLabels), b.add(M), M.attr({ index: 0, j: f }), this.barLabels.enabled) { var T = x.polarToCartesian(t.centerX, t.centerY, t.size, w), z = this.barLabels.formatter(e.globals.seriesNames[f], { seriesIndex: f, w: e }), X = ["apexcharts-radialbar-label"]; this.barLabels.onClick || X.push("apexcharts-no-click"); var E = this.barLabels.useSeriesColors ? e.globals.colors[f] : e.config.chart.foreColor; E || (E = e.config.chart.foreColor); var Y = T.x - this.barLabels.margin, F = T.y, R = i.drawText({ x: Y, y: F, text: z, textAnchor: "end", dominantBaseline: "middle", fontFamily: this.barLabels.fontFamily, fontWeight: this.barLabels.fontWeight, fontSize: this.barLabels.fontSize, foreColor: E, cssClass: X.join(" ") }); R.on("click", this.onBarLabelClick), R.attr({ rel: f + 1 }), 0 !== w && R.attr({ "transform-origin": "".concat(Y, " ").concat(F), transform: "rotate(".concat(w, " 0 0)") }), b.add(R) } var D = 0; !this.initialAnim || e.globals.resized || e.globals.dataChanged || (D = e.config.chart.animations.speed), e.globals.dataChanged && (D = e.config.chart.animations.dynamicAnimation.speed), this.animDur = D / (1.2 * t.series.length) + this.animDur, this.animBeginArr.push(this.animDur), this.animatePaths(M, { centerX: t.centerX, centerY: t.centerY, endAngle: S, startAngle: w, prevEndAngle: C, prevStartAngle: k, size: t.size, i: f, totalItems: 2, animBeginArr: this.animBeginArr, dur: D, shouldSetPrevPaths: !0, easing: e.globals.easing }) } return { g: r, elHollow: c, dataLabels: u } } }, { key: "drawHollow", value: function (t) { var e = new m(this.ctx).drawCircle(2 * t.size); return e.attr({ class: "apexcharts-radialbar-hollow", cx: t.centerX, cy: t.centerY, r: t.size, fill: t.fill }), e } }, { key: "drawHollowImage", value: function (t, e, i, a) { var s = this.w, r = new H(this.ctx), o = x.randomId(), n = s.config.plotOptions.radialBar.hollow.image; if (s.config.plotOptions.radialBar.hollow.imageClipped) r.clippedImgArea({ width: i, height: i, image: n, patternID: "pattern".concat(s.globals.cuid).concat(o) }), a = "url(#pattern".concat(s.globals.cuid).concat(o, ")"); else { var l = s.config.plotOptions.radialBar.hollow.imageWidth, h = s.config.plotOptions.radialBar.hollow.imageHeight; if (void 0 === l && void 0 === h) { var c = s.globals.dom.Paper.image(n).loaded((function (e) { this.move(t.centerX - e.width / 2 + s.config.plotOptions.radialBar.hollow.imageOffsetX, t.centerY - e.height / 2 + s.config.plotOptions.radialBar.hollow.imageOffsetY) })); e.add(c) } else { var d = s.globals.dom.Paper.image(n).loaded((function (e) { this.move(t.centerX - l / 2 + s.config.plotOptions.radialBar.hollow.imageOffsetX, t.centerY - h / 2 + s.config.plotOptions.radialBar.hollow.imageOffsetY), this.size(l, h) })); e.add(d) } } return a } }, { key: "getStrokeWidth", value: function (t) { var e = this.w; return t.size * (100 - parseInt(e.config.plotOptions.radialBar.hollow.size, 10)) / 100 / (t.series.length + 1) - this.margin } }, { key: "onBarLabelClick", value: function (t) { var e = parseInt(t.target.getAttribute("rel"), 10) - 1, i = this.barLabels.onClick, a = this.w; i && i(a.globals.seriesNames[e], { w: a, seriesIndex: e }) } }]), i }(Lt), It = function (t) { n(s, t); var i = d(s); function s() { return a(this, s), i.apply(this, arguments) } return r(s, [{ key: "draw", value: function (t, i) { var a = this.w, s = new m(this.ctx); this.rangeBarOptions = this.w.config.plotOptions.rangeBar, this.series = t, this.seriesRangeStart = a.globals.seriesRangeStart, this.seriesRangeEnd = a.globals.seriesRangeEnd, this.barHelpers.initVariables(t); for (var r = s.group({ class: "apexcharts-rangebar-series apexcharts-plot-series" }), n = 0; n < t.length; n++) { var l, h, c, d, g = void 0, u = void 0, p = a.globals.comboCharts ? i[n] : n, f = this.barHelpers.getGroupIndex(p).columnGroupIndex, b = s.group({ class: "apexcharts-series", seriesName: x.escapeString(a.globals.seriesNames[p]), rel: n + 1, "data:realIndex": p }); this.ctx.series.addCollapsedClassToSeries(b, p), t[n].length > 0 && (this.visibleI = this.visibleI + 1); var v = 0, y = 0, w = 0; this.yRatio.length > 1 && (this.yaxisIndex = a.globals.seriesYAxisReverseMap[p][0], w = p); var k = this.barHelpers.initialPositions(); u = k.y, d = k.zeroW, g = k.x, y = k.barWidth, v = k.barHeight, l = k.xDivision, h = k.yDivision, c = k.zeroH; for (var A = s.group({ class: "apexcharts-datalabels", "data:realIndex": p }), S = s.group({ class: "apexcharts-rangebar-goals-markers" }), C = 0; C < a.globals.dataPoints; C++) { var L, P = this.barHelpers.getStrokeWidth(n, C, p), M = this.seriesRangeStart[n][C], I = this.seriesRangeEnd[n][C], T = null, z = null, X = null, E = { x: g, y: u, strokeWidth: P, elSeries: b }, Y = this.seriesLen; if (a.config.plotOptions.bar.rangeBarGroupRows && (Y = 1), void 0 === a.config.series[n].data[C]) break; if (this.isHorizontal) { X = u + v * this.visibleI; var F = (h - v * Y) / 2; if (a.config.series[n].data[C].x) { var R = this.detectOverlappingBars({ i: n, j: C, barYPosition: X, srty: F, barHeight: v, yDivision: h, initPositions: k }); v = R.barHeight, X = R.barYPosition } y = (T = this.drawRangeBarPaths(e({ indexes: { i: n, j: C, realIndex: p }, barHeight: v, barYPosition: X, zeroW: d, yDivision: h, y1: M, y2: I }, E))).barWidth } else { a.globals.isXNumeric && (g = (a.globals.seriesX[n][C] - a.globals.minX) / this.xRatio - y / 2), z = g + y * this.visibleI; var H = (l - y * Y) / 2; if (a.config.series[n].data[C].x) { var D = this.detectOverlappingBars({ i: n, j: C, barXPosition: z, srtx: H, barWidth: y, xDivision: l, initPositions: k }); y = D.barWidth, z = D.barXPosition } v = (T = this.drawRangeColumnPaths(e({ indexes: { i: n, j: C, realIndex: p, translationsIndex: w }, barWidth: y, barXPosition: z, zeroH: c, xDivision: l }, E))).barHeight } var O = this.barHelpers.drawGoalLine({ barXPosition: T.barXPosition, barYPosition: X, goalX: T.goalX, goalY: T.goalY, barHeight: v, barWidth: y }); O && S.add(O), u = T.y, g = T.x; var N = this.barHelpers.getPathFillColor(t, n, C, p), W = a.globals.stroke.colors[p]; this.renderSeries((o(L = { realIndex: p, pathFill: N, lineFill: W, j: C, i: n, x: g, y: u, y1: M, y2: I, pathFrom: T.pathFrom, pathTo: T.pathTo, strokeWidth: P, elSeries: b, series: t, barHeight: v, barWidth: y, barXPosition: z, barYPosition: X }, "barWidth", y), o(L, "columnGroupIndex", f), o(L, "elDataLabelsWrap", A), o(L, "elGoalsMarkers", S), o(L, "visibleSeries", this.visibleI), o(L, "type", "rangebar"), L)) } r.add(b) } return r } }, { key: "detectOverlappingBars", value: function (t) { var e = t.i, i = t.j, a = t.barYPosition, s = t.barXPosition, r = t.srty, o = t.srtx, n = t.barHeight, l = t.barWidth, h = t.yDivision, c = t.xDivision, d = t.initPositions, g = this.w, u = [], p = g.config.series[e].data[i].rangeName, f = g.config.series[e].data[i].x, x = Array.isArray(f) ? f.join(" ") : f, b = g.globals.labels.map((function (t) { return Array.isArray(t) ? t.join(" ") : t })).indexOf(x), v = g.globals.seriesRange[e].findIndex((function (t) { return t.x === x && t.overlaps.length > 0 })); return this.isHorizontal ? (a = g.config.plotOptions.bar.rangeBarGroupRows ? r + h * b : r + n * this.visibleI + h * b, v > -1 && !g.config.plotOptions.bar.rangeBarOverlap && (u = g.globals.seriesRange[e][v].overlaps).indexOf(p) > -1 && (a = (n = d.barHeight / u.length) * this.visibleI + h * (100 - parseInt(this.barOptions.barHeight, 10)) / 100 / 2 + n * (this.visibleI + u.indexOf(p)) + h * b)) : (b > -1 && !g.globals.timescaleLabels.length && (s = g.config.plotOptions.bar.rangeBarGroupRows ? o + c * b : o + l * this.visibleI + c * b), v > -1 && !g.config.plotOptions.bar.rangeBarOverlap && (u = g.globals.seriesRange[e][v].overlaps).indexOf(p) > -1 && (s = (l = d.barWidth / u.length) * this.visibleI + c * (100 - parseInt(this.barOptions.barWidth, 10)) / 100 / 2 + l * (this.visibleI + u.indexOf(p)) + c * b)), { barYPosition: a, barXPosition: s, barHeight: n, barWidth: l } } }, { key: "drawRangeColumnPaths", value: function (t) { var e = t.indexes, i = t.x, a = t.xDivision, s = t.barWidth, r = t.barXPosition, o = t.zeroH, n = this.w, l = e.i, h = e.j, c = e.realIndex, d = e.translationsIndex, g = this.yRatio[d], u = this.getRangeValue(c, h), p = Math.min(u.start, u.end), f = Math.max(u.start, u.end); void 0 === this.series[l][h] || null === this.series[l][h] ? p = o : (p = o - p / g, f = o - f / g); var x = Math.abs(f - p), b = this.barHelpers.getColumnPaths({ barXPosition: r, barWidth: s, y1: p, y2: f, strokeWidth: this.strokeWidth, series: this.seriesRangeEnd, realIndex: c, i: c, j: h, w: n }); if (n.globals.isXNumeric) { var v = this.getBarXForNumericXAxis({ x: i, j: h, realIndex: c, barWidth: s }); i = v.x, r = v.barXPosition } else i += a; return { pathTo: b.pathTo, pathFrom: b.pathFrom, barHeight: x, x: i, y: u.start < 0 && u.end < 0 ? p : f, goalY: this.barHelpers.getGoalValues("y", null, o, l, h, d), barXPosition: r } } }, { key: "drawRangeBarPaths", value: function (t) { var e = t.indexes, i = t.y, a = t.y1, s = t.y2, r = t.yDivision, o = t.barHeight, n = t.barYPosition, l = t.zeroW, h = this.w, c = e.realIndex, d = e.j, g = l + a / this.invertedYRatio, u = l + s / this.invertedYRatio, p = this.getRangeValue(c, d), f = Math.abs(u - g), x = this.barHelpers.getBarpaths({ barYPosition: n, barHeight: o, x1: g, x2: u, strokeWidth: this.strokeWidth, series: this.seriesRangeEnd, i: c, realIndex: c, j: d, w: h }); return h.globals.isXNumeric || (i += r), { pathTo: x.pathTo, pathFrom: x.pathFrom, barWidth: f, x: p.start < 0 && p.end < 0 ? g : u, goalX: this.barHelpers.getGoalValues("x", l, null, c, d), y: i } } }, { key: "getRangeValue", value: function (t, e) { var i = this.w; return { start: i.globals.seriesRangeStart[t][e], end: i.globals.seriesRangeEnd[t][e] } } }]), s }(yt), Tt = function () { function t(e) { a(this, t), this.w = e.w, this.lineCtx = e } return r(t, [{ key: "sameValueSeriesFix", value: function (t, e) { var i = this.w; if (("gradient" === i.config.fill.type || "gradient" === i.config.fill.type[t]) && new y(this.lineCtx.ctx, i).seriesHaveSameValues(t)) { var a = e[t].slice(); a[a.length - 1] = a[a.length - 1] + 1e-6, e[t] = a } return e } }, { key: "calculatePoints", value: function (t) { var e = t.series, i = t.realIndex, a = t.x, s = t.y, r = t.i, o = t.j, n = t.prevY, l = this.w, h = [], c = []; if (0 === o) { var d = this.lineCtx.categoryAxisCorrection + l.config.markers.offsetX; l.globals.isXNumeric && (d = (l.globals.seriesX[i][0] - l.globals.minX) / this.lineCtx.xRatio + l.config.markers.offsetX), h.push(d), c.push(x.isNumber(e[r][0]) ? n + l.config.markers.offsetY : null), h.push(a + l.config.markers.offsetX), c.push(x.isNumber(e[r][o + 1]) ? s + l.config.markers.offsetY : null) } else h.push(a + l.config.markers.offsetX), c.push(x.isNumber(e[r][o + 1]) ? s + l.config.markers.offsetY : null); return { x: h, y: c } } }, { key: "checkPreviousPaths", value: function (t) { for (var e = t.pathFromLine, i = t.pathFromArea, a = t.realIndex, s = this.w, r = 0; r < s.globals.previousPaths.length; r++) { var o = s.globals.previousPaths[r]; ("line" === o.type || "area" === o.type) && o.paths.length > 0 && parseInt(o.realIndex, 10) === parseInt(a, 10) && ("line" === o.type ? (this.lineCtx.appendPathFrom = !1, e = s.globals.previousPaths[r].paths[0].d) : "area" === o.type && (this.lineCtx.appendPathFrom = !1, i = s.globals.previousPaths[r].paths[0].d, s.config.stroke.show && s.globals.previousPaths[r].paths[1] && (e = s.globals.previousPaths[r].paths[1].d))) } return { pathFromLine: e, pathFromArea: i } } }, { key: "determineFirstPrevY", value: function (t) { var e, i, a, s = t.i, r = t.realIndex, o = t.series, n = t.prevY, l = t.lineYPosition, h = t.translationsIndex, c = this.w, d = c.config.chart.stacked && !c.globals.comboCharts || c.config.chart.stacked && c.globals.comboCharts && (!this.w.config.chart.stackOnlyBar || "bar" === (null === (e = this.w.config.series[r]) || void 0 === e ? void 0 : e.type) || "column" === (null === (i = this.w.config.series[r]) || void 0 === i ? void 0 : i.type)); if (void 0 !== (null === (a = o[s]) || void 0 === a ? void 0 : a[0])) n = (l = d && s > 0 ? this.lineCtx.prevSeriesY[s - 1][0] : this.lineCtx.zeroY) - o[s][0] / this.lineCtx.yRatio[h] + 2 * (this.lineCtx.isReversed ? o[s][0] / this.lineCtx.yRatio[h] : 0); else if (d && s > 0 && void 0 === o[s][0]) for (var g = s - 1; g >= 0; g--)if (null !== o[g][0] && void 0 !== o[g][0]) { n = l = this.lineCtx.prevSeriesY[g][0]; break } return { prevY: n, lineYPosition: l } } }]), t }(), zt = function (t) { for (var e, i, a, s, r = function (t) { for (var e = [], i = t[0], a = t[1], s = e[0] = Yt(i, a), r = 1, o = t.length - 1; r < o; r++)i = a, a = t[r + 1], e[r] = .5 * (s + (s = Yt(i, a))); return e[r] = s, e }(t), o = t.length - 1, n = [], l = 0; l < o; l++)a = Yt(t[l], t[l + 1]), Math.abs(a) < 1e-6 ? r[l] = r[l + 1] = 0 : (s = (e = r[l] / a) * e + (i = r[l + 1] / a) * i) > 9 && (s = 3 * a / Math.sqrt(s), r[l] = s * e, r[l + 1] = s * i); for (var h = 0; h <= o; h++)s = (t[Math.min(o, h + 1)][0] - t[Math.max(0, h - 1)][0]) / (6 * (1 + r[h] * r[h])), n.push([s || 0, r[h] * s || 0]); return n }, Xt = function (t) { var e = zt(t), i = t[1], a = t[0], s = [], r = e[1], o = e[0]; s.push(a, [a[0] + o[0], a[1] + o[1], i[0] - r[0], i[1] - r[1], i[0], i[1]]); for (var n = 2, l = e.length; n < l; n++) { var h = t[n], c = e[n]; s.push([h[0] - c[0], h[1] - c[1], h[0], h[1]]) } return s }, Et = function (t, e, i) { var a = t.slice(e, i); if (e) { if (i - e > 1 && a[1].length < 6) { var s = a[0].length; a[1] = [2 * a[0][s - 2] - a[0][s - 4], 2 * a[0][s - 1] - a[0][s - 3]].concat(a[1]) } a[0] = a[0].slice(-2) } return a }; function Yt(t, e) { return (e[1] - t[1]) / (e[0] - t[0]) } var Ft = function () { function t(e, i, s) { a(this, t), this.ctx = e, this.w = e.w, this.xyRatios = i, this.pointsChart = !("bubble" !== this.w.config.chart.type && "scatter" !== this.w.config.chart.type) || s, this.scatter = new O(this.ctx), this.noNegatives = this.w.globals.minX === Number.MAX_VALUE, this.lineHelpers = new Tt(this), this.markers = new D(this.ctx), this.prevSeriesY = [], this.categoryAxisCorrection = 0, this.yaxisIndex = 0 } return r(t, [{ key: "draw", value: function (t, i, a, s) { var r, o = this.w, n = new m(this.ctx), l = o.globals.comboCharts ? i : o.config.chart.type, h = n.group({ class: "apexcharts-".concat(l, "-series apexcharts-plot-series") }), c = new y(this.ctx, o); this.yRatio = this.xyRatios.yRatio, this.zRatio = this.xyRatios.zRatio, this.xRatio = this.xyRatios.xRatio, this.baseLineY = this.xyRatios.baseLineY, t = c.getLogSeries(t), this.yRatio = c.getLogYRatios(this.yRatio), this.prevSeriesY = []; for (var d = [], g = 0; g < t.length; g++) { t = this.lineHelpers.sameValueSeriesFix(g, t); var u = o.globals.comboCharts ? a[g] : g, p = this.yRatio.length > 1 ? u : 0; this._initSerieVariables(t, g, u); var f = [], x = [], b = [], v = o.globals.padHorizontal + this.categoryAxisCorrection; this.ctx.series.addCollapsedClassToSeries(this.elSeries, u), o.globals.isXNumeric && o.globals.seriesX.length > 0 && (v = (o.globals.seriesX[u][0] - o.globals.minX) / this.xRatio), b.push(v); var w, k = v, A = void 0, S = k, C = this.zeroY, L = this.zeroY; C = this.lineHelpers.determineFirstPrevY({ i: g, realIndex: u, series: t, prevY: C, lineYPosition: 0, translationsIndex: p }).prevY, "monotoneCubic" === o.config.stroke.curve && null === t[g][0] ? f.push(null) : f.push(C), w = C; "rangeArea" === l && (A = L = this.lineHelpers.determineFirstPrevY({ i: g, realIndex: u, series: s, prevY: L, lineYPosition: 0, translationsIndex: p }).prevY, x.push(null !== f[0] ? L : null)); var P = this._calculatePathsFrom({ type: l, series: t, i: g, realIndex: u, translationsIndex: p, prevX: S, prevY: C, prevY2: L }), M = [f[0]], I = [x[0]], T = { type: l, series: t, realIndex: u, translationsIndex: p, i: g, x: v, y: 1, pX: k, pY: w, pathsFrom: P, linePaths: [], areaPaths: [], seriesIndex: a, lineYPosition: 0, xArrj: b, yArrj: f, y2Arrj: x, seriesRangeEnd: s }, z = this._iterateOverDataPoints(e(e({}, T), {}, { iterations: "rangeArea" === l ? t[g].length - 1 : void 0, isRangeStart: !0 })); if ("rangeArea" === l) { for (var X = this._calculatePathsFrom({ series: s, i: g, realIndex: u, prevX: S, prevY: L }), E = this._iterateOverDataPoints(e(e({}, T), {}, { series: s, xArrj: [v], yArrj: M, y2Arrj: I, pY: A, areaPaths: z.areaPaths, pathsFrom: X, iterations: s[g].length - 1, isRangeStart: !1 })), Y = z.linePaths.length / 2, F = 0; F < Y; F++)z.linePaths[F] = E.linePaths[F + Y] + z.linePaths[F]; z.linePaths.splice(Y), z.pathFromLine = E.pathFromLine + z.pathFromLine } else z.pathFromArea += n.line(0, this.zeroY); this._handlePaths({ type: l, realIndex: u, i: g, paths: z }), this.elSeries.add(this.elPointsMain), this.elSeries.add(this.elDataLabelsWrap), d.push(this.elSeries) } if (void 0 !== (null === (r = o.config.series[0]) || void 0 === r ? void 0 : r.zIndex) && d.sort((function (t, e) { return Number(t.node.getAttribute("zIndex")) - Number(e.node.getAttribute("zIndex")) })), o.config.chart.stacked) for (var R = d.length - 1; R >= 0; R--)h.add(d[R]); else for (var H = 0; H < d.length; H++)h.add(d[H]); return h } }, { key: "_initSerieVariables", value: function (t, e, i) { var a = this.w, s = new m(this.ctx); this.xDivision = a.globals.gridWidth / (a.globals.dataPoints - ("on" === a.config.xaxis.tickPlacement ? 1 : 0)), this.strokeWidth = Array.isArray(a.config.stroke.width) ? a.config.stroke.width[i] : a.config.stroke.width; var r = 0; this.yRatio.length > 1 && (this.yaxisIndex = a.globals.seriesYAxisReverseMap[i], r = i), this.isReversed = a.config.yaxis[this.yaxisIndex] && a.config.yaxis[this.yaxisIndex].reversed, this.zeroY = a.globals.gridHeight - this.baseLineY[r] - (this.isReversed ? a.globals.gridHeight : 0) + (this.isReversed ? 2 * this.baseLineY[r] : 0), this.areaBottomY = this.zeroY, (this.zeroY > a.globals.gridHeight || "end" === a.config.plotOptions.area.fillTo) && (this.areaBottomY = a.globals.gridHeight), this.categoryAxisCorrection = this.xDivision / 2, this.elSeries = s.group({ class: "apexcharts-series", zIndex: void 0 !== a.config.series[i].zIndex ? a.config.series[i].zIndex : i, seriesName: x.escapeString(a.globals.seriesNames[i]) }), this.elPointsMain = s.group({ class: "apexcharts-series-markers-wrap", "data:realIndex": i }), this.elDataLabelsWrap = s.group({ class: "apexcharts-datalabels", "data:realIndex": i }); var o = t[e].length === a.globals.dataPoints; this.elSeries.attr({ "data:longestSeries": o, rel: e + 1, "data:realIndex": i }), this.appendPathFrom = !0 } }, { key: "_calculatePathsFrom", value: function (t) { var e, i, a, s, r = t.type, o = t.series, n = t.i, l = t.realIndex, h = t.translationsIndex, c = t.prevX, d = t.prevY, g = t.prevY2, u = this.w, p = new m(this.ctx); if (null === o[n][0]) { for (var f = 0; f < o[n].length; f++)if (null !== o[n][f]) { c = this.xDivision * f, d = this.zeroY - o[n][f] / this.yRatio[h], e = p.move(c, d), i = p.move(c, this.areaBottomY); break } } else e = p.move(c, d), "rangeArea" === r && (e = p.move(c, g) + p.line(c, d)), i = p.move(c, this.areaBottomY) + p.line(c, d); if (a = p.move(0, this.zeroY) + p.line(0, this.zeroY), s = p.move(0, this.zeroY) + p.line(0, this.zeroY), u.globals.previousPaths.length > 0) { var x = this.lineHelpers.checkPreviousPaths({ pathFromLine: a, pathFromArea: s, realIndex: l }); a = x.pathFromLine, s = x.pathFromArea } return { prevX: c, prevY: d, linePath: e, areaPath: i, pathFromLine: a, pathFromArea: s } } }, { key: "_handlePaths", value: function (t) { var i = t.type, a = t.realIndex, s = t.i, r = t.paths, o = this.w, n = new m(this.ctx), l = new H(this.ctx); this.prevSeriesY.push(r.yArrj), o.globals.seriesXvalues[a] = r.xArrj, o.globals.seriesYvalues[a] = r.yArrj; var h = o.config.forecastDataPoints; if (h.count > 0 && "rangeArea" !== i) { var c = o.globals.seriesXvalues[a][o.globals.seriesXvalues[a].length - h.count - 1], d = n.drawRect(c, 0, o.globals.gridWidth, o.globals.gridHeight, 0); o.globals.dom.elForecastMask.appendChild(d.node); var g = n.drawRect(0, 0, c, o.globals.gridHeight, 0); o.globals.dom.elNonForecastMask.appendChild(g.node) } this.pointsChart || o.globals.delayedElements.push({ el: this.elPointsMain.node, index: a }); var u = { i: s, realIndex: a, animationDelay: s, initialSpeed: o.config.chart.animations.speed, dataChangeSpeed: o.config.chart.animations.dynamicAnimation.speed, className: "apexcharts-".concat(i) }; if ("area" === i) for (var p = l.fillPath({ seriesNumber: a }), f = 0; f < r.areaPaths.length; f++) { var x = n.renderPaths(e(e({}, u), {}, { pathFrom: r.pathFromArea, pathTo: r.areaPaths[f], stroke: "none", strokeWidth: 0, strokeLineCap: null, fill: p })); this.elSeries.add(x) } if (o.config.stroke.show && !this.pointsChart) { var b = null; if ("line" === i) b = l.fillPath({ seriesNumber: a, i: s }); else if ("solid" === o.config.stroke.fill.type) b = o.globals.stroke.colors[a]; else { var v = o.config.fill; o.config.fill = o.config.stroke.fill, b = l.fillPath({ seriesNumber: a, i: s }), o.config.fill = v } for (var y = 0; y < r.linePaths.length; y++) { var w = b; "rangeArea" === i && (w = l.fillPath({ seriesNumber: a })); var k = e(e({}, u), {}, { pathFrom: r.pathFromLine, pathTo: r.linePaths[y], stroke: b, strokeWidth: this.strokeWidth, strokeLineCap: o.config.stroke.lineCap, fill: "rangeArea" === i ? w : "none" }), A = n.renderPaths(k); if (this.elSeries.add(A), A.attr("fill-rule", "evenodd"), h.count > 0 && "rangeArea" !== i) { var S = n.renderPaths(k); S.node.setAttribute("stroke-dasharray", h.dashArray), h.strokeWidth && S.node.setAttribute("stroke-width", h.strokeWidth), this.elSeries.add(S), S.attr("clip-path", "url(#forecastMask".concat(o.globals.cuid, ")")), A.attr("clip-path", "url(#nonForecastMask".concat(o.globals.cuid, ")")) } } } } }, { key: "_iterateOverDataPoints", value: function (t) { var e, i, a = this, s = t.type, r = t.series, o = t.iterations, n = t.realIndex, l = t.translationsIndex, h = t.i, c = t.x, d = t.y, g = t.pX, u = t.pY, p = t.pathsFrom, f = t.linePaths, b = t.areaPaths, v = t.seriesIndex, y = t.lineYPosition, w = t.xArrj, k = t.yArrj, A = t.y2Arrj, S = t.isRangeStart, C = t.seriesRangeEnd, L = this.w, P = new m(this.ctx), M = this.yRatio, I = p.prevY, T = p.linePath, z = p.areaPath, X = p.pathFromLine, E = p.pathFromArea, Y = x.isNumber(L.globals.minYArr[n]) ? L.globals.minYArr[n] : L.globals.minY; o || (o = L.globals.dataPoints > 1 ? L.globals.dataPoints - 1 : L.globals.dataPoints); var F = function (t, e) { return e - t / M[l] + 2 * (a.isReversed ? t / M[l] : 0) }, R = d, H = L.config.chart.stacked && !L.globals.comboCharts || L.config.chart.stacked && L.globals.comboCharts && (!this.w.config.chart.stackOnlyBar || "bar" === (null === (e = this.w.config.series[n]) || void 0 === e ? void 0 : e.type) || "column" === (null === (i = this.w.config.series[n]) || void 0 === i ? void 0 : i.type)), D = L.config.stroke.curve; Array.isArray(D) && (D = Array.isArray(v) ? D[v[h]] : D[h]); for (var O, N = 0, W = 0; W < o; W++) { var B = void 0 === r[h][W + 1] || null === r[h][W + 1]; if (L.globals.isXNumeric) { var G = L.globals.seriesX[n][W + 1]; void 0 === L.globals.seriesX[n][W + 1] && (G = L.globals.seriesX[n][o - 1]), c = (G - L.globals.minX) / this.xRatio } else c += this.xDivision; if (H) if (h > 0 && L.globals.collapsedSeries.length < L.config.series.length - 1) { y = this.prevSeriesY[function (t) { for (var e = t; e > 0; e--) { if (!(L.globals.collapsedSeriesIndices.indexOf((null == v ? void 0 : v[e]) || e) > -1)) return e; e-- } return 0 }(h - 1)][W + 1] } else y = this.zeroY; else y = this.zeroY; B ? d = F(Y, y) : (d = F(r[h][W + 1], y), "rangeArea" === s && (R = F(C[h][W + 1], y))), w.push(c), !B || "smooth" !== L.config.stroke.curve && "monotoneCubic" !== L.config.stroke.curve ? (k.push(d), A.push(R)) : (k.push(null), A.push(null)); var V = this.lineHelpers.calculatePoints({ series: r, x: c, y: d, realIndex: n, i: h, j: W, prevY: I }), j = this._createPaths({ type: s, series: r, i: h, realIndex: n, j: W, x: c, y: d, y2: R, xArrj: w, yArrj: k, y2Arrj: A, pX: g, pY: u, pathState: N, segmentStartX: O, linePath: T, areaPath: z, linePaths: f, areaPaths: b, curve: D, isRangeStart: S }); b = j.areaPaths, f = j.linePaths, g = j.pX, u = j.pY, N = j.pathState, O = j.segmentStartX, z = j.areaPath, T = j.linePath, !this.appendPathFrom || "monotoneCubic" === D && "rangeArea" === s || (X += P.line(c, this.zeroY), E += P.line(c, this.zeroY)), this.handleNullDataPoints(r, V, h, W, n), this._handleMarkersAndLabels({ type: s, pointsPos: V, i: h, j: W, realIndex: n, isRangeStart: S }) } return { yArrj: k, xArrj: w, pathFromArea: E, areaPaths: b, pathFromLine: X, linePaths: f, linePath: T, areaPath: z } } }, { key: "_handleMarkersAndLabels", value: function (t) { var e = t.type, i = t.pointsPos, a = t.isRangeStart, s = t.i, r = t.j, o = t.realIndex, n = this.w, l = new N(this.ctx); if (this.pointsChart) this.scatter.draw(this.elSeries, r, { realIndex: o, pointsPos: i, zRatio: this.zRatio, elParent: this.elPointsMain }); else { n.globals.series[s].length > 1 && this.elPointsMain.node.classList.add("apexcharts-element-hidden"); var h = this.markers.plotChartMarkers(i, o, r + 1); null !== h && this.elPointsMain.add(h) } var c = l.drawDataLabel({ type: e, isRangeStart: a, pos: i, i: o, j: r + 1 }); null !== c && this.elDataLabelsWrap.add(c) } }, { key: "_createPaths", value: function (t) { var e = t.type, i = t.series, a = t.i; t.realIndex; var s = t.j, r = t.x, o = t.y, n = t.xArrj, l = t.yArrj, h = t.y2, c = t.y2Arrj, d = t.pX, g = t.pY, u = t.pathState, p = t.segmentStartX, f = t.linePath, x = t.areaPath, b = t.linePaths, v = t.areaPaths, y = t.curve, w = t.isRangeStart; this.w; var k, A = new m(this.ctx), S = this.areaBottomY, C = "rangeArea" === e, L = "rangeArea" === e && w; switch (y) { case "monotoneCubic": var P = w ? l : c; switch (u) { case 0: if (null === P[s + 1]) break; u = 1; case 1: if (!(C ? n.length === i[a].length : s === i[a].length - 2)) break; case 2: var M = w ? n : n.slice().reverse(), I = w ? P : P.slice().reverse(), T = (k = I, M.map((function (t, e) { return [t, k[e]] })).filter((function (t) { return null !== t[1] }))), z = T.length > 1 ? Xt(T) : T, X = []; C && (L ? v = T : X = v.reverse()); var E = 0, Y = 0; if (function (t, e) { for (var i = function (t) { var e = [], i = 0; return t.forEach((function (t) { null !== t ? i++ : i > 0 && (e.push(i), i = 0) })), i > 0 && e.push(i), e }(t), a = [], s = 0, r = 0; s < i.length; r += i[s++])a[s] = Et(e, r, r + i[s]); return a }(I, z).forEach((function (t) { E++; var e = function (t) { for (var e = "", i = 0; i < t.length; i++) { var a = t[i], s = a.length; s > 4 ? (e += "C".concat(a[0], ", ").concat(a[1]), e += ", ".concat(a[2], ", ").concat(a[3]), e += ", ".concat(a[4], ", ").concat(a[5])) : s > 2 && (e += "S".concat(a[0], ", ").concat(a[1]), e += ", ".concat(a[2], ", ").concat(a[3])) } return e }(t), i = Y, a = (Y += t.length) - 1; L ? f = A.move(T[i][0], T[i][1]) + e : C ? f = A.move(X[i][0], X[i][1]) + A.line(T[i][0], T[i][1]) + e + A.line(X[a][0], X[a][1]) : (f = A.move(T[i][0], T[i][1]) + e, x = f + A.line(T[a][0], S) + A.line(T[i][0], S) + "z", v.push(x)), b.push(f) })), C && E > 1 && !L) { var F = b.slice(E).reverse(); b.splice(E), F.forEach((function (t) { return b.push(t) })) } u = 0 }break; case "smooth": var R = .35 * (r - d); if (null === i[a][s]) u = 0; else switch (u) { case 0: if (p = d, f = L ? A.move(d, c[s]) + A.line(d, g) : A.move(d, g), x = A.move(d, g), u = 1, s < i[a].length - 2) { var H = A.curve(d + R, g, r - R, o, r, o); f += H, x += H; break } case 1: if (null === i[a][s + 1]) f += L ? A.line(d, h) : A.move(d, g), x += A.line(d, S) + A.line(p, S) + "z", b.push(f), v.push(x); else { var D = A.curve(d + R, g, r - R, o, r, o); f += D, x += D, s >= i[a].length - 2 && (L && (f += A.curve(r, o, r, o, r, h) + A.move(r, h)), x += A.curve(r, o, r, o, r, S) + A.line(p, S) + "z", b.push(f), v.push(x)) } }d = r, g = o; break; default: var O = function (t, e, i) { var a = []; switch (t) { case "stepline": a = A.line(e, null, "H") + A.line(null, i, "V"); break; case "linestep": a = A.line(null, i, "V") + A.line(e, null, "H"); break; case "straight": a = A.line(e, i) }return a }; if (null === i[a][s]) u = 0; else switch (u) { case 0: if (p = d, f = L ? A.move(d, c[s]) + A.line(d, g) : A.move(d, g), x = A.move(d, g), u = 1, s < i[a].length - 2) { var N = O(y, r, o); f += N, x += N; break } case 1: if (null === i[a][s + 1]) f += L ? A.line(d, h) : A.move(d, g), x += A.line(d, S) + A.line(p, S) + "z", b.push(f), v.push(x); else { var W = O(y, r, o); f += W, x += W, s >= i[a].length - 2 && (L && (f += A.line(r, h)), x += A.line(r, S) + A.line(p, S) + "z", b.push(f), v.push(x)) } }d = r, g = o }return { linePaths: b, areaPaths: v, pX: d, pY: g, pathState: u, segmentStartX: p, linePath: f, areaPath: x } } }, { key: "handleNullDataPoints", value: function (t, e, i, a, s) { var r = this.w; if (null === t[i][a] && r.config.markers.showNullDataPoints || 1 === t[i].length) { var o = this.strokeWidth - r.config.markers.strokeWidth / 2; o > 0 || (o = 0); var n = this.markers.plotChartMarkers(e, s, a + 1, o, !0); null !== n && this.elPointsMain.add(n) } } }]), t }(); window.TreemapSquared = {}, window.TreemapSquared.generate = function () { function t(e, i, a, s) { this.xoffset = e, this.yoffset = i, this.height = s, this.width = a, this.shortestEdge = function () { return Math.min(this.height, this.width) }, this.getCoordinates = function (t) { var e, i = [], a = this.xoffset, s = this.yoffset, o = r(t) / this.height, n = r(t) / this.width; if (this.width >= this.height) for (e = 0; e < t.length; e++)i.push([a, s, a + o, s + t[e] / o]), s += t[e] / o; else for (e = 0; e < t.length; e++)i.push([a, s, a + t[e] / n, s + n]), a += t[e] / n; return i }, this.cutArea = function (e) { var i; if (this.width >= this.height) { var a = e / this.height, s = this.width - a; i = new t(this.xoffset + a, this.yoffset, s, this.height) } else { var r = e / this.width, o = this.height - r; i = new t(this.xoffset, this.yoffset + r, this.width, o) } return i } } function e(e, a, s, o, n) { o = void 0 === o ? 0 : o, n = void 0 === n ? 0 : n; var l = i(function (t, e) { var i, a = [], s = e / r(t); for (i = 0; i < t.length; i++)a[i] = t[i] * s; return a }(e, a * s), [], new t(o, n, a, s), []); return function (t) { var e, i, a = []; for (e = 0; e < t.length; e++)for (i = 0; i < t[e].length; i++)a.push(t[e][i]); return a }(l) } function i(t, e, s, o) { var n, l, h; if (0 !== t.length) return n = s.shortestEdge(), function (t, e, i) { var s; if (0 === t.length) return !0; (s = t.slice()).push(e); var r = a(t, i), o = a(s, i); return r >= o }(e, l = t[0], n) ? (e.push(l), i(t.slice(1), e, s, o)) : (h = s.cutArea(r(e), o), o.push(s.getCoordinates(e)), i(t, [], h, o)), o; o.push(s.getCoordinates(e)) } function a(t, e) { var i = Math.min.apply(Math, t), a = Math.max.apply(Math, t), s = r(t); return Math.max(Math.pow(e, 2) * a / Math.pow(s, 2), Math.pow(s, 2) / (Math.pow(e, 2) * i)) } function s(t) { return t && t.constructor === Array } function r(t) { var e, i = 0; for (e = 0; e < t.length; e++)i += t[e]; return i } function o(t) { var e, i = 0; if (s(t[0])) for (e = 0; e < t.length; e++)i += o(t[e]); else i = r(t); return i } return function t(i, a, r, n, l) { n = void 0 === n ? 0 : n, l = void 0 === l ? 0 : l; var h, c, d = [], g = []; if (s(i[0])) { for (c = 0; c < i.length; c++)d[c] = o(i[c]); for (h = e(d, a, r, n, l), c = 0; c < i.length; c++)g.push(t(i[c], h[c][2] - h[c][0], h[c][3] - h[c][1], h[c][0], h[c][1])) } else g = e(i, a, r, n, l); return g } }(); var Rt, Ht, Dt = function () { function t(e, i) { a(this, t), this.ctx = e, this.w = e.w, this.strokeWidth = this.w.config.stroke.width, this.helpers = new At(e), this.dynamicAnim = this.w.config.chart.animations.dynamicAnimation, this.labels = [] } return r(t, [{ key: "draw", value: function (t) { var e = this, i = this.w, a = new m(this.ctx), s = new H(this.ctx), r = a.group({ class: "apexcharts-treemap" }); if (i.globals.noData) return r; var o = []; return t.forEach((function (t) { var e = t.map((function (t) { return Math.abs(t) })); o.push(e) })), this.negRange = this.helpers.checkColorRange(), i.config.series.forEach((function (t, i) { t.data.forEach((function (t) { Array.isArray(e.labels[i]) || (e.labels[i] = []), e.labels[i].push(t.x) })) })), window.TreemapSquared.generate(o, i.globals.gridWidth, i.globals.gridHeight).forEach((function (o, n) { var l = a.group({ class: "apexcharts-series apexcharts-treemap-series", seriesName: x.escapeString(i.globals.seriesNames[n]), rel: n + 1, "data:realIndex": n }); if (i.config.chart.dropShadow.enabled) { var h = i.config.chart.dropShadow; new v(e.ctx).dropShadow(r, h, n) } var c = a.group({ class: "apexcharts-data-labels" }); o.forEach((function (r, o) { var h = r[0], c = r[1], d = r[2], g = r[3], u = a.drawRect(h, c, d - h, g - c, i.config.plotOptions.treemap.borderRadius, "#fff", 1, e.strokeWidth, i.config.plotOptions.treemap.useFillColorAsStroke ? f : i.globals.stroke.colors[n]); u.attr({ cx: h, cy: c, index: n, i: n, j: o, width: d - h, height: g - c }); var p = e.helpers.getShadeColor(i.config.chart.type, n, o, e.negRange), f = p.color; void 0 !== i.config.series[n].data[o] && i.config.series[n].data[o].fillColor && (f = i.config.series[n].data[o].fillColor); var x = s.fillPath({ color: f, seriesNumber: n, dataPointIndex: o }); u.node.classList.add("apexcharts-treemap-rect"), u.attr({ fill: x }), e.helpers.addListeners(u); var b = { x: h + (d - h) / 2, y: c + (g - c) / 2, width: 0, height: 0 }, v = { x: h, y: c, width: d - h, height: g - c }; if (i.config.chart.animations.enabled && !i.globals.dataChanged) { var m = 1; i.globals.resized || (m = i.config.chart.animations.speed), e.animateTreemap(u, b, v, m) } if (i.globals.dataChanged) { var y = 1; e.dynamicAnim.enabled && i.globals.shouldAnimate && (y = e.dynamicAnim.speed, i.globals.previousPaths[n] && i.globals.previousPaths[n][o] && i.globals.previousPaths[n][o].rect && (b = i.globals.previousPaths[n][o].rect), e.animateTreemap(u, b, v, y)) } var w = e.getFontSize(r), k = i.config.dataLabels.formatter(e.labels[n][o], { value: i.globals.series[n][o], seriesIndex: n, dataPointIndex: o, w: i }); "truncate" === i.config.plotOptions.treemap.dataLabels.format && (w = parseInt(i.config.dataLabels.style.fontSize, 10), k = e.truncateLabels(k, w, h, c, d, g)); var A = e.helpers.calculateDataLabels({ text: k, x: (h + d) / 2, y: (c + g) / 2 + e.strokeWidth / 2 + w / 3, i: n, j: o, colorProps: p, fontSize: w, series: t }); i.config.dataLabels.enabled && A && e.rotateToFitLabel(A, w, k, h, c, d, g), l.add(u), null !== A && l.add(A) })), l.add(c), r.add(l) })), r } }, { key: "getFontSize", value: function (t) { var e = this.w; var i, a, s, r, o = function t(e) { var i, a = 0; if (Array.isArray(e[0])) for (i = 0; i < e.length; i++)a += t(e[i]); else for (i = 0; i < e.length; i++)a += e[i].length; return a }(this.labels) / function t(e) { var i, a = 0; if (Array.isArray(e[0])) for (i = 0; i < e.length; i++)a += t(e[i]); else for (i = 0; i < e.length; i++)a += 1; return a }(this.labels); return i = t[2] - t[0], a = t[3] - t[1], s = i * a, r = Math.pow(s, .5), Math.min(r / o, parseInt(e.config.dataLabels.style.fontSize, 10)) } }, { key: "rotateToFitLabel", value: function (t, e, i, a, s, r, o) { var n = new m(this.ctx), l = n.getTextRects(i, e); if (l.width + this.w.config.stroke.width + 5 > r - a && l.width <= o - s) { var h = n.rotateAroundCenter(t.node); t.node.setAttribute("transform", "rotate(-90 ".concat(h.x, " ").concat(h.y, ") translate(").concat(l.height / 3, ")")) } } }, { key: "truncateLabels", value: function (t, e, i, a, s, r) { var o = new m(this.ctx), n = o.getTextRects(t, e).width + this.w.config.stroke.width + 5 > s - i && r - a > s - i ? r - a : s - i, l = o.getTextBasedOnMaxWidth({ text: t, maxWidth: n, fontSize: e }); return t.length !== l.length && n / e < 5 ? "" : l } }, { key: "animateTreemap", value: function (t, e, i, a) { var s = new b(this.ctx); s.animateRect(t, { x: e.x, y: e.y, width: e.width, height: e.height }, { x: i.x, y: i.y, width: i.width, height: i.height }, a, (function () { s.animationCompleted(t) })) } }]), t }(), Ot = 86400, Nt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w, this.timeScaleArray = [], this.utc = this.w.config.xaxis.labels.datetimeUTC } return r(t, [{ key: "calculateTimeScaleTicks", value: function (t, i) { var a = this, s = this.w; if (s.globals.allSeriesCollapsed) return s.globals.labels = [], s.globals.timescaleLabels = [], []; var r = new A(this.ctx), o = (i - t) / 864e5; this.determineInterval(o), s.globals.disableZoomIn = !1, s.globals.disableZoomOut = !1, o < .00011574074074074075 ? s.globals.disableZoomIn = !0 : o > 5e4 && (s.globals.disableZoomOut = !0); var n = r.getTimeUnitsfromTimestamp(t, i, this.utc), l = s.globals.gridWidth / o, h = l / 24, c = h / 60, d = c / 60, g = Math.floor(24 * o), u = Math.floor(1440 * o), p = Math.floor(o * Ot), f = Math.floor(o), x = Math.floor(o / 30), b = Math.floor(o / 365), v = { minMillisecond: n.minMillisecond, minSecond: n.minSecond, minMinute: n.minMinute, minHour: n.minHour, minDate: n.minDate, minMonth: n.minMonth, minYear: n.minYear }, m = { firstVal: v, currentMillisecond: v.minMillisecond, currentSecond: v.minSecond, currentMinute: v.minMinute, currentHour: v.minHour, currentMonthDate: v.minDate, currentDate: v.minDate, currentMonth: v.minMonth, currentYear: v.minYear, daysWidthOnXAxis: l, hoursWidthOnXAxis: h, minutesWidthOnXAxis: c, secondsWidthOnXAxis: d, numberOfSeconds: p, numberOfMinutes: u, numberOfHours: g, numberOfDays: f, numberOfMonths: x, numberOfYears: b }; switch (this.tickInterval) { case "years": this.generateYearScale(m); break; case "months": case "half_year": this.generateMonthScale(m); break; case "months_days": case "months_fortnight": case "days": case "week_days": this.generateDayScale(m); break; case "hours": this.generateHourScale(m); break; case "minutes_fives": case "minutes": this.generateMinuteScale(m); break; case "seconds_tens": case "seconds_fives": case "seconds": this.generateSecondScale(m) }var y = this.timeScaleArray.map((function (t) { var i = { position: t.position, unit: t.unit, year: t.year, day: t.day ? t.day : 1, hour: t.hour ? t.hour : 0, month: t.month + 1 }; return "month" === t.unit ? e(e({}, i), {}, { day: 1, value: t.value + 1 }) : "day" === t.unit || "hour" === t.unit ? e(e({}, i), {}, { value: t.value }) : "minute" === t.unit ? e(e({}, i), {}, { value: t.value, minute: t.value }) : "second" === t.unit ? e(e({}, i), {}, { value: t.value, minute: t.minute, second: t.second }) : t })); return y.filter((function (t) { var e = 1, i = Math.ceil(s.globals.gridWidth / 120), r = t.value; void 0 !== s.config.xaxis.tickAmount && (i = s.config.xaxis.tickAmount), y.length > i && (e = Math.floor(y.length / i)); var o = !1, n = !1; switch (a.tickInterval) { case "years": "year" === t.unit && (o = !0); break; case "half_year": e = 7, "year" === t.unit && (o = !0); break; case "months": e = 1, "year" === t.unit && (o = !0); break; case "months_fortnight": e = 15, "year" !== t.unit && "month" !== t.unit || (o = !0), 30 === r && (n = !0); break; case "months_days": e = 10, "month" === t.unit && (o = !0), 30 === r && (n = !0); break; case "week_days": e = 8, "month" === t.unit && (o = !0); break; case "days": e = 1, "month" === t.unit && (o = !0); break; case "hours": "day" === t.unit && (o = !0); break; case "minutes_fives": case "seconds_fives": r % 5 != 0 && (n = !0); break; case "seconds_tens": r % 10 != 0 && (n = !0) }if ("hours" === a.tickInterval || "minutes_fives" === a.tickInterval || "seconds_tens" === a.tickInterval || "seconds_fives" === a.tickInterval) { if (!n) return !0 } else if ((r % e == 0 || o) && !n) return !0 })) } }, { key: "recalcDimensionsBasedOnFormat", value: function (t, e) { var i = this.w, a = this.formatDates(t), s = this.removeOverlappingTS(a); i.globals.timescaleLabels = s.slice(), new ot(this.ctx).plotCoords() } }, { key: "determineInterval", value: function (t) { var e = 24 * t, i = 60 * e; switch (!0) { case t / 365 > 5: this.tickInterval = "years"; break; case t > 800: this.tickInterval = "half_year"; break; case t > 180: this.tickInterval = "months"; break; case t > 90: this.tickInterval = "months_fortnight"; break; case t > 60: this.tickInterval = "months_days"; break; case t > 30: this.tickInterval = "week_days"; break; case t > 2: this.tickInterval = "days"; break; case e > 2.4: this.tickInterval = "hours"; break; case i > 15: this.tickInterval = "minutes_fives"; break; case i > 5: this.tickInterval = "minutes"; break; case i > 1: this.tickInterval = "seconds_tens"; break; case 60 * i > 20: this.tickInterval = "seconds_fives"; break; default: this.tickInterval = "seconds" } } }, { key: "generateYearScale", value: function (t) { var e = t.firstVal, i = t.currentMonth, a = t.currentYear, s = t.daysWidthOnXAxis, r = t.numberOfYears, o = e.minYear, n = 0, l = new A(this.ctx), h = "year"; if (e.minDate > 1 || e.minMonth > 0) { var c = l.determineRemainingDaysOfYear(e.minYear, e.minMonth, e.minDate); n = (l.determineDaysOfYear(e.minYear) - c + 1) * s, o = e.minYear + 1, this.timeScaleArray.push({ position: n, value: o, unit: h, year: o, month: x.monthMod(i + 1) }) } else 1 === e.minDate && 0 === e.minMonth && this.timeScaleArray.push({ position: n, value: o, unit: h, year: a, month: x.monthMod(i + 1) }); for (var d = o, g = n, u = 0; u < r; u++)d++, g = l.determineDaysOfYear(d - 1) * s + g, this.timeScaleArray.push({ position: g, value: d, unit: h, year: d, month: 1 }) } }, { key: "generateMonthScale", value: function (t) { var e = t.firstVal, i = t.currentMonthDate, a = t.currentMonth, s = t.currentYear, r = t.daysWidthOnXAxis, o = t.numberOfMonths, n = a, l = 0, h = new A(this.ctx), c = "month", d = 0; if (e.minDate > 1) { l = (h.determineDaysOfMonths(a + 1, e.minYear) - i + 1) * r, n = x.monthMod(a + 1); var g = s + d, u = x.monthMod(n), p = n; 0 === n && (c = "year", p = g, u = 1, g += d += 1), this.timeScaleArray.push({ position: l, value: p, unit: c, year: g, month: u }) } else this.timeScaleArray.push({ position: l, value: n, unit: c, year: s, month: x.monthMod(a) }); for (var f = n + 1, b = l, v = 0, m = 1; v < o; v++, m++) { 0 === (f = x.monthMod(f)) ? (c = "year", d += 1) : c = "month"; var y = this._getYear(s, f, d); b = h.determineDaysOfMonths(f, y) * r + b; var w = 0 === f ? y : f; this.timeScaleArray.push({ position: b, value: w, unit: c, year: y, month: 0 === f ? 1 : f }), f++ } } }, { key: "generateDayScale", value: function (t) { var e = t.firstVal, i = t.currentMonth, a = t.currentYear, s = t.hoursWidthOnXAxis, r = t.numberOfDays, o = new A(this.ctx), n = "day", l = e.minDate + 1, h = l, c = function (t, e, i) { return t > o.determineDaysOfMonths(e + 1, i) ? (h = 1, n = "month", g = e += 1, e) : e }, d = (24 - e.minHour) * s, g = l, u = c(h, i, a); 0 === e.minHour && 1 === e.minDate ? (d = 0, g = x.monthMod(e.minMonth), n = "month", h = e.minDate) : 1 !== e.minDate && 0 === e.minHour && 0 === e.minMinute && (d = 0, l = e.minDate, g = l, u = c(h = l, i, a)), this.timeScaleArray.push({ position: d, value: g, unit: n, year: this._getYear(a, u, 0), month: x.monthMod(u), day: h }); for (var p = d, f = 0; f < r; f++) { n = "day", u = c(h += 1, u, this._getYear(a, u, 0)); var b = this._getYear(a, u, 0); p = 24 * s + p; var v = 1 === h ? x.monthMod(u) : h; this.timeScaleArray.push({ position: p, value: v, unit: n, year: b, month: x.monthMod(u), day: v }) } } }, { key: "generateHourScale", value: function (t) { var e = t.firstVal, i = t.currentDate, a = t.currentMonth, s = t.currentYear, r = t.minutesWidthOnXAxis, o = t.numberOfHours, n = new A(this.ctx), l = "hour", h = function (t, e) { return t > n.determineDaysOfMonths(e + 1, s) && (f = 1, e += 1), { month: e, date: f } }, c = function (t, e) { return t > n.determineDaysOfMonths(e + 1, s) ? e += 1 : e }, d = 60 - (e.minMinute + e.minSecond / 60), g = d * r, u = e.minHour + 1, p = u; 60 === d && (g = 0, p = u = e.minHour); var f = i; p >= 24 && (p = 0, f += 1, l = "day"); var b = h(f, a).month; b = c(f, b), this.timeScaleArray.push({ position: g, value: u, unit: l, day: f, hour: p, year: s, month: x.monthMod(b) }), p++; for (var v = g, m = 0; m < o; m++) { if (l = "hour", p >= 24) p = 0, l = "day", b = h(f += 1, b).month, b = c(f, b); var y = this._getYear(s, b, 0); v = 60 * r + v; var w = 0 === p ? f : p; this.timeScaleArray.push({ position: v, value: w, unit: l, hour: p, day: f, year: y, month: x.monthMod(b) }), p++ } } }, { key: "generateMinuteScale", value: function (t) { for (var e = t.currentMillisecond, i = t.currentSecond, a = t.currentMinute, s = t.currentHour, r = t.currentDate, o = t.currentMonth, n = t.currentYear, l = t.minutesWidthOnXAxis, h = t.secondsWidthOnXAxis, c = t.numberOfMinutes, d = a + 1, g = r, u = o, p = n, f = s, b = (60 - i - e / 1e3) * h, v = 0; v < c; v++)d >= 60 && (d = 0, 24 === (f += 1) && (f = 0)), this.timeScaleArray.push({ position: b, value: d, unit: "minute", hour: f, minute: d, day: g, year: this._getYear(p, u, 0), month: x.monthMod(u) }), b += l, d++ } }, { key: "generateSecondScale", value: function (t) { for (var e = t.currentMillisecond, i = t.currentSecond, a = t.currentMinute, s = t.currentHour, r = t.currentDate, o = t.currentMonth, n = t.currentYear, l = t.secondsWidthOnXAxis, h = t.numberOfSeconds, c = i + 1, d = a, g = r, u = o, p = n, f = s, b = (1e3 - e) / 1e3 * l, v = 0; v < h; v++)c >= 60 && (c = 0, ++d >= 60 && (d = 0, 24 === ++f && (f = 0))), this.timeScaleArray.push({ position: b, value: c, unit: "second", hour: f, minute: d, second: c, day: g, year: this._getYear(p, u, 0), month: x.monthMod(u) }), b += l, c++ } }, { key: "createRawDateString", value: function (t, e) { var i = t.year; return 0 === t.month && (t.month = 1), i += "-" + ("0" + t.month.toString()).slice(-2), "day" === t.unit ? i += "day" === t.unit ? "-" + ("0" + e).slice(-2) : "-01" : i += "-" + ("0" + (t.day ? t.day : "1")).slice(-2), "hour" === t.unit ? i += "hour" === t.unit ? "T" + ("0" + e).slice(-2) : "T00" : i += "T" + ("0" + (t.hour ? t.hour : "0")).slice(-2), "minute" === t.unit ? i += ":" + ("0" + e).slice(-2) : i += ":" + (t.minute ? ("0" + t.minute).slice(-2) : "00"), "second" === t.unit ? i += ":" + ("0" + e).slice(-2) : i += ":00", this.utc && (i += ".000Z"), i } }, { key: "formatDates", value: function (t) { var e = this, i = this.w; return t.map((function (t) { var a = t.value.toString(), s = new A(e.ctx), r = e.createRawDateString(t, a), o = s.getDate(s.parseDate(r)); if (e.utc || (o = s.getDate(s.parseDateWithTimezone(r))), void 0 === i.config.xaxis.labels.format) { var n = "dd MMM", l = i.config.xaxis.labels.datetimeFormatter; "year" === t.unit && (n = l.year), "month" === t.unit && (n = l.month), "day" === t.unit && (n = l.day), "hour" === t.unit && (n = l.hour), "minute" === t.unit && (n = l.minute), "second" === t.unit && (n = l.second), a = s.formatDate(o, n) } else a = s.formatDate(o, i.config.xaxis.labels.format); return { dateString: r, position: t.position, value: a, unit: t.unit, year: t.year, month: t.month } })) } }, { key: "removeOverlappingTS", value: function (t) { var e, i = this, a = new m(this.ctx), s = !1; t.length > 0 && t[0].value && t.every((function (e) { return e.value.length === t[0].value.length })) && (s = !0, e = a.getTextRects(t[0].value).width); var r = 0, o = t.map((function (o, n) { if (n > 0 && i.w.config.xaxis.labels.hideOverlappingLabels) { var l = s ? e : a.getTextRects(t[r].value).width, h = t[r].position; return o.position > h + l + 10 ? (r = n, o) : null } return o })); return o = o.filter((function (t) { return null !== t })) } }, { key: "_getYear", value: function (t, e, i) { return t + Math.floor(e / 12) + i } }]), t }(), Wt = function () { function t(e, i) { a(this, t), this.ctx = i, this.w = i.w, this.el = e } return r(t, [{ key: "setupElements", value: function () { var t = this.w.globals, e = this.w.config, i = e.chart.type; t.axisCharts = ["line", "area", "bar", "rangeBar", "rangeArea", "candlestick", "boxPlot", "scatter", "bubble", "radar", "heatmap", "treemap"].indexOf(i) > -1, t.xyCharts = ["line", "area", "bar", "rangeBar", "rangeArea", "candlestick", "boxPlot", "scatter", "bubble"].indexOf(i) > -1, t.isBarHorizontal = ("bar" === e.chart.type || "rangeBar" === e.chart.type || "boxPlot" === e.chart.type) && e.plotOptions.bar.horizontal, t.chartClass = ".apexcharts" + t.chartID, t.dom.baseEl = this.el, t.dom.elWrap = document.createElement("div"), m.setAttrs(t.dom.elWrap, { id: t.chartClass.substring(1), class: "apexcharts-canvas " + t.chartClass.substring(1) }), this.el.appendChild(t.dom.elWrap), t.dom.Paper = new window.SVG.Doc(t.dom.elWrap), t.dom.Paper.attr({ class: "apexcharts-svg", "xmlns:data": "ApexChartsNS", transform: "translate(".concat(e.chart.offsetX, ", ").concat(e.chart.offsetY, ")") }), t.dom.Paper.node.style.background = "dark" !== e.theme.mode || e.chart.background ? e.chart.background : "rgba(0, 0, 0, 0.8)", this.setSVGDimensions(), t.dom.elLegendForeign = document.createElementNS(t.SVGNS, "foreignObject"), m.setAttrs(t.dom.elLegendForeign, { x: 0, y: 0, width: t.svgWidth, height: t.svgHeight }), t.dom.elLegendWrap = document.createElement("div"), t.dom.elLegendWrap.classList.add("apexcharts-legend"), t.dom.elLegendWrap.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"), t.dom.elLegendForeign.appendChild(t.dom.elLegendWrap), t.dom.Paper.node.appendChild(t.dom.elLegendForeign), t.dom.elGraphical = t.dom.Paper.group().attr({ class: "apexcharts-inner apexcharts-graphical" }), t.dom.elDefs = t.dom.Paper.defs(), t.dom.Paper.add(t.dom.elGraphical), t.dom.elGraphical.add(t.dom.elDefs) } }, { key: "plotChartType", value: function (t, e) { var i = this.w, a = i.config, s = i.globals, r = { series: [], i: [] }, o = { series: [], i: [] }, n = { series: [], i: [] }, l = { series: [], i: [] }, h = { series: [], i: [] }, c = { series: [], i: [] }, d = { series: [], i: [] }, g = { series: [], i: [] }, p = { series: [], seriesRangeEnd: [], i: [] }, f = void 0 !== a.chart.type ? a.chart.type : "line", x = null, b = 0; s.series.forEach((function (e, a) { var u = t[a].type || f; switch (u) { case "column": case "bar": h.series.push(e), h.i.push(a), i.globals.columnSeries = h; break; case "area": o.series.push(e), o.i.push(a); break; case "line": r.series.push(e), r.i.push(a); break; case "scatter": n.series.push(e), n.i.push(a); break; case "bubble": l.series.push(e), l.i.push(a); break; case "candlestick": c.series.push(e), c.i.push(a); break; case "boxPlot": d.series.push(e), d.i.push(a); break; case "rangeBar": g.series.push(e), g.i.push(a); break; case "rangeArea": p.series.push(s.seriesRangeStart[a]), p.seriesRangeEnd.push(s.seriesRangeEnd[a]), p.i.push(a); break; case "heatmap": case "treemap": case "pie": case "donut": case "polarArea": case "radialBar": case "radar": x = u; break; default: console.warn("You have specified an unrecognized series type (", u, ").") }f !== u && "scatter" !== u && b++ })), b > 0 && (null !== x && console.warn("Chart or series type ", x, " can not appear with other chart or series types."), h.series.length > 0 && a.plotOptions.bar.horizontal && (b -= h.length, h = { series: [], i: [] }, i.globals.columnSeries = { series: [], i: [] }, console.warn("Horizontal bars are not supported in a mixed/combo chart. Please turn off `plotOptions.bar.horizontal`"))), s.comboCharts || (s.comboCharts = b > 0); var v = new Ft(this.ctx, e), m = new kt(this.ctx, e); this.ctx.pie = new Lt(this.ctx); var w = new Mt(this.ctx); this.ctx.rangeBar = new It(this.ctx, e); var k = new Pt(this.ctx), A = []; if (s.comboCharts) { var S, C, L = new y(this.ctx); if (o.series.length > 0) (S = A).push.apply(S, u(L.drawSeriesByGroup(o, s.areaGroups, "area", v))); if (h.series.length > 0) if (i.config.chart.stacked) { var P = new wt(this.ctx, e); A.push(P.draw(h.series, h.i)) } else this.ctx.bar = new yt(this.ctx, e), A.push(this.ctx.bar.draw(h.series, h.i)); if (p.series.length > 0 && A.push(v.draw(p.series, "rangeArea", p.i, p.seriesRangeEnd)), r.series.length > 0) (C = A).push.apply(C, u(L.drawSeriesByGroup(r, s.lineGroups, "line", v))); if (c.series.length > 0 && A.push(m.draw(c.series, "candlestick", c.i)), d.series.length > 0 && A.push(m.draw(d.series, "boxPlot", d.i)), g.series.length > 0 && A.push(this.ctx.rangeBar.draw(g.series, g.i)), n.series.length > 0) { var M = new Ft(this.ctx, e, !0); A.push(M.draw(n.series, "scatter", n.i)) } if (l.series.length > 0) { var I = new Ft(this.ctx, e, !0); A.push(I.draw(l.series, "bubble", l.i)) } } else switch (a.chart.type) { case "line": A = v.draw(s.series, "line"); break; case "area": A = v.draw(s.series, "area"); break; case "bar": if (a.chart.stacked) A = new wt(this.ctx, e).draw(s.series); else this.ctx.bar = new yt(this.ctx, e), A = this.ctx.bar.draw(s.series); break; case "candlestick": A = new kt(this.ctx, e).draw(s.series, "candlestick"); break; case "boxPlot": A = new kt(this.ctx, e).draw(s.series, a.chart.type); break; case "rangeBar": A = this.ctx.rangeBar.draw(s.series); break; case "rangeArea": A = v.draw(s.seriesRangeStart, "rangeArea", void 0, s.seriesRangeEnd); break; case "heatmap": A = new St(this.ctx, e).draw(s.series); break; case "treemap": A = new Dt(this.ctx, e).draw(s.series); break; case "pie": case "donut": case "polarArea": A = this.ctx.pie.draw(s.series); break; case "radialBar": A = w.draw(s.series); break; case "radar": A = k.draw(s.series); break; default: A = v.draw(s.series) }return A } }, { key: "setSVGDimensions", value: function () { var t = this.w.globals, e = this.w.config; t.svgWidth = e.chart.width, t.svgHeight = e.chart.height; var i = x.getDimensions(this.el), a = e.chart.width.toString().split(/[0-9]+/g).pop(); "%" === a ? x.isNumber(i[0]) && (0 === i[0].width && (i = x.getDimensions(this.el.parentNode)), t.svgWidth = i[0] * parseInt(e.chart.width, 10) / 100) : "px" !== a && "" !== a || (t.svgWidth = parseInt(e.chart.width, 10)); var s = e.chart.height.toString().split(/[0-9]+/g).pop(); if ("auto" !== t.svgHeight && "" !== t.svgHeight) if ("%" === s) { var r = x.getDimensions(this.el.parentNode); t.svgHeight = r[1] * parseInt(e.chart.height, 10) / 100 } else t.svgHeight = parseInt(e.chart.height, 10); else t.axisCharts ? t.svgHeight = t.svgWidth / 1.61 : t.svgHeight = t.svgWidth / 1.2; if (t.svgWidth < 0 && (t.svgWidth = 0), t.svgHeight < 0 && (t.svgHeight = 0), m.setAttrs(t.dom.Paper.node, { width: t.svgWidth, height: t.svgHeight }), "%" !== s) { var o = e.chart.sparkline.enabled ? 0 : t.axisCharts ? e.chart.parentHeightOffset : 0; t.dom.Paper.node.parentNode.parentNode.style.minHeight = t.svgHeight + o + "px" } t.dom.elWrap.style.width = t.svgWidth + "px", t.dom.elWrap.style.height = t.svgHeight + "px" } }, { key: "shiftGraphPosition", value: function () { var t = this.w.globals, e = t.translateY, i = { transform: "translate(" + t.translateX + ", " + e + ")" }; m.setAttrs(t.dom.elGraphical.node, i) } }, { key: "resizeNonAxisCharts", value: function () { var t = this.w, e = t.globals, i = 0, a = t.config.chart.sparkline.enabled ? 1 : 15; a += t.config.grid.padding.bottom, "top" !== t.config.legend.position && "bottom" !== t.config.legend.position || !t.config.legend.show || t.config.legend.floating || (i = new lt(this.ctx).legendHelpers.getLegendBBox().clwh + 10); var s = t.globals.dom.baseEl.querySelector(".apexcharts-radialbar, .apexcharts-pie"), r = 2.05 * t.globals.radialSize; if (s && !t.config.chart.sparkline.enabled && 0 !== t.config.plotOptions.radialBar.startAngle) { var o = x.getBoundingClientRect(s); r = o.bottom; var n = o.bottom - o.top; r = Math.max(2.05 * t.globals.radialSize, n) } var l = r + e.translateY + i + a; e.dom.elLegendForeign && e.dom.elLegendForeign.setAttribute("height", l), t.config.chart.height && String(t.config.chart.height).indexOf("%") > 0 || (e.dom.elWrap.style.height = l + "px", m.setAttrs(e.dom.Paper.node, { height: l }), e.dom.Paper.node.parentNode.parentNode.style.minHeight = l + "px") } }, { key: "coreCalculations", value: function () { new U(this.ctx).init() } }, { key: "resetGlobals", value: function () { var t = this, e = function () { return t.w.config.series.map((function (t) { return [] })) }, i = new F, a = this.w.globals; i.initGlobalVars(a), a.seriesXvalues = e(), a.seriesYvalues = e() } }, { key: "isMultipleY", value: function () { if (this.w.config.yaxis.constructor === Array && this.w.config.yaxis.length > 1) return this.w.globals.isMultipleYAxis = !0, !0 } }, { key: "xySettings", value: function () { var t = null, e = this.w; if (e.globals.axisCharts) { if ("back" === e.config.xaxis.crosshairs.position) new Q(this.ctx).drawXCrosshairs(); if ("back" === e.config.yaxis[0].crosshairs.position) new Q(this.ctx).drawYCrosshairs(); if ("datetime" === e.config.xaxis.type && void 0 === e.config.xaxis.labels.formatter) { this.ctx.timeScale = new Nt(this.ctx); var i = []; isFinite(e.globals.minX) && isFinite(e.globals.maxX) && !e.globals.isBarHorizontal ? i = this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minX, e.globals.maxX) : e.globals.isBarHorizontal && (i = this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minY, e.globals.maxY)), this.ctx.timeScale.recalcDimensionsBasedOnFormat(i) } t = new y(this.ctx).getCalculatedRatios() } return t } }, { key: "updateSourceChart", value: function (t) { this.ctx.w.globals.selection = void 0, this.ctx.updateHelpers._updateOptions({ chart: { selection: { xaxis: { min: t.w.globals.minX, max: t.w.globals.maxX } } } }, !1, !1) } }, { key: "setupBrushHandler", value: function () { var t = this, e = this.w; if (e.config.chart.brush.enabled && "function" != typeof e.config.chart.events.selection) { var i = Array.isArray(e.config.chart.brush.targets) ? e.config.chart.brush.targets : [e.config.chart.brush.target]; i.forEach((function (e) { var i = ApexCharts.getChartByID(e); i.w.globals.brushSource = t.ctx, "function" != typeof i.w.config.chart.events.zoomed && (i.w.config.chart.events.zoomed = function () { t.updateSourceChart(i) }), "function" != typeof i.w.config.chart.events.scrolled && (i.w.config.chart.events.scrolled = function () { t.updateSourceChart(i) }) })), e.config.chart.events.selection = function (t, e) { i.forEach((function (t) { ApexCharts.getChartByID(t).ctx.updateHelpers._updateOptions({ xaxis: { min: e.xaxis.min, max: e.xaxis.max } }, !1, !1, !1, !1) })) } } } }]), t }(), Bt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "_updateOptions", value: function (t) { var e = this, a = arguments.length > 1 && void 0 !== arguments[1] && arguments[1], s = !(arguments.length > 2 && void 0 !== arguments[2]) || arguments[2], r = !(arguments.length > 3 && void 0 !== arguments[3]) || arguments[3], o = arguments.length > 4 && void 0 !== arguments[4] && arguments[4]; return new Promise((function (n) { var l = [e.ctx]; r && (l = e.ctx.getSyncedCharts()), e.ctx.w.globals.isExecCalled && (l = [e.ctx], e.ctx.w.globals.isExecCalled = !1), l.forEach((function (r, h) { var c = r.w; if (c.globals.shouldAnimate = s, a || (c.globals.resized = !0, c.globals.dataChanged = !0, s && r.series.getPreviousPaths()), t && "object" === i(t) && (r.config = new Y(t), t = y.extendArrayProps(r.config, t, c), r.w.globals.chartID !== e.ctx.w.globals.chartID && delete t.series, c.config = x.extend(c.config, t), o && (c.globals.lastXAxis = t.xaxis ? x.clone(t.xaxis) : [], c.globals.lastYAxis = t.yaxis ? x.clone(t.yaxis) : [], c.globals.initialConfig = x.extend({}, c.config), c.globals.initialSeries = x.clone(c.config.series), t.series))) { for (var d = 0; d < c.globals.collapsedSeriesIndices.length; d++) { var g = c.config.series[c.globals.collapsedSeriesIndices[d]]; c.globals.collapsedSeries[d].data = c.globals.axisCharts ? g.data.slice() : g } for (var u = 0; u < c.globals.ancillaryCollapsedSeriesIndices.length; u++) { var p = c.config.series[c.globals.ancillaryCollapsedSeriesIndices[u]]; c.globals.ancillaryCollapsedSeries[u].data = c.globals.axisCharts ? p.data.slice() : p } r.series.emptyCollapsedSeries(c.config.series) } return r.update(t).then((function () { h === l.length - 1 && n(r) })) })) })) } }, { key: "_updateSeries", value: function (t, e) { var i = this, a = arguments.length > 2 && void 0 !== arguments[2] && arguments[2]; return new Promise((function (s) { var r, o = i.w; return o.globals.shouldAnimate = e, o.globals.dataChanged = !0, e && i.ctx.series.getPreviousPaths(), o.globals.axisCharts ? (0 === (r = t.map((function (t, e) { return i._extendSeries(t, e) }))).length && (r = [{ data: [] }]), o.config.series = r) : o.config.series = t.slice(), a && (o.globals.initialConfig.series = x.clone(o.config.series), o.globals.initialSeries = x.clone(o.config.series)), i.ctx.update().then((function () { s(i.ctx) })) })) } }, { key: "_extendSeries", value: function (t, i) { var a = this.w, s = a.config.series[i]; return e(e({}, a.config.series[i]), {}, { name: t.name ? t.name : null == s ? void 0 : s.name, color: t.color ? t.color : null == s ? void 0 : s.color, type: t.type ? t.type : null == s ? void 0 : s.type, group: t.group ? t.group : null == s ? void 0 : s.group, data: t.data ? t.data : null == s ? void 0 : s.data, zIndex: void 0 !== t.zIndex ? t.zIndex : i }) } }, { key: "toggleDataPointSelection", value: function (t, e) { var i = this.w, a = null, s = ".apexcharts-series[data\\:realIndex='".concat(t, "']"); return i.globals.axisCharts ? a = i.globals.dom.Paper.select("".concat(s, " path[j='").concat(e, "'], ").concat(s, " circle[j='").concat(e, "'], ").concat(s, " rect[j='").concat(e, "']")).members[0] : void 0 === e && (a = i.globals.dom.Paper.select("".concat(s, " path[j='").concat(t, "']")).members[0], "pie" !== i.config.chart.type && "polarArea" !== i.config.chart.type && "donut" !== i.config.chart.type || this.ctx.pie.pieClicked(t)), a ? (new m(this.ctx).pathMouseDown(a, null), a.node ? a.node : null) : (console.warn("toggleDataPointSelection: Element not found"), null) } }, { key: "forceXAxisUpdate", value: function (t) { var e = this.w; if (["min", "max"].forEach((function (i) { void 0 !== t.xaxis[i] && (e.config.xaxis[i] = t.xaxis[i], e.globals.lastXAxis[i] = t.xaxis[i]) })), t.xaxis.categories && t.xaxis.categories.length && (e.config.xaxis.categories = t.xaxis.categories), e.config.xaxis.convertedCatToNumeric) { var i = new E(t); t = i.convertCatToNumericXaxis(t, this.ctx) } return t } }, { key: "forceYAxisUpdate", value: function (t) { return t.chart && t.chart.stacked && "100%" === t.chart.stackType && (Array.isArray(t.yaxis) ? t.yaxis.forEach((function (e, i) { t.yaxis[i].min = 0, t.yaxis[i].max = 100 })) : (t.yaxis.min = 0, t.yaxis.max = 100)), t } }, { key: "revertDefaultAxisMinMax", value: function (t) { var e = this, i = this.w, a = i.globals.lastXAxis, s = i.globals.lastYAxis; t && t.xaxis && (a = t.xaxis), t && t.yaxis && (s = t.yaxis), i.config.xaxis.min = a.min, i.config.xaxis.max = a.max; var r = function (t) { void 0 !== s[t] && (i.config.yaxis[t].min = s[t].min, i.config.yaxis[t].max = s[t].max) }; i.config.yaxis.map((function (t, a) { i.globals.zoomed || void 0 !== s[a] ? r(a) : void 0 !== e.ctx.opts.yaxis[a] && (t.min = e.ctx.opts.yaxis[a].min, t.max = e.ctx.opts.yaxis[a].max) })) } }]), t }(); Rt = "undefined" != typeof window ? window : void 0, Ht = function (t, e) { var a = (void 0 !== this ? this : t).SVG = function (t) { if (a.supported) return t = new a.Doc(t), a.parser.draw || a.prepare(), t }; if (a.ns = "http://www.w3.org/2000/svg", a.xmlns = "http://www.w3.org/2000/xmlns/", a.xlink = "http://www.w3.org/1999/xlink", a.svgjs = "http://svgjs.dev", a.supported = !0, !a.supported) return !1; a.did = 1e3, a.eid = function (t) { return "Svgjs" + d(t) + a.did++ }, a.create = function (t) { var i = e.createElementNS(this.ns, t); return i.setAttribute("id", this.eid(t)), i }, a.extend = function () { var t, e; e = (t = [].slice.call(arguments)).pop(); for (var i = t.length - 1; i >= 0; i--)if (t[i]) for (var s in e) t[i].prototype[s] = e[s]; a.Set && a.Set.inherit && a.Set.inherit() }, a.invent = function (t) { var e = "function" == typeof t.create ? t.create : function () { this.constructor.call(this, a.create(t.create)) }; return t.inherit && (e.prototype = new t.inherit), t.extend && a.extend(e, t.extend), t.construct && a.extend(t.parent || a.Container, t.construct), e }, a.adopt = function (e) { return e ? e.instance ? e.instance : ((i = "svg" == e.nodeName ? e.parentNode instanceof t.SVGElement ? new a.Nested : new a.Doc : "linearGradient" == e.nodeName ? new a.Gradient("linear") : "radialGradient" == e.nodeName ? new a.Gradient("radial") : a[d(e.nodeName)] ? new (a[d(e.nodeName)]) : new a.Element(e)).type = e.nodeName, i.node = e, e.instance = i, i instanceof a.Doc && i.namespace().defs(), i.setData(JSON.parse(e.getAttribute("svgjs:data")) || {}), i) : null; var i }, a.prepare = function () { var t = e.getElementsByTagName("body")[0], i = (t ? new a.Doc(t) : a.adopt(e.documentElement).nested()).size(2, 0); a.parser = { body: t || e.documentElement, draw: i.style("opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden").node, poly: i.polyline().node, path: i.path().node, native: a.create("svg") } }, a.parser = { native: a.create("svg") }, e.addEventListener("DOMContentLoaded", (function () { a.parser.draw || a.prepare() }), !1), a.regex = { numberAndUnit: /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i, hex: /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i, rgb: /rgb\((\d+),(\d+),(\d+)\)/, reference: /#([a-z0-9\-_]+)/i, transforms: /\)\s*,?\s*/, whitespace: /\s/g, isHex: /^#[a-f0-9]{3,6}$/i, isRgb: /^rgb\(/, isCss: /[^:]+:[^;]+;?/, isBlank: /^(\s+)?$/, isNumber: /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, isPercent: /^-?[\d\.]+%$/, isImage: /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i, delimiter: /[\s,]+/, hyphen: /([^e])\-/gi, pathLetters: /[MLHVCSQTAZ]/gi, isPathLetter: /[MLHVCSQTAZ]/i, numbersWithDots: /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi, dots: /\./g }, a.utils = { map: function (t, e) { for (var i = t.length, a = [], s = 0; s < i; s++)a.push(e(t[s])); return a }, filter: function (t, e) { for (var i = t.length, a = [], s = 0; s < i; s++)e(t[s]) && a.push(t[s]); return a }, filterSVGElements: function (e) { return this.filter(e, (function (e) { return e instanceof t.SVGElement })) } }, a.defaults = { attrs: { "fill-opacity": 1, "stroke-opacity": 1, "stroke-width": 0, "stroke-linejoin": "miter", "stroke-linecap": "butt", fill: "#000000", stroke: "#000000", opacity: 1, x: 0, y: 0, cx: 0, cy: 0, width: 0, height: 0, r: 0, rx: 0, ry: 0, offset: 0, "stop-opacity": 1, "stop-color": "#000000", "font-size": 16, "font-family": "Helvetica, Arial, sans-serif", "text-anchor": "start" } }, a.Color = function (t) { var e, s; this.r = 0, this.g = 0, this.b = 0, t && ("string" == typeof t ? a.regex.isRgb.test(t) ? (e = a.regex.rgb.exec(t.replace(a.regex.whitespace, "")), this.r = parseInt(e[1]), this.g = parseInt(e[2]), this.b = parseInt(e[3])) : a.regex.isHex.test(t) && (e = a.regex.hex.exec(4 == (s = t).length ? ["#", s.substring(1, 2), s.substring(1, 2), s.substring(2, 3), s.substring(2, 3), s.substring(3, 4), s.substring(3, 4)].join("") : s), this.r = parseInt(e[1], 16), this.g = parseInt(e[2], 16), this.b = parseInt(e[3], 16)) : "object" === i(t) && (this.r = t.r, this.g = t.g, this.b = t.b)) }, a.extend(a.Color, { toString: function () { return this.toHex() }, toHex: function () { return "#" + g(this.r) + g(this.g) + g(this.b) }, toRgb: function () { return "rgb(" + [this.r, this.g, this.b].join() + ")" }, brightness: function () { return this.r / 255 * .3 + this.g / 255 * .59 + this.b / 255 * .11 }, morph: function (t) { return this.destination = new a.Color(t), this }, at: function (t) { return this.destination ? (t = t < 0 ? 0 : t > 1 ? 1 : t, new a.Color({ r: ~~(this.r + (this.destination.r - this.r) * t), g: ~~(this.g + (this.destination.g - this.g) * t), b: ~~(this.b + (this.destination.b - this.b) * t) })) : this } }), a.Color.test = function (t) { return t += "", a.regex.isHex.test(t) || a.regex.isRgb.test(t) }, a.Color.isRgb = function (t) { return t && "number" == typeof t.r && "number" == typeof t.g && "number" == typeof t.b }, a.Color.isColor = function (t) { return a.Color.isRgb(t) || a.Color.test(t) }, a.Array = function (t, e) { 0 == (t = (t || []).valueOf()).length && e && (t = e.valueOf()), this.value = this.parse(t) }, a.extend(a.Array, { toString: function () { return this.value.join(" ") }, valueOf: function () { return this.value }, parse: function (t) { return t = t.valueOf(), Array.isArray(t) ? t : this.split(t) } }), a.PointArray = function (t, e) { a.Array.call(this, t, e || [[0, 0]]) }, a.PointArray.prototype = new a.Array, a.PointArray.prototype.constructor = a.PointArray; for (var s = { M: function (t, e, i) { return e.x = i.x = t[0], e.y = i.y = t[1], ["M", e.x, e.y] }, L: function (t, e) { return e.x = t[0], e.y = t[1], ["L", t[0], t[1]] }, H: function (t, e) { return e.x = t[0], ["H", t[0]] }, V: function (t, e) { return e.y = t[0], ["V", t[0]] }, C: function (t, e) { return e.x = t[4], e.y = t[5], ["C", t[0], t[1], t[2], t[3], t[4], t[5]] }, Q: function (t, e) { return e.x = t[2], e.y = t[3], ["Q", t[0], t[1], t[2], t[3]] }, S: function (t, e) { return e.x = t[2], e.y = t[3], ["S", t[0], t[1], t[2], t[3]] }, Z: function (t, e, i) { return e.x = i.x, e.y = i.y, ["Z"] } }, r = "mlhvqtcsaz".split(""), o = 0, n = r.length; o < n; ++o)s[r[o]] = function (t) { return function (e, i, a) { if ("H" == t) e[0] = e[0] + i.x; else if ("V" == t) e[0] = e[0] + i.y; else if ("A" == t) e[5] = e[5] + i.x, e[6] = e[6] + i.y; else for (var r = 0, o = e.length; r < o; ++r)e[r] = e[r] + (r % 2 ? i.y : i.x); if (s && "function" == typeof s[t]) return s[t](e, i, a) } }(r[o].toUpperCase()); a.PathArray = function (t, e) { a.Array.call(this, t, e || [["M", 0, 0]]) }, a.PathArray.prototype = new a.Array, a.PathArray.prototype.constructor = a.PathArray, a.extend(a.PathArray, { toString: function () { return function (t) { for (var e = 0, i = t.length, a = ""; e < i; e++)a += t[e][0], null != t[e][1] && (a += t[e][1], null != t[e][2] && (a += " ", a += t[e][2], null != t[e][3] && (a += " ", a += t[e][3], a += " ", a += t[e][4], null != t[e][5] && (a += " ", a += t[e][5], a += " ", a += t[e][6], null != t[e][7] && (a += " ", a += t[e][7]))))); return a + " " }(this.value) }, move: function (t, e) { var i = this.bbox(); return i.x, i.y, this }, at: function (t) { if (!this.destination) return this; for (var e = this.value, i = this.destination.value, s = [], r = new a.PathArray, o = 0, n = e.length; o < n; o++) { s[o] = [e[o][0]]; for (var l = 1, h = e[o].length; l < h; l++)s[o][l] = e[o][l] + (i[o][l] - e[o][l]) * t; "A" === s[o][0] && (s[o][4] = +(0 != s[o][4]), s[o][5] = +(0 != s[o][5])) } return r.value = s, r }, parse: function (t) { if (t instanceof a.PathArray) return t.valueOf(); var e, i = { M: 2, L: 2, H: 1, V: 1, C: 6, S: 4, Q: 4, T: 2, A: 7, Z: 0 }; t = "string" == typeof t ? t.replace(a.regex.numbersWithDots, h).replace(a.regex.pathLetters, " $& ").replace(a.regex.hyphen, "$1 -").trim().split(a.regex.delimiter) : t.reduce((function (t, e) { return [].concat.call(t, e) }), []); var r = [], o = new a.Point, n = new a.Point, l = 0, c = t.length; do { a.regex.isPathLetter.test(t[l]) ? (e = t[l], ++l) : "M" == e ? e = "L" : "m" == e && (e = "l"), r.push(s[e].call(null, t.slice(l, l += i[e.toUpperCase()]).map(parseFloat), o, n)) } while (c > l); return r }, bbox: function () { return a.parser.draw || a.prepare(), a.parser.path.setAttribute("d", this.toString()), a.parser.path.getBBox() } }), a.Number = a.invent({ create: function (t, e) { this.value = 0, this.unit = e || "", "number" == typeof t ? this.value = isNaN(t) ? 0 : isFinite(t) ? t : t < 0 ? -34e37 : 34e37 : "string" == typeof t ? (e = t.match(a.regex.numberAndUnit)) && (this.value = parseFloat(e[1]), "%" == e[5] ? this.value /= 100 : "s" == e[5] && (this.value *= 1e3), this.unit = e[5]) : t instanceof a.Number && (this.value = t.valueOf(), this.unit = t.unit) }, extend: { toString: function () { return ("%" == this.unit ? ~~(1e8 * this.value) / 1e6 : "s" == this.unit ? this.value / 1e3 : this.value) + this.unit }, toJSON: function () { return this.toString() }, valueOf: function () { return this.value }, plus: function (t) { return t = new a.Number(t), new a.Number(this + t, this.unit || t.unit) }, minus: function (t) { return t = new a.Number(t), new a.Number(this - t, this.unit || t.unit) }, times: function (t) { return t = new a.Number(t), new a.Number(this * t, this.unit || t.unit) }, divide: function (t) { return t = new a.Number(t), new a.Number(this / t, this.unit || t.unit) }, to: function (t) { var e = new a.Number(this); return "string" == typeof t && (e.unit = t), e }, morph: function (t) { return this.destination = new a.Number(t), t.relative && (this.destination.value += this.value), this }, at: function (t) { return this.destination ? new a.Number(this.destination).minus(this).times(t).plus(this) : this } } }), a.Element = a.invent({ create: function (t) { this._stroke = a.defaults.attrs.stroke, this._event = null, this.dom = {}, (this.node = t) && (this.type = t.nodeName, this.node.instance = this, this._stroke = t.getAttribute("stroke") || this._stroke) }, extend: { x: function (t) { return this.attr("x", t) }, y: function (t) { return this.attr("y", t) }, cx: function (t) { return null == t ? this.x() + this.width() / 2 : this.x(t - this.width() / 2) }, cy: function (t) { return null == t ? this.y() + this.height() / 2 : this.y(t - this.height() / 2) }, move: function (t, e) { return this.x(t).y(e) }, center: function (t, e) { return this.cx(t).cy(e) }, width: function (t) { return this.attr("width", t) }, height: function (t) { return this.attr("height", t) }, size: function (t, e) { var i = u(this, t, e); return this.width(new a.Number(i.width)).height(new a.Number(i.height)) }, clone: function (t) { this.writeDataToDom(); var e = x(this.node.cloneNode(!0)); return t ? t.add(e) : this.after(e), e }, remove: function () { return this.parent() && this.parent().removeElement(this), this }, replace: function (t) { return this.after(t).remove(), t }, addTo: function (t) { return t.put(this) }, putIn: function (t) { return t.add(this) }, id: function (t) { return this.attr("id", t) }, show: function () { return this.style("display", "") }, hide: function () { return this.style("display", "none") }, visible: function () { return "none" != this.style("display") }, toString: function () { return this.attr("id") }, classes: function () { var t = this.attr("class"); return null == t ? [] : t.trim().split(a.regex.delimiter) }, hasClass: function (t) { return -1 != this.classes().indexOf(t) }, addClass: function (t) { if (!this.hasClass(t)) { var e = this.classes(); e.push(t), this.attr("class", e.join(" ")) } return this }, removeClass: function (t) { return this.hasClass(t) && this.attr("class", this.classes().filter((function (e) { return e != t })).join(" ")), this }, toggleClass: function (t) { return this.hasClass(t) ? this.removeClass(t) : this.addClass(t) }, reference: function (t) { return a.get(this.attr(t)) }, parent: function (e) { var i = this; if (!i.node.parentNode) return null; if (i = a.adopt(i.node.parentNode), !e) return i; for (; i && i.node instanceof t.SVGElement;) { if ("string" == typeof e ? i.matches(e) : i instanceof e) return i; if (!i.node.parentNode || "#document" == i.node.parentNode.nodeName) return null; i = a.adopt(i.node.parentNode) } }, doc: function () { return this instanceof a.Doc ? this : this.parent(a.Doc) }, parents: function (t) { var e = [], i = this; do { if (!(i = i.parent(t)) || !i.node) break; e.push(i) } while (i.parent); return e }, matches: function (t) { return function (t, e) { return (t.matches || t.matchesSelector || t.msMatchesSelector || t.mozMatchesSelector || t.webkitMatchesSelector || t.oMatchesSelector).call(t, e) }(this.node, t) }, native: function () { return this.node }, svg: function (t) { var i = e.createElementNS("http://www.w3.org/2000/svg", "svg"); if (!(t && this instanceof a.Parent)) return i.appendChild(t = e.createElementNS("http://www.w3.org/2000/svg", "svg")), this.writeDataToDom(), t.appendChild(this.node.cloneNode(!0)), i.innerHTML.replace(/^/, "").replace(/<\/svg>$/, ""); i.innerHTML = "" + t.replace(/\n/, "").replace(/<([\w:-]+)([^<]+?)\/>/g, "<$1$2>") + ""; for (var s = 0, r = i.firstChild.childNodes.length; s < r; s++)this.node.appendChild(i.firstChild.firstChild); return this }, writeDataToDom: function () { return (this.each || this.lines) && (this.each ? this : this.lines()).each((function () { this.writeDataToDom() })), this.node.removeAttribute("svgjs:data"), Object.keys(this.dom).length && this.node.setAttribute("svgjs:data", JSON.stringify(this.dom)), this }, setData: function (t) { return this.dom = t, this }, is: function (t) { return function (t, e) { return t instanceof e }(this, t) } } }), a.easing = { "-": function (t) { return t }, "<>": function (t) { return -Math.cos(t * Math.PI) / 2 + .5 }, ">": function (t) { return Math.sin(t * Math.PI / 2) }, "<": function (t) { return 1 - Math.cos(t * Math.PI / 2) } }, a.morph = function (t) { return function (e, i) { return new a.MorphObj(e, i).at(t) } }, a.Situation = a.invent({ create: function (t) { this.init = !1, this.reversed = !1, this.reversing = !1, this.duration = new a.Number(t.duration).valueOf(), this.delay = new a.Number(t.delay).valueOf(), this.start = +new Date + this.delay, this.finish = this.start + this.duration, this.ease = t.ease, this.loop = 0, this.loops = !1, this.animations = {}, this.attrs = {}, this.styles = {}, this.transforms = [], this.once = {} } }), a.FX = a.invent({ create: function (t) { this._target = t, this.situations = [], this.active = !1, this.situation = null, this.paused = !1, this.lastPos = 0, this.pos = 0, this.absPos = 0, this._speed = 1 }, extend: { animate: function (t, e, s) { "object" === i(t) && (e = t.ease, s = t.delay, t = t.duration); var r = new a.Situation({ duration: t || 1e3, delay: s || 0, ease: a.easing[e || "-"] || e }); return this.queue(r), this }, target: function (t) { return t && t instanceof a.Element ? (this._target = t, this) : this._target }, timeToAbsPos: function (t) { return (t - this.situation.start) / (this.situation.duration / this._speed) }, absPosToTime: function (t) { return this.situation.duration / this._speed * t + this.situation.start }, startAnimFrame: function () { this.stopAnimFrame(), this.animationFrame = t.requestAnimationFrame(function () { this.step() }.bind(this)) }, stopAnimFrame: function () { t.cancelAnimationFrame(this.animationFrame) }, start: function () { return !this.active && this.situation && (this.active = !0, this.startCurrent()), this }, startCurrent: function () { return this.situation.start = +new Date + this.situation.delay / this._speed, this.situation.finish = this.situation.start + this.situation.duration / this._speed, this.initAnimations().step() }, queue: function (t) { return ("function" == typeof t || t instanceof a.Situation) && this.situations.push(t), this.situation || (this.situation = this.situations.shift()), this }, dequeue: function () { return this.stop(), this.situation = this.situations.shift(), this.situation && (this.situation instanceof a.Situation ? this.start() : this.situation.call(this)), this }, initAnimations: function () { var t, e = this.situation; if (e.init) return this; for (var i in e.animations) { t = this.target()[i](), Array.isArray(t) || (t = [t]), Array.isArray(e.animations[i]) || (e.animations[i] = [e.animations[i]]); for (var s = t.length; s--;)e.animations[i][s] instanceof a.Number && (t[s] = new a.Number(t[s])), e.animations[i][s] = t[s].morph(e.animations[i][s]) } for (var i in e.attrs) e.attrs[i] = new a.MorphObj(this.target().attr(i), e.attrs[i]); for (var i in e.styles) e.styles[i] = new a.MorphObj(this.target().style(i), e.styles[i]); return e.initialTransformation = this.target().matrixify(), e.init = !0, this }, clearQueue: function () { return this.situations = [], this }, clearCurrent: function () { return this.situation = null, this }, stop: function (t, e) { var i = this.active; return this.active = !1, e && this.clearQueue(), t && this.situation && (!i && this.startCurrent(), this.atEnd()), this.stopAnimFrame(), this.clearCurrent() }, after: function (t) { var e = this.last(); return this.target().on("finished.fx", (function i(a) { a.detail.situation == e && (t.call(this, e), this.off("finished.fx", i)) })), this._callStart() }, during: function (t) { var e = this.last(), i = function (i) { i.detail.situation == e && t.call(this, i.detail.pos, a.morph(i.detail.pos), i.detail.eased, e) }; return this.target().off("during.fx", i).on("during.fx", i), this.after((function () { this.off("during.fx", i) })), this._callStart() }, afterAll: function (t) { var e = function e(i) { t.call(this), this.off("allfinished.fx", e) }; return this.target().off("allfinished.fx", e).on("allfinished.fx", e), this._callStart() }, last: function () { return this.situations.length ? this.situations[this.situations.length - 1] : this.situation }, add: function (t, e, i) { return this.last()[i || "animations"][t] = e, this._callStart() }, step: function (t) { var e, i, a; t || (this.absPos = this.timeToAbsPos(+new Date)), !1 !== this.situation.loops ? (e = Math.max(this.absPos, 0), i = Math.floor(e), !0 === this.situation.loops || i < this.situation.loops ? (this.pos = e - i, a = this.situation.loop, this.situation.loop = i) : (this.absPos = this.situation.loops, this.pos = 1, a = this.situation.loop - 1, this.situation.loop = this.situation.loops), this.situation.reversing && (this.situation.reversed = this.situation.reversed != Boolean((this.situation.loop - a) % 2))) : (this.absPos = Math.min(this.absPos, 1), this.pos = this.absPos), this.pos < 0 && (this.pos = 0), this.situation.reversed && (this.pos = 1 - this.pos); var s = this.situation.ease(this.pos); for (var r in this.situation.once) r > this.lastPos && r <= s && (this.situation.once[r].call(this.target(), this.pos, s), delete this.situation.once[r]); return this.active && this.target().fire("during", { pos: this.pos, eased: s, fx: this, situation: this.situation }), this.situation ? (this.eachAt(), 1 == this.pos && !this.situation.reversed || this.situation.reversed && 0 == this.pos ? (this.stopAnimFrame(), this.target().fire("finished", { fx: this, situation: this.situation }), this.situations.length || (this.target().fire("allfinished"), this.situations.length || (this.target().off(".fx"), this.active = !1)), this.active ? this.dequeue() : this.clearCurrent()) : !this.paused && this.active && this.startAnimFrame(), this.lastPos = s, this) : this }, eachAt: function () { var t, e = this, i = this.target(), s = this.situation; for (var r in s.animations) t = [].concat(s.animations[r]).map((function (t) { return "string" != typeof t && t.at ? t.at(s.ease(e.pos), e.pos) : t })), i[r].apply(i, t); for (var r in s.attrs) t = [r].concat(s.attrs[r]).map((function (t) { return "string" != typeof t && t.at ? t.at(s.ease(e.pos), e.pos) : t })), i.attr.apply(i, t); for (var r in s.styles) t = [r].concat(s.styles[r]).map((function (t) { return "string" != typeof t && t.at ? t.at(s.ease(e.pos), e.pos) : t })), i.style.apply(i, t); if (s.transforms.length) { t = s.initialTransformation, r = 0; for (var o = s.transforms.length; r < o; r++) { var n = s.transforms[r]; n instanceof a.Matrix ? t = n.relative ? t.multiply((new a.Matrix).morph(n).at(s.ease(this.pos))) : t.morph(n).at(s.ease(this.pos)) : (n.relative || n.undo(t.extract()), t = t.multiply(n.at(s.ease(this.pos)))) } i.matrix(t) } return this }, once: function (t, e, i) { var a = this.last(); return i || (t = a.ease(t)), a.once[t] = e, this }, _callStart: function () { return setTimeout(function () { this.start() }.bind(this), 0), this } }, parent: a.Element, construct: { animate: function (t, e, i) { return (this.fx || (this.fx = new a.FX(this))).animate(t, e, i) }, delay: function (t) { return (this.fx || (this.fx = new a.FX(this))).delay(t) }, stop: function (t, e) { return this.fx && this.fx.stop(t, e), this }, finish: function () { return this.fx && this.fx.finish(), this } } }), a.MorphObj = a.invent({ create: function (t, e) { return a.Color.isColor(e) ? new a.Color(t).morph(e) : a.regex.delimiter.test(t) ? a.regex.pathLetters.test(t) ? new a.PathArray(t).morph(e) : new a.Array(t).morph(e) : a.regex.numberAndUnit.test(e) ? new a.Number(t).morph(e) : (this.value = t, void (this.destination = e)) }, extend: { at: function (t, e) { return e < 1 ? this.value : this.destination }, valueOf: function () { return this.value } } }), a.extend(a.FX, { attr: function (t, e, a) { if ("object" === i(t)) for (var s in t) this.attr(s, t[s]); else this.add(t, e, "attrs"); return this }, plot: function (t, e, i, a) { return 4 == arguments.length ? this.plot([t, e, i, a]) : this.add("plot", new (this.target().morphArray)(t)) } }), a.Box = a.invent({ create: function (t, e, s, r) { if (!("object" !== i(t) || t instanceof a.Element)) return a.Box.call(this, null != t.left ? t.left : t.x, null != t.top ? t.top : t.y, t.width, t.height); var o; 4 == arguments.length && (this.x = t, this.y = e, this.width = s, this.height = r), null == (o = this).x && (o.x = 0, o.y = 0, o.width = 0, o.height = 0), o.w = o.width, o.h = o.height, o.x2 = o.x + o.width, o.y2 = o.y + o.height, o.cx = o.x + o.width / 2, o.cy = o.y + o.height / 2 } }), a.BBox = a.invent({ create: function (t) { if (a.Box.apply(this, [].slice.call(arguments)), t instanceof a.Element) { var i; try { if (!e.documentElement.contains) { for (var s = t.node; s.parentNode;)s = s.parentNode; if (s != e) throw new Error("Element not in the dom") } i = t.node.getBBox() } catch (e) { if (t instanceof a.Shape) { a.parser.draw || a.prepare(); var r = t.clone(a.parser.draw.instance).show(); r && r.node && "function" == typeof r.node.getBBox && (i = r.node.getBBox()), r && "function" == typeof r.remove && r.remove() } else i = { x: t.node.clientLeft, y: t.node.clientTop, width: t.node.clientWidth, height: t.node.clientHeight } } a.Box.call(this, i) } }, inherit: a.Box, parent: a.Element, construct: { bbox: function () { return new a.BBox(this) } } }), a.BBox.prototype.constructor = a.BBox, a.Matrix = a.invent({ create: function (t) { var e = f([1, 0, 0, 1, 0, 0]); t = null === t ? e : t instanceof a.Element ? t.matrixify() : "string" == typeof t ? f(t.split(a.regex.delimiter).map(parseFloat)) : 6 == arguments.length ? f([].slice.call(arguments)) : Array.isArray(t) ? f(t) : t && "object" === i(t) ? t : e; for (var s = v.length - 1; s >= 0; --s)this[v[s]] = null != t[v[s]] ? t[v[s]] : e[v[s]] }, extend: { extract: function () { var t = p(this, 0, 1); p(this, 1, 0); var e = 180 / Math.PI * Math.atan2(t.y, t.x) - 90; return { x: this.e, y: this.f, transformedX: (this.e * Math.cos(e * Math.PI / 180) + this.f * Math.sin(e * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b), transformedY: (this.f * Math.cos(e * Math.PI / 180) + this.e * Math.sin(-e * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d), rotation: e, a: this.a, b: this.b, c: this.c, d: this.d, e: this.e, f: this.f, matrix: new a.Matrix(this) } }, clone: function () { return new a.Matrix(this) }, morph: function (t) { return this.destination = new a.Matrix(t), this }, multiply: function (t) { return new a.Matrix(this.native().multiply(function (t) { return t instanceof a.Matrix || (t = new a.Matrix(t)), t }(t).native())) }, inverse: function () { return new a.Matrix(this.native().inverse()) }, translate: function (t, e) { return new a.Matrix(this.native().translate(t || 0, e || 0)) }, native: function () { for (var t = a.parser.native.createSVGMatrix(), e = v.length - 1; e >= 0; e--)t[v[e]] = this[v[e]]; return t }, toString: function () { return "matrix(" + b(this.a) + "," + b(this.b) + "," + b(this.c) + "," + b(this.d) + "," + b(this.e) + "," + b(this.f) + ")" } }, parent: a.Element, construct: { ctm: function () { return new a.Matrix(this.node.getCTM()) }, screenCTM: function () { if (this instanceof a.Nested) { var t = this.rect(1, 1), e = t.node.getScreenCTM(); return t.remove(), new a.Matrix(e) } return new a.Matrix(this.node.getScreenCTM()) } } }), a.Point = a.invent({ create: function (t, e) { var a; a = Array.isArray(t) ? { x: t[0], y: t[1] } : "object" === i(t) ? { x: t.x, y: t.y } : null != t ? { x: t, y: null != e ? e : t } : { x: 0, y: 0 }, this.x = a.x, this.y = a.y }, extend: { clone: function () { return new a.Point(this) }, morph: function (t, e) { return this.destination = new a.Point(t, e), this } } }), a.extend(a.Element, { point: function (t, e) { return new a.Point(t, e).transform(this.screenCTM().inverse()) } }), a.extend(a.Element, { attr: function (t, e, s) { if (null == t) { for (t = {}, s = (e = this.node.attributes).length - 1; s >= 0; s--)t[e[s].nodeName] = a.regex.isNumber.test(e[s].nodeValue) ? parseFloat(e[s].nodeValue) : e[s].nodeValue; return t } if ("object" === i(t)) for (var r in t) this.attr(r, t[r]); else if (null === e) this.node.removeAttribute(t); else { if (null == e) return null == (e = this.node.getAttribute(t)) ? a.defaults.attrs[t] : a.regex.isNumber.test(e) ? parseFloat(e) : e; "stroke-width" == t ? this.attr("stroke", parseFloat(e) > 0 ? this._stroke : null) : "stroke" == t && (this._stroke = e), "fill" != t && "stroke" != t || (a.regex.isImage.test(e) && (e = this.doc().defs().image(e, 0, 0)), e instanceof a.Image && (e = this.doc().defs().pattern(0, 0, (function () { this.add(e) })))), "number" == typeof e ? e = new a.Number(e) : a.Color.isColor(e) ? e = new a.Color(e) : Array.isArray(e) && (e = new a.Array(e)), "leading" == t ? this.leading && this.leading(e) : "string" == typeof s ? this.node.setAttributeNS(s, t, e.toString()) : this.node.setAttribute(t, e.toString()), !this.rebuild || "font-size" != t && "x" != t || this.rebuild(t, e) } return this } }), a.extend(a.Element, { transform: function (t, e) { var s; return "object" !== i(t) ? (s = new a.Matrix(this).extract(), "string" == typeof t ? s[t] : s) : (s = new a.Matrix(this), e = !!e || !!t.relative, null != t.a && (s = e ? s.multiply(new a.Matrix(t)) : new a.Matrix(t)), this.attr("transform", s)) } }), a.extend(a.Element, { untransform: function () { return this.attr("transform", null) }, matrixify: function () { return (this.attr("transform") || "").split(a.regex.transforms).slice(0, -1).map((function (t) { var e = t.trim().split("("); return [e[0], e[1].split(a.regex.delimiter).map((function (t) { return parseFloat(t) }))] })).reduce((function (t, e) { return "matrix" == e[0] ? t.multiply(f(e[1])) : t[e[0]].apply(t, e[1]) }), new a.Matrix) }, toParent: function (t) { if (this == t) return this; var e = this.screenCTM(), i = t.screenCTM().inverse(); return this.addTo(t).untransform().transform(i.multiply(e)), this }, toDoc: function () { return this.toParent(this.doc()) } }), a.Transformation = a.invent({ create: function (t, e) { if (arguments.length > 1 && "boolean" != typeof e) return this.constructor.call(this, [].slice.call(arguments)); if (Array.isArray(t)) for (var a = 0, s = this.arguments.length; a < s; ++a)this[this.arguments[a]] = t[a]; else if (t && "object" === i(t)) for (a = 0, s = this.arguments.length; a < s; ++a)this[this.arguments[a]] = t[this.arguments[a]]; this.inversed = !1, !0 === e && (this.inversed = !0) } }), a.Translate = a.invent({ parent: a.Matrix, inherit: a.Transformation, create: function (t, e) { this.constructor.apply(this, [].slice.call(arguments)) }, extend: { arguments: ["transformedX", "transformedY"], method: "translate" } }), a.extend(a.Element, { style: function (t, e) { if (0 == arguments.length) return this.node.style.cssText || ""; if (arguments.length < 2) if ("object" === i(t)) for (var s in t) this.style(s, t[s]); else { if (!a.regex.isCss.test(t)) return this.node.style[c(t)]; for (t = t.split(/\s*;\s*/).filter((function (t) { return !!t })).map((function (t) { return t.split(/\s*:\s*/) })); e = t.pop();)this.style(e[0], e[1]) } else this.node.style[c(t)] = null === e || a.regex.isBlank.test(e) ? "" : e; return this } }), a.Parent = a.invent({ create: function (t) { this.constructor.call(this, t) }, inherit: a.Element, extend: { children: function () { return a.utils.map(a.utils.filterSVGElements(this.node.childNodes), (function (t) { return a.adopt(t) })) }, add: function (t, e) { return null == e ? this.node.appendChild(t.node) : t.node != this.node.childNodes[e] && this.node.insertBefore(t.node, this.node.childNodes[e]), this }, put: function (t, e) { return this.add(t, e), t }, has: function (t) { return this.index(t) >= 0 }, index: function (t) { return [].slice.call(this.node.childNodes).indexOf(t.node) }, get: function (t) { return a.adopt(this.node.childNodes[t]) }, first: function () { return this.get(0) }, last: function () { return this.get(this.node.childNodes.length - 1) }, each: function (t, e) { for (var i = this.children(), s = 0, r = i.length; s < r; s++)i[s] instanceof a.Element && t.apply(i[s], [s, i]), e && i[s] instanceof a.Container && i[s].each(t, e); return this }, removeElement: function (t) { return this.node.removeChild(t.node), this }, clear: function () { for (; this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild); return delete this._defs, this }, defs: function () { return this.doc().defs() } } }), a.extend(a.Parent, { ungroup: function (t, e) { return 0 === e || this instanceof a.Defs || this.node == a.parser.draw || (t = t || (this instanceof a.Doc ? this : this.parent(a.Parent)), e = e || 1 / 0, this.each((function () { return this instanceof a.Defs ? this : this instanceof a.Parent ? this.ungroup(t, e - 1) : this.toParent(t) })), this.node.firstChild || this.remove()), this }, flatten: function (t, e) { return this.ungroup(t, e) } }), a.Container = a.invent({ create: function (t) { this.constructor.call(this, t) }, inherit: a.Parent }), a.ViewBox = a.invent({ parent: a.Container, construct: {} }), ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "touchstart", "touchmove", "touchleave", "touchend", "touchcancel"].forEach((function (t) { a.Element.prototype[t] = function (e) { return a.on(this.node, t, e), this } })), a.listeners = [], a.handlerMap = [], a.listenerId = 0, a.on = function (t, e, i, s, r) { var o = i.bind(s || t.instance || t), n = (a.handlerMap.indexOf(t) + 1 || a.handlerMap.push(t)) - 1, l = e.split(".")[0], h = e.split(".")[1] || "*"; a.listeners[n] = a.listeners[n] || {}, a.listeners[n][l] = a.listeners[n][l] || {}, a.listeners[n][l][h] = a.listeners[n][l][h] || {}, i._svgjsListenerId || (i._svgjsListenerId = ++a.listenerId), a.listeners[n][l][h][i._svgjsListenerId] = o, t.addEventListener(l, o, r || { passive: !1 }) }, a.off = function (t, e, i) { var s = a.handlerMap.indexOf(t), r = e && e.split(".")[0], o = e && e.split(".")[1], n = ""; if (-1 != s) if (i) { if ("function" == typeof i && (i = i._svgjsListenerId), !i) return; a.listeners[s][r] && a.listeners[s][r][o || "*"] && (t.removeEventListener(r, a.listeners[s][r][o || "*"][i], !1), delete a.listeners[s][r][o || "*"][i]) } else if (o && r) { if (a.listeners[s][r] && a.listeners[s][r][o]) { for (var l in a.listeners[s][r][o]) a.off(t, [r, o].join("."), l); delete a.listeners[s][r][o] } } else if (o) for (var h in a.listeners[s]) for (var n in a.listeners[s][h]) o === n && a.off(t, [h, o].join(".")); else if (r) { if (a.listeners[s][r]) { for (var n in a.listeners[s][r]) a.off(t, [r, n].join(".")); delete a.listeners[s][r] } } else { for (var h in a.listeners[s]) a.off(t, h); delete a.listeners[s], delete a.handlerMap[s] } }, a.extend(a.Element, { on: function (t, e, i, s) { return a.on(this.node, t, e, i, s), this }, off: function (t, e) { return a.off(this.node, t, e), this }, fire: function (e, i) { return e instanceof t.Event ? this.node.dispatchEvent(e) : this.node.dispatchEvent(e = new a.CustomEvent(e, { detail: i, cancelable: !0 })), this._event = e, this }, event: function () { return this._event } }), a.Defs = a.invent({ create: "defs", inherit: a.Container }), a.G = a.invent({ create: "g", inherit: a.Container, extend: { x: function (t) { return null == t ? this.transform("x") : this.transform({ x: t - this.x() }, !0) } }, construct: { group: function () { return this.put(new a.G) } } }), a.Doc = a.invent({ create: function (t) { t && ("svg" == (t = "string" == typeof t ? e.getElementById(t) : t).nodeName ? this.constructor.call(this, t) : (this.constructor.call(this, a.create("svg")), t.appendChild(this.node), this.size("100%", "100%")), this.namespace().defs()) }, inherit: a.Container, extend: { namespace: function () { return this.attr({ xmlns: a.ns, version: "1.1" }).attr("xmlns:xlink", a.xlink, a.xmlns).attr("xmlns:svgjs", a.svgjs, a.xmlns) }, defs: function () { var t; return this._defs || ((t = this.node.getElementsByTagName("defs")[0]) ? this._defs = a.adopt(t) : this._defs = new a.Defs, this.node.appendChild(this._defs.node)), this._defs }, parent: function () { return this.node.parentNode && "#document" != this.node.parentNode.nodeName ? this.node.parentNode : null }, remove: function () { return this.parent() && this.parent().removeChild(this.node), this }, clear: function () { for (; this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild); return delete this._defs, a.parser.draw && !a.parser.draw.parentNode && this.node.appendChild(a.parser.draw), this }, clone: function (t) { this.writeDataToDom(); var e = this.node, i = x(e.cloneNode(!0)); return t ? (t.node || t).appendChild(i.node) : e.parentNode.insertBefore(i.node, e.nextSibling), i } } }), a.extend(a.Element, {}), a.Gradient = a.invent({ create: function (t) { this.constructor.call(this, a.create(t + "Gradient")), this.type = t }, inherit: a.Container, extend: { at: function (t, e, i) { return this.put(new a.Stop).update(t, e, i) }, update: function (t) { return this.clear(), "function" == typeof t && t.call(this, this), this }, fill: function () { return "url(#" + this.id() + ")" }, toString: function () { return this.fill() }, attr: function (t, e, i) { return "transform" == t && (t = "gradientTransform"), a.Container.prototype.attr.call(this, t, e, i) } }, construct: { gradient: function (t, e) { return this.defs().gradient(t, e) } } }), a.extend(a.Gradient, a.FX, { from: function (t, e) { return "radial" == (this._target || this).type ? this.attr({ fx: new a.Number(t), fy: new a.Number(e) }) : this.attr({ x1: new a.Number(t), y1: new a.Number(e) }) }, to: function (t, e) { return "radial" == (this._target || this).type ? this.attr({ cx: new a.Number(t), cy: new a.Number(e) }) : this.attr({ x2: new a.Number(t), y2: new a.Number(e) }) } }), a.extend(a.Defs, { gradient: function (t, e) { return this.put(new a.Gradient(t)).update(e) } }), a.Stop = a.invent({ create: "stop", inherit: a.Element, extend: { update: function (t) { return ("number" == typeof t || t instanceof a.Number) && (t = { offset: arguments[0], color: arguments[1], opacity: arguments[2] }), null != t.opacity && this.attr("stop-opacity", t.opacity), null != t.color && this.attr("stop-color", t.color), null != t.offset && this.attr("offset", new a.Number(t.offset)), this } } }), a.Pattern = a.invent({ create: "pattern", inherit: a.Container, extend: { fill: function () { return "url(#" + this.id() + ")" }, update: function (t) { return this.clear(), "function" == typeof t && t.call(this, this), this }, toString: function () { return this.fill() }, attr: function (t, e, i) { return "transform" == t && (t = "patternTransform"), a.Container.prototype.attr.call(this, t, e, i) } }, construct: { pattern: function (t, e, i) { return this.defs().pattern(t, e, i) } } }), a.extend(a.Defs, { pattern: function (t, e, i) { return this.put(new a.Pattern).update(i).attr({ x: 0, y: 0, width: t, height: e, patternUnits: "userSpaceOnUse" }) } }), a.Shape = a.invent({ create: function (t) { this.constructor.call(this, t) }, inherit: a.Element }), a.Symbol = a.invent({ create: "symbol", inherit: a.Container, construct: { symbol: function () { return this.put(new a.Symbol) } } }), a.Use = a.invent({ create: "use", inherit: a.Shape, extend: { element: function (t, e) { return this.attr("href", (e || "") + "#" + t, a.xlink) } }, construct: { use: function (t, e) { return this.put(new a.Use).element(t, e) } } }), a.Rect = a.invent({ create: "rect", inherit: a.Shape, construct: { rect: function (t, e) { return this.put(new a.Rect).size(t, e) } } }), a.Circle = a.invent({ create: "circle", inherit: a.Shape, construct: { circle: function (t) { return this.put(new a.Circle).rx(new a.Number(t).divide(2)).move(0, 0) } } }), a.extend(a.Circle, a.FX, { rx: function (t) { return this.attr("r", t) }, ry: function (t) { return this.rx(t) } }), a.Ellipse = a.invent({ create: "ellipse", inherit: a.Shape, construct: { ellipse: function (t, e) { return this.put(new a.Ellipse).size(t, e).move(0, 0) } } }), a.extend(a.Ellipse, a.Rect, a.FX, { rx: function (t) { return this.attr("rx", t) }, ry: function (t) { return this.attr("ry", t) } }), a.extend(a.Circle, a.Ellipse, { x: function (t) { return null == t ? this.cx() - this.rx() : this.cx(t + this.rx()) }, y: function (t) { return null == t ? this.cy() - this.ry() : this.cy(t + this.ry()) }, cx: function (t) { return null == t ? this.attr("cx") : this.attr("cx", t) }, cy: function (t) { return null == t ? this.attr("cy") : this.attr("cy", t) }, width: function (t) { return null == t ? 2 * this.rx() : this.rx(new a.Number(t).divide(2)) }, height: function (t) { return null == t ? 2 * this.ry() : this.ry(new a.Number(t).divide(2)) }, size: function (t, e) { var i = u(this, t, e); return this.rx(new a.Number(i.width).divide(2)).ry(new a.Number(i.height).divide(2)) } }), a.Line = a.invent({ create: "line", inherit: a.Shape, extend: { array: function () { return new a.PointArray([[this.attr("x1"), this.attr("y1")], [this.attr("x2"), this.attr("y2")]]) }, plot: function (t, e, i, s) { return null == t ? this.array() : (t = void 0 !== e ? { x1: t, y1: e, x2: i, y2: s } : new a.PointArray(t).toLine(), this.attr(t)) }, move: function (t, e) { return this.attr(this.array().move(t, e).toLine()) }, size: function (t, e) { var i = u(this, t, e); return this.attr(this.array().size(i.width, i.height).toLine()) } }, construct: { line: function (t, e, i, s) { return a.Line.prototype.plot.apply(this.put(new a.Line), null != t ? [t, e, i, s] : [0, 0, 0, 0]) } } }), a.Polyline = a.invent({ create: "polyline", inherit: a.Shape, construct: { polyline: function (t) { return this.put(new a.Polyline).plot(t || new a.PointArray) } } }), a.Polygon = a.invent({ create: "polygon", inherit: a.Shape, construct: { polygon: function (t) { return this.put(new a.Polygon).plot(t || new a.PointArray) } } }), a.extend(a.Polyline, a.Polygon, { array: function () { return this._array || (this._array = new a.PointArray(this.attr("points"))) }, plot: function (t) { return null == t ? this.array() : this.clear().attr("points", "string" == typeof t ? t : this._array = new a.PointArray(t)) }, clear: function () { return delete this._array, this }, move: function (t, e) { return this.attr("points", this.array().move(t, e)) }, size: function (t, e) { var i = u(this, t, e); return this.attr("points", this.array().size(i.width, i.height)) } }), a.extend(a.Line, a.Polyline, a.Polygon, { morphArray: a.PointArray, x: function (t) { return null == t ? this.bbox().x : this.move(t, this.bbox().y) }, y: function (t) { return null == t ? this.bbox().y : this.move(this.bbox().x, t) }, width: function (t) { var e = this.bbox(); return null == t ? e.width : this.size(t, e.height) }, height: function (t) { var e = this.bbox(); return null == t ? e.height : this.size(e.width, t) } }), a.Path = a.invent({ create: "path", inherit: a.Shape, extend: { morphArray: a.PathArray, array: function () { return this._array || (this._array = new a.PathArray(this.attr("d"))) }, plot: function (t) { return null == t ? this.array() : this.clear().attr("d", "string" == typeof t ? t : this._array = new a.PathArray(t)) }, clear: function () { return delete this._array, this } }, construct: { path: function (t) { return this.put(new a.Path).plot(t || new a.PathArray) } } }), a.Image = a.invent({ create: "image", inherit: a.Shape, extend: { load: function (e) { if (!e) return this; var i = this, s = new t.Image; return a.on(s, "load", (function () { a.off(s); var t = i.parent(a.Pattern); null !== t && (0 == i.width() && 0 == i.height() && i.size(s.width, s.height), t && 0 == t.width() && 0 == t.height() && t.size(i.width(), i.height()), "function" == typeof i._loaded && i._loaded.call(i, { width: s.width, height: s.height, ratio: s.width / s.height, url: e })) })), a.on(s, "error", (function (t) { a.off(s), "function" == typeof i._error && i._error.call(i, t) })), this.attr("href", s.src = this.src = e, a.xlink) }, loaded: function (t) { return this._loaded = t, this }, error: function (t) { return this._error = t, this } }, construct: { image: function (t, e, i) { return this.put(new a.Image).load(t).size(e || 0, i || e || 0) } } }), a.Text = a.invent({ create: function () { this.constructor.call(this, a.create("text")), this.dom.leading = new a.Number(1.3), this._rebuild = !0, this._build = !1, this.attr("font-family", a.defaults.attrs["font-family"]) }, inherit: a.Shape, extend: { x: function (t) { return null == t ? this.attr("x") : this.attr("x", t) }, text: function (t) { if (void 0 === t) { t = ""; for (var e = this.node.childNodes, i = 0, s = e.length; i < s; ++i)0 != i && 3 != e[i].nodeType && 1 == a.adopt(e[i]).dom.newLined && (t += "\n"), t += e[i].textContent; return t } if (this.clear().build(!0), "function" == typeof t) t.call(this, this); else { i = 0; for (var r = (t = t.split("\n")).length; i < r; i++)this.tspan(t[i]).newLine() } return this.build(!1).rebuild() }, size: function (t) { return this.attr("font-size", t).rebuild() }, leading: function (t) { return null == t ? this.dom.leading : (this.dom.leading = new a.Number(t), this.rebuild()) }, lines: function () { var t = (this.textPath && this.textPath() || this).node, e = a.utils.map(a.utils.filterSVGElements(t.childNodes), (function (t) { return a.adopt(t) })); return new a.Set(e) }, rebuild: function (t) { if ("boolean" == typeof t && (this._rebuild = t), this._rebuild) { var e = this, i = 0, s = this.dom.leading * new a.Number(this.attr("font-size")); this.lines().each((function () { this.dom.newLined && (e.textPath() || this.attr("x", e.attr("x")), "\n" == this.text() ? i += s : (this.attr("dy", s + i), i = 0)) })), this.fire("rebuild") } return this }, build: function (t) { return this._build = !!t, this }, setData: function (t) { return this.dom = t, this.dom.leading = new a.Number(t.leading || 1.3), this } }, construct: { text: function (t) { return this.put(new a.Text).text(t) }, plain: function (t) { return this.put(new a.Text).plain(t) } } }), a.Tspan = a.invent({ create: "tspan", inherit: a.Shape, extend: { text: function (t) { return null == t ? this.node.textContent + (this.dom.newLined ? "\n" : "") : ("function" == typeof t ? t.call(this, this) : this.plain(t), this) }, dx: function (t) { return this.attr("dx", t) }, dy: function (t) { return this.attr("dy", t) }, newLine: function () { var t = this.parent(a.Text); return this.dom.newLined = !0, this.dy(t.dom.leading * t.attr("font-size")).attr("x", t.x()) } } }), a.extend(a.Text, a.Tspan, { plain: function (t) { return !1 === this._build && this.clear(), this.node.appendChild(e.createTextNode(t)), this }, tspan: function (t) { var e = (this.textPath && this.textPath() || this).node, i = new a.Tspan; return !1 === this._build && this.clear(), e.appendChild(i.node), i.text(t) }, clear: function () { for (var t = (this.textPath && this.textPath() || this).node; t.hasChildNodes();)t.removeChild(t.lastChild); return this }, length: function () { return this.node.getComputedTextLength() } }), a.TextPath = a.invent({ create: "textPath", inherit: a.Parent, parent: a.Text, construct: { morphArray: a.PathArray, array: function () { var t = this.track(); return t ? t.array() : null }, plot: function (t) { var e = this.track(), i = null; return e && (i = e.plot(t)), null == t ? i : this }, track: function () { var t = this.textPath(); if (t) return t.reference("href") }, textPath: function () { if (this.node.firstChild && "textPath" == this.node.firstChild.nodeName) return a.adopt(this.node.firstChild) } } }), a.Nested = a.invent({ create: function () { this.constructor.call(this, a.create("svg")), this.style("overflow", "visible") }, inherit: a.Container, construct: { nested: function () { return this.put(new a.Nested) } } }); var l = { stroke: ["color", "width", "opacity", "linecap", "linejoin", "miterlimit", "dasharray", "dashoffset"], fill: ["color", "opacity", "rule"], prefix: function (t, e) { return "color" == e ? t : t + "-" + e } }; function h(t, e, i, s) { return i + s.replace(a.regex.dots, " .") } function c(t) { return t.toLowerCase().replace(/-(.)/g, (function (t, e) { return e.toUpperCase() })) } function d(t) { return t.charAt(0).toUpperCase() + t.slice(1) } function g(t) { var e = t.toString(16); return 1 == e.length ? "0" + e : e } function u(t, e, i) { if (null == e || null == i) { var a = t.bbox(); null == e ? e = a.width / a.height * i : null == i && (i = a.height / a.width * e) } return { width: e, height: i } } function p(t, e, i) { return { x: e * t.a + i * t.c + 0, y: e * t.b + i * t.d + 0 } } function f(t) { return { a: t[0], b: t[1], c: t[2], d: t[3], e: t[4], f: t[5] } } function x(e) { for (var i = e.childNodes.length - 1; i >= 0; i--)e.childNodes[i] instanceof t.SVGElement && x(e.childNodes[i]); return a.adopt(e).id(a.eid(e.nodeName)) } function b(t) { return Math.abs(t) > 1e-37 ? t : 0 } ["fill", "stroke"].forEach((function (t) { var e = {}; e[t] = function (e) { if (void 0 === e) return this; if ("string" == typeof e || a.Color.isRgb(e) || e && "function" == typeof e.fill) this.attr(t, e); else for (var i = l[t].length - 1; i >= 0; i--)null != e[l[t][i]] && this.attr(l.prefix(t, l[t][i]), e[l[t][i]]); return this }, a.extend(a.Element, a.FX, e) })), a.extend(a.Element, a.FX, { translate: function (t, e) { return this.transform({ x: t, y: e }) }, matrix: function (t) { return this.attr("transform", new a.Matrix(6 == arguments.length ? [].slice.call(arguments) : t)) }, opacity: function (t) { return this.attr("opacity", t) }, dx: function (t) { return this.x(new a.Number(t).plus(this instanceof a.FX ? 0 : this.x()), !0) }, dy: function (t) { return this.y(new a.Number(t).plus(this instanceof a.FX ? 0 : this.y()), !0) } }), a.extend(a.Path, { length: function () { return this.node.getTotalLength() }, pointAt: function (t) { return this.node.getPointAtLength(t) } }), a.Set = a.invent({ create: function (t) { Array.isArray(t) ? this.members = t : this.clear() }, extend: { add: function () { for (var t = [].slice.call(arguments), e = 0, i = t.length; e < i; e++)this.members.push(t[e]); return this }, remove: function (t) { var e = this.index(t); return e > -1 && this.members.splice(e, 1), this }, each: function (t) { for (var e = 0, i = this.members.length; e < i; e++)t.apply(this.members[e], [e, this.members]); return this }, clear: function () { return this.members = [], this }, length: function () { return this.members.length }, has: function (t) { return this.index(t) >= 0 }, index: function (t) { return this.members.indexOf(t) }, get: function (t) { return this.members[t] }, first: function () { return this.get(0) }, last: function () { return this.get(this.members.length - 1) }, valueOf: function () { return this.members } }, construct: { set: function (t) { return new a.Set(t) } } }), a.FX.Set = a.invent({ create: function (t) { this.set = t } }), a.Set.inherit = function () { var t = []; for (var e in a.Shape.prototype) "function" == typeof a.Shape.prototype[e] && "function" != typeof a.Set.prototype[e] && t.push(e); for (var e in t.forEach((function (t) { a.Set.prototype[t] = function () { for (var e = 0, i = this.members.length; e < i; e++)this.members[e] && "function" == typeof this.members[e][t] && this.members[e][t].apply(this.members[e], arguments); return "animate" == t ? this.fx || (this.fx = new a.FX.Set(this)) : this } })), t = [], a.FX.prototype) "function" == typeof a.FX.prototype[e] && "function" != typeof a.FX.Set.prototype[e] && t.push(e); t.forEach((function (t) { a.FX.Set.prototype[t] = function () { for (var e = 0, i = this.set.members.length; e < i; e++)this.set.members[e].fx[t].apply(this.set.members[e].fx, arguments); return this } })) }, a.extend(a.Element, {}), a.extend(a.Element, { remember: function (t, e) { if ("object" === i(arguments[0])) for (var a in t) this.remember(a, t[a]); else { if (1 == arguments.length) return this.memory()[t]; this.memory()[t] = e } return this }, forget: function () { if (0 == arguments.length) this._memory = {}; else for (var t = arguments.length - 1; t >= 0; t--)delete this.memory()[arguments[t]]; return this }, memory: function () { return this._memory || (this._memory = {}) } }), a.get = function (t) { var i = e.getElementById(function (t) { var e = (t || "").toString().match(a.regex.reference); if (e) return e[1] }(t) || t); return a.adopt(i) }, a.select = function (t, i) { return new a.Set(a.utils.map((i || e).querySelectorAll(t), (function (t) { return a.adopt(t) }))) }, a.extend(a.Parent, { select: function (t) { return a.select(t, this.node) } }); var v = "abcdef".split(""); if ("function" != typeof t.CustomEvent) { var m = function (t, i) { i = i || { bubbles: !1, cancelable: !1, detail: void 0 }; var a = e.createEvent("CustomEvent"); return a.initCustomEvent(t, i.bubbles, i.cancelable, i.detail), a }; m.prototype = t.Event.prototype, a.CustomEvent = m } else a.CustomEvent = t.CustomEvent; return a }, "function" == typeof define && define.amd ? define((function () { return Ht(Rt, Rt.document) })) : "object" === ("undefined" == typeof exports ? "undefined" : i(exports)) && "undefined" != typeof module ? module.exports = Rt.document ? Ht(Rt, Rt.document) : function (t) { return Ht(t, t.document) } : Rt.SVG = Ht(Rt, Rt.document), /*! svg.filter.js - v2.0.2 - 2016-02-24 * https://github.com/wout/svg.filter.js * Copyright (c) 2016 Wout Fierens; Licensed MIT */ function () { SVG.Filter = SVG.invent({ create: "filter", inherit: SVG.Parent, extend: { source: "SourceGraphic", sourceAlpha: "SourceAlpha", background: "BackgroundImage", backgroundAlpha: "BackgroundAlpha", fill: "FillPaint", stroke: "StrokePaint", autoSetIn: !0, put: function (t, e) { return this.add(t, e), !t.attr("in") && this.autoSetIn && t.attr("in", this.source), t.attr("result") || t.attr("result", t), t }, blend: function (t, e, i) { return this.put(new SVG.BlendEffect(t, e, i)) }, colorMatrix: function (t, e) { return this.put(new SVG.ColorMatrixEffect(t, e)) }, convolveMatrix: function (t) { return this.put(new SVG.ConvolveMatrixEffect(t)) }, componentTransfer: function (t) { return this.put(new SVG.ComponentTransferEffect(t)) }, composite: function (t, e, i) { return this.put(new SVG.CompositeEffect(t, e, i)) }, flood: function (t, e) { return this.put(new SVG.FloodEffect(t, e)) }, offset: function (t, e) { return this.put(new SVG.OffsetEffect(t, e)) }, image: function (t) { return this.put(new SVG.ImageEffect(t)) }, merge: function () { var t = [void 0]; for (var e in arguments) t.push(arguments[e]); return this.put(new (SVG.MergeEffect.bind.apply(SVG.MergeEffect, t))) }, gaussianBlur: function (t, e) { return this.put(new SVG.GaussianBlurEffect(t, e)) }, morphology: function (t, e) { return this.put(new SVG.MorphologyEffect(t, e)) }, diffuseLighting: function (t, e, i) { return this.put(new SVG.DiffuseLightingEffect(t, e, i)) }, displacementMap: function (t, e, i, a, s) { return this.put(new SVG.DisplacementMapEffect(t, e, i, a, s)) }, specularLighting: function (t, e, i, a) { return this.put(new SVG.SpecularLightingEffect(t, e, i, a)) }, tile: function () { return this.put(new SVG.TileEffect) }, turbulence: function (t, e, i, a, s) { return this.put(new SVG.TurbulenceEffect(t, e, i, a, s)) }, toString: function () { return "url(#" + this.attr("id") + ")" } } }), SVG.extend(SVG.Defs, { filter: function (t) { var e = this.put(new SVG.Filter); return "function" == typeof t && t.call(e, e), e } }), SVG.extend(SVG.Container, { filter: function (t) { return this.defs().filter(t) } }), SVG.extend(SVG.Element, SVG.G, SVG.Nested, { filter: function (t) { return this.filterer = t instanceof SVG.Element ? t : this.doc().filter(t), this.doc() && this.filterer.doc() !== this.doc() && this.doc().defs().add(this.filterer), this.attr("filter", this.filterer), this.filterer }, unfilter: function (t) { return this.filterer && !0 === t && this.filterer.remove(), delete this.filterer, this.attr("filter", null) } }), SVG.Effect = SVG.invent({ create: function () { this.constructor.call(this) }, inherit: SVG.Element, extend: { in: function (t) { return null == t ? this.parent() && this.parent().select('[result="' + this.attr("in") + '"]').get(0) || this.attr("in") : this.attr("in", t) }, result: function (t) { return null == t ? this.attr("result") : this.attr("result", t) }, toString: function () { return this.result() } } }), SVG.ParentEffect = SVG.invent({ create: function () { this.constructor.call(this) }, inherit: SVG.Parent, extend: { in: function (t) { return null == t ? this.parent() && this.parent().select('[result="' + this.attr("in") + '"]').get(0) || this.attr("in") : this.attr("in", t) }, result: function (t) { return null == t ? this.attr("result") : this.attr("result", t) }, toString: function () { return this.result() } } }); var t = { blend: function (t, e) { return this.parent() && this.parent().blend(this, t, e) }, colorMatrix: function (t, e) { return this.parent() && this.parent().colorMatrix(t, e).in(this) }, convolveMatrix: function (t) { return this.parent() && this.parent().convolveMatrix(t).in(this) }, componentTransfer: function (t) { return this.parent() && this.parent().componentTransfer(t).in(this) }, composite: function (t, e) { return this.parent() && this.parent().composite(this, t, e) }, flood: function (t, e) { return this.parent() && this.parent().flood(t, e) }, offset: function (t, e) { return this.parent() && this.parent().offset(t, e).in(this) }, image: function (t) { return this.parent() && this.parent().image(t) }, merge: function () { return this.parent() && this.parent().merge.apply(this.parent(), [this].concat(arguments)) }, gaussianBlur: function (t, e) { return this.parent() && this.parent().gaussianBlur(t, e).in(this) }, morphology: function (t, e) { return this.parent() && this.parent().morphology(t, e).in(this) }, diffuseLighting: function (t, e, i) { return this.parent() && this.parent().diffuseLighting(t, e, i).in(this) }, displacementMap: function (t, e, i, a) { return this.parent() && this.parent().displacementMap(this, t, e, i, a) }, specularLighting: function (t, e, i, a) { return this.parent() && this.parent().specularLighting(t, e, i, a).in(this) }, tile: function () { return this.parent() && this.parent().tile().in(this) }, turbulence: function (t, e, i, a, s) { return this.parent() && this.parent().turbulence(t, e, i, a, s).in(this) } }; SVG.extend(SVG.Effect, t), SVG.extend(SVG.ParentEffect, t), SVG.ChildEffect = SVG.invent({ create: function () { this.constructor.call(this) }, inherit: SVG.Element, extend: { in: function (t) { this.attr("in", t) } } }); var e = { blend: function (t, e, i) { this.attr({ in: t, in2: e, mode: i || "normal" }) }, colorMatrix: function (t, e) { "matrix" == t && (e = s(e)), this.attr({ type: t, values: void 0 === e ? null : e }) }, convolveMatrix: function (t) { t = s(t), this.attr({ order: Math.sqrt(t.split(" ").length), kernelMatrix: t }) }, composite: function (t, e, i) { this.attr({ in: t, in2: e, operator: i }) }, flood: function (t, e) { this.attr("flood-color", t), null != e && this.attr("flood-opacity", e) }, offset: function (t, e) { this.attr({ dx: t, dy: e }) }, image: function (t) { this.attr("href", t, SVG.xlink) }, displacementMap: function (t, e, i, a, s) { this.attr({ in: t, in2: e, scale: i, xChannelSelector: a, yChannelSelector: s }) }, gaussianBlur: function (t, e) { null != t || null != e ? this.attr("stdDeviation", function (t) { if (!Array.isArray(t)) return t; for (var e = 0, i = t.length, a = []; e < i; e++)a.push(t[e]); return a.join(" ") }(Array.prototype.slice.call(arguments))) : this.attr("stdDeviation", "0 0") }, morphology: function (t, e) { this.attr({ operator: t, radius: e }) }, tile: function () { }, turbulence: function (t, e, i, a, s) { this.attr({ numOctaves: e, seed: i, stitchTiles: a, baseFrequency: t, type: s }) } }, i = { merge: function () { var t; if (arguments[0] instanceof SVG.Set) { var e = this; arguments[0].each((function (t) { this instanceof SVG.MergeNode ? e.put(this) : (this instanceof SVG.Effect || this instanceof SVG.ParentEffect) && e.put(new SVG.MergeNode(this)) })) } else { t = Array.isArray(arguments[0]) ? arguments[0] : arguments; for (var i = 0; i < t.length; i++)t[i] instanceof SVG.MergeNode ? this.put(t[i]) : this.put(new SVG.MergeNode(t[i])) } }, componentTransfer: function (t) { if (this.rgb = new SVG.Set, ["r", "g", "b", "a"].forEach(function (t) { this[t] = new (SVG["Func" + t.toUpperCase()])("identity"), this.rgb.add(this[t]), this.node.appendChild(this[t].node) }.bind(this)), t) for (var e in t.rgb && (["r", "g", "b"].forEach(function (e) { this[e].attr(t.rgb) }.bind(this)), delete t.rgb), t) this[e].attr(t[e]) }, diffuseLighting: function (t, e, i) { this.attr({ surfaceScale: t, diffuseConstant: e, kernelUnitLength: i }) }, specularLighting: function (t, e, i, a) { this.attr({ surfaceScale: t, diffuseConstant: e, specularExponent: i, kernelUnitLength: a }) } }, a = { distantLight: function (t, e) { this.attr({ azimuth: t, elevation: e }) }, pointLight: function (t, e, i) { this.attr({ x: t, y: e, z: i }) }, spotLight: function (t, e, i, a, s, r) { this.attr({ x: t, y: e, z: i, pointsAtX: a, pointsAtY: s, pointsAtZ: r }) }, mergeNode: function (t) { this.attr("in", t) } }; function s(t) { return Array.isArray(t) && (t = new SVG.Array(t)), t.toString().replace(/^\s+/, "").replace(/\s+$/, "").replace(/\s+/g, " ") } function r() { var t = function () { }; for (var e in "function" == typeof arguments[arguments.length - 1] && (t = arguments[arguments.length - 1], Array.prototype.splice.call(arguments, arguments.length - 1, 1)), arguments) for (var i in arguments[e]) t(arguments[e][i], i, arguments[e]) } ["r", "g", "b", "a"].forEach((function (t) { a["Func" + t.toUpperCase()] = function (t) { switch (this.attr("type", t), t) { case "table": this.attr("tableValues", arguments[1]); break; case "linear": this.attr("slope", arguments[1]), this.attr("intercept", arguments[2]); break; case "gamma": this.attr("amplitude", arguments[1]), this.attr("exponent", arguments[2]), this.attr("offset", arguments[2]) } } })), r(e, (function (t, e) { var i = e.charAt(0).toUpperCase() + e.slice(1); SVG[i + "Effect"] = SVG.invent({ create: function () { this.constructor.call(this, SVG.create("fe" + i)), t.apply(this, arguments), this.result(this.attr("id") + "Out") }, inherit: SVG.Effect, extend: {} }) })), r(i, (function (t, e) { var i = e.charAt(0).toUpperCase() + e.slice(1); SVG[i + "Effect"] = SVG.invent({ create: function () { this.constructor.call(this, SVG.create("fe" + i)), t.apply(this, arguments), this.result(this.attr("id") + "Out") }, inherit: SVG.ParentEffect, extend: {} }) })), r(a, (function (t, e) { var i = e.charAt(0).toUpperCase() + e.slice(1); SVG[i] = SVG.invent({ create: function () { this.constructor.call(this, SVG.create("fe" + i)), t.apply(this, arguments) }, inherit: SVG.ChildEffect, extend: {} }) })), SVG.extend(SVG.MergeEffect, { in: function (t) { return t instanceof SVG.MergeNode ? this.add(t, 0) : this.add(new SVG.MergeNode(t), 0), this } }), SVG.extend(SVG.CompositeEffect, SVG.BlendEffect, SVG.DisplacementMapEffect, { in2: function (t) { return null == t ? this.parent() && this.parent().select('[result="' + this.attr("in2") + '"]').get(0) || this.attr("in2") : this.attr("in2", t) } }), SVG.filter = { sepiatone: [.343, .669, .119, 0, 0, .249, .626, .13, 0, 0, .172, .334, .111, 0, 0, 0, 0, 0, 1, 0] } }.call(void 0), function () { function t(t, s, r, o, n, l, h) { for (var c = t.slice(s, r || h), d = o.slice(n, l || h), g = 0, u = { pos: [0, 0], start: [0, 0] }, p = { pos: [0, 0], start: [0, 0] }; ;) { if (c[g] = e.call(u, c[g]), d[g] = e.call(p, d[g]), c[g][0] != d[g][0] || "M" == c[g][0] || "A" == c[g][0] && (c[g][4] != d[g][4] || c[g][5] != d[g][5]) ? (Array.prototype.splice.apply(c, [g, 1].concat(a.call(u, c[g]))), Array.prototype.splice.apply(d, [g, 1].concat(a.call(p, d[g])))) : (c[g] = i.call(u, c[g]), d[g] = i.call(p, d[g])), ++g == c.length && g == d.length) break; g == c.length && c.push(["C", u.pos[0], u.pos[1], u.pos[0], u.pos[1], u.pos[0], u.pos[1]]), g == d.length && d.push(["C", p.pos[0], p.pos[1], p.pos[0], p.pos[1], p.pos[0], p.pos[1]]) } return { start: c, dest: d } } function e(t) { switch (t[0]) { case "z": case "Z": t[0] = "L", t[1] = this.start[0], t[2] = this.start[1]; break; case "H": t[0] = "L", t[2] = this.pos[1]; break; case "V": t[0] = "L", t[2] = t[1], t[1] = this.pos[0]; break; case "T": t[0] = "Q", t[3] = t[1], t[4] = t[2], t[1] = this.reflection[1], t[2] = this.reflection[0]; break; case "S": t[0] = "C", t[6] = t[4], t[5] = t[3], t[4] = t[2], t[3] = t[1], t[2] = this.reflection[1], t[1] = this.reflection[0] }return t } function i(t) { var e = t.length; return this.pos = [t[e - 2], t[e - 1]], -1 != "SCQT".indexOf(t[0]) && (this.reflection = [2 * this.pos[0] - t[e - 4], 2 * this.pos[1] - t[e - 3]]), t } function a(t) { var e = [t]; switch (t[0]) { case "M": return this.pos = this.start = [t[1], t[2]], e; case "L": t[5] = t[3] = t[1], t[6] = t[4] = t[2], t[1] = this.pos[0], t[2] = this.pos[1]; break; case "Q": t[6] = t[4], t[5] = t[3], t[4] = 1 * t[4] / 3 + 2 * t[2] / 3, t[3] = 1 * t[3] / 3 + 2 * t[1] / 3, t[2] = 1 * this.pos[1] / 3 + 2 * t[2] / 3, t[1] = 1 * this.pos[0] / 3 + 2 * t[1] / 3; break; case "A": e = function (t, e) { var i, a, s, r, o, n, l, h, c, d, g, u, p, f, x, b, v, m, y, w, k, A, S, C, L, P, M = Math.abs(e[1]), I = Math.abs(e[2]), T = e[3] % 360, z = e[4], X = e[5], E = e[6], Y = e[7], F = new SVG.Point(t), R = new SVG.Point(E, Y), H = []; if (0 === M || 0 === I || F.x === R.x && F.y === R.y) return [["C", F.x, F.y, R.x, R.y, R.x, R.y]]; i = new SVG.Point((F.x - R.x) / 2, (F.y - R.y) / 2).transform((new SVG.Matrix).rotate(T)), (a = i.x * i.x / (M * M) + i.y * i.y / (I * I)) > 1 && (M *= a = Math.sqrt(a), I *= a); s = (new SVG.Matrix).rotate(T).scale(1 / M, 1 / I).rotate(-T), F = F.transform(s), R = R.transform(s), r = [R.x - F.x, R.y - F.y], n = r[0] * r[0] + r[1] * r[1], o = Math.sqrt(n), r[0] /= o, r[1] /= o, l = n < 4 ? Math.sqrt(1 - n / 4) : 0, z === X && (l *= -1); h = new SVG.Point((R.x + F.x) / 2 + l * -r[1], (R.y + F.y) / 2 + l * r[0]), c = new SVG.Point(F.x - h.x, F.y - h.y), d = new SVG.Point(R.x - h.x, R.y - h.y), g = Math.acos(c.x / Math.sqrt(c.x * c.x + c.y * c.y)), c.y < 0 && (g *= -1); u = Math.acos(d.x / Math.sqrt(d.x * d.x + d.y * d.y)), d.y < 0 && (u *= -1); X && g > u && (u += 2 * Math.PI); !X && g < u && (u -= 2 * Math.PI); for (f = Math.ceil(2 * Math.abs(g - u) / Math.PI), b = [], v = g, p = (u - g) / f, x = 4 * Math.tan(p / 4) / 3, k = 0; k <= f; k++)y = Math.cos(v), m = Math.sin(v), w = new SVG.Point(h.x + y, h.y + m), b[k] = [new SVG.Point(w.x + x * m, w.y - x * y), w, new SVG.Point(w.x - x * m, w.y + x * y)], v += p; for (b[0][0] = b[0][1].clone(), b[b.length - 1][2] = b[b.length - 1][1].clone(), s = (new SVG.Matrix).rotate(T).scale(M, I).rotate(-T), k = 0, A = b.length; k < A; k++)b[k][0] = b[k][0].transform(s), b[k][1] = b[k][1].transform(s), b[k][2] = b[k][2].transform(s); for (k = 1, A = b.length; k < A; k++)S = (w = b[k - 1][2]).x, C = w.y, L = (w = b[k][0]).x, P = w.y, E = (w = b[k][1]).x, Y = w.y, H.push(["C", S, C, L, P, E, Y]); return H }(this.pos, t), t = e[0] }return t[0] = "C", this.pos = [t[5], t[6]], this.reflection = [2 * t[5] - t[3], 2 * t[6] - t[4]], e } function s(t, e) { if (!1 === e) return !1; for (var i = e, a = t.length; i < a; ++i)if ("M" == t[i][0]) return i; return !1 } SVG.extend(SVG.PathArray, { morph: function (e) { for (var i = this.value, a = this.parse(e), r = 0, o = 0, n = !1, l = !1; !1 !== r || !1 !== o;) { var h; n = s(i, !1 !== r && r + 1), l = s(a, !1 !== o && o + 1), !1 === r && (r = 0 == (h = new SVG.PathArray(c.start).bbox()).height || 0 == h.width ? i.push(i[0]) - 1 : i.push(["M", h.x + h.width / 2, h.y + h.height / 2]) - 1), !1 === o && (o = 0 == (h = new SVG.PathArray(c.dest).bbox()).height || 0 == h.width ? a.push(a[0]) - 1 : a.push(["M", h.x + h.width / 2, h.y + h.height / 2]) - 1); var c = t(i, r, n, a, o, l); i = i.slice(0, r).concat(c.start, !1 === n ? [] : i.slice(n)), a = a.slice(0, o).concat(c.dest, !1 === l ? [] : a.slice(l)), r = !1 !== n && r + c.start.length, o = !1 !== l && o + c.dest.length } return this.value = i, this.destination = new SVG.PathArray, this.destination.value = a, this } }) }(), /*! svg.draggable.js - v2.2.2 - 2019-01-08 * https://github.com/svgdotjs/svg.draggable.js * Copyright (c) 2019 Wout Fierens; Licensed MIT */ function () { function t(t) { t.remember("_draggable", this), this.el = t } t.prototype.init = function (t, e) { var i = this; this.constraint = t, this.value = e, this.el.on("mousedown.drag", (function (t) { i.start(t) })), this.el.on("touchstart.drag", (function (t) { i.start(t) })) }, t.prototype.transformPoint = function (t, e) { var i = (t = t || window.event).changedTouches && t.changedTouches[0] || t; return this.p.x = i.clientX - (e || 0), this.p.y = i.clientY, this.p.matrixTransform(this.m) }, t.prototype.getBBox = function () { var t = this.el.bbox(); return this.el instanceof SVG.Nested && (t = this.el.rbox()), (this.el instanceof SVG.G || this.el instanceof SVG.Use || this.el instanceof SVG.Nested) && (t.x = this.el.x(), t.y = this.el.y()), t }, t.prototype.start = function (t) { if ("click" != t.type && "mousedown" != t.type && "mousemove" != t.type || 1 == (t.which || t.buttons)) { var e = this; if (this.el.fire("beforedrag", { event: t, handler: this }), !this.el.event().defaultPrevented) { t.preventDefault(), t.stopPropagation(), this.parent = this.parent || this.el.parent(SVG.Nested) || this.el.parent(SVG.Doc), this.p = this.parent.node.createSVGPoint(), this.m = this.el.node.getScreenCTM().inverse(); var i, a = this.getBBox(); if (this.el instanceof SVG.Text) switch (i = this.el.node.getComputedTextLength(), this.el.attr("text-anchor")) { case "middle": i /= 2; break; case "start": i = 0 }this.startPoints = { point: this.transformPoint(t, i), box: a, transform: this.el.transform() }, SVG.on(window, "mousemove.drag", (function (t) { e.drag(t) })), SVG.on(window, "touchmove.drag", (function (t) { e.drag(t) })), SVG.on(window, "mouseup.drag", (function (t) { e.end(t) })), SVG.on(window, "touchend.drag", (function (t) { e.end(t) })), this.el.fire("dragstart", { event: t, p: this.startPoints.point, m: this.m, handler: this }) } } }, t.prototype.drag = function (t) { var e = this.getBBox(), i = this.transformPoint(t), a = this.startPoints.box.x + i.x - this.startPoints.point.x, s = this.startPoints.box.y + i.y - this.startPoints.point.y, r = this.constraint, o = i.x - this.startPoints.point.x, n = i.y - this.startPoints.point.y; if (this.el.fire("dragmove", { event: t, p: i, m: this.m, handler: this }), this.el.event().defaultPrevented) return i; if ("function" == typeof r) { var l = r.call(this.el, a, s, this.m); "boolean" == typeof l && (l = { x: l, y: l }), !0 === l.x ? this.el.x(a) : !1 !== l.x && this.el.x(l.x), !0 === l.y ? this.el.y(s) : !1 !== l.y && this.el.y(l.y) } else "object" == typeof r && (null != r.minX && a < r.minX ? o = (a = r.minX) - this.startPoints.box.x : null != r.maxX && a > r.maxX - e.width && (o = (a = r.maxX - e.width) - this.startPoints.box.x), null != r.minY && s < r.minY ? n = (s = r.minY) - this.startPoints.box.y : null != r.maxY && s > r.maxY - e.height && (n = (s = r.maxY - e.height) - this.startPoints.box.y), null != r.snapToGrid && (a -= a % r.snapToGrid, s -= s % r.snapToGrid, o -= o % r.snapToGrid, n -= n % r.snapToGrid), this.el instanceof SVG.G ? this.el.matrix(this.startPoints.transform).transform({ x: o, y: n }, !0) : this.el.move(a, s)); return i }, t.prototype.end = function (t) { var e = this.drag(t); this.el.fire("dragend", { event: t, p: e, m: this.m, handler: this }), SVG.off(window, "mousemove.drag"), SVG.off(window, "touchmove.drag"), SVG.off(window, "mouseup.drag"), SVG.off(window, "touchend.drag") }, SVG.extend(SVG.Element, { draggable: function (e, i) { "function" != typeof e && "object" != typeof e || (i = e, e = !0); var a = this.remember("_draggable") || new t(this); return (e = void 0 === e || e) ? a.init(i || {}, e) : (this.off("mousedown.drag"), this.off("touchstart.drag")), this } }) }.call(void 0), function () { function t(t) { this.el = t, t.remember("_selectHandler", this), this.pointSelection = { isSelected: !1 }, this.rectSelection = { isSelected: !1 }, this.pointsList = { lt: [0, 0], rt: ["width", 0], rb: ["width", "height"], lb: [0, "height"], t: ["width", 0], r: ["width", "height"], b: ["width", "height"], l: [0, "height"] }, this.pointCoord = function (t, e, i) { var a = "string" != typeof t ? t : e[t]; return i ? a / 2 : a }, this.pointCoords = function (t, e) { var i = this.pointsList[t]; return { x: this.pointCoord(i[0], e, "t" === t || "b" === t), y: this.pointCoord(i[1], e, "r" === t || "l" === t) } } } t.prototype.init = function (t, e) { var i = this.el.bbox(); this.options = {}; var a = this.el.selectize.defaults.points; for (var s in this.el.selectize.defaults) this.options[s] = this.el.selectize.defaults[s], void 0 !== e[s] && (this.options[s] = e[s]); var r = ["points", "pointsExclude"]; for (var s in r) { var o = this.options[r[s]]; "string" == typeof o ? o = o.length > 0 ? o.split(/\s*,\s*/i) : [] : "boolean" == typeof o && "points" === r[s] && (o = o ? a : []), this.options[r[s]] = o } this.options.points = [a, this.options.points].reduce((function (t, e) { return t.filter((function (t) { return e.indexOf(t) > -1 })) })), this.options.points = [this.options.points, this.options.pointsExclude].reduce((function (t, e) { return t.filter((function (t) { return e.indexOf(t) < 0 })) })), this.parent = this.el.parent(), this.nested = this.nested || this.parent.group(), this.nested.matrix(new SVG.Matrix(this.el).translate(i.x, i.y)), this.options.deepSelect && -1 !== ["line", "polyline", "polygon"].indexOf(this.el.type) ? this.selectPoints(t) : this.selectRect(t), this.observe(), this.cleanup() }, t.prototype.selectPoints = function (t) { return this.pointSelection.isSelected = t, this.pointSelection.set || (this.pointSelection.set = this.parent.set(), this.drawPoints()), this }, t.prototype.getPointArray = function () { var t = this.el.bbox(); return this.el.array().valueOf().map((function (e) { return [e[0] - t.x, e[1] - t.y] })) }, t.prototype.drawPoints = function () { for (var t = this, e = this.getPointArray(), i = 0, a = e.length; i < a; ++i) { var s = function (e) { return function (i) { (i = i || window.event).preventDefault ? i.preventDefault() : i.returnValue = !1, i.stopPropagation(); var a = i.pageX || i.touches[0].pageX, s = i.pageY || i.touches[0].pageY; t.el.fire("point", { x: a, y: s, i: e, event: i }) } }(i), r = this.drawPoint(e[i][0], e[i][1]).addClass(this.options.classPoints).addClass(this.options.classPoints + "_point").on("touchstart", s).on("mousedown", s); this.pointSelection.set.add(r) } }, t.prototype.drawPoint = function (t, e) { var i = this.options.pointType; switch (i) { case "circle": return this.drawCircle(t, e); case "rect": return this.drawRect(t, e); default: if ("function" == typeof i) return i.call(this, t, e); throw new Error("Unknown " + i + " point type!") } }, t.prototype.drawCircle = function (t, e) { return this.nested.circle(this.options.pointSize).center(t, e) }, t.prototype.drawRect = function (t, e) { return this.nested.rect(this.options.pointSize, this.options.pointSize).center(t, e) }, t.prototype.updatePointSelection = function () { var t = this.getPointArray(); this.pointSelection.set.each((function (e) { this.cx() === t[e][0] && this.cy() === t[e][1] || this.center(t[e][0], t[e][1]) })) }, t.prototype.updateRectSelection = function () { var t = this, e = this.el.bbox(); if (this.rectSelection.set.get(0).attr({ width: e.width, height: e.height }), this.options.points.length && this.options.points.map((function (i, a) { var s = t.pointCoords(i, e); t.rectSelection.set.get(a + 1).center(s.x, s.y) })), this.options.rotationPoint) { var i = this.rectSelection.set.length(); this.rectSelection.set.get(i - 1).center(e.width / 2, 20) } }, t.prototype.selectRect = function (t) { var e = this, i = this.el.bbox(); function a(t) { return function (i) { (i = i || window.event).preventDefault ? i.preventDefault() : i.returnValue = !1, i.stopPropagation(); var a = i.pageX || i.touches[0].pageX, s = i.pageY || i.touches[0].pageY; e.el.fire(t, { x: a, y: s, event: i }) } } if (this.rectSelection.isSelected = t, this.rectSelection.set = this.rectSelection.set || this.parent.set(), this.rectSelection.set.get(0) || this.rectSelection.set.add(this.nested.rect(i.width, i.height).addClass(this.options.classRect)), this.options.points.length && this.rectSelection.set.length() < 2) { this.options.points.map((function (t, s) { var r = e.pointCoords(t, i), o = e.drawPoint(r.x, r.y).attr("class", e.options.classPoints + "_" + t).on("mousedown", a(t)).on("touchstart", a(t)); e.rectSelection.set.add(o) })), this.rectSelection.set.each((function () { this.addClass(e.options.classPoints) })) } if (this.options.rotationPoint && (this.options.points && !this.rectSelection.set.get(9) || !this.options.points && !this.rectSelection.set.get(1))) { var s = function (t) { (t = t || window.event).preventDefault ? t.preventDefault() : t.returnValue = !1, t.stopPropagation(); var i = t.pageX || t.touches[0].pageX, a = t.pageY || t.touches[0].pageY; e.el.fire("rot", { x: i, y: a, event: t }) }, r = this.drawPoint(i.width / 2, 20).attr("class", this.options.classPoints + "_rot").on("touchstart", s).on("mousedown", s); this.rectSelection.set.add(r) } }, t.prototype.handler = function () { var t = this.el.bbox(); this.nested.matrix(new SVG.Matrix(this.el).translate(t.x, t.y)), this.rectSelection.isSelected && this.updateRectSelection(), this.pointSelection.isSelected && this.updatePointSelection() }, t.prototype.observe = function () { var t = this; if (MutationObserver) if (this.rectSelection.isSelected || this.pointSelection.isSelected) this.observerInst = this.observerInst || new MutationObserver((function () { t.handler() })), this.observerInst.observe(this.el.node, { attributes: !0 }); else try { this.observerInst.disconnect(), delete this.observerInst } catch (t) { } else this.el.off("DOMAttrModified.select"), (this.rectSelection.isSelected || this.pointSelection.isSelected) && this.el.on("DOMAttrModified.select", (function () { t.handler() })) }, t.prototype.cleanup = function () { !this.rectSelection.isSelected && this.rectSelection.set && (this.rectSelection.set.each((function () { this.remove() })), this.rectSelection.set.clear(), delete this.rectSelection.set), !this.pointSelection.isSelected && this.pointSelection.set && (this.pointSelection.set.each((function () { this.remove() })), this.pointSelection.set.clear(), delete this.pointSelection.set), this.pointSelection.isSelected || this.rectSelection.isSelected || (this.nested.remove(), delete this.nested) }, SVG.extend(SVG.Element, { selectize: function (e, i) { return "object" == typeof e && (i = e, e = !0), (this.remember("_selectHandler") || new t(this)).init(void 0 === e || e, i || {}), this } }), SVG.Element.prototype.selectize.defaults = { points: ["lt", "rt", "rb", "lb", "t", "r", "b", "l"], pointsExclude: [], classRect: "svg_select_boundingRect", classPoints: "svg_select_points", pointSize: 7, rotationPoint: !0, deepSelect: !1, pointType: "circle" } }(), function () { (function () { function t(t) { t.remember("_resizeHandler", this), this.el = t, this.parameters = {}, this.lastUpdateCall = null, this.p = t.doc().node.createSVGPoint() } t.prototype.transformPoint = function (t, e, i) { return this.p.x = t - (this.offset.x - window.pageXOffset), this.p.y = e - (this.offset.y - window.pageYOffset), this.p.matrixTransform(i || this.m) }, t.prototype._extractPosition = function (t) { return { x: null != t.clientX ? t.clientX : t.touches[0].clientX, y: null != t.clientY ? t.clientY : t.touches[0].clientY } }, t.prototype.init = function (t) { var e = this; if (this.stop(), "stop" !== t) { for (var i in this.options = {}, this.el.resize.defaults) this.options[i] = this.el.resize.defaults[i], void 0 !== t[i] && (this.options[i] = t[i]); this.el.on("lt.resize", (function (t) { e.resize(t || window.event) })), this.el.on("rt.resize", (function (t) { e.resize(t || window.event) })), this.el.on("rb.resize", (function (t) { e.resize(t || window.event) })), this.el.on("lb.resize", (function (t) { e.resize(t || window.event) })), this.el.on("t.resize", (function (t) { e.resize(t || window.event) })), this.el.on("r.resize", (function (t) { e.resize(t || window.event) })), this.el.on("b.resize", (function (t) { e.resize(t || window.event) })), this.el.on("l.resize", (function (t) { e.resize(t || window.event) })), this.el.on("rot.resize", (function (t) { e.resize(t || window.event) })), this.el.on("point.resize", (function (t) { e.resize(t || window.event) })), this.update() } }, t.prototype.stop = function () { return this.el.off("lt.resize"), this.el.off("rt.resize"), this.el.off("rb.resize"), this.el.off("lb.resize"), this.el.off("t.resize"), this.el.off("r.resize"), this.el.off("b.resize"), this.el.off("l.resize"), this.el.off("rot.resize"), this.el.off("point.resize"), this }, t.prototype.resize = function (t) { var e = this; this.m = this.el.node.getScreenCTM().inverse(), this.offset = { x: window.pageXOffset, y: window.pageYOffset }; var i = this._extractPosition(t.detail.event); if (this.parameters = { type: this.el.type, p: this.transformPoint(i.x, i.y), x: t.detail.x, y: t.detail.y, box: this.el.bbox(), rotation: this.el.transform().rotation }, "text" === this.el.type && (this.parameters.fontSize = this.el.attr()["font-size"]), void 0 !== t.detail.i) { var a = this.el.array().valueOf(); this.parameters.i = t.detail.i, this.parameters.pointCoords = [a[t.detail.i][0], a[t.detail.i][1]] } switch (t.type) { case "lt": this.calc = function (t, e) { var i = this.snapToGrid(t, e); if (this.parameters.box.width - i[0] > 0 && this.parameters.box.height - i[1] > 0) { if ("text" === this.parameters.type) return this.el.move(this.parameters.box.x + i[0], this.parameters.box.y), void this.el.attr("font-size", this.parameters.fontSize - i[0]); i = this.checkAspectRatio(i), this.el.move(this.parameters.box.x + i[0], this.parameters.box.y + i[1]).size(this.parameters.box.width - i[0], this.parameters.box.height - i[1]) } }; break; case "rt": this.calc = function (t, e) { var i = this.snapToGrid(t, e, 2); if (this.parameters.box.width + i[0] > 0 && this.parameters.box.height - i[1] > 0) { if ("text" === this.parameters.type) return this.el.move(this.parameters.box.x - i[0], this.parameters.box.y), void this.el.attr("font-size", this.parameters.fontSize + i[0]); i = this.checkAspectRatio(i, !0), this.el.move(this.parameters.box.x, this.parameters.box.y + i[1]).size(this.parameters.box.width + i[0], this.parameters.box.height - i[1]) } }; break; case "rb": this.calc = function (t, e) { var i = this.snapToGrid(t, e, 0); if (this.parameters.box.width + i[0] > 0 && this.parameters.box.height + i[1] > 0) { if ("text" === this.parameters.type) return this.el.move(this.parameters.box.x - i[0], this.parameters.box.y), void this.el.attr("font-size", this.parameters.fontSize + i[0]); i = this.checkAspectRatio(i), this.el.move(this.parameters.box.x, this.parameters.box.y).size(this.parameters.box.width + i[0], this.parameters.box.height + i[1]) } }; break; case "lb": this.calc = function (t, e) { var i = this.snapToGrid(t, e, 1); if (this.parameters.box.width - i[0] > 0 && this.parameters.box.height + i[1] > 0) { if ("text" === this.parameters.type) return this.el.move(this.parameters.box.x + i[0], this.parameters.box.y), void this.el.attr("font-size", this.parameters.fontSize - i[0]); i = this.checkAspectRatio(i, !0), this.el.move(this.parameters.box.x + i[0], this.parameters.box.y).size(this.parameters.box.width - i[0], this.parameters.box.height + i[1]) } }; break; case "t": this.calc = function (t, e) { var i = this.snapToGrid(t, e, 2); if (this.parameters.box.height - i[1] > 0) { if ("text" === this.parameters.type) return; this.el.move(this.parameters.box.x, this.parameters.box.y + i[1]).height(this.parameters.box.height - i[1]) } }; break; case "r": this.calc = function (t, e) { var i = this.snapToGrid(t, e, 0); if (this.parameters.box.width + i[0] > 0) { if ("text" === this.parameters.type) return; this.el.move(this.parameters.box.x, this.parameters.box.y).width(this.parameters.box.width + i[0]) } }; break; case "b": this.calc = function (t, e) { var i = this.snapToGrid(t, e, 0); if (this.parameters.box.height + i[1] > 0) { if ("text" === this.parameters.type) return; this.el.move(this.parameters.box.x, this.parameters.box.y).height(this.parameters.box.height + i[1]) } }; break; case "l": this.calc = function (t, e) { var i = this.snapToGrid(t, e, 1); if (this.parameters.box.width - i[0] > 0) { if ("text" === this.parameters.type) return; this.el.move(this.parameters.box.x + i[0], this.parameters.box.y).width(this.parameters.box.width - i[0]) } }; break; case "rot": this.calc = function (t, e) { var i = t + this.parameters.p.x, a = e + this.parameters.p.y, s = Math.atan2(this.parameters.p.y - this.parameters.box.y - this.parameters.box.height / 2, this.parameters.p.x - this.parameters.box.x - this.parameters.box.width / 2), r = Math.atan2(a - this.parameters.box.y - this.parameters.box.height / 2, i - this.parameters.box.x - this.parameters.box.width / 2), o = this.parameters.rotation + 180 * (r - s) / Math.PI + this.options.snapToAngle / 2; this.el.center(this.parameters.box.cx, this.parameters.box.cy).rotate(o - o % this.options.snapToAngle, this.parameters.box.cx, this.parameters.box.cy) }; break; case "point": this.calc = function (t, e) { var i = this.snapToGrid(t, e, this.parameters.pointCoords[0], this.parameters.pointCoords[1]), a = this.el.array().valueOf(); a[this.parameters.i][0] = this.parameters.pointCoords[0] + i[0], a[this.parameters.i][1] = this.parameters.pointCoords[1] + i[1], this.el.plot(a) } }this.el.fire("resizestart", { dx: this.parameters.x, dy: this.parameters.y, event: t }), SVG.on(window, "touchmove.resize", (function (t) { e.update(t || window.event) })), SVG.on(window, "touchend.resize", (function () { e.done() })), SVG.on(window, "mousemove.resize", (function (t) { e.update(t || window.event) })), SVG.on(window, "mouseup.resize", (function () { e.done() })) }, t.prototype.update = function (t) { if (t) { var e = this._extractPosition(t), i = this.transformPoint(e.x, e.y), a = i.x - this.parameters.p.x, s = i.y - this.parameters.p.y; this.lastUpdateCall = [a, s], this.calc(a, s), this.el.fire("resizing", { dx: a, dy: s, event: t }) } else this.lastUpdateCall && this.calc(this.lastUpdateCall[0], this.lastUpdateCall[1]) }, t.prototype.done = function () { this.lastUpdateCall = null, SVG.off(window, "mousemove.resize"), SVG.off(window, "mouseup.resize"), SVG.off(window, "touchmove.resize"), SVG.off(window, "touchend.resize"), this.el.fire("resizedone") }, t.prototype.snapToGrid = function (t, e, i, a) { var s; return void 0 !== a ? s = [(i + t) % this.options.snapToGrid, (a + e) % this.options.snapToGrid] : (i = null == i ? 3 : i, s = [(this.parameters.box.x + t + (1 & i ? 0 : this.parameters.box.width)) % this.options.snapToGrid, (this.parameters.box.y + e + (2 & i ? 0 : this.parameters.box.height)) % this.options.snapToGrid]), t < 0 && (s[0] -= this.options.snapToGrid), e < 0 && (s[1] -= this.options.snapToGrid), t -= Math.abs(s[0]) < this.options.snapToGrid / 2 ? s[0] : s[0] - (t < 0 ? -this.options.snapToGrid : this.options.snapToGrid), e -= Math.abs(s[1]) < this.options.snapToGrid / 2 ? s[1] : s[1] - (e < 0 ? -this.options.snapToGrid : this.options.snapToGrid), this.constraintToBox(t, e, i, a) }, t.prototype.constraintToBox = function (t, e, i, a) { var s, r, o = this.options.constraint || {}; return void 0 !== a ? (s = i, r = a) : (s = this.parameters.box.x + (1 & i ? 0 : this.parameters.box.width), r = this.parameters.box.y + (2 & i ? 0 : this.parameters.box.height)), void 0 !== o.minX && s + t < o.minX && (t = o.minX - s), void 0 !== o.maxX && s + t > o.maxX && (t = o.maxX - s), void 0 !== o.minY && r + e < o.minY && (e = o.minY - r), void 0 !== o.maxY && r + e > o.maxY && (e = o.maxY - r), [t, e] }, t.prototype.checkAspectRatio = function (t, e) { if (!this.options.saveAspectRatio) return t; var i = t.slice(), a = this.parameters.box.width / this.parameters.box.height, s = this.parameters.box.width + t[0], r = this.parameters.box.height - t[1], o = s / r; return o < a ? (i[1] = s / a - this.parameters.box.height, e && (i[1] = -i[1])) : o > a && (i[0] = this.parameters.box.width - r * a, e && (i[0] = -i[0])), i }, SVG.extend(SVG.Element, { resize: function (e) { return (this.remember("_resizeHandler") || new t(this)).init(e || {}), this } }), SVG.Element.prototype.resize.defaults = { snapToAngle: .1, snapToGrid: 1, constraint: {}, saveAspectRatio: !1 } }).call(this) }(), void 0 === window.Apex && (window.Apex = {}); var Gt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "initModules", value: function () { this.ctx.publicMethods = ["updateOptions", "updateSeries", "appendData", "appendSeries", "isSeriesHidden", "toggleSeries", "showSeries", "hideSeries", "setLocale", "resetSeries", "zoomX", "toggleDataPointSelection", "dataURI", "exportToCSV", "addXaxisAnnotation", "addYaxisAnnotation", "addPointAnnotation", "clearAnnotations", "removeAnnotation", "paper", "destroy"], this.ctx.eventList = ["click", "mousedown", "mousemove", "mouseleave", "touchstart", "touchmove", "touchleave", "mouseup", "touchend"], this.ctx.animations = new b(this.ctx), this.ctx.axes = new J(this.ctx), this.ctx.core = new Wt(this.ctx.el, this.ctx), this.ctx.config = new Y({}), this.ctx.data = new B(this.ctx), this.ctx.grid = new j(this.ctx), this.ctx.graphics = new m(this.ctx), this.ctx.coreUtils = new y(this.ctx), this.ctx.crosshairs = new Q(this.ctx), this.ctx.events = new Z(this.ctx), this.ctx.exports = new G(this.ctx), this.ctx.localization = new $(this.ctx), this.ctx.options = new I, this.ctx.responsive = new K(this.ctx), this.ctx.series = new W(this.ctx), this.ctx.theme = new tt(this.ctx), this.ctx.formatters = new S(this.ctx), this.ctx.titleSubtitle = new et(this.ctx), this.ctx.legend = new lt(this.ctx), this.ctx.toolbar = new ht(this.ctx), this.ctx.tooltip = new bt(this.ctx), this.ctx.dimensions = new ot(this.ctx), this.ctx.updateHelpers = new Bt(this.ctx), this.ctx.zoomPanSelection = new ct(this.ctx), this.ctx.w.globals.tooltip = new bt(this.ctx) } }]), t }(), Vt = function () { function t(e) { a(this, t), this.ctx = e, this.w = e.w } return r(t, [{ key: "clear", value: function (t) { var e = t.isUpdating; this.ctx.zoomPanSelection && this.ctx.zoomPanSelection.destroy(), this.ctx.toolbar && this.ctx.toolbar.destroy(), this.ctx.animations = null, this.ctx.axes = null, this.ctx.annotations = null, this.ctx.core = null, this.ctx.data = null, this.ctx.grid = null, this.ctx.series = null, this.ctx.responsive = null, this.ctx.theme = null, this.ctx.formatters = null, this.ctx.titleSubtitle = null, this.ctx.legend = null, this.ctx.dimensions = null, this.ctx.options = null, this.ctx.crosshairs = null, this.ctx.zoomPanSelection = null, this.ctx.updateHelpers = null, this.ctx.toolbar = null, this.ctx.localization = null, this.ctx.w.globals.tooltip = null, this.clearDomElements({ isUpdating: e }) } }, { key: "killSVG", value: function (t) { t.each((function (t, e) { this.removeClass("*"), this.off(), this.stop() }), !0), t.ungroup(), t.clear() } }, { key: "clearDomElements", value: function (t) { var e = this, i = t.isUpdating, a = this.w.globals.dom.Paper.node; a.parentNode && a.parentNode.parentNode && !i && (a.parentNode.parentNode.style.minHeight = "unset"); var s = this.w.globals.dom.baseEl; s && this.ctx.eventList.forEach((function (t) { s.removeEventListener(t, e.ctx.events.documentEvent) })); var r = this.w.globals.dom; if (null !== this.ctx.el) for (; this.ctx.el.firstChild;)this.ctx.el.removeChild(this.ctx.el.firstChild); this.killSVG(r.Paper), r.Paper.remove(), r.elWrap = null, r.elGraphical = null, r.elLegendWrap = null, r.elLegendForeign = null, r.baseEl = null, r.elGridRect = null, r.elGridRectMask = null, r.elGridRectMarkerMask = null, r.elForecastMask = null, r.elNonForecastMask = null, r.elDefs = null } }]), t }(), jt = new WeakMap; var _t = function () { function t(e, i) { a(this, t), this.opts = i, this.ctx = this, this.w = new R(i).init(), this.el = e, this.w.globals.cuid = x.randomId(), this.w.globals.chartID = this.w.config.chart.id ? x.escapeString(this.w.config.chart.id) : this.w.globals.cuid, new Gt(this).initModules(), this.create = x.bind(this.create, this), this.windowResizeHandler = this._windowResizeHandler.bind(this), this.parentResizeHandler = this._parentResizeCallback.bind(this) } return r(t, [{ key: "render", value: function () { var t = this; return new Promise((function (e, i) { if (null !== t.el) { void 0 === Apex._chartInstances && (Apex._chartInstances = []), t.w.config.chart.id && Apex._chartInstances.push({ id: t.w.globals.chartID, group: t.w.config.chart.group, chart: t }), t.setLocale(t.w.config.chart.defaultLocale); var a = t.w.config.chart.events.beforeMount; "function" == typeof a && a(t, t.w), t.events.fireEvent("beforeMount", [t, t.w]), window.addEventListener("resize", t.windowResizeHandler), function (t, e) { var i = !1; if (t.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) { var a = t.getBoundingClientRect(); "none" !== t.style.display && 0 !== a.width || (i = !0) } var s = new ResizeObserver((function (a) { i && e.call(t, a), i = !0 })); t.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? Array.from(t.children).forEach((function (t) { return s.observe(t) })) : s.observe(t), jt.set(e, s) }(t.el.parentNode, t.parentResizeHandler); var s = t.el.getRootNode && t.el.getRootNode(), r = x.is("ShadowRoot", s), o = t.el.ownerDocument, n = r ? s.getElementById("apexcharts-css") : o.getElementById("apexcharts-css"); if (!n) { var l; (n = document.createElement("style")).id = "apexcharts-css", n.textContent = '@keyframes opaque {\n 0% {\n opacity: 0\n }\n\n to {\n opacity: 1\n }\n}\n\n@keyframes resizeanim {\n 0%,to {\n opacity: 0\n }\n}\n\n.apexcharts-canvas {\n position: relative;\n user-select: none\n}\n\n.apexcharts-canvas ::-webkit-scrollbar {\n -webkit-appearance: none;\n width: 6px\n}\n\n.apexcharts-canvas ::-webkit-scrollbar-thumb {\n border-radius: 4px;\n background-color: rgba(0,0,0,.5);\n box-shadow: 0 0 1px rgba(255,255,255,.5);\n -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5)\n}\n\n.apexcharts-inner {\n position: relative\n}\n\n.apexcharts-text tspan {\n font-family: inherit\n}\n\n.legend-mouseover-inactive {\n transition: .15s ease all;\n opacity: .2\n}\n\n.apexcharts-legend-text {\n padding-left: 15px;\n margin-left: -15px;\n}\n\n.apexcharts-series-collapsed {\n opacity: 0\n}\n\n.apexcharts-tooltip {\n border-radius: 5px;\n box-shadow: 2px 2px 6px -4px #999;\n cursor: default;\n font-size: 14px;\n left: 62px;\n opacity: 0;\n pointer-events: none;\n position: absolute;\n top: 20px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n white-space: nowrap;\n z-index: 12;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-theme-light {\n border: 1px solid #e3e3e3;\n background: rgba(255,255,255,.96)\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark {\n color: #fff;\n background: rgba(30,30,30,.8)\n}\n\n.apexcharts-tooltip * {\n font-family: inherit\n}\n\n.apexcharts-tooltip-title {\n padding: 6px;\n font-size: 15px;\n margin-bottom: 4px\n}\n\n.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title {\n background: #eceff1;\n border-bottom: 1px solid #ddd\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark .apexcharts-tooltip-title {\n background: rgba(0,0,0,.7);\n border-bottom: 1px solid #333\n}\n\n.apexcharts-tooltip-text-goals-value,.apexcharts-tooltip-text-y-value,.apexcharts-tooltip-text-z-value {\n display: inline-block;\n margin-left: 5px;\n font-weight: 600\n}\n\n.apexcharts-tooltip-text-goals-label:empty,.apexcharts-tooltip-text-goals-value:empty,.apexcharts-tooltip-text-y-label:empty,.apexcharts-tooltip-text-y-value:empty,.apexcharts-tooltip-text-z-value:empty,.apexcharts-tooltip-title:empty {\n display: none\n}\n\n.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n padding: 6px 0 5px\n}\n\n.apexcharts-tooltip-goals-group,.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n display: flex\n}\n\n.apexcharts-tooltip-text-goals-label:not(:empty),.apexcharts-tooltip-text-goals-value:not(:empty) {\n margin-top: -6px\n}\n\n.apexcharts-tooltip-marker {\n width: 12px;\n height: 12px;\n position: relative;\n top: 0;\n margin-right: 10px;\n border-radius: 50%\n}\n\n.apexcharts-tooltip-series-group {\n padding: 0 10px;\n display: none;\n text-align: left;\n justify-content: left;\n align-items: center\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {\n opacity: 1\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active,.apexcharts-tooltip-series-group:last-child {\n padding-bottom: 4px\n}\n\n.apexcharts-tooltip-series-group-hidden {\n opacity: 0;\n height: 0;\n line-height: 0;\n padding: 0!important\n}\n\n.apexcharts-tooltip-y-group {\n padding: 6px 0 5px\n}\n\n.apexcharts-custom-tooltip,.apexcharts-tooltip-box {\n padding: 4px 8px\n}\n\n.apexcharts-tooltip-boxPlot {\n display: flex;\n flex-direction: column-reverse\n}\n\n.apexcharts-tooltip-box>div {\n margin: 4px 0\n}\n\n.apexcharts-tooltip-box span.value {\n font-weight: 700\n}\n\n.apexcharts-tooltip-rangebar {\n padding: 5px 8px\n}\n\n.apexcharts-tooltip-rangebar .category {\n font-weight: 600;\n color: #777\n}\n\n.apexcharts-tooltip-rangebar .series-name {\n font-weight: 700;\n display: block;\n margin-bottom: 5px\n}\n\n.apexcharts-xaxistooltip,.apexcharts-yaxistooltip {\n opacity: 0;\n pointer-events: none;\n color: #373d3f;\n font-size: 13px;\n text-align: center;\n border-radius: 2px;\n position: absolute;\n z-index: 10;\n background: #eceff1;\n border: 1px solid #90a4ae\n}\n\n.apexcharts-xaxistooltip {\n padding: 9px 10px;\n transition: .15s ease all\n}\n\n.apexcharts-xaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-xaxistooltip:after,.apexcharts-xaxistooltip:before {\n left: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-xaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-left: -6px\n}\n\n.apexcharts-xaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-left: -7px\n}\n\n.apexcharts-xaxistooltip-bottom:after,.apexcharts-xaxistooltip-bottom:before {\n bottom: 100%\n}\n\n.apexcharts-xaxistooltip-top:after,.apexcharts-xaxistooltip-top:before {\n top: 100%\n}\n\n.apexcharts-xaxistooltip-bottom:after {\n border-bottom-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-bottom:before {\n border-bottom-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before {\n border-bottom-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip-top:after {\n border-top-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-top:before {\n border-top-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before {\n border-top-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-yaxistooltip {\n padding: 4px 10px\n}\n\n.apexcharts-yaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-yaxistooltip:after,.apexcharts-yaxistooltip:before {\n top: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-yaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-top: -6px\n}\n\n.apexcharts-yaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-top: -7px\n}\n\n.apexcharts-yaxistooltip-left:after,.apexcharts-yaxistooltip-left:before {\n left: 100%\n}\n\n.apexcharts-yaxistooltip-right:after,.apexcharts-yaxistooltip-right:before {\n right: 100%\n}\n\n.apexcharts-yaxistooltip-left:after {\n border-left-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-left:before {\n border-left-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before {\n border-left-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip-right:after {\n border-right-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-right:before {\n border-right-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before {\n border-right-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip.apexcharts-active {\n opacity: 1\n}\n\n.apexcharts-yaxistooltip-hidden {\n display: none\n}\n\n.apexcharts-xcrosshairs,.apexcharts-ycrosshairs {\n pointer-events: none;\n opacity: 0;\n transition: .15s ease all\n}\n\n.apexcharts-xcrosshairs.apexcharts-active,.apexcharts-ycrosshairs.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-ycrosshairs-hidden {\n opacity: 0\n}\n\n.apexcharts-selection-rect {\n cursor: move\n}\n\n.svg_select_boundingRect,.svg_select_points_rot {\n pointer-events: none;\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_boundingRect,.apexcharts-selection-rect+g .svg_select_points_rot {\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_points_l,.apexcharts-selection-rect+g .svg_select_points_r {\n cursor: ew-resize;\n opacity: 1;\n visibility: visible\n}\n\n.svg_select_points {\n fill: #efefef;\n stroke: #333;\n rx: 2\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-zoom {\n cursor: crosshair\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-pan {\n cursor: move\n}\n\n.apexcharts-menu-icon,.apexcharts-pan-icon,.apexcharts-reset-icon,.apexcharts-selection-icon,.apexcharts-toolbar-custom-icon,.apexcharts-zoom-icon,.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n cursor: pointer;\n width: 20px;\n height: 20px;\n line-height: 24px;\n color: #6e8192;\n text-align: center\n}\n\n.apexcharts-menu-icon svg,.apexcharts-reset-icon svg,.apexcharts-zoom-icon svg,.apexcharts-zoomin-icon svg,.apexcharts-zoomout-icon svg {\n fill: #6e8192\n}\n\n.apexcharts-selection-icon svg {\n fill: #444;\n transform: scale(.76)\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon svg,.apexcharts-theme-dark .apexcharts-pan-icon svg,.apexcharts-theme-dark .apexcharts-reset-icon svg,.apexcharts-theme-dark .apexcharts-selection-icon svg,.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,.apexcharts-theme-dark .apexcharts-zoom-icon svg,.apexcharts-theme-dark .apexcharts-zoomin-icon svg,.apexcharts-theme-dark .apexcharts-zoomout-icon svg {\n fill: #f3f4f5\n}\n\n.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg {\n fill: #008ffb\n}\n\n.apexcharts-theme-light .apexcharts-menu-icon:hover svg,.apexcharts-theme-light .apexcharts-reset-icon:hover svg,.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg {\n fill: #333\n}\n\n.apexcharts-menu-icon,.apexcharts-selection-icon {\n position: relative\n}\n\n.apexcharts-reset-icon {\n margin-left: 5px\n}\n\n.apexcharts-menu-icon,.apexcharts-reset-icon,.apexcharts-zoom-icon {\n transform: scale(.85)\n}\n\n.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n transform: scale(.7)\n}\n\n.apexcharts-zoomout-icon {\n margin-right: 3px\n}\n\n.apexcharts-pan-icon {\n transform: scale(.62);\n position: relative;\n left: 1px;\n top: 0\n}\n\n.apexcharts-pan-icon svg {\n fill: #fff;\n stroke: #6e8192;\n stroke-width: 2\n}\n\n.apexcharts-pan-icon.apexcharts-selected svg {\n stroke: #008ffb\n}\n\n.apexcharts-pan-icon:not(.apexcharts-selected):hover svg {\n stroke: #333\n}\n\n.apexcharts-toolbar {\n position: absolute;\n z-index: 11;\n max-width: 176px;\n text-align: right;\n border-radius: 3px;\n padding: 0 6px 2px;\n display: flex;\n justify-content: space-between;\n align-items: center\n}\n\n.apexcharts-menu {\n background: #fff;\n position: absolute;\n top: 100%;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 3px;\n right: 10px;\n opacity: 0;\n min-width: 110px;\n transition: .15s ease all;\n pointer-events: none\n}\n\n.apexcharts-menu.apexcharts-menu-open {\n opacity: 1;\n pointer-events: all;\n transition: .15s ease all\n}\n\n.apexcharts-menu-item {\n padding: 6px 7px;\n font-size: 12px;\n cursor: pointer\n}\n\n.apexcharts-theme-light .apexcharts-menu-item:hover {\n background: #eee\n}\n\n.apexcharts-theme-dark .apexcharts-menu {\n background: rgba(0,0,0,.7);\n color: #fff\n}\n\n@media screen and (min-width:768px) {\n .apexcharts-canvas:hover .apexcharts-toolbar {\n opacity: 1\n }\n}\n\n.apexcharts-canvas .apexcharts-element-hidden,.apexcharts-datalabel.apexcharts-element-hidden,.apexcharts-hide .apexcharts-series-points {\n display: none;\n}\n\n.apexcharts-hidden-element-shown {\n opacity: 1;\n transition: 0.25s ease all;\n}\n.apexcharts-datalabel,.apexcharts-datalabel-label,.apexcharts-datalabel-value,.apexcharts-datalabels,.apexcharts-pie-label {\n cursor: default;\n pointer-events: none\n}\n\n.apexcharts-pie-label-delay {\n opacity: 0;\n animation-name: opaque;\n animation-duration: .3s;\n animation-fill-mode: forwards;\n animation-timing-function: ease\n}\n\n.apexcharts-radialbar-label {\n cursor: pointer;\n}\n\n.apexcharts-annotation-rect,.apexcharts-area-series .apexcharts-area,.apexcharts-area-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-gridline,.apexcharts-line,.apexcharts-line-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-point-annotation-label,.apexcharts-radar-series path,.apexcharts-radar-series polygon,.apexcharts-toolbar svg,.apexcharts-tooltip .apexcharts-marker,.apexcharts-xaxis-annotation-label,.apexcharts-yaxis-annotation-label,.apexcharts-zoom-rect {\n pointer-events: none\n}\n\n.apexcharts-marker {\n transition: .15s ease all\n}\n\n.resize-triggers {\n animation: 1ms resizeanim;\n visibility: hidden;\n opacity: 0;\n height: 100%;\n width: 100%;\n overflow: hidden\n}\n\n.contract-trigger:before,.resize-triggers,.resize-triggers>div {\n content: " ";\n display: block;\n position: absolute;\n top: 0;\n left: 0\n}\n\n.resize-triggers>div {\n height: 100%;\n width: 100%;\n background: #eee;\n overflow: auto\n}\n\n.contract-trigger:before {\n overflow: hidden;\n width: 200%;\n height: 200%\n}\n\n.apexcharts-bar-goals-markers{\n pointer-events: none\n}\n\n.apexcharts-bar-shadows{\n pointer-events: none\n}\n\n.apexcharts-rangebar-goals-markers{\n pointer-events: none\n}'; var h = (null === (l = t.opts.chart) || void 0 === l ? void 0 : l.nonce) || t.w.config.chart.nonce; h && n.setAttribute("nonce", h), r ? s.prepend(n) : o.head.appendChild(n) } var c = t.create(t.w.config.series, {}); if (!c) return e(t); t.mount(c).then((function () { "function" == typeof t.w.config.chart.events.mounted && t.w.config.chart.events.mounted(t, t.w), t.events.fireEvent("mounted", [t, t.w]), e(c) })).catch((function (t) { i(t) })) } else i(new Error("Element not found")) })) } }, { key: "create", value: function (t, e) { var i = this.w; new Gt(this).initModules(); var a = this.w.globals; (a.noData = !1, a.animationEnded = !1, this.responsive.checkResponsiveConfig(e), i.config.xaxis.convertedCatToNumeric) && new E(i.config).convertCatToNumericXaxis(i.config, this.ctx); if (null === this.el) return a.animationEnded = !0, null; if (this.core.setupElements(), "treemap" === i.config.chart.type && (i.config.grid.show = !1, i.config.yaxis[0].show = !1), 0 === a.svgWidth) return a.animationEnded = !0, null; var s = y.checkComboSeries(t, i.config.chart.type); a.comboCharts = s.comboCharts, a.comboBarCount = s.comboBarCount; var r = t.every((function (t) { return t.data && 0 === t.data.length })); (0 === t.length || r && a.collapsedSeries.length < 1) && this.series.handleNoData(), this.events.setupEventHandlers(), this.data.parseData(t), this.theme.init(), new D(this).setGlobalMarkerSize(), this.formatters.setLabelFormatters(), this.titleSubtitle.draw(), a.noData && a.collapsedSeries.length !== a.series.length && !i.config.legend.showForSingleSeries || this.legend.init(), this.series.hasAllSeriesEqualX(), a.axisCharts && (this.core.coreCalculations(), "category" !== i.config.xaxis.type && this.formatters.setLabelFormatters(), this.ctx.toolbar.minX = i.globals.minX, this.ctx.toolbar.maxX = i.globals.maxX), this.formatters.heatmapLabelFormatters(), new y(this).getLargestMarkerSize(), this.dimensions.plotCoords(); var o = this.core.xySettings(); this.grid.createGridMask(); var n = this.core.plotChartType(t, o), l = new N(this); return l.bringForward(), i.config.dataLabels.background.enabled && l.dataLabelsBackground(), this.core.shiftGraphPosition(), { elGraph: n, xyRatios: o, dimensions: { plot: { left: i.globals.translateX, top: i.globals.translateY, width: i.globals.gridWidth, height: i.globals.gridHeight } } } } }, { key: "mount", value: function () { var t = this, e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : null, i = this, a = i.w; return new Promise((function (s, r) { if (null === i.el) return r(new Error("Not enough data to display or target element not found")); (null === e || a.globals.allSeriesCollapsed) && i.series.handleNoData(), i.grid = new j(i); var o, n, l = i.grid.drawGrid(); (i.annotations = new T(i), i.annotations.drawImageAnnos(), i.annotations.drawTextAnnos(), "back" === a.config.grid.position) && (l && a.globals.dom.elGraphical.add(l.el), null != l && null !== (o = l.elGridBorders) && void 0 !== o && o.node && a.globals.dom.elGraphical.add(l.elGridBorders)); if (Array.isArray(e.elGraph)) for (var h = 0; h < e.elGraph.length; h++)a.globals.dom.elGraphical.add(e.elGraph[h]); else a.globals.dom.elGraphical.add(e.elGraph); "front" === a.config.grid.position && (l && a.globals.dom.elGraphical.add(l.el), null != l && null !== (n = l.elGridBorders) && void 0 !== n && n.node && a.globals.dom.elGraphical.add(l.elGridBorders)); "front" === a.config.xaxis.crosshairs.position && i.crosshairs.drawXCrosshairs(), "front" === a.config.yaxis[0].crosshairs.position && i.crosshairs.drawYCrosshairs(), "treemap" !== a.config.chart.type && i.axes.drawAxis(a.config.chart.type, l); var c = new V(t.ctx, l), d = new q(t.ctx, l); if (null !== l && (c.xAxisLabelCorrections(l.xAxisTickWidth), d.setYAxisTextAlignments(), a.config.yaxis.map((function (t, e) { -1 === a.globals.ignoreYAxisIndexes.indexOf(e) && d.yAxisTitleRotate(e, t.opposite) }))), i.annotations.drawAxesAnnotations(), !a.globals.noData) { if (a.config.tooltip.enabled && !a.globals.noData && i.w.globals.tooltip.drawTooltip(e.xyRatios), a.globals.axisCharts && (a.globals.isXNumeric || a.config.xaxis.convertedCatToNumeric || a.globals.isRangeBar)) (a.config.chart.zoom.enabled || a.config.chart.selection && a.config.chart.selection.enabled || a.config.chart.pan && a.config.chart.pan.enabled) && i.zoomPanSelection.init({ xyRatios: e.xyRatios }); else { var g = a.config.chart.toolbar.tools;["zoom", "zoomin", "zoomout", "selection", "pan", "reset"].forEach((function (t) { g[t] = !1 })) } a.config.chart.toolbar.show && !a.globals.allSeriesCollapsed && i.toolbar.createToolbar() } a.globals.memory.methodsToExec.length > 0 && a.globals.memory.methodsToExec.forEach((function (t) { t.method(t.params, !1, t.context) })), a.globals.axisCharts || a.globals.noData || i.core.resizeNonAxisCharts(), s(i) })) } }, { key: "destroy", value: function () { var t, e; window.removeEventListener("resize", this.windowResizeHandler), this.el.parentNode, t = this.parentResizeHandler, (e = jt.get(t)) && (e.disconnect(), jt.delete(t)); var i = this.w.config.chart.id; i && Apex._chartInstances.forEach((function (t, e) { t.id === x.escapeString(i) && Apex._chartInstances.splice(e, 1) })), new Vt(this.ctx).clear({ isUpdating: !1 }) } }, { key: "updateOptions", value: function (t) { var e = this, i = arguments.length > 1 && void 0 !== arguments[1] && arguments[1], a = !(arguments.length > 2 && void 0 !== arguments[2]) || arguments[2], s = !(arguments.length > 3 && void 0 !== arguments[3]) || arguments[3], r = !(arguments.length > 4 && void 0 !== arguments[4]) || arguments[4], o = this.w; return o.globals.selection = void 0, t.series && (this.series.resetSeries(!1, !0, !1), t.series.length && t.series[0].data && (t.series = t.series.map((function (t, i) { return e.updateHelpers._extendSeries(t, i) }))), this.updateHelpers.revertDefaultAxisMinMax()), t.xaxis && (t = this.updateHelpers.forceXAxisUpdate(t)), t.yaxis && (t = this.updateHelpers.forceYAxisUpdate(t)), o.globals.collapsedSeriesIndices.length > 0 && this.series.clearPreviousPaths(), t.theme && (t = this.theme.updateThemeOptions(t)), this.updateHelpers._updateOptions(t, i, a, s, r) } }, { key: "updateSeries", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : [], e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1], i = !(arguments.length > 2 && void 0 !== arguments[2]) || arguments[2]; return this.series.resetSeries(!1), this.updateHelpers.revertDefaultAxisMinMax(), this.updateHelpers._updateSeries(t, e, i) } }, { key: "appendSeries", value: function (t) { var e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1], i = !(arguments.length > 2 && void 0 !== arguments[2]) || arguments[2], a = this.w.config.series.slice(); return a.push(t), this.series.resetSeries(!1), this.updateHelpers.revertDefaultAxisMinMax(), this.updateHelpers._updateSeries(a, e, i) } }, { key: "appendData", value: function (t) { var e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1], i = this; i.w.globals.dataChanged = !0, i.series.getPreviousPaths(); for (var a = i.w.config.series.slice(), s = 0; s < a.length; s++)if (null !== t[s] && void 0 !== t[s]) for (var r = 0; r < t[s].data.length; r++)a[s].data.push(t[s].data[r]); return i.w.config.series = a, e && (i.w.globals.initialSeries = x.clone(i.w.config.series)), this.update() } }, { key: "update", value: function (t) { var e = this; return new Promise((function (i, a) { new Vt(e.ctx).clear({ isUpdating: !0 }); var s = e.create(e.w.config.series, t); if (!s) return i(e); e.mount(s).then((function () { "function" == typeof e.w.config.chart.events.updated && e.w.config.chart.events.updated(e, e.w), e.events.fireEvent("updated", [e, e.w]), e.w.globals.isDirty = !0, i(e) })).catch((function (t) { a(t) })) })) } }, { key: "getSyncedCharts", value: function () { var t = this.getGroupedCharts(), e = [this]; return t.length && (e = [], t.forEach((function (t) { e.push(t) }))), e } }, { key: "getGroupedCharts", value: function () { var t = this; return Apex._chartInstances.filter((function (t) { if (t.group) return !0 })).map((function (e) { return t.w.config.chart.group === e.group ? e.chart : t })) } }, { key: "toggleSeries", value: function (t) { return this.series.toggleSeries(t) } }, { key: "highlightSeriesOnLegendHover", value: function (t, e) { return this.series.toggleSeriesOnHover(t, e) } }, { key: "showSeries", value: function (t) { this.series.showSeries(t) } }, { key: "hideSeries", value: function (t) { this.series.hideSeries(t) } }, { key: "isSeriesHidden", value: function (t) { this.series.isSeriesHidden(t) } }, { key: "resetSeries", value: function () { var t = !(arguments.length > 0 && void 0 !== arguments[0]) || arguments[0], e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1]; this.series.resetSeries(t, e) } }, { key: "addEventListener", value: function (t, e) { this.events.addEventListener(t, e) } }, { key: "removeEventListener", value: function (t, e) { this.events.removeEventListener(t, e) } }, { key: "addXaxisAnnotation", value: function (t) { var e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1], i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : void 0, a = this; i && (a = i), a.annotations.addXaxisAnnotationExternal(t, e, a) } }, { key: "addYaxisAnnotation", value: function (t) { var e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1], i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : void 0, a = this; i && (a = i), a.annotations.addYaxisAnnotationExternal(t, e, a) } }, { key: "addPointAnnotation", value: function (t) { var e = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1], i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : void 0, a = this; i && (a = i), a.annotations.addPointAnnotationExternal(t, e, a) } }, { key: "clearAnnotations", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : void 0, e = this; t && (e = t), e.annotations.clearAnnotations(e) } }, { key: "removeAnnotation", value: function (t) { var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : void 0, i = this; e && (i = e), i.annotations.removeAnnotation(i, t) } }, { key: "getChartArea", value: function () { return this.w.globals.dom.baseEl.querySelector(".apexcharts-inner") } }, { key: "getSeriesTotalXRange", value: function (t, e) { return this.coreUtils.getSeriesTotalsXRange(t, e) } }, { key: "getHighestValueInSeries", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 0; return new U(this.ctx).getMinYMaxY(t).highestY } }, { key: "getLowestValueInSeries", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 0; return new U(this.ctx).getMinYMaxY(t).lowestY } }, { key: "getSeriesTotal", value: function () { return this.w.globals.seriesTotals } }, { key: "toggleDataPointSelection", value: function (t, e) { return this.updateHelpers.toggleDataPointSelection(t, e) } }, { key: "zoomX", value: function (t, e) { this.ctx.toolbar.zoomUpdateOptions(t, e) } }, { key: "setLocale", value: function (t) { this.localization.setCurrentLocaleValues(t) } }, { key: "dataURI", value: function (t) { return new G(this.ctx).dataURI(t) } }, { key: "exportToCSV", value: function () { var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; return new G(this.ctx).exportToCSV(t) } }, { key: "paper", value: function () { return this.w.globals.dom.Paper } }, { key: "_parentResizeCallback", value: function () { this.w.globals.animationEnded && this.w.config.chart.redrawOnParentResize && this._windowResize() } }, { key: "_windowResize", value: function () { var t = this; clearTimeout(this.w.globals.resizeTimer), this.w.globals.resizeTimer = window.setTimeout((function () { t.w.globals.resized = !0, t.w.globals.dataChanged = !1, t.ctx.update() }), 150) } }, { key: "_windowResizeHandler", value: function () { var t = this.w.config.chart.redrawOnWindowResize; "function" == typeof t && (t = t()), t && this._windowResize() } }], [{ key: "getChartByID", value: function (t) { var e = x.escapeString(t); if (Apex._chartInstances) { var i = Apex._chartInstances.filter((function (t) { return t.id === e }))[0]; return i && i.chart } } }, { key: "initOnLoad", value: function () { for (var e = document.querySelectorAll("[data-apexcharts]"), i = 0; i < e.length; i++) { new t(e[i], JSON.parse(e[i].getAttribute("data-options"))).render() } } }, { key: "exec", value: function (t, e) { var i = this.getChartByID(t); if (i) { i.w.globals.isExecCalled = !0; var a = null; if (-1 !== i.publicMethods.indexOf(e)) { for (var s = arguments.length, r = new Array(s > 2 ? s - 2 : 0), o = 2; o < s; o++)r[o - 2] = arguments[o]; a = i[e].apply(i, r) } return a } } }, { key: "merge", value: function (t, e) { return x.extend(t, e) } }]), t }(); return _t })); ================================================ FILE: public/js/dropzone.js ================================================ !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(self,(function(){return function(){var e={3099:function(e){e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},6077:function(e,t,n){var r=n(111);e.exports=function(e){if(!r(e)&&null!==e)throw TypeError("Can't set "+String(e)+" as a prototype");return e}},1223:function(e,t,n){var r=n(5112),i=n(30),o=n(3070),a=r("unscopables"),u=Array.prototype;null==u[a]&&o.f(u,a,{configurable:!0,value:i(null)}),e.exports=function(e){u[a][e]=!0}},1530:function(e,t,n){"use strict";var r=n(8710).charAt;e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},5787:function(e){e.exports=function(e,t,n){if(!(e instanceof t))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation");return e}},9670:function(e,t,n){var r=n(111);e.exports=function(e){if(!r(e))throw TypeError(String(e)+" is not an object");return e}},4019:function(e){e.exports="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof DataView},260:function(e,t,n){"use strict";var r,i=n(4019),o=n(9781),a=n(7854),u=n(111),s=n(6656),l=n(648),c=n(8880),f=n(1320),p=n(3070).f,h=n(9518),d=n(7674),v=n(5112),y=n(9711),g=a.Int8Array,m=g&&g.prototype,b=a.Uint8ClampedArray,x=b&&b.prototype,w=g&&h(g),E=m&&h(m),k=Object.prototype,A=k.isPrototypeOf,S=v("toStringTag"),F=y("TYPED_ARRAY_TAG"),T=i&&!!d&&"Opera"!==l(a.opera),C=!1,L={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},R={BigInt64Array:8,BigUint64Array:8},I=function(e){if(!u(e))return!1;var t=l(e);return s(L,t)||s(R,t)};for(r in L)a[r]||(T=!1);if((!T||"function"!=typeof w||w===Function.prototype)&&(w=function(){throw TypeError("Incorrect invocation")},T))for(r in L)a[r]&&d(a[r],w);if((!T||!E||E===k)&&(E=w.prototype,T))for(r in L)a[r]&&d(a[r].prototype,E);if(T&&h(x)!==E&&d(x,E),o&&!s(E,S))for(r in C=!0,p(E,S,{get:function(){return u(this)?this[F]:void 0}}),L)a[r]&&c(a[r],F,r);e.exports={NATIVE_ARRAY_BUFFER_VIEWS:T,TYPED_ARRAY_TAG:C&&F,aTypedArray:function(e){if(I(e))return e;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(e){if(d){if(A.call(w,e))return e}else for(var t in L)if(s(L,r)){var n=a[t];if(n&&(e===n||A.call(n,e)))return e}throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(e,t,n){if(o){if(n)for(var r in L){var i=a[r];i&&s(i.prototype,e)&&delete i.prototype[e]}E[e]&&!n||f(E,e,n?t:T&&m[e]||t)}},exportTypedArrayStaticMethod:function(e,t,n){var r,i;if(o){if(d){if(n)for(r in L)(i=a[r])&&s(i,e)&&delete i[e];if(w[e]&&!n)return;try{return f(w,e,n?t:T&&g[e]||t)}catch(e){}}for(r in L)!(i=a[r])||i[e]&&!n||f(i,e,t)}},isView:function(e){if(!u(e))return!1;var t=l(e);return"DataView"===t||s(L,t)||s(R,t)},isTypedArray:I,TypedArray:w,TypedArrayPrototype:E}},3331:function(e,t,n){"use strict";var r=n(7854),i=n(9781),o=n(4019),a=n(8880),u=n(2248),s=n(7293),l=n(5787),c=n(9958),f=n(7466),p=n(7067),h=n(1179),d=n(9518),v=n(7674),y=n(8006).f,g=n(3070).f,m=n(1285),b=n(8003),x=n(9909),w=x.get,E=x.set,k="ArrayBuffer",A="DataView",S="Wrong index",F=r.ArrayBuffer,T=F,C=r.DataView,L=C&&C.prototype,R=Object.prototype,I=r.RangeError,U=h.pack,O=h.unpack,_=function(e){return[255&e]},M=function(e){return[255&e,e>>8&255]},z=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},P=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},j=function(e){return U(e,23,4)},D=function(e){return U(e,52,8)},N=function(e,t){g(e.prototype,t,{get:function(){return w(this)[t]}})},B=function(e,t,n,r){var i=p(n),o=w(e);if(i+t>o.byteLength)throw I(S);var a=w(o.buffer).bytes,u=i+o.byteOffset,s=a.slice(u,u+t);return r?s:s.reverse()},q=function(e,t,n,r,i,o){var a=p(n),u=w(e);if(a+t>u.byteLength)throw I(S);for(var s=w(u.buffer).bytes,l=a+u.byteOffset,c=r(+i),f=0;fG;)(W=Y[G++])in T||a(T,W,F[W]);H.constructor=T}v&&d(L)!==R&&v(L,R);var Q=new C(new T(2)),$=L.setInt8;Q.setInt8(0,2147483648),Q.setInt8(1,2147483649),!Q.getInt8(0)&&Q.getInt8(1)||u(L,{setInt8:function(e,t){$.call(this,e,t<<24>>24)},setUint8:function(e,t){$.call(this,e,t<<24>>24)}},{unsafe:!0})}else T=function(e){l(this,T,k);var t=p(e);E(this,{bytes:m.call(new Array(t),0),byteLength:t}),i||(this.byteLength=t)},C=function(e,t,n){l(this,C,A),l(e,T,A);var r=w(e).byteLength,o=c(t);if(o<0||o>r)throw I("Wrong offset");if(o+(n=void 0===n?r-o:f(n))>r)throw I("Wrong length");E(this,{buffer:e,byteLength:n,byteOffset:o}),i||(this.buffer=e,this.byteLength=n,this.byteOffset=o)},i&&(N(T,"byteLength"),N(C,"buffer"),N(C,"byteLength"),N(C,"byteOffset")),u(C.prototype,{getInt8:function(e){return B(this,1,e)[0]<<24>>24},getUint8:function(e){return B(this,1,e)[0]},getInt16:function(e){var t=B(this,2,e,arguments.length>1?arguments[1]:void 0);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=B(this,2,e,arguments.length>1?arguments[1]:void 0);return t[1]<<8|t[0]},getInt32:function(e){return P(B(this,4,e,arguments.length>1?arguments[1]:void 0))},getUint32:function(e){return P(B(this,4,e,arguments.length>1?arguments[1]:void 0))>>>0},getFloat32:function(e){return O(B(this,4,e,arguments.length>1?arguments[1]:void 0),23)},getFloat64:function(e){return O(B(this,8,e,arguments.length>1?arguments[1]:void 0),52)},setInt8:function(e,t){q(this,1,e,_,t)},setUint8:function(e,t){q(this,1,e,_,t)},setInt16:function(e,t){q(this,2,e,M,t,arguments.length>2?arguments[2]:void 0)},setUint16:function(e,t){q(this,2,e,M,t,arguments.length>2?arguments[2]:void 0)},setInt32:function(e,t){q(this,4,e,z,t,arguments.length>2?arguments[2]:void 0)},setUint32:function(e,t){q(this,4,e,z,t,arguments.length>2?arguments[2]:void 0)},setFloat32:function(e,t){q(this,4,e,j,t,arguments.length>2?arguments[2]:void 0)},setFloat64:function(e,t){q(this,8,e,D,t,arguments.length>2?arguments[2]:void 0)}});b(T,k),b(C,A),e.exports={ArrayBuffer:T,DataView:C}},1048:function(e,t,n){"use strict";var r=n(7908),i=n(1400),o=n(7466),a=Math.min;e.exports=[].copyWithin||function(e,t){var n=r(this),u=o(n.length),s=i(e,u),l=i(t,u),c=arguments.length>2?arguments[2]:void 0,f=a((void 0===c?u:i(c,u))-l,u-s),p=1;for(l0;)l in n?n[s]=n[l]:delete n[s],s+=p,l+=p;return n}},1285:function(e,t,n){"use strict";var r=n(7908),i=n(1400),o=n(7466);e.exports=function(e){for(var t=r(this),n=o(t.length),a=arguments.length,u=i(a>1?arguments[1]:void 0,n),s=a>2?arguments[2]:void 0,l=void 0===s?n:i(s,n);l>u;)t[u++]=e;return t}},8533:function(e,t,n){"use strict";var r=n(2092).forEach,i=n(9341)("forEach");e.exports=i?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},8457:function(e,t,n){"use strict";var r=n(9974),i=n(7908),o=n(3411),a=n(7659),u=n(7466),s=n(6135),l=n(1246);e.exports=function(e){var t,n,c,f,p,h,d=i(e),v="function"==typeof this?this:Array,y=arguments.length,g=y>1?arguments[1]:void 0,m=void 0!==g,b=l(d),x=0;if(m&&(g=r(g,y>2?arguments[2]:void 0,2)),null==b||v==Array&&a(b))for(n=new v(t=u(d.length));t>x;x++)h=m?g(d[x],x):d[x],s(n,x,h);else for(p=(f=b.call(d)).next,n=new v;!(c=p.call(f)).done;x++)h=m?o(f,g,[c.value,x],!0):c.value,s(n,x,h);return n.length=x,n}},1318:function(e,t,n){var r=n(5656),i=n(7466),o=n(1400),a=function(e){return function(t,n,a){var u,s=r(t),l=i(s.length),c=o(a,l);if(e&&n!=n){for(;l>c;)if((u=s[c++])!=u)return!0}else for(;l>c;c++)if((e||c in s)&&s[c]===n)return e||c||0;return!e&&-1}};e.exports={includes:a(!0),indexOf:a(!1)}},2092:function(e,t,n){var r=n(9974),i=n(8361),o=n(7908),a=n(7466),u=n(5417),s=[].push,l=function(e){var t=1==e,n=2==e,l=3==e,c=4==e,f=6==e,p=7==e,h=5==e||f;return function(d,v,y,g){for(var m,b,x=o(d),w=i(x),E=r(v,y,3),k=a(w.length),A=0,S=g||u,F=t?S(d,k):n||p?S(d,0):void 0;k>A;A++)if((h||A in w)&&(b=E(m=w[A],A,x),e))if(t)F[A]=b;else if(b)switch(e){case 3:return!0;case 5:return m;case 6:return A;case 2:s.call(F,m)}else switch(e){case 4:return!1;case 7:s.call(F,m)}return f?-1:l||c?c:F}};e.exports={forEach:l(0),map:l(1),filter:l(2),some:l(3),every:l(4),find:l(5),findIndex:l(6),filterOut:l(7)}},6583:function(e,t,n){"use strict";var r=n(5656),i=n(9958),o=n(7466),a=n(9341),u=Math.min,s=[].lastIndexOf,l=!!s&&1/[1].lastIndexOf(1,-0)<0,c=a("lastIndexOf"),f=l||!c;e.exports=f?function(e){if(l)return s.apply(this,arguments)||0;var t=r(this),n=o(t.length),a=n-1;for(arguments.length>1&&(a=u(a,i(arguments[1]))),a<0&&(a=n+a);a>=0;a--)if(a in t&&t[a]===e)return a||0;return-1}:s},1194:function(e,t,n){var r=n(7293),i=n(5112),o=n(7392),a=i("species");e.exports=function(e){return o>=51||!r((function(){var t=[];return(t.constructor={})[a]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},9341:function(e,t,n){"use strict";var r=n(7293);e.exports=function(e,t){var n=[][e];return!!n&&r((function(){n.call(null,t||function(){throw 1},1)}))}},3671:function(e,t,n){var r=n(3099),i=n(7908),o=n(8361),a=n(7466),u=function(e){return function(t,n,u,s){r(n);var l=i(t),c=o(l),f=a(l.length),p=e?f-1:0,h=e?-1:1;if(u<2)for(;;){if(p in c){s=c[p],p+=h;break}if(p+=h,e?p<0:f<=p)throw TypeError("Reduce of empty array with no initial value")}for(;e?p>=0:f>p;p+=h)p in c&&(s=n(s,c[p],p,l));return s}};e.exports={left:u(!1),right:u(!0)}},5417:function(e,t,n){var r=n(111),i=n(3157),o=n(5112)("species");e.exports=function(e,t){var n;return i(e)&&("function"!=typeof(n=e.constructor)||n!==Array&&!i(n.prototype)?r(n)&&null===(n=n[o])&&(n=void 0):n=void 0),new(void 0===n?Array:n)(0===t?0:t)}},3411:function(e,t,n){var r=n(9670),i=n(9212);e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){throw i(e),t}}},7072:function(e,t,n){var r=n(5112)("iterator"),i=!1;try{var o=0,a={next:function(){return{done:!!o++}},return:function(){i=!0}};a[r]=function(){return this},Array.from(a,(function(){throw 2}))}catch(e){}e.exports=function(e,t){if(!t&&!i)return!1;var n=!1;try{var o={};o[r]=function(){return{next:function(){return{done:n=!0}}}},e(o)}catch(e){}return n}},4326:function(e){var t={}.toString;e.exports=function(e){return t.call(e).slice(8,-1)}},648:function(e,t,n){var r=n(1694),i=n(4326),o=n(5112)("toStringTag"),a="Arguments"==i(function(){return arguments}());e.exports=r?i:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),o))?n:a?i(t):"Object"==(r=i(t))&&"function"==typeof t.callee?"Arguments":r}},9920:function(e,t,n){var r=n(6656),i=n(3887),o=n(1236),a=n(3070);e.exports=function(e,t){for(var n=i(t),u=a.f,s=o.f,l=0;l=74)&&(r=a.match(/Chrome\/(\d+)/))&&(i=r[1]),e.exports=i&&+i},748:function(e){e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2109:function(e,t,n){var r=n(7854),i=n(1236).f,o=n(8880),a=n(1320),u=n(3505),s=n(9920),l=n(4705);e.exports=function(e,t){var n,c,f,p,h,d=e.target,v=e.global,y=e.stat;if(n=v?r:y?r[d]||u(d,{}):(r[d]||{}).prototype)for(c in t){if(p=t[c],f=e.noTargetGet?(h=i(n,c))&&h.value:n[c],!l(v?c:d+(y?".":"#")+c,e.forced)&&void 0!==f){if(typeof p==typeof f)continue;s(p,f)}(e.sham||f&&f.sham)&&o(p,"sham",!0),a(n,c,p,e)}}},7293:function(e){e.exports=function(e){try{return!!e()}catch(e){return!0}}},7007:function(e,t,n){"use strict";n(4916);var r=n(1320),i=n(7293),o=n(5112),a=n(2261),u=n(8880),s=o("species"),l=!i((function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")})),c="$0"==="a".replace(/./,"$0"),f=o("replace"),p=!!/./[f]&&""===/./[f]("a","$0"),h=!i((function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));e.exports=function(e,t,n,f){var d=o(e),v=!i((function(){var t={};return t[d]=function(){return 7},7!=""[e](t)})),y=v&&!i((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[s]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return t=!0,null},n[d](""),!t}));if(!v||!y||"replace"===e&&(!l||!c||p)||"split"===e&&!h){var g=/./[d],m=n(d,""[e],(function(e,t,n,r,i){return t.exec===a?v&&!i?{done:!0,value:g.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),{REPLACE_KEEPS_$0:c,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:p}),b=m[0],x=m[1];r(String.prototype,e,b),r(RegExp.prototype,d,2==t?function(e,t){return x.call(e,this,t)}:function(e){return x.call(e,this)})}f&&u(RegExp.prototype[d],"sham",!0)}},9974:function(e,t,n){var r=n(3099);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)}}return function(){return e.apply(t,arguments)}}},5005:function(e,t,n){var r=n(857),i=n(7854),o=function(e){return"function"==typeof e?e:void 0};e.exports=function(e,t){return arguments.length<2?o(r[e])||o(i[e]):r[e]&&r[e][t]||i[e]&&i[e][t]}},1246:function(e,t,n){var r=n(648),i=n(7497),o=n(5112)("iterator");e.exports=function(e){if(null!=e)return e[o]||e["@@iterator"]||i[r(e)]}},8554:function(e,t,n){var r=n(9670),i=n(1246);e.exports=function(e){var t=i(e);if("function"!=typeof t)throw TypeError(String(e)+" is not iterable");return r(t.call(e))}},647:function(e,t,n){var r=n(7908),i=Math.floor,o="".replace,a=/\$([$&'`]|\d\d?|<[^>]*>)/g,u=/\$([$&'`]|\d\d?)/g;e.exports=function(e,t,n,s,l,c){var f=n+e.length,p=s.length,h=u;return void 0!==l&&(l=r(l),h=a),o.call(c,h,(function(r,o){var a;switch(o.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,n);case"'":return t.slice(f);case"<":a=l[o.slice(1,-1)];break;default:var u=+o;if(0===u)return r;if(u>p){var c=i(u/10);return 0===c?r:c<=p?void 0===s[c-1]?o.charAt(1):s[c-1]+o.charAt(1):r}a=s[u-1]}return void 0===a?"":a}))}},7854:function(e,t,n){var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},6656:function(e){var t={}.hasOwnProperty;e.exports=function(e,n){return t.call(e,n)}},3501:function(e){e.exports={}},490:function(e,t,n){var r=n(5005);e.exports=r("document","documentElement")},4664:function(e,t,n){var r=n(9781),i=n(7293),o=n(317);e.exports=!r&&!i((function(){return 7!=Object.defineProperty(o("div"),"a",{get:function(){return 7}}).a}))},1179:function(e){var t=Math.abs,n=Math.pow,r=Math.floor,i=Math.log,o=Math.LN2;e.exports={pack:function(e,a,u){var s,l,c,f=new Array(u),p=8*u-a-1,h=(1<>1,v=23===a?n(2,-24)-n(2,-77):0,y=e<0||0===e&&1/e<0?1:0,g=0;for((e=t(e))!=e||e===1/0?(l=e!=e?1:0,s=h):(s=r(i(e)/o),e*(c=n(2,-s))<1&&(s--,c*=2),(e+=s+d>=1?v/c:v*n(2,1-d))*c>=2&&(s++,c/=2),s+d>=h?(l=0,s=h):s+d>=1?(l=(e*c-1)*n(2,a),s+=d):(l=e*n(2,d-1)*n(2,a),s=0));a>=8;f[g++]=255&l,l/=256,a-=8);for(s=s<0;f[g++]=255&s,s/=256,p-=8);return f[--g]|=128*y,f},unpack:function(e,t){var r,i=e.length,o=8*i-t-1,a=(1<>1,s=o-7,l=i-1,c=e[l--],f=127&c;for(c>>=7;s>0;f=256*f+e[l],l--,s-=8);for(r=f&(1<<-s)-1,f>>=-s,s+=t;s>0;r=256*r+e[l],l--,s-=8);if(0===f)f=1-u;else{if(f===a)return r?NaN:c?-1/0:1/0;r+=n(2,t),f-=u}return(c?-1:1)*r*n(2,f-t)}}},8361:function(e,t,n){var r=n(7293),i=n(4326),o="".split;e.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(e){return"String"==i(e)?o.call(e,""):Object(e)}:Object},9587:function(e,t,n){var r=n(111),i=n(7674);e.exports=function(e,t,n){var o,a;return i&&"function"==typeof(o=t.constructor)&&o!==n&&r(a=o.prototype)&&a!==n.prototype&&i(e,a),e}},2788:function(e,t,n){var r=n(5465),i=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(e){return i.call(e)}),e.exports=r.inspectSource},9909:function(e,t,n){var r,i,o,a=n(8536),u=n(7854),s=n(111),l=n(8880),c=n(6656),f=n(5465),p=n(6200),h=n(3501),d=u.WeakMap;if(a){var v=f.state||(f.state=new d),y=v.get,g=v.has,m=v.set;r=function(e,t){return t.facade=e,m.call(v,e,t),t},i=function(e){return y.call(v,e)||{}},o=function(e){return g.call(v,e)}}else{var b=p("state");h[b]=!0,r=function(e,t){return t.facade=e,l(e,b,t),t},i=function(e){return c(e,b)?e[b]:{}},o=function(e){return c(e,b)}}e.exports={set:r,get:i,has:o,enforce:function(e){return o(e)?i(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!s(t)||(n=i(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}}}},7659:function(e,t,n){var r=n(5112),i=n(7497),o=r("iterator"),a=Array.prototype;e.exports=function(e){return void 0!==e&&(i.Array===e||a[o]===e)}},3157:function(e,t,n){var r=n(4326);e.exports=Array.isArray||function(e){return"Array"==r(e)}},4705:function(e,t,n){var r=n(7293),i=/#|\.prototype\./,o=function(e,t){var n=u[a(e)];return n==l||n!=s&&("function"==typeof t?r(t):!!t)},a=o.normalize=function(e){return String(e).replace(i,".").toLowerCase()},u=o.data={},s=o.NATIVE="N",l=o.POLYFILL="P";e.exports=o},111:function(e){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},1913:function(e){e.exports=!1},7850:function(e,t,n){var r=n(111),i=n(4326),o=n(5112)("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[o])?!!t:"RegExp"==i(e))}},9212:function(e,t,n){var r=n(9670);e.exports=function(e){var t=e.return;if(void 0!==t)return r(t.call(e)).value}},3383:function(e,t,n){"use strict";var r,i,o,a=n(7293),u=n(9518),s=n(8880),l=n(6656),c=n(5112),f=n(1913),p=c("iterator"),h=!1;[].keys&&("next"in(o=[].keys())?(i=u(u(o)))!==Object.prototype&&(r=i):h=!0);var d=null==r||a((function(){var e={};return r[p].call(e)!==e}));d&&(r={}),f&&!d||l(r,p)||s(r,p,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:h}},7497:function(e){e.exports={}},133:function(e,t,n){var r=n(7293);e.exports=!!Object.getOwnPropertySymbols&&!r((function(){return!String(Symbol())}))},590:function(e,t,n){var r=n(7293),i=n(5112),o=n(1913),a=i("iterator");e.exports=!r((function(){var e=new URL("b?a=1&b=2&c=3","http://a"),t=e.searchParams,n="";return e.pathname="c%20d",t.forEach((function(e,r){t.delete("b"),n+=r+e})),o&&!e.toJSON||!t.sort||"http://a/c%20d?a=1&c=3"!==e.href||"3"!==t.get("c")||"a=1"!==String(new URLSearchParams("?a=1"))||!t[a]||"a"!==new URL("https://a@b").username||"b"!==new URLSearchParams(new URLSearchParams("a=b")).get("a")||"xn--e1aybc"!==new URL("http://тест").host||"#%D0%B1"!==new URL("http://a#б").hash||"a1c3"!==n||"x"!==new URL("http://x",void 0).host}))},8536:function(e,t,n){var r=n(7854),i=n(2788),o=r.WeakMap;e.exports="function"==typeof o&&/native code/.test(i(o))},1574:function(e,t,n){"use strict";var r=n(9781),i=n(7293),o=n(1956),a=n(5181),u=n(5296),s=n(7908),l=n(8361),c=Object.assign,f=Object.defineProperty;e.exports=!c||i((function(){if(r&&1!==c({b:1},c(f({},"a",{enumerable:!0,get:function(){f(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},n=Symbol(),i="abcdefghijklmnopqrst";return e[n]=7,i.split("").forEach((function(e){t[e]=e})),7!=c({},e)[n]||o(c({},t)).join("")!=i}))?function(e,t){for(var n=s(e),i=arguments.length,c=1,f=a.f,p=u.f;i>c;)for(var h,d=l(arguments[c++]),v=f?o(d).concat(f(d)):o(d),y=v.length,g=0;y>g;)h=v[g++],r&&!p.call(d,h)||(n[h]=d[h]);return n}:c},30:function(e,t,n){var r,i=n(9670),o=n(6048),a=n(748),u=n(3501),s=n(490),l=n(317),c=n(6200)("IE_PROTO"),f=function(){},p=function(e){return"'),this.element.appendChild(e));var i=e.getElementsByTagName("span")[0];return i&&(null!=i.textContent?i.textContent=this.options.dictFallbackMessage:null!=i.innerText&&(i.innerText=this.options.dictFallbackMessage)),this.element.appendChild(this.getFallbackForm())},resize:function(e,t,n,r){var i={srcX:0,srcY:0,srcWidth:e.width,srcHeight:e.height},o=e.width/e.height;null==t&&null==n?(t=i.srcWidth,n=i.srcHeight):null==t?t=n*o:null==n&&(n=t/o);var a=(t=Math.min(t,i.srcWidth))/(n=Math.min(n,i.srcHeight));if(i.srcWidth>t||i.srcHeight>n)if("crop"===r)o>a?(i.srcHeight=e.height,i.srcWidth=i.srcHeight*a):(i.srcWidth=e.width,i.srcHeight=i.srcWidth/a);else{if("contain"!==r)throw new Error("Unknown resizeMethod '".concat(r,"'"));o>a?n=t/o:t=n*o}return i.srcX=(e.width-i.srcWidth)/2,i.srcY=(e.height-i.srcHeight)/2,i.trgWidth=t,i.trgHeight=n,i},transformFile:function(e,t){return(this.options.resizeWidth||this.options.resizeHeight)&&e.type.match(/image.*/)?this.resizeImage(e,this.options.resizeWidth,this.options.resizeHeight,this.options.resizeMethod,t):t(e)},previewTemplate:'
      Check
      Error
      ',drop:function(e){return this.element.classList.remove("dz-drag-hover")},dragstart:function(e){},dragend:function(e){return this.element.classList.remove("dz-drag-hover")},dragenter:function(e){return this.element.classList.add("dz-drag-hover")},dragover:function(e){return this.element.classList.add("dz-drag-hover")},dragleave:function(e){return this.element.classList.remove("dz-drag-hover")},paste:function(e){},reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(e){var t=this;if(this.element===this.previewsContainer&&this.element.classList.add("dz-started"),this.previewsContainer&&!this.options.disablePreviews){e.previewElement=b.createElement(this.options.previewTemplate.trim()),e.previewTemplate=e.previewElement,this.previewsContainer.appendChild(e.previewElement);var n,r=a(e.previewElement.querySelectorAll("[data-dz-name]"),!0);try{for(r.s();!(n=r.n()).done;){var i=n.value;i.textContent=e.name}}catch(e){r.e(e)}finally{r.f()}var o,u=a(e.previewElement.querySelectorAll("[data-dz-size]"),!0);try{for(u.s();!(o=u.n()).done;)(i=o.value).innerHTML=this.filesize(e.size)}catch(e){u.e(e)}finally{u.f()}this.options.addRemoveLinks&&(e._removeLink=b.createElement(''.concat(this.options.dictRemoveFile,"")),e.previewElement.appendChild(e._removeLink));var s,l=function(n){return n.preventDefault(),n.stopPropagation(),e.status===b.UPLOADING?b.confirm(t.options.dictCancelUploadConfirmation,(function(){return t.removeFile(e)})):t.options.dictRemoveFileConfirmation?b.confirm(t.options.dictRemoveFileConfirmation,(function(){return t.removeFile(e)})):t.removeFile(e)},c=a(e.previewElement.querySelectorAll("[data-dz-remove]"),!0);try{for(c.s();!(s=c.n()).done;)s.value.addEventListener("click",l)}catch(e){c.e(e)}finally{c.f()}}},removedfile:function(e){return null!=e.previewElement&&null!=e.previewElement.parentNode&&e.previewElement.parentNode.removeChild(e.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(e,t){if(e.previewElement){e.previewElement.classList.remove("dz-file-preview");var n,r=a(e.previewElement.querySelectorAll("[data-dz-thumbnail]"),!0);try{for(r.s();!(n=r.n()).done;){var i=n.value;i.alt=e.name,i.src=t}}catch(e){r.e(e)}finally{r.f()}return setTimeout((function(){return e.previewElement.classList.add("dz-image-preview")}),1)}},error:function(e,t){if(e.previewElement){e.previewElement.classList.add("dz-error"),"string"!=typeof t&&t.error&&(t=t.error);var n,r=a(e.previewElement.querySelectorAll("[data-dz-errormessage]"),!0);try{for(r.s();!(n=r.n()).done;)n.value.textContent=t}catch(e){r.e(e)}finally{r.f()}}},errormultiple:function(){},processing:function(e){if(e.previewElement&&(e.previewElement.classList.add("dz-processing"),e._removeLink))return e._removeLink.innerHTML=this.options.dictCancelUpload},processingmultiple:function(){},uploadprogress:function(e,t,n){if(e.previewElement){var r,i=a(e.previewElement.querySelectorAll("[data-dz-uploadprogress]"),!0);try{for(i.s();!(r=i.n()).done;){var o=r.value;"PROGRESS"===o.nodeName?o.value=t:o.style.width="".concat(t,"%")}}catch(e){i.e(e)}finally{i.f()}}},totaluploadprogress:function(){},sending:function(){},sendingmultiple:function(){},success:function(e){if(e.previewElement)return e.previewElement.classList.add("dz-success")},successmultiple:function(){},canceled:function(e){return this.emit("error",e,this.options.dictUploadCanceled)},canceledmultiple:function(){},complete:function(e){if(e._removeLink&&(e._removeLink.innerHTML=this.options.dictRemoveFile),e.previewElement)return e.previewElement.classList.add("dz-complete")},completemultiple:function(){},maxfilesexceeded:function(){},maxfilesreached:function(){},queuecomplete:function(){},addedfiles:function(){}};function l(e){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function c(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return f(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?f(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,i=function(){};return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return a=e.done,e},e:function(e){u=!0,o=e},f:function(){try{a||null==n.return||n.return()}finally{if(u)throw o}}}}function f(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n"))),this.clickableElements.length&&function t(){e.hiddenFileInput&&e.hiddenFileInput.parentNode.removeChild(e.hiddenFileInput),e.hiddenFileInput=document.createElement("input"),e.hiddenFileInput.setAttribute("type","file"),(null===e.options.maxFiles||e.options.maxFiles>1)&&e.hiddenFileInput.setAttribute("multiple","multiple"),e.hiddenFileInput.className="dz-hidden-input",null!==e.options.acceptedFiles&&e.hiddenFileInput.setAttribute("accept",e.options.acceptedFiles),null!==e.options.capture&&e.hiddenFileInput.setAttribute("capture",e.options.capture),e.hiddenFileInput.setAttribute("tabindex","-1"),e.hiddenFileInput.style.visibility="hidden",e.hiddenFileInput.style.position="absolute",e.hiddenFileInput.style.top="0",e.hiddenFileInput.style.left="0",e.hiddenFileInput.style.height="0",e.hiddenFileInput.style.width="0",i.getElement(e.options.hiddenInputContainer,"hiddenInputContainer").appendChild(e.hiddenFileInput),e.hiddenFileInput.addEventListener("change",(function(){var n=e.hiddenFileInput.files;if(n.length){var r,i=c(n,!0);try{for(i.s();!(r=i.n()).done;){var o=r.value;e.addFile(o)}}catch(e){i.e(e)}finally{i.f()}}e.emit("addedfiles",n),t()}))}(),this.URL=null!==window.URL?window.URL:window.webkitURL;var t,n=c(this.events,!0);try{for(n.s();!(t=n.n()).done;){var r=t.value;this.on(r,this.options[r])}}catch(e){n.e(e)}finally{n.f()}this.on("uploadprogress",(function(){return e.updateTotalUploadProgress()})),this.on("removedfile",(function(){return e.updateTotalUploadProgress()})),this.on("canceled",(function(t){return e.emit("complete",t)})),this.on("complete",(function(t){if(0===e.getAddedFiles().length&&0===e.getUploadingFiles().length&&0===e.getQueuedFiles().length)return setTimeout((function(){return e.emit("queuecomplete")}),0)}));var o=function(e){if(function(e){if(e.dataTransfer.types)for(var t=0;t")),n+='');var r=i.createElement(n);return"FORM"!==this.element.tagName?(t=i.createElement('
      '))).appendChild(r):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method)),null!=t?t:r}},{key:"getExistingFallback",value:function(){for(var e=function(e){var t,n=c(e,!0);try{for(n.s();!(t=n.n()).done;){var r=t.value;if(/(^| )fallback($| )/.test(r.className))return r}}catch(e){n.e(e)}finally{n.f()}},t=0,n=["div","form"];t0){for(var r=["tb","gb","mb","kb","b"],i=0;i=Math.pow(this.options.filesizeBase,4-i)/10){t=e/Math.pow(this.options.filesizeBase,4-i),n=o;break}}t=Math.round(10*t)/10}return"".concat(t," ").concat(this.options.dictFileSizeUnits[n])}},{key:"_updateMaxFilesReachedClass",value:function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")}},{key:"drop",value:function(e){if(e.dataTransfer){this.emit("drop",e);for(var t=[],n=0;n0){var i,o=c(r,!0);try{for(o.s();!(i=o.n()).done;){var a=i.value;a.isFile?a.file((function(e){if(!n.options.ignoreHiddenFiles||"."!==e.name.substring(0,1))return e.fullPath="".concat(t,"/").concat(e.name),n.addFile(e)})):a.isDirectory&&n._addFilesFromDirectory(a,"".concat(t,"/").concat(a.name))}}catch(e){o.e(e)}finally{o.f()}e()}return null}),i)}()}},{key:"accept",value:function(e,t){this.options.maxFilesize&&e.size>1024*this.options.maxFilesize*1024?t(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(e.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):i.isValidFile(e,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(t(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",e)):this.options.accept.call(this,e,t):t(this.options.dictInvalidFileType)}},{key:"addFile",value:function(e){var t=this;e.upload={uuid:i.uuidv4(),progress:0,total:e.size,bytesSent:0,filename:this._renameFile(e)},this.files.push(e),e.status=i.ADDED,this.emit("addedfile",e),this._enqueueThumbnail(e),this.accept(e,(function(n){n?(e.accepted=!1,t._errorProcessing([e],n)):(e.accepted=!0,t.options.autoQueue&&t.enqueueFile(e)),t._updateMaxFilesReachedClass()}))}},{key:"enqueueFiles",value:function(e){var t,n=c(e,!0);try{for(n.s();!(t=n.n()).done;){var r=t.value;this.enqueueFile(r)}}catch(e){n.e(e)}finally{n.f()}return null}},{key:"enqueueFile",value:function(e){var t=this;if(e.status!==i.ADDED||!0!==e.accepted)throw new Error("This file can't be queued because it has already been processed or was rejected.");if(e.status=i.QUEUED,this.options.autoProcessQueue)return setTimeout((function(){return t.processQueue()}),0)}},{key:"_enqueueThumbnail",value:function(e){var t=this;if(this.options.createImageThumbnails&&e.type.match(/image.*/)&&e.size<=1024*this.options.maxThumbnailFilesize*1024)return this._thumbnailQueue.push(e),setTimeout((function(){return t._processThumbnailQueue()}),0)}},{key:"_processThumbnailQueue",value:function(){var e=this;if(!this._processingThumbnail&&0!==this._thumbnailQueue.length){this._processingThumbnail=!0;var t=this._thumbnailQueue.shift();return this.createThumbnail(t,this.options.thumbnailWidth,this.options.thumbnailHeight,this.options.thumbnailMethod,!0,(function(n){return e.emit("thumbnail",t,n),e._processingThumbnail=!1,e._processThumbnailQueue()}))}}},{key:"removeFile",value:function(e){if(e.status===i.UPLOADING&&this.cancelUpload(e),this.files=x(this.files,e),this.emit("removedfile",e),0===this.files.length)return this.emit("reset")}},{key:"removeAllFiles",value:function(e){null==e&&(e=!1);var t,n=c(this.files.slice(),!0);try{for(n.s();!(t=n.n()).done;){var r=t.value;(r.status!==i.UPLOADING||e)&&this.removeFile(r)}}catch(e){n.e(e)}finally{n.f()}return null}},{key:"resizeImage",value:function(e,t,n,r,o){var a=this;return this.createThumbnail(e,t,n,r,!0,(function(t,n){if(null==n)return o(e);var r=a.options.resizeMimeType;null==r&&(r=e.type);var u=n.toDataURL(r,a.options.resizeQuality);return"image/jpeg"!==r&&"image/jpg"!==r||(u=k.restore(e.dataURL,u)),o(i.dataURItoBlob(u))}))}},{key:"createThumbnail",value:function(e,t,n,r,i,o){var a=this,u=new FileReader;u.onload=function(){e.dataURL=u.result,"image/svg+xml"!==e.type?a.createThumbnailFromUrl(e,t,n,r,i,o):null!=o&&o(u.result)},u.readAsDataURL(e)}},{key:"displayExistingFile",value:function(e,t,n,r){var i=this,o=!(arguments.length>4&&void 0!==arguments[4])||arguments[4];if(this.emit("addedfile",e),this.emit("complete",e),o){var a=function(t){i.emit("thumbnail",e,t),n&&n()};e.dataURL=t,this.createThumbnailFromUrl(e,this.options.thumbnailWidth,this.options.thumbnailHeight,this.options.thumbnailMethod,this.options.fixOrientation,a,r)}else this.emit("thumbnail",e,t),n&&n()}},{key:"createThumbnailFromUrl",value:function(e,t,n,r,i,o,a){var u=this,s=document.createElement("img");return a&&(s.crossOrigin=a),i="from-image"!=getComputedStyle(document.body).imageOrientation&&i,s.onload=function(){var a=function(e){return e(1)};return"undefined"!=typeof EXIF&&null!==EXIF&&i&&(a=function(e){return EXIF.getData(s,(function(){return e(EXIF.getTag(this,"Orientation"))}))}),a((function(i){e.width=s.width,e.height=s.height;var a=u.options.resize.call(u,e,t,n,r),l=document.createElement("canvas"),c=l.getContext("2d");switch(l.width=a.trgWidth,l.height=a.trgHeight,i>4&&(l.width=a.trgHeight,l.height=a.trgWidth),i){case 2:c.translate(l.width,0),c.scale(-1,1);break;case 3:c.translate(l.width,l.height),c.rotate(Math.PI);break;case 4:c.translate(0,l.height),c.scale(1,-1);break;case 5:c.rotate(.5*Math.PI),c.scale(1,-1);break;case 6:c.rotate(.5*Math.PI),c.translate(0,-l.width);break;case 7:c.rotate(.5*Math.PI),c.translate(l.height,-l.width),c.scale(-1,1);break;case 8:c.rotate(-.5*Math.PI),c.translate(-l.height,0)}E(c,s,null!=a.srcX?a.srcX:0,null!=a.srcY?a.srcY:0,a.srcWidth,a.srcHeight,null!=a.trgX?a.trgX:0,null!=a.trgY?a.trgY:0,a.trgWidth,a.trgHeight);var f=l.toDataURL("image/png");if(null!=o)return o(f,l)}))},null!=o&&(s.onerror=o),s.src=e.dataURL}},{key:"processQueue",value:function(){var e=this.options.parallelUploads,t=this.getUploadingFiles().length,n=t;if(!(t>=e)){var r=this.getQueuedFiles();if(r.length>0){if(this.options.uploadMultiple)return this.processFiles(r.slice(0,e-t));for(;n1?t-1:0),r=1;rt.options.chunkSize),e[0].upload.totalChunkCount=Math.ceil(r.size/t.options.chunkSize)}if(e[0].upload.chunked){var o=e[0],a=n[0];o.upload.chunks=[];var u=function(){for(var n=0;void 0!==o.upload.chunks[n];)n++;if(!(n>=o.upload.totalChunkCount)){var r=n*t.options.chunkSize,u=Math.min(r+t.options.chunkSize,a.size),s={name:t._getParamName(0),data:a.webkitSlice?a.webkitSlice(r,u):a.slice(r,u),filename:o.upload.filename,chunkIndex:n};o.upload.chunks[n]={file:o,index:n,dataBlock:s,status:i.UPLOADING,progress:0,retries:0},t._uploadData(e,[s])}};if(o.upload.finishedChunkUpload=function(n,r){var a=!0;n.status=i.SUCCESS,n.dataBlock=null,n.xhr=null;for(var s=0;s1?t-1:0),r=1;r=a;u?o++:o--)i[o]=t.charCodeAt(o);return new Blob([r],{type:n})};var x=function(e,t){return e.filter((function(e){return e!==t})).map((function(e){return e}))},w=function(e){return e.replace(/[\-_](\w)/g,(function(e){return e.charAt(1).toUpperCase()}))};b.createElement=function(e){var t=document.createElement("div");return t.innerHTML=e,t.childNodes[0]},b.elementInside=function(e,t){if(e===t)return!0;for(;e=e.parentNode;)if(e===t)return!0;return!1},b.getElement=function(e,t){var n;if("string"==typeof e?n=document.querySelector(e):null!=e.nodeType&&(n=e),null==n)throw new Error("Invalid `".concat(t,"` option provided. Please provide a CSS selector or a plain HTML element."));return n},b.getElements=function(e,t){var n,r;if(e instanceof Array){r=[];try{var i,o=c(e,!0);try{for(o.s();!(i=o.n()).done;)n=i.value,r.push(this.getElement(n,t))}catch(e){o.e(e)}finally{o.f()}}catch(e){r=null}}else if("string"==typeof e){r=[];var a,u=c(document.querySelectorAll(e),!0);try{for(u.s();!(a=u.n()).done;)n=a.value,r.push(n)}catch(e){u.e(e)}finally{u.f()}}else null!=e.nodeType&&(r=[e]);if(null==r||!r.length)throw new Error("Invalid `".concat(t,"` option provided. Please provide a CSS selector, a plain HTML element or a list of those."));return r},b.confirm=function(e,t,n){return window.confirm(e)?t():null!=n?n():void 0},b.isValidFile=function(e,t){if(!t)return!0;t=t.split(",");var n,r=e.type,i=r.replace(/\/.*$/,""),o=c(t,!0);try{for(o.s();!(n=o.n()).done;){var a=n.value;if("."===(a=a.trim()).charAt(0)){if(-1!==e.name.toLowerCase().indexOf(a.toLowerCase(),e.name.length-a.length))return!0}else if(/\/\*$/.test(a)){if(i===a.replace(/\/.*$/,""))return!0}else if(r===a)return!0}}catch(e){o.e(e)}finally{o.f()}return!1},"undefined"!=typeof jQuery&&null!==jQuery&&(jQuery.fn.dropzone=function(e){return this.each((function(){return new b(this,e)}))}),b.ADDED="added",b.QUEUED="queued",b.ACCEPTED=b.QUEUED,b.UPLOADING="uploading",b.PROCESSING=b.UPLOADING,b.CANCELED="canceled",b.ERROR="error",b.SUCCESS="success";var E=function(e,t,n,r,i,o,a,u,s,l){var c=function(e){e.naturalWidth;var t=e.naturalHeight,n=document.createElement("canvas");n.width=1,n.height=t;var r=n.getContext("2d");r.drawImage(e,0,0);for(var i=r.getImageData(1,0,1,t).data,o=0,a=t,u=t;u>o;)0===i[4*(u-1)+3]?a=u:o=u,u=a+o>>1;var s=u/t;return 0===s?1:s}(t);return e.drawImage(t,n,r,i,o,a,u,s,l/c)},k=function(){function e(){p(this,e)}return d(e,null,[{key:"initClass",value:function(){this.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}},{key:"encode64",value:function(e){for(var t="",n=void 0,r=void 0,i="",o=void 0,a=void 0,u=void 0,s="",l=0;o=(n=e[l++])>>2,a=(3&n)<<4|(r=e[l++])>>4,u=(15&r)<<2|(i=e[l++])>>6,s=63&i,isNaN(r)?u=s=64:isNaN(i)&&(s=64),t=t+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(a)+this.KEY_STR.charAt(u)+this.KEY_STR.charAt(s),n=r=i="",o=a=u=s="",le.length)break}return n}},{key:"decode64",value:function(e){var t=void 0,n=void 0,r="",i=void 0,o=void 0,a="",u=0,s=[];for(/[^A-Za-z0-9\+\/\=]/g.exec(e)&&console.warn("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\nExpect errors in decoding."),e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");t=this.KEY_STR.indexOf(e.charAt(u++))<<2|(i=this.KEY_STR.indexOf(e.charAt(u++)))>>4,n=(15&i)<<4|(o=this.KEY_STR.indexOf(e.charAt(u++)))>>2,r=(3&o)<<6|(a=this.KEY_STR.indexOf(e.charAt(u++))),s.push(t),64!==o&&s.push(n),64!==a&&s.push(r),t=n=r="",i=o=a="",u=0?!0:typeof process<"u"?process.platform==="win32":!1}}W.Environment=n})(ie||(ie={}));var ie;(function(W){class n{constructor(d,f,p){this.type=d,this.detail=f,this.timestamp=p}}W.LoaderEvent=n;class i{constructor(d){this._events=[new n(1,"",d)]}record(d,f){this._events.push(new n(d,f,W.Utilities.getHighPerformanceTimestamp()))}getEvents(){return this._events}}W.LoaderEventRecorder=i;class x{record(d,f){}getEvents(){return[]}}x.INSTANCE=new x,W.NullLoaderEventRecorder=x})(ie||(ie={}));var ie;(function(W){class n{static fileUriToFilePath(x,A){if(A=decodeURI(A).replace(/%23/g,"#"),x){if(/^file:\/\/\//.test(A))return A.substr(8);if(/^file:\/\//.test(A))return A.substr(5)}else if(/^file:\/\//.test(A))return A.substr(7);return A}static startsWith(x,A){return x.length>=A.length&&x.substr(0,A.length)===A}static endsWith(x,A){return x.length>=A.length&&x.substr(x.length-A.length)===A}static containsQueryString(x){return/^[^\#]*\?/gi.test(x)}static isAbsolutePath(x){return/^((http:\/\/)|(https:\/\/)|(file:\/\/)|(\/))/.test(x)}static forEachProperty(x,A){if(x){let d;for(d in x)x.hasOwnProperty(d)&&A(d,x[d])}}static isEmpty(x){let A=!0;return n.forEachProperty(x,()=>{A=!1}),A}static recursiveClone(x){if(!x||typeof x!="object"||x instanceof RegExp||!Array.isArray(x)&&Object.getPrototypeOf(x)!==Object.prototype)return x;let A=Array.isArray(x)?[]:{};return n.forEachProperty(x,(d,f)=>{f&&typeof f=="object"?A[d]=n.recursiveClone(f):A[d]=f}),A}static generateAnonymousModule(){return"===anonymous"+n.NEXT_ANONYMOUS_ID+++"==="}static isAnonymousModule(x){return n.startsWith(x,"===anonymous")}static getHighPerformanceTimestamp(){return this.PERFORMANCE_NOW_PROBED||(this.PERFORMANCE_NOW_PROBED=!0,this.HAS_PERFORMANCE_NOW=W.global.performance&&typeof W.global.performance.now=="function"),this.HAS_PERFORMANCE_NOW?W.global.performance.now():Date.now()}}n.NEXT_ANONYMOUS_ID=1,n.PERFORMANCE_NOW_PROBED=!1,n.HAS_PERFORMANCE_NOW=!1,W.Utilities=n})(ie||(ie={}));var ie;(function(W){function n(A){if(A instanceof Error)return A;const d=new Error(A.message||String(A)||"Unknown Error");return A.stack&&(d.stack=A.stack),d}W.ensureError=n;class i{static validateConfigurationOptions(d){function f(p){if(p.phase==="loading"){console.error('Loading "'+p.moduleId+'" failed'),console.error(p),console.error("Here are the modules that depend on it:"),console.error(p.neededBy);return}if(p.phase==="factory"){console.error('The factory function of "'+p.moduleId+'" has thrown an exception'),console.error(p),console.error("Here are the modules that depend on it:"),console.error(p.neededBy);return}}if(d=d||{},typeof d.baseUrl!="string"&&(d.baseUrl=""),typeof d.isBuild!="boolean"&&(d.isBuild=!1),typeof d.paths!="object"&&(d.paths={}),typeof d.config!="object"&&(d.config={}),typeof d.catchError>"u"&&(d.catchError=!1),typeof d.recordStats>"u"&&(d.recordStats=!1),typeof d.urlArgs!="string"&&(d.urlArgs=""),typeof d.onError!="function"&&(d.onError=f),Array.isArray(d.ignoreDuplicateModules)||(d.ignoreDuplicateModules=[]),d.baseUrl.length>0&&(W.Utilities.endsWith(d.baseUrl,"/")||(d.baseUrl+="/")),typeof d.cspNonce!="string"&&(d.cspNonce=""),typeof d.preferScriptTags>"u"&&(d.preferScriptTags=!1),d.nodeCachedData&&typeof d.nodeCachedData=="object"&&(typeof d.nodeCachedData.seed!="string"&&(d.nodeCachedData.seed="seed"),(typeof d.nodeCachedData.writeDelay!="number"||d.nodeCachedData.writeDelay<0)&&(d.nodeCachedData.writeDelay=1e3*7),!d.nodeCachedData.path||typeof d.nodeCachedData.path!="string")){const p=n(new Error("INVALID cached data configuration, 'path' MUST be set"));p.phase="configuration",d.onError(p),d.nodeCachedData=void 0}return d}static mergeConfigurationOptions(d=null,f=null){let p=W.Utilities.recursiveClone(f||{});return W.Utilities.forEachProperty(d,(c,a)=>{c==="ignoreDuplicateModules"&&typeof p.ignoreDuplicateModules<"u"?p.ignoreDuplicateModules=p.ignoreDuplicateModules.concat(a):c==="paths"&&typeof p.paths<"u"?W.Utilities.forEachProperty(a,(m,e)=>p.paths[m]=e):c==="config"&&typeof p.config<"u"?W.Utilities.forEachProperty(a,(m,e)=>p.config[m]=e):p[c]=W.Utilities.recursiveClone(a)}),i.validateConfigurationOptions(p)}}W.ConfigurationOptionsUtil=i;class x{constructor(d,f){if(this._env=d,this.options=i.mergeConfigurationOptions(f),this._createIgnoreDuplicateModulesMap(),this._createSortedPathsRules(),this.options.baseUrl===""&&this.options.nodeRequire&&this.options.nodeRequire.main&&this.options.nodeRequire.main.filename&&this._env.isNode){let p=this.options.nodeRequire.main.filename,c=Math.max(p.lastIndexOf("/"),p.lastIndexOf("\\"));this.options.baseUrl=p.substring(0,c+1)}}_createIgnoreDuplicateModulesMap(){this.ignoreDuplicateModulesMap={};for(let d=0;d{Array.isArray(f)?this.sortedPathsRules.push({from:d,to:f}):this.sortedPathsRules.push({from:d,to:[f]})}),this.sortedPathsRules.sort((d,f)=>f.from.length-d.from.length)}cloneAndMerge(d){return new x(this._env,i.mergeConfigurationOptions(d,this.options))}getOptionsLiteral(){return this.options}_applyPaths(d){let f;for(let p=0,c=this.sortedPathsRules.length;pthis.triggerCallback(m),s=>this.triggerErrorback(m,s))}triggerCallback(a){let m=this._callbackMap[a];delete this._callbackMap[a];for(let e=0;e{a.removeEventListener("load",r),a.removeEventListener("error",s)},r=o=>{h(),m()},s=o=>{h(),e(o)};a.addEventListener("load",r),a.addEventListener("error",s)}load(a,m,e,h){if(/^node\|/.test(m)){let r=a.getConfig().getOptionsLiteral(),s=f(a.getRecorder(),r.nodeRequire||W.global.nodeRequire),o=m.split("|"),u=null;try{u=s(o[1])}catch(S){h(S);return}a.enqueueDefineAnonymousModule([],()=>u),e()}else{let r=document.createElement("script");r.setAttribute("async","async"),r.setAttribute("type","text/javascript"),this.attachListeners(r,e,h);const{trustedTypesPolicy:s}=a.getConfig().getOptionsLiteral();s&&(m=s.createScriptURL(m)),r.setAttribute("src",m);const{cspNonce:o}=a.getConfig().getOptionsLiteral();o&&r.setAttribute("nonce",o),document.getElementsByTagName("head")[0].appendChild(r)}}}function x(c){const{trustedTypesPolicy:a}=c.getConfig().getOptionsLiteral();try{return(a?self.eval(a.createScript("","true")):new Function("true")).call(self),!0}catch{return!1}}class A{constructor(){this._cachedCanUseEval=null}_canUseEval(a){return this._cachedCanUseEval===null&&(this._cachedCanUseEval=x(a)),this._cachedCanUseEval}load(a,m,e,h){if(/^node\|/.test(m)){const r=a.getConfig().getOptionsLiteral(),s=f(a.getRecorder(),r.nodeRequire||W.global.nodeRequire),o=m.split("|");let u=null;try{u=s(o[1])}catch(S){h(S);return}a.enqueueDefineAnonymousModule([],function(){return u}),e()}else{const{trustedTypesPolicy:r}=a.getConfig().getOptionsLiteral();if(!(/^((http:)|(https:)|(file:))/.test(m)&&m.substring(0,self.origin.length)!==self.origin)&&this._canUseEval(a)){fetch(m).then(o=>{if(o.status!==200)throw new Error(o.statusText);return o.text()}).then(o=>{o=`${o} //# sourceURL=${m}`,(r?self.eval(r.createScript("",o)):new Function(o)).call(self),e()}).then(void 0,h);return}try{r&&(m=r.createScriptURL(m)),importScripts(m),e()}catch(o){h(o)}}}}class d{constructor(a){this._env=a,this._didInitialize=!1,this._didPatchNodeRequire=!1}_init(a){this._didInitialize||(this._didInitialize=!0,this._fs=a("fs"),this._vm=a("vm"),this._path=a("path"),this._crypto=a("crypto"))}_initNodeRequire(a,m){const{nodeCachedData:e}=m.getConfig().getOptionsLiteral();if(!e||this._didPatchNodeRequire)return;this._didPatchNodeRequire=!0;const h=this,r=a("module");function s(o){const u=o.constructor;let S=function(N){try{return o.require(N)}finally{}};return S.resolve=function(N,P){return u._resolveFilename(N,o,!1,P)},S.resolve.paths=function(N){return u._resolveLookupPaths(N,o)},S.main=process.mainModule,S.extensions=u._extensions,S.cache=u._cache,S}r.prototype._compile=function(o,u){const S=r.wrap(o.replace(/^#!.*/,"")),L=m.getRecorder(),N=h._getCachedDataPath(e,u),P={filename:u};let E;try{const y=h._fs.readFileSync(N);E=y.slice(0,16),P.cachedData=y.slice(16),L.record(60,N)}catch{L.record(61,N)}const v=new h._vm.Script(S,P),l=v.runInThisContext(P),b=h._path.dirname(u),g=s(this),w=[this.exports,g,this,u,b,process,Me,Buffer],M=l.apply(this.exports,w);return h._handleCachedData(v,S,N,!P.cachedData,m),h._verifyCachedData(v,S,N,E,m),M}}load(a,m,e,h){const r=a.getConfig().getOptionsLiteral(),s=f(a.getRecorder(),r.nodeRequire||W.global.nodeRequire),o=r.nodeInstrumenter||function(S){return S};this._init(s),this._initNodeRequire(s,a);let u=a.getRecorder();if(/^node\|/.test(m)){let S=m.split("|"),L=null;try{L=s(S[1])}catch(N){h(N);return}a.enqueueDefineAnonymousModule([],()=>L),e()}else{m=W.Utilities.fileUriToFilePath(this._env.isWindows,m);const S=this._path.normalize(m),L=this._getElectronRendererScriptPathOrUri(S),N=!!r.nodeCachedData,P=N?this._getCachedDataPath(r.nodeCachedData,m):void 0;this._readSourceAndCachedData(S,P,u,(E,v,l,b)=>{if(E){h(E);return}let g;v.charCodeAt(0)===d._BOM?g=d._PREFIX+v.substring(1)+d._SUFFIX:g=d._PREFIX+v+d._SUFFIX,g=o(g,S);const w={filename:L,cachedData:l},M=this._createAndEvalScript(a,g,w,e,h);this._handleCachedData(M,g,P,N&&!l,a),this._verifyCachedData(M,g,P,b,a)})}}_createAndEvalScript(a,m,e,h,r){const s=a.getRecorder();s.record(31,e.filename);const o=new this._vm.Script(m,e),u=o.runInThisContext(e),S=a.getGlobalAMDDefineFunc();let L=!1;const N=function(){return L=!0,S.apply(null,arguments)};return N.amd=S.amd,u.call(W.global,a.getGlobalAMDRequireFunc(),N,e.filename,this._path.dirname(e.filename)),s.record(32,e.filename),L?h():r(new Error(`Didn't receive define call in ${e.filename}!`)),o}_getElectronRendererScriptPathOrUri(a){if(!this._env.isElectronRenderer)return a;let m=a.match(/^([a-z])\:(.*)/i);return m?`file:///${(m[1].toUpperCase()+":"+m[2]).replace(/\\/g,"/")}`:`file://${a}`}_getCachedDataPath(a,m){const e=this._crypto.createHash("md5").update(m,"utf8").update(a.seed,"utf8").update(process.arch,"").digest("hex"),h=this._path.basename(m).replace(/\.js$/,"");return this._path.join(a.path,`${h}-${e}.code`)}_handleCachedData(a,m,e,h,r){a.cachedDataRejected?this._fs.unlink(e,s=>{r.getRecorder().record(62,e),this._createAndWriteCachedData(a,m,e,r),s&&r.getConfig().onError(s)}):h&&this._createAndWriteCachedData(a,m,e,r)}_createAndWriteCachedData(a,m,e,h){let r=Math.ceil(h.getConfig().getOptionsLiteral().nodeCachedData.writeDelay*(1+Math.random())),s=-1,o=0,u;const S=()=>{setTimeout(()=>{u||(u=this._crypto.createHash("md5").update(m,"utf8").digest());const L=a.createCachedData();if(!(L.length===0||L.length===s||o>=5)){if(L.length{N&&h.getConfig().onError(N),h.getRecorder().record(63,e),S()})}},r*Math.pow(4,o++))};S()}_readSourceAndCachedData(a,m,e,h){if(!m)this._fs.readFile(a,{encoding:"utf8"},h);else{let r,s,o,u=2;const S=L=>{L?h(L):--u===0&&h(void 0,r,s,o)};this._fs.readFile(a,{encoding:"utf8"},(L,N)=>{r=N,S(L)}),this._fs.readFile(m,(L,N)=>{!L&&N&&N.length>0?(o=N.slice(0,16),s=N.slice(16),e.record(60,m)):e.record(61,m),S()})}}_verifyCachedData(a,m,e,h,r){h&&(a.cachedDataRejected||setTimeout(()=>{const s=this._crypto.createHash("md5").update(m,"utf8").digest();h.equals(s)||(r.getConfig().onError(new Error(`FAILED TO VERIFY CACHED DATA, deleting stale '${e}' now, but a RESTART IS REQUIRED`)),this._fs.unlink(e,o=>{o&&r.getConfig().onError(o)}))},Math.ceil(5e3*(1+Math.random()))))}}d._BOM=65279,d._PREFIX="(function (require, define, __filename, __dirname) { ",d._SUFFIX=` });`;function f(c,a){if(a.__$__isRecorded)return a;const m=function(h){c.record(33,h);try{return a(h)}finally{c.record(34,h)}};return m.__$__isRecorded=!0,m}W.ensureRecordedNodeRequire=f;function p(c){return new n(c)}W.createScriptLoader=p})(ie||(ie={}));var ie;(function(W){class n{constructor(c){let a=c.lastIndexOf("/");a!==-1?this.fromModulePath=c.substr(0,a+1):this.fromModulePath=""}static _normalizeModuleId(c){let a=c,m;for(m=/\/\.\//;m.test(a);)a=a.replace(m,"/");for(a=a.replace(/^\.\//g,""),m=/\/(([^\/])|([^\/][^\/\.])|([^\/\.][^\/])|([^\/][^\/][^\/]+))\/\.\.\//;m.test(a);)a=a.replace(m,"/");return a=a.replace(/^(([^\/])|([^\/][^\/\.])|([^\/\.][^\/])|([^\/][^\/][^\/]+))\/\.\.\//,""),a}resolveModule(c){let a=c;return W.Utilities.isAbsolutePath(a)||(W.Utilities.startsWith(a,"./")||W.Utilities.startsWith(a,"../"))&&(a=n._normalizeModuleId(this.fromModulePath+a)),a}}n.ROOT=new n(""),W.ModuleIdResolver=n;class i{constructor(c,a,m,e,h,r){this.id=c,this.strId=a,this.dependencies=m,this._callback=e,this._errorback=h,this.moduleIdResolver=r,this.exports={},this.error=null,this.exportsPassedIn=!1,this.unresolvedDependenciesCount=this.dependencies.length,this._isComplete=!1}static _safeInvokeFunction(c,a){try{return{returnedValue:c.apply(W.global,a),producedError:null}}catch(m){return{returnedValue:null,producedError:m}}}static _invokeFactory(c,a,m,e){return c.shouldInvokeFactory(a)?c.shouldCatchError()?this._safeInvokeFunction(m,e):{returnedValue:m.apply(W.global,e),producedError:null}:{returnedValue:null,producedError:null}}complete(c,a,m,e){this._isComplete=!0;let h=null;if(this._callback)if(typeof this._callback=="function"){c.record(21,this.strId);let r=i._invokeFactory(a,this.strId,this._callback,m);h=r.producedError,c.record(22,this.strId),!h&&typeof r.returnedValue<"u"&&(!this.exportsPassedIn||W.Utilities.isEmpty(this.exports))&&(this.exports=r.returnedValue)}else this.exports=this._callback;if(h){let r=W.ensureError(h);r.phase="factory",r.moduleId=this.strId,r.neededBy=e(this.id),this.error=r,a.onError(r)}this.dependencies=null,this._callback=null,this._errorback=null,this.moduleIdResolver=null}onDependencyError(c){return this._isComplete=!0,this.error=c,this._errorback?(this._errorback(c),!0):!1}isComplete(){return this._isComplete}}W.Module=i;class x{constructor(){this._nextId=0,this._strModuleIdToIntModuleId=new Map,this._intModuleIdToStrModuleId=[],this.getModuleId("exports"),this.getModuleId("module"),this.getModuleId("require")}getMaxModuleId(){return this._nextId}getModuleId(c){let a=this._strModuleIdToIntModuleId.get(c);return typeof a>"u"&&(a=this._nextId++,this._strModuleIdToIntModuleId.set(c,a),this._intModuleIdToStrModuleId[a]=c),a}getStrModuleId(c){return this._intModuleIdToStrModuleId[c]}}class A{constructor(c){this.id=c}}A.EXPORTS=new A(0),A.MODULE=new A(1),A.REQUIRE=new A(2),W.RegularDependency=A;class d{constructor(c,a,m){this.id=c,this.pluginId=a,this.pluginParam=m}}W.PluginDependency=d;class f{constructor(c,a,m,e,h=0){this._env=c,this._scriptLoader=a,this._loaderAvailableTimestamp=h,this._defineFunc=m,this._requireFunc=e,this._moduleIdProvider=new x,this._config=new W.Configuration(this._env),this._hasDependencyCycle=!1,this._modules2=[],this._knownModules2=[],this._inverseDependencies2=[],this._inversePluginDependencies2=new Map,this._currentAnonymousDefineCall=null,this._recorder=null,this._buildInfoPath=[],this._buildInfoDefineStack=[],this._buildInfoDependencies=[],this._requireFunc.moduleManager=this}reset(){return new f(this._env,this._scriptLoader,this._defineFunc,this._requireFunc,this._loaderAvailableTimestamp)}getGlobalAMDDefineFunc(){return this._defineFunc}getGlobalAMDRequireFunc(){return this._requireFunc}static _findRelevantLocationInStack(c,a){let m=r=>r.replace(/\\/g,"/"),e=m(c),h=a.split(/\n/);for(let r=0;rthis._moduleIdProvider.getStrModuleId(u.id))),this._resolve(o)}_normalizeDependency(c,a){if(c==="exports")return A.EXPORTS;if(c==="module")return A.MODULE;if(c==="require")return A.REQUIRE;let m=c.indexOf("!");if(m>=0){let e=a.resolveModule(c.substr(0,m)),h=a.resolveModule(c.substr(m+1)),r=this._moduleIdProvider.getModuleId(e+"!"+h),s=this._moduleIdProvider.getModuleId(e);return new d(r,s,h)}return new A(this._moduleIdProvider.getModuleId(a.resolveModule(c)))}_normalizeDependencies(c,a){let m=[],e=0;for(let h=0,r=c.length;hthis._moduleIdProvider.getStrModuleId(r));const h=W.ensureError(a);return h.phase="loading",h.moduleId=m,h.neededBy=e,h}_onLoadError(c,a){const m=this._createLoadError(c,a);this._modules2[c]||(this._modules2[c]=new i(c,this._moduleIdProvider.getStrModuleId(c),[],()=>{},null,null));let e=[];for(let s=0,o=this._moduleIdProvider.getMaxModuleId();s0;){let s=r.shift(),o=this._modules2[s];o&&(h=o.onDependencyError(m)||h);let u=this._inverseDependencies2[s];if(u)for(let S=0,L=u.length;S0;){let s=h.shift().dependencies;if(s)for(let o=0,u=s.length;othis._relativeRequire(c,m,e,h);return a.toUrl=m=>this._config.requireToUrl(c.resolveModule(m)),a.getStats=()=>this.getLoaderEvents(),a.hasDependencyCycle=()=>this._hasDependencyCycle,a.config=(m,e=!1)=>{this.configure(m,e)},a.__$__nodeRequire=W.global.nodeRequire,a}_loadModule(c){if(this._modules2[c]||this._knownModules2[c])return;this._knownModules2[c]=!0;let a=this._moduleIdProvider.getStrModuleId(c),m=this._config.moduleIdToPaths(a),e=/^@[^\/]+\/[^\/]+$/;this._env.isNode&&(a.indexOf("/")===-1||e.test(a))&&m.push("node|"+a);let h=-1,r=s=>{if(h++,h>=m.length)this._onLoadError(c,s);else{let o=m[h],u=this.getRecorder();if(this._config.isBuild()&&o==="empty:"){this._buildInfoPath[c]=o,this.defineModule(this._moduleIdProvider.getStrModuleId(c),[],null,null,null),this._onLoad(c);return}u.record(10,o),this._scriptLoader.load(this,o,()=>{this._config.isBuild()&&(this._buildInfoPath[c]=o),u.record(11,o),this._onLoad(c)},S=>{u.record(12,o),r(S)})}};r(null)}_loadPluginDependency(c,a){if(this._modules2[a.id]||this._knownModules2[a.id])return;this._knownModules2[a.id]=!0;let m=e=>{this.defineModule(this._moduleIdProvider.getStrModuleId(a.id),[],e,null,null)};m.error=e=>{this._config.onError(this._createLoadError(a.id,e))},c.load(a.pluginParam,this._createRequire(n.ROOT),m,this._config.getOptionsLiteral())}_resolve(c){let a=c.dependencies;if(a)for(let m=0,e=a.length;mthis._moduleIdProvider.getStrModuleId(o)).join(` => `)),c.unresolvedDependenciesCount--;continue}if(this._inverseDependencies2[h.id]=this._inverseDependencies2[h.id]||[],this._inverseDependencies2[h.id].push(c.id),h instanceof d){let s=this._modules2[h.pluginId];if(s&&s.isComplete()){this._loadPluginDependency(s.exports,h);continue}let o=this._inversePluginDependencies2.get(h.pluginId);o||(o=[],this._inversePluginDependencies2.set(h.pluginId,o)),o.push(h),this._loadModule(h.pluginId);continue}this._loadModule(h.id)}c.unresolvedDependenciesCount===0&&this._onModuleComplete(c)}_onModuleComplete(c){let a=this.getRecorder();if(c.isComplete())return;let m=c.dependencies,e=[];if(m)for(let o=0,u=m.length;othis._config.getConfigForModule(c.strId)};continue}if(S===A.REQUIRE){e[o]=this._createRequire(c.moduleIdResolver);continue}let L=this._modules2[S.id];if(L){e[o]=L.exports;continue}e[o]=null}const h=o=>(this._inverseDependencies2[o]||[]).map(u=>this._moduleIdProvider.getStrModuleId(u));c.complete(a,this._config,e,h);let r=this._inverseDependencies2[c.id];if(this._inverseDependencies2[c.id]=null,r)for(let o=0,u=r.length;o"u"&&f())})(ie||(ie={})),function(){const W=globalThis.MonacoEnvironment,n=W&&W.baseUrl?W.baseUrl:"../../../";function i(e,h){if(W?.createTrustedTypesPolicy)try{return W.createTrustedTypesPolicy(e,h)}catch(r){console.warn(r);return}try{return self.trustedTypes?.createPolicy(e,h)}catch(r){console.warn(r);return}}const x=i("amdLoader",{createScriptURL:e=>e,createScript:(e,...h)=>{const r=h.slice(0,-1).join(","),s=h.pop().toString();return`(function anonymous(${r}) { ${s} })`}});function A(){try{return(x?globalThis.eval(x.createScript("","true")):new Function("true")).call(globalThis),!0}catch{return!1}}function d(){return new Promise((e,h)=>{if(typeof globalThis.define=="function"&&globalThis.define.amd)return e();const r=n+"vs/loader.js";if(!(/^((http:)|(https:)|(file:))/.test(r)&&r.substring(0,globalThis.origin.length)!==globalThis.origin)&&A()){fetch(r).then(o=>{if(o.status!==200)throw new Error(o.statusText);return o.text()}).then(o=>{o=`${o} //# sourceURL=${r}`,(x?globalThis.eval(x.createScript("",o)):new Function(o)).call(globalThis),e()}).then(void 0,h);return}x?importScripts(x.createScriptURL(r)):importScripts(r),e()})}function f(){require.config({baseUrl:n,catchError:!0,trustedTypesPolicy:x,amdModulesPattern:/^vs\//})}function p(e){return d().then(()=>(f(),new Promise((h,r)=>{require([e],h,r)})))}function c(e){setTimeout(function(){const h=e.create((r,s)=>{globalThis.postMessage(r,s)});for(self.onmessage=r=>h.onmessage(r.data,r.ports);m.length>0;)self.onmessage(m.shift())},0)}typeof globalThis.define=="function"&&globalThis.define.amd&&f();let a=!0;const m=[];globalThis.onmessage=e=>{if(!a){m.push(e);return}a=!1,p(e.data).then(h=>{c(h)},h=>{console.error(h)})}}(),X(J[7],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.Permutation=n.CallbackIterable=n.ArrayQueue=n.booleanComparator=n.numberComparator=n.CompareResult=void 0,n.tail=i,n.tail2=x,n.equals=A,n.removeFastWithoutKeepingOrder=d,n.binarySearch=f,n.binarySearch2=p,n.quickSelect=c,n.groupBy=a,n.groupAdjacentBy=m,n.forEachAdjacent=e,n.forEachWithNeighbors=h,n.coalesce=r,n.coalesceInPlace=s,n.isFalsyOrEmpty=o,n.isNonEmptyArray=u,n.distinct=S,n.firstOrDefault=L,n.range=N,n.arrayInsert=P,n.pushToStart=E,n.pushToEnd=v,n.pushMany=l,n.asArray=b,n.insertInto=g,n.splice=w,n.compareBy=_,n.tieBreakComparators=C,n.reverseOrder=T;function i(F,q=0){return F[F.length-(1+q)]}function x(F){if(F.length===0)throw new Error("Invalid tail call");return[F.slice(0,F.length-1),F[F.length-1]]}function A(F,q,B=(G,$)=>G===$){if(F===q)return!0;if(!F||!q||F.length!==q.length)return!1;for(let G=0,$=F.length;G<$;G++)if(!B(F[G],q[G]))return!1;return!0}function d(F,q){const B=F.length-1;qB(F[G],q))}function p(F,q){let B=0,G=F-1;for(;B<=G;){const $=(B+G)/2|0,U=q($);if(U<0)B=$+1;else if(U>0)G=$-1;else return $}return-(B+1)}function c(F,q,B){if(F=F|0,F>=q.length)throw new TypeError("invalid index");const G=q[Math.floor(q.length*Math.random())],$=[],U=[],ee=[];for(const re of q){const ue=B(re,G);ue<0?$.push(re):ue>0?U.push(re):ee.push(re)}return F<$.length?c(F,$,B):F<$.length+ee.length?ee[0]:c(F-($.length+ee.length),U,B)}function a(F,q){const B=[];let G;for(const $ of F.slice(0).sort(q))!G||q(G[0],$)!==0?(G=[$],B.push(G)):G.push($);return B}function*m(F,q){let B,G;for(const $ of F)G!==void 0&&q(G,$)?B.push($):(B&&(yield B),B=[$]),G=$;B&&(yield B)}function e(F,q){for(let B=0;B<=F.length;B++)q(B===0?void 0:F[B-1],B===F.length?void 0:F[B])}function h(F,q){for(let B=0;B!!q)}function s(F){let q=0;for(let B=0;B0}function S(F,q=B=>B){const B=new Set;return F.filter(G=>{const $=q(G);return B.has($)?!1:(B.add($),!0)})}function L(F,q){return F.length>0?F[0]:q}function N(F,q){let B=typeof q=="number"?F:0;typeof q=="number"?B=F:(B=0,q=F);const G=[];if(B<=q)for(let $=B;$q;$--)G.push($);return G}function P(F,q,B){const G=F.slice(0,q),$=F.slice(q);return G.concat(B,$)}function E(F,q){const B=F.indexOf(q);B>-1&&(F.splice(B,1),F.unshift(q))}function v(F,q){const B=F.indexOf(q);B>-1&&(F.splice(B,1),F.push(q))}function l(F,q){for(const B of q)F.push(B)}function b(F){return Array.isArray(F)?F:[F]}function g(F,q,B){const G=M(F,q),$=F.length,U=B.length;F.length=$+U;for(let ee=$-1;ee>=G;ee--)F[ee+U]=F[ee];for(let ee=0;ee0}F.isGreaterThan=G;function $(U){return U===0}F.isNeitherLessOrGreaterThan=$,F.greaterThan=1,F.lessThan=-1,F.neitherLessOrGreaterThan=0})(y||(n.CompareResult=y={}));function _(F,q){return(B,G)=>q(F(B),F(G))}function C(...F){return(q,B)=>{for(const G of F){const $=G(q,B);if(!y.isNeitherLessOrGreaterThan($))return $}return y.neitherLessOrGreaterThan}}const R=(F,q)=>F-q;n.numberComparator=R;const D=(F,q)=>(0,n.numberComparator)(F?1:0,q?1:0);n.booleanComparator=D;function T(F){return(q,B)=>-F(q,B)}class O{constructor(q){this.items=q,this.firstIdx=0,this.lastIdx=this.items.length-1}get length(){return this.lastIdx-this.firstIdx+1}takeWhile(q){let B=this.firstIdx;for(;B=0&&q(this.items[B]);)B--;const G=B===this.lastIdx?null:this.items.slice(B+1,this.lastIdx+1);return this.lastIdx=B,G}peek(){if(this.length!==0)return this.items[this.firstIdx]}dequeue(){const q=this.items[this.firstIdx];return this.firstIdx++,q}takeCount(q){const B=this.items.slice(this.firstIdx,this.firstIdx+q);return this.firstIdx+=q,B}}n.ArrayQueue=O;class z{static{this.empty=new z(q=>{})}constructor(q){this.iterate=q}toArray(){const q=[];return this.iterate(B=>(q.push(B),!0)),q}filter(q){return new z(B=>this.iterate(G=>q(G)?B(G):!0))}map(q){return new z(B=>this.iterate(G=>B(q(G))))}findLast(q){let B;return this.iterate(G=>(q(G)&&(B=G),!0)),B}findLastMaxBy(q){let B,G=!0;return this.iterate($=>((G||y.isGreaterThan(q($,B)))&&(G=!1,B=$),!0)),B}}n.CallbackIterable=z;class j{constructor(q){this._indexMap=q}static createSortPermutation(q,B){const G=Array.from(q.keys()).sort(($,U)=>B(q[$],q[U]));return new j(G)}apply(q){return q.map((B,G)=>q[this._indexMap[G]])}inverse(){const q=this._indexMap.slice();for(let B=0;B=0;S--){const L=s[S];if(o(L))return S}return-1}function A(s,o){const u=d(s,o);return u===-1?void 0:s[u]}function d(s,o,u=0,S=s.length){let L=u,N=S;for(;L0&&(u=L)}return u}function m(s,o){if(s.length===0)return;let u=s[0];for(let S=1;S=0&&(u=L)}return u}function e(s,o){return a(s,(u,S)=>-o(u,S))}function h(s,o){if(s.length===0)return-1;let u=0;for(let S=1;S0&&(u=S)}return u}function r(s,o){for(const u of s){const S=o(u);if(S!==void 0)return S}}}),X(J[39],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.CachedFunction=n.LRUCachedFunction=void 0,n.identity=i;function i(d){return d}class x{constructor(f,p){this.lastCache=void 0,this.lastArgKey=void 0,typeof f=="function"?(this._fn=f,this._computeKey=i):(this._fn=p,this._computeKey=f.getCacheKey)}get(f){const p=this._computeKey(f);return this.lastArgKey!==p&&(this.lastArgKey=p,this.lastCache=this._fn(f)),this.lastCache}}n.LRUCachedFunction=x;class A{get cachedValues(){return this._map}constructor(f,p){this._map=new Map,this._map2=new Map,typeof f=="function"?(this._fn=f,this._computeKey=i):(this._fn=p,this._computeKey=f.getCacheKey)}get(f){const p=this._computeKey(f);if(this._map2.has(p))return this._map2.get(p);const c=this._fn(f);return this._map.set(f,c),this._map2.set(p,c),c}}n.CachedFunction=A}),X(J[40],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.Color=n.HSVA=n.HSLA=n.RGBA=void 0;function i(p,c){const a=Math.pow(10,c);return Math.round(p*a)/a}class x{constructor(c,a,m,e=1){this._rgbaBrand=void 0,this.r=Math.min(255,Math.max(0,c))|0,this.g=Math.min(255,Math.max(0,a))|0,this.b=Math.min(255,Math.max(0,m))|0,this.a=i(Math.max(Math.min(1,e),0),3)}static equals(c,a){return c.r===a.r&&c.g===a.g&&c.b===a.b&&c.a===a.a}}n.RGBA=x;class A{constructor(c,a,m,e){this._hslaBrand=void 0,this.h=Math.max(Math.min(360,c),0)|0,this.s=i(Math.max(Math.min(1,a),0),3),this.l=i(Math.max(Math.min(1,m),0),3),this.a=i(Math.max(Math.min(1,e),0),3)}static equals(c,a){return c.h===a.h&&c.s===a.s&&c.l===a.l&&c.a===a.a}static fromRGBA(c){const a=c.r/255,m=c.g/255,e=c.b/255,h=c.a,r=Math.max(a,m,e),s=Math.min(a,m,e);let o=0,u=0;const S=(s+r)/2,L=r-s;if(L>0){switch(u=Math.min(S<=.5?L/(2*S):L/(2-2*S),1),r){case a:o=(m-e)/L+(m1&&(m-=1),m<1/6?c+(a-c)*6*m:m<1/2?a:m<2/3?c+(a-c)*(2/3-m)*6:c}static toRGBA(c){const a=c.h/360,{s:m,l:e,a:h}=c;let r,s,o;if(m===0)r=s=o=e;else{const u=e<.5?e*(1+m):e+m-e*m,S=2*e-u;r=A._hue2rgb(S,u,a+1/3),s=A._hue2rgb(S,u,a),o=A._hue2rgb(S,u,a-1/3)}return new x(Math.round(r*255),Math.round(s*255),Math.round(o*255),h)}}n.HSLA=A;class d{constructor(c,a,m,e){this._hsvaBrand=void 0,this.h=Math.max(Math.min(360,c),0)|0,this.s=i(Math.max(Math.min(1,a),0),3),this.v=i(Math.max(Math.min(1,m),0),3),this.a=i(Math.max(Math.min(1,e),0),3)}static equals(c,a){return c.h===a.h&&c.s===a.s&&c.v===a.v&&c.a===a.a}static fromRGBA(c){const a=c.r/255,m=c.g/255,e=c.b/255,h=Math.max(a,m,e),r=Math.min(a,m,e),s=h-r,o=h===0?0:s/h;let u;return s===0?u=0:h===a?u=((m-e)/s%6+6)%6:h===m?u=(e-a)/s+2:u=(a-m)/s+4,new d(Math.round(u*60),o,h,c.a)}static toRGBA(c){const{h:a,s:m,v:e,a:h}=c,r=e*m,s=r*(1-Math.abs(a/60%2-1)),o=e-r;let[u,S,L]=[0,0,0];return a<60?(u=r,S=s):a<120?(u=s,S=r):a<180?(S=r,L=s):a<240?(S=s,L=r):a<300?(u=s,L=r):a<=360&&(u=r,L=s),u=Math.round((u+o)*255),S=Math.round((S+o)*255),L=Math.round((L+o)*255),new x(u,S,L,h)}}n.HSVA=d;class f{static fromHex(c){return f.Format.CSS.parseHex(c)||f.red}static equals(c,a){return!c&&!a?!0:!c||!a?!1:c.equals(a)}get hsla(){return this._hsla?this._hsla:A.fromRGBA(this.rgba)}get hsva(){return this._hsva?this._hsva:d.fromRGBA(this.rgba)}constructor(c){if(c)if(c instanceof x)this.rgba=c;else if(c instanceof A)this._hsla=c,this.rgba=A.toRGBA(c);else if(c instanceof d)this._hsva=c,this.rgba=d.toRGBA(c);else throw new Error("Invalid color ctor argument");else throw new Error("Color needs a value")}equals(c){return!!c&&x.equals(this.rgba,c.rgba)&&A.equals(this.hsla,c.hsla)&&d.equals(this.hsva,c.hsva)}getRelativeLuminance(){const c=f._relativeLuminanceForComponent(this.rgba.r),a=f._relativeLuminanceForComponent(this.rgba.g),m=f._relativeLuminanceForComponent(this.rgba.b),e=.2126*c+.7152*a+.0722*m;return i(e,4)}static _relativeLuminanceForComponent(c){const a=c/255;return a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)}isLighter(){return(this.rgba.r*299+this.rgba.g*587+this.rgba.b*114)/1e3>=128}isLighterThan(c){const a=this.getRelativeLuminance(),m=c.getRelativeLuminance();return a>m}isDarkerThan(c){const a=this.getRelativeLuminance(),m=c.getRelativeLuminance();return a{throw u.stack?r.isErrorNoTelemetry(u)?new r(u.message+` `+u.stack):new Error(u.message+` `+u.stack):u},0)}}emit(u){this.listeners.forEach(S=>{S(u)})}onUnexpectedError(u){this.unexpectedErrorHandler(u),this.emit(u)}onUnexpectedExternalError(u){this.unexpectedErrorHandler(u)}}n.ErrorHandler=i,n.errorHandler=new i;function x(o){p(o)||n.errorHandler.onUnexpectedError(o)}function A(o){p(o)||n.errorHandler.onUnexpectedExternalError(o)}function d(o){if(o instanceof Error){const{name:u,message:S}=o,L=o.stacktrace||o.stack;return{$isError:!0,name:u,message:S,stack:L,noTelemetry:r.isErrorNoTelemetry(o)}}return o}const f="Canceled";function p(o){return o instanceof c?!0:o instanceof Error&&o.name===f&&o.message===f}class c extends Error{constructor(){super(f),this.name=this.message}}n.CancellationError=c;function a(){const o=new Error(f);return o.name=o.message,o}function m(o){return o?new Error(`Illegal argument: ${o}`):new Error("Illegal argument")}function e(o){return o?new Error(`Illegal state: ${o}`):new Error("Illegal state")}class h extends Error{constructor(u){super("NotSupported"),u&&(this.message=u)}}n.NotSupportedError=h;class r extends Error{constructor(u){super(u),this.name="CodeExpectedError"}static fromError(u){if(u instanceof r)return u;const S=new r;return S.message=u.message,S.stack=u.stack,S}static isErrorNoTelemetry(u){return u.name==="CodeExpectedError"}}n.ErrorNoTelemetry=r;class s extends Error{constructor(u){super(u||"An unexpected bug occurred."),Object.setPrototypeOf(this,s.prototype)}}n.BugIndicatingError=s}),X(J[12],Z([0,1,3]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.ok=x,n.assertNever=A,n.softAssert=d,n.assertFn=f,n.checkAdjacentItems=p;function x(c,a){if(!c)throw new Error(a?`Assertion failed (${a})`:"Assertion Failed")}function A(c,a="Unreachable"){throw new Error(a)}function d(c){c||(0,i.onUnexpectedError)(new i.BugIndicatingError("Soft Assertion Failed"))}function f(c){if(!c()){debugger;c(),(0,i.onUnexpectedError)(new i.BugIndicatingError("Assertion Failed"))}}function p(c,a){let m=0;for(;m=0;b--)yield l[b]}x.reverse=m;function e(l){return!l||l[Symbol.iterator]().next().done===!0}x.isEmpty=e;function h(l){return l[Symbol.iterator]().next().value}x.first=h;function r(l,b){let g=0;for(const w of l)if(b(w,g++))return!0;return!1}x.some=r;function s(l,b){for(const g of l)if(b(g))return g}x.find=s;function*o(l,b){for(const g of l)b(g)&&(yield g)}x.filter=o;function*u(l,b){let g=0;for(const w of l)yield b(w,g++)}x.map=u;function*S(l,b){let g=0;for(const w of l)yield*b(w,g++)}x.flatMap=S;function*L(...l){for(const b of l)yield*b}x.concat=L;function N(l,b,g){let w=g;for(const M of l)w=b(w,M);return w}x.reduce=N;function*P(l,b,g=l.length){for(b<0&&(b+=l.length),g<0?g+=l.length:g>l.length&&(g=l.length);b=98&&L<=113)return null;switch(L){case 16:return"Up";case 18:return"Down";case 15:return"Left";case 17:return"Right"}return x.keyCodeToStr(L)}e.toElectronAccelerator=S})(a||(n.KeyCodeUtils=a={}));function m(e,h){const r=(h&65535)<<16>>>0;return(e|r)>>>0}}),X(J[43],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.Lazy=void 0;class i{constructor(A){this.executor=A,this._didRun=!1}get value(){if(!this._didRun)try{this._value=this.executor()}catch(A){this._error=A}finally{this._didRun=!0}if(this._error)throw this._error;return this._value}get rawValue(){return this._value}}n.Lazy=i}),X(J[8],Z([0,1,18,19]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.DisposableMap=n.ImmortalReference=n.RefCountedDisposable=n.MutableDisposable=n.Disposable=n.DisposableStore=void 0,n.setDisposableTracker=f,n.trackDisposable=p,n.markAsDisposed=c,n.markAsSingleton=e,n.isDisposable=h,n.dispose=r,n.combinedDisposable=s,n.toDisposable=o;const A=!1;let d=null;function f(v){d=v}if(A){const v="__is_disposable_tracked__";f(new class{trackDisposable(l){const b=new Error("Potentially leaked disposable").stack;setTimeout(()=>{l[v]||console.log(b)},3e3)}setParent(l,b){if(l&&l!==S.None)try{l[v]=!0}catch{}}markAsDisposed(l){if(l&&l!==S.None)try{l[v]=!0}catch{}}markAsSingleton(l){}})}function p(v){return d?.trackDisposable(v),v}function c(v){d?.markAsDisposed(v)}function a(v,l){d?.setParent(v,l)}function m(v,l){if(d)for(const b of v)d.setParent(b,l)}function e(v){return d?.markAsSingleton(v),v}function h(v){return typeof v=="object"&&v!==null&&typeof v.dispose=="function"&&v.dispose.length===0}function r(v){if(x.Iterable.is(v)){const l=[];for(const b of v)if(b)try{b.dispose()}catch(g){l.push(g)}if(l.length===1)throw l[0];if(l.length>1)throw new AggregateError(l,"Encountered errors while disposing of store");return Array.isArray(v)?[]:v}else if(v)return v.dispose(),v}function s(...v){const l=o(()=>r(v));return m(v,l),l}function o(v){const l=p({dispose:(0,i.createSingleCallFunction)(()=>{c(l),v()})});return l}class u{static{this.DISABLE_DISPOSED_WARNING=!1}constructor(){this._toDispose=new Set,this._isDisposed=!1,p(this)}dispose(){this._isDisposed||(c(this),this._isDisposed=!0,this.clear())}get isDisposed(){return this._isDisposed}clear(){if(this._toDispose.size!==0)try{r(this._toDispose)}finally{this._toDispose.clear()}}add(l){if(!l)return l;if(l===this)throw new Error("Cannot register a disposable on itself!");return a(l,this),this._isDisposed?u.DISABLE_DISPOSED_WARNING||console.warn(new Error("Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!").stack):this._toDispose.add(l),l}deleteAndLeak(l){l&&this._toDispose.has(l)&&(this._toDispose.delete(l),a(l,null))}}n.DisposableStore=u;class S{static{this.None=Object.freeze({dispose(){}})}constructor(){this._store=new u,p(this),a(this._store,this)}dispose(){c(this),this._store.dispose()}_register(l){if(l===this)throw new Error("Cannot register a disposable on itself!");return this._store.add(l)}}n.Disposable=S;class L{constructor(){this._isDisposed=!1,p(this)}get value(){return this._isDisposed?void 0:this._value}set value(l){this._isDisposed||l===this._value||(this._value?.dispose(),l&&a(l,this),this._value=l)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,c(this),this._value?.dispose(),this._value=void 0}}n.MutableDisposable=L;class N{constructor(l){this._disposable=l,this._counter=1}acquire(){return this._counter++,this}release(){return--this._counter===0&&this._disposable.dispose(),this}}n.RefCountedDisposable=N;class P{constructor(l){this.object=l}dispose(){}}n.ImmortalReference=P;class E{constructor(){this._store=new Map,this._isDisposed=!1,p(this)}dispose(){c(this),this._isDisposed=!0,this.clearAndDisposeAll()}clearAndDisposeAll(){if(this._store.size)try{r(this._store.values())}finally{this._store.clear()}}get(l){return this._store.get(l)}set(l,b,g=!1){this._isDisposed&&console.warn(new Error("Trying to add a disposable to a DisposableMap that has already been disposed of. The added object will be leaked!").stack),g||this._store.get(l)?.dispose(),this._store.set(l,b)}deleteAndDispose(l){this._store.get(l)?.dispose(),this._store.delete(l)}[Symbol.iterator](){return this._store[Symbol.iterator]()}}n.DisposableMap=E}),X(J[20],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.LinkedList=void 0;class i{static{this.Undefined=new i(void 0)}constructor(d){this.element=d,this.next=i.Undefined,this.prev=i.Undefined}}class x{constructor(){this._first=i.Undefined,this._last=i.Undefined,this._size=0}get size(){return this._size}isEmpty(){return this._first===i.Undefined}clear(){let d=this._first;for(;d!==i.Undefined;){const f=d.next;d.prev=i.Undefined,d.next=i.Undefined,d=f}this._first=i.Undefined,this._last=i.Undefined,this._size=0}unshift(d){return this._insert(d,!1)}push(d){return this._insert(d,!0)}_insert(d,f){const p=new i(d);if(this._first===i.Undefined)this._first=p,this._last=p;else if(f){const a=this._last;this._last=p,p.prev=a,a.next=p}else{const a=this._first;this._first=p,p.next=a,a.prev=p}this._size+=1;let c=!1;return()=>{c||(c=!0,this._remove(p))}}shift(){if(this._first!==i.Undefined){const d=this._first.element;return this._remove(this._first),d}}pop(){if(this._last!==i.Undefined){const d=this._last.element;return this._remove(this._last),d}}_remove(d){if(d.prev!==i.Undefined&&d.next!==i.Undefined){const f=d.prev;f.next=d.next,d.next.prev=f}else d.prev===i.Undefined&&d.next===i.Undefined?(this._first=i.Undefined,this._last=i.Undefined):d.next===i.Undefined?(this._last=this._last.prev,this._last.next=i.Undefined):d.prev===i.Undefined&&(this._first=this._first.next,this._first.prev=i.Undefined);this._size-=1}*[Symbol.iterator](){let d=this._first;for(;d!==i.Undefined;)yield d.element,d=d.next}}n.LinkedList=x}),X(J[21],Z([0,1]),function(W,n){"use strict";var i,x;Object.defineProperty(n,"__esModule",{value:!0}),n.SetMap=n.BidirectionalMap=n.LRUCache=n.LinkedMap=n.ResourceMap=void 0;class A{constructor(r,s){this.uri=r,this.value=s}}function d(h){return Array.isArray(h)}class f{static{this.defaultToKey=r=>r.toString()}constructor(r,s){if(this[i]="ResourceMap",r instanceof f)this.map=new Map(r.map),this.toKey=s??f.defaultToKey;else if(d(r)){this.map=new Map,this.toKey=s??f.defaultToKey;for(const[o,u]of r)this.set(o,u)}else this.map=new Map,this.toKey=r??f.defaultToKey}set(r,s){return this.map.set(this.toKey(r),new A(r,s)),this}get(r){return this.map.get(this.toKey(r))?.value}has(r){return this.map.has(this.toKey(r))}get size(){return this.map.size}clear(){this.map.clear()}delete(r){return this.map.delete(this.toKey(r))}forEach(r,s){typeof s<"u"&&(r=r.bind(s));for(const[o,u]of this.map)r(u.value,u.uri,this)}*values(){for(const r of this.map.values())yield r.value}*keys(){for(const r of this.map.values())yield r.uri}*entries(){for(const r of this.map.values())yield[r.uri,r.value]}*[(i=Symbol.toStringTag,Symbol.iterator)](){for(const[,r]of this.map)yield[r.uri,r.value]}}n.ResourceMap=f;class p{constructor(){this[x]="LinkedMap",this._map=new Map,this._head=void 0,this._tail=void 0,this._size=0,this._state=0}clear(){this._map.clear(),this._head=void 0,this._tail=void 0,this._size=0,this._state++}isEmpty(){return!this._head&&!this._tail}get size(){return this._size}get first(){return this._head?.value}get last(){return this._tail?.value}has(r){return this._map.has(r)}get(r,s=0){const o=this._map.get(r);if(o)return s!==0&&this.touch(o,s),o.value}set(r,s,o=0){let u=this._map.get(r);if(u)u.value=s,o!==0&&this.touch(u,o);else{switch(u={key:r,value:s,next:void 0,previous:void 0},o){case 0:this.addItemLast(u);break;case 1:this.addItemFirst(u);break;case 2:this.addItemLast(u);break;default:this.addItemLast(u);break}this._map.set(r,u),this._size++}return this}delete(r){return!!this.remove(r)}remove(r){const s=this._map.get(r);if(s)return this._map.delete(r),this.removeItem(s),this._size--,s.value}shift(){if(!this._head&&!this._tail)return;if(!this._head||!this._tail)throw new Error("Invalid list");const r=this._head;return this._map.delete(r.key),this.removeItem(r),this._size--,r.value}forEach(r,s){const o=this._state;let u=this._head;for(;u;){if(s?r.bind(s)(u.value,u.key,this):r(u.value,u.key,this),this._state!==o)throw new Error("LinkedMap got modified during iteration.");u=u.next}}keys(){const r=this,s=this._state;let o=this._head;const u={[Symbol.iterator](){return u},next(){if(r._state!==s)throw new Error("LinkedMap got modified during iteration.");if(o){const S={value:o.key,done:!1};return o=o.next,S}else return{value:void 0,done:!0}}};return u}values(){const r=this,s=this._state;let o=this._head;const u={[Symbol.iterator](){return u},next(){if(r._state!==s)throw new Error("LinkedMap got modified during iteration.");if(o){const S={value:o.value,done:!1};return o=o.next,S}else return{value:void 0,done:!0}}};return u}entries(){const r=this,s=this._state;let o=this._head;const u={[Symbol.iterator](){return u},next(){if(r._state!==s)throw new Error("LinkedMap got modified during iteration.");if(o){const S={value:[o.key,o.value],done:!1};return o=o.next,S}else return{value:void 0,done:!0}}};return u}[(x=Symbol.toStringTag,Symbol.iterator)](){return this.entries()}trimOld(r){if(r>=this.size)return;if(r===0){this.clear();return}let s=this._head,o=this.size;for(;s&&o>r;)this._map.delete(s.key),s=s.next,o--;this._head=s,this._size=o,s&&(s.previous=void 0),this._state++}trimNew(r){if(r>=this.size)return;if(r===0){this.clear();return}let s=this._tail,o=this.size;for(;s&&o>r;)this._map.delete(s.key),s=s.previous,o--;this._tail=s,this._size=o,s&&(s.next=void 0),this._state++}addItemFirst(r){if(!this._head&&!this._tail)this._tail=r;else if(this._head)r.next=this._head,this._head.previous=r;else throw new Error("Invalid list");this._head=r,this._state++}addItemLast(r){if(!this._head&&!this._tail)this._head=r;else if(this._tail)r.previous=this._tail,this._tail.next=r;else throw new Error("Invalid list");this._tail=r,this._state++}removeItem(r){if(r===this._head&&r===this._tail)this._head=void 0,this._tail=void 0;else if(r===this._head){if(!r.next)throw new Error("Invalid list");r.next.previous=void 0,this._head=r.next}else if(r===this._tail){if(!r.previous)throw new Error("Invalid list");r.previous.next=void 0,this._tail=r.previous}else{const s=r.next,o=r.previous;if(!s||!o)throw new Error("Invalid list");s.previous=o,o.next=s}r.next=void 0,r.previous=void 0,this._state++}touch(r,s){if(!this._head||!this._tail)throw new Error("Invalid list");if(!(s!==1&&s!==2)){if(s===1){if(r===this._head)return;const o=r.next,u=r.previous;r===this._tail?(u.next=void 0,this._tail=u):(o.previous=u,u.next=o),r.previous=void 0,r.next=this._head,this._head.previous=r,this._head=r,this._state++}else if(s===2){if(r===this._tail)return;const o=r.next,u=r.previous;r===this._head?(o.previous=void 0,this._head=o):(o.previous=u,u.next=o),r.next=void 0,r.previous=this._tail,this._tail.next=r,this._tail=r,this._state++}}}toJSON(){const r=[];return this.forEach((s,o)=>{r.push([o,s])}),r}fromJSON(r){this.clear();for(const[s,o]of r)this.set(s,o)}}n.LinkedMap=p;class c extends p{constructor(r,s=1){super(),this._limit=r,this._ratio=Math.min(Math.max(0,s),1)}get limit(){return this._limit}set limit(r){this._limit=r,this.checkTrim()}get(r,s=2){return super.get(r,s)}peek(r){return super.get(r,0)}set(r,s){return super.set(r,s,2),this}checkTrim(){this.size>this._limit&&this.trim(Math.round(this._limit*this._ratio))}}class a extends c{constructor(r,s=1){super(r,s)}trim(r){this.trimOld(r)}set(r,s){return super.set(r,s),this.checkTrim(),this}}n.LRUCache=a;class m{constructor(r){if(this._m1=new Map,this._m2=new Map,r)for(const[s,o]of r)this.set(s,o)}clear(){this._m1.clear(),this._m2.clear()}set(r,s){this._m1.set(r,s),this._m2.set(s,r)}get(r){return this._m1.get(r)}getKey(r){return this._m2.get(r)}delete(r){const s=this._m1.get(r);return s===void 0?!1:(this._m1.delete(r),this._m2.delete(s),!0)}keys(){return this._m1.keys()}values(){return this._m1.values()}}n.BidirectionalMap=m;class e{constructor(){this.map=new Map}add(r,s){let o=this.map.get(r);o||(o=new Set,this.map.set(r,o)),o.add(s)}delete(r,s){const o=this.map.get(r);o&&(o.delete(s),o.size===0&&this.map.delete(r))}forEach(r,s){const o=this.map.get(r);o&&o.forEach(s)}get(r){const s=this.map.get(r);return s||new Set}}n.SetMap=e}),X(J[22],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.StopWatch=void 0;const i=globalThis.performance&&typeof globalThis.performance.now=="function";class x{static create(d){return new x(d)}constructor(d){this._now=i&&d===!1?Date.now:globalThis.performance.now.bind(globalThis.performance),this._startTime=this._now(),this._stopTime=-1}stop(){this._stopTime=this._now()}reset(){this._startTime=this._now(),this._stopTime=-1}elapsed(){return this._stopTime!==-1?this._stopTime-this._startTime:this._now()-this._startTime}}n.StopWatch=x}),X(J[9],Z([0,1,3,18,8,20,22]),function(W,n,i,x,A,d,f){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.Relay=n.EventBufferer=n.EventMultiplexer=n.MicrotaskEmitter=n.DebounceEmitter=n.PauseableEmitter=n.createEventDeliveryQueue=n.Emitter=n.ListenerRefusalError=n.ListenerLeakError=n.EventProfiling=n.Event=void 0;const p=!1,c=!1,a=!1;var m;(function(C){C.None=()=>A.Disposable.None;function R(K){if(a){const{onDidAddListener:Q}=K,k=s.create();let I=0;K.onDidAddListener=()=>{++I===2&&(console.warn("snapshotted emitter LIKELY used public and SHOULD HAVE BEEN created with DisposableStore. snapshotted here"),k.print()),Q?.()}}}function D(K,Q){return ee(K,()=>{},0,void 0,!0,void 0,Q)}C.defer=D;function T(K){return(Q,k=null,I)=>{let V=!1,H;return H=K(Y=>{if(!V)return H?H.dispose():V=!0,Q.call(k,Y)},null,I),V&&H.dispose(),H}}C.once=T;function O(K,Q){return C.once(C.filter(K,Q))}C.onceIf=O;function z(K,Q,k){return $((I,V=null,H)=>K(Y=>I.call(V,Q(Y)),null,H),k)}C.map=z;function j(K,Q,k){return $((I,V=null,H)=>K(Y=>{Q(Y),I.call(V,Y)},null,H),k)}C.forEach=j;function F(K,Q,k){return $((I,V=null,H)=>K(Y=>Q(Y)&&I.call(V,Y),null,H),k)}C.filter=F;function q(K){return K}C.signal=q;function B(...K){return(Q,k=null,I)=>{const V=(0,A.combinedDisposable)(...K.map(H=>H(Y=>Q.call(k,Y))));return U(V,I)}}C.any=B;function G(K,Q,k,I){let V=k;return z(K,H=>(V=Q(V,H),V),I)}C.reduce=G;function $(K,Q){let k;const I={onWillAddFirstListener(){k=K(V.fire,V)},onDidRemoveLastListener(){k?.dispose()}};Q||R(I);const V=new E(I);return Q?.add(V),V.event}function U(K,Q){return Q instanceof Array?Q.push(K):Q&&Q.add(K),K}function ee(K,Q,k=100,I=!1,V=!1,H,Y){let te,ne,ae,le=0,oe;const se={leakWarningThreshold:H,onWillAddFirstListener(){te=K(he=>{le++,ne=Q(ne,he),I&&!ae&&(ce.fire(ne),ne=void 0),oe=()=>{const be=ne;ne=void 0,ae=void 0,(!I||le>1)&&ce.fire(be),le=0},typeof k=="number"?(clearTimeout(ae),ae=setTimeout(oe,k)):ae===void 0&&(ae=0,queueMicrotask(oe))})},onWillRemoveListener(){V&&le>0&&oe?.()},onDidRemoveLastListener(){oe=void 0,te.dispose()}};Y||R(se);const ce=new E(se);return Y?.add(ce),ce.event}C.debounce=ee;function re(K,Q=0,k){return C.debounce(K,(I,V)=>I?(I.push(V),I):[V],Q,void 0,!0,void 0,k)}C.accumulate=re;function ue(K,Q=(I,V)=>I===V,k){let I=!0,V;return F(K,H=>{const Y=I||!Q(H,V);return I=!1,V=H,Y},k)}C.latch=ue;function de(K,Q,k){return[C.filter(K,Q,k),C.filter(K,I=>!Q(I),k)]}C.split=de;function ge(K,Q=!1,k=[],I){let V=k.slice(),H=K(ne=>{V?V.push(ne):te.fire(ne)});I&&I.add(H);const Y=()=>{V?.forEach(ne=>te.fire(ne)),V=null},te=new E({onWillAddFirstListener(){H||(H=K(ne=>te.fire(ne)),I&&I.add(H))},onDidAddFirstListener(){V&&(Q?setTimeout(Y):Y())},onDidRemoveLastListener(){H&&H.dispose(),H=null}});return I&&I.add(te),te.event}C.buffer=ge;function t(K,Q){return(I,V,H)=>{const Y=Q(new pe);return K(function(te){const ne=Y.evaluate(te);ne!==me&&I.call(V,ne)},void 0,H)}}C.chain=t;const me=Symbol("HaltChainable");class pe{constructor(){this.steps=[]}map(Q){return this.steps.push(Q),this}forEach(Q){return this.steps.push(k=>(Q(k),k)),this}filter(Q){return this.steps.push(k=>Q(k)?k:me),this}reduce(Q,k){let I=k;return this.steps.push(V=>(I=Q(I,V),I)),this}latch(Q=(k,I)=>k===I){let k=!0,I;return this.steps.push(V=>{const H=k||!Q(V,I);return k=!1,I=V,H?V:me}),this}evaluate(Q){for(const k of this.steps)if(Q=k(Q),Q===me)break;return Q}}function Le(K,Q,k=I=>I){const I=(...te)=>Y.fire(k(...te)),V=()=>K.on(Q,I),H=()=>K.removeListener(Q,I),Y=new E({onWillAddFirstListener:V,onDidRemoveLastListener:H});return Y.event}C.fromNodeEventEmitter=Le;function we(K,Q,k=I=>I){const I=(...te)=>Y.fire(k(...te)),V=()=>K.addEventListener(Q,I),H=()=>K.removeEventListener(Q,I),Y=new E({onWillAddFirstListener:V,onDidRemoveLastListener:H});return Y.event}C.fromDOMEventEmitter=we;function Ce(K){return new Promise(Q=>T(K)(Q))}C.toPromise=Ce;function ve(K){const Q=new E;return K.then(k=>{Q.fire(k)},()=>{Q.fire(void 0)}).finally(()=>{Q.dispose()}),Q.event}C.fromPromise=ve;function fe(K,Q){return K(k=>Q.fire(k))}C.forward=fe;function Se(K,Q,k){return Q(k),K(I=>Q(I))}C.runAndSubscribe=Se;class _e{constructor(Q,k){this._observable=Q,this._counter=0,this._hasChanged=!1;const I={onWillAddFirstListener:()=>{Q.addObserver(this),this._observable.reportChanges()},onDidRemoveLastListener:()=>{Q.removeObserver(this)}};k||R(I),this.emitter=new E(I),k&&k.add(this.emitter)}beginUpdate(Q){this._counter++}handlePossibleChange(Q){}handleChange(Q,k){this._hasChanged=!0}endUpdate(Q){this._counter--,this._counter===0&&(this._observable.reportChanges(),this._hasChanged&&(this._hasChanged=!1,this.emitter.fire(this._observable.get())))}}function ye(K,Q){return new _e(K,Q).emitter.event}C.fromObservable=ye;function Ee(K){return(Q,k,I)=>{let V=0,H=!1;const Y={beginUpdate(){V++},endUpdate(){V--,V===0&&(K.reportChanges(),H&&(H=!1,Q.call(k)))},handlePossibleChange(){},handleChange(){H=!0}};K.addObserver(Y),K.reportChanges();const te={dispose(){K.removeObserver(Y)}};return I instanceof A.DisposableStore?I.add(te):Array.isArray(I)&&I.push(te),te}}C.fromObservableLight=Ee})(m||(n.Event=m={}));class e{static{this.all=new Set}static{this._idPool=0}constructor(R){this.listenerCount=0,this.invocationCount=0,this.elapsedOverall=0,this.durations=[],this.name=`${R}_${e._idPool++}`,e.all.add(this)}start(R){this._stopWatch=new f.StopWatch,this.listenerCount=R}stop(){if(this._stopWatch){const R=this._stopWatch.elapsed();this.durations.push(R),this.elapsedOverall+=R,this.invocationCount+=1,this._stopWatch=void 0}}}n.EventProfiling=e;let h=-1;class r{static{this._idPool=1}constructor(R,D,T=(r._idPool++).toString(16).padStart(3,"0")){this._errorHandler=R,this.threshold=D,this.name=T,this._warnCountdown=0}dispose(){this._stacks?.clear()}check(R,D){const T=this.threshold;if(T<=0||D{const z=this._stacks.get(R.value)||0;this._stacks.set(R.value,z-1)}}getMostFrequentStack(){if(!this._stacks)return;let R,D=0;for(const[T,O]of this._stacks)(!R||D{if(C instanceof S)R(C);else for(let D=0;D{C.length!==0&&(console.warn("[LEAKING LISTENERS] GC'ed these listeners that were NOT yet disposed:"),console.warn(C.join(` `)),C.length=0)},3e3),P=new FinalizationRegistry(R=>{typeof R=="string"&&C.push(R)})}class E{constructor(R){this._size=0,this._options=R,this._leakageMon=h>0||this._options?.leakWarningThreshold?new r(R?.onListenerError??i.onUnexpectedError,this._options?.leakWarningThreshold??h):void 0,this._perfMon=this._options?._profName?new e(this._options._profName):void 0,this._deliveryQueue=this._options?.deliveryQueue}dispose(){if(!this._disposed){if(this._disposed=!0,this._deliveryQueue?.current===this&&this._deliveryQueue.reset(),this._listeners){if(c){const R=this._listeners;queueMicrotask(()=>{N(R,D=>D.stack?.print())})}this._listeners=void 0,this._size=0}this._options?.onDidRemoveLastListener?.(),this._leakageMon?.dispose()}}get event(){return this._event??=(R,D,T)=>{if(this._leakageMon&&this._size>this._leakageMon.threshold**2){const q=`[${this._leakageMon.name}] REFUSES to accept new listeners because it exceeded its threshold by far (${this._size} vs ${this._leakageMon.threshold})`;console.warn(q);const B=this._leakageMon.getMostFrequentStack()??["UNKNOWN stack",-1],G=new u(`${q}. HINT: Stack shows most frequent listener (${B[1]}-times)`,B[0]);return(this._options?.onListenerError||i.onUnexpectedError)(G),A.Disposable.None}if(this._disposed)return A.Disposable.None;D&&(R=R.bind(D));const O=new S(R);let z,j;this._leakageMon&&this._size>=Math.ceil(this._leakageMon.threshold*.2)&&(O.stack=s.create(),z=this._leakageMon.check(O.stack,this._size+1)),c&&(O.stack=j??s.create()),this._listeners?this._listeners instanceof S?(this._deliveryQueue??=new l,this._listeners=[this._listeners,O]):this._listeners.push(O):(this._options?.onWillAddFirstListener?.(this),this._listeners=O,this._options?.onDidAddFirstListener?.(this)),this._size++;const F=(0,A.toDisposable)(()=>{P?.unregister(F),z?.(),this._removeListener(O)});if(T instanceof A.DisposableStore?T.add(F):Array.isArray(T)&&T.push(F),P){const q=new Error().stack.split(` `).slice(2,3).join(` `).trim(),B=/(file:|vscode-file:\/\/vscode-app)?(\/[^:]*:\d+:\d+)/.exec(q);P.register(F,B?.[2]??q,F)}return F},this._event}_removeListener(R){if(this._options?.onWillRemoveListener?.(this),!this._listeners)return;if(this._size===1){this._listeners=void 0,this._options?.onDidRemoveLastListener?.(this),this._size=0;return}const D=this._listeners,T=D.indexOf(R);if(T===-1)throw console.log("disposed?",this._disposed),console.log("size?",this._size),console.log("arr?",JSON.stringify(this._listeners)),new Error("Attempted to dispose unknown listener");this._size--,D[T]=void 0;const O=this._deliveryQueue.current===this;if(this._size*L<=D.length){let z=0;for(let j=0;j0}}n.Emitter=E;const v=()=>new l;n.createEventDeliveryQueue=v;class l{constructor(){this.i=-1,this.end=0}enqueue(R,D,T){this.i=0,this.end=T,this.current=R,this.value=D}reset(){this.i=this.end,this.current=void 0,this.value=void 0}}class b extends E{constructor(R){super(R),this._isPaused=0,this._eventQueue=new d.LinkedList,this._mergeFn=R?.merge}pause(){this._isPaused++}resume(){if(this._isPaused!==0&&--this._isPaused===0)if(this._mergeFn){if(this._eventQueue.size>0){const R=Array.from(this._eventQueue);this._eventQueue.clear(),super.fire(this._mergeFn(R))}}else for(;!this._isPaused&&this._eventQueue.size!==0;)super.fire(this._eventQueue.shift())}fire(R){this._size&&(this._isPaused!==0?this._eventQueue.push(R):super.fire(R))}}n.PauseableEmitter=b;class g extends b{constructor(R){super(R),this._delay=R.delay??100}fire(R){this._handle||(this.pause(),this._handle=setTimeout(()=>{this._handle=void 0,this.resume()},this._delay)),super.fire(R)}}n.DebounceEmitter=g;class w extends E{constructor(R){super(R),this._queuedEvents=[],this._mergeFn=R?.merge}fire(R){this.hasListeners()&&(this._queuedEvents.push(R),this._queuedEvents.length===1&&queueMicrotask(()=>{this._mergeFn?super.fire(this._mergeFn(this._queuedEvents)):this._queuedEvents.forEach(D=>super.fire(D)),this._queuedEvents=[]}))}}n.MicrotaskEmitter=w;class M{constructor(){this.hasListeners=!1,this.events=[],this.emitter=new E({onWillAddFirstListener:()=>this.onFirstListenerAdd(),onDidRemoveLastListener:()=>this.onLastListenerRemove()})}get event(){return this.emitter.event}add(R){const D={event:R,listener:null};this.events.push(D),this.hasListeners&&this.hook(D);const T=()=>{this.hasListeners&&this.unhook(D);const O=this.events.indexOf(D);this.events.splice(O,1)};return(0,A.toDisposable)((0,x.createSingleCallFunction)(T))}onFirstListenerAdd(){this.hasListeners=!0,this.events.forEach(R=>this.hook(R))}onLastListenerRemove(){this.hasListeners=!1,this.events.forEach(R=>this.unhook(R))}hook(R){R.listener=R.event(D=>this.emitter.fire(D))}unhook(R){R.listener?.dispose(),R.listener=null}dispose(){this.emitter.dispose();for(const R of this.events)R.listener?.dispose();this.events=[]}}n.EventMultiplexer=M;class y{constructor(){this.data=[]}wrapEvent(R,D,T){return(O,z,j)=>R(F=>{const q=this.data[this.data.length-1];if(!D){q?q.buffers.push(()=>O.call(z,F)):O.call(z,F);return}const B=q;if(!B){O.call(z,D(T,F));return}B.items??=[],B.items.push(F),B.buffers.length===0&&q.buffers.push(()=>{B.reducedResult??=T?B.items.reduce(D,T):B.items.reduce(D),O.call(z,B.reducedResult)})},void 0,j)}bufferEvents(R){const D={buffers:new Array};this.data.push(D);const T=R();return this.data.pop(),D.buffers.forEach(O=>O()),T}}n.EventBufferer=y;class _{constructor(){this.listening=!1,this.inputEvent=m.None,this.inputEventListener=A.Disposable.None,this.emitter=new E({onDidAddFirstListener:()=>{this.listening=!0,this.inputEventListener=this.inputEvent(this.emitter.fire,this.emitter)},onDidRemoveLastListener:()=>{this.listening=!1,this.inputEventListener.dispose()}}),this.event=this.emitter.event}set input(R){this.inputEvent=R,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=R(this.emitter.fire,this.emitter))}dispose(){this.inputEventListener.dispose(),this.emitter.dispose()}}n.Relay=_}),X(J[23],Z([0,1,9]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.CancellationTokenSource=n.CancellationToken=void 0,n.cancelOnDispose=p;const x=Object.freeze(function(c,a){const m=setTimeout(c.bind(a),0);return{dispose(){clearTimeout(m)}}});var A;(function(c){function a(m){return m===c.None||m===c.Cancelled||m instanceof d?!0:!m||typeof m!="object"?!1:typeof m.isCancellationRequested=="boolean"&&typeof m.onCancellationRequested=="function"}c.isCancellationToken=a,c.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:i.Event.None}),c.Cancelled=Object.freeze({isCancellationRequested:!0,onCancellationRequested:x})})(A||(n.CancellationToken=A={}));class d{constructor(){this._isCancelled=!1,this._emitter=null}cancel(){this._isCancelled||(this._isCancelled=!0,this._emitter&&(this._emitter.fire(void 0),this.dispose()))}get isCancellationRequested(){return this._isCancelled}get onCancellationRequested(){return this._isCancelled?x:(this._emitter||(this._emitter=new i.Emitter),this._emitter.event)}dispose(){this._emitter&&(this._emitter.dispose(),this._emitter=null)}}class f{constructor(a){this._token=void 0,this._parentListener=void 0,this._parentListener=a&&a.onCancellationRequested(this.cancel,this)}get token(){return this._token||(this._token=new d),this._token}cancel(){this._token?this._token instanceof d&&this._token.cancel():this._token=A.Cancelled}dispose(a=!1){a&&this.cancel(),this._parentListener?.dispose(),this._token?this._token instanceof d&&this._token.dispose():this._token=A.None}}n.CancellationTokenSource=f;function p(c){const a=new f;return c.add({dispose(){a.cancel()}}),a.token}}),X(J[6],Z([0,1,39,43]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.InvisibleCharacters=n.AmbiguousCharacters=n.noBreakWhitespace=n.UTF8_BOM_CHARACTER=n.UNUSUAL_LINE_TERMINATORS=n.GraphemeIterator=n.CodePointIterator=void 0,n.isFalsyOrWhitespace=A,n.format=f,n.htmlAttributeEncodeValue=p,n.escape=c,n.escapeRegExpCharacters=a,n.trim=m,n.ltrim=e,n.rtrim=h,n.convertSimple2RegExpPattern=r,n.stripWildcards=s,n.createRegExp=o,n.regExpLeadsToEndlessLoop=u,n.splitLines=S,n.splitLinesIncludeSeparators=L,n.firstNonWhitespaceIndex=N,n.getLeadingWhitespace=P,n.lastNonWhitespaceIndex=E,n.compare=v,n.compareSubstring=l,n.compareIgnoreCase=b,n.compareSubstringIgnoreCase=g,n.isAsciiDigit=w,n.isLowerAsciiLetter=M,n.isUpperAsciiLetter=y,n.equalsIgnoreCase=_,n.startsWithIgnoreCase=C,n.commonPrefixLength=R,n.commonSuffixLength=D,n.isHighSurrogate=T,n.isLowSurrogate=O,n.computeCodePoint=z,n.getNextCodePoint=j,n.nextCharLength=G,n.prevCharLength=$,n.getCharContainingOffset=U,n.containsRTL=ue,n.isBasicASCII=ge,n.containsUnusualLineTerminators=t,n.isFullWidthCharacter=me,n.isEmojiImprecise=pe,n.startsWithUTF8BOM=Le,n.containsUppercaseCharacter=we,n.singleLetterHash=Ce,n.getLeftDeleteOffset=_e;function A(k){return!k||typeof k!="string"?!0:k.trim().length===0}const d=/{(\d+)}/g;function f(k,...I){return I.length===0?k:k.replace(d,function(V,H){const Y=parseInt(H,10);return isNaN(Y)||Y<0||Y>=I.length?V:I[Y]})}function p(k){return k.replace(/[<>"'&]/g,I=>{switch(I){case"<":return"<";case">":return">";case'"':return""";case"'":return"'";case"&":return"&"}return I})}function c(k){return k.replace(/[<>&]/g,function(I){switch(I){case"<":return"<";case">":return">";case"&":return"&";default:return I}})}function a(k){return k.replace(/[\\\{\}\*\+\?\|\^\$\.\[\]\(\)]/g,"\\$&")}function m(k,I=" "){const V=e(k,I);return h(V,I)}function e(k,I){if(!k||!I)return k;const V=I.length;if(V===0||k.length===0)return k;let H=0;for(;k.indexOf(I,H)===H;)H=H+V;return k.substring(H)}function h(k,I){if(!k||!I)return k;const V=I.length,H=k.length;if(V===0||H===0)return k;let Y=H,te=-1;for(;te=k.lastIndexOf(I,Y-1),!(te===-1||te+V!==Y);){if(te===0)return"";Y=te}return k.substring(0,Y)}function r(k){return k.replace(/[\-\\\{\}\+\?\|\^\$\.\,\[\]\(\)\#\s]/g,"\\$&").replace(/[\*]/g,".*")}function s(k){return k.replace(/\*/g,"")}function o(k,I,V={}){if(!k)throw new Error("Cannot create regex from empty string");I||(k=a(k)),V.wholeWord&&(/\B/.test(k.charAt(0))||(k="\\b"+k),/\B/.test(k.charAt(k.length-1))||(k=k+"\\b"));let H="";return V.global&&(H+="g"),V.matchCase||(H+="i"),V.multiline&&(H+="m"),V.unicode&&(H+="u"),new RegExp(k,H)}function u(k){return k.source==="^"||k.source==="^$"||k.source==="$"||k.source==="^\\s*$"?!1:!!(k.exec("")&&k.lastIndex===0)}function S(k){return k.split(/\r\n|\r|\n/)}function L(k){const I=[],V=k.split(/(\r\n|\r|\n)/);for(let H=0;H=0;V--){const H=k.charCodeAt(V);if(H!==32&&H!==9)return V}return-1}function v(k,I){return kI?1:0}function l(k,I,V=0,H=k.length,Y=0,te=I.length){for(;Voe)return 1}const ne=H-V,ae=te-Y;return neae?1:0}function b(k,I){return g(k,I,0,k.length,0,I.length)}function g(k,I,V=0,H=k.length,Y=0,te=I.length){for(;V=128||oe>=128)return l(k.toLowerCase(),I.toLowerCase(),V,H,Y,te);M(le)&&(le-=32),M(oe)&&(oe-=32);const se=le-oe;if(se!==0)return se}const ne=H-V,ae=te-Y;return neae?1:0}function w(k){return k>=48&&k<=57}function M(k){return k>=97&&k<=122}function y(k){return k>=65&&k<=90}function _(k,I){return k.length===I.length&&g(k,I)===0}function C(k,I){const V=I.length;return I.length>k.length?!1:g(k,I,0,V)===0}function R(k,I){const V=Math.min(k.length,I.length);let H;for(H=0;H1){const H=k.charCodeAt(I-2);if(T(H))return z(H,V)}return V}class q{get offset(){return this._offset}constructor(I,V=0){this._str=I,this._len=I.length,this._offset=V}setOffset(I){this._offset=I}prevCodePoint(){const I=F(this._str,this._offset);return this._offset-=I>=65536?2:1,I}nextCodePoint(){const I=j(this._str,this._len,this._offset);return this._offset+=I>=65536?2:1,I}eol(){return this._offset>=this._len}}n.CodePointIterator=q;class B{get offset(){return this._iterator.offset}constructor(I,V=0){this._iterator=new q(I,V)}nextGraphemeLength(){const I=fe.getInstance(),V=this._iterator,H=V.offset;let Y=I.getGraphemeBreakType(V.nextCodePoint());for(;!V.eol();){const te=V.offset,ne=I.getGraphemeBreakType(V.nextCodePoint());if(ve(Y,ne)){V.setOffset(te);break}Y=ne}return V.offset-H}prevGraphemeLength(){const I=fe.getInstance(),V=this._iterator,H=V.offset;let Y=I.getGraphemeBreakType(V.prevCodePoint());for(;V.offset>0;){const te=V.offset,ne=I.getGraphemeBreakType(V.prevCodePoint());if(ve(ne,Y)){V.setOffset(te);break}Y=ne}return H-V.offset}eol(){return this._iterator.eol()}}n.GraphemeIterator=B;function G(k,I){return new B(k,I).nextGraphemeLength()}function $(k,I){return new B(k,I).prevGraphemeLength()}function U(k,I){I>0&&O(k.charCodeAt(I))&&I--;const V=I+G(k,I);return[V-$(k,V),V]}let ee;function re(){return/(?:[\u05BE\u05C0\u05C3\u05C6\u05D0-\u05F4\u0608\u060B\u060D\u061B-\u064A\u066D-\u066F\u0671-\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u0710\u0712-\u072F\u074D-\u07A5\u07B1-\u07EA\u07F4\u07F5\u07FA\u07FE-\u0815\u081A\u0824\u0828\u0830-\u0858\u085E-\u088E\u08A0-\u08C9\u200F\uFB1D\uFB1F-\uFB28\uFB2A-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFC\uFE70-\uFEFC]|\uD802[\uDC00-\uDD1B\uDD20-\uDE00\uDE10-\uDE35\uDE40-\uDEE4\uDEEB-\uDF35\uDF40-\uDFFF]|\uD803[\uDC00-\uDD23\uDE80-\uDEA9\uDEAD-\uDF45\uDF51-\uDF81\uDF86-\uDFF6]|\uD83A[\uDC00-\uDCCF\uDD00-\uDD43\uDD4B-\uDFFF]|\uD83B[\uDC00-\uDEBB])/}function ue(k){return ee||(ee=re()),ee.test(k)}const de=/^[\t\n\r\x20-\x7E]*$/;function ge(k){return de.test(k)}n.UNUSUAL_LINE_TERMINATORS=/[\u2028\u2029]/;function t(k){return n.UNUSUAL_LINE_TERMINATORS.test(k)}function me(k){return k>=11904&&k<=55215||k>=63744&&k<=64255||k>=65281&&k<=65374}function pe(k){return k>=127462&&k<=127487||k===8986||k===8987||k===9200||k===9203||k>=9728&&k<=10175||k===11088||k===11093||k>=127744&&k<=128591||k>=128640&&k<=128764||k>=128992&&k<=129008||k>=129280&&k<=129535||k>=129648&&k<=129782}n.UTF8_BOM_CHARACTER="\uFEFF";function Le(k){return!!(k&&k.length>0&&k.charCodeAt(0)===65279)}function we(k,I=!1){return k?(I&&(k=k.replace(/\\./g,"")),k.toLowerCase()!==k):!1}function Ce(k){return k=k%(2*26),k<26?String.fromCharCode(97+k):String.fromCharCode(65+k-26)}function ve(k,I){return k===0?I!==5&&I!==7:k===2&&I===3?!1:k===4||k===2||k===3||I===4||I===2||I===3?!0:!(k===8&&(I===8||I===9||I===11||I===12)||(k===11||k===9)&&(I===9||I===10)||(k===12||k===10)&&I===10||I===5||I===13||I===7||k===1||k===13&&I===14||k===6&&I===6)}class fe{static{this._INSTANCE=null}static getInstance(){return fe._INSTANCE||(fe._INSTANCE=new fe),fe._INSTANCE}constructor(){this._data=Se()}getGraphemeBreakType(I){if(I<32)return I===10?3:I===13?2:4;if(I<127)return 0;const V=this._data,H=V.length/3;let Y=1;for(;Y<=H;)if(IV[3*Y+1])Y=2*Y+1;else return V[3*Y+2];return 0}}function Se(){return JSON.parse("[0,0,0,51229,51255,12,44061,44087,12,127462,127487,6,7083,7085,5,47645,47671,12,54813,54839,12,128678,128678,14,3270,3270,5,9919,9923,14,45853,45879,12,49437,49463,12,53021,53047,12,71216,71218,7,128398,128399,14,129360,129374,14,2519,2519,5,4448,4519,9,9742,9742,14,12336,12336,14,44957,44983,12,46749,46775,12,48541,48567,12,50333,50359,12,52125,52151,12,53917,53943,12,69888,69890,5,73018,73018,5,127990,127990,14,128558,128559,14,128759,128760,14,129653,129655,14,2027,2035,5,2891,2892,7,3761,3761,5,6683,6683,5,8293,8293,4,9825,9826,14,9999,9999,14,43452,43453,5,44509,44535,12,45405,45431,12,46301,46327,12,47197,47223,12,48093,48119,12,48989,49015,12,49885,49911,12,50781,50807,12,51677,51703,12,52573,52599,12,53469,53495,12,54365,54391,12,65279,65279,4,70471,70472,7,72145,72147,7,119173,119179,5,127799,127818,14,128240,128244,14,128512,128512,14,128652,128652,14,128721,128722,14,129292,129292,14,129445,129450,14,129734,129743,14,1476,1477,5,2366,2368,7,2750,2752,7,3076,3076,5,3415,3415,5,4141,4144,5,6109,6109,5,6964,6964,5,7394,7400,5,9197,9198,14,9770,9770,14,9877,9877,14,9968,9969,14,10084,10084,14,43052,43052,5,43713,43713,5,44285,44311,12,44733,44759,12,45181,45207,12,45629,45655,12,46077,46103,12,46525,46551,12,46973,46999,12,47421,47447,12,47869,47895,12,48317,48343,12,48765,48791,12,49213,49239,12,49661,49687,12,50109,50135,12,50557,50583,12,51005,51031,12,51453,51479,12,51901,51927,12,52349,52375,12,52797,52823,12,53245,53271,12,53693,53719,12,54141,54167,12,54589,54615,12,55037,55063,12,69506,69509,5,70191,70193,5,70841,70841,7,71463,71467,5,72330,72342,5,94031,94031,5,123628,123631,5,127763,127765,14,127941,127941,14,128043,128062,14,128302,128317,14,128465,128467,14,128539,128539,14,128640,128640,14,128662,128662,14,128703,128703,14,128745,128745,14,129004,129007,14,129329,129330,14,129402,129402,14,129483,129483,14,129686,129704,14,130048,131069,14,173,173,4,1757,1757,1,2200,2207,5,2434,2435,7,2631,2632,5,2817,2817,5,3008,3008,5,3201,3201,5,3387,3388,5,3542,3542,5,3902,3903,7,4190,4192,5,6002,6003,5,6439,6440,5,6765,6770,7,7019,7027,5,7154,7155,7,8205,8205,13,8505,8505,14,9654,9654,14,9757,9757,14,9792,9792,14,9852,9853,14,9890,9894,14,9937,9937,14,9981,9981,14,10035,10036,14,11035,11036,14,42654,42655,5,43346,43347,7,43587,43587,5,44006,44007,7,44173,44199,12,44397,44423,12,44621,44647,12,44845,44871,12,45069,45095,12,45293,45319,12,45517,45543,12,45741,45767,12,45965,45991,12,46189,46215,12,46413,46439,12,46637,46663,12,46861,46887,12,47085,47111,12,47309,47335,12,47533,47559,12,47757,47783,12,47981,48007,12,48205,48231,12,48429,48455,12,48653,48679,12,48877,48903,12,49101,49127,12,49325,49351,12,49549,49575,12,49773,49799,12,49997,50023,12,50221,50247,12,50445,50471,12,50669,50695,12,50893,50919,12,51117,51143,12,51341,51367,12,51565,51591,12,51789,51815,12,52013,52039,12,52237,52263,12,52461,52487,12,52685,52711,12,52909,52935,12,53133,53159,12,53357,53383,12,53581,53607,12,53805,53831,12,54029,54055,12,54253,54279,12,54477,54503,12,54701,54727,12,54925,54951,12,55149,55175,12,68101,68102,5,69762,69762,7,70067,70069,7,70371,70378,5,70720,70721,7,71087,71087,5,71341,71341,5,71995,71996,5,72249,72249,7,72850,72871,5,73109,73109,5,118576,118598,5,121505,121519,5,127245,127247,14,127568,127569,14,127777,127777,14,127872,127891,14,127956,127967,14,128015,128016,14,128110,128172,14,128259,128259,14,128367,128368,14,128424,128424,14,128488,128488,14,128530,128532,14,128550,128551,14,128566,128566,14,128647,128647,14,128656,128656,14,128667,128673,14,128691,128693,14,128715,128715,14,128728,128732,14,128752,128752,14,128765,128767,14,129096,129103,14,129311,129311,14,129344,129349,14,129394,129394,14,129413,129425,14,129466,129471,14,129511,129535,14,129664,129666,14,129719,129722,14,129760,129767,14,917536,917631,5,13,13,2,1160,1161,5,1564,1564,4,1807,1807,1,2085,2087,5,2307,2307,7,2382,2383,7,2497,2500,5,2563,2563,7,2677,2677,5,2763,2764,7,2879,2879,5,2914,2915,5,3021,3021,5,3142,3144,5,3263,3263,5,3285,3286,5,3398,3400,7,3530,3530,5,3633,3633,5,3864,3865,5,3974,3975,5,4155,4156,7,4229,4230,5,5909,5909,7,6078,6085,7,6277,6278,5,6451,6456,7,6744,6750,5,6846,6846,5,6972,6972,5,7074,7077,5,7146,7148,7,7222,7223,5,7416,7417,5,8234,8238,4,8417,8417,5,9000,9000,14,9203,9203,14,9730,9731,14,9748,9749,14,9762,9763,14,9776,9783,14,9800,9811,14,9831,9831,14,9872,9873,14,9882,9882,14,9900,9903,14,9929,9933,14,9941,9960,14,9974,9974,14,9989,9989,14,10006,10006,14,10062,10062,14,10160,10160,14,11647,11647,5,12953,12953,14,43019,43019,5,43232,43249,5,43443,43443,5,43567,43568,7,43696,43696,5,43765,43765,7,44013,44013,5,44117,44143,12,44229,44255,12,44341,44367,12,44453,44479,12,44565,44591,12,44677,44703,12,44789,44815,12,44901,44927,12,45013,45039,12,45125,45151,12,45237,45263,12,45349,45375,12,45461,45487,12,45573,45599,12,45685,45711,12,45797,45823,12,45909,45935,12,46021,46047,12,46133,46159,12,46245,46271,12,46357,46383,12,46469,46495,12,46581,46607,12,46693,46719,12,46805,46831,12,46917,46943,12,47029,47055,12,47141,47167,12,47253,47279,12,47365,47391,12,47477,47503,12,47589,47615,12,47701,47727,12,47813,47839,12,47925,47951,12,48037,48063,12,48149,48175,12,48261,48287,12,48373,48399,12,48485,48511,12,48597,48623,12,48709,48735,12,48821,48847,12,48933,48959,12,49045,49071,12,49157,49183,12,49269,49295,12,49381,49407,12,49493,49519,12,49605,49631,12,49717,49743,12,49829,49855,12,49941,49967,12,50053,50079,12,50165,50191,12,50277,50303,12,50389,50415,12,50501,50527,12,50613,50639,12,50725,50751,12,50837,50863,12,50949,50975,12,51061,51087,12,51173,51199,12,51285,51311,12,51397,51423,12,51509,51535,12,51621,51647,12,51733,51759,12,51845,51871,12,51957,51983,12,52069,52095,12,52181,52207,12,52293,52319,12,52405,52431,12,52517,52543,12,52629,52655,12,52741,52767,12,52853,52879,12,52965,52991,12,53077,53103,12,53189,53215,12,53301,53327,12,53413,53439,12,53525,53551,12,53637,53663,12,53749,53775,12,53861,53887,12,53973,53999,12,54085,54111,12,54197,54223,12,54309,54335,12,54421,54447,12,54533,54559,12,54645,54671,12,54757,54783,12,54869,54895,12,54981,55007,12,55093,55119,12,55243,55291,10,66045,66045,5,68325,68326,5,69688,69702,5,69817,69818,5,69957,69958,7,70089,70092,5,70198,70199,5,70462,70462,5,70502,70508,5,70750,70750,5,70846,70846,7,71100,71101,5,71230,71230,7,71351,71351,5,71737,71738,5,72000,72000,7,72160,72160,5,72273,72278,5,72752,72758,5,72882,72883,5,73031,73031,5,73461,73462,7,94192,94193,7,119149,119149,7,121403,121452,5,122915,122916,5,126980,126980,14,127358,127359,14,127535,127535,14,127759,127759,14,127771,127771,14,127792,127793,14,127825,127867,14,127897,127899,14,127945,127945,14,127985,127986,14,128000,128007,14,128021,128021,14,128066,128100,14,128184,128235,14,128249,128252,14,128266,128276,14,128335,128335,14,128379,128390,14,128407,128419,14,128444,128444,14,128481,128481,14,128499,128499,14,128526,128526,14,128536,128536,14,128543,128543,14,128556,128556,14,128564,128564,14,128577,128580,14,128643,128645,14,128649,128649,14,128654,128654,14,128660,128660,14,128664,128664,14,128675,128675,14,128686,128689,14,128695,128696,14,128705,128709,14,128717,128719,14,128725,128725,14,128736,128741,14,128747,128748,14,128755,128755,14,128762,128762,14,128981,128991,14,129009,129023,14,129160,129167,14,129296,129304,14,129320,129327,14,129340,129342,14,129356,129356,14,129388,129392,14,129399,129400,14,129404,129407,14,129432,129442,14,129454,129455,14,129473,129474,14,129485,129487,14,129648,129651,14,129659,129660,14,129671,129679,14,129709,129711,14,129728,129730,14,129751,129753,14,129776,129782,14,917505,917505,4,917760,917999,5,10,10,3,127,159,4,768,879,5,1471,1471,5,1536,1541,1,1648,1648,5,1767,1768,5,1840,1866,5,2070,2073,5,2137,2139,5,2274,2274,1,2363,2363,7,2377,2380,7,2402,2403,5,2494,2494,5,2507,2508,7,2558,2558,5,2622,2624,7,2641,2641,5,2691,2691,7,2759,2760,5,2786,2787,5,2876,2876,5,2881,2884,5,2901,2902,5,3006,3006,5,3014,3016,7,3072,3072,5,3134,3136,5,3157,3158,5,3260,3260,5,3266,3266,5,3274,3275,7,3328,3329,5,3391,3392,7,3405,3405,5,3457,3457,5,3536,3537,7,3551,3551,5,3636,3642,5,3764,3772,5,3895,3895,5,3967,3967,7,3993,4028,5,4146,4151,5,4182,4183,7,4226,4226,5,4253,4253,5,4957,4959,5,5940,5940,7,6070,6070,7,6087,6088,7,6158,6158,4,6432,6434,5,6448,6449,7,6679,6680,5,6742,6742,5,6754,6754,5,6783,6783,5,6912,6915,5,6966,6970,5,6978,6978,5,7042,7042,7,7080,7081,5,7143,7143,7,7150,7150,7,7212,7219,5,7380,7392,5,7412,7412,5,8203,8203,4,8232,8232,4,8265,8265,14,8400,8412,5,8421,8432,5,8617,8618,14,9167,9167,14,9200,9200,14,9410,9410,14,9723,9726,14,9733,9733,14,9745,9745,14,9752,9752,14,9760,9760,14,9766,9766,14,9774,9774,14,9786,9786,14,9794,9794,14,9823,9823,14,9828,9828,14,9833,9850,14,9855,9855,14,9875,9875,14,9880,9880,14,9885,9887,14,9896,9897,14,9906,9916,14,9926,9927,14,9935,9935,14,9939,9939,14,9962,9962,14,9972,9972,14,9978,9978,14,9986,9986,14,9997,9997,14,10002,10002,14,10017,10017,14,10055,10055,14,10071,10071,14,10133,10135,14,10548,10549,14,11093,11093,14,12330,12333,5,12441,12442,5,42608,42610,5,43010,43010,5,43045,43046,5,43188,43203,7,43302,43309,5,43392,43394,5,43446,43449,5,43493,43493,5,43571,43572,7,43597,43597,7,43703,43704,5,43756,43757,5,44003,44004,7,44009,44010,7,44033,44059,12,44089,44115,12,44145,44171,12,44201,44227,12,44257,44283,12,44313,44339,12,44369,44395,12,44425,44451,12,44481,44507,12,44537,44563,12,44593,44619,12,44649,44675,12,44705,44731,12,44761,44787,12,44817,44843,12,44873,44899,12,44929,44955,12,44985,45011,12,45041,45067,12,45097,45123,12,45153,45179,12,45209,45235,12,45265,45291,12,45321,45347,12,45377,45403,12,45433,45459,12,45489,45515,12,45545,45571,12,45601,45627,12,45657,45683,12,45713,45739,12,45769,45795,12,45825,45851,12,45881,45907,12,45937,45963,12,45993,46019,12,46049,46075,12,46105,46131,12,46161,46187,12,46217,46243,12,46273,46299,12,46329,46355,12,46385,46411,12,46441,46467,12,46497,46523,12,46553,46579,12,46609,46635,12,46665,46691,12,46721,46747,12,46777,46803,12,46833,46859,12,46889,46915,12,46945,46971,12,47001,47027,12,47057,47083,12,47113,47139,12,47169,47195,12,47225,47251,12,47281,47307,12,47337,47363,12,47393,47419,12,47449,47475,12,47505,47531,12,47561,47587,12,47617,47643,12,47673,47699,12,47729,47755,12,47785,47811,12,47841,47867,12,47897,47923,12,47953,47979,12,48009,48035,12,48065,48091,12,48121,48147,12,48177,48203,12,48233,48259,12,48289,48315,12,48345,48371,12,48401,48427,12,48457,48483,12,48513,48539,12,48569,48595,12,48625,48651,12,48681,48707,12,48737,48763,12,48793,48819,12,48849,48875,12,48905,48931,12,48961,48987,12,49017,49043,12,49073,49099,12,49129,49155,12,49185,49211,12,49241,49267,12,49297,49323,12,49353,49379,12,49409,49435,12,49465,49491,12,49521,49547,12,49577,49603,12,49633,49659,12,49689,49715,12,49745,49771,12,49801,49827,12,49857,49883,12,49913,49939,12,49969,49995,12,50025,50051,12,50081,50107,12,50137,50163,12,50193,50219,12,50249,50275,12,50305,50331,12,50361,50387,12,50417,50443,12,50473,50499,12,50529,50555,12,50585,50611,12,50641,50667,12,50697,50723,12,50753,50779,12,50809,50835,12,50865,50891,12,50921,50947,12,50977,51003,12,51033,51059,12,51089,51115,12,51145,51171,12,51201,51227,12,51257,51283,12,51313,51339,12,51369,51395,12,51425,51451,12,51481,51507,12,51537,51563,12,51593,51619,12,51649,51675,12,51705,51731,12,51761,51787,12,51817,51843,12,51873,51899,12,51929,51955,12,51985,52011,12,52041,52067,12,52097,52123,12,52153,52179,12,52209,52235,12,52265,52291,12,52321,52347,12,52377,52403,12,52433,52459,12,52489,52515,12,52545,52571,12,52601,52627,12,52657,52683,12,52713,52739,12,52769,52795,12,52825,52851,12,52881,52907,12,52937,52963,12,52993,53019,12,53049,53075,12,53105,53131,12,53161,53187,12,53217,53243,12,53273,53299,12,53329,53355,12,53385,53411,12,53441,53467,12,53497,53523,12,53553,53579,12,53609,53635,12,53665,53691,12,53721,53747,12,53777,53803,12,53833,53859,12,53889,53915,12,53945,53971,12,54001,54027,12,54057,54083,12,54113,54139,12,54169,54195,12,54225,54251,12,54281,54307,12,54337,54363,12,54393,54419,12,54449,54475,12,54505,54531,12,54561,54587,12,54617,54643,12,54673,54699,12,54729,54755,12,54785,54811,12,54841,54867,12,54897,54923,12,54953,54979,12,55009,55035,12,55065,55091,12,55121,55147,12,55177,55203,12,65024,65039,5,65520,65528,4,66422,66426,5,68152,68154,5,69291,69292,5,69633,69633,5,69747,69748,5,69811,69814,5,69826,69826,5,69932,69932,7,70016,70017,5,70079,70080,7,70095,70095,5,70196,70196,5,70367,70367,5,70402,70403,7,70464,70464,5,70487,70487,5,70709,70711,7,70725,70725,7,70833,70834,7,70843,70844,7,70849,70849,7,71090,71093,5,71103,71104,5,71227,71228,7,71339,71339,5,71344,71349,5,71458,71461,5,71727,71735,5,71985,71989,7,71998,71998,5,72002,72002,7,72154,72155,5,72193,72202,5,72251,72254,5,72281,72283,5,72344,72345,5,72766,72766,7,72874,72880,5,72885,72886,5,73023,73029,5,73104,73105,5,73111,73111,5,92912,92916,5,94095,94098,5,113824,113827,4,119142,119142,7,119155,119162,4,119362,119364,5,121476,121476,5,122888,122904,5,123184,123190,5,125252,125258,5,127183,127183,14,127340,127343,14,127377,127386,14,127491,127503,14,127548,127551,14,127744,127756,14,127761,127761,14,127769,127769,14,127773,127774,14,127780,127788,14,127796,127797,14,127820,127823,14,127869,127869,14,127894,127895,14,127902,127903,14,127943,127943,14,127947,127950,14,127972,127972,14,127988,127988,14,127992,127994,14,128009,128011,14,128019,128019,14,128023,128041,14,128064,128064,14,128102,128107,14,128174,128181,14,128238,128238,14,128246,128247,14,128254,128254,14,128264,128264,14,128278,128299,14,128329,128330,14,128348,128359,14,128371,128377,14,128392,128393,14,128401,128404,14,128421,128421,14,128433,128434,14,128450,128452,14,128476,128478,14,128483,128483,14,128495,128495,14,128506,128506,14,128519,128520,14,128528,128528,14,128534,128534,14,128538,128538,14,128540,128542,14,128544,128549,14,128552,128555,14,128557,128557,14,128560,128563,14,128565,128565,14,128567,128576,14,128581,128591,14,128641,128642,14,128646,128646,14,128648,128648,14,128650,128651,14,128653,128653,14,128655,128655,14,128657,128659,14,128661,128661,14,128663,128663,14,128665,128666,14,128674,128674,14,128676,128677,14,128679,128685,14,128690,128690,14,128694,128694,14,128697,128702,14,128704,128704,14,128710,128714,14,128716,128716,14,128720,128720,14,128723,128724,14,128726,128727,14,128733,128735,14,128742,128744,14,128746,128746,14,128749,128751,14,128753,128754,14,128756,128758,14,128761,128761,14,128763,128764,14,128884,128895,14,128992,129003,14,129008,129008,14,129036,129039,14,129114,129119,14,129198,129279,14,129293,129295,14,129305,129310,14,129312,129319,14,129328,129328,14,129331,129338,14,129343,129343,14,129351,129355,14,129357,129359,14,129375,129387,14,129393,129393,14,129395,129398,14,129401,129401,14,129403,129403,14,129408,129412,14,129426,129431,14,129443,129444,14,129451,129453,14,129456,129465,14,129472,129472,14,129475,129482,14,129484,129484,14,129488,129510,14,129536,129647,14,129652,129652,14,129656,129658,14,129661,129663,14,129667,129670,14,129680,129685,14,129705,129708,14,129712,129718,14,129723,129727,14,129731,129733,14,129744,129750,14,129754,129759,14,129768,129775,14,129783,129791,14,917504,917504,4,917506,917535,4,917632,917759,4,918000,921599,4,0,9,4,11,12,4,14,31,4,169,169,14,174,174,14,1155,1159,5,1425,1469,5,1473,1474,5,1479,1479,5,1552,1562,5,1611,1631,5,1750,1756,5,1759,1764,5,1770,1773,5,1809,1809,5,1958,1968,5,2045,2045,5,2075,2083,5,2089,2093,5,2192,2193,1,2250,2273,5,2275,2306,5,2362,2362,5,2364,2364,5,2369,2376,5,2381,2381,5,2385,2391,5,2433,2433,5,2492,2492,5,2495,2496,7,2503,2504,7,2509,2509,5,2530,2531,5,2561,2562,5,2620,2620,5,2625,2626,5,2635,2637,5,2672,2673,5,2689,2690,5,2748,2748,5,2753,2757,5,2761,2761,7,2765,2765,5,2810,2815,5,2818,2819,7,2878,2878,5,2880,2880,7,2887,2888,7,2893,2893,5,2903,2903,5,2946,2946,5,3007,3007,7,3009,3010,7,3018,3020,7,3031,3031,5,3073,3075,7,3132,3132,5,3137,3140,7,3146,3149,5,3170,3171,5,3202,3203,7,3262,3262,7,3264,3265,7,3267,3268,7,3271,3272,7,3276,3277,5,3298,3299,5,3330,3331,7,3390,3390,5,3393,3396,5,3402,3404,7,3406,3406,1,3426,3427,5,3458,3459,7,3535,3535,5,3538,3540,5,3544,3550,7,3570,3571,7,3635,3635,7,3655,3662,5,3763,3763,7,3784,3789,5,3893,3893,5,3897,3897,5,3953,3966,5,3968,3972,5,3981,3991,5,4038,4038,5,4145,4145,7,4153,4154,5,4157,4158,5,4184,4185,5,4209,4212,5,4228,4228,7,4237,4237,5,4352,4447,8,4520,4607,10,5906,5908,5,5938,5939,5,5970,5971,5,6068,6069,5,6071,6077,5,6086,6086,5,6089,6099,5,6155,6157,5,6159,6159,5,6313,6313,5,6435,6438,7,6441,6443,7,6450,6450,5,6457,6459,5,6681,6682,7,6741,6741,7,6743,6743,7,6752,6752,5,6757,6764,5,6771,6780,5,6832,6845,5,6847,6862,5,6916,6916,7,6965,6965,5,6971,6971,7,6973,6977,7,6979,6980,7,7040,7041,5,7073,7073,7,7078,7079,7,7082,7082,7,7142,7142,5,7144,7145,5,7149,7149,5,7151,7153,5,7204,7211,7,7220,7221,7,7376,7378,5,7393,7393,7,7405,7405,5,7415,7415,7,7616,7679,5,8204,8204,5,8206,8207,4,8233,8233,4,8252,8252,14,8288,8292,4,8294,8303,4,8413,8416,5,8418,8420,5,8482,8482,14,8596,8601,14,8986,8987,14,9096,9096,14,9193,9196,14,9199,9199,14,9201,9202,14,9208,9210,14,9642,9643,14,9664,9664,14,9728,9729,14,9732,9732,14,9735,9741,14,9743,9744,14,9746,9746,14,9750,9751,14,9753,9756,14,9758,9759,14,9761,9761,14,9764,9765,14,9767,9769,14,9771,9773,14,9775,9775,14,9784,9785,14,9787,9791,14,9793,9793,14,9795,9799,14,9812,9822,14,9824,9824,14,9827,9827,14,9829,9830,14,9832,9832,14,9851,9851,14,9854,9854,14,9856,9861,14,9874,9874,14,9876,9876,14,9878,9879,14,9881,9881,14,9883,9884,14,9888,9889,14,9895,9895,14,9898,9899,14,9904,9905,14,9917,9918,14,9924,9925,14,9928,9928,14,9934,9934,14,9936,9936,14,9938,9938,14,9940,9940,14,9961,9961,14,9963,9967,14,9970,9971,14,9973,9973,14,9975,9977,14,9979,9980,14,9982,9985,14,9987,9988,14,9992,9996,14,9998,9998,14,10000,10001,14,10004,10004,14,10013,10013,14,10024,10024,14,10052,10052,14,10060,10060,14,10067,10069,14,10083,10083,14,10085,10087,14,10145,10145,14,10175,10175,14,11013,11015,14,11088,11088,14,11503,11505,5,11744,11775,5,12334,12335,5,12349,12349,14,12951,12951,14,42607,42607,5,42612,42621,5,42736,42737,5,43014,43014,5,43043,43044,7,43047,43047,7,43136,43137,7,43204,43205,5,43263,43263,5,43335,43345,5,43360,43388,8,43395,43395,7,43444,43445,7,43450,43451,7,43454,43456,7,43561,43566,5,43569,43570,5,43573,43574,5,43596,43596,5,43644,43644,5,43698,43700,5,43710,43711,5,43755,43755,7,43758,43759,7,43766,43766,5,44005,44005,5,44008,44008,5,44012,44012,7,44032,44032,11,44060,44060,11,44088,44088,11,44116,44116,11,44144,44144,11,44172,44172,11,44200,44200,11,44228,44228,11,44256,44256,11,44284,44284,11,44312,44312,11,44340,44340,11,44368,44368,11,44396,44396,11,44424,44424,11,44452,44452,11,44480,44480,11,44508,44508,11,44536,44536,11,44564,44564,11,44592,44592,11,44620,44620,11,44648,44648,11,44676,44676,11,44704,44704,11,44732,44732,11,44760,44760,11,44788,44788,11,44816,44816,11,44844,44844,11,44872,44872,11,44900,44900,11,44928,44928,11,44956,44956,11,44984,44984,11,45012,45012,11,45040,45040,11,45068,45068,11,45096,45096,11,45124,45124,11,45152,45152,11,45180,45180,11,45208,45208,11,45236,45236,11,45264,45264,11,45292,45292,11,45320,45320,11,45348,45348,11,45376,45376,11,45404,45404,11,45432,45432,11,45460,45460,11,45488,45488,11,45516,45516,11,45544,45544,11,45572,45572,11,45600,45600,11,45628,45628,11,45656,45656,11,45684,45684,11,45712,45712,11,45740,45740,11,45768,45768,11,45796,45796,11,45824,45824,11,45852,45852,11,45880,45880,11,45908,45908,11,45936,45936,11,45964,45964,11,45992,45992,11,46020,46020,11,46048,46048,11,46076,46076,11,46104,46104,11,46132,46132,11,46160,46160,11,46188,46188,11,46216,46216,11,46244,46244,11,46272,46272,11,46300,46300,11,46328,46328,11,46356,46356,11,46384,46384,11,46412,46412,11,46440,46440,11,46468,46468,11,46496,46496,11,46524,46524,11,46552,46552,11,46580,46580,11,46608,46608,11,46636,46636,11,46664,46664,11,46692,46692,11,46720,46720,11,46748,46748,11,46776,46776,11,46804,46804,11,46832,46832,11,46860,46860,11,46888,46888,11,46916,46916,11,46944,46944,11,46972,46972,11,47000,47000,11,47028,47028,11,47056,47056,11,47084,47084,11,47112,47112,11,47140,47140,11,47168,47168,11,47196,47196,11,47224,47224,11,47252,47252,11,47280,47280,11,47308,47308,11,47336,47336,11,47364,47364,11,47392,47392,11,47420,47420,11,47448,47448,11,47476,47476,11,47504,47504,11,47532,47532,11,47560,47560,11,47588,47588,11,47616,47616,11,47644,47644,11,47672,47672,11,47700,47700,11,47728,47728,11,47756,47756,11,47784,47784,11,47812,47812,11,47840,47840,11,47868,47868,11,47896,47896,11,47924,47924,11,47952,47952,11,47980,47980,11,48008,48008,11,48036,48036,11,48064,48064,11,48092,48092,11,48120,48120,11,48148,48148,11,48176,48176,11,48204,48204,11,48232,48232,11,48260,48260,11,48288,48288,11,48316,48316,11,48344,48344,11,48372,48372,11,48400,48400,11,48428,48428,11,48456,48456,11,48484,48484,11,48512,48512,11,48540,48540,11,48568,48568,11,48596,48596,11,48624,48624,11,48652,48652,11,48680,48680,11,48708,48708,11,48736,48736,11,48764,48764,11,48792,48792,11,48820,48820,11,48848,48848,11,48876,48876,11,48904,48904,11,48932,48932,11,48960,48960,11,48988,48988,11,49016,49016,11,49044,49044,11,49072,49072,11,49100,49100,11,49128,49128,11,49156,49156,11,49184,49184,11,49212,49212,11,49240,49240,11,49268,49268,11,49296,49296,11,49324,49324,11,49352,49352,11,49380,49380,11,49408,49408,11,49436,49436,11,49464,49464,11,49492,49492,11,49520,49520,11,49548,49548,11,49576,49576,11,49604,49604,11,49632,49632,11,49660,49660,11,49688,49688,11,49716,49716,11,49744,49744,11,49772,49772,11,49800,49800,11,49828,49828,11,49856,49856,11,49884,49884,11,49912,49912,11,49940,49940,11,49968,49968,11,49996,49996,11,50024,50024,11,50052,50052,11,50080,50080,11,50108,50108,11,50136,50136,11,50164,50164,11,50192,50192,11,50220,50220,11,50248,50248,11,50276,50276,11,50304,50304,11,50332,50332,11,50360,50360,11,50388,50388,11,50416,50416,11,50444,50444,11,50472,50472,11,50500,50500,11,50528,50528,11,50556,50556,11,50584,50584,11,50612,50612,11,50640,50640,11,50668,50668,11,50696,50696,11,50724,50724,11,50752,50752,11,50780,50780,11,50808,50808,11,50836,50836,11,50864,50864,11,50892,50892,11,50920,50920,11,50948,50948,11,50976,50976,11,51004,51004,11,51032,51032,11,51060,51060,11,51088,51088,11,51116,51116,11,51144,51144,11,51172,51172,11,51200,51200,11,51228,51228,11,51256,51256,11,51284,51284,11,51312,51312,11,51340,51340,11,51368,51368,11,51396,51396,11,51424,51424,11,51452,51452,11,51480,51480,11,51508,51508,11,51536,51536,11,51564,51564,11,51592,51592,11,51620,51620,11,51648,51648,11,51676,51676,11,51704,51704,11,51732,51732,11,51760,51760,11,51788,51788,11,51816,51816,11,51844,51844,11,51872,51872,11,51900,51900,11,51928,51928,11,51956,51956,11,51984,51984,11,52012,52012,11,52040,52040,11,52068,52068,11,52096,52096,11,52124,52124,11,52152,52152,11,52180,52180,11,52208,52208,11,52236,52236,11,52264,52264,11,52292,52292,11,52320,52320,11,52348,52348,11,52376,52376,11,52404,52404,11,52432,52432,11,52460,52460,11,52488,52488,11,52516,52516,11,52544,52544,11,52572,52572,11,52600,52600,11,52628,52628,11,52656,52656,11,52684,52684,11,52712,52712,11,52740,52740,11,52768,52768,11,52796,52796,11,52824,52824,11,52852,52852,11,52880,52880,11,52908,52908,11,52936,52936,11,52964,52964,11,52992,52992,11,53020,53020,11,53048,53048,11,53076,53076,11,53104,53104,11,53132,53132,11,53160,53160,11,53188,53188,11,53216,53216,11,53244,53244,11,53272,53272,11,53300,53300,11,53328,53328,11,53356,53356,11,53384,53384,11,53412,53412,11,53440,53440,11,53468,53468,11,53496,53496,11,53524,53524,11,53552,53552,11,53580,53580,11,53608,53608,11,53636,53636,11,53664,53664,11,53692,53692,11,53720,53720,11,53748,53748,11,53776,53776,11,53804,53804,11,53832,53832,11,53860,53860,11,53888,53888,11,53916,53916,11,53944,53944,11,53972,53972,11,54000,54000,11,54028,54028,11,54056,54056,11,54084,54084,11,54112,54112,11,54140,54140,11,54168,54168,11,54196,54196,11,54224,54224,11,54252,54252,11,54280,54280,11,54308,54308,11,54336,54336,11,54364,54364,11,54392,54392,11,54420,54420,11,54448,54448,11,54476,54476,11,54504,54504,11,54532,54532,11,54560,54560,11,54588,54588,11,54616,54616,11,54644,54644,11,54672,54672,11,54700,54700,11,54728,54728,11,54756,54756,11,54784,54784,11,54812,54812,11,54840,54840,11,54868,54868,11,54896,54896,11,54924,54924,11,54952,54952,11,54980,54980,11,55008,55008,11,55036,55036,11,55064,55064,11,55092,55092,11,55120,55120,11,55148,55148,11,55176,55176,11,55216,55238,9,64286,64286,5,65056,65071,5,65438,65439,5,65529,65531,4,66272,66272,5,68097,68099,5,68108,68111,5,68159,68159,5,68900,68903,5,69446,69456,5,69632,69632,7,69634,69634,7,69744,69744,5,69759,69761,5,69808,69810,7,69815,69816,7,69821,69821,1,69837,69837,1,69927,69931,5,69933,69940,5,70003,70003,5,70018,70018,7,70070,70078,5,70082,70083,1,70094,70094,7,70188,70190,7,70194,70195,7,70197,70197,7,70206,70206,5,70368,70370,7,70400,70401,5,70459,70460,5,70463,70463,7,70465,70468,7,70475,70477,7,70498,70499,7,70512,70516,5,70712,70719,5,70722,70724,5,70726,70726,5,70832,70832,5,70835,70840,5,70842,70842,5,70845,70845,5,70847,70848,5,70850,70851,5,71088,71089,7,71096,71099,7,71102,71102,7,71132,71133,5,71219,71226,5,71229,71229,5,71231,71232,5,71340,71340,7,71342,71343,7,71350,71350,7,71453,71455,5,71462,71462,7,71724,71726,7,71736,71736,7,71984,71984,5,71991,71992,7,71997,71997,7,71999,71999,1,72001,72001,1,72003,72003,5,72148,72151,5,72156,72159,7,72164,72164,7,72243,72248,5,72250,72250,1,72263,72263,5,72279,72280,7,72324,72329,1,72343,72343,7,72751,72751,7,72760,72765,5,72767,72767,5,72873,72873,7,72881,72881,7,72884,72884,7,73009,73014,5,73020,73021,5,73030,73030,1,73098,73102,7,73107,73108,7,73110,73110,7,73459,73460,5,78896,78904,4,92976,92982,5,94033,94087,7,94180,94180,5,113821,113822,5,118528,118573,5,119141,119141,5,119143,119145,5,119150,119154,5,119163,119170,5,119210,119213,5,121344,121398,5,121461,121461,5,121499,121503,5,122880,122886,5,122907,122913,5,122918,122922,5,123566,123566,5,125136,125142,5,126976,126979,14,126981,127182,14,127184,127231,14,127279,127279,14,127344,127345,14,127374,127374,14,127405,127461,14,127489,127490,14,127514,127514,14,127538,127546,14,127561,127567,14,127570,127743,14,127757,127758,14,127760,127760,14,127762,127762,14,127766,127768,14,127770,127770,14,127772,127772,14,127775,127776,14,127778,127779,14,127789,127791,14,127794,127795,14,127798,127798,14,127819,127819,14,127824,127824,14,127868,127868,14,127870,127871,14,127892,127893,14,127896,127896,14,127900,127901,14,127904,127940,14,127942,127942,14,127944,127944,14,127946,127946,14,127951,127955,14,127968,127971,14,127973,127984,14,127987,127987,14,127989,127989,14,127991,127991,14,127995,127999,5,128008,128008,14,128012,128014,14,128017,128018,14,128020,128020,14,128022,128022,14,128042,128042,14,128063,128063,14,128065,128065,14,128101,128101,14,128108,128109,14,128173,128173,14,128182,128183,14,128236,128237,14,128239,128239,14,128245,128245,14,128248,128248,14,128253,128253,14,128255,128258,14,128260,128263,14,128265,128265,14,128277,128277,14,128300,128301,14,128326,128328,14,128331,128334,14,128336,128347,14,128360,128366,14,128369,128370,14,128378,128378,14,128391,128391,14,128394,128397,14,128400,128400,14,128405,128406,14,128420,128420,14,128422,128423,14,128425,128432,14,128435,128443,14,128445,128449,14,128453,128464,14,128468,128475,14,128479,128480,14,128482,128482,14,128484,128487,14,128489,128494,14,128496,128498,14,128500,128505,14,128507,128511,14,128513,128518,14,128521,128525,14,128527,128527,14,128529,128529,14,128533,128533,14,128535,128535,14,128537,128537,14]")}function _e(k,I){if(k===0)return 0;const V=ye(k,I);if(V!==void 0)return V;const H=new q(I,k);return H.prevCodePoint(),H.offset}function ye(k,I){const V=new q(I,k);let H=V.prevCodePoint();for(;Ee(H)||H===65039||H===8419;){if(V.offset===0)return;H=V.prevCodePoint()}if(!pe(H))return;let Y=V.offset;return Y>0&&V.prevCodePoint()===8205&&(Y=V.offset),Y}function Ee(k){return 127995<=k&&k<=127999}n.noBreakWhitespace="\xA0";class K{static{this.ambiguousCharacterData=new x.Lazy(()=>JSON.parse('{"_common":[8232,32,8233,32,5760,32,8192,32,8193,32,8194,32,8195,32,8196,32,8197,32,8198,32,8200,32,8201,32,8202,32,8287,32,8199,32,8239,32,2042,95,65101,95,65102,95,65103,95,8208,45,8209,45,8210,45,65112,45,1748,45,8259,45,727,45,8722,45,10134,45,11450,45,1549,44,1643,44,8218,44,184,44,42233,44,894,59,2307,58,2691,58,1417,58,1795,58,1796,58,5868,58,65072,58,6147,58,6153,58,8282,58,1475,58,760,58,42889,58,8758,58,720,58,42237,58,451,33,11601,33,660,63,577,63,2429,63,5038,63,42731,63,119149,46,8228,46,1793,46,1794,46,42510,46,68176,46,1632,46,1776,46,42232,46,1373,96,65287,96,8219,96,8242,96,1370,96,1523,96,8175,96,65344,96,900,96,8189,96,8125,96,8127,96,8190,96,697,96,884,96,712,96,714,96,715,96,756,96,699,96,701,96,700,96,702,96,42892,96,1497,96,2036,96,2037,96,5194,96,5836,96,94033,96,94034,96,65339,91,10088,40,10098,40,12308,40,64830,40,65341,93,10089,41,10099,41,12309,41,64831,41,10100,123,119060,123,10101,125,65342,94,8270,42,1645,42,8727,42,66335,42,5941,47,8257,47,8725,47,8260,47,9585,47,10187,47,10744,47,119354,47,12755,47,12339,47,11462,47,20031,47,12035,47,65340,92,65128,92,8726,92,10189,92,10741,92,10745,92,119311,92,119355,92,12756,92,20022,92,12034,92,42872,38,708,94,710,94,5869,43,10133,43,66203,43,8249,60,10094,60,706,60,119350,60,5176,60,5810,60,5120,61,11840,61,12448,61,42239,61,8250,62,10095,62,707,62,119351,62,5171,62,94015,62,8275,126,732,126,8128,126,8764,126,65372,124,65293,45,120784,50,120794,50,120804,50,120814,50,120824,50,130034,50,42842,50,423,50,1000,50,42564,50,5311,50,42735,50,119302,51,120785,51,120795,51,120805,51,120815,51,120825,51,130035,51,42923,51,540,51,439,51,42858,51,11468,51,1248,51,94011,51,71882,51,120786,52,120796,52,120806,52,120816,52,120826,52,130036,52,5070,52,71855,52,120787,53,120797,53,120807,53,120817,53,120827,53,130037,53,444,53,71867,53,120788,54,120798,54,120808,54,120818,54,120828,54,130038,54,11474,54,5102,54,71893,54,119314,55,120789,55,120799,55,120809,55,120819,55,120829,55,130039,55,66770,55,71878,55,2819,56,2538,56,2666,56,125131,56,120790,56,120800,56,120810,56,120820,56,120830,56,130040,56,547,56,546,56,66330,56,2663,57,2920,57,2541,57,3437,57,120791,57,120801,57,120811,57,120821,57,120831,57,130041,57,42862,57,11466,57,71884,57,71852,57,71894,57,9082,97,65345,97,119834,97,119886,97,119938,97,119990,97,120042,97,120094,97,120146,97,120198,97,120250,97,120302,97,120354,97,120406,97,120458,97,593,97,945,97,120514,97,120572,97,120630,97,120688,97,120746,97,65313,65,119808,65,119860,65,119912,65,119964,65,120016,65,120068,65,120120,65,120172,65,120224,65,120276,65,120328,65,120380,65,120432,65,913,65,120488,65,120546,65,120604,65,120662,65,120720,65,5034,65,5573,65,42222,65,94016,65,66208,65,119835,98,119887,98,119939,98,119991,98,120043,98,120095,98,120147,98,120199,98,120251,98,120303,98,120355,98,120407,98,120459,98,388,98,5071,98,5234,98,5551,98,65314,66,8492,66,119809,66,119861,66,119913,66,120017,66,120069,66,120121,66,120173,66,120225,66,120277,66,120329,66,120381,66,120433,66,42932,66,914,66,120489,66,120547,66,120605,66,120663,66,120721,66,5108,66,5623,66,42192,66,66178,66,66209,66,66305,66,65347,99,8573,99,119836,99,119888,99,119940,99,119992,99,120044,99,120096,99,120148,99,120200,99,120252,99,120304,99,120356,99,120408,99,120460,99,7428,99,1010,99,11429,99,43951,99,66621,99,128844,67,71922,67,71913,67,65315,67,8557,67,8450,67,8493,67,119810,67,119862,67,119914,67,119966,67,120018,67,120174,67,120226,67,120278,67,120330,67,120382,67,120434,67,1017,67,11428,67,5087,67,42202,67,66210,67,66306,67,66581,67,66844,67,8574,100,8518,100,119837,100,119889,100,119941,100,119993,100,120045,100,120097,100,120149,100,120201,100,120253,100,120305,100,120357,100,120409,100,120461,100,1281,100,5095,100,5231,100,42194,100,8558,68,8517,68,119811,68,119863,68,119915,68,119967,68,120019,68,120071,68,120123,68,120175,68,120227,68,120279,68,120331,68,120383,68,120435,68,5024,68,5598,68,5610,68,42195,68,8494,101,65349,101,8495,101,8519,101,119838,101,119890,101,119942,101,120046,101,120098,101,120150,101,120202,101,120254,101,120306,101,120358,101,120410,101,120462,101,43826,101,1213,101,8959,69,65317,69,8496,69,119812,69,119864,69,119916,69,120020,69,120072,69,120124,69,120176,69,120228,69,120280,69,120332,69,120384,69,120436,69,917,69,120492,69,120550,69,120608,69,120666,69,120724,69,11577,69,5036,69,42224,69,71846,69,71854,69,66182,69,119839,102,119891,102,119943,102,119995,102,120047,102,120099,102,120151,102,120203,102,120255,102,120307,102,120359,102,120411,102,120463,102,43829,102,42905,102,383,102,7837,102,1412,102,119315,70,8497,70,119813,70,119865,70,119917,70,120021,70,120073,70,120125,70,120177,70,120229,70,120281,70,120333,70,120385,70,120437,70,42904,70,988,70,120778,70,5556,70,42205,70,71874,70,71842,70,66183,70,66213,70,66853,70,65351,103,8458,103,119840,103,119892,103,119944,103,120048,103,120100,103,120152,103,120204,103,120256,103,120308,103,120360,103,120412,103,120464,103,609,103,7555,103,397,103,1409,103,119814,71,119866,71,119918,71,119970,71,120022,71,120074,71,120126,71,120178,71,120230,71,120282,71,120334,71,120386,71,120438,71,1292,71,5056,71,5107,71,42198,71,65352,104,8462,104,119841,104,119945,104,119997,104,120049,104,120101,104,120153,104,120205,104,120257,104,120309,104,120361,104,120413,104,120465,104,1211,104,1392,104,5058,104,65320,72,8459,72,8460,72,8461,72,119815,72,119867,72,119919,72,120023,72,120179,72,120231,72,120283,72,120335,72,120387,72,120439,72,919,72,120494,72,120552,72,120610,72,120668,72,120726,72,11406,72,5051,72,5500,72,42215,72,66255,72,731,105,9075,105,65353,105,8560,105,8505,105,8520,105,119842,105,119894,105,119946,105,119998,105,120050,105,120102,105,120154,105,120206,105,120258,105,120310,105,120362,105,120414,105,120466,105,120484,105,618,105,617,105,953,105,8126,105,890,105,120522,105,120580,105,120638,105,120696,105,120754,105,1110,105,42567,105,1231,105,43893,105,5029,105,71875,105,65354,106,8521,106,119843,106,119895,106,119947,106,119999,106,120051,106,120103,106,120155,106,120207,106,120259,106,120311,106,120363,106,120415,106,120467,106,1011,106,1112,106,65322,74,119817,74,119869,74,119921,74,119973,74,120025,74,120077,74,120129,74,120181,74,120233,74,120285,74,120337,74,120389,74,120441,74,42930,74,895,74,1032,74,5035,74,5261,74,42201,74,119844,107,119896,107,119948,107,120000,107,120052,107,120104,107,120156,107,120208,107,120260,107,120312,107,120364,107,120416,107,120468,107,8490,75,65323,75,119818,75,119870,75,119922,75,119974,75,120026,75,120078,75,120130,75,120182,75,120234,75,120286,75,120338,75,120390,75,120442,75,922,75,120497,75,120555,75,120613,75,120671,75,120729,75,11412,75,5094,75,5845,75,42199,75,66840,75,1472,108,8739,73,9213,73,65512,73,1633,108,1777,73,66336,108,125127,108,120783,73,120793,73,120803,73,120813,73,120823,73,130033,73,65321,73,8544,73,8464,73,8465,73,119816,73,119868,73,119920,73,120024,73,120128,73,120180,73,120232,73,120284,73,120336,73,120388,73,120440,73,65356,108,8572,73,8467,108,119845,108,119897,108,119949,108,120001,108,120053,108,120105,73,120157,73,120209,73,120261,73,120313,73,120365,73,120417,73,120469,73,448,73,120496,73,120554,73,120612,73,120670,73,120728,73,11410,73,1030,73,1216,73,1493,108,1503,108,1575,108,126464,108,126592,108,65166,108,65165,108,1994,108,11599,73,5825,73,42226,73,93992,73,66186,124,66313,124,119338,76,8556,76,8466,76,119819,76,119871,76,119923,76,120027,76,120079,76,120131,76,120183,76,120235,76,120287,76,120339,76,120391,76,120443,76,11472,76,5086,76,5290,76,42209,76,93974,76,71843,76,71858,76,66587,76,66854,76,65325,77,8559,77,8499,77,119820,77,119872,77,119924,77,120028,77,120080,77,120132,77,120184,77,120236,77,120288,77,120340,77,120392,77,120444,77,924,77,120499,77,120557,77,120615,77,120673,77,120731,77,1018,77,11416,77,5047,77,5616,77,5846,77,42207,77,66224,77,66321,77,119847,110,119899,110,119951,110,120003,110,120055,110,120107,110,120159,110,120211,110,120263,110,120315,110,120367,110,120419,110,120471,110,1400,110,1404,110,65326,78,8469,78,119821,78,119873,78,119925,78,119977,78,120029,78,120081,78,120185,78,120237,78,120289,78,120341,78,120393,78,120445,78,925,78,120500,78,120558,78,120616,78,120674,78,120732,78,11418,78,42208,78,66835,78,3074,111,3202,111,3330,111,3458,111,2406,111,2662,111,2790,111,3046,111,3174,111,3302,111,3430,111,3664,111,3792,111,4160,111,1637,111,1781,111,65359,111,8500,111,119848,111,119900,111,119952,111,120056,111,120108,111,120160,111,120212,111,120264,111,120316,111,120368,111,120420,111,120472,111,7439,111,7441,111,43837,111,959,111,120528,111,120586,111,120644,111,120702,111,120760,111,963,111,120532,111,120590,111,120648,111,120706,111,120764,111,11423,111,4351,111,1413,111,1505,111,1607,111,126500,111,126564,111,126596,111,65259,111,65260,111,65258,111,65257,111,1726,111,64428,111,64429,111,64427,111,64426,111,1729,111,64424,111,64425,111,64423,111,64422,111,1749,111,3360,111,4125,111,66794,111,71880,111,71895,111,66604,111,1984,79,2534,79,2918,79,12295,79,70864,79,71904,79,120782,79,120792,79,120802,79,120812,79,120822,79,130032,79,65327,79,119822,79,119874,79,119926,79,119978,79,120030,79,120082,79,120134,79,120186,79,120238,79,120290,79,120342,79,120394,79,120446,79,927,79,120502,79,120560,79,120618,79,120676,79,120734,79,11422,79,1365,79,11604,79,4816,79,2848,79,66754,79,42227,79,71861,79,66194,79,66219,79,66564,79,66838,79,9076,112,65360,112,119849,112,119901,112,119953,112,120005,112,120057,112,120109,112,120161,112,120213,112,120265,112,120317,112,120369,112,120421,112,120473,112,961,112,120530,112,120544,112,120588,112,120602,112,120646,112,120660,112,120704,112,120718,112,120762,112,120776,112,11427,112,65328,80,8473,80,119823,80,119875,80,119927,80,119979,80,120031,80,120083,80,120187,80,120239,80,120291,80,120343,80,120395,80,120447,80,929,80,120504,80,120562,80,120620,80,120678,80,120736,80,11426,80,5090,80,5229,80,42193,80,66197,80,119850,113,119902,113,119954,113,120006,113,120058,113,120110,113,120162,113,120214,113,120266,113,120318,113,120370,113,120422,113,120474,113,1307,113,1379,113,1382,113,8474,81,119824,81,119876,81,119928,81,119980,81,120032,81,120084,81,120188,81,120240,81,120292,81,120344,81,120396,81,120448,81,11605,81,119851,114,119903,114,119955,114,120007,114,120059,114,120111,114,120163,114,120215,114,120267,114,120319,114,120371,114,120423,114,120475,114,43847,114,43848,114,7462,114,11397,114,43905,114,119318,82,8475,82,8476,82,8477,82,119825,82,119877,82,119929,82,120033,82,120189,82,120241,82,120293,82,120345,82,120397,82,120449,82,422,82,5025,82,5074,82,66740,82,5511,82,42211,82,94005,82,65363,115,119852,115,119904,115,119956,115,120008,115,120060,115,120112,115,120164,115,120216,115,120268,115,120320,115,120372,115,120424,115,120476,115,42801,115,445,115,1109,115,43946,115,71873,115,66632,115,65331,83,119826,83,119878,83,119930,83,119982,83,120034,83,120086,83,120138,83,120190,83,120242,83,120294,83,120346,83,120398,83,120450,83,1029,83,1359,83,5077,83,5082,83,42210,83,94010,83,66198,83,66592,83,119853,116,119905,116,119957,116,120009,116,120061,116,120113,116,120165,116,120217,116,120269,116,120321,116,120373,116,120425,116,120477,116,8868,84,10201,84,128872,84,65332,84,119827,84,119879,84,119931,84,119983,84,120035,84,120087,84,120139,84,120191,84,120243,84,120295,84,120347,84,120399,84,120451,84,932,84,120507,84,120565,84,120623,84,120681,84,120739,84,11430,84,5026,84,42196,84,93962,84,71868,84,66199,84,66225,84,66325,84,119854,117,119906,117,119958,117,120010,117,120062,117,120114,117,120166,117,120218,117,120270,117,120322,117,120374,117,120426,117,120478,117,42911,117,7452,117,43854,117,43858,117,651,117,965,117,120534,117,120592,117,120650,117,120708,117,120766,117,1405,117,66806,117,71896,117,8746,85,8899,85,119828,85,119880,85,119932,85,119984,85,120036,85,120088,85,120140,85,120192,85,120244,85,120296,85,120348,85,120400,85,120452,85,1357,85,4608,85,66766,85,5196,85,42228,85,94018,85,71864,85,8744,118,8897,118,65366,118,8564,118,119855,118,119907,118,119959,118,120011,118,120063,118,120115,118,120167,118,120219,118,120271,118,120323,118,120375,118,120427,118,120479,118,7456,118,957,118,120526,118,120584,118,120642,118,120700,118,120758,118,1141,118,1496,118,71430,118,43945,118,71872,118,119309,86,1639,86,1783,86,8548,86,119829,86,119881,86,119933,86,119985,86,120037,86,120089,86,120141,86,120193,86,120245,86,120297,86,120349,86,120401,86,120453,86,1140,86,11576,86,5081,86,5167,86,42719,86,42214,86,93960,86,71840,86,66845,86,623,119,119856,119,119908,119,119960,119,120012,119,120064,119,120116,119,120168,119,120220,119,120272,119,120324,119,120376,119,120428,119,120480,119,7457,119,1121,119,1309,119,1377,119,71434,119,71438,119,71439,119,43907,119,71919,87,71910,87,119830,87,119882,87,119934,87,119986,87,120038,87,120090,87,120142,87,120194,87,120246,87,120298,87,120350,87,120402,87,120454,87,1308,87,5043,87,5076,87,42218,87,5742,120,10539,120,10540,120,10799,120,65368,120,8569,120,119857,120,119909,120,119961,120,120013,120,120065,120,120117,120,120169,120,120221,120,120273,120,120325,120,120377,120,120429,120,120481,120,5441,120,5501,120,5741,88,9587,88,66338,88,71916,88,65336,88,8553,88,119831,88,119883,88,119935,88,119987,88,120039,88,120091,88,120143,88,120195,88,120247,88,120299,88,120351,88,120403,88,120455,88,42931,88,935,88,120510,88,120568,88,120626,88,120684,88,120742,88,11436,88,11613,88,5815,88,42219,88,66192,88,66228,88,66327,88,66855,88,611,121,7564,121,65369,121,119858,121,119910,121,119962,121,120014,121,120066,121,120118,121,120170,121,120222,121,120274,121,120326,121,120378,121,120430,121,120482,121,655,121,7935,121,43866,121,947,121,8509,121,120516,121,120574,121,120632,121,120690,121,120748,121,1199,121,4327,121,71900,121,65337,89,119832,89,119884,89,119936,89,119988,89,120040,89,120092,89,120144,89,120196,89,120248,89,120300,89,120352,89,120404,89,120456,89,933,89,978,89,120508,89,120566,89,120624,89,120682,89,120740,89,11432,89,1198,89,5033,89,5053,89,42220,89,94019,89,71844,89,66226,89,119859,122,119911,122,119963,122,120015,122,120067,122,120119,122,120171,122,120223,122,120275,122,120327,122,120379,122,120431,122,120483,122,7458,122,43923,122,71876,122,66293,90,71909,90,65338,90,8484,90,8488,90,119833,90,119885,90,119937,90,119989,90,120041,90,120197,90,120249,90,120301,90,120353,90,120405,90,120457,90,918,90,120493,90,120551,90,120609,90,120667,90,120725,90,5059,90,42204,90,71849,90,65282,34,65284,36,65285,37,65286,38,65290,42,65291,43,65294,46,65295,47,65296,48,65297,49,65298,50,65299,51,65300,52,65301,53,65302,54,65303,55,65304,56,65305,57,65308,60,65309,61,65310,62,65312,64,65316,68,65318,70,65319,71,65324,76,65329,81,65330,82,65333,85,65334,86,65335,87,65343,95,65346,98,65348,100,65350,102,65355,107,65357,109,65358,110,65361,113,65362,114,65364,116,65365,117,65367,119,65370,122,65371,123,65373,125,119846,109],"_default":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"cs":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"de":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"es":[8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"fr":[65374,126,65306,58,65281,33,8216,96,8245,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"it":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"ja":[8211,45,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65292,44,65307,59],"ko":[8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"pl":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"pt-BR":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"qps-ploc":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"ru":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,305,105,921,73,1009,112,215,120,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"tr":[160,32,8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"zh-hans":[65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41],"zh-hant":[8211,45,65374,126,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65307,59]}'))}static{this.cache=new i.LRUCachedFunction({getCacheKey:JSON.stringify},I=>{function V(se){const ce=new Map;for(let he=0;he!se.startsWith("_")&&se in te);ne.length===0&&(ne=["_default"]);let ae;for(const se of ne){const ce=V(te[se]);ae=Y(ae,ce)}const le=V(te._common),oe=H(le,ae);return new K(oe)})}static getInstance(I){return K.cache.get(Array.from(I))}static{this._locales=new x.Lazy(()=>Object.keys(K.ambiguousCharacterData.value).filter(I=>!I.startsWith("_")))}static getLocales(){return K._locales.value}constructor(I){this.confusableDictionary=I}isAmbiguous(I){return this.confusableDictionary.has(I)}getPrimaryConfusable(I){return this.confusableDictionary.get(I)}getConfusableCodePoints(){return new Set(this.confusableDictionary.keys())}}n.AmbiguousCharacters=K;class Q{static getRawData(){return JSON.parse("[9,10,11,12,13,32,127,160,173,847,1564,4447,4448,6068,6069,6155,6156,6157,6158,7355,7356,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8234,8235,8236,8237,8238,8239,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,10240,12288,12644,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65279,65440,65520,65521,65522,65523,65524,65525,65526,65527,65528,65532,78844,119155,119156,119157,119158,119159,119160,119161,119162,917504,917505,917506,917507,917508,917509,917510,917511,917512,917513,917514,917515,917516,917517,917518,917519,917520,917521,917522,917523,917524,917525,917526,917527,917528,917529,917530,917531,917532,917533,917534,917535,917536,917537,917538,917539,917540,917541,917542,917543,917544,917545,917546,917547,917548,917549,917550,917551,917552,917553,917554,917555,917556,917557,917558,917559,917560,917561,917562,917563,917564,917565,917566,917567,917568,917569,917570,917571,917572,917573,917574,917575,917576,917577,917578,917579,917580,917581,917582,917583,917584,917585,917586,917587,917588,917589,917590,917591,917592,917593,917594,917595,917596,917597,917598,917599,917600,917601,917602,917603,917604,917605,917606,917607,917608,917609,917610,917611,917612,917613,917614,917615,917616,917617,917618,917619,917620,917621,917622,917623,917624,917625,917626,917627,917628,917629,917630,917631,917760,917761,917762,917763,917764,917765,917766,917767,917768,917769,917770,917771,917772,917773,917774,917775,917776,917777,917778,917779,917780,917781,917782,917783,917784,917785,917786,917787,917788,917789,917790,917791,917792,917793,917794,917795,917796,917797,917798,917799,917800,917801,917802,917803,917804,917805,917806,917807,917808,917809,917810,917811,917812,917813,917814,917815,917816,917817,917818,917819,917820,917821,917822,917823,917824,917825,917826,917827,917828,917829,917830,917831,917832,917833,917834,917835,917836,917837,917838,917839,917840,917841,917842,917843,917844,917845,917846,917847,917848,917849,917850,917851,917852,917853,917854,917855,917856,917857,917858,917859,917860,917861,917862,917863,917864,917865,917866,917867,917868,917869,917870,917871,917872,917873,917874,917875,917876,917877,917878,917879,917880,917881,917882,917883,917884,917885,917886,917887,917888,917889,917890,917891,917892,917893,917894,917895,917896,917897,917898,917899,917900,917901,917902,917903,917904,917905,917906,917907,917908,917909,917910,917911,917912,917913,917914,917915,917916,917917,917918,917919,917920,917921,917922,917923,917924,917925,917926,917927,917928,917929,917930,917931,917932,917933,917934,917935,917936,917937,917938,917939,917940,917941,917942,917943,917944,917945,917946,917947,917948,917949,917950,917951,917952,917953,917954,917955,917956,917957,917958,917959,917960,917961,917962,917963,917964,917965,917966,917967,917968,917969,917970,917971,917972,917973,917974,917975,917976,917977,917978,917979,917980,917981,917982,917983,917984,917985,917986,917987,917988,917989,917990,917991,917992,917993,917994,917995,917996,917997,917998,917999]")}static{this._data=void 0}static getData(){return this._data||(this._data=new Set(Q.getRawData())),this._data}static isInvisibleCharacter(I){return Q.getData().has(I)}static get codePoints(){return Q.getData()}}n.InvisibleCharacters=Q}),X(J[44],Z([0,1,6]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.StringSHA1=void 0,n.hash=x,n.doHash=A,n.numberHash=d,n.stringHash=p,n.toHexString=r;function x(o){return A(o,0)}function A(o,u){switch(typeof o){case"object":return o===null?d(349,u):Array.isArray(o)?c(o,u):a(o,u);case"string":return p(o,u);case"boolean":return f(o,u);case"number":return d(o,u);case"undefined":return d(937,u);default:return d(617,u)}}function d(o,u){return(u<<5)-u+o|0}function f(o,u){return d(o?433:863,u)}function p(o,u){u=d(149417,u);for(let S=0,L=o.length;SA(L,S),u)}function a(o,u){return u=d(181387,u),Object.keys(o).sort().reduce((S,L)=>(S=p(L,S),A(o[L],S)),u)}function m(o,u,S=32){const L=S-u,N=~((1<>>L)>>>0}function e(o,u=0,S=o.byteLength,L=0){for(let N=0;NS.toString(16).padStart(2,"0")).join(""):h((o>>>0).toString(16),u/4)}class s{static{this._bigBlock32=new DataView(new ArrayBuffer(320))}constructor(){this._h0=1732584193,this._h1=4023233417,this._h2=2562383102,this._h3=271733878,this._h4=3285377520,this._buff=new Uint8Array(67),this._buffDV=new DataView(this._buff.buffer),this._buffLen=0,this._totalLen=0,this._leftoverHighSurrogate=0,this._finished=!1}update(u){const S=u.length;if(S===0)return;const L=this._buff;let N=this._buffLen,P=this._leftoverHighSurrogate,E,v;for(P!==0?(E=P,v=-1,P=0):(E=u.charCodeAt(0),v=0);;){let l=E;if(i.isHighSurrogate(E))if(v+1>>6,u[S++]=128|(L&63)>>>0):L<65536?(u[S++]=224|(L&61440)>>>12,u[S++]=128|(L&4032)>>>6,u[S++]=128|(L&63)>>>0):(u[S++]=240|(L&1835008)>>>18,u[S++]=128|(L&258048)>>>12,u[S++]=128|(L&4032)>>>6,u[S++]=128|(L&63)>>>0),S>=64&&(this._step(),S-=64,this._totalLen+=64,u[0]=u[64],u[1]=u[65],u[2]=u[66]),S}digest(){return this._finished||(this._finished=!0,this._leftoverHighSurrogate&&(this._leftoverHighSurrogate=0,this._buffLen=this._push(this._buff,this._buffLen,65533)),this._totalLen+=this._buffLen,this._wrapUp()),r(this._h0)+r(this._h1)+r(this._h2)+r(this._h3)+r(this._h4)}_wrapUp(){this._buff[this._buffLen++]=128,e(this._buff,this._buffLen),this._buffLen>56&&(this._step(),e(this._buff));const u=8*this._totalLen;this._buffDV.setUint32(56,Math.floor(u/4294967296),!1),this._buffDV.setUint32(60,u%4294967296,!1),this._step()}_step(){const u=s._bigBlock32,S=this._buffDV;for(let w=0;w<64;w+=4)u.setUint32(w,S.getUint32(w,!1),!1);for(let w=64;w<320;w+=4)u.setUint32(w,m(u.getUint32(w-12,!1)^u.getUint32(w-32,!1)^u.getUint32(w-56,!1)^u.getUint32(w-64,!1),1),!1);let L=this._h0,N=this._h1,P=this._h2,E=this._h3,v=this._h4,l,b,g;for(let w=0;w<80;w++)w<20?(l=N&P|~N&E,b=1518500249):w<40?(l=N^P^E,b=1859775393):w<60?(l=N&P|N&E|P&E,b=2400959708):(l=N^P^E,b=3395469782),g=m(L,5)+l+v+b+u.getUint32(w*4,!1)&4294967295,v=E,E=P,P=m(N,30),N=L,L=g;this._h0=this._h0+L&4294967295,this._h1=this._h1+N&4294967295,this._h2=this._h2+P&4294967295,this._h3=this._h3+E&4294967295,this._h4=this._h4+v&4294967295}}n.StringSHA1=s}),X(J[24],Z([0,1,41,44]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.LcsDiff=n.StringDiffSequence=void 0,n.stringDiff=d;class A{constructor(e){this.source=e}getElements(){const e=this.source,h=new Int32Array(e.length);for(let r=0,s=e.length;r0||this.m_modifiedCount>0)&&this.m_changes.push(new i.DiffChange(this.m_originalStart,this.m_originalCount,this.m_modifiedStart,this.m_modifiedCount)),this.m_originalCount=0,this.m_modifiedCount=0,this.m_originalStart=1073741824,this.m_modifiedStart=1073741824}AddOriginalElement(e,h){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,h),this.m_originalCount++}AddModifiedElement(e,h){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,h),this.m_modifiedCount++}getChanges(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes}getReverseChanges(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes.reverse(),this.m_changes}}class a{constructor(e,h,r=null){this.ContinueProcessingPredicate=r,this._originalSequence=e,this._modifiedSequence=h;const[s,o,u]=a._getElements(e),[S,L,N]=a._getElements(h);this._hasStrings=u&&N,this._originalStringElements=s,this._originalElementsOrHash=o,this._modifiedStringElements=S,this._modifiedElementsOrHash=L,this.m_forwardHistory=[],this.m_reverseHistory=[]}static _isStringArray(e){return e.length>0&&typeof e[0]=="string"}static _getElements(e){const h=e.getElements();if(a._isStringArray(h)){const r=new Int32Array(h.length);for(let s=0,o=h.length;s=e&&s>=r&&this.ElementsAreEqual(h,s);)h--,s--;if(e>h||r>s){let E;return r<=s?(f.Assert(e===h+1,"originalStart should only be one more than originalEnd"),E=[new i.DiffChange(e,0,r,s-r+1)]):e<=h?(f.Assert(r===s+1,"modifiedStart should only be one more than modifiedEnd"),E=[new i.DiffChange(e,h-e+1,r,0)]):(f.Assert(e===h+1,"originalStart should only be one more than originalEnd"),f.Assert(r===s+1,"modifiedStart should only be one more than modifiedEnd"),E=[]),E}const u=[0],S=[0],L=this.ComputeRecursionPoint(e,h,r,s,u,S,o),N=u[0],P=S[0];if(L!==null)return L;if(!o[0]){const E=this.ComputeDiffRecursive(e,N,r,P,o);let v=[];return o[0]?v=[new i.DiffChange(N+1,h-(N+1)+1,P+1,s-(P+1)+1)]:v=this.ComputeDiffRecursive(N+1,h,P+1,s,o),this.ConcatenateChanges(E,v)}return[new i.DiffChange(e,h-e+1,r,s-r+1)]}WALKTRACE(e,h,r,s,o,u,S,L,N,P,E,v,l,b,g,w,M,y){let _=null,C=null,R=new c,D=h,T=r,O=l[0]-w[0]-s,z=-1073741824,j=this.m_forwardHistory.length-1;do{const F=O+e;F===D||F=0&&(N=this.m_forwardHistory[j],e=N[0],D=1,T=N.length-1)}while(--j>=-1);if(_=R.getReverseChanges(),y[0]){let F=l[0]+1,q=w[0]+1;if(_!==null&&_.length>0){const B=_[_.length-1];F=Math.max(F,B.getOriginalEnd()),q=Math.max(q,B.getModifiedEnd())}C=[new i.DiffChange(F,v-F+1,q,g-q+1)]}else{R=new c,D=u,T=S,O=l[0]-w[0]-L,z=1073741824,j=M?this.m_reverseHistory.length-1:this.m_reverseHistory.length-2;do{const F=O+o;F===D||F=P[F+1]?(E=P[F+1]-1,b=E-O-L,E>z&&R.MarkNextChange(),z=E+1,R.AddOriginalElement(E+1,b+1),O=F+1-o):(E=P[F-1],b=E-O-L,E>z&&R.MarkNextChange(),z=E,R.AddModifiedElement(E+1,b+1),O=F-1-o),j>=0&&(P=this.m_reverseHistory[j],o=P[0],D=1,T=P.length-1)}while(--j>=-1);C=R.getChanges()}return this.ConcatenateChanges(_,C)}ComputeRecursionPoint(e,h,r,s,o,u,S){let L=0,N=0,P=0,E=0,v=0,l=0;e--,r--,o[0]=0,u[0]=0,this.m_forwardHistory=[],this.m_reverseHistory=[];const b=h-e+(s-r),g=b+1,w=new Int32Array(g),M=new Int32Array(g),y=s-r,_=h-e,C=e-r,R=h-s,T=(_-y)%2===0;w[y]=e,M[_]=h,S[0]=!1;for(let O=1;O<=b/2+1;O++){let z=0,j=0;P=this.ClipDiagonalBound(y-O,O,y,g),E=this.ClipDiagonalBound(y+O,O,y,g);for(let q=P;q<=E;q+=2){q===P||qz+j&&(z=L,j=N),!T&&Math.abs(q-_)<=O-1&&L>=M[q])return o[0]=L,u[0]=N,B<=M[q]&&O<=1448?this.WALKTRACE(y,P,E,C,_,v,l,R,w,M,L,h,o,N,s,u,T,S):null}const F=(z-e+(j-r)-O)/2;if(this.ContinueProcessingPredicate!==null&&!this.ContinueProcessingPredicate(z,F))return S[0]=!0,o[0]=z,u[0]=j,F>0&&O<=1448?this.WALKTRACE(y,P,E,C,_,v,l,R,w,M,L,h,o,N,s,u,T,S):(e++,r++,[new i.DiffChange(e,h-e+1,r,s-r+1)]);v=this.ClipDiagonalBound(_-O,O,_,g),l=this.ClipDiagonalBound(_+O,O,_,g);for(let q=v;q<=l;q+=2){q===v||q=M[q+1]?L=M[q+1]-1:L=M[q-1],N=L-(q-_)-R;const B=L;for(;L>e&&N>r&&this.ElementsAreEqual(L,N);)L--,N--;if(M[q]=L,T&&Math.abs(q-y)<=O&&L<=w[q])return o[0]=L,u[0]=N,B>=w[q]&&O<=1448?this.WALKTRACE(y,P,E,C,_,v,l,R,w,M,L,h,o,N,s,u,T,S):null}if(O<=1447){let q=new Int32Array(E-P+2);q[0]=y-P+1,p.Copy2(w,P,q,1,E-P+1),this.m_forwardHistory.push(q),q=new Int32Array(l-v+2),q[0]=_-v+1,p.Copy2(M,v,q,1,l-v+1),this.m_reverseHistory.push(q)}}return this.WALKTRACE(y,P,E,C,_,v,l,R,w,M,L,h,o,N,s,u,T,S)}PrettifyChanges(e){for(let h=0;h0,S=r.modifiedLength>0;for(;r.originalStart+r.originalLength=0;h--){const r=e[h];let s=0,o=0;if(h>0){const E=e[h-1];s=E.originalStart+E.originalLength,o=E.modifiedStart+E.modifiedLength}const u=r.originalLength>0,S=r.modifiedLength>0;let L=0,N=this._boundaryScore(r.originalStart,r.originalLength,r.modifiedStart,r.modifiedLength);for(let E=1;;E++){const v=r.originalStart-E,l=r.modifiedStart-E;if(vN&&(N=g,L=E)}r.originalStart-=L,r.modifiedStart-=L;const P=[null];if(h>0&&this.ChangesOverlap(e[h-1],e[h],P)){e[h-1]=P[0],e.splice(h,1),h++;continue}}if(this._hasStrings)for(let h=1,r=e.length;h0&&l>L&&(L=l,N=E,P=v)}return L>0?[N,P]:null}_contiguousSequenceScore(e,h,r){let s=0;for(let o=0;o=this._originalElementsOrHash.length-1?!0:this._hasStrings&&/^\s*$/.test(this._originalStringElements[e])}_OriginalRegionIsBoundary(e,h){if(this._OriginalIsBoundary(e)||this._OriginalIsBoundary(e-1))return!0;if(h>0){const r=e+h;if(this._OriginalIsBoundary(r-1)||this._OriginalIsBoundary(r))return!0}return!1}_ModifiedIsBoundary(e){return e<=0||e>=this._modifiedElementsOrHash.length-1?!0:this._hasStrings&&/^\s*$/.test(this._modifiedStringElements[e])}_ModifiedRegionIsBoundary(e,h){if(this._ModifiedIsBoundary(e)||this._ModifiedIsBoundary(e-1))return!0;if(h>0){const r=e+h;if(this._ModifiedIsBoundary(r-1)||this._ModifiedIsBoundary(r))return!0}return!1}_boundaryScore(e,h,r,s){const o=this._OriginalRegionIsBoundary(e,h)?1:0,u=this._ModifiedRegionIsBoundary(r,s)?1:0;return o+u}ConcatenateChanges(e,h){const r=[];if(e.length===0||h.length===0)return h.length>0?h:e;if(this.ChangesOverlap(e[e.length-1],h[0],r)){const s=new Array(e.length+h.length-1);return p.Copy(e,0,s,0,e.length-1),s[e.length-1]=r[0],p.Copy(h,1,s,e.length,h.length-1),s}else{const s=new Array(e.length+h.length);return p.Copy(e,0,s,0,e.length),p.Copy(h,0,s,e.length,h.length),s}}ChangesOverlap(e,h,r){if(f.Assert(e.originalStart<=h.originalStart,"Left change is not less than or equal to right change"),f.Assert(e.modifiedStart<=h.modifiedStart,"Left change is not less than or equal to right change"),e.originalStart+e.originalLength>=h.originalStart||e.modifiedStart+e.modifiedLength>=h.modifiedStart){const s=e.originalStart;let o=e.originalLength;const u=e.modifiedStart;let S=e.modifiedLength;return e.originalStart+e.originalLength>=h.originalStart&&(o=h.originalStart+h.originalLength-e.originalStart),e.modifiedStart+e.modifiedLength>=h.modifiedStart&&(S=h.modifiedStart+h.modifiedLength-e.modifiedStart),r[0]=new i.DiffChange(s,o,u,S),!0}else return r[0]=null,!1}ClipDiagonalBound(e,h,r,s){if(e>=0&&e"u"}function a(u){return!m(u)}function m(u){return c(u)||u===null}function e(u,S){if(!u)throw new Error(S?`Unexpected type, expected '${S}'`:"Unexpected type")}function h(u){if(m(u))throw new Error("Assertion Failed: argument is undefined or null");return u}function r(u){return typeof u=="function"}function s(u,S){const L=Math.min(u.length,S.length);for(let N=0;N{s[o]=u&&typeof u=="object"?x(u):u}),s}function A(r){if(!r||typeof r!="object")return r;const s=[r];for(;s.length>0;){const o=s.shift();Object.freeze(o);for(const u in o)if(d.call(o,u)){const S=o[u];typeof S=="object"&&!Object.isFrozen(S)&&!(0,i.isTypedArray)(S)&&s.push(S)}}return r}const d=Object.prototype.hasOwnProperty;function f(r,s){return p(r,s,new Set)}function p(r,s,o){if((0,i.isUndefinedOrNull)(r))return r;const u=s(r);if(typeof u<"u")return u;if(Array.isArray(r)){const S=[];for(const L of r)S.push(p(L,s,o));return S}if((0,i.isObject)(r)){if(o.has(r))throw new Error("Cannot clone recursive data-structure");o.add(r);const S={};for(const L in r)d.call(r,L)&&(S[L]=p(r[L],s,o));return o.delete(r),S}return r}function c(r,s,o=!0){return(0,i.isObject)(r)?((0,i.isObject)(s)&&Object.keys(s).forEach(u=>{u in r?o&&((0,i.isObject)(r[u])&&(0,i.isObject)(s[u])?c(r[u],s[u],o):r[u]=s[u]):r[u]=s[u]}),r):s}function a(r,s){if(r===s)return!0;if(r==null||s===null||s===void 0||typeof r!=typeof s||typeof r!="object"||Array.isArray(r)!==Array.isArray(s))return!1;let o,u;if(Array.isArray(r)){if(r.length!==s.length)return!1;for(o=0;ofunction(){const L=Array.prototype.slice.call(arguments,0);return s(S,L)},u={};for(const S of r)u[S]=o(S);return u}}),X(J[28],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.toUint8=i,n.toUint32=x;function i(A){return A<0?0:A>255?255:A|0}function x(A){return A<0?0:A>4294967295?4294967295:A|0}}),X(J[29],Z([0,1,28]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.CharacterSet=n.CharacterClassifier=void 0;class x{constructor(f){const p=(0,i.toUint8)(f);this._defaultValue=p,this._asciiMap=x._createAsciiMap(p),this._map=new Map}static _createAsciiMap(f){const p=new Uint8Array(256);return p.fill(f),p}set(f,p){const c=(0,i.toUint8)(p);f>=0&&f<256?this._asciiMap[f]=c:this._map.set(f,c)}get(f){return f>=0&&f<256?this._asciiMap[f]:this._map.get(f)||this._defaultValue}clear(){this._asciiMap.fill(this._defaultValue),this._map.clear()}}n.CharacterClassifier=x;class A{constructor(){this._actual=new x(0)}add(f){this._actual.set(f,1)}has(f){return this._actual.get(f)===1}clear(){return this._actual.clear()}}n.CharacterSet=A}),X(J[5],Z([0,1,3]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.OffsetRangeSet=n.OffsetRange=void 0;class x{static addRange(f,p){let c=0;for(;cp))return new x(f,p)}static ofLength(f){return new x(0,f)}static ofStartAndLength(f,p){return new x(f,f+p)}constructor(f,p){if(this.start=f,this.endExclusive=p,f>p)throw new i.BugIndicatingError(`Invalid range: ${this.toString()}`)}get isEmpty(){return this.start===this.endExclusive}delta(f){return new x(this.start+f,this.endExclusive+f)}deltaStart(f){return new x(this.start+f,this.endExclusive)}deltaEnd(f){return new x(this.start,this.endExclusive+f)}get length(){return this.endExclusive-this.start}toString(){return`[${this.start}, ${this.endExclusive})`}contains(f){return this.start<=f&&f=f.endExclusive}slice(f){return f.slice(this.start,this.endExclusive)}substring(f){return f.substring(this.start,this.endExclusive)}clip(f){if(this.isEmpty)throw new i.BugIndicatingError(`Invalid clipping range: ${this.toString()}`);return Math.max(this.start,Math.min(this.endExclusive-1,f))}clipCyclic(f){if(this.isEmpty)throw new i.BugIndicatingError(`Invalid clipping range: ${this.toString()}`);return f=this.endExclusive?this.start+(f-this.start)%this.length:f}forEach(f){for(let p=this.start;pf.toString()).join(", ")}intersectsStrict(f){let p=0;for(;pf+p.length,0)}}n.OffsetRangeSet=A}),X(J[4],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.Position=void 0;class i{constructor(A,d){this.lineNumber=A,this.column=d}with(A=this.lineNumber,d=this.column){return A===this.lineNumber&&d===this.column?this:new i(A,d)}delta(A=0,d=0){return this.with(this.lineNumber+A,this.column+d)}equals(A){return i.equals(this,A)}static equals(A,d){return!A&&!d?!0:!!A&&!!d&&A.lineNumber===d.lineNumber&&A.column===d.column}isBefore(A){return i.isBefore(this,A)}static isBefore(A,d){return A.lineNumberp||d===p&&f>c?(this.startLineNumber=p,this.startColumn=c,this.endLineNumber=d,this.endColumn=f):(this.startLineNumber=d,this.startColumn=f,this.endLineNumber=p,this.endColumn=c)}isEmpty(){return x.isEmpty(this)}static isEmpty(d){return d.startLineNumber===d.endLineNumber&&d.startColumn===d.endColumn}containsPosition(d){return x.containsPosition(this,d)}static containsPosition(d,f){return!(f.lineNumberd.endLineNumber||f.lineNumber===d.startLineNumber&&f.columnd.endColumn)}static strictContainsPosition(d,f){return!(f.lineNumberd.endLineNumber||f.lineNumber===d.startLineNumber&&f.column<=d.startColumn||f.lineNumber===d.endLineNumber&&f.column>=d.endColumn)}containsRange(d){return x.containsRange(this,d)}static containsRange(d,f){return!(f.startLineNumberd.endLineNumber||f.endLineNumber>d.endLineNumber||f.startLineNumber===d.startLineNumber&&f.startColumnd.endColumn)}strictContainsRange(d){return x.strictContainsRange(this,d)}static strictContainsRange(d,f){return!(f.startLineNumberd.endLineNumber||f.endLineNumber>d.endLineNumber||f.startLineNumber===d.startLineNumber&&f.startColumn<=d.startColumn||f.endLineNumber===d.endLineNumber&&f.endColumn>=d.endColumn)}plusRange(d){return x.plusRange(this,d)}static plusRange(d,f){let p,c,a,m;return f.startLineNumberd.endLineNumber?(a=f.endLineNumber,m=f.endColumn):f.endLineNumber===d.endLineNumber?(a=f.endLineNumber,m=Math.max(f.endColumn,d.endColumn)):(a=d.endLineNumber,m=d.endColumn),new x(p,c,a,m)}intersectRanges(d){return x.intersectRanges(this,d)}static intersectRanges(d,f){let p=d.startLineNumber,c=d.startColumn,a=d.endLineNumber,m=d.endColumn;const e=f.startLineNumber,h=f.startColumn,r=f.endLineNumber,s=f.endColumn;return pr?(a=r,m=s):a===r&&(m=Math.min(m,s)),p>a||p===a&&c>m?null:new x(p,c,a,m)}equalsRange(d){return x.equalsRange(this,d)}static equalsRange(d,f){return!d&&!f?!0:!!d&&!!f&&d.startLineNumber===f.startLineNumber&&d.startColumn===f.startColumn&&d.endLineNumber===f.endLineNumber&&d.endColumn===f.endColumn}getEndPosition(){return x.getEndPosition(this)}static getEndPosition(d){return new i.Position(d.endLineNumber,d.endColumn)}getStartPosition(){return x.getStartPosition(this)}static getStartPosition(d){return new i.Position(d.startLineNumber,d.startColumn)}toString(){return"["+this.startLineNumber+","+this.startColumn+" -> "+this.endLineNumber+","+this.endColumn+"]"}setEndPosition(d,f){return new x(this.startLineNumber,this.startColumn,d,f)}setStartPosition(d,f){return new x(d,f,this.endLineNumber,this.endColumn)}collapseToStart(){return x.collapseToStart(this)}static collapseToStart(d){return new x(d.startLineNumber,d.startColumn,d.startLineNumber,d.startColumn)}collapseToEnd(){return x.collapseToEnd(this)}static collapseToEnd(d){return new x(d.endLineNumber,d.endColumn,d.endLineNumber,d.endColumn)}delta(d){return new x(this.startLineNumber+d,this.startColumn,this.endLineNumber+d,this.endColumn)}static fromPositions(d,f=d){return new x(d.lineNumber,d.column,f.lineNumber,f.column)}static lift(d){return d?new x(d.startLineNumber,d.startColumn,d.endLineNumber,d.endColumn):null}static isIRange(d){return d&&typeof d.startLineNumber=="number"&&typeof d.startColumn=="number"&&typeof d.endLineNumber=="number"&&typeof d.endColumn=="number"}static areIntersectingOrTouching(d,f){return!(d.endLineNumberd.startLineNumber}toJSON(){return this}}n.Range=x}),X(J[13],Z([0,1,3,5,2,15]),function(W,n,i,x,A,d){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.LineRangeSet=n.LineRange=void 0;class f{static fromRangeInclusive(a){return new f(a.startLineNumber,a.endLineNumber+1)}static joinMany(a){if(a.length===0)return[];let m=new p(a[0].slice());for(let e=1;em)throw new i.BugIndicatingError(`startLineNumber ${a} cannot be after endLineNumberExclusive ${m}`);this.startLineNumber=a,this.endLineNumberExclusive=m}contains(a){return this.startLineNumber<=a&&ah.endLineNumberExclusive>=a.startLineNumber),e=(0,d.findLastIdxMonotonous)(this._normalizedRanges,h=>h.startLineNumber<=a.endLineNumberExclusive)+1;if(m===e)this._normalizedRanges.splice(m,0,a);else if(m===e-1){const h=this._normalizedRanges[m];this._normalizedRanges[m]=h.join(a)}else{const h=this._normalizedRanges[m].join(this._normalizedRanges[e-1]).join(a);this._normalizedRanges.splice(m,e-m,h)}}contains(a){const m=(0,d.findLastMonotonous)(this._normalizedRanges,e=>e.startLineNumber<=a);return!!m&&m.endLineNumberExclusive>a}intersects(a){const m=(0,d.findLastMonotonous)(this._normalizedRanges,e=>e.startLineNumbera.startLineNumber}getUnion(a){if(this._normalizedRanges.length===0)return a;if(a._normalizedRanges.length===0)return this;const m=[];let e=0,h=0,r=null;for(;e=s.startLineNumber?r=new f(r.startLineNumber,Math.max(r.endLineNumberExclusive,s.endLineNumberExclusive)):(m.push(r),r=s)}return r!==null&&m.push(r),new p(m)}subtractFrom(a){const m=(0,d.findFirstIdxMonotonousOrArrLen)(this._normalizedRanges,s=>s.endLineNumberExclusive>=a.startLineNumber),e=(0,d.findLastIdxMonotonous)(this._normalizedRanges,s=>s.startLineNumber<=a.endLineNumberExclusive)+1;if(m===e)return new p([a]);const h=[];let r=a.startLineNumber;for(let s=m;sr&&h.push(new f(r,o.startLineNumber)),r=o.endLineNumberExclusive}return ra.toString()).join(", ")}getIntersection(a){const m=[];let e=0,h=0;for(;em.delta(a)))}}n.LineRangeSet=p}),X(J[48],Z([0,1,4,2]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.Selection=void 0;class A extends x.Range{constructor(f,p,c,a){super(f,p,c,a),this.selectionStartLineNumber=f,this.selectionStartColumn=p,this.positionLineNumber=c,this.positionColumn=a}toString(){return"["+this.selectionStartLineNumber+","+this.selectionStartColumn+" -> "+this.positionLineNumber+","+this.positionColumn+"]"}equalsSelection(f){return A.selectionsEqual(this,f)}static selectionsEqual(f,p){return f.selectionStartLineNumber===p.selectionStartLineNumber&&f.selectionStartColumn===p.selectionStartColumn&&f.positionLineNumber===p.positionLineNumber&&f.positionColumn===p.positionColumn}getDirection(){return this.selectionStartLineNumber===this.startLineNumber&&this.selectionStartColumn===this.startColumn?0:1}setEndPosition(f,p){return this.getDirection()===0?new A(this.startLineNumber,this.startColumn,f,p):new A(f,p,this.startLineNumber,this.startColumn)}getPosition(){return new i.Position(this.positionLineNumber,this.positionColumn)}getSelectionStart(){return new i.Position(this.selectionStartLineNumber,this.selectionStartColumn)}setStartPosition(f,p){return this.getDirection()===0?new A(f,p,this.endLineNumber,this.endColumn):new A(this.endLineNumber,this.endColumn,f,p)}static fromPositions(f,p=f){return new A(f.lineNumber,f.column,p.lineNumber,p.column)}static fromRange(f,p){return p===0?new A(f.startLineNumber,f.startColumn,f.endLineNumber,f.endColumn):new A(f.endLineNumber,f.endColumn,f.startLineNumber,f.startColumn)}static liftSelection(f){return new A(f.selectionStartLineNumber,f.selectionStartColumn,f.positionLineNumber,f.positionColumn)}static selectionsArrEqual(f,p){if(f&&!p||!f&&p)return!1;if(!f&&!p)return!0;if(f.length!==p.length)return!1;for(let c=0,a=f.length;cf.lineCount:this.columnCount>=f.columnCount}createRange(f){return this.lineCount===0?new x.Range(f.lineNumber,f.column,f.lineNumber,f.column+this.columnCount):new x.Range(f.lineNumber,f.column,f.lineNumber+this.lineCount,this.columnCount+1)}addToPosition(f){return this.lineCount===0?new i.Position(f.lineNumber,f.column+this.columnCount):new i.Position(f.lineNumber+this.lineCount,this.columnCount+1)}toString(){return`${this.lineCount},${this.columnCount}`}}n.TextLength=A}),X(J[49],Z([0,1,5,30]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.PositionOffsetTransformer=void 0;class A{constructor(f){this.text=f,this.lineStartOffsetByLineIdx=[],this.lineStartOffsetByLineIdx.push(0);for(let p=0;p(0,i.checkAdjacentItems)(s,(o,u)=>o.range.getEndPosition().isBeforeOrEqual(u.range.getStartPosition())))}apply(s){let o="",u=new A.Position(1,1);for(const L of this.edits){const N=L.range,P=N.getStartPosition(),E=N.getEndPosition(),v=m(u,P);v.isEmpty()||(o+=s.getValueOfRange(v)),o+=L.text,u=E}const S=m(u,s.endPositionExclusive);return S.isEmpty()||(o+=s.getValueOfRange(S)),o}applyToString(s){const o=new h(s);return this.apply(o)}getNewRanges(){const s=[];let o=0,u=0,S=0;for(const L of this.edits){const N=p.TextLength.ofText(L.text),P=A.Position.lift({lineNumber:L.range.startLineNumber+u,column:L.range.startColumn+(L.range.startLineNumber===o?S:0)}),E=N.createRange(P);s.push(E),u=E.endLineNumber-L.range.endLineNumber,S=E.endColumn-L.range.endColumn,o=L.range.endLineNumber}return s}}n.TextEdit=c;class a{constructor(s,o){this.range=s,this.text=o}toSingleEditOperation(){return{range:this.range,text:this.text}}}n.SingleTextEdit=a;function m(r,s){if(r.lineNumber===s.lineNumber&&r.column===Number.MAX_SAFE_INTEGER)return f.Range.fromPositions(s,s);if(!r.isBeforeOrEqual(s))throw new x.BugIndicatingError("start must be before end");return new f.Range(r.lineNumber,r.column,s.lineNumber,s.column)}class e{get endPositionExclusive(){return this.length.addToPosition(new A.Position(1,1))}}n.AbstractText=e;class h extends e{constructor(s){super(),this.value=s,this._t=new d.PositionOffsetTransformer(this.value)}getValueOfRange(s){return this._t.getOffsetRange(s).substring(this.value)}get length(){return this._t.textLength}}n.StringText=h}),X(J[51],Z([0,1,21,29]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.WordCharacterClassifier=void 0,n.getMapForWordSeparators=f;class A extends x.CharacterClassifier{constructor(c,a){super(0),this._segmenter=null,this._cachedLine=null,this._cachedSegments=[],this.intlSegmenterLocales=a,this.intlSegmenterLocales.length>0?this._segmenter=new Intl.Segmenter(this.intlSegmenterLocales,{granularity:"word"}):this._segmenter=null;for(let m=0,e=c.length;ma)break;m=e}return m}findNextIntlWordAtOrAfterOffset(c,a){for(const m of this._getIntlSegmenterWordsOnLine(c))if(!(m.index/?";function A(a=""){let m="(-?\\d*\\.\\d\\w*)|([^";for(const e of n.USUAL_WORD_SEPARATORS)a.indexOf(e)>=0||(m+="\\"+e);return m+="\\s]+)",new RegExp(m,"g")}n.DEFAULT_WORD_REGEXP=A();function d(a){let m=n.DEFAULT_WORD_REGEXP;if(a&&a instanceof RegExp)if(a.global)m=a;else{let e="g";a.ignoreCase&&(e+="i"),a.multiline&&(e+="m"),a.unicode&&(e+="u"),m=new RegExp(a.source,e)}return m.lastIndex=0,m}const f=new x.LinkedList;f.unshift({maxLen:1e3,windowSize:15,timeBudget:150});function p(a,m,e,h,r){if(m=d(m),r||(r=i.Iterable.first(f)),e.length>r.maxLen){let L=a-r.maxLen/2;return L<0?L=0:h+=L,e=e.substring(L,a+r.maxLen/2),p(a,m,e,h,r)}const s=Date.now(),o=a-1-h;let u=-1,S=null;for(let L=1;!(Date.now()-s>=r.timeBudget);L++){const N=o-r.windowSize*L;m.lastIndex=Math.max(0,N);const P=c(m,e,o,u);if(!P&&S||(S=P,N<=0))break;u=N}if(S){const L={word:S[0],startColumn:h+1+S.index,endColumn:h+1+S.index+S[0].length};return m.lastIndex=0,L}return null}function c(a,m,e,h){let r;for(;r=a.exec(m);){const s=r.index||0;if(s<=e&&a.lastIndex>=e)return r;if(h>0&&s>h)return null}return null}}),X(J[10],Z([0,1,7,3,5]),function(W,n,i,x,A){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.DateTimeout=n.InfiniteTimeout=n.OffsetPair=n.SequenceDiff=n.DiffAlgorithmResult=void 0;class d{static trivial(e,h){return new d([new f(A.OffsetRange.ofLength(e.length),A.OffsetRange.ofLength(h.length))],!1)}static trivialTimedOut(e,h){return new d([new f(A.OffsetRange.ofLength(e.length),A.OffsetRange.ofLength(h.length))],!0)}constructor(e,h){this.diffs=e,this.hitTimeout=h}}n.DiffAlgorithmResult=d;class f{static invert(e,h){const r=[];return(0,i.forEachAdjacent)(e,(s,o)=>{r.push(f.fromOffsetPairs(s?s.getEndExclusives():p.zero,o?o.getStarts():new p(h,(s?s.seq2Range.endExclusive-s.seq1Range.endExclusive:0)+h)))}),r}static fromOffsetPairs(e,h){return new f(new A.OffsetRange(e.offset1,h.offset1),new A.OffsetRange(e.offset2,h.offset2))}static assertSorted(e){let h;for(const r of e){if(h&&!(h.seq1Range.endExclusive<=r.seq1Range.start&&h.seq2Range.endExclusive<=r.seq2Range.start))throw new x.BugIndicatingError("Sequence diffs must be sorted");h=r}}constructor(e,h){this.seq1Range=e,this.seq2Range=h}swap(){return new f(this.seq2Range,this.seq1Range)}toString(){return`${this.seq1Range} <-> ${this.seq2Range}`}join(e){return new f(this.seq1Range.join(e.seq1Range),this.seq2Range.join(e.seq2Range))}delta(e){return e===0?this:new f(this.seq1Range.delta(e),this.seq2Range.delta(e))}deltaStart(e){return e===0?this:new f(this.seq1Range.deltaStart(e),this.seq2Range.deltaStart(e))}deltaEnd(e){return e===0?this:new f(this.seq1Range.deltaEnd(e),this.seq2Range.deltaEnd(e))}intersect(e){const h=this.seq1Range.intersect(e.seq1Range),r=this.seq2Range.intersect(e.seq2Range);if(!(!h||!r))return new f(h,r)}getStarts(){return new p(this.seq1Range.start,this.seq2Range.start)}getEndExclusives(){return new p(this.seq1Range.endExclusive,this.seq2Range.endExclusive)}}n.SequenceDiff=f;class p{static{this.zero=new p(0,0)}static{this.max=new p(Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER)}constructor(e,h){this.offset1=e,this.offset2=h}toString(){return`${this.offset1} <-> ${this.offset2}`}delta(e){return e===0?this:new p(this.offset1+e,this.offset2+e)}equals(e){return this.offset1===e.offset1&&this.offset2===e.offset2}}n.OffsetPair=p;class c{static{this.instance=new c}isValid(){return!0}}n.InfiniteTimeout=c;class a{constructor(e){if(this.timeout=e,this.startTime=Date.now(),this.valid=!0,e<=0)throw new x.BugIndicatingError("timeout must be positive")}isValid(){if(!(Date.now()-this.startTimeh.length||_>r.length)continue;const C=s(y,_);u.set(L,C);const R=y===w?S.get(L+1):S.get(L-1);if(S.set(L,C!==y?new d(R,y,_,C-y):R),u.get(L)===h.length&&u.get(L)-L===r.length)break e}}let N=S.get(L);const P=[];let E=h.length,v=r.length;for(;;){const l=N?N.x+N.length:0,b=N?N.y+N.length:0;if((l!==E||b!==v)&&P.push(new x.SequenceDiff(new i.OffsetRange(l,E),new i.OffsetRange(b,v))),!N)break;E=N.x,v=N.y,N=N.prev}return P.reverse(),new x.DiffAlgorithmResult(P,!1)}}n.MyersDiffAlgorithm=A;class d{constructor(a,m,e,h){this.prev=a,this.x=m,this.y=e,this.length=h}}class f{constructor(){this.positiveArr=new Int32Array(10),this.negativeArr=new Int32Array(10)}get(a){return a<0?(a=-a-1,this.negativeArr[a]):this.positiveArr[a]}set(a,m){if(a<0){if(a=-a-1,a>=this.negativeArr.length){const e=this.negativeArr;this.negativeArr=new Int32Array(e.length*2),this.negativeArr.set(e)}this.negativeArr[a]=m}else{if(a>=this.positiveArr.length){const e=this.positiveArr;this.positiveArr=new Int32Array(e.length*2),this.positiveArr.set(e)}this.positiveArr[a]=m}}}class p{constructor(){this.positiveArr=[],this.negativeArr=[]}get(a){return a<0?(a=-a-1,this.negativeArr[a]):this.positiveArr[a]}set(a,m){a<0?(a=-a-1,this.negativeArr[a]=m):this.positiveArr[a]=m}}}),X(J[52],Z([0,1,7,5,10]),function(W,n,i,x,A){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.optimizeSequenceDiffs=d,n.removeShortMatches=a,n.extendDiffsToEntireWordIfAppropriate=m,n.removeVeryShortMatchingLinesBetweenDiffs=h,n.removeVeryShortMatchingTextBetweenLongDiffs=r;function d(s,o,u){let S=u;return S=f(s,o,S),S=f(s,o,S),S=p(s,o,S),S}function f(s,o,u){if(u.length===0)return u;const S=[];S.push(u[0]);for(let N=1;N0&&(E=E.delta(l))}L.push(E)}return S.length>0&&L.push(S[S.length-1]),L}function p(s,o,u){if(!s.getBoundaryScore||!o.getBoundaryScore)return u;for(let S=0;S0?u[S-1]:void 0,N=u[S],P=S+1=S.start&&s.seq2Range.start-P>=L.start&&u.isStronglyEqual(s.seq2Range.start-P,s.seq2Range.endExclusive-P)&&P<100;)P++;P--;let E=0;for(;s.seq1Range.start+El&&(l=y,v=b)}return s.delta(v)}function a(s,o,u){const S=[];for(const L of u){const N=S[S.length-1];if(!N){S.push(L);continue}L.seq1Range.start-N.seq1Range.endExclusive<=2||L.seq2Range.start-N.seq2Range.endExclusive<=2?S[S.length-1]=new A.SequenceDiff(N.seq1Range.join(L.seq1Range),N.seq2Range.join(L.seq2Range)):S.push(L)}return S}function m(s,o,u){const S=A.SequenceDiff.invert(u,s.length),L=[];let N=new A.OffsetPair(0,0);function P(v,l){if(v.offset10;){const C=S[0];if(!(C.seq1Range.intersects(w.seq1Range)||C.seq2Range.intersects(w.seq2Range)))break;const D=s.findWordContaining(C.seq1Range.start),T=o.findWordContaining(C.seq2Range.start),O=new A.SequenceDiff(D,T),z=O.intersect(C);if(y+=z.seq1Range.length,_+=z.seq2Range.length,w=w.join(O),w.seq1Range.endExclusive>=C.seq1Range.endExclusive)S.shift();else break}y+_<(w.seq1Range.length+w.seq2Range.length)*2/3&&L.push(w),N=w.getEndExclusives()}for(;S.length>0;){const v=S.shift();v.seq1Range.isEmpty||(P(v.getStarts(),v),P(v.getEndExclusives().delta(-1),v))}return e(u,L)}function e(s,o){const u=[];for(;s.length>0||o.length>0;){const S=s[0],L=o[0];let N;S&&(!L||S.seq1Range.start0&&u[u.length-1].seq1Range.endExclusive>=N.seq1Range.start?u[u.length-1]=u[u.length-1].join(N):u.push(N)}return u}function h(s,o,u){let S=u;if(S.length===0)return S;let L=0,N;do{N=!1;const P=[S[0]];for(let E=1;E5||M.seq1Range.length+M.seq2Range.length>5)};const v=S[E],l=P[P.length-1];b(l,v)?(N=!0,P[P.length-1]=P[P.length-1].join(v)):P.push(v)}S=P}while(L++<10&&N);return S}function r(s,o,u){let S=u;if(S.length===0)return S;let L=0,N;do{N=!1;const E=[S[0]];for(let v=1;v5||_.length>500)return!1;const R=s.getText(_).trim();if(R.length>20||R.split(/\r\n|\r|\n/).length>1)return!1;const D=s.countLinesIn(M.seq1Range),T=M.seq1Range.length,O=o.countLinesIn(M.seq2Range),z=M.seq2Range.length,j=s.countLinesIn(y.seq1Range),F=y.seq1Range.length,q=o.countLinesIn(y.seq2Range),B=y.seq2Range.length,G=2*40+50;function $(U){return Math.min(U,G)}return Math.pow(Math.pow($(D*40+T),1.5)+Math.pow($(O*40+z),1.5),1.5)+Math.pow(Math.pow($(j*40+F),1.5)+Math.pow($(q*40+B),1.5),1.5)>(G**1.5)**1.5*1.3};const l=S[v],b=E[E.length-1];g(b,l)?(N=!0,E[E.length-1]=E[E.length-1].join(l)):E.push(l)}S=E}while(L++<10&&N);const P=[];return(0,i.forEachWithNeighbors)(S,(E,v,l)=>{let b=v;function g(R){return R.length>0&&R.trim().length<=3&&v.seq1Range.length+v.seq2Range.length>100}const w=s.extendToFullLines(v.seq1Range),M=s.getText(new x.OffsetRange(w.start,v.seq1Range.start));g(M)&&(b=b.deltaStart(-M.length));const y=s.getText(new x.OffsetRange(v.seq1Range.endExclusive,w.endExclusive));g(y)&&(b=b.deltaEnd(y.length));const _=A.SequenceDiff.fromOffsetPairs(E?E.getEndExclusives():A.OffsetPair.zero,l?l.getStarts():A.OffsetPair.max),C=b.intersect(_);P.length>0&&C.getStarts().equals(P[P.length-1].getEndExclusives())?P[P.length-1]=P[P.length-1].join(C):P.push(C)}),P}}),X(J[53],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.LineSequence=void 0;class i{constructor(d,f){this.trimmedHash=d,this.lines=f}getElement(d){return this.trimmedHash[d]}get length(){return this.trimmedHash.length}getBoundaryScore(d){const f=d===0?0:x(this.lines[d-1]),p=d===this.lines.length?0:x(this.lines[d]);return 1e3-(f+p)}getText(d){return this.lines.slice(d.start,d.endExclusive).join(` `)}isStronglyEqual(d,f){return this.lines[d]===this.lines[f]}}n.LineSequence=i;function x(A){let d=0;for(;d0&&E>0&&h.get(P-1,E-1)===3&&(b+=r.get(P-1,E-1)),b+=m?m(P,E):1):b=-1;const g=Math.max(v,l,b);if(g===b){const w=P>0&&E>0?r.get(P-1,E-1):0;r.set(P,E,w+1),h.set(P,E,3)}else g===v?(r.set(P,E,0),h.set(P,E,1)):g===l&&(r.set(P,E,0),h.set(P,E,2));e.set(P,E,g)}const s=[];let o=p.length,u=c.length;function S(P,E){(P+1!==o||E+1!==u)&&s.push(new x.SequenceDiff(new i.OffsetRange(P+1,o),new i.OffsetRange(E+1,u))),o=P,u=E}let L=p.length-1,N=c.length-1;for(;L>=0&&N>=0;)h.get(L,N)===3?(S(L,N),L--,N--):h.get(L,N)===1?L--:N--;return S(-1,-1),s.reverse(),new x.DiffAlgorithmResult(s,!1)}}n.DynamicProgrammingDiffing=d}),X(J[33],Z([0,1,15,5,4,2,16]),function(W,n,i,x,A,d,f){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.LinesSliceCharSequence=void 0;class p{constructor(r,s,o){this.lines=r,this.range=s,this.considerWhitespaceChanges=o,this.elements=[],this.firstElementOffsetByLineIdx=[],this.lineStartOffsets=[],this.trimmedWsLengthsByLineIdx=[],this.firstElementOffsetByLineIdx.push(0);for(let u=this.range.startLineNumber;u<=this.range.endLineNumber;u++){let S=r[u-1],L=0;u===this.range.startLineNumber&&this.range.startColumn>1&&(L=this.range.startColumn-1,S=S.substring(L)),this.lineStartOffsets.push(L);let N=0;if(!o){const E=S.trimStart();N=S.length-E.length,S=E.trimEnd()}this.trimmedWsLengthsByLineIdx.push(N);const P=u===this.range.endLineNumber?Math.min(this.range.endColumn-1-L-N,S.length):S.length;for(let E=0;EString.fromCharCode(s)).join("")}getElement(r){return this.elements[r]}get length(){return this.elements.length}getBoundaryScore(r){const s=e(r>0?this.elements[r-1]:-1),o=e(rS<=r),u=r-this.firstElementOffsetByLineIdx[o];return new A.Position(this.range.startLineNumber+o,1+this.lineStartOffsets[o]+u+(u===0&&s==="left"?0:this.trimmedWsLengthsByLineIdx[o]))}translateRange(r){const s=this.translateOffset(r.start,"right"),o=this.translateOffset(r.endExclusive,"left");return o.isBefore(s)?d.Range.fromPositions(o,o):d.Range.fromPositions(s,o)}findWordContaining(r){if(r<0||r>=this.elements.length||!c(this.elements[r]))return;let s=r;for(;s>0&&c(this.elements[s-1]);)s--;let o=r;for(;ou<=r.start)??0,o=(0,i.findFirstMonotonous)(this.firstElementOffsetByLineIdx,u=>r.endExclusive<=u)??this.elements.length;return new x.OffsetRange(s,o)}}n.LinesSliceCharSequence=p;function c(h){return h>=97&&h<=122||h>=65&&h<=90||h>=48&&h<=57}const a={0:0,1:0,2:0,3:10,4:2,5:30,6:3,7:10,8:10};function m(h){return a[h]}function e(h){return h===10?8:h===13?7:(0,f.isSpace)(h)?6:h>=97&&h<=122?0:h>=65&&h<=90?1:h>=48&&h<=57?2:h===-1?3:h===44||h===59?5:4}}),X(J[34],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.MovedText=n.LinesDiff=void 0;class i{constructor(d,f,p){this.changes=d,this.moves=f,this.hitTimeout=p}}n.LinesDiff=i;class x{constructor(d,f){this.lineRangeMapping=d,this.changes=f}}n.MovedText=x}),X(J[17],Z([0,1,3,13,4,2,50]),function(W,n,i,x,A,d,f){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.RangeMapping=n.DetailedLineRangeMapping=n.LineRangeMapping=void 0;class p{static inverse(r,s,o){const u=[];let S=1,L=1;for(const P of r){const E=new p(new x.LineRange(S,P.original.startLineNumber),new x.LineRange(L,P.modified.startLineNumber));E.modified.isEmpty||u.push(E),S=P.original.endLineNumberExclusive,L=P.modified.endLineNumberExclusive}const N=new p(new x.LineRange(S,s+1),new x.LineRange(L,o+1));return N.modified.isEmpty||u.push(N),u}static clip(r,s,o){const u=[];for(const S of r){const L=S.original.intersect(s),N=S.modified.intersect(o);L&&!L.isEmpty&&N&&!N.isEmpty&&u.push(new p(L,N))}return u}constructor(r,s){this.original=r,this.modified=s}toString(){return`{${this.original.toString()}->${this.modified.toString()}}`}flip(){return new p(this.modified,this.original)}join(r){return new p(this.original.join(r.original),this.modified.join(r.modified))}toRangeMapping(){const r=this.original.toInclusiveRange(),s=this.modified.toInclusiveRange();if(r&&s)return new e(r,s);if(this.original.startLineNumber===1||this.modified.startLineNumber===1){if(!(this.modified.startLineNumber===1&&this.original.startLineNumber===1))throw new i.BugIndicatingError("not a valid diff");return new e(new d.Range(this.original.startLineNumber,1,this.original.endLineNumberExclusive,1),new d.Range(this.modified.startLineNumber,1,this.modified.endLineNumberExclusive,1))}else return new e(new d.Range(this.original.startLineNumber-1,Number.MAX_SAFE_INTEGER,this.original.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),new d.Range(this.modified.startLineNumber-1,Number.MAX_SAFE_INTEGER,this.modified.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER))}toRangeMapping2(r,s){if(a(this.original.endLineNumberExclusive,r)&&a(this.modified.endLineNumberExclusive,s))return new e(new d.Range(this.original.startLineNumber,1,this.original.endLineNumberExclusive,1),new d.Range(this.modified.startLineNumber,1,this.modified.endLineNumberExclusive,1));if(!this.original.isEmpty&&!this.modified.isEmpty)return new e(d.Range.fromPositions(new A.Position(this.original.startLineNumber,1),c(new A.Position(this.original.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),r)),d.Range.fromPositions(new A.Position(this.modified.startLineNumber,1),c(new A.Position(this.modified.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),s)));if(this.original.startLineNumber>1&&this.modified.startLineNumber>1)return new e(d.Range.fromPositions(c(new A.Position(this.original.startLineNumber-1,Number.MAX_SAFE_INTEGER),r),c(new A.Position(this.original.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),r)),d.Range.fromPositions(c(new A.Position(this.modified.startLineNumber-1,Number.MAX_SAFE_INTEGER),s),c(new A.Position(this.modified.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),s)));throw new i.BugIndicatingError}}n.LineRangeMapping=p;function c(h,r){if(h.lineNumber<1)return new A.Position(1,1);if(h.lineNumber>r.length)return new A.Position(r.length,r[r.length-1].length+1);const s=r[h.lineNumber-1];return h.column>s.length+1?new A.Position(h.lineNumber,s.length+1):h}function a(h,r){return h>=1&&h<=r.length}class m extends p{static fromRangeMappings(r){const s=x.LineRange.join(r.map(u=>x.LineRange.fromRangeInclusive(u.originalRange))),o=x.LineRange.join(r.map(u=>x.LineRange.fromRangeInclusive(u.modifiedRange)));return new m(s,o,r)}constructor(r,s,o){super(r,s),this.innerChanges=o}flip(){return new m(this.modified,this.original,this.innerChanges?.map(r=>r.flip()))}withInnerChangesFromLineRanges(){return new m(this.original,this.modified,[this.toRangeMapping()])}}n.DetailedLineRangeMapping=m;class e{static assertSorted(r){for(let s=1;s${this.modifiedRange.toString()}}`}flip(){return new e(this.modifiedRange,this.originalRange)}toTextEdit(r){const s=r.getValueOfRange(this.modifiedRange);return new f.SingleTextEdit(this.originalRange,s)}}n.RangeMapping=e}),X(J[55],Z([0,1,10,17,7,15,21,13,33,16,32,2]),function(W,n,i,x,A,d,f,p,c,a,m,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.computeMovedLines=h;function h(N,P,E,v,l,b){let{moves:g,excludedChanges:w}=s(N,P,E,b);if(!b.isValid())return[];const M=N.filter(_=>!w.has(_)),y=o(M,v,l,P,E,b);return(0,A.pushMany)(g,y),g=S(g),g=g.filter(_=>{const C=_.original.toOffsetRange().slice(P).map(D=>D.trim());return C.join(` `).length>=15&&r(C,D=>D.length>=2)>=2}),g=L(N,g),g}function r(N,P){let E=0;for(const v of N)P(v)&&E++;return E}function s(N,P,E,v){const l=[],b=N.filter(M=>M.modified.isEmpty&&M.original.length>=3).map(M=>new a.LineRangeFragment(M.original,P,M)),g=new Set(N.filter(M=>M.original.isEmpty&&M.modified.length>=3).map(M=>new a.LineRangeFragment(M.modified,E,M))),w=new Set;for(const M of b){let y=-1,_;for(const C of g){const R=M.computeSimilarity(C);R>y&&(y=R,_=C)}if(y>.9&&_&&(g.delete(_),l.push(new x.LineRangeMapping(M.range,_.range)),w.add(M.source),w.add(_.source)),!v.isValid())return{moves:l,excludedChanges:w}}return{moves:l,excludedChanges:w}}function o(N,P,E,v,l,b){const g=[],w=new f.SetMap;for(const R of N)for(let D=R.original.startLineNumber;DR.modified.startLineNumber,A.numberComparator));for(const R of N){let D=[];for(let T=R.modified.startLineNumber;T{for(const B of D)if(B.originalLineRange.endLineNumberExclusive+1===F.endLineNumberExclusive&&B.modifiedLineRange.endLineNumberExclusive+1===z.endLineNumberExclusive){B.originalLineRange=new p.LineRange(B.originalLineRange.startLineNumber,F.endLineNumberExclusive),B.modifiedLineRange=new p.LineRange(B.modifiedLineRange.startLineNumber,z.endLineNumberExclusive),j.push(B);return}const q={modifiedLineRange:z,originalLineRange:F};M.push(q),j.push(q)}),D=j}if(!b.isValid())return[]}M.sort((0,A.reverseOrder)((0,A.compareBy)(R=>R.modifiedLineRange.length,A.numberComparator)));const y=new p.LineRangeSet,_=new p.LineRangeSet;for(const R of M){const D=R.modifiedLineRange.startLineNumber-R.originalLineRange.startLineNumber,T=y.subtractFrom(R.modifiedLineRange),O=_.subtractFrom(R.originalLineRange).getWithDelta(D),z=T.getIntersection(O);for(const j of z.ranges){if(j.length<3)continue;const F=j,q=j.delta(-D);g.push(new x.LineRangeMapping(q,F)),y.addRange(F),_.addRange(q)}}g.sort((0,A.compareBy)(R=>R.original.startLineNumber,A.numberComparator));const C=new d.MonotonousArray(N);for(let R=0;R$.original.startLineNumber<=D.original.startLineNumber),O=(0,d.findLastMonotonous)(N,$=>$.modified.startLineNumber<=D.modified.startLineNumber),z=Math.max(D.original.startLineNumber-T.original.startLineNumber,D.modified.startLineNumber-O.modified.startLineNumber),j=C.findLastMonotonous($=>$.original.startLineNumber$.modified.startLineNumberv.length||U>l.length||y.contains(U)||_.contains($)||!u(v[$-1],l[U-1],b))break}B>0&&(_.addRange(new p.LineRange(D.original.startLineNumber-B,D.original.startLineNumber)),y.addRange(new p.LineRange(D.modified.startLineNumber-B,D.modified.startLineNumber)));let G;for(G=0;Gv.length||U>l.length||y.contains(U)||_.contains($)||!u(v[$-1],l[U-1],b))break}G>0&&(_.addRange(new p.LineRange(D.original.endLineNumberExclusive,D.original.endLineNumberExclusive+G)),y.addRange(new p.LineRange(D.modified.endLineNumberExclusive,D.modified.endLineNumberExclusive+G))),(B>0||G>0)&&(g[R]=new x.LineRangeMapping(new p.LineRange(D.original.startLineNumber-B,D.original.endLineNumberExclusive+G),new p.LineRange(D.modified.startLineNumber-B,D.modified.endLineNumberExclusive+G)))}return g}function u(N,P,E){if(N.trim()===P.trim())return!0;if(N.length>300&&P.length>300)return!1;const l=new m.MyersDiffAlgorithm().compute(new c.LinesSliceCharSequence([N],new e.Range(1,1,1,N.length),!1),new c.LinesSliceCharSequence([P],new e.Range(1,1,1,P.length),!1),E);let b=0;const g=i.SequenceDiff.invert(l.diffs,N.length);for(const _ of g)_.seq1Range.forEach(C=>{(0,a.isSpace)(N.charCodeAt(C))||b++});function w(_){let C=0;for(let R=0;RP.length?N:P);return b/M>.6&&M>10}function S(N){if(N.length===0)return N;N.sort((0,A.compareBy)(E=>E.original.startLineNumber,A.numberComparator));const P=[N[0]];for(let E=1;E=0&&g>=0&&b+g<=2){P[P.length-1]=v.join(l);continue}P.push(l)}return P}function L(N,P){const E=new d.MonotonousArray(N);return P=P.filter(v=>{const l=E.findLastMonotonous(w=>w.original.startLineNumberw.modified.startLineNumber$===U))return new s.LinesDiff([],[],!1);if(E.length===1&&E[0].length===0||v.length===1&&v[0].length===0)return new s.LinesDiff([new o.DetailedLineRangeMapping(new A.LineRange(1,E.length+1),new A.LineRange(1,v.length+1),[new o.RangeMapping(new f.Range(1,1,E.length,E[E.length-1].length+1),new f.Range(1,1,v.length,v[v.length-1].length+1))])],[],!1);const b=l.maxComputationTimeMs===0?p.InfiniteTimeout.instance:new p.DateTimeout(l.maxComputationTimeMs),g=!l.ignoreTrimWhitespace,w=new Map;function M($){let U=w.get($);return U===void 0&&(U=w.size,w.set($,U)),U}const y=E.map($=>M($.trim())),_=v.map($=>M($.trim())),C=new h.LineSequence(y,E),R=new h.LineSequence(_,v),D=C.length+R.length<1700?this.dynamicProgrammingDiffing.compute(C,R,b,($,U)=>E[$]===v[U]?v[U].length===0?.1:1+Math.log(1+v[U].length):.99):this.myersDiffingAlgorithm.compute(C,R,b);let T=D.diffs,O=D.hitTimeout;T=(0,e.optimizeSequenceDiffs)(C,R,T),T=(0,e.removeVeryShortMatchingLinesBetweenDiffs)(C,R,T);const z=[],j=$=>{if(g)for(let U=0;U<$;U++){const ee=F+U,re=q+U;if(E[ee]!==v[re]){const ue=this.refineDiff(E,v,new p.SequenceDiff(new d.OffsetRange(ee,ee+1),new d.OffsetRange(re,re+1)),b,g);for(const de of ue.mappings)z.push(de);ue.hitTimeout&&(O=!0)}}};let F=0,q=0;for(const $ of T){(0,x.assertFn)(()=>$.seq1Range.start-F===$.seq2Range.start-q);const U=$.seq1Range.start-F;j(U),F=$.seq1Range.endExclusive,q=$.seq2Range.endExclusive;const ee=this.refineDiff(E,v,$,b,g);ee.hitTimeout&&(O=!0);for(const re of ee.mappings)z.push(re)}j(E.length-F);const B=S(z,E,v);let G=[];return l.computeMoves&&(G=this.computeMoves(B,E,v,y,_,b,g)),(0,x.assertFn)(()=>{function $(ee,re){if(ee.lineNumber<1||ee.lineNumber>re.length)return!1;const ue=re[ee.lineNumber-1];return!(ee.column<1||ee.column>ue.length+1)}function U(ee,re){return!(ee.startLineNumber<1||ee.startLineNumber>re.length+1||ee.endLineNumberExclusive<1||ee.endLineNumberExclusive>re.length+1)}for(const ee of B){if(!ee.innerChanges)return!1;for(const re of ee.innerChanges)if(!($(re.modifiedRange.getStartPosition(),v)&&$(re.modifiedRange.getEndPosition(),v)&&$(re.originalRange.getStartPosition(),E)&&$(re.originalRange.getEndPosition(),E)))return!1;if(!U(ee.modified,v)||!U(ee.original,E))return!1}return!0}),new s.LinesDiff(B,G,O)}computeMoves(E,v,l,b,g,w,M){return(0,m.computeMovedLines)(E,v,l,b,g,w).map(C=>{const R=this.refineDiff(v,l,new p.SequenceDiff(C.original.toOffsetRange(),C.modified.toOffsetRange()),w,M),D=S(R.mappings,v,l,!0);return new s.MovedText(C,D)})}refineDiff(E,v,l,b,g){const M=N(l).toRangeMapping2(E,v),y=new r.LinesSliceCharSequence(E,M.originalRange,g),_=new r.LinesSliceCharSequence(v,M.modifiedRange,g),C=y.length+_.length<500?this.dynamicProgrammingDiffing.compute(y,_,b):this.myersDiffingAlgorithm.compute(y,_,b),R=!1;let D=C.diffs;R&&p.SequenceDiff.assertSorted(D),D=(0,e.optimizeSequenceDiffs)(y,_,D),R&&p.SequenceDiff.assertSorted(D),D=(0,e.extendDiffsToEntireWordIfAppropriate)(y,_,D),R&&p.SequenceDiff.assertSorted(D),D=(0,e.removeShortMatches)(y,_,D),R&&p.SequenceDiff.assertSorted(D),D=(0,e.removeVeryShortMatchingTextBetweenLongDiffs)(y,_,D),R&&p.SequenceDiff.assertSorted(D);const T=D.map(O=>new o.RangeMapping(y.translateRange(O.seq1Range),_.translateRange(O.seq2Range)));return R&&o.RangeMapping.assertSorted(T),{mappings:T,hitTimeout:C.hitTimeout}}}n.DefaultLinesDiffComputer=u;function S(P,E,v,l=!1){const b=[];for(const g of(0,i.groupAdjacentBy)(P.map(w=>L(w,E,v)),(w,M)=>w.original.overlapOrTouch(M.original)||w.modified.overlapOrTouch(M.modified))){const w=g[0],M=g[g.length-1];b.push(new o.DetailedLineRangeMapping(w.original.join(M.original),w.modified.join(M.modified),g.map(y=>y.innerChanges[0])))}return(0,x.assertFn)(()=>!l&&b.length>0&&(b[0].modified.startLineNumber!==b[0].original.startLineNumber||v.length-b[b.length-1].modified.endLineNumberExclusive!==E.length-b[b.length-1].original.endLineNumberExclusive)?!1:(0,x.checkAdjacentItems)(b,(g,w)=>w.original.startLineNumber-g.original.endLineNumberExclusive===w.modified.startLineNumber-g.modified.endLineNumberExclusive&&g.original.endLineNumberExclusive=v[P.modifiedRange.startLineNumber-1].length&&P.originalRange.startColumn-1>=E[P.originalRange.startLineNumber-1].length&&P.originalRange.startLineNumber<=P.originalRange.endLineNumber+b&&P.modifiedRange.startLineNumber<=P.modifiedRange.endLineNumber+b&&(l=1);const g=new A.LineRange(P.originalRange.startLineNumber+l,P.originalRange.endLineNumber+1+b),w=new A.LineRange(P.modifiedRange.startLineNumber+l,P.modifiedRange.endLineNumber+1+b);return new o.DetailedLineRangeMapping(g,w,[P])}function N(P){return new o.LineRangeMapping(new A.LineRange(P.seq1Range.start+1,P.seq1Range.endExclusive+1),new A.LineRange(P.seq2Range.start+1,P.seq2Range.endExclusive+1))}}),X(J[57],Z([0,1,24,34,17,6,2,12,13]),function(W,n,i,x,A,d,f,p,c){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.DiffComputer=n.LegacyLinesDiffComputer=void 0;const a=3;class m{computeDiff(v,l,b){const w=new S(v,l,{maxComputationTime:b.maxComputationTimeMs,shouldIgnoreTrimWhitespace:b.ignoreTrimWhitespace,shouldComputeCharChanges:!0,shouldMakePrettyDiff:!0,shouldPostProcessCharChanges:!0}).computeDiff(),M=[];let y=null;for(const _ of w.changes){let C;_.originalEndLineNumber===0?C=new c.LineRange(_.originalStartLineNumber+1,_.originalStartLineNumber+1):C=new c.LineRange(_.originalStartLineNumber,_.originalEndLineNumber+1);let R;_.modifiedEndLineNumber===0?R=new c.LineRange(_.modifiedStartLineNumber+1,_.modifiedStartLineNumber+1):R=new c.LineRange(_.modifiedStartLineNumber,_.modifiedEndLineNumber+1);let D=new A.DetailedLineRangeMapping(C,R,_.charChanges?.map(T=>new A.RangeMapping(new f.Range(T.originalStartLineNumber,T.originalStartColumn,T.originalEndLineNumber,T.originalEndColumn),new f.Range(T.modifiedStartLineNumber,T.modifiedStartColumn,T.modifiedEndLineNumber,T.modifiedEndColumn))));y&&(y.modified.endLineNumberExclusive===D.modified.startLineNumber||y.original.endLineNumberExclusive===D.original.startLineNumber)&&(D=new A.DetailedLineRangeMapping(y.original.join(D.original),y.modified.join(D.modified),y.innerChanges&&D.innerChanges?y.innerChanges.concat(D.innerChanges):void 0),M.pop()),M.push(D),y=D}return(0,p.assertFn)(()=>(0,p.checkAdjacentItems)(M,(_,C)=>C.original.startLineNumber-_.original.endLineNumberExclusive===C.modified.startLineNumber-_.modified.endLineNumberExclusive&&_.original.endLineNumberExclusive(v===10?"\\n":String.fromCharCode(v))+`-(${this._lineNumbers[l]},${this._columns[l]})`).join(", ")+"]"}_assertIndex(v,l){if(v<0||v>=l.length)throw new Error("Illegal index")}getElements(){return this._charCodes}getStartLineNumber(v){return v>0&&v===this._lineNumbers.length?this.getEndLineNumber(v-1):(this._assertIndex(v,this._lineNumbers),this._lineNumbers[v])}getEndLineNumber(v){return v===-1?this.getStartLineNumber(v+1):(this._assertIndex(v,this._lineNumbers),this._charCodes[v]===10?this._lineNumbers[v]+1:this._lineNumbers[v])}getStartColumn(v){return v>0&&v===this._columns.length?this.getEndColumn(v-1):(this._assertIndex(v,this._columns),this._columns[v])}getEndColumn(v){return v===-1?this.getStartColumn(v+1):(this._assertIndex(v,this._columns),this._charCodes[v]===10?1:this._columns[v]+1)}}class s{constructor(v,l,b,g,w,M,y,_){this.originalStartLineNumber=v,this.originalStartColumn=l,this.originalEndLineNumber=b,this.originalEndColumn=g,this.modifiedStartLineNumber=w,this.modifiedStartColumn=M,this.modifiedEndLineNumber=y,this.modifiedEndColumn=_}static createFromDiffChange(v,l,b){const g=l.getStartLineNumber(v.originalStart),w=l.getStartColumn(v.originalStart),M=l.getEndLineNumber(v.originalStart+v.originalLength-1),y=l.getEndColumn(v.originalStart+v.originalLength-1),_=b.getStartLineNumber(v.modifiedStart),C=b.getStartColumn(v.modifiedStart),R=b.getEndLineNumber(v.modifiedStart+v.modifiedLength-1),D=b.getEndColumn(v.modifiedStart+v.modifiedLength-1);return new s(g,w,M,y,_,C,R,D)}}function o(E){if(E.length<=1)return E;const v=[E[0]];let l=v[0];for(let b=1,g=E.length;b0&&l.originalLength<20&&l.modifiedLength>0&&l.modifiedLength<20&&w()){const O=b.createCharSequence(v,l.originalStart,l.originalStart+l.originalLength-1),z=g.createCharSequence(v,l.modifiedStart,l.modifiedStart+l.modifiedLength-1);if(O.getElements().length>0&&z.getElements().length>0){let j=e(O,z,w,!0).changes;y&&(j=o(j)),T=[];for(let F=0,q=j.length;F1&&j>1;){const F=T.charCodeAt(z-2),q=O.charCodeAt(j-2);if(F!==q)break;z--,j--}(z>1||j>1)&&this._pushTrimWhitespaceCharChange(g,w+1,1,z,M+1,1,j)}{let z=N(T,1),j=N(O,1);const F=T.length+1,q=O.length+1;for(;z!0;const v=Date.now();return()=>Date.now()-vnew i.LegacyLinesDiffComputer,getDefault:()=>new x.DefaultLinesDiffComputer}}),X(J[59],Z([0,1,40]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.computeDefaultDocumentColors=e;function x(h){const r=[];for(const s of h){const o=Number(s);(o||o===0&&s.replace(/\s/g,"")!=="")&&r.push(o)}return r}function A(h,r,s,o){return{red:h/255,blue:s/255,green:r/255,alpha:o}}function d(h,r){const s=r.index,o=r[0].length;if(!s)return;const u=h.positionAt(s);return{startLineNumber:u.lineNumber,startColumn:u.column,endLineNumber:u.lineNumber,endColumn:u.column+o}}function f(h,r){if(!h)return;const s=i.Color.Format.CSS.parseHex(r);if(s)return{range:h,color:A(s.rgba.r,s.rgba.g,s.rgba.b,s.rgba.a)}}function p(h,r,s){if(!h||r.length!==1)return;const u=r[0].values(),S=x(u);return{range:h,color:A(S[0],S[1],S[2],s?S[3]:1)}}function c(h,r,s){if(!h||r.length!==1)return;const u=r[0].values(),S=x(u),L=new i.Color(new i.HSLA(S[0],S[1]/100,S[2]/100,s?S[3]:1));return{range:h,color:A(L.rgba.r,L.rgba.g,L.rgba.b,L.rgba.a)}}function a(h,r){return typeof h=="string"?[...h.matchAll(r)]:h.findMatches(r)}function m(h){const r=[],o=a(h,/\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%]*\))|(#)([A-Fa-f0-9]{3})\b|(#)([A-Fa-f0-9]{4})\b|(#)([A-Fa-f0-9]{6})\b|(#)([A-Fa-f0-9]{8})\b/gm);if(o.length>0)for(const u of o){const S=u.filter(E=>E!==void 0),L=S[1],N=S[2];if(!N)continue;let P;if(L==="rgb"){const E=/^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*\)$/gm;P=p(d(h,u),a(N,E),!1)}else if(L==="rgba"){const E=/^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(0[.][0-9]+|[.][0-9]+|[01][.]|[01])\s*\)$/gm;P=p(d(h,u),a(N,E),!0)}else if(L==="hsl"){const E=/^\(\s*(36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*\)$/gm;P=c(d(h,u),a(N,E),!1)}else if(L==="hsla"){const E=/^\(\s*(36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*,\s*(0[.][0-9]+|[.][0-9]+|[01][.]|[01])\s*\)$/gm;P=c(d(h,u),a(N,E),!0)}else L==="#"&&(P=f(d(h,u),L+N));P&&r.push(P)}return r}function e(h){return!h||typeof h.getValue!="function"||typeof h.positionAt!="function"?[]:m(h)}}),X(J[60],Z([0,1,29]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.LinkComputer=n.StateMachine=void 0,n.computeLinks=m;class x{constructor(h,r,s){const o=new Uint8Array(h*r);for(let u=0,S=h*r;ur&&(r=N),L>s&&(s=L),P>s&&(s=P)}r++,s++;const o=new x(s,r,0);for(let u=0,S=h.length;u=this._maxCharCode?0:this._states.get(h,r)}}n.StateMachine=A;let d=null;function f(){return d===null&&(d=new A([[1,104,2],[1,72,2],[1,102,6],[1,70,6],[2,116,3],[2,84,3],[3,116,4],[3,84,4],[4,112,5],[4,80,5],[5,115,9],[5,83,9],[5,58,10],[6,105,7],[6,73,7],[7,108,8],[7,76,8],[8,101,9],[8,69,9],[9,58,10],[10,47,11],[11,47,12]])),d}let p=null;function c(){if(p===null){p=new i.CharacterClassifier(0);const e=` <>'"\u3001\u3002\uFF61\uFF64\uFF0C\uFF0E\uFF1A\uFF1B\u2018\u3008\u300C\u300E\u3014\uFF08\uFF3B\uFF5B\uFF62\uFF63\uFF5D\uFF3D\uFF09\u3015\u300F\u300D\u3009\u2019\uFF40\uFF5E\u2026`;for(let r=0;ro);if(o>0){const L=r.charCodeAt(o-1),N=r.charCodeAt(S);(L===40&&N===41||L===91&&N===93||L===123&&N===125)&&S--}return{range:{startLineNumber:s,startColumn:o+1,endLineNumber:s,endColumn:S+2},url:r.substring(o,S+1)}}static computeLinks(h,r=f()){const s=c(),o=[];for(let u=1,S=h.getLineCount();u<=S;u++){const L=h.getLineContent(u),N=L.length;let P=0,E=0,v=0,l=1,b=!1,g=!1,w=!1,M=!1;for(;P=0?(p+=f?1:-1,p<0?p=A.length-1:p%=A.length,A[p]):null}}n.BasicInplaceReplace=i}),X(J[62],Z([0,1,27]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.ApplyEditsResult=n.SearchData=n.ValidAnnotatedEditOperation=n.FindMatch=n.TextModelResolvedOptions=n.InjectedTextCursorStops=n.GlyphMarginLane=n.OverviewRulerLane=void 0,n.isITextSnapshot=c,n.shouldSynchronizeModel=h;var x;(function(r){r[r.Left=1]="Left",r[r.Center=2]="Center",r[r.Right=4]="Right",r[r.Full=7]="Full"})(x||(n.OverviewRulerLane=x={}));var A;(function(r){r[r.Left=1]="Left",r[r.Center=2]="Center",r[r.Right=3]="Right"})(A||(n.GlyphMarginLane=A={}));var d;(function(r){r[r.Both=0]="Both",r[r.Right=1]="Right",r[r.Left=2]="Left",r[r.None=3]="None"})(d||(n.InjectedTextCursorStops=d={}));class f{get originalIndentSize(){return this._indentSizeIsTabSize?"tabSize":this.indentSize}constructor(s){this._textModelResolvedOptionsBrand=void 0,this.tabSize=Math.max(1,s.tabSize|0),s.indentSize==="tabSize"?(this.indentSize=this.tabSize,this._indentSizeIsTabSize=!0):(this.indentSize=Math.max(1,s.indentSize|0),this._indentSizeIsTabSize=!1),this.insertSpaces=!!s.insertSpaces,this.defaultEOL=s.defaultEOL|0,this.trimAutoWhitespace=!!s.trimAutoWhitespace,this.bracketPairColorizationOptions=s.bracketPairColorizationOptions}equals(s){return this.tabSize===s.tabSize&&this._indentSizeIsTabSize===s._indentSizeIsTabSize&&this.indentSize===s.indentSize&&this.insertSpaces===s.insertSpaces&&this.defaultEOL===s.defaultEOL&&this.trimAutoWhitespace===s.trimAutoWhitespace&&(0,i.equals)(this.bracketPairColorizationOptions,s.bracketPairColorizationOptions)}createChangeEvent(s){return{tabSize:this.tabSize!==s.tabSize,indentSize:this.indentSize!==s.indentSize,insertSpaces:this.insertSpaces!==s.insertSpaces,trimAutoWhitespace:this.trimAutoWhitespace!==s.trimAutoWhitespace}}}n.TextModelResolvedOptions=f;class p{constructor(s,o){this._findMatchBrand=void 0,this.range=s,this.matches=o}}n.FindMatch=p;function c(r){return r&&typeof r.read=="function"}class a{constructor(s,o,u,S,L,N){this.identifier=s,this.range=o,this.text=u,this.forceMoveMarkers=S,this.isAutoWhitespaceEdit=L,this._isTracked=N}}n.ValidAnnotatedEditOperation=a;class m{constructor(s,o,u){this.regex=s,this.wordSeparators=o,this.simpleSearch=u}}n.SearchData=m;class e{constructor(s,o,u){this.reverseEdits=s,this.changes=o,this.trimAutoWhitespaceLineNumbers=u}}n.ApplyEditsResult=e;function h(r){return!r.isTooLargeForSyncing()&&!r.isForSimpleWidget}}),X(J[63],Z([0,1,7,28]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.PrefixSumIndexOfResult=n.ConstantTimePrefixSumComputer=n.PrefixSumComputer=void 0;class A{constructor(c){this.values=c,this.prefixSum=new Uint32Array(c.length),this.prefixSumValidIndex=new Int32Array(1),this.prefixSumValidIndex[0]=-1}insertValues(c,a){c=(0,x.toUint32)(c);const m=this.values,e=this.prefixSum,h=a.length;return h===0?!1:(this.values=new Uint32Array(m.length+h),this.values.set(m.subarray(0,c),0),this.values.set(m.subarray(c),c+h),this.values.set(a,c),c-1=0&&this.prefixSum.set(e.subarray(0,this.prefixSumValidIndex[0]+1)),!0)}setValue(c,a){return c=(0,x.toUint32)(c),a=(0,x.toUint32)(a),this.values[c]===a?!1:(this.values[c]=a,c-1=m.length)return!1;const h=m.length-c;return a>=h&&(a=h),a===0?!1:(this.values=new Uint32Array(m.length-a),this.values.set(m.subarray(0,c),0),this.values.set(m.subarray(c+a),c),this.prefixSum=new Uint32Array(this.values.length),c-1=0&&this.prefixSum.set(e.subarray(0,this.prefixSumValidIndex[0]+1)),!0)}getTotalSum(){return this.values.length===0?0:this._getPrefixSum(this.values.length-1)}getPrefixSum(c){return c<0?0:(c=(0,x.toUint32)(c),this._getPrefixSum(c))}_getPrefixSum(c){if(c<=this.prefixSumValidIndex[0])return this.prefixSum[c];let a=this.prefixSumValidIndex[0]+1;a===0&&(this.prefixSum[0]=this.values[0],a++),c>=this.values.length&&(c=this.values.length-1);for(let m=a;m<=c;m++)this.prefixSum[m]=this.prefixSum[m-1]+this.values[m];return this.prefixSumValidIndex[0]=Math.max(this.prefixSumValidIndex[0],c),this.prefixSum[c]}getIndexOf(c){c=Math.floor(c),this.getTotalSum();let a=0,m=this.values.length-1,e=0,h=0,r=0;for(;a<=m;)if(e=a+(m-a)/2|0,h=this.prefixSum[e],r=h-this.values[e],c=h)a=e+1;else break;return new f(e,c-r)}}n.PrefixSumComputer=A;class d{constructor(c){this._values=c,this._isValid=!1,this._validEndIndex=-1,this._prefixSum=[],this._indexBySum=[]}getTotalSum(){return this._ensureValid(),this._indexBySum.length}getPrefixSum(c){return this._ensureValid(),c===0?0:this._prefixSum[c-1]}getIndexOf(c){this._ensureValid();const a=this._indexBySum[c],m=a>0?this._prefixSum[a-1]:0;return new f(a,c-m)}removeValues(c,a){this._values.splice(c,a),this._invalidate(c)}insertValues(c,a){this._values=(0,i.arrayInsert)(this._values,c,a),this._invalidate(c)}_invalidate(c){this._isValid=!1,this._validEndIndex=Math.min(this._validEndIndex,c-1)}_ensureValid(){if(!this._isValid){for(let c=this._validEndIndex+1,a=this._values.length;c0?this._prefixSum[c-1]:0;this._prefixSum[c]=e+m;for(let h=0;h=0;let N=null;try{N=i.createRegExp(this.searchString,this.isRegex,{matchCase:this.matchCase,wholeWord:!1,multiline:L,global:!0,unicode:!0})}catch{return null}if(!N)return null;let P=!this.isRegex&&!L;return P&&this.searchString.toLowerCase()!==this.searchString.toUpperCase()&&(P=this.matchCase),new f.SearchData(N,this.wordSeparators?(0,x.getMapForWordSeparators)(this.wordSeparators,[]):null,P?this.searchString:null)}}n.SearchParams=c;function a(S){if(!S||S.length===0)return!1;for(let L=0,N=S.length;L=N)break;const E=S.charCodeAt(L);if(E===110||E===114||E===87)return!0}}return!1}function m(S,L,N){if(!N)return new f.FindMatch(S,null);const P=[];for(let E=0,v=L.length;E>0);N[v]>=L?E=v-1:N[v+1]>=L?(P=v,E=v):P=v+1}return P+1}}class h{static findMatches(L,N,P,E,v){const l=N.parseSearchRequest();return l?l.regex.multiline?this._doFindMatchesMultiline(L,P,new u(l.wordSeparators,l.regex),E,v):this._doFindMatchesLineByLine(L,P,l,E,v):[]}static _getMultilineMatchRange(L,N,P,E,v,l){let b,g=0;E?(g=E.findLineFeedCountBeforeOffset(v),b=N+v+g):b=N+v;let w;if(E){const C=E.findLineFeedCountBeforeOffset(v+l.length)-g;w=b+l.length+C}else w=b+l.length;const M=L.getPositionAt(b),y=L.getPositionAt(w);return new d.Range(M.lineNumber,M.column,y.lineNumber,y.column)}static _doFindMatchesMultiline(L,N,P,E,v){const l=L.getOffsetAt(N.getStartPosition()),b=L.getValueInRange(N,1),g=L.getEOL()===`\r `?new e(b):null,w=[];let M=0,y;for(P.reset(0);y=P.next(b);)if(w[M++]=m(this._getMultilineMatchRange(L,l,b,g,y.index,y[0]),y,E),M>=v)return w;return w}static _doFindMatchesLineByLine(L,N,P,E,v){const l=[];let b=0;if(N.startLineNumber===N.endLineNumber){const w=L.getLineContent(N.startLineNumber).substring(N.startColumn-1,N.endColumn-1);return b=this._findMatchesInLine(P,w,N.startLineNumber,N.startColumn-1,b,l,E,v),l}const g=L.getLineContent(N.startLineNumber).substring(N.startColumn-1);b=this._findMatchesInLine(P,g,N.startLineNumber,N.startColumn-1,b,l,E,v);for(let w=N.startLineNumber+1;w=g))return v;return v}const M=new u(L.wordSeparators,L.regex);let y;M.reset(0);do if(y=M.next(N),y&&(l[v++]=m(new d.Range(P,y.index+1+E,P,y.index+1+y[0].length+E),y,b),v>=g))return v;while(y);return v}static findNextMatch(L,N,P,E){const v=N.parseSearchRequest();if(!v)return null;const l=new u(v.wordSeparators,v.regex);return v.regex.multiline?this._doFindNextMatchMultiline(L,P,l,E):this._doFindNextMatchLineByLine(L,P,l,E)}static _doFindNextMatchMultiline(L,N,P,E){const v=new A.Position(N.lineNumber,1),l=L.getOffsetAt(v),b=L.getLineCount(),g=L.getValueInRange(new d.Range(v.lineNumber,v.column,b,L.getLineMaxColumn(b)),1),w=L.getEOL()===`\r `?new e(g):null;P.reset(N.column-1);const M=P.next(g);return M?m(this._getMultilineMatchRange(L,l,g,w,M.index,M[0]),M,E):N.lineNumber!==1||N.column!==1?this._doFindNextMatchMultiline(L,new A.Position(1,1),P,E):null}static _doFindNextMatchLineByLine(L,N,P,E){const v=L.getLineCount(),l=N.lineNumber,b=L.getLineContent(l),g=this._findFirstMatchInLine(P,b,l,N.column,E);if(g)return g;for(let w=1;w<=v;w++){const M=(l+w-1)%v,y=L.getLineContent(M+1),_=this._findFirstMatchInLine(P,y,M+1,1,E);if(_)return _}return null}static _findFirstMatchInLine(L,N,P,E,v){L.reset(E-1);const l=L.next(N);return l?m(new d.Range(P,l.index+1,P,l.index+1+l[0].length),l,v):null}static findPreviousMatch(L,N,P,E){const v=N.parseSearchRequest();if(!v)return null;const l=new u(v.wordSeparators,v.regex);return v.regex.multiline?this._doFindPreviousMatchMultiline(L,P,l,E):this._doFindPreviousMatchLineByLine(L,P,l,E)}static _doFindPreviousMatchMultiline(L,N,P,E){const v=this._doFindMatchesMultiline(L,new d.Range(1,1,N.lineNumber,N.column),P,E,10*p);if(v.length>0)return v[v.length-1];const l=L.getLineCount();return N.lineNumber!==l||N.column!==L.getLineMaxColumn(l)?this._doFindPreviousMatchMultiline(L,new A.Position(l,L.getLineMaxColumn(l)),P,E):null}static _doFindPreviousMatchLineByLine(L,N,P,E){const v=L.getLineCount(),l=N.lineNumber,b=L.getLineContent(l).substring(0,N.column-1),g=this._findLastMatchInLine(P,b,l,E);if(g)return g;for(let w=1;w<=v;w++){const M=(v+l-w-1)%v,y=L.getLineContent(M+1),_=this._findLastMatchInLine(P,y,M+1,E);if(_)return _}return null}static _findLastMatchInLine(L,N,P,E){let v=null,l;for(L.reset(0);l=L.next(N);)v=m(new d.Range(P,l.index+1,P,l.index+1+l[0].length),l,E);return v}}n.TextModelSearch=h;function r(S,L,N,P,E){if(P===0)return!0;const v=L.charCodeAt(P-1);if(S.get(v)!==0||v===13||v===10)return!0;if(E>0){const l=L.charCodeAt(P);if(S.get(l)!==0)return!0}return!1}function s(S,L,N,P,E){if(P+E===N)return!0;const v=L.charCodeAt(P+E);if(S.get(v)!==0||v===13||v===10)return!0;if(E>0){const l=L.charCodeAt(P+E-1);if(S.get(l)!==0)return!0}return!1}function o(S,L,N,P,E){return r(S,L,N,P,E)&&s(S,L,N,P,E)}class u{constructor(L,N){this._wordSeparators=L,this._searchRegex=N,this._prevMatchStartIndex=-1,this._prevMatchLength=0}reset(L){this._searchRegex.lastIndex=L,this._prevMatchStartIndex=-1,this._prevMatchLength=0}next(L){const N=L.length;let P;do{if(this._prevMatchStartIndex+this._prevMatchLength===N||(P=this._searchRegex.exec(L),!P))return null;const E=P.index,v=P[0].length;if(E===this._prevMatchStartIndex&&v===this._prevMatchLength){if(v===0){i.getNextCodePoint(L,N,this._searchRegex.lastIndex)>65535?this._searchRegex.lastIndex+=2:this._searchRegex.lastIndex+=1;continue}return null}if(this._prevMatchStartIndex=E,this._prevMatchLength=v,!this._wordSeparators||o(this._wordSeparators,L,N,E,v))return P}while(P);return null}}n.Searcher=u}),X(J[66],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.EditorWorkerHost=void 0;class i{static{this.CHANNEL_NAME="editorWorkerHost"}static getChannel(A){return A.getChannel(i.CHANNEL_NAME)}static setChannel(A,d){A.setChannel(i.CHANNEL_NAME,d)}}n.EditorWorkerHost=i}),X(J[67],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.findSectionHeaders=A;const i=new RegExp("\\bMARK:\\s*(.*)$","d"),x=/^-+|-+$/g;function A(a,m){let e=[];if(m.findRegionSectionHeaders&&m.foldingRules?.markers){const h=d(a,m);e=e.concat(h)}if(m.findMarkSectionHeaders){const h=f(a);e=e.concat(h)}return e}function d(a,m){const e=[],h=a.getLineCount();for(let r=1;r<=h;r++){const s=a.getLineContent(r),o=s.match(m.foldingRules.markers.start);if(o){const u={startLineNumber:r,startColumn:o[0].length+1,endLineNumber:r,endColumn:s.length+1};if(u.endColumn>u.startColumn){const S={range:u,...c(s.substring(o[0].length)),shouldBeInComments:!1};(S.text||S.hasSeparatorLine)&&e.push(S)}}}return e}function f(a){const m=[],e=a.getLineCount();for(let h=1;h<=e;h++){const r=a.getLineContent(h);p(r,h,m)}return m}function p(a,m,e){i.lastIndex=0;const h=i.exec(a);if(h){const r=h.indices[1][0]+1,s=h.indices[1][1]+1,o={startLineNumber:m,startColumn:r,endLineNumber:m,endColumn:s};if(o.endColumn>o.startColumn){const u={range:o,...c(h[1]),shouldBeInComments:!0};(u.text||u.hasSeparatorLine)&&e.push(u)}}}function c(a){a=a.trim();const m=a.startsWith("-");return a=a.replace(x,""),{text:a,hasSeparatorLine:m}}}),X(J[68],Z([0,1,2,65,6,12,31]),function(W,n,i,x,A,d,f){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.UnicodeTextModelHighlighter=void 0;class p{static computeUnicodeHighlights(h,r,s){const o=s?s.startLineNumber:1,u=s?s.endLineNumber:h.getLineCount(),S=new a(r),L=S.getCandidateCodePoints();let N;L==="allNonBasicAscii"?N=new RegExp("[^\\t\\n\\r\\x20-\\x7E]","g"):N=new RegExp(`${c(Array.from(L))}`,"g");const P=new x.Searcher(null,N),E=[];let v=!1,l,b=0,g=0,w=0;e:for(let M=o,y=u;M<=y;M++){const _=h.getLineContent(M),C=_.length;P.reset(0);do if(l=P.next(_),l){let R=l.index,D=l.index+l[0].length;if(R>0){const j=_.charCodeAt(R-1);A.isHighSurrogate(j)&&R--}if(D+1=1e3){v=!0;break e}E.push(new i.Range(M,R+1,M,D+1))}}while(l)}return{ranges:E,hasMore:v,ambiguousCharacterCount:b,invisibleCharacterCount:g,nonBasicAsciiCharacterCount:w}}static computeUnicodeHighlightReason(h,r){const s=new a(r);switch(s.shouldHighlightNonBasicASCII(h,null)){case 0:return null;case 2:return{kind:1};case 3:{const u=h.codePointAt(0),S=s.ambiguousCharacters.getPrimaryConfusable(u),L=A.AmbiguousCharacters.getLocales().filter(N=>!A.AmbiguousCharacters.getInstance(new Set([...r.allowedLocales,N])).isAmbiguous(u));return{kind:0,confusableWith:String.fromCodePoint(S),notAmbiguousInLocales:L}}case 1:return{kind:2}}}}n.UnicodeTextModelHighlighter=p;function c(e,h){return`[${A.escapeRegExpCharacters(e.map(s=>String.fromCodePoint(s)).join(""))}]`}class a{constructor(h){this.options=h,this.allowedCodePoints=new Set(h.allowedCodePoints),this.ambiguousCharacters=A.AmbiguousCharacters.getInstance(new Set(h.allowedLocales))}getCandidateCodePoints(){if(this.options.nonBasicASCII)return"allNonBasicAscii";const h=new Set;if(this.options.invisibleCharacters)for(const r of A.InvisibleCharacters.codePoints)m(String.fromCodePoint(r))||h.add(r);if(this.options.ambiguousCharacters)for(const r of this.ambiguousCharacters.getConfusableCodePoints())h.add(r);for(const r of this.allowedCodePoints)h.delete(r);return h}shouldHighlightNonBasicASCII(h,r){const s=h.codePointAt(0);if(this.allowedCodePoints.has(s))return 0;if(this.options.nonBasicASCII)return 1;let o=!1,u=!1;if(r)for(const S of r){const L=S.codePointAt(0),N=A.isBasicASCII(S);o=o||N,!N&&!this.ambiguousCharacters.isAmbiguous(L)&&!A.InvisibleCharacters.isInvisibleCharacter(L)&&(u=!0)}return!o&&u?0:this.options.invisibleCharacters&&!m(h)&&A.InvisibleCharacters.isInvisibleCharacter(s)?2:this.options.ambiguousCharacters&&this.ambiguousCharacters.isAmbiguous(s)?3:0}}function m(e){return e===" "||e===` `||e===" "}}),X(J[69],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.WrappingIndent=n.TrackedRangeStickiness=n.TextEditorCursorStyle=n.TextEditorCursorBlinkingStyle=n.SymbolTag=n.SymbolKind=n.SignatureHelpTriggerKind=n.ShowLightbulbIconMode=n.SelectionDirection=n.ScrollbarVisibility=n.ScrollType=n.RenderMinimap=n.RenderLineNumbersType=n.PositionAffinity=n.PartialAcceptTriggerKind=n.OverviewRulerLane=n.OverlayWidgetPositionPreference=n.NewSymbolNameTriggerKind=n.NewSymbolNameTag=n.MouseTargetType=n.MinimapSectionHeaderStyle=n.MinimapPosition=n.MarkerTag=n.MarkerSeverity=n.KeyCode=n.InlineEditTriggerKind=n.InlineCompletionTriggerKind=n.InlayHintKind=n.InjectedTextCursorStops=n.IndentAction=n.HoverVerbosityAction=n.GlyphMarginLane=n.EndOfLineSequence=n.EndOfLinePreference=n.EditorOption=n.EditorAutoIndentStrategy=n.DocumentHighlightKind=n.DefaultEndOfLine=n.CursorChangeReason=n.ContentWidgetPositionPreference=n.CompletionTriggerKind=n.CompletionItemTag=n.CompletionItemKind=n.CompletionItemInsertTextRule=n.CodeActionTriggerType=n.AccessibilitySupport=void 0;var i;(function(t){t[t.Unknown=0]="Unknown",t[t.Disabled=1]="Disabled",t[t.Enabled=2]="Enabled"})(i||(n.AccessibilitySupport=i={}));var x;(function(t){t[t.Invoke=1]="Invoke",t[t.Auto=2]="Auto"})(x||(n.CodeActionTriggerType=x={}));var A;(function(t){t[t.None=0]="None",t[t.KeepWhitespace=1]="KeepWhitespace",t[t.InsertAsSnippet=4]="InsertAsSnippet"})(A||(n.CompletionItemInsertTextRule=A={}));var d;(function(t){t[t.Method=0]="Method",t[t.Function=1]="Function",t[t.Constructor=2]="Constructor",t[t.Field=3]="Field",t[t.Variable=4]="Variable",t[t.Class=5]="Class",t[t.Struct=6]="Struct",t[t.Interface=7]="Interface",t[t.Module=8]="Module",t[t.Property=9]="Property",t[t.Event=10]="Event",t[t.Operator=11]="Operator",t[t.Unit=12]="Unit",t[t.Value=13]="Value",t[t.Constant=14]="Constant",t[t.Enum=15]="Enum",t[t.EnumMember=16]="EnumMember",t[t.Keyword=17]="Keyword",t[t.Text=18]="Text",t[t.Color=19]="Color",t[t.File=20]="File",t[t.Reference=21]="Reference",t[t.Customcolor=22]="Customcolor",t[t.Folder=23]="Folder",t[t.TypeParameter=24]="TypeParameter",t[t.User=25]="User",t[t.Issue=26]="Issue",t[t.Snippet=27]="Snippet"})(d||(n.CompletionItemKind=d={}));var f;(function(t){t[t.Deprecated=1]="Deprecated"})(f||(n.CompletionItemTag=f={}));var p;(function(t){t[t.Invoke=0]="Invoke",t[t.TriggerCharacter=1]="TriggerCharacter",t[t.TriggerForIncompleteCompletions=2]="TriggerForIncompleteCompletions"})(p||(n.CompletionTriggerKind=p={}));var c;(function(t){t[t.EXACT=0]="EXACT",t[t.ABOVE=1]="ABOVE",t[t.BELOW=2]="BELOW"})(c||(n.ContentWidgetPositionPreference=c={}));var a;(function(t){t[t.NotSet=0]="NotSet",t[t.ContentFlush=1]="ContentFlush",t[t.RecoverFromMarkers=2]="RecoverFromMarkers",t[t.Explicit=3]="Explicit",t[t.Paste=4]="Paste",t[t.Undo=5]="Undo",t[t.Redo=6]="Redo"})(a||(n.CursorChangeReason=a={}));var m;(function(t){t[t.LF=1]="LF",t[t.CRLF=2]="CRLF"})(m||(n.DefaultEndOfLine=m={}));var e;(function(t){t[t.Text=0]="Text",t[t.Read=1]="Read",t[t.Write=2]="Write"})(e||(n.DocumentHighlightKind=e={}));var h;(function(t){t[t.None=0]="None",t[t.Keep=1]="Keep",t[t.Brackets=2]="Brackets",t[t.Advanced=3]="Advanced",t[t.Full=4]="Full"})(h||(n.EditorAutoIndentStrategy=h={}));var r;(function(t){t[t.acceptSuggestionOnCommitCharacter=0]="acceptSuggestionOnCommitCharacter",t[t.acceptSuggestionOnEnter=1]="acceptSuggestionOnEnter",t[t.accessibilitySupport=2]="accessibilitySupport",t[t.accessibilityPageSize=3]="accessibilityPageSize",t[t.ariaLabel=4]="ariaLabel",t[t.ariaRequired=5]="ariaRequired",t[t.autoClosingBrackets=6]="autoClosingBrackets",t[t.autoClosingComments=7]="autoClosingComments",t[t.screenReaderAnnounceInlineSuggestion=8]="screenReaderAnnounceInlineSuggestion",t[t.autoClosingDelete=9]="autoClosingDelete",t[t.autoClosingOvertype=10]="autoClosingOvertype",t[t.autoClosingQuotes=11]="autoClosingQuotes",t[t.autoIndent=12]="autoIndent",t[t.automaticLayout=13]="automaticLayout",t[t.autoSurround=14]="autoSurround",t[t.bracketPairColorization=15]="bracketPairColorization",t[t.guides=16]="guides",t[t.codeLens=17]="codeLens",t[t.codeLensFontFamily=18]="codeLensFontFamily",t[t.codeLensFontSize=19]="codeLensFontSize",t[t.colorDecorators=20]="colorDecorators",t[t.colorDecoratorsLimit=21]="colorDecoratorsLimit",t[t.columnSelection=22]="columnSelection",t[t.comments=23]="comments",t[t.contextmenu=24]="contextmenu",t[t.copyWithSyntaxHighlighting=25]="copyWithSyntaxHighlighting",t[t.cursorBlinking=26]="cursorBlinking",t[t.cursorSmoothCaretAnimation=27]="cursorSmoothCaretAnimation",t[t.cursorStyle=28]="cursorStyle",t[t.cursorSurroundingLines=29]="cursorSurroundingLines",t[t.cursorSurroundingLinesStyle=30]="cursorSurroundingLinesStyle",t[t.cursorWidth=31]="cursorWidth",t[t.disableLayerHinting=32]="disableLayerHinting",t[t.disableMonospaceOptimizations=33]="disableMonospaceOptimizations",t[t.domReadOnly=34]="domReadOnly",t[t.dragAndDrop=35]="dragAndDrop",t[t.dropIntoEditor=36]="dropIntoEditor",t[t.emptySelectionClipboard=37]="emptySelectionClipboard",t[t.experimentalWhitespaceRendering=38]="experimentalWhitespaceRendering",t[t.extraEditorClassName=39]="extraEditorClassName",t[t.fastScrollSensitivity=40]="fastScrollSensitivity",t[t.find=41]="find",t[t.fixedOverflowWidgets=42]="fixedOverflowWidgets",t[t.folding=43]="folding",t[t.foldingStrategy=44]="foldingStrategy",t[t.foldingHighlight=45]="foldingHighlight",t[t.foldingImportsByDefault=46]="foldingImportsByDefault",t[t.foldingMaximumRegions=47]="foldingMaximumRegions",t[t.unfoldOnClickAfterEndOfLine=48]="unfoldOnClickAfterEndOfLine",t[t.fontFamily=49]="fontFamily",t[t.fontInfo=50]="fontInfo",t[t.fontLigatures=51]="fontLigatures",t[t.fontSize=52]="fontSize",t[t.fontWeight=53]="fontWeight",t[t.fontVariations=54]="fontVariations",t[t.formatOnPaste=55]="formatOnPaste",t[t.formatOnType=56]="formatOnType",t[t.glyphMargin=57]="glyphMargin",t[t.gotoLocation=58]="gotoLocation",t[t.hideCursorInOverviewRuler=59]="hideCursorInOverviewRuler",t[t.hover=60]="hover",t[t.inDiffEditor=61]="inDiffEditor",t[t.inlineSuggest=62]="inlineSuggest",t[t.inlineEdit=63]="inlineEdit",t[t.letterSpacing=64]="letterSpacing",t[t.lightbulb=65]="lightbulb",t[t.lineDecorationsWidth=66]="lineDecorationsWidth",t[t.lineHeight=67]="lineHeight",t[t.lineNumbers=68]="lineNumbers",t[t.lineNumbersMinChars=69]="lineNumbersMinChars",t[t.linkedEditing=70]="linkedEditing",t[t.links=71]="links",t[t.matchBrackets=72]="matchBrackets",t[t.minimap=73]="minimap",t[t.mouseStyle=74]="mouseStyle",t[t.mouseWheelScrollSensitivity=75]="mouseWheelScrollSensitivity",t[t.mouseWheelZoom=76]="mouseWheelZoom",t[t.multiCursorMergeOverlapping=77]="multiCursorMergeOverlapping",t[t.multiCursorModifier=78]="multiCursorModifier",t[t.multiCursorPaste=79]="multiCursorPaste",t[t.multiCursorLimit=80]="multiCursorLimit",t[t.occurrencesHighlight=81]="occurrencesHighlight",t[t.overviewRulerBorder=82]="overviewRulerBorder",t[t.overviewRulerLanes=83]="overviewRulerLanes",t[t.padding=84]="padding",t[t.pasteAs=85]="pasteAs",t[t.parameterHints=86]="parameterHints",t[t.peekWidgetDefaultFocus=87]="peekWidgetDefaultFocus",t[t.placeholder=88]="placeholder",t[t.definitionLinkOpensInPeek=89]="definitionLinkOpensInPeek",t[t.quickSuggestions=90]="quickSuggestions",t[t.quickSuggestionsDelay=91]="quickSuggestionsDelay",t[t.readOnly=92]="readOnly",t[t.readOnlyMessage=93]="readOnlyMessage",t[t.renameOnType=94]="renameOnType",t[t.renderControlCharacters=95]="renderControlCharacters",t[t.renderFinalNewline=96]="renderFinalNewline",t[t.renderLineHighlight=97]="renderLineHighlight",t[t.renderLineHighlightOnlyWhenFocus=98]="renderLineHighlightOnlyWhenFocus",t[t.renderValidationDecorations=99]="renderValidationDecorations",t[t.renderWhitespace=100]="renderWhitespace",t[t.revealHorizontalRightPadding=101]="revealHorizontalRightPadding",t[t.roundedSelection=102]="roundedSelection",t[t.rulers=103]="rulers",t[t.scrollbar=104]="scrollbar",t[t.scrollBeyondLastColumn=105]="scrollBeyondLastColumn",t[t.scrollBeyondLastLine=106]="scrollBeyondLastLine",t[t.scrollPredominantAxis=107]="scrollPredominantAxis",t[t.selectionClipboard=108]="selectionClipboard",t[t.selectionHighlight=109]="selectionHighlight",t[t.selectOnLineNumbers=110]="selectOnLineNumbers",t[t.showFoldingControls=111]="showFoldingControls",t[t.showUnused=112]="showUnused",t[t.snippetSuggestions=113]="snippetSuggestions",t[t.smartSelect=114]="smartSelect",t[t.smoothScrolling=115]="smoothScrolling",t[t.stickyScroll=116]="stickyScroll",t[t.stickyTabStops=117]="stickyTabStops",t[t.stopRenderingLineAfter=118]="stopRenderingLineAfter",t[t.suggest=119]="suggest",t[t.suggestFontSize=120]="suggestFontSize",t[t.suggestLineHeight=121]="suggestLineHeight",t[t.suggestOnTriggerCharacters=122]="suggestOnTriggerCharacters",t[t.suggestSelection=123]="suggestSelection",t[t.tabCompletion=124]="tabCompletion",t[t.tabIndex=125]="tabIndex",t[t.unicodeHighlighting=126]="unicodeHighlighting",t[t.unusualLineTerminators=127]="unusualLineTerminators",t[t.useShadowDOM=128]="useShadowDOM",t[t.useTabStops=129]="useTabStops",t[t.wordBreak=130]="wordBreak",t[t.wordSegmenterLocales=131]="wordSegmenterLocales",t[t.wordSeparators=132]="wordSeparators",t[t.wordWrap=133]="wordWrap",t[t.wordWrapBreakAfterCharacters=134]="wordWrapBreakAfterCharacters",t[t.wordWrapBreakBeforeCharacters=135]="wordWrapBreakBeforeCharacters",t[t.wordWrapColumn=136]="wordWrapColumn",t[t.wordWrapOverride1=137]="wordWrapOverride1",t[t.wordWrapOverride2=138]="wordWrapOverride2",t[t.wrappingIndent=139]="wrappingIndent",t[t.wrappingStrategy=140]="wrappingStrategy",t[t.showDeprecated=141]="showDeprecated",t[t.inlayHints=142]="inlayHints",t[t.editorClassName=143]="editorClassName",t[t.pixelRatio=144]="pixelRatio",t[t.tabFocusMode=145]="tabFocusMode",t[t.layoutInfo=146]="layoutInfo",t[t.wrappingInfo=147]="wrappingInfo",t[t.defaultColorDecorators=148]="defaultColorDecorators",t[t.colorDecoratorsActivatedOn=149]="colorDecoratorsActivatedOn",t[t.inlineCompletionsAccessibilityVerbose=150]="inlineCompletionsAccessibilityVerbose"})(r||(n.EditorOption=r={}));var s;(function(t){t[t.TextDefined=0]="TextDefined",t[t.LF=1]="LF",t[t.CRLF=2]="CRLF"})(s||(n.EndOfLinePreference=s={}));var o;(function(t){t[t.LF=0]="LF",t[t.CRLF=1]="CRLF"})(o||(n.EndOfLineSequence=o={}));var u;(function(t){t[t.Left=1]="Left",t[t.Center=2]="Center",t[t.Right=3]="Right"})(u||(n.GlyphMarginLane=u={}));var S;(function(t){t[t.Increase=0]="Increase",t[t.Decrease=1]="Decrease"})(S||(n.HoverVerbosityAction=S={}));var L;(function(t){t[t.None=0]="None",t[t.Indent=1]="Indent",t[t.IndentOutdent=2]="IndentOutdent",t[t.Outdent=3]="Outdent"})(L||(n.IndentAction=L={}));var N;(function(t){t[t.Both=0]="Both",t[t.Right=1]="Right",t[t.Left=2]="Left",t[t.None=3]="None"})(N||(n.InjectedTextCursorStops=N={}));var P;(function(t){t[t.Type=1]="Type",t[t.Parameter=2]="Parameter"})(P||(n.InlayHintKind=P={}));var E;(function(t){t[t.Automatic=0]="Automatic",t[t.Explicit=1]="Explicit"})(E||(n.InlineCompletionTriggerKind=E={}));var v;(function(t){t[t.Invoke=0]="Invoke",t[t.Automatic=1]="Automatic"})(v||(n.InlineEditTriggerKind=v={}));var l;(function(t){t[t.DependsOnKbLayout=-1]="DependsOnKbLayout",t[t.Unknown=0]="Unknown",t[t.Backspace=1]="Backspace",t[t.Tab=2]="Tab",t[t.Enter=3]="Enter",t[t.Shift=4]="Shift",t[t.Ctrl=5]="Ctrl",t[t.Alt=6]="Alt",t[t.PauseBreak=7]="PauseBreak",t[t.CapsLock=8]="CapsLock",t[t.Escape=9]="Escape",t[t.Space=10]="Space",t[t.PageUp=11]="PageUp",t[t.PageDown=12]="PageDown",t[t.End=13]="End",t[t.Home=14]="Home",t[t.LeftArrow=15]="LeftArrow",t[t.UpArrow=16]="UpArrow",t[t.RightArrow=17]="RightArrow",t[t.DownArrow=18]="DownArrow",t[t.Insert=19]="Insert",t[t.Delete=20]="Delete",t[t.Digit0=21]="Digit0",t[t.Digit1=22]="Digit1",t[t.Digit2=23]="Digit2",t[t.Digit3=24]="Digit3",t[t.Digit4=25]="Digit4",t[t.Digit5=26]="Digit5",t[t.Digit6=27]="Digit6",t[t.Digit7=28]="Digit7",t[t.Digit8=29]="Digit8",t[t.Digit9=30]="Digit9",t[t.KeyA=31]="KeyA",t[t.KeyB=32]="KeyB",t[t.KeyC=33]="KeyC",t[t.KeyD=34]="KeyD",t[t.KeyE=35]="KeyE",t[t.KeyF=36]="KeyF",t[t.KeyG=37]="KeyG",t[t.KeyH=38]="KeyH",t[t.KeyI=39]="KeyI",t[t.KeyJ=40]="KeyJ",t[t.KeyK=41]="KeyK",t[t.KeyL=42]="KeyL",t[t.KeyM=43]="KeyM",t[t.KeyN=44]="KeyN",t[t.KeyO=45]="KeyO",t[t.KeyP=46]="KeyP",t[t.KeyQ=47]="KeyQ",t[t.KeyR=48]="KeyR",t[t.KeyS=49]="KeyS",t[t.KeyT=50]="KeyT",t[t.KeyU=51]="KeyU",t[t.KeyV=52]="KeyV",t[t.KeyW=53]="KeyW",t[t.KeyX=54]="KeyX",t[t.KeyY=55]="KeyY",t[t.KeyZ=56]="KeyZ",t[t.Meta=57]="Meta",t[t.ContextMenu=58]="ContextMenu",t[t.F1=59]="F1",t[t.F2=60]="F2",t[t.F3=61]="F3",t[t.F4=62]="F4",t[t.F5=63]="F5",t[t.F6=64]="F6",t[t.F7=65]="F7",t[t.F8=66]="F8",t[t.F9=67]="F9",t[t.F10=68]="F10",t[t.F11=69]="F11",t[t.F12=70]="F12",t[t.F13=71]="F13",t[t.F14=72]="F14",t[t.F15=73]="F15",t[t.F16=74]="F16",t[t.F17=75]="F17",t[t.F18=76]="F18",t[t.F19=77]="F19",t[t.F20=78]="F20",t[t.F21=79]="F21",t[t.F22=80]="F22",t[t.F23=81]="F23",t[t.F24=82]="F24",t[t.NumLock=83]="NumLock",t[t.ScrollLock=84]="ScrollLock",t[t.Semicolon=85]="Semicolon",t[t.Equal=86]="Equal",t[t.Comma=87]="Comma",t[t.Minus=88]="Minus",t[t.Period=89]="Period",t[t.Slash=90]="Slash",t[t.Backquote=91]="Backquote",t[t.BracketLeft=92]="BracketLeft",t[t.Backslash=93]="Backslash",t[t.BracketRight=94]="BracketRight",t[t.Quote=95]="Quote",t[t.OEM_8=96]="OEM_8",t[t.IntlBackslash=97]="IntlBackslash",t[t.Numpad0=98]="Numpad0",t[t.Numpad1=99]="Numpad1",t[t.Numpad2=100]="Numpad2",t[t.Numpad3=101]="Numpad3",t[t.Numpad4=102]="Numpad4",t[t.Numpad5=103]="Numpad5",t[t.Numpad6=104]="Numpad6",t[t.Numpad7=105]="Numpad7",t[t.Numpad8=106]="Numpad8",t[t.Numpad9=107]="Numpad9",t[t.NumpadMultiply=108]="NumpadMultiply",t[t.NumpadAdd=109]="NumpadAdd",t[t.NUMPAD_SEPARATOR=110]="NUMPAD_SEPARATOR",t[t.NumpadSubtract=111]="NumpadSubtract",t[t.NumpadDecimal=112]="NumpadDecimal",t[t.NumpadDivide=113]="NumpadDivide",t[t.KEY_IN_COMPOSITION=114]="KEY_IN_COMPOSITION",t[t.ABNT_C1=115]="ABNT_C1",t[t.ABNT_C2=116]="ABNT_C2",t[t.AudioVolumeMute=117]="AudioVolumeMute",t[t.AudioVolumeUp=118]="AudioVolumeUp",t[t.AudioVolumeDown=119]="AudioVolumeDown",t[t.BrowserSearch=120]="BrowserSearch",t[t.BrowserHome=121]="BrowserHome",t[t.BrowserBack=122]="BrowserBack",t[t.BrowserForward=123]="BrowserForward",t[t.MediaTrackNext=124]="MediaTrackNext",t[t.MediaTrackPrevious=125]="MediaTrackPrevious",t[t.MediaStop=126]="MediaStop",t[t.MediaPlayPause=127]="MediaPlayPause",t[t.LaunchMediaPlayer=128]="LaunchMediaPlayer",t[t.LaunchMail=129]="LaunchMail",t[t.LaunchApp2=130]="LaunchApp2",t[t.Clear=131]="Clear",t[t.MAX_VALUE=132]="MAX_VALUE"})(l||(n.KeyCode=l={}));var b;(function(t){t[t.Hint=1]="Hint",t[t.Info=2]="Info",t[t.Warning=4]="Warning",t[t.Error=8]="Error"})(b||(n.MarkerSeverity=b={}));var g;(function(t){t[t.Unnecessary=1]="Unnecessary",t[t.Deprecated=2]="Deprecated"})(g||(n.MarkerTag=g={}));var w;(function(t){t[t.Inline=1]="Inline",t[t.Gutter=2]="Gutter"})(w||(n.MinimapPosition=w={}));var M;(function(t){t[t.Normal=1]="Normal",t[t.Underlined=2]="Underlined"})(M||(n.MinimapSectionHeaderStyle=M={}));var y;(function(t){t[t.UNKNOWN=0]="UNKNOWN",t[t.TEXTAREA=1]="TEXTAREA",t[t.GUTTER_GLYPH_MARGIN=2]="GUTTER_GLYPH_MARGIN",t[t.GUTTER_LINE_NUMBERS=3]="GUTTER_LINE_NUMBERS",t[t.GUTTER_LINE_DECORATIONS=4]="GUTTER_LINE_DECORATIONS",t[t.GUTTER_VIEW_ZONE=5]="GUTTER_VIEW_ZONE",t[t.CONTENT_TEXT=6]="CONTENT_TEXT",t[t.CONTENT_EMPTY=7]="CONTENT_EMPTY",t[t.CONTENT_VIEW_ZONE=8]="CONTENT_VIEW_ZONE",t[t.CONTENT_WIDGET=9]="CONTENT_WIDGET",t[t.OVERVIEW_RULER=10]="OVERVIEW_RULER",t[t.SCROLLBAR=11]="SCROLLBAR",t[t.OVERLAY_WIDGET=12]="OVERLAY_WIDGET",t[t.OUTSIDE_EDITOR=13]="OUTSIDE_EDITOR"})(y||(n.MouseTargetType=y={}));var _;(function(t){t[t.AIGenerated=1]="AIGenerated"})(_||(n.NewSymbolNameTag=_={}));var C;(function(t){t[t.Invoke=0]="Invoke",t[t.Automatic=1]="Automatic"})(C||(n.NewSymbolNameTriggerKind=C={}));var R;(function(t){t[t.TOP_RIGHT_CORNER=0]="TOP_RIGHT_CORNER",t[t.BOTTOM_RIGHT_CORNER=1]="BOTTOM_RIGHT_CORNER",t[t.TOP_CENTER=2]="TOP_CENTER"})(R||(n.OverlayWidgetPositionPreference=R={}));var D;(function(t){t[t.Left=1]="Left",t[t.Center=2]="Center",t[t.Right=4]="Right",t[t.Full=7]="Full"})(D||(n.OverviewRulerLane=D={}));var T;(function(t){t[t.Word=0]="Word",t[t.Line=1]="Line",t[t.Suggest=2]="Suggest"})(T||(n.PartialAcceptTriggerKind=T={}));var O;(function(t){t[t.Left=0]="Left",t[t.Right=1]="Right",t[t.None=2]="None",t[t.LeftOfInjectedText=3]="LeftOfInjectedText",t[t.RightOfInjectedText=4]="RightOfInjectedText"})(O||(n.PositionAffinity=O={}));var z;(function(t){t[t.Off=0]="Off",t[t.On=1]="On",t[t.Relative=2]="Relative",t[t.Interval=3]="Interval",t[t.Custom=4]="Custom"})(z||(n.RenderLineNumbersType=z={}));var j;(function(t){t[t.None=0]="None",t[t.Text=1]="Text",t[t.Blocks=2]="Blocks"})(j||(n.RenderMinimap=j={}));var F;(function(t){t[t.Smooth=0]="Smooth",t[t.Immediate=1]="Immediate"})(F||(n.ScrollType=F={}));var q;(function(t){t[t.Auto=1]="Auto",t[t.Hidden=2]="Hidden",t[t.Visible=3]="Visible"})(q||(n.ScrollbarVisibility=q={}));var B;(function(t){t[t.LTR=0]="LTR",t[t.RTL=1]="RTL"})(B||(n.SelectionDirection=B={}));var G;(function(t){t.Off="off",t.OnCode="onCode",t.On="on"})(G||(n.ShowLightbulbIconMode=G={}));var $;(function(t){t[t.Invoke=1]="Invoke",t[t.TriggerCharacter=2]="TriggerCharacter",t[t.ContentChange=3]="ContentChange"})($||(n.SignatureHelpTriggerKind=$={}));var U;(function(t){t[t.File=0]="File",t[t.Module=1]="Module",t[t.Namespace=2]="Namespace",t[t.Package=3]="Package",t[t.Class=4]="Class",t[t.Method=5]="Method",t[t.Property=6]="Property",t[t.Field=7]="Field",t[t.Constructor=8]="Constructor",t[t.Enum=9]="Enum",t[t.Interface=10]="Interface",t[t.Function=11]="Function",t[t.Variable=12]="Variable",t[t.Constant=13]="Constant",t[t.String=14]="String",t[t.Number=15]="Number",t[t.Boolean=16]="Boolean",t[t.Array=17]="Array",t[t.Object=18]="Object",t[t.Key=19]="Key",t[t.Null=20]="Null",t[t.EnumMember=21]="EnumMember",t[t.Struct=22]="Struct",t[t.Event=23]="Event",t[t.Operator=24]="Operator",t[t.TypeParameter=25]="TypeParameter"})(U||(n.SymbolKind=U={}));var ee;(function(t){t[t.Deprecated=1]="Deprecated"})(ee||(n.SymbolTag=ee={}));var re;(function(t){t[t.Hidden=0]="Hidden",t[t.Blink=1]="Blink",t[t.Smooth=2]="Smooth",t[t.Phase=3]="Phase",t[t.Expand=4]="Expand",t[t.Solid=5]="Solid"})(re||(n.TextEditorCursorBlinkingStyle=re={}));var ue;(function(t){t[t.Line=1]="Line",t[t.Block=2]="Block",t[t.Underline=3]="Underline",t[t.LineThin=4]="LineThin",t[t.BlockOutline=5]="BlockOutline",t[t.UnderlineThin=6]="UnderlineThin"})(ue||(n.TextEditorCursorStyle=ue={}));var de;(function(t){t[t.AlwaysGrowsWhenTypingAtEdges=0]="AlwaysGrowsWhenTypingAtEdges",t[t.NeverGrowsWhenTypingAtEdges=1]="NeverGrowsWhenTypingAtEdges",t[t.GrowsOnlyWhenTypingBefore=2]="GrowsOnlyWhenTypingBefore",t[t.GrowsOnlyWhenTypingAfter=3]="GrowsOnlyWhenTypingAfter"})(de||(n.TrackedRangeStickiness=de={}));var ge;(function(t){t[t.None=0]="None",t[t.Same=1]="Same",t[t.Indent=2]="Indent",t[t.DeepIndent=3]="DeepIndent"})(ge||(n.WrappingIndent=ge={}))}),X(J[70],Z([0,1,9,8]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.TokenizationRegistry=void 0;class A{constructor(){this._tokenizationSupports=new Map,this._factories=new Map,this._onDidChange=new i.Emitter,this.onDidChange=this._onDidChange.event,this._colorMap=null}handleChange(p){this._onDidChange.fire({changedLanguages:p,changedColorMap:!1})}register(p,c){return this._tokenizationSupports.set(p,c),this.handleChange([p]),(0,x.toDisposable)(()=>{this._tokenizationSupports.get(p)===c&&(this._tokenizationSupports.delete(p),this.handleChange([p]))})}get(p){return this._tokenizationSupports.get(p)||null}registerFactory(p,c){this._factories.get(p)?.dispose();const a=new d(this,p,c);return this._factories.set(p,a),(0,x.toDisposable)(()=>{const m=this._factories.get(p);!m||m!==a||(this._factories.delete(p),m.dispose())})}async getOrCreate(p){const c=this.get(p);if(c)return c;const a=this._factories.get(p);return!a||a.isResolved?null:(await a.resolve(),this.get(p))}isResolved(p){if(this.get(p))return!0;const a=this._factories.get(p);return!!(!a||a.isResolved)}setColorMap(p){this._colorMap=p,this._onDidChange.fire({changedLanguages:Array.from(this._tokenizationSupports.keys()),changedColorMap:!0})}getColorMap(){return this._colorMap}getDefaultBackground(){return this._colorMap&&this._colorMap.length>2?this._colorMap[2]:null}}n.TokenizationRegistry=A;class d extends x.Disposable{get isResolved(){return this._isResolved}constructor(p,c,a){super(),this._registry=p,this._languageId=c,this._factory=a,this._isDisposed=!1,this._resolvePromise=null,this._isResolved=!1}dispose(){this._isDisposed=!0,super.dispose()}async resolve(){return this._resolvePromise||(this._resolvePromise=this._create()),this._resolvePromise}async _create(){const p=await this._factory.tokenizationSupport;this._isResolved=!0,p&&!this._isDisposed&&this._register(this._registry.register(this._languageId,p))}}}),X(J[35],Z([0,1]),function(W,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.getNLSMessages=i,n.getNLSLanguage=x;function i(){return globalThis._VSCODE_NLS_MESSAGES}function x(){return globalThis._VSCODE_NLS_LANGUAGE}}),X(J[36],Z([0,1,35,35]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.getNLSMessages=n.getNLSLanguage=void 0,n.localize=f,n.localize2=c,Object.defineProperty(n,"getNLSLanguage",{enumerable:!0,get:function(){return x.getNLSLanguage}}),Object.defineProperty(n,"getNLSMessages",{enumerable:!0,get:function(){return x.getNLSMessages}});const A=(0,i.getNLSLanguage)()==="pseudo"||typeof document<"u"&&document.location&&document.location.hash.indexOf("pseudo=true")>=0;function d(a,m){let e;return m.length===0?e=a:e=a.replace(/\{(\d+)\}/g,(h,r)=>{const s=r[0],o=m[s];let u=h;return typeof o=="string"?u=o:(typeof o=="number"||typeof o=="boolean"||o===void 0||o===null)&&(u=String(o)),u}),A&&(e="\uFF3B"+e.replace(/[aouei]/g,"$&$&")+"\uFF3D"),e}function f(a,m,...e){return d(typeof a=="number"?p(a,m):m,e)}function p(a,m){const e=(0,i.getNLSMessages)()?.[a];if(typeof e!="string"){if(typeof m=="string")return m;throw new Error(`!!! NLS MISSING: ${a} !!!`)}return e}function c(a,m,...e){let h;typeof a=="number"?h=p(a,m):h=m;const r=d(h,e);return{value:r,original:m===h?r:d(m,e)}}}),X(J[11],Z([0,1,36]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.isAndroid=n.isEdge=n.isSafari=n.isFirefox=n.isChrome=n.OS=n.setTimeout0=n.setTimeout0IsFaster=n.language=n.userAgent=n.isMobile=n.isIOS=n.webWorkerOrigin=n.isWebWorker=n.isWeb=n.isNative=n.isLinux=n.isMacintosh=n.isWindows=n.LANGUAGE_DEFAULT=void 0,n.isLittleEndian=g,n.LANGUAGE_DEFAULT="en";let x=!1,A=!1,d=!1,f=!1,p=!1,c=!1,a=!1,m=!1,e=!1,h=!1,r,s=n.LANGUAGE_DEFAULT,o=n.LANGUAGE_DEFAULT,u,S;const L=globalThis;let N;typeof L.vscode<"u"&&typeof L.vscode.process<"u"?N=L.vscode.process:typeof process<"u"&&typeof process?.versions?.node=="string"&&(N=process);const P=typeof N?.versions?.electron=="string",E=P&&N?.type==="renderer";if(typeof N=="object"){x=N.platform==="win32",A=N.platform==="darwin",d=N.platform==="linux",f=d&&!!N.env.SNAP&&!!N.env.SNAP_REVISION,a=P,e=!!N.env.CI||!!N.env.BUILD_ARTIFACTSTAGINGDIRECTORY,r=n.LANGUAGE_DEFAULT,s=n.LANGUAGE_DEFAULT;const w=N.env.VSCODE_NLS_CONFIG;if(w)try{const M=JSON.parse(w);r=M.userLocale,o=M.osLocale,s=M.resolvedLanguage||n.LANGUAGE_DEFAULT,u=M.languagePack?.translationsConfigFile}catch{}p=!0}else typeof navigator=="object"&&!E?(S=navigator.userAgent,x=S.indexOf("Windows")>=0,A=S.indexOf("Macintosh")>=0,m=(S.indexOf("Macintosh")>=0||S.indexOf("iPad")>=0||S.indexOf("iPhone")>=0)&&!!navigator.maxTouchPoints&&navigator.maxTouchPoints>0,d=S.indexOf("Linux")>=0,h=S?.indexOf("Mobi")>=0,c=!0,s=i.getNLSLanguage()||n.LANGUAGE_DEFAULT,r=navigator.language.toLowerCase(),o=r):console.error("Unable to resolve platform.");let v=0;A?v=1:x?v=3:d&&(v=2),n.isWindows=x,n.isMacintosh=A,n.isLinux=d,n.isNative=p,n.isWeb=c,n.isWebWorker=c&&typeof L.importScripts=="function",n.webWorkerOrigin=n.isWebWorker?L.origin:void 0,n.isIOS=m,n.isMobile=h,n.userAgent=S,n.language=s,n.setTimeout0IsFaster=typeof L.postMessage=="function"&&!L.importScripts,n.setTimeout0=(()=>{if(n.setTimeout0IsFaster){const w=[];L.addEventListener("message",y=>{if(y.data&&y.data.vscodeScheduleAsyncWork)for(let _=0,C=w.length;_{const _=++M;w.push({id:_,callback:y}),L.postMessage({vscodeScheduleAsyncWork:_},"*")}}return w=>setTimeout(w)})(),n.OS=A||m?2:x?1:3;let l=!0,b=!1;function g(){if(!b){b=!0;const w=new Uint8Array(2);w[0]=1,w[1]=2,l=new Uint16Array(w.buffer)[0]===513}return l}n.isChrome=!!(n.userAgent&&n.userAgent.indexOf("Chrome")>=0),n.isFirefox=!!(n.userAgent&&n.userAgent.indexOf("Firefox")>=0),n.isSafari=!!(!n.isChrome&&n.userAgent&&n.userAgent.indexOf("Safari")>=0),n.isEdge=!!(n.userAgent&&n.userAgent.indexOf("Edg/")>=0),n.isAndroid=!!(n.userAgent&&n.userAgent.indexOf("Android")>=0)}),X(J[71],Z([0,1,23,3,9,8,11,45]),function(W,n,i,x,A,d,f,p){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.CancelableAsyncIterableObject=n.AsyncIterableObject=n.Promises=n.DeferredPromise=n.GlobalIdleValue=n.AbstractIdleValue=n._runWhenIdle=n.runWhenGlobalIdle=n.RunOnceScheduler=n.IntervalTimer=n.TimeoutTimer=n.ThrottledDelayer=n.Delayer=n.Throttler=void 0,n.isThenable=c,n.createCancelablePromise=a,n.raceCancellation=m,n.timeout=u,n.disposableTimeout=S,n.first=L,n.createCancelableAsyncIterable=y;function c(_){return!!_&&typeof _.then=="function"}function a(_){const C=new i.CancellationTokenSource,R=_(C.token),D=new Promise((T,O)=>{const z=C.token.onCancellationRequested(()=>{z.dispose(),O(new x.CancellationError)});Promise.resolve(R).then(j=>{z.dispose(),C.dispose(),T(j)},j=>{z.dispose(),C.dispose(),O(j)})});return new class{cancel(){C.cancel(),C.dispose()}then(T,O){return D.then(T,O)}catch(T){return this.then(void 0,T)}finally(T){return D.finally(T)}}}function m(_,C,R){return new Promise((D,T)=>{const O=C.onCancellationRequested(()=>{O.dispose(),D(R)});_.then(D,T).finally(()=>O.dispose())})}class e{constructor(){this.isDisposed=!1,this.activePromise=null,this.queuedPromise=null,this.queuedPromiseFactory=null}queue(C){if(this.isDisposed)return Promise.reject(new Error("Throttler is disposed"));if(this.activePromise){if(this.queuedPromiseFactory=C,!this.queuedPromise){const R=()=>{if(this.queuedPromise=null,this.isDisposed)return;const D=this.queue(this.queuedPromiseFactory);return this.queuedPromiseFactory=null,D};this.queuedPromise=new Promise(D=>{this.activePromise.then(R,R).then(D)})}return new Promise((R,D)=>{this.queuedPromise.then(R,D)})}return this.activePromise=C(),new Promise((R,D)=>{this.activePromise.then(T=>{this.activePromise=null,R(T)},T=>{this.activePromise=null,D(T)})})}dispose(){this.isDisposed=!0}}n.Throttler=e;const h=(_,C)=>{let R=!0;const D=setTimeout(()=>{R=!1,C()},_);return{isTriggered:()=>R,dispose:()=>{clearTimeout(D),R=!1}}},r=_=>{let C=!0;return queueMicrotask(()=>{C&&(C=!1,_())}),{isTriggered:()=>C,dispose:()=>{C=!1}}};class s{constructor(C){this.defaultDelay=C,this.deferred=null,this.completionPromise=null,this.doResolve=null,this.doReject=null,this.task=null}trigger(C,R=this.defaultDelay){this.task=C,this.cancelTimeout(),this.completionPromise||(this.completionPromise=new Promise((T,O)=>{this.doResolve=T,this.doReject=O}).then(()=>{if(this.completionPromise=null,this.doResolve=null,this.task){const T=this.task;return this.task=null,T()}}));const D=()=>{this.deferred=null,this.doResolve?.(null)};return this.deferred=R===p.MicrotaskDelay?r(D):h(R,D),this.completionPromise}isTriggered(){return!!this.deferred?.isTriggered()}cancel(){this.cancelTimeout(),this.completionPromise&&(this.doReject?.(new x.CancellationError),this.completionPromise=null)}cancelTimeout(){this.deferred?.dispose(),this.deferred=null}dispose(){this.cancel()}}n.Delayer=s;class o{constructor(C){this.delayer=new s(C),this.throttler=new e}trigger(C,R){return this.delayer.trigger(()=>this.throttler.queue(C),R)}cancel(){this.delayer.cancel()}dispose(){this.delayer.dispose(),this.throttler.dispose()}}n.ThrottledDelayer=o;function u(_,C){return C?new Promise((R,D)=>{const T=setTimeout(()=>{O.dispose(),R()},_),O=C.onCancellationRequested(()=>{clearTimeout(T),O.dispose(),D(new x.CancellationError)})}):a(R=>u(_,R))}function S(_,C=0,R){const D=setTimeout(()=>{_(),R&&T.dispose()},C),T=(0,d.toDisposable)(()=>{clearTimeout(D),R?.deleteAndLeak(T)});return R?.add(T),T}function L(_,C=D=>!!D,R=null){let D=0;const T=_.length,O=()=>{if(D>=T)return Promise.resolve(R);const z=_[D++];return Promise.resolve(z()).then(F=>C(F)?Promise.resolve(F):O())};return O()}class N{constructor(C,R){this._isDisposed=!1,this._token=-1,typeof C=="function"&&typeof R=="number"&&this.setIfNotSet(C,R)}dispose(){this.cancel(),this._isDisposed=!0}cancel(){this._token!==-1&&(clearTimeout(this._token),this._token=-1)}cancelAndSet(C,R){if(this._isDisposed)throw new x.BugIndicatingError("Calling 'cancelAndSet' on a disposed TimeoutTimer");this.cancel(),this._token=setTimeout(()=>{this._token=-1,C()},R)}setIfNotSet(C,R){if(this._isDisposed)throw new x.BugIndicatingError("Calling 'setIfNotSet' on a disposed TimeoutTimer");this._token===-1&&(this._token=setTimeout(()=>{this._token=-1,C()},R))}}n.TimeoutTimer=N;class P{constructor(){this.disposable=void 0,this.isDisposed=!1}cancel(){this.disposable?.dispose(),this.disposable=void 0}cancelAndSet(C,R,D=globalThis){if(this.isDisposed)throw new x.BugIndicatingError("Calling 'cancelAndSet' on a disposed IntervalTimer");this.cancel();const T=D.setInterval(()=>{C()},R);this.disposable=(0,d.toDisposable)(()=>{D.clearInterval(T),this.disposable=void 0})}dispose(){this.cancel(),this.isDisposed=!0}}n.IntervalTimer=P;class E{constructor(C,R){this.timeoutToken=-1,this.runner=C,this.timeout=R,this.timeoutHandler=this.onTimeout.bind(this)}dispose(){this.cancel(),this.runner=null}cancel(){this.isScheduled()&&(clearTimeout(this.timeoutToken),this.timeoutToken=-1)}schedule(C=this.timeout){this.cancel(),this.timeoutToken=setTimeout(this.timeoutHandler,C)}get delay(){return this.timeout}set delay(C){this.timeout=C}isScheduled(){return this.timeoutToken!==-1}onTimeout(){this.timeoutToken=-1,this.runner&&this.doRun()}doRun(){this.runner?.()}}n.RunOnceScheduler=E,function(){typeof globalThis.requestIdleCallback!="function"||typeof globalThis.cancelIdleCallback!="function"?n._runWhenIdle=(_,C)=>{(0,f.setTimeout0)(()=>{if(R)return;const D=Date.now()+15;C(Object.freeze({didTimeout:!0,timeRemaining(){return Math.max(0,D-Date.now())}}))});let R=!1;return{dispose(){R||(R=!0)}}}:n._runWhenIdle=(_,C,R)=>{const D=_.requestIdleCallback(C,typeof R=="number"?{timeout:R}:void 0);let T=!1;return{dispose(){T||(T=!0,_.cancelIdleCallback(D))}}},n.runWhenGlobalIdle=_=>(0,n._runWhenIdle)(globalThis,_)}();class v{constructor(C,R){this._didRun=!1,this._executor=()=>{try{this._value=R()}catch(D){this._error=D}finally{this._didRun=!0}},this._handle=(0,n._runWhenIdle)(C,()=>this._executor())}dispose(){this._handle.dispose()}get value(){if(this._didRun||(this._handle.dispose(),this._executor()),this._error)throw this._error;return this._value}get isInitialized(){return this._didRun}}n.AbstractIdleValue=v;class l extends v{constructor(C){super(globalThis,C)}}n.GlobalIdleValue=l;class b{get isRejected(){return this.outcome?.outcome===1}get isSettled(){return!!this.outcome}constructor(){this.p=new Promise((C,R)=>{this.completeCallback=C,this.errorCallback=R})}complete(C){return new Promise(R=>{this.completeCallback(C),this.outcome={outcome:0,value:C},R()})}error(C){return new Promise(R=>{this.errorCallback(C),this.outcome={outcome:1,value:C},R()})}cancel(){return this.error(new x.CancellationError)}}n.DeferredPromise=b;var g;(function(_){async function C(D){let T;const O=await Promise.all(D.map(z=>z.then(j=>j,j=>{T||(T=j)})));if(typeof T<"u")throw T;return O}_.settled=C;function R(D){return new Promise(async(T,O)=>{try{await D(T,O)}catch(z){O(z)}})}_.withAsyncBody=R})(g||(n.Promises=g={}));class w{static fromArray(C){return new w(R=>{R.emitMany(C)})}static fromPromise(C){return new w(async R=>{R.emitMany(await C)})}static fromPromises(C){return new w(async R=>{await Promise.all(C.map(async D=>R.emitOne(await D)))})}static merge(C){return new w(async R=>{await Promise.all(C.map(async D=>{for await(const T of D)R.emitOne(T)}))})}static{this.EMPTY=w.fromArray([])}constructor(C,R){this._state=0,this._results=[],this._error=null,this._onReturn=R,this._onStateChanged=new A.Emitter,queueMicrotask(async()=>{const D={emitOne:T=>this.emitOne(T),emitMany:T=>this.emitMany(T),reject:T=>this.reject(T)};try{await Promise.resolve(C(D)),this.resolve()}catch(T){this.reject(T)}finally{D.emitOne=void 0,D.emitMany=void 0,D.reject=void 0}})}[Symbol.asyncIterator](){let C=0;return{next:async()=>{do{if(this._state===2)throw this._error;if(C(this._onReturn?.(),{done:!0,value:void 0})}}static map(C,R){return new w(async D=>{for await(const T of C)D.emitOne(R(T))})}map(C){return w.map(this,C)}static filter(C,R){return new w(async D=>{for await(const T of C)R(T)&&D.emitOne(T)})}filter(C){return w.filter(this,C)}static coalesce(C){return w.filter(C,R=>!!R)}coalesce(){return w.coalesce(this)}static async toPromise(C){const R=[];for await(const D of C)R.push(D);return R}toPromise(){return w.toPromise(this)}emitOne(C){this._state===0&&(this._results.push(C),this._onStateChanged.fire())}emitMany(C){this._state===0&&(this._results=this._results.concat(C),this._onStateChanged.fire())}resolve(){this._state===0&&(this._state=1,this._onStateChanged.fire())}reject(C){this._state===0&&(this._state=2,this._error=C,this._onStateChanged.fire())}}n.AsyncIterableObject=w;class M extends w{constructor(C,R){super(R),this._source=C}cancel(){this._source.cancel()}}n.CancelableAsyncIterableObject=M;function y(_){const C=new i.CancellationTokenSource,R=_(C.token);return new M(C,async D=>{const T=C.token.onCancellationRequested(()=>{T.dispose(),C.dispose(),D.reject(new x.CancellationError)});try{for await(const O of R){if(C.token.isCancellationRequested)return;D.emitOne(O)}T.dispose(),C.dispose()}catch(O){T.dispose(),C.dispose(),D.reject(O)}})}}),X(J[72],Z([0,1,11]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.platform=n.env=n.cwd=void 0;let x;const A=globalThis.vscode;if(typeof A<"u"&&typeof A.process<"u"){const d=A.process;x={get platform(){return d.platform},get arch(){return d.arch},get env(){return d.env},cwd(){return d.cwd()}}}else typeof process<"u"&&typeof process?.versions?.node=="string"?x={get platform(){return process.platform},get arch(){return process.arch},get env(){return process.env},cwd(){return process.env.VSCODE_CWD||process.cwd()}}:x={get platform(){return i.isWindows?"win32":i.isMacintosh?"darwin":"linux"},get arch(){},get env(){return{}},cwd(){return"/"}};n.cwd=x.cwd,n.env=x.env,n.platform=x.platform}),X(J[37],Z([0,1,72]),function(W,n,i){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sep=n.extname=n.basename=n.dirname=n.relative=n.resolve=n.join=n.normalize=n.posix=n.win32=void 0;const x=65,A=97,d=90,f=122,p=46,c=47,a=92,m=58,e=63;class h extends Error{constructor(b,g,w){let M;typeof g=="string"&&g.indexOf("not ")===0?(M="must not be",g=g.replace(/^not /,"")):M="must be";const y=b.indexOf(".")!==-1?"property":"argument";let _=`The "${b}" ${y} ${M} of type ${g}`;_+=`. Received type ${typeof w}`,super(_),this.code="ERR_INVALID_ARG_TYPE"}}function r(l,b){if(l===null||typeof l!="object")throw new h(b,"Object",l)}function s(l,b){if(typeof l!="string")throw new h(b,"string",l)}const o=i.platform==="win32";function u(l){return l===c||l===a}function S(l){return l===c}function L(l){return l>=x&&l<=d||l>=A&&l<=f}function N(l,b,g,w){let M="",y=0,_=-1,C=0,R=0;for(let D=0;D<=l.length;++D){if(D2){const T=M.lastIndexOf(g);T===-1?(M="",y=0):(M=M.slice(0,T),y=M.length-1-M.lastIndexOf(g)),_=D,C=0;continue}else if(M.length!==0){M="",y=0,_=D,C=0;continue}}b&&(M+=M.length>0?`${g}..`:"..",y=2)}else M.length>0?M+=`${g}${l.slice(_+1,D)}`:M=l.slice(_+1,D),y=D-_-1;_=D,C=0}else R===p&&C!==-1?++C:C=-1}return M}function P(l){return l?`${l[0]==="."?"":"."}${l}`:""}function E(l,b){r(b,"pathObject");const g=b.dir||b.root,w=b.base||`${b.name||""}${P(b.ext)}`;return g?g===b.root?`${g}${w}`:`${g}${l}${w}`:w}n.win32={resolve(...l){let b="",g="",w=!1;for(let M=l.length-1;M>=-1;M--){let y;if(M>=0){if(y=l[M],s(y,`paths[${M}]`),y.length===0)continue}else b.length===0?y=i.cwd():(y=i.env[`=${b}`]||i.cwd(),(y===void 0||y.slice(0,2).toLowerCase()!==b.toLowerCase()&&y.charCodeAt(2)===a)&&(y=`${b}\\`));const _=y.length;let C=0,R="",D=!1;const T=y.charCodeAt(0);if(_===1)u(T)&&(C=1,D=!0);else if(u(T))if(D=!0,u(y.charCodeAt(1))){let O=2,z=O;for(;O<_&&!u(y.charCodeAt(O));)O++;if(O<_&&O!==z){const j=y.slice(z,O);for(z=O;O<_&&u(y.charCodeAt(O));)O++;if(O<_&&O!==z){for(z=O;O<_&&!u(y.charCodeAt(O));)O++;(O===_||O!==z)&&(R=`\\\\${j}\\${y.slice(z,O)}`,C=O)}}}else C=1;else L(T)&&y.charCodeAt(1)===m&&(R=y.slice(0,2),C=2,_>2&&u(y.charCodeAt(2))&&(D=!0,C=3));if(R.length>0)if(b.length>0){if(R.toLowerCase()!==b.toLowerCase())continue}else b=R;if(w){if(b.length>0)break}else if(g=`${y.slice(C)}\\${g}`,w=D,D&&b.length>0)break}return g=N(g,!w,"\\",u),w?`${b}\\${g}`:`${b}${g}`||"."},normalize(l){s(l,"path");const b=l.length;if(b===0)return".";let g=0,w,M=!1;const y=l.charCodeAt(0);if(b===1)return S(y)?"\\":l;if(u(y))if(M=!0,u(l.charCodeAt(1))){let C=2,R=C;for(;C2&&u(l.charCodeAt(2))&&(M=!0,g=3));let _=g0&&u(l.charCodeAt(b-1))&&(_+="\\"),w===void 0?M?`\\${_}`:_:M?`${w}\\${_}`:`${w}${_}`},isAbsolute(l){s(l,"path");const b=l.length;if(b===0)return!1;const g=l.charCodeAt(0);return u(g)||b>2&&L(g)&&l.charCodeAt(1)===m&&u(l.charCodeAt(2))},join(...l){if(l.length===0)return".";let b,g;for(let y=0;y0&&(b===void 0?b=g=_:b+=`\\${_}`)}if(b===void 0)return".";let w=!0,M=0;if(typeof g=="string"&&u(g.charCodeAt(0))){++M;const y=g.length;y>1&&u(g.charCodeAt(1))&&(++M,y>2&&(u(g.charCodeAt(2))?++M:w=!1))}if(w){for(;M=2&&(b=`\\${b.slice(M)}`)}return n.win32.normalize(b)},relative(l,b){if(s(l,"from"),s(b,"to"),l===b)return"";const g=n.win32.resolve(l),w=n.win32.resolve(b);if(g===w||(l=g.toLowerCase(),b=w.toLowerCase(),l===b))return"";let M=0;for(;MM&&l.charCodeAt(y-1)===a;)y--;const _=y-M;let C=0;for(;CC&&b.charCodeAt(R-1)===a;)R--;const D=R-C,T=_T){if(b.charCodeAt(C+z)===a)return w.slice(C+z+1);if(z===2)return w.slice(C+z)}_>T&&(l.charCodeAt(M+z)===a?O=z:z===2&&(O=3)),O===-1&&(O=0)}let j="";for(z=M+O+1;z<=y;++z)(z===y||l.charCodeAt(z)===a)&&(j+=j.length===0?"..":"\\..");return C+=O,j.length>0?`${j}${w.slice(C,R)}`:(w.charCodeAt(C)===a&&++C,w.slice(C,R))},toNamespacedPath(l){if(typeof l!="string"||l.length===0)return l;const b=n.win32.resolve(l);if(b.length<=2)return l;if(b.charCodeAt(0)===a){if(b.charCodeAt(1)===a){const g=b.charCodeAt(2);if(g!==e&&g!==p)return`\\\\?\\UNC\\${b.slice(2)}`}}else if(L(b.charCodeAt(0))&&b.charCodeAt(1)===m&&b.charCodeAt(2)===a)return`\\\\?\\${b}`;return l},dirname(l){s(l,"path");const b=l.length;if(b===0)return".";let g=-1,w=0;const M=l.charCodeAt(0);if(b===1)return u(M)?l:".";if(u(M)){if(g=w=1,u(l.charCodeAt(1))){let C=2,R=C;for(;C2&&u(l.charCodeAt(2))?3:2,w=g);let y=-1,_=!0;for(let C=b-1;C>=w;--C)if(u(l.charCodeAt(C))){if(!_){y=C;break}}else _=!1;if(y===-1){if(g===-1)return".";y=g}return l.slice(0,y)},basename(l,b){b!==void 0&&s(b,"suffix"),s(l,"path");let g=0,w=-1,M=!0,y;if(l.length>=2&&L(l.charCodeAt(0))&&l.charCodeAt(1)===m&&(g=2),b!==void 0&&b.length>0&&b.length<=l.length){if(b===l)return"";let _=b.length-1,C=-1;for(y=l.length-1;y>=g;--y){const R=l.charCodeAt(y);if(u(R)){if(!M){g=y+1;break}}else C===-1&&(M=!1,C=y+1),_>=0&&(R===b.charCodeAt(_)?--_===-1&&(w=y):(_=-1,w=C))}return g===w?w=C:w===-1&&(w=l.length),l.slice(g,w)}for(y=l.length-1;y>=g;--y)if(u(l.charCodeAt(y))){if(!M){g=y+1;break}}else w===-1&&(M=!1,w=y+1);return w===-1?"":l.slice(g,w)},extname(l){s(l,"path");let b=0,g=-1,w=0,M=-1,y=!0,_=0;l.length>=2&&l.charCodeAt(1)===m&&L(l.charCodeAt(0))&&(b=w=2);for(let C=l.length-1;C>=b;--C){const R=l.charCodeAt(C);if(u(R)){if(!y){w=C+1;break}continue}M===-1&&(y=!1,M=C+1),R===p?g===-1?g=C:_!==1&&(_=1):g!==-1&&(_=-1)}return g===-1||M===-1||_===0||_===1&&g===M-1&&g===w+1?"":l.slice(g,M)},format:E.bind(null,"\\"),parse(l){s(l,"path");const b={root:"",dir:"",base:"",ext:"",name:""};if(l.length===0)return b;const g=l.length;let w=0,M=l.charCodeAt(0);if(g===1)return u(M)?(b.root=b.dir=l,b):(b.base=b.name=l,b);if(u(M)){if(w=1,u(l.charCodeAt(1))){let O=2,z=O;for(;O0&&(b.root=l.slice(0,w));let y=-1,_=w,C=-1,R=!0,D=l.length-1,T=0;for(;D>=w;--D){if(M=l.charCodeAt(D),u(M)){if(!R){_=D+1;break}continue}C===-1&&(R=!1,C=D+1),M===p?y===-1?y=D:T!==1&&(T=1):y!==-1&&(T=-1)}return C!==-1&&(y===-1||T===0||T===1&&y===C-1&&y===_+1?b.base=b.name=l.slice(_,C):(b.name=l.slice(_,y),b.base=l.slice(_,C),b.ext=l.slice(y,C))),_>0&&_!==w?b.dir=l.slice(0,_-1):b.dir=b.root,b},sep:"\\",delimiter:";",win32:null,posix:null};const v=(()=>{if(o){const l=/\\/g;return()=>{const b=i.cwd().replace(l,"/");return b.slice(b.indexOf("/"))}}return()=>i.cwd()})();n.posix={resolve(...l){let b="",g=!1;for(let w=l.length-1;w>=-1&&!g;w--){const M=w>=0?l[w]:v();s(M,`paths[${w}]`),M.length!==0&&(b=`${M}/${b}`,g=M.charCodeAt(0)===c)}return b=N(b,!g,"/",S),g?`/${b}`:b.length>0?b:"."},normalize(l){if(s(l,"path"),l.length===0)return".";const b=l.charCodeAt(0)===c,g=l.charCodeAt(l.length-1)===c;return l=N(l,!b,"/",S),l.length===0?b?"/":g?"./":".":(g&&(l+="/"),b?`/${l}`:l)},isAbsolute(l){return s(l,"path"),l.length>0&&l.charCodeAt(0)===c},join(...l){if(l.length===0)return".";let b;for(let g=0;g0&&(b===void 0?b=w:b+=`/${w}`)}return b===void 0?".":n.posix.normalize(b)},relative(l,b){if(s(l,"from"),s(b,"to"),l===b||(l=n.posix.resolve(l),b=n.posix.resolve(b),l===b))return"";const g=1,w=l.length,M=w-g,y=1,_=b.length-y,C=M<_?M:_;let R=-1,D=0;for(;DC){if(b.charCodeAt(y+D)===c)return b.slice(y+D+1);if(D===0)return b.slice(y+D)}else M>C&&(l.charCodeAt(g+D)===c?R=D:D===0&&(R=0));let T="";for(D=g+R+1;D<=w;++D)(D===w||l.charCodeAt(D)===c)&&(T+=T.length===0?"..":"/..");return`${T}${b.slice(y+R)}`},toNamespacedPath(l){return l},dirname(l){if(s(l,"path"),l.length===0)return".";const b=l.charCodeAt(0)===c;let g=-1,w=!0;for(let M=l.length-1;M>=1;--M)if(l.charCodeAt(M)===c){if(!w){g=M;break}}else w=!1;return g===-1?b?"/":".":b&&g===1?"//":l.slice(0,g)},basename(l,b){b!==void 0&&s(b,"ext"),s(l,"path");let g=0,w=-1,M=!0,y;if(b!==void 0&&b.length>0&&b.length<=l.length){if(b===l)return"";let _=b.length-1,C=-1;for(y=l.length-1;y>=0;--y){const R=l.charCodeAt(y);if(R===c){if(!M){g=y+1;break}}else C===-1&&(M=!1,C=y+1),_>=0&&(R===b.charCodeAt(_)?--_===-1&&(w=y):(_=-1,w=C))}return g===w?w=C:w===-1&&(w=l.length),l.slice(g,w)}for(y=l.length-1;y>=0;--y)if(l.charCodeAt(y)===c){if(!M){g=y+1;break}}else w===-1&&(M=!1,w=y+1);return w===-1?"":l.slice(g,w)},extname(l){s(l,"path");let b=-1,g=0,w=-1,M=!0,y=0;for(let _=l.length-1;_>=0;--_){const C=l.charCodeAt(_);if(C===c){if(!M){g=_+1;break}continue}w===-1&&(M=!1,w=_+1),C===p?b===-1?b=_:y!==1&&(y=1):b!==-1&&(y=-1)}return b===-1||w===-1||y===0||y===1&&b===w-1&&b===g+1?"":l.slice(b,w)},format:E.bind(null,"/"),parse(l){s(l,"path");const b={root:"",dir:"",base:"",ext:"",name:""};if(l.length===0)return b;const g=l.charCodeAt(0)===c;let w;g?(b.root="/",w=1):w=0;let M=-1,y=0,_=-1,C=!0,R=l.length-1,D=0;for(;R>=w;--R){const T=l.charCodeAt(R);if(T===c){if(!C){y=R+1;break}continue}_===-1&&(C=!1,_=R+1),T===p?M===-1?M=R:D!==1&&(D=1):M!==-1&&(D=-1)}if(_!==-1){const T=y===0&&g?1:y;M===-1||D===0||D===1&&M===_-1&&M===y+1?b.base=b.name=l.slice(T,_):(b.name=l.slice(T,M),b.base=l.slice(T,_),b.ext=l.slice(M,_))}return y>0?b.dir=l.slice(0,y-1):g&&(b.dir="/"),b},sep:"/",delimiter:":",win32:null,posix:null},n.posix.win32=n.win32.win32=n.win32,n.posix.posix=n.win32.posix=n.posix,n.normalize=o?n.win32.normalize:n.posix.normalize,n.join=o?n.win32.join:n.posix.join,n.resolve=o?n.win32.resolve:n.posix.resolve,n.relative=o?n.win32.relative:n.posix.relative,n.dirname=o?n.win32.dirname:n.posix.dirname,n.basename=o?n.win32.basename:n.posix.basename,n.extname=o?n.win32.extname:n.posix.extname,n.sep=o?n.win32.sep:n.posix.sep}),X(J[14],Z([0,1,37,11]),function(W,n,i,x){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.URI=void 0,n.uriToFsPath=N;const A=/^\w[\w\d+.-]*$/,d=/^\//,f=/^\/\//;function p(b,g){if(!b.scheme&&g)throw new Error(`[UriError]: Scheme is missing: {scheme: "", authority: "${b.authority}", path: "${b.path}", query: "${b.query}", fragment: "${b.fragment}"}`);if(b.scheme&&!A.test(b.scheme))throw new Error("[UriError]: Scheme contains illegal characters.");if(b.path){if(b.authority){if(!d.test(b.path))throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character')}else if(f.test(b.path))throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")')}}function c(b,g){return!b&&!g?"file":b}function a(b,g){switch(b){case"https":case"http":case"file":g?g[0]!==e&&(g=e+g):g=e;break}return g}const m="",e="/",h=/^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;class r{static isUri(g){return g instanceof r?!0:g?typeof g.authority=="string"&&typeof g.fragment=="string"&&typeof g.path=="string"&&typeof g.query=="string"&&typeof g.scheme=="string"&&typeof g.fsPath=="string"&&typeof g.with=="function"&&typeof g.toString=="function":!1}constructor(g,w,M,y,_,C=!1){typeof g=="object"?(this.scheme=g.scheme||m,this.authority=g.authority||m,this.path=g.path||m,this.query=g.query||m,this.fragment=g.fragment||m):(this.scheme=c(g,C),this.authority=w||m,this.path=a(this.scheme,M||m),this.query=y||m,this.fragment=_||m,p(this,C))}get fsPath(){return N(this,!1)}with(g){if(!g)return this;let{scheme:w,authority:M,path:y,query:_,fragment:C}=g;return w===void 0?w=this.scheme:w===null&&(w=m),M===void 0?M=this.authority:M===null&&(M=m),y===void 0?y=this.path:y===null&&(y=m),_===void 0?_=this.query:_===null&&(_=m),C===void 0?C=this.fragment:C===null&&(C=m),w===this.scheme&&M===this.authority&&y===this.path&&_===this.query&&C===this.fragment?this:new o(w,M,y,_,C)}static parse(g,w=!1){const M=h.exec(g);return M?new o(M[2]||m,l(M[4]||m),l(M[5]||m),l(M[7]||m),l(M[9]||m),w):new o(m,m,m,m,m)}static file(g){let w=m;if(x.isWindows&&(g=g.replace(/\\/g,e)),g[0]===e&&g[1]===e){const M=g.indexOf(e,2);M===-1?(w=g.substring(2),g=e):(w=g.substring(2,M),g=g.substring(M)||e)}return new o("file",w,g,m,m)}static from(g,w){return new o(g.scheme,g.authority,g.path,g.query,g.fragment,w)}static joinPath(g,...w){if(!g.path)throw new Error("[UriError]: cannot call joinPath on URI without path");let M;return x.isWindows&&g.scheme==="file"?M=r.file(i.win32.join(N(g,!0),...w)).path:M=i.posix.join(g.path,...w),g.with({path:M})}toString(g=!1){return P(this,g)}toJSON(){return this}static revive(g){if(g){if(g instanceof r)return g;{const w=new o(g);return w._formatted=g.external??null,w._fsPath=g._sep===s?g.fsPath??null:null,w}}else return g}}n.URI=r;const s=x.isWindows?1:void 0;class o extends r{constructor(){super(...arguments),this._formatted=null,this._fsPath=null}get fsPath(){return this._fsPath||(this._fsPath=N(this,!1)),this._fsPath}toString(g=!1){return g?P(this,!0):(this._formatted||(this._formatted=P(this,!1)),this._formatted)}toJSON(){const g={$mid:1};return this._fsPath&&(g.fsPath=this._fsPath,g._sep=s),this._formatted&&(g.external=this._formatted),this.path&&(g.path=this.path),this.scheme&&(g.scheme=this.scheme),this.authority&&(g.authority=this.authority),this.query&&(g.query=this.query),this.fragment&&(g.fragment=this.fragment),g}}const u={58:"%3A",47:"%2F",63:"%3F",35:"%23",91:"%5B",93:"%5D",64:"%40",33:"%21",36:"%24",38:"%26",39:"%27",40:"%28",41:"%29",42:"%2A",43:"%2B",44:"%2C",59:"%3B",61:"%3D",32:"%20"};function S(b,g,w){let M,y=-1;for(let _=0;_=97&&C<=122||C>=65&&C<=90||C>=48&&C<=57||C===45||C===46||C===95||C===126||g&&C===47||w&&C===91||w&&C===93||w&&C===58)y!==-1&&(M+=encodeURIComponent(b.substring(y,_)),y=-1),M!==void 0&&(M+=b.charAt(_));else{M===void 0&&(M=b.substr(0,_));const R=u[C];R!==void 0?(y!==-1&&(M+=encodeURIComponent(b.substring(y,_)),y=-1),M+=R):y===-1&&(y=_)}}return y!==-1&&(M+=encodeURIComponent(b.substring(y))),M!==void 0?M:b}function L(b){let g;for(let w=0;w1&&b.scheme==="file"?w=`//${b.authority}${b.path}`:b.path.charCodeAt(0)===47&&(b.path.charCodeAt(1)>=65&&b.path.charCodeAt(1)<=90||b.path.charCodeAt(1)>=97&&b.path.charCodeAt(1)<=122)&&b.path.charCodeAt(2)===58?g?w=b.path.substr(1):w=b.path[1].toLowerCase()+b.path.substr(2):w=b.path,x.isWindows&&(w=w.replace(/\//g,"\\")),w}function P(b,g){const w=g?L:S;let M="",{scheme:y,authority:_,path:C,query:R,fragment:D}=b;if(y&&(M+=y,M+=":"),(_||y==="file")&&(M+=e,M+=e),_){let T=_.indexOf("@");if(T!==-1){const O=_.substr(0,T);_=_.substr(T+1),T=O.lastIndexOf(":"),T===-1?M+=w(O,!1,!1):(M+=w(O.substr(0,T),!1,!1),M+=":",M+=w(O.substr(T+1),!1,!0)),M+="@"}_=_.toLowerCase(),T=_.lastIndexOf(":"),T===-1?M+=w(_,!1,!0):(M+=w(_.substr(0,T),!1,!0),M+=_.substr(T))}if(C){if(C.length>=3&&C.charCodeAt(0)===47&&C.charCodeAt(2)===58){const T=C.charCodeAt(1);T>=65&&T<=90&&(C=`/${String.fromCharCode(T+32)}:${C.substr(3)}`)}else if(C.length>=2&&C.charCodeAt(1)===58){const T=C.charCodeAt(0);T>=65&&T<=90&&(C=`${String.fromCharCode(T+32)}:${C.substr(2)}`)}M+=w(C,!0,!1)}return R&&(M+="?",M+=w(R,!1,!1)),D&&(M+="#",M+=g?D:S(D,!1,!1)),M}function E(b){try{return decodeURIComponent(b)}catch{return b.length>3?b.substr(0,3)+E(b.substr(3)):b}}const v=/(%[0-9A-Za-z][0-9A-Za-z])+/g;function l(b){return b.match(v)?b.replace(v,g=>E(g)):b}}),X(J[38],Z([0,1,3,11,6,14,37]),function(W,n,i,x,A,d,f){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.COI=n.FileAccess=n.VSCODE_AUTHORITY=n.RemoteAuthorities=n.connectionTokenQueryName=n.Schemas=void 0,n.matchesScheme=c,n.matchesSomeScheme=a;var p;(function(r){r.inMemory="inmemory",r.vscode="vscode",r.internal="private",r.walkThrough="walkThrough",r.walkThroughSnippet="walkThroughSnippet",r.http="http",r.https="https",r.file="file",r.mailto="mailto",r.untitled="untitled",r.data="data",r.command="command",r.vscodeRemote="vscode-remote",r.vscodeRemoteResource="vscode-remote-resource",r.vscodeManagedRemoteResource="vscode-managed-remote-resource",r.vscodeUserData="vscode-userdata",r.vscodeCustomEditor="vscode-custom-editor",r.vscodeNotebookCell="vscode-notebook-cell",r.vscodeNotebookCellMetadata="vscode-notebook-cell-metadata",r.vscodeNotebookCellMetadataDiff="vscode-notebook-cell-metadata-diff",r.vscodeNotebookCellOutput="vscode-notebook-cell-output",r.vscodeNotebookCellOutputDiff="vscode-notebook-cell-output-diff",r.vscodeNotebookMetadata="vscode-notebook-metadata",r.vscodeInteractiveInput="vscode-interactive-input",r.vscodeSettings="vscode-settings",r.vscodeWorkspaceTrust="vscode-workspace-trust",r.vscodeTerminal="vscode-terminal",r.vscodeChatCodeBlock="vscode-chat-code-block",r.vscodeChatCodeCompareBlock="vscode-chat-code-compare-block",r.vscodeChatSesssion="vscode-chat-editor",r.webviewPanel="webview-panel",r.vscodeWebview="vscode-webview",r.extension="extension",r.vscodeFileResource="vscode-file",r.tmp="tmp",r.vsls="vsls",r.vscodeSourceControl="vscode-scm",r.commentsInput="comment",r.codeSetting="code-setting",r.outputChannel="output"})(p||(n.Schemas=p={}));function c(r,s){return d.URI.isUri(r)?(0,A.equalsIgnoreCase)(r.scheme,s):(0,A.startsWithIgnoreCase)(r,s+":")}function a(r,...s){return s.some(o=>c(r,o))}n.connectionTokenQueryName="tkn";class m{constructor(){this._hosts=Object.create(null),this._ports=Object.create(null),this._connectionTokens=Object.create(null),this._preferredWebSchema="http",this._delegate=null,this._serverRootPath="/"}setPreferredWebSchema(s){this._preferredWebSchema=s}get _remoteResourcesPath(){return f.posix.join(this._serverRootPath,p.vscodeRemoteResource)}rewrite(s){if(this._delegate)try{return this._delegate(s)}catch(P){return i.onUnexpectedError(P),s}const o=s.authority;let u=this._hosts[o];u&&u.indexOf(":")!==-1&&u.indexOf("[")===-1&&(u=`[${u}]`);const S=this._ports[o],L=this._connectionTokens[o];let N=`path=${encodeURIComponent(s.path)}`;return typeof L=="string"&&(N+=`&${n.connectionTokenQueryName}=${encodeURIComponent(L)}`),d.URI.from({scheme:x.isWeb?this._preferredWebSchema:p.vscodeRemoteResource,authority:`${u}:${S}`,path:this._remoteResourcesPath,query:N})}}n.RemoteAuthorities=new m,n.VSCODE_AUTHORITY="vscode-app";class e{static{this.FALLBACK_AUTHORITY=n.VSCODE_AUTHORITY}asBrowserUri(s){const o=this.toUri(s,W);return this.uriToBrowserUri(o)}uriToBrowserUri(s){return s.scheme===p.vscodeRemote?n.RemoteAuthorities.rewrite(s):s.scheme===p.file&&(x.isNative||x.webWorkerOrigin===`${p.vscodeFileResource}://${e.FALLBACK_AUTHORITY}`)?s.with({scheme:p.vscodeFileResource,authority:s.authority||e.FALLBACK_AUTHORITY,query:null,fragment:null}):s}toUri(s,o){if(d.URI.isUri(s))return s;if(globalThis._VSCODE_FILE_ROOT){const u=globalThis._VSCODE_FILE_ROOT;if(/^\w[\w\d+.-]*:\/\//.test(u))return d.URI.joinPath(d.URI.parse(u,!0),s);const S=f.join(u,s);return d.URI.file(S)}return d.URI.parse(o.toUrl(s))}}n.FileAccess=new e;var h;(function(r){const s=new Map([["1",{"Cross-Origin-Opener-Policy":"same-origin"}],["2",{"Cross-Origin-Embedder-Policy":"require-corp"}],["3",{"Cross-Origin-Opener-Policy":"same-origin","Cross-Origin-Embedder-Policy":"require-corp"}]]);r.CoopAndCoep=Object.freeze(s.get("3"));const o="vscode-coi";function u(L){let N;typeof L=="string"?N=new URL(L).searchParams:L instanceof URL?N=L.searchParams:d.URI.isUri(L)&&(N=new URL(L.toString(!0)).searchParams);const P=N?.get(o);if(P)return s.get(P)}r.getHeadersFromQuery=u;function S(L,N,P){if(!globalThis.crossOriginIsolated)return;const E=N&&P?"3":P?"2":"1";L instanceof URLSearchParams?L.set(o,E):L[o]=E}r.addSearchParam=S})(h||(n.COI=h={}))}),X(J[76],Z([0,1,3,9,8,38,11,6]),function(W,n,i,x,A,d,f,p){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.SimpleWorkerServer=n.SimpleWorkerClient=void 0,n.logOnceWebWorkerWarning=h,n.create=l;const c=!1,a="default",m="$initialize";let e=!1;function h(b){f.isWeb&&(e||(e=!0,console.warn("Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq")),console.warn(b.message))}class r{constructor(g,w,M,y,_){this.vsWorker=g,this.req=w,this.channel=M,this.method=y,this.args=_,this.type=0}}class s{constructor(g,w,M,y){this.vsWorker=g,this.seq=w,this.res=M,this.err=y,this.type=1}}class o{constructor(g,w,M,y,_){this.vsWorker=g,this.req=w,this.channel=M,this.eventName=y,this.arg=_,this.type=2}}class u{constructor(g,w,M){this.vsWorker=g,this.req=w,this.event=M,this.type=3}}class S{constructor(g,w){this.vsWorker=g,this.req=w,this.type=4}}class L{constructor(g){this._workerId=-1,this._handler=g,this._lastSentReq=0,this._pendingReplies=Object.create(null),this._pendingEmitters=new Map,this._pendingEvents=new Map}setWorkerId(g){this._workerId=g}sendMessage(g,w,M){const y=String(++this._lastSentReq);return new Promise((_,C)=>{this._pendingReplies[y]={resolve:_,reject:C},this._send(new r(this._workerId,y,g,w,M))})}listen(g,w,M){let y=null;const _=new x.Emitter({onWillAddFirstListener:()=>{y=String(++this._lastSentReq),this._pendingEmitters.set(y,_),this._send(new o(this._workerId,y,g,w,M))},onDidRemoveLastListener:()=>{this._pendingEmitters.delete(y),this._send(new S(this._workerId,y)),y=null}});return _.event}handleMessage(g){!g||!g.vsWorker||this._workerId!==-1&&g.vsWorker!==this._workerId||this._handleMessage(g)}createProxyToRemoteChannel(g,w){const M={get:(y,_)=>(typeof _=="string"&&!y[_]&&(E(_)?y[_]=C=>this.listen(g,_,C):P(_)?y[_]=this.listen(g,_,void 0):_.charCodeAt(0)===36&&(y[_]=async(...C)=>(await w?.(),this.sendMessage(g,_,C)))),y[_])};return new Proxy(Object.create(null),M)}_handleMessage(g){switch(g.type){case 1:return this._handleReplyMessage(g);case 0:return this._handleRequestMessage(g);case 2:return this._handleSubscribeEventMessage(g);case 3:return this._handleEventMessage(g);case 4:return this._handleUnsubscribeEventMessage(g)}}_handleReplyMessage(g){if(!this._pendingReplies[g.seq]){console.warn("Got reply to unknown seq");return}const w=this._pendingReplies[g.seq];if(delete this._pendingReplies[g.seq],g.err){let M=g.err;g.err.$isError&&(M=new Error,M.name=g.err.name,M.message=g.err.message,M.stack=g.err.stack),w.reject(M);return}w.resolve(g.res)}_handleRequestMessage(g){const w=g.req;this._handler.handleMessage(g.channel,g.method,g.args).then(y=>{this._send(new s(this._workerId,w,y,void 0))},y=>{y.detail instanceof Error&&(y.detail=(0,i.transformErrorForSerialization)(y.detail)),this._send(new s(this._workerId,w,void 0,(0,i.transformErrorForSerialization)(y)))})}_handleSubscribeEventMessage(g){const w=g.req,M=this._handler.handleEvent(g.channel,g.eventName,g.arg)(y=>{this._send(new u(this._workerId,w,y))});this._pendingEvents.set(w,M)}_handleEventMessage(g){if(!this._pendingEmitters.has(g.req)){console.warn("Got event for unknown req");return}this._pendingEmitters.get(g.req).fire(g.event)}_handleUnsubscribeEventMessage(g){if(!this._pendingEvents.has(g.req)){console.warn("Got unsubscribe for unknown req");return}this._pendingEvents.get(g.req).dispose(),this._pendingEvents.delete(g.req)}_send(g){const w=[];if(g.type===0)for(let M=0;M{this._protocol.handleMessage(_)},_=>{(0,i.onUnexpectedError)(_)})),this._protocol=new L({sendMessage:(_,C)=>{this._worker.postMessage(_,C)},handleMessage:(_,C,R)=>this._handleMessage(_,C,R),handleEvent:(_,C,R)=>this._handleEvent(_,C,R)}),this._protocol.setWorkerId(this._worker.getId());let M=null;const y=globalThis.require;typeof y<"u"&&typeof y.getConfig=="function"?M=y.getConfig():typeof globalThis.requirejs<"u"&&(M=globalThis.requirejs.s.contexts._.config),this._onModuleLoaded=this._protocol.sendMessage(a,m,[this._worker.getId(),JSON.parse(JSON.stringify(M)),w.amdModuleId]),this.proxy=this._protocol.createProxyToRemoteChannel(a,async()=>{await this._onModuleLoaded}),this._onModuleLoaded.catch(_=>{this._onError("Worker failed to load "+w.amdModuleId,_)})}_handleMessage(g,w,M){const y=this._localChannels.get(g);if(!y)return Promise.reject(new Error(`Missing channel ${g} on main thread`));if(typeof y[w]!="function")return Promise.reject(new Error(`Missing method ${w} on main thread channel ${g}`));try{return Promise.resolve(y[w].apply(y,M))}catch(_){return Promise.reject(_)}}_handleEvent(g,w,M){const y=this._localChannels.get(g);if(!y)throw new Error(`Missing channel ${g} on main thread`);if(E(w)){const _=y[w].call(y,M);if(typeof _!="function")throw new Error(`Missing dynamic event ${w} on main thread channel ${g}.`);return _}if(P(w)){const _=y[w];if(typeof _!="function")throw new Error(`Missing event ${w} on main thread channel ${g}.`);return _}throw new Error(`Malformed event name ${w}`)}setChannel(g,w){this._localChannels.set(g,w)}_onError(g,w){console.error(g),console.info(w)}}n.SimpleWorkerClient=N;function P(b){return b[0]==="o"&&b[1]==="n"&&p.isUpperAsciiLetter(b.charCodeAt(2))}function E(b){return/^onDynamic/.test(b)&&p.isUpperAsciiLetter(b.charCodeAt(9))}class v{constructor(g,w){this._localChannels=new Map,this._remoteChannels=new Map,this._requestHandlerFactory=w,this._requestHandler=null,this._protocol=new L({sendMessage:(M,y)=>{g(M,y)},handleMessage:(M,y,_)=>this._handleMessage(M,y,_),handleEvent:(M,y,_)=>this._handleEvent(M,y,_)})}onmessage(g){this._protocol.handleMessage(g)}_handleMessage(g,w,M){if(g===a&&w===m)return this.initialize(M[0],M[1],M[2]);const y=g===a?this._requestHandler:this._localChannels.get(g);if(!y)return Promise.reject(new Error(`Missing channel ${g} on worker thread`));if(typeof y[w]!="function")return Promise.reject(new Error(`Missing method ${w} on worker thread channel ${g}`));try{return Promise.resolve(y[w].apply(y,M))}catch(_){return Promise.reject(_)}}_handleEvent(g,w,M){const y=g===a?this._requestHandler:this._localChannels.get(g);if(!y)throw new Error(`Missing channel ${g} on worker thread`);if(E(w)){const _=y[w].call(y,M);if(typeof _!="function")throw new Error(`Missing dynamic event ${w} on request handler.`);return _}if(P(w)){const _=y[w];if(typeof _!="function")throw new Error(`Missing event ${w} on request handler.`);return _}throw new Error(`Malformed event name ${w}`)}getChannel(g){if(!this._remoteChannels.has(g)){const w=this._protocol.createProxyToRemoteChannel(g);this._remoteChannels.set(g,w)}return this._remoteChannels.get(g)}async initialize(g,w,M){if(this._protocol.setWorkerId(g),this._requestHandlerFactory){this._requestHandler=this._requestHandlerFactory(this);return}if(w&&(typeof w.baseUrl<"u"&&delete w.baseUrl,typeof w.paths<"u"&&typeof w.paths.vs<"u"&&delete w.paths.vs,typeof w.trustedTypesPolicy<"u"&&delete w.trustedTypesPolicy,w.catchError=!0,globalThis.require.config(w)),c){const y=d.FileAccess.asBrowserUri(`${M}.js`).toString(!0);return new Promise((_,C)=>{W([`${y}`],_,C)}).then(_=>{if(this._requestHandler=_.create(this),!this._requestHandler)throw new Error("No RequestHandler!")})}return new Promise((y,_)=>{(globalThis.require||W)([M],R=>{if(this._requestHandler=R.create(this),!this._requestHandler){_(new Error("No RequestHandler!"));return}y()},_)})}}n.SimpleWorkerServer=v;function l(b){return new v(b,null)}}),X(J[73],Z([0,1,47,14,2,70,36]),function(W,n,i,x,A,d,f){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.InlineEditTriggerKind=n.TreeSitterTokenizationRegistry=n.TokenizationRegistry=n.LazyTokenizationSupport=n.InlayHintKind=n.Command=n.NewSymbolNameTriggerKind=n.NewSymbolNameTag=n.FoldingRangeKind=n.TextEdit=n.SymbolKinds=n.symbolKindNames=n.DocumentHighlightKind=n.SignatureHelpTriggerKind=n.DocumentPasteTriggerKind=n.SelectedSuggestionInfo=n.InlineCompletionTriggerKind=n.CompletionItemKinds=n.HoverVerbosityAction=n.EncodedTokenizationResult=n.TokenizationResult=n.Token=void 0,n.isLocationLink=S,n.getAriaLabelForSymbol=L;class p{constructor(_,C,R){this.offset=_,this.type=C,this.language=R,this._tokenBrand=void 0}toString(){return"("+this.offset+", "+this.type+")"}}n.Token=p;class c{constructor(_,C){this.tokens=_,this.endState=C,this._tokenizationResultBrand=void 0}}n.TokenizationResult=c;class a{constructor(_,C){this.tokens=_,this.endState=C,this._encodedTokenizationResultBrand=void 0}}n.EncodedTokenizationResult=a;var m;(function(y){y[y.Increase=0]="Increase",y[y.Decrease=1]="Decrease"})(m||(n.HoverVerbosityAction=m={}));var e;(function(y){const _=new Map;_.set(0,i.Codicon.symbolMethod),_.set(1,i.Codicon.symbolFunction),_.set(2,i.Codicon.symbolConstructor),_.set(3,i.Codicon.symbolField),_.set(4,i.Codicon.symbolVariable),_.set(5,i.Codicon.symbolClass),_.set(6,i.Codicon.symbolStruct),_.set(7,i.Codicon.symbolInterface),_.set(8,i.Codicon.symbolModule),_.set(9,i.Codicon.symbolProperty),_.set(10,i.Codicon.symbolEvent),_.set(11,i.Codicon.symbolOperator),_.set(12,i.Codicon.symbolUnit),_.set(13,i.Codicon.symbolValue),_.set(15,i.Codicon.symbolEnum),_.set(14,i.Codicon.symbolConstant),_.set(15,i.Codicon.symbolEnum),_.set(16,i.Codicon.symbolEnumMember),_.set(17,i.Codicon.symbolKeyword),_.set(27,i.Codicon.symbolSnippet),_.set(18,i.Codicon.symbolText),_.set(19,i.Codicon.symbolColor),_.set(20,i.Codicon.symbolFile),_.set(21,i.Codicon.symbolReference),_.set(22,i.Codicon.symbolCustomColor),_.set(23,i.Codicon.symbolFolder),_.set(24,i.Codicon.symbolTypeParameter),_.set(25,i.Codicon.account),_.set(26,i.Codicon.issues);function C(T){let O=_.get(T);return O||(console.info("No codicon found for CompletionItemKind "+T),O=i.Codicon.symbolProperty),O}y.toIcon=C;const R=new Map;R.set("method",0),R.set("function",1),R.set("constructor",2),R.set("field",3),R.set("variable",4),R.set("class",5),R.set("struct",6),R.set("interface",7),R.set("module",8),R.set("property",9),R.set("event",10),R.set("operator",11),R.set("unit",12),R.set("value",13),R.set("constant",14),R.set("enum",15),R.set("enum-member",16),R.set("enumMember",16),R.set("keyword",17),R.set("snippet",27),R.set("text",18),R.set("color",19),R.set("file",20),R.set("reference",21),R.set("customcolor",22),R.set("folder",23),R.set("type-parameter",24),R.set("typeParameter",24),R.set("account",25),R.set("issue",26);function D(T,O){let z=R.get(T);return typeof z>"u"&&!O&&(z=9),z}y.fromString=D})(e||(n.CompletionItemKinds=e={}));var h;(function(y){y[y.Automatic=0]="Automatic",y[y.Explicit=1]="Explicit"})(h||(n.InlineCompletionTriggerKind=h={}));class r{constructor(_,C,R,D){this.range=_,this.text=C,this.completionKind=R,this.isSnippetText=D}equals(_){return A.Range.lift(this.range).equalsRange(_.range)&&this.text===_.text&&this.completionKind===_.completionKind&&this.isSnippetText===_.isSnippetText}}n.SelectedSuggestionInfo=r;var s;(function(y){y[y.Automatic=0]="Automatic",y[y.PasteAs=1]="PasteAs"})(s||(n.DocumentPasteTriggerKind=s={}));var o;(function(y){y[y.Invoke=1]="Invoke",y[y.TriggerCharacter=2]="TriggerCharacter",y[y.ContentChange=3]="ContentChange"})(o||(n.SignatureHelpTriggerKind=o={}));var u;(function(y){y[y.Text=0]="Text",y[y.Read=1]="Read",y[y.Write=2]="Write"})(u||(n.DocumentHighlightKind=u={}));function S(y){return y&&x.URI.isUri(y.uri)&&A.Range.isIRange(y.range)&&(A.Range.isIRange(y.originSelectionRange)||A.Range.isIRange(y.targetSelectionRange))}n.symbolKindNames={17:(0,f.localize)(669,"array"),16:(0,f.localize)(670,"boolean"),4:(0,f.localize)(671,"class"),13:(0,f.localize)(672,"constant"),8:(0,f.localize)(673,"constructor"),9:(0,f.localize)(674,"enumeration"),21:(0,f.localize)(675,"enumeration member"),23:(0,f.localize)(676,"event"),7:(0,f.localize)(677,"field"),0:(0,f.localize)(678,"file"),11:(0,f.localize)(679,"function"),10:(0,f.localize)(680,"interface"),19:(0,f.localize)(681,"key"),5:(0,f.localize)(682,"method"),1:(0,f.localize)(683,"module"),2:(0,f.localize)(684,"namespace"),20:(0,f.localize)(685,"null"),15:(0,f.localize)(686,"number"),18:(0,f.localize)(687,"object"),24:(0,f.localize)(688,"operator"),3:(0,f.localize)(689,"package"),6:(0,f.localize)(690,"property"),14:(0,f.localize)(691,"string"),22:(0,f.localize)(692,"struct"),25:(0,f.localize)(693,"type parameter"),12:(0,f.localize)(694,"variable")};function L(y,_){return(0,f.localize)(695,"{0} ({1})",y,n.symbolKindNames[_])}var N;(function(y){const _=new Map;_.set(0,i.Codicon.symbolFile),_.set(1,i.Codicon.symbolModule),_.set(2,i.Codicon.symbolNamespace),_.set(3,i.Codicon.symbolPackage),_.set(4,i.Codicon.symbolClass),_.set(5,i.Codicon.symbolMethod),_.set(6,i.Codicon.symbolProperty),_.set(7,i.Codicon.symbolField),_.set(8,i.Codicon.symbolConstructor),_.set(9,i.Codicon.symbolEnum),_.set(10,i.Codicon.symbolInterface),_.set(11,i.Codicon.symbolFunction),_.set(12,i.Codicon.symbolVariable),_.set(13,i.Codicon.symbolConstant),_.set(14,i.Codicon.symbolString),_.set(15,i.Codicon.symbolNumber),_.set(16,i.Codicon.symbolBoolean),_.set(17,i.Codicon.symbolArray),_.set(18,i.Codicon.symbolObject),_.set(19,i.Codicon.symbolKey),_.set(20,i.Codicon.symbolNull),_.set(21,i.Codicon.symbolEnumMember),_.set(22,i.Codicon.symbolStruct),_.set(23,i.Codicon.symbolEvent),_.set(24,i.Codicon.symbolOperator),_.set(25,i.Codicon.symbolTypeParameter);function C(R){let D=_.get(R);return D||(console.info("No codicon found for SymbolKind "+R),D=i.Codicon.symbolProperty),D}y.toIcon=C})(N||(n.SymbolKinds=N={}));class P{}n.TextEdit=P;class E{static{this.Comment=new E("comment")}static{this.Imports=new E("imports")}static{this.Region=new E("region")}static fromValue(_){switch(_){case"comment":return E.Comment;case"imports":return E.Imports;case"region":return E.Region}return new E(_)}constructor(_){this.value=_}}n.FoldingRangeKind=E;var v;(function(y){y[y.AIGenerated=1]="AIGenerated"})(v||(n.NewSymbolNameTag=v={}));var l;(function(y){y[y.Invoke=0]="Invoke",y[y.Automatic=1]="Automatic"})(l||(n.NewSymbolNameTriggerKind=l={}));var b;(function(y){function _(C){return!C||typeof C!="object"?!1:typeof C.id=="string"&&typeof C.title=="string"}y.is=_})(b||(n.Command=b={}));var g;(function(y){y[y.Type=1]="Type",y[y.Parameter=2]="Parameter"})(g||(n.InlayHintKind=g={}));class w{constructor(_){this.createSupport=_,this._tokenizationSupport=null}dispose(){this._tokenizationSupport&&this._tokenizationSupport.then(_=>{_&&_.dispose()})}get tokenizationSupport(){return this._tokenizationSupport||(this._tokenizationSupport=this.createSupport()),this._tokenizationSupport}}n.LazyTokenizationSupport=w,n.TokenizationRegistry=new d.TokenizationRegistry,n.TreeSitterTokenizationRegistry=new d.TokenizationRegistry;var M;(function(y){y[y.Invoke=0]="Invoke",y[y.Automatic=1]="Automatic"})(M||(n.InlineEditTriggerKind=M={}))}),X(J[74],Z([0,1,23,9,42,14,4,2,48,73,69]),function(W,n,i,x,A,d,f,p,c,a,m){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.KeyMod=void 0,n.createMonacoBaseAPI=h;class e{static{this.CtrlCmd=2048}static{this.Shift=1024}static{this.Alt=512}static{this.WinCtrl=256}static chord(s,o){return(0,A.KeyChord)(s,o)}}n.KeyMod=e;function h(){return{editor:void 0,languages:void 0,CancellationTokenSource:i.CancellationTokenSource,Emitter:x.Emitter,KeyCode:m.KeyCode,KeyMod:e,Position:f.Position,Range:p.Range,Selection:c.Selection,SelectionDirection:m.SelectionDirection,MarkerSeverity:m.MarkerSeverity,MarkerTag:m.MarkerTag,Uri:d.URI,Token:a.Token}}}),X(J[75],Z([0,1,71,8,14,4,2,31,64]),function(W,n,i,x,A,d,f,p,c){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.MirrorModel=n.WorkerTextModelSyncServer=n.WorkerTextModelSyncClient=n.STOP_SYNC_MODEL_DELTA_TIME_MS=void 0,n.STOP_SYNC_MODEL_DELTA_TIME_MS=60*1e3;class a extends x.Disposable{constructor(r,s,o=!1){if(super(),this._syncedModels=Object.create(null),this._syncedModelsLastUsedTime=Object.create(null),this._proxy=r,this._modelService=s,!o){const u=new i.IntervalTimer;u.cancelAndSet(()=>this._checkStopModelSync(),Math.round(n.STOP_SYNC_MODEL_DELTA_TIME_MS/2)),this._register(u)}}dispose(){for(const r in this._syncedModels)(0,x.dispose)(this._syncedModels[r]);this._syncedModels=Object.create(null),this._syncedModelsLastUsedTime=Object.create(null),super.dispose()}ensureSyncedResources(r,s=!1){for(const o of r){const u=o.toString();this._syncedModels[u]||this._beginModelSync(o,s),this._syncedModels[u]&&(this._syncedModelsLastUsedTime[u]=new Date().getTime())}}_checkStopModelSync(){const r=new Date().getTime(),s=[];for(const o in this._syncedModelsLastUsedTime)r-this._syncedModelsLastUsedTime[o]>n.STOP_SYNC_MODEL_DELTA_TIME_MS&&s.push(o);for(const o of s)this._stopModelSync(o)}_beginModelSync(r,s){const o=this._modelService.getModel(r);if(!o||!s&&o.isTooLargeForSyncing())return;const u=r.toString();this._proxy.$acceptNewModel({url:o.uri.toString(),lines:o.getLinesContent(),EOL:o.getEOL(),versionId:o.getVersionId()});const S=new x.DisposableStore;S.add(o.onDidChangeContent(L=>{this._proxy.$acceptModelChanged(u.toString(),L)})),S.add(o.onWillDispose(()=>{this._stopModelSync(u)})),S.add((0,x.toDisposable)(()=>{this._proxy.$acceptRemovedModel(u)})),this._syncedModels[u]=S}_stopModelSync(r){const s=this._syncedModels[r];delete this._syncedModels[r],delete this._syncedModelsLastUsedTime[r],(0,x.dispose)(s)}}n.WorkerTextModelSyncClient=a;class m{constructor(){this._models=Object.create(null)}getModel(r){return this._models[r]}getModels(){const r=[];return Object.keys(this._models).forEach(s=>r.push(this._models[s])),r}$acceptNewModel(r){this._models[r.url]=new e(A.URI.parse(r.url),r.lines,r.EOL,r.versionId)}$acceptModelChanged(r,s){if(!this._models[r])return;this._models[r].onEvents(s)}$acceptRemovedModel(r){this._models[r]&&delete this._models[r]}}n.WorkerTextModelSyncServer=m;class e extends c.MirrorTextModel{get uri(){return this._uri}get eol(){return this._eol}getValue(){return this.getText()}findMatches(r){const s=[];for(let o=0;othis._lines.length)s=this._lines.length,o=this._lines[s-1].length+1,u=!0;else{const S=this._lines[s-1].length+1;o<1?(o=1,u=!0):o>S&&(o=S,u=!0)}return u?{lineNumber:s,column:o}:r}}n.MirrorModel=e}),X(J[77],Z([0,1,24,2,60,61,74,66,22,68,58,27,38,59,67,75]),function(W,n,i,x,A,d,f,p,c,a,m,e,h,r,s,o){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.EditorSimpleWorker=n.BaseEditorSimpleWorker=void 0,n.create=N;const u=!1;class S{constructor(){this._workerTextModelSyncServer=new o.WorkerTextModelSyncServer}dispose(){}_getModel(E){return this._workerTextModelSyncServer.getModel(E)}_getModels(){return this._workerTextModelSyncServer.getModels()}$acceptNewModel(E){this._workerTextModelSyncServer.$acceptNewModel(E)}$acceptModelChanged(E,v){this._workerTextModelSyncServer.$acceptModelChanged(E,v)}$acceptRemovedModel(E){this._workerTextModelSyncServer.$acceptRemovedModel(E)}async $computeUnicodeHighlights(E,v,l){const b=this._getModel(E);return b?a.UnicodeTextModelHighlighter.computeUnicodeHighlights(b,v,l):{ranges:[],hasMore:!1,ambiguousCharacterCount:0,invisibleCharacterCount:0,nonBasicAsciiCharacterCount:0}}async $findSectionHeaders(E,v){const l=this._getModel(E);return l?(0,s.findSectionHeaders)(l,v):[]}async $computeDiff(E,v,l,b){const g=this._getModel(E),w=this._getModel(v);return!g||!w?null:L.computeDiff(g,w,l,b)}static computeDiff(E,v,l,b){const g=b==="advanced"?m.linesDiffComputers.getDefault():m.linesDiffComputers.getLegacy(),w=E.getLinesContent(),M=v.getLinesContent(),y=g.computeDiff(w,M,l),_=y.changes.length>0?!1:this._modelsAreIdentical(E,v);function C(R){return R.map(D=>[D.original.startLineNumber,D.original.endLineNumberExclusive,D.modified.startLineNumber,D.modified.endLineNumberExclusive,D.innerChanges?.map(T=>[T.originalRange.startLineNumber,T.originalRange.startColumn,T.originalRange.endLineNumber,T.originalRange.endColumn,T.modifiedRange.startLineNumber,T.modifiedRange.startColumn,T.modifiedRange.endLineNumber,T.modifiedRange.endColumn])])}return{identical:_,quitEarly:y.hitTimeout,changes:C(y.changes),moves:y.moves.map(R=>[R.lineRangeMapping.original.startLineNumber,R.lineRangeMapping.original.endLineNumberExclusive,R.lineRangeMapping.modified.startLineNumber,R.lineRangeMapping.modified.endLineNumberExclusive,C(R.changes)])}}static _modelsAreIdentical(E,v){const l=E.getLineCount(),b=v.getLineCount();if(l!==b)return!1;for(let g=1;g<=l;g++){const w=E.getLineContent(g),M=v.getLineContent(g);if(w!==M)return!1}return!0}static{this._diffLimit=1e5}async $computeMoreMinimalEdits(E,v,l){const b=this._getModel(E);if(!b)return v;const g=[];let w;v=v.slice(0).sort((y,_)=>{if(y.range&&_.range)return x.Range.compareRangesUsingStarts(y.range,_.range);const C=y.range?0:1,R=_.range?0:1;return C-R});let M=0;for(let y=1;yL._diffLimit){g.push({range:y,text:_});continue}const D=(0,i.stringDiff)(R,_,l),T=b.offsetAt(x.Range.lift(y).getStartPosition());for(const O of D){const z=b.positionAt(T+O.originalStart),j=b.positionAt(T+O.originalStart+O.originalLength),F={text:_.substr(O.modifiedStart,O.modifiedLength),range:{startLineNumber:z.lineNumber,startColumn:z.column,endLineNumber:j.lineNumber,endColumn:j.column}};b.getValueInRange(F.range)!==F.text&&g.push(F)}}return typeof w=="number"&&g.push({eol:w,text:"",range:{startLineNumber:0,startColumn:0,endLineNumber:0,endColumn:0}}),g}async $computeLinks(E){const v=this._getModel(E);return v?(0,A.computeLinks)(v):null}async $computeDefaultDocumentColors(E){const v=this._getModel(E);return v?(0,r.computeDefaultDocumentColors)(v):null}static{this._suggestionsLimit=1e4}async $textualSuggest(E,v,l,b){const g=new c.StopWatch,w=new RegExp(l,b),M=new Set;e:for(const y of E){const _=this._getModel(y);if(_){for(const C of _.words(w))if(!(C===v||!isNaN(Number(C)))&&(M.add(C),M.size>L._suggestionsLimit))break e}}return{words:Array.from(M),duration:g.elapsed()}}async $computeWordRanges(E,v,l,b){const g=this._getModel(E);if(!g)return Object.create(null);const w=new RegExp(l,b),M=Object.create(null);for(let y=v.startLineNumber;ythis._host.$fhr(M,y),w={host:(0,e.createProxyObject)(l,b),getMirrorModels:()=>this._getModels()};return this._foreignModuleFactory?(this._foreignModule=this._foreignModuleFactory(w,v),Promise.resolve((0,e.getAllMethodNames)(this._foreignModule))):new Promise((M,y)=>{const _=C=>{this._foreignModule=C.create(w,v),M((0,e.getAllMethodNames)(this._foreignModule))};if(!u)W([`${E}`],_,y);else{const C=h.FileAccess.asBrowserUri(`${E}.js`).toString(!0);new Promise((R,D)=>{W([`${C}`],R,D)}).then(_).catch(y)}})}$fmr(E,v){if(!this._foreignModule||typeof this._foreignModule[E]!="function")return Promise.reject(new Error("Missing requestHandler or method: "+E));try{return Promise.resolve(this._foreignModule[E].apply(this._foreignModule,v))}catch(l){return Promise.reject(l)}}}n.EditorSimpleWorker=L;function N(P){return new L(p.EditorWorkerHost.getChannel(P),null)}typeof importScripts=="function"&&(globalThis.monaco=(0,f.createMonacoBaseAPI)())})}).call(this); //# sourceMappingURL=../../../../min-maps/vs/base/worker/workerMain.js.map ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/abap/abap.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/abap/abap", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var i in e)s(t,i,{get:e[i],enumerable:!0})},d=(t,e,i,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of r(e))!c.call(t,n)&&n!==i&&s(t,n,{get:()=>e[n],enumerable:!(a=o(e,n))||a.enumerable});return t};var p=t=>d(s({},"__esModule",{value:!0}),t);var g={};l(g,{conf:()=>m,language:()=>u});var m={comments:{lineComment:"*"},brackets:[["[","]"],["(",")"]]},u={defaultToken:"invalid",ignoreCase:!0,tokenPostfix:".abap",keywords:["abap-source","abbreviated","abstract","accept","accepting","according","activation","actual","add","add-corresponding","adjacent","after","alias","aliases","align","all","allocate","alpha","analysis","analyzer","and","append","appendage","appending","application","archive","area","arithmetic","as","ascending","aspect","assert","assign","assigned","assigning","association","asynchronous","at","attributes","authority","authority-check","avg","back","background","backup","backward","badi","base","before","begin","between","big","binary","bintohex","bit","black","blank","blanks","blob","block","blocks","blue","bound","boundaries","bounds","boxed","break-point","buffer","by","bypassing","byte","byte-order","call","calling","case","cast","casting","catch","center","centered","chain","chain-input","chain-request","change","changing","channels","character","char-to-hex","check","checkbox","ci_","circular","class","class-coding","class-data","class-events","class-methods","class-pool","cleanup","clear","client","clob","clock","close","coalesce","code","coding","col_background","col_group","col_heading","col_key","col_negative","col_normal","col_positive","col_total","collect","color","column","columns","comment","comments","commit","common","communication","comparing","component","components","compression","compute","concat","concat_with_space","concatenate","cond","condense","condition","connect","connection","constants","context","contexts","continue","control","controls","conv","conversion","convert","copies","copy","corresponding","country","cover","cpi","create","creating","critical","currency","currency_conversion","current","cursor","cursor-selection","customer","customer-function","dangerous","data","database","datainfo","dataset","date","dats_add_days","dats_add_months","dats_days_between","dats_is_valid","daylight","dd/mm/yy","dd/mm/yyyy","ddmmyy","deallocate","decimal_shift","decimals","declarations","deep","default","deferred","define","defining","definition","delete","deleting","demand","department","descending","describe","destination","detail","dialog","directory","disconnect","display","display-mode","distinct","divide","divide-corresponding","division","do","dummy","duplicate","duplicates","duration","during","dynamic","dynpro","edit","editor-call","else","elseif","empty","enabled","enabling","encoding","end","endat","endcase","endcatch","endchain","endclass","enddo","endenhancement","end-enhancement-section","endexec","endform","endfunction","endian","endif","ending","endinterface","end-lines","endloop","endmethod","endmodule","end-of-definition","end-of-editing","end-of-file","end-of-page","end-of-selection","endon","endprovide","endselect","end-test-injection","end-test-seam","endtry","endwhile","endwith","engineering","enhancement","enhancement-point","enhancements","enhancement-section","entries","entry","enum","environment","equiv","errormessage","errors","escaping","event","events","exact","except","exception","exceptions","exception-table","exclude","excluding","exec","execute","exists","exit","exit-command","expand","expanding","expiration","explicit","exponent","export","exporting","extend","extended","extension","extract","fail","fetch","field","field-groups","fields","field-symbol","field-symbols","file","filter","filters","filter-table","final","find","first","first-line","fixed-point","fkeq","fkge","flush","font","for","form","format","forward","found","frame","frames","free","friends","from","function","functionality","function-pool","further","gaps","generate","get","giving","gkeq","gkge","global","grant","green","group","groups","handle","handler","harmless","hashed","having","hdb","header","headers","heading","head-lines","help-id","help-request","hextobin","hide","high","hint","hold","hotspot","icon","id","identification","identifier","ids","if","ignore","ignoring","immediately","implementation","implementations","implemented","implicit","import","importing","in","inactive","incl","include","includes","including","increment","index","index-line","infotypes","inheriting","init","initial","initialization","inner","inout","input","insert","instance","instances","instr","intensified","interface","interface-pool","interfaces","internal","intervals","into","inverse","inverted-date","is","iso","job","join","keep","keeping","kernel","key","keys","keywords","kind","language","last","late","layout","leading","leave","left","left-justified","leftplus","leftspace","legacy","length","let","level","levels","like","line","lines","line-count","linefeed","line-selection","line-size","list","listbox","list-processing","little","llang","load","load-of-program","lob","local","locale","locator","logfile","logical","log-point","long","loop","low","lower","lpad","lpi","ltrim","mail","main","major-id","mapping","margin","mark","mask","match","matchcode","max","maximum","medium","members","memory","mesh","message","message-id","messages","messaging","method","methods","min","minimum","minor-id","mm/dd/yy","mm/dd/yyyy","mmddyy","mode","modif","modifier","modify","module","move","move-corresponding","multiply","multiply-corresponding","name","nametab","native","nested","nesting","new","new-line","new-page","new-section","next","no","no-display","no-extension","no-gap","no-gaps","no-grouping","no-heading","no-scrolling","no-sign","no-title","no-topofpage","no-zero","node","nodes","non-unicode","non-unique","not","null","number","object","objects","obligatory","occurrence","occurrences","occurs","of","off","offset","ole","on","only","open","option","optional","options","or","order","other","others","out","outer","output","output-length","overflow","overlay","pack","package","pad","padding","page","pages","parameter","parameters","parameter-table","part","partially","pattern","percentage","perform","performing","person","pf1","pf10","pf11","pf12","pf13","pf14","pf15","pf2","pf3","pf4","pf5","pf6","pf7","pf8","pf9","pf-status","pink","places","pool","pos_high","pos_low","position","pragmas","precompiled","preferred","preserving","primary","print","print-control","priority","private","procedure","process","program","property","protected","provide","public","push","pushbutton","put","queue-only","quickinfo","radiobutton","raise","raising","range","ranges","read","reader","read-only","receive","received","receiver","receiving","red","redefinition","reduce","reduced","ref","reference","refresh","regex","reject","remote","renaming","replace","replacement","replacing","report","request","requested","reserve","reset","resolution","respecting","responsible","result","results","resumable","resume","retry","return","returncode","returning","returns","right","right-justified","rightplus","rightspace","risk","rmc_communication_failure","rmc_invalid_status","rmc_system_failure","role","rollback","rows","rpad","rtrim","run","sap","sap-spool","saving","scale_preserving","scale_preserving_scientific","scan","scientific","scientific_with_leading_zero","scroll","scroll-boundary","scrolling","search","secondary","seconds","section","select","selection","selections","selection-screen","selection-set","selection-sets","selection-table","select-options","send","separate","separated","set","shared","shift","short","shortdump-id","sign_as_postfix","single","size","skip","skipping","smart","some","sort","sortable","sorted","source","specified","split","spool","spots","sql","sqlscript","stable","stamp","standard","starting","start-of-editing","start-of-selection","state","statement","statements","static","statics","statusinfo","step-loop","stop","structure","structures","style","subkey","submatches","submit","subroutine","subscreen","subtract","subtract-corresponding","suffix","sum","summary","summing","supplied","supply","suppress","switch","switchstates","symbol","syncpoints","syntax","syntax-check","syntax-trace","system-call","system-exceptions","system-exit","tab","tabbed","table","tables","tableview","tabstrip","target","task","tasks","test","testing","test-injection","test-seam","text","textpool","then","throw","time","times","timestamp","timezone","tims_is_valid","title","titlebar","title-lines","to","tokenization","tokens","top-lines","top-of-page","trace-file","trace-table","trailing","transaction","transfer","transformation","translate","transporting","trmac","truncate","truncation","try","tstmp_add_seconds","tstmp_current_utctimestamp","tstmp_is_valid","tstmp_seconds_between","type","type-pool","type-pools","types","uline","unassign","under","unicode","union","unique","unit_conversion","unix","unpack","until","unwind","up","update","upper","user","user-command","using","utf-8","valid","value","value-request","values","vary","varying","verification-message","version","via","view","visible","wait","warning","when","whenever","where","while","width","window","windows","with","with-heading","without","with-title","word","work","write","writer","xml","xsd","yellow","yes","yymmdd","zero","zone","abap_system_timezone","abap_user_timezone","access","action","adabas","adjust_numbers","allow_precision_loss","allowed","amdp","applicationuser","as_geo_json","as400","associations","balance","behavior","breakup","bulk","cds","cds_client","check_before_save","child","clients","corr","corr_spearman","cross","cycles","datn_add_days","datn_add_months","datn_days_between","dats_from_datn","dats_tims_to_tstmp","dats_to_datn","db2","db6","ddl","dense_rank","depth","deterministic","discarding","entities","entity","error","failed","finalize","first_value","fltp_to_dec","following","fractional","full","graph","grouping","hierarchy","hierarchy_ancestors","hierarchy_ancestors_aggregate","hierarchy_descendants","hierarchy_descendants_aggregate","hierarchy_siblings","incremental","indicators","lag","last_value","lead","leaves","like_regexpr","link","locale_sap","lock","locks","many","mapped","matched","measures","median","mssqlnt","multiple","nodetype","ntile","nulls","occurrences_regexpr","one","operations","oracle","orphans","over","parent","parents","partition","pcre","period","pfcg_mapping","preceding","privileged","product","projection","rank","redirected","replace_regexpr","reported","response","responses","root","row","row_number","sap_system_date","save","schema","session","sets","shortdump","siblings","spantree","start","stddev","string_agg","subtotal","sybase","tims_from_timn","tims_to_timn","to_blob","to_clob","total","trace-entry","tstmp_to_dats","tstmp_to_dst","tstmp_to_tims","tstmpl_from_utcl","tstmpl_to_utcl","unbounded","utcl_add_seconds","utcl_current","utcl_seconds_between","uuid","var","verbatim"],builtinFunctions:["abs","acos","asin","atan","bit-set","boolc","boolx","ceil","char_off","charlen","cmax","cmin","concat_lines_of","contains","contains_any_not_of","contains_any_of","cos","cosh","count","count_any_not_of","count_any_of","dbmaxlen","distance","escape","exp","find_any_not_of","find_any_of","find_end","floor","frac","from_mixed","ipow","line_exists","line_index","log","log10","matches","nmax","nmin","numofchar","repeat","rescale","reverse","round","segment","shift_left","shift_right","sign","sin","sinh","sqrt","strlen","substring","substring_after","substring_before","substring_from","substring_to","tan","tanh","to_lower","to_mixed","to_upper","trunc","utclong_add","utclong_current","utclong_diff","xsdbool","xstrlen"],typeKeywords:["b","c","d","decfloat16","decfloat34","f","i","int8","n","p","s","string","t","utclong","x","xstring","any","clike","csequence","decfloat","numeric","simple","xsequence","accp","char","clnt","cuky","curr","datn","dats","d16d","d16n","d16r","d34d","d34n","d34r","dec","df16_dec","df16_raw","df34_dec","df34_raw","fltp","geom_ewkb","int1","int2","int4","lang","lchr","lraw","numc","quan","raw","rawstring","sstring","timn","tims","unit","utcl","df16_scl","df34_scl","prec","varc","abap_bool","abap_false","abap_true","abap_undefined","me","screen","space","super","sy","syst","table_line","*sys*"],builtinMethods:["class_constructor","constructor"],derivedTypes:["%CID","%CID_REF","%CONTROL","%DATA","%ELEMENT","%FAIL","%KEY","%MSG","%PARAM","%PID","%PID_ASSOC","%PID_PARENT","%_HINTS"],cdsLanguage:["@AbapAnnotation","@AbapCatalog","@AccessControl","@API","@ClientDependent","@ClientHandling","@CompatibilityContract","@DataAging","@EndUserText","@Environment","@LanguageDependency","@MappingRole","@Metadata","@MetadataExtension","@ObjectModel","@Scope","@Semantics","$EXTENSION","$SELF"],selectors:["->","->*","=>","~","~*"],operators:[" +"," -","/","*","**","div","mod","=","#","@","+=","-=","*=","/=","**=","&&=","?=","&","&&","bit-and","bit-not","bit-or","bit-xor","m","o","z","<"," >","<=",">=","<>","><","=<","=>","bt","byte-ca","byte-cn","byte-co","byte-cs","byte-na","byte-ns","ca","cn","co","cp","cs","eq","ge","gt","le","lt","na","nb","ne","np","ns","*/","*:","--","/*","//"],symbols:/[=>))*/,{cases:{"@typeKeywords":"type","@keywords":"keyword","@cdsLanguage":"annotation","@derivedTypes":"type","@builtinFunctions":"type","@builtinMethods":"type","@operators":"key","@default":"identifier"}}],[/<[\w]+>/,"identifier"],[/##[\w|_]+/,"comment"],{include:"@whitespace"},[/[:,.]/,"delimiter"],[/[{}()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@selectors":"tag","@operators":"key","@default":""}}],[/'/,{token:"string",bracket:"@open",next:"@stringquote"}],[/`/,{token:"string",bracket:"@open",next:"@stringping"}],[/\|/,{token:"string",bracket:"@open",next:"@stringtemplate"}],[/\d+/,"number"]],stringtemplate:[[/[^\\\|]+/,"string"],[/\\\|/,"string"],[/\|/,{token:"string",bracket:"@close",next:"@pop"}]],stringping:[[/[^\\`]+/,"string"],[/`/,{token:"string",bracket:"@close",next:"@pop"}]],stringquote:[[/[^\\']+/,"string"],[/'/,{token:"string",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/^\*.*$/,"comment"],[/\".*$/,"comment"]]}};return p(g);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/apex/apex.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/apex/apex", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var i=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var d=(e,t)=>{for(var s in t)i(e,s,{get:t[s],enumerable:!0})},g=(e,t,s,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of c(t))!l.call(e,o)&&o!==s&&i(e,o,{get:()=>t[o],enumerable:!(a=r(t,o))||a.enumerable});return e};var p=e=>g(i({},"__esModule",{value:!0}),e);var h={};d(h,{conf:()=>m,language:()=>b});var m={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}],folding:{markers:{start:new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:))")}}},u=["abstract","activate","and","any","array","as","asc","assert","autonomous","begin","bigdecimal","blob","boolean","break","bulk","by","case","cast","catch","char","class","collect","commit","const","continue","convertcurrency","decimal","default","delete","desc","do","double","else","end","enum","exception","exit","export","extends","false","final","finally","float","for","from","future","get","global","goto","group","having","hint","if","implements","import","in","inner","insert","instanceof","int","interface","into","join","last_90_days","last_month","last_n_days","last_week","like","limit","list","long","loop","map","merge","native","new","next_90_days","next_month","next_n_days","next_week","not","null","nulls","number","object","of","on","or","outer","override","package","parallel","pragma","private","protected","public","retrieve","return","returning","rollback","savepoint","search","select","set","short","sort","stat","static","strictfp","super","switch","synchronized","system","testmethod","then","this","this_month","this_week","throw","throws","today","tolabel","tomorrow","transaction","transient","trigger","true","try","type","undelete","update","upsert","using","virtual","void","volatile","webservice","when","where","while","yesterday"],f=e=>e.charAt(0).toUpperCase()+e.substr(1),n=[];u.forEach(e=>{n.push(e),n.push(e.toUpperCase()),n.push(f(e))});var b={defaultToken:"",tokenPostfix:".apex",keywords:n,operators:["=",">","<","!","~","?",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>",">>>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>=",">>>="],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,"annotation"],[/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)[fFdD]/,"number.float"],[/(@digits)[lL]?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string",'@string."'],[/'/,"string","@string.'"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@apexdoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],apexdoc:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}};return p(h);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/azcli/azcli.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/azcli/azcli", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(t,e)=>{for(var o in e)s(t,o,{get:e[o],enumerable:!0})},k=(t,e,o,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of r(e))!l.call(t,n)&&n!==o&&s(t,n,{get:()=>e[n],enumerable:!(a=i(e,n))||a.enumerable});return t};var p=t=>k(s({},"__esModule",{value:!0}),t);var d={};c(d,{conf:()=>f,language:()=>g});var f={comments:{lineComment:"#"}},g={defaultToken:"keyword",ignoreCase:!0,tokenPostfix:".azcli",str:/[^#\s]/,tokenizer:{root:[{include:"@comment"},[/\s-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":{token:"key.identifier",next:"@type"}}}],[/^-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":{token:"key.identifier",next:"@type"}}}]],type:[{include:"@comment"},[/-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":"key.identifier"}}],[/@str+\s*/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}]],comment:[[/#.*$/,{cases:{"@eos":{token:"comment",next:"@popall"}}}]]}};return p(d);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/bat/bat.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/bat/bat", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var n=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var g=(o,e)=>{for(var t in e)n(o,t,{get:e[t],enumerable:!0})},c=(o,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of l(e))!i.call(o,s)&&s!==t&&n(o,s,{get:()=>e[s],enumerable:!(a=r(e,s))||a.enumerable});return o};var p=o=>c(n({},"__esModule",{value:!0}),o);var k={};g(k,{conf:()=>d,language:()=>m});var d={comments:{lineComment:"REM"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],folding:{markers:{start:new RegExp("^\\s*(::\\s*|REM\\s+)#region"),end:new RegExp("^\\s*(::\\s*|REM\\s+)#endregion")}}},m={defaultToken:"",ignoreCase:!0,tokenPostfix:".bat",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"}],keywords:/call|defined|echo|errorlevel|exist|for|goto|if|pause|set|shift|start|title|not|pushd|popd/,symbols:/[=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var g=(e,n)=>{for(var o in n)r(e,o,{get:n[o],enumerable:!0})},l=(e,n,o,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of c(n))!a.call(e,t)&&t!==o&&r(e,t,{get:()=>n[t],enumerable:!(i=s(n,t))||i.enumerable});return e};var m=e=>l(r({},"__esModule",{value:!0}),e);var y={};g(y,{conf:()=>$,language:()=>w});var p=e=>`\\b${e}\\b`,k="[_a-zA-Z]",x="[_a-zA-Z0-9]",u=p(`${k}${x}*`),d=["targetScope","resource","module","param","var","output","for","in","if","existing"],b=["true","false","null"],f="[ \\t\\r\\n]",C="[0-9]+",$={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'"},{open:"'''",close:"'''"}],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'",notIn:["string","comment"]},{open:"'''",close:"'''",notIn:["string","comment"]}],autoCloseBefore:`:.,=}])' `,indentationRules:{increaseIndentPattern:new RegExp("^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$"),decreaseIndentPattern:new RegExp("^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$")}},w={defaultToken:"",tokenPostfix:".bicep",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"}],symbols:/[=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(o,e)=>{for(var n in e)s(o,n,{get:e[n],enumerable:!0})},m=(o,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of a(e))!l.call(o,t)&&t!==n&&s(o,t,{get:()=>e[t],enumerable:!(r=i(e,t))||r.enumerable});return o};var p=o=>m(s({},"__esModule",{value:!0}),o);var u={};c(u,{conf:()=>d,language:()=>g});var d={comments:{lineComment:"//",blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'},{open:"(*",close:"*)"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'},{open:"(*",close:"*)"}]},g={defaultToken:"",tokenPostfix:".cameligo",ignoreCase:!0,brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],keywords:["abs","assert","block","Bytes","case","Crypto","Current","else","failwith","false","for","fun","if","in","let","let%entry","let%init","List","list","Map","map","match","match%nat","mod","not","operation","Operation","of","record","Set","set","sender","skip","source","String","then","to","true","type","with"],typeKeywords:["int","unit","string","tz","nat","bool"],operators:["=",">","<","<=",">=","<>",":",":=","and","mod","or","+","-","*","/","@","&","^","%","->","<-","&&","||"],symbols:/[=><:@\^&|+\-*\/\^%]+/,tokenizer:{root:[[/[a-zA-Z_][\w]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/\$[0-9a-fA-F]{1,16}/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'/,"string","@string"],[/'[^\\']'/,"string"],[/'/,"string.invalid"],[/\#\d+/,"string"]],comment:[[/[^\(\*]+/,"comment"],[/\*\)/,"comment","@pop"],[/\(\*/,"comment"]],string:[[/[^\\']+/,"string"],[/\\./,"string.escape.invalid"],[/'/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,"white"],[/\(\*/,"comment","@comment"],[/\/\/.*$/,"comment"]]}};return p(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/clojure/clojure.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/clojure/clojure", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var a=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var d=(t,e)=>{for(var r in e)a(t,r,{get:e[r],enumerable:!0})},l=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of i(e))!c.call(t,n)&&n!==r&&a(t,n,{get:()=>e[n],enumerable:!(s=o(e,n))||s.enumerable});return t};var p=t=>l(a({},"__esModule",{value:!0}),t);var h={};d(h,{conf:()=>u,language:()=>m});var u={comments:{lineComment:";;"},brackets:[["[","]"],["(",")"],["{","}"]],autoClosingPairs:[{open:"[",close:"]"},{open:'"',close:'"'},{open:"(",close:")"},{open:"{",close:"}"}],surroundingPairs:[{open:"[",close:"]"},{open:'"',close:'"'},{open:"(",close:")"},{open:"{",close:"}"}]},m={defaultToken:"",ignoreCase:!0,tokenPostfix:".clj",brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"}],constants:["true","false","nil"],numbers:/^(?:[+\-]?\d+(?:(?:N|(?:[eE][+\-]?\d+))|(?:\.?\d*(?:M|(?:[eE][+\-]?\d+))?)|\/\d+|[xX][0-9a-fA-F]+|r[0-9a-zA-Z]+)?(?=[\\\[\]\s"#'(),;@^`{}~]|$))/,characters:/^(?:\\(?:backspace|formfeed|newline|return|space|tab|o[0-7]{3}|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{4}|.)?(?=[\\\[\]\s"(),;@^`{}~]|$))/,escapes:/^\\(?:["'\\bfnrt]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,qualifiedSymbols:/^(?:(?:[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*(?:\.[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*)*\/)?(?:\/|[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*)*(?=[\\\[\]\s"(),;@^`{}~]|$))/,specialForms:[".","catch","def","do","if","monitor-enter","monitor-exit","new","quote","recur","set!","throw","try","var"],coreSymbols:["*","*'","*1","*2","*3","*agent*","*allow-unresolved-vars*","*assert*","*clojure-version*","*command-line-args*","*compile-files*","*compile-path*","*compiler-options*","*data-readers*","*default-data-reader-fn*","*e","*err*","*file*","*flush-on-newline*","*fn-loader*","*in*","*math-context*","*ns*","*out*","*print-dup*","*print-length*","*print-level*","*print-meta*","*print-namespace-maps*","*print-readably*","*read-eval*","*reader-resolver*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","+","+'","-","-'","->","->>","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","..","/","<","<=","=","==",">",">=","EMPTY-NODE","Inst","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","any?","apply","areduce","array-map","as->","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assert","assoc","assoc!","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","binding","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case","cast","cat","char","char-array","char-escape-string","char-name-string","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","coll?","comment","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","cond","cond->","cond->>","condp","conj","conj!","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","declare","dedupe","default-data-readers","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype","delay","delay?","deliver","denominator","deref","derive","descendants","destructure","disj","disj!","dissoc","dissoc!","distinct","distinct?","doall","dorun","doseq","dosync","dotimes","doto","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-data","ex-info","extend","extend-protocol","extend-type","extenders","extends?","false?","ffirst","file-seq","filter","filterv","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn","fn?","fnext","fnil","for","force","format","frequencies","future","future-call","future-cancel","future-cancelled?","future-done?","future?","gen-class","gen-interface","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","io!","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","lazy-cat","lazy-seq","let","letfn","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","locking","long","long-array","longs","loop","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memfn","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","or","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop","pop!","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","primitives-classnames","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy","proxy-call-with-super","proxy-mappings","proxy-name","proxy-super","push-thread-bindings","pvalues","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","refer-clojure","reify","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-watch","repeat","repeatedly","replace","replicate","require","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some->","some->>","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","test","the-ns","thread-bound?","time","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unquote","unquote-splicing","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","vswap!","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn","xml-seq","zero?","zipmap"],tokenizer:{root:[{include:"@whitespace"},[/@numbers/,"number"],[/@characters/,"string"],{include:"@string"},[/[()\[\]{}]/,"@brackets"],[/\/#"(?:\.|(?:")|[^"\n])*"\/g/,"regexp"],[/[#'@^`~]/,"meta"],[/@qualifiedSymbols/,{cases:{"^:.+$":"constant","@specialForms":"keyword","@coreSymbols":"keyword","@constants":"constant","@default":"identifier"}}]],whitespace:[[/[\s,]+/,"white"],[/;.*$/,"comment"],[/\(comment\b/,"comment","@comment"]],comment:[[/\(/,"comment","@push"],[/\)/,"comment","@pop"],[/[^()]/,"comment"]],string:[[/"/,"string","@multiLineString"]],multiLineString:[[/"/,"string","@popall"],[/@escapes/,"string.escape"],[/./,"string"]]}};return p(h);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/coffee/coffee.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/coffee/coffee", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var l=(n,e)=>{for(var t in e)s(n,t,{get:e[t],enumerable:!0})},p=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of g(e))!a.call(n,r)&&r!==t&&s(n,r,{get:()=>e[r],enumerable:!(o=i(e,r))||o.enumerable});return n};var c=n=>p(s({},"__esModule",{value:!0}),n);var m={};l(m,{conf:()=>d,language:()=>x});var d={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\#%\^\&\*\(\)\=\$\-\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{blockComment:["###","###"],lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*#region\\b"),end:new RegExp("^\\s*#endregion\\b")}}},x={defaultToken:"",ignoreCase:!0,tokenPostfix:".coffee",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"}],regEx:/\/(?!\/\/)(?:[^\/\\]|\\.)*\/[igm]*/,keywords:["and","or","is","isnt","not","on","yes","@","no","off","true","false","null","this","new","delete","typeof","in","instanceof","return","throw","break","continue","debugger","if","else","switch","for","while","do","try","catch","finally","class","extends","super","undefined","then","unless","until","loop","of","by","when"],symbols:/[=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var c=(n,e)=>{for(var i in e)o(n,i,{get:e[i],enumerable:!0})},l=(n,e,i,_)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of a(e))!s.call(n,t)&&t!==i&&o(n,t,{get:()=>e[t],enumerable:!(_=r(e,t))||_.enumerable});return n};var d=n=>l(o({},"__esModule",{value:!0}),n);var u={};c(u,{conf:()=>p,language:()=>m});var p={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"[",close:"]"},{open:"{",close:"}"},{open:"(",close:")"},{open:"'",close:"'",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*#pragma\\s+region\\b"),end:new RegExp("^\\s*#pragma\\s+endregion\\b")}}},m={defaultToken:"",tokenPostfix:".cpp",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"},{token:"delimiter.angle",open:"<",close:">"}],keywords:["abstract","amp","array","auto","bool","break","case","catch","char","class","const","constexpr","const_cast","continue","cpu","decltype","default","delegate","delete","do","double","dynamic_cast","each","else","enum","event","explicit","export","extern","false","final","finally","float","for","friend","gcnew","generic","goto","if","in","initonly","inline","int","interface","interior_ptr","internal","literal","long","mutable","namespace","new","noexcept","nullptr","__nullptr","operator","override","partial","pascal","pin_ptr","private","property","protected","public","ref","register","reinterpret_cast","restrict","return","safe_cast","sealed","short","signed","sizeof","static","static_assert","static_cast","struct","switch","template","this","thread_local","throw","tile_static","true","try","typedef","typeid","typename","union","unsigned","using","virtual","void","volatile","wchar_t","where","while","_asm","_based","_cdecl","_declspec","_fastcall","_if_exists","_if_not_exists","_inline","_multiple_inheritance","_pascal","_single_inheritance","_stdcall","_virtual_inheritance","_w64","__abstract","__alignof","__asm","__assume","__based","__box","__builtin_alignof","__cdecl","__clrcall","__declspec","__delegate","__event","__except","__fastcall","__finally","__forceinline","__gc","__hook","__identifier","__if_exists","__if_not_exists","__inline","__int128","__int16","__int32","__int64","__int8","__interface","__leave","__m128","__m128d","__m128i","__m256","__m256d","__m256i","__m512","__m512d","__m512i","__m64","__multiple_inheritance","__newslot","__nogc","__noop","__nounwind","__novtordisp","__pascal","__pin","__pragma","__property","__ptr32","__ptr64","__raise","__restrict","__resume","__sealed","__single_inheritance","__stdcall","__super","__thiscall","__try","__try_cast","__typeof","__unaligned","__unhook","__uuidof","__value","__virtual_inheritance","__w64","__wchar_t"],operators:["=",">","<","!","~","?",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>="],symbols:/[=>\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/,"number.float"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/,"number.hex"],[/0[0-7']*[0-7](@integersuffix)/,"number.octal"],[/0[bB][0-1']*[0-1](@integersuffix)/,"number.binary"],[/\d[\d']*\d(@integersuffix)/,"number"],[/\d(@integersuffix)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@doccomment"],[/\/\*/,"comment","@comment"],[/\/\/.*\\$/,"comment","@linecomment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],linecomment:[[/.*[^\\]$/,"comment","@pop"],[/[^]+/,"comment"]],doccomment:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],raw:[[/[^)]+/,"string.raw"],[/\)$S2\"/,{token:"string.raw.end",next:"@pop"}],[/\)/,"string.raw"]],annotation:[{include:"@whitespace"},[/using|alignas/,"keyword"],[/[a-zA-Z0-9_]+/,"annotation"],[/[,:]/,"delimiter"],[/[()]/,"@brackets"],[/\]\s*\]/,{token:"annotation",next:"@pop"}]],include:[[/(\s*)(<)([^<>]*)(>)/,["","keyword.directive.include.begin","string.include.identifier",{token:"keyword.directive.include.end",next:"@pop"}]],[/(\s*)(")([^"]*)(")/,["","keyword.directive.include.begin","string.include.identifier",{token:"keyword.directive.include.end",next:"@pop"}]]]}};return d(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/csharp/csharp.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/csharp/csharp", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var o in e)s(t,o,{get:e[o],enumerable:!0})},p=(t,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of a(e))!c.call(t,n)&&n!==o&&s(t,n,{get:()=>e[n],enumerable:!(i=r(e,n))||i.enumerable});return t};var g=t=>p(s({},"__esModule",{value:!0}),t);var u={};l(u,{conf:()=>d,language:()=>m});var d={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\$\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],folding:{markers:{start:new RegExp("^\\s*#region\\b"),end:new RegExp("^\\s*#endregion\\b")}}},m={defaultToken:"",tokenPostfix:".cs",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],keywords:["extern","alias","using","bool","decimal","sbyte","byte","short","ushort","int","uint","long","ulong","char","float","double","object","dynamic","string","assembly","is","as","ref","out","this","base","new","typeof","void","checked","unchecked","default","delegate","var","const","if","else","switch","case","while","do","for","foreach","in","break","continue","goto","return","throw","try","catch","finally","lock","yield","from","let","where","join","on","equals","into","orderby","ascending","descending","select","group","by","namespace","partial","class","field","event","method","param","public","protected","internal","private","abstract","sealed","static","struct","readonly","volatile","virtual","override","params","get","set","add","remove","operator","true","false","implicit","explicit","interface","enum","null","async","await","fixed","sizeof","stackalloc","unsafe","nameof","when"],namespaceFollows:["namespace","using"],parenFollows:["if","for","while","switch","foreach","using","catch","when"],operators:["=","??","||","&&","|","^","&","==","!=","<=",">=","<<","+","-","*","/","%","!","~","++","--","+=","-=","*=","/=","%=","&=","|=","^=","<<=",">>=",">>","=>"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/[0-9_]*\.[0-9_]+([eE][\-+]?\d+)?[fFdD]?/,"number.float"],[/0[xX][0-9a-fA-F_]+/,"number.hex"],[/0[bB][01_]+/,"number.hex"],[/[0-9_]+/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,{token:"string.quote",next:"@string"}],[/\$\@"/,{token:"string.quote",next:"@litinterpstring"}],[/\@"/,{token:"string.quote",next:"@litstring"}],[/\$"/,{token:"string.quote",next:"@interpolatedstring"}],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],qualified:[[/[a-zA-Z_][\w]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],[/\./,"delimiter"],["","","@pop"]],namespace:[{include:"@whitespace"},[/[A-Z]\w*/,"namespace"],[/[\.=]/,"delimiter"],["","","@pop"]],comment:[[/[^\/*]+/,"comment"],["\\*/","comment","@pop"],[/[\/*]/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",next:"@pop"}]],litstring:[[/[^"]+/,"string"],[/""/,"string.escape"],[/"/,{token:"string.quote",next:"@pop"}]],litinterpstring:[[/[^"{]+/,"string"],[/""/,"string.escape"],[/{{/,"string.escape"],[/}}/,"string.escape"],[/{/,{token:"string.quote",next:"root.litinterpstring"}],[/"/,{token:"string.quote",next:"@pop"}]],interpolatedstring:[[/[^\\"{]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/{{/,"string.escape"],[/}}/,"string.escape"],[/{/,{token:"string.quote",next:"root.interpolatedstring"}],[/"/,{token:"string.quote",next:"@pop"}]],whitespace:[[/^[ \t\v\f]*#((r)|(load))(?=\s)/,"directive.csx"],[/^[ \t\v\f]*#\w.*$/,"namespace.cpp"],[/[ \t\v\f\r\n]+/,""],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]]}};return g(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/csp/csp.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/csp/csp", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var a=(r,t)=>{for(var s in t)o(r,s,{get:t[s],enumerable:!0})},c=(r,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of u(t))!g.call(r,e)&&e!==s&&o(r,e,{get:()=>t[e],enumerable:!(n=i(t,e))||n.enumerable});return r};var q=r=>c(o({},"__esModule",{value:!0}),r);var p={};a(p,{conf:()=>f,language:()=>l});var f={brackets:[],autoClosingPairs:[],surroundingPairs:[]},l={keywords:[],typeKeywords:[],tokenPostfix:".csp",operators:[],symbols:/[=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var m=(t,e)=>{for(var o in e)r(t,o,{get:e[o],enumerable:!0})},c=(t,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of s(e))!l.call(t,n)&&n!==o&&r(t,n,{get:()=>e[n],enumerable:!(i=a(e,n))||i.enumerable});return t};var d=t=>c(r({},"__esModule",{value:!0}),t);var k={};m(k,{conf:()=>u,language:()=>p});var u={wordPattern:/(#?-?\d*\.\d\w*%?)|((::|[@#.!:])?[\w-?]+%?)|::|[@#.!:]/g,comments:{blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]},{open:"'",close:"'",notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/"),end:new RegExp("^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/")}}},p={defaultToken:"",tokenPostfix:".css",ws:`[ \r\f]*`,identifier:"-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*",brackets:[{open:"{",close:"}",token:"delimiter.bracket"},{open:"[",close:"]",token:"delimiter.bracket"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],tokenizer:{root:[{include:"@selector"}],selector:[{include:"@comments"},{include:"@import"},{include:"@strings"},["[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)",{token:"keyword",next:"@keyframedeclaration"}],["[@](page|content|font-face|-moz-document)",{token:"keyword"}],["[@](charset|namespace)",{token:"keyword",next:"@declarationbody"}],["(url-prefix)(\\()",["attribute.value",{token:"delimiter.parenthesis",next:"@urldeclaration"}]],["(url)(\\()",["attribute.value",{token:"delimiter.parenthesis",next:"@urldeclaration"}]],{include:"@selectorname"},["[\\*]","tag"],["[>\\+,]","delimiter"],["\\[",{token:"delimiter.bracket",next:"@selectorattribute"}],["{",{token:"delimiter.bracket",next:"@selectorbody"}]],selectorbody:[{include:"@comments"},["[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))","attribute.name","@rulevalue"],["}",{token:"delimiter.bracket",next:"@pop"}]],selectorname:[["(\\.|#(?=[^{])|%|(@identifier)|:)+","tag"]],selectorattribute:[{include:"@term"},["]",{token:"delimiter.bracket",next:"@pop"}]],term:[{include:"@comments"},["(url-prefix)(\\()",["attribute.value",{token:"delimiter.parenthesis",next:"@urldeclaration"}]],["(url)(\\()",["attribute.value",{token:"delimiter.parenthesis",next:"@urldeclaration"}]],{include:"@functioninvocation"},{include:"@numbers"},{include:"@name"},{include:"@strings"},["([<>=\\+\\-\\*\\/\\^\\|\\~,])","delimiter"],[",","delimiter"]],rulevalue:[{include:"@comments"},{include:"@strings"},{include:"@term"},["!important","keyword"],[";","delimiter","@pop"],["(?=})",{token:"",next:"@pop"}]],warndebug:[["[@](warn|debug)",{token:"keyword",next:"@declarationbody"}]],import:[["[@](import)",{token:"keyword",next:"@declarationbody"}]],urldeclaration:[{include:"@strings"},[`[^)\r ]+`,"string"],["\\)",{token:"delimiter.parenthesis",next:"@pop"}]],parenthizedterm:[{include:"@term"},["\\)",{token:"delimiter.parenthesis",next:"@pop"}]],declarationbody:[{include:"@term"},[";","delimiter","@pop"],["(?=})",{token:"",next:"@pop"}]],comments:[["\\/\\*","comment","@comment"],["\\/\\/+.*","comment"]],comment:[["\\*\\/","comment","@pop"],[/[^*/]+/,"comment"],[/./,"comment"]],name:[["@identifier","attribute.value"]],numbers:[["-?(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?",{token:"attribute.value.number",next:"@units"}],["#[0-9a-fA-F_]+(?!\\w)","attribute.value.hex"]],units:[["(em|ex|ch|rem|fr|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?","attribute.value.unit","@pop"]],keyframedeclaration:[["@identifier","attribute.value"],["{",{token:"delimiter.bracket",switchTo:"@keyframebody"}]],keyframebody:[{include:"@term"},["{",{token:"delimiter.bracket",next:"@selectorbody"}],["}",{token:"delimiter.bracket",next:"@pop"}]],functioninvocation:[["@identifier\\(",{token:"attribute.value",next:"@functionarguments"}]],functionarguments:[["\\$@identifier@ws:","attribute.name"],["[,]","delimiter"],{include:"@term"},["\\)",{token:"attribute.value",next:"@pop"}]],strings:[['~?"',{token:"string",next:"@stringenddoublequote"}],["~?'",{token:"string",next:"@stringendquote"}]],stringenddoublequote:[["\\\\.","string"],['"',{token:"string",next:"@pop"}],[/[^\\"]+/,"string"],[".","string"]],stringendquote:[["\\\\.","string"],["'",{token:"string",next:"@pop"}],[/[^\\']+/,"string"],[".","string"]]}};return d(k);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/cypher/cypher.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/cypher/cypher", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(i,e)=>{for(var n in e)s(i,n,{get:e[n],enumerable:!0})},g=(i,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of a(e))!l.call(i,t)&&t!==n&&s(i,t,{get:()=>e[t],enumerable:!(o=r(e,t))||o.enumerable});return i};var p=i=>g(s({},"__esModule",{value:!0}),i);var u={};c(u,{conf:()=>d,language:()=>m});var d={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}]},m={defaultToken:"",tokenPostfix:".cypher",ignoreCase:!0,brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.bracket"},{open:"(",close:")",token:"delimiter.parenthesis"}],keywords:["ALL","AND","AS","ASC","ASCENDING","BY","CALL","CASE","CONTAINS","CREATE","DELETE","DESC","DESCENDING","DETACH","DISTINCT","ELSE","END","ENDS","EXISTS","IN","IS","LIMIT","MANDATORY","MATCH","MERGE","NOT","ON","ON","OPTIONAL","OR","ORDER","REMOVE","RETURN","SET","SKIP","STARTS","THEN","UNION","UNWIND","WHEN","WHERE","WITH","XOR","YIELD"],builtinLiterals:["true","TRUE","false","FALSE","null","NULL"],builtinFunctions:["abs","acos","asin","atan","atan2","avg","ceil","coalesce","collect","cos","cot","count","degrees","e","endNode","exists","exp","floor","head","id","keys","labels","last","left","length","log","log10","lTrim","max","min","nodes","percentileCont","percentileDisc","pi","properties","radians","rand","range","relationships","replace","reverse","right","round","rTrim","sign","sin","size","split","sqrt","startNode","stDev","stDevP","substring","sum","tail","tan","timestamp","toBoolean","toFloat","toInteger","toLower","toString","toUpper","trim","type"],operators:["+","-","*","/","%","^","=","<>","<",">","<=",">=","->","<-","-->","<--"],escapes:/\\(?:[tbnrf\\"'`]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,digits:/\d+/,octaldigits:/[0-7]+/,hexdigits:/[0-9a-fA-F]+/,tokenizer:{root:[[/[{}[\]()]/,"@brackets"],{include:"common"}],common:[{include:"@whitespace"},{include:"@numbers"},{include:"@strings"},[/:[a-zA-Z_][\w]*/,"type.identifier"],[/[a-zA-Z_][\w]*(?=\()/,{cases:{"@builtinFunctions":"predefined.function"}}],[/[a-zA-Z_$][\w$]*/,{cases:{"@keywords":"keyword","@builtinLiterals":"predefined.literal","@default":"identifier"}}],[/`/,"identifier.escape","@identifierBacktick"],[/[;,.:|]/,"delimiter"],[/[<>=%+\-*/^]+/,{cases:{"@operators":"delimiter","@default":""}}]],numbers:[[/-?(@digits)[eE](-?(@digits))?/,"number.float"],[/-?(@digits)?\.(@digits)([eE]-?(@digits))?/,"number.float"],[/-?0x(@hexdigits)/,"number.hex"],[/-?0(@octaldigits)/,"number.octal"],[/-?(@digits)/,"number"]],strings:[[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string","@stringDouble"],[/'/,"string","@stringSingle"]],whitespace:[[/[ \t\r\n]+/,"white"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/\/\/.*/,"comment"],[/[^/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[/*]/,"comment"]],stringDouble:[[/[^\\"]+/,"string"],[/@escapes/,"string"],[/\\./,"string.invalid"],[/"/,"string","@pop"]],stringSingle:[[/[^\\']+/,"string"],[/@escapes/,"string"],[/\\./,"string.invalid"],[/'/,"string","@pop"]],identifierBacktick:[[/[^\\`]+/,"identifier.escape"],[/@escapes/,"identifier.escape"],[/\\./,"identifier.escape.invalid"],[/`/,"identifier.escape","@pop"]]}};return p(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/dart/dart.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/dart/dart", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var p=(n,e)=>{for(var t in e)r(n,t,{get:e[t],enumerable:!0})},g=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of c(e))!a.call(n,o)&&o!==t&&r(n,o,{get:()=>e[o],enumerable:!(s=i(e,o))||s.enumerable});return n};var l=n=>g(r({},"__esModule",{value:!0}),n);var x={};p(x,{conf:()=>d,language:()=>m});var d={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string"]},{open:"`",close:"`",notIn:["string","comment"]},{open:"/**",close:" */",notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"},{open:"(",close:")"},{open:'"',close:'"'},{open:"`",close:"`"}],folding:{markers:{start:/^\s*\s*#?region\b/,end:/^\s*\s*#?endregion\b/}}},m={defaultToken:"invalid",tokenPostfix:".dart",keywords:["abstract","dynamic","implements","show","as","else","import","static","assert","enum","in","super","async","export","interface","switch","await","extends","is","sync","break","external","library","this","case","factory","mixin","throw","catch","false","new","true","class","final","null","try","const","finally","on","typedef","continue","for","operator","var","covariant","Function","part","void","default","get","rethrow","while","deferred","hide","return","with","do","if","set","yield"],typeKeywords:["int","double","String","bool"],operators:["+","-","*","/","~/","%","++","--","==","!=",">","<",">=","<=","=","-=","/=","%=",">>=","^=","+=","*=","~/=","<<=","&=","!=","||","&&","&","|","^","~","<<",">>","!",">>>","??","?",":","|="],symbols:/[=>](?!@symbols)/,"@brackets"],[/!(?=([^=]|$))/,"delimiter"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/(@digits)[eE]([\-+]?(@digits))?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/,"number.float"],[/0[xX](@hexdigits)n?/,"number.hex"],[/0[oO]?(@octaldigits)n?/,"number.octal"],[/0[bB](@binarydigits)n?/,"number.binary"],[/(@digits)n?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string_double"],[/'/,"string","@string_single"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@jsdoc"],[/\/\*/,"comment","@comment"],[/\/\/\/.*$/,"comment.doc"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],jsdoc:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],regexp:[[/(\{)(\d+(?:,\d*)?)(\})/,["regexp.escape.control","regexp.escape.control","regexp.escape.control"]],[/(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/,["regexp.escape.control",{token:"regexp.escape.control",next:"@regexrange"}]],[/(\()(\?:|\?=|\?!)/,["regexp.escape.control","regexp.escape.control"]],[/[()]/,"regexp.escape.control"],[/@regexpctl/,"regexp.escape.control"],[/[^\\\/]/,"regexp"],[/@regexpesc/,"regexp.escape"],[/\\\./,"regexp.invalid"],[/(\/)([gimsuy]*)/,[{token:"regexp",bracket:"@close",next:"@pop"},"keyword.other"]]],regexrange:[[/-/,"regexp.escape.control"],[/\^/,"regexp.invalid"],[/@regexpesc/,"regexp.escape"],[/[^\]]/,"regexp"],[/\]/,{token:"regexp.escape.control",next:"@pop",bracket:"@close"}]],string_double:[[/[^\\"\$]+/,"string"],[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"],[/\$\w+/,"identifier"]],string_single:[[/[^\\'\$]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/'/,"string","@pop"],[/\$\w+/,"identifier"]]}};return l(x);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/dockerfile/dockerfile.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/dockerfile/dockerfile", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var a=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var p=(o,e)=>{for(var s in e)a(o,s,{get:e[s],enumerable:!0})},g=(o,e,s,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of r(e))!i.call(o,n)&&n!==s&&a(o,n,{get:()=>e[n],enumerable:!(t=l(e,n))||t.enumerable});return o};var c=o=>g(a({},"__esModule",{value:!0}),o);var k={};p(k,{conf:()=>u,language:()=>d});var u={brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},d={defaultToken:"",tokenPostfix:".dockerfile",variable:/\${?[\w]+}?/,tokenizer:{root:[{include:"@whitespace"},{include:"@comment"},[/(ONBUILD)(\s+)/,["keyword",""]],[/(ENV)(\s+)([\w]+)/,["keyword","",{token:"variable",next:"@arguments"}]],[/(FROM|MAINTAINER|RUN|EXPOSE|ENV|ADD|ARG|VOLUME|LABEL|USER|WORKDIR|COPY|CMD|STOPSIGNAL|SHELL|HEALTHCHECK|ENTRYPOINT)/,{token:"keyword",next:"@arguments"}]],arguments:[{include:"@whitespace"},{include:"@strings"},[/(@variable)/,{cases:{"@eos":{token:"variable",next:"@popall"},"@default":"variable"}}],[/\\/,{cases:{"@eos":"","@default":""}}],[/./,{cases:{"@eos":{token:"",next:"@popall"},"@default":""}}]],whitespace:[[/\s+/,{cases:{"@eos":{token:"",next:"@popall"},"@default":""}}]],comment:[[/(^#.*$)/,"comment","@popall"]],strings:[[/\\'$/,"","@popall"],[/\\'/,""],[/'$/,"string","@popall"],[/'/,"string","@stringBody"],[/"$/,"string","@popall"],[/"/,"string","@dblStringBody"]],stringBody:[[/[^\\\$']/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}],[/\\./,"string.escape"],[/'$/,"string","@popall"],[/'/,"string","@pop"],[/(@variable)/,"variable"],[/\\$/,"string"],[/$/,"string","@popall"]],dblStringBody:[[/[^\\\$"]/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}],[/\\./,"string.escape"],[/"$/,"string","@popall"],[/"/,"string","@pop"],[/(@variable)/,"variable"],[/\\$/,"string"],[/$/,"string","@popall"]]}};return c(k);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/ecl/ecl.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/ecl/ecl", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(o,e)=>{for(var t in e)r(o,t,{get:e[t],enumerable:!0})},d=(o,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of s(e))!l.call(o,n)&&n!==t&&r(o,n,{get:()=>e[n],enumerable:!(a=i(e,n))||a.enumerable});return o};var p=o=>d(r({},"__esModule",{value:!0}),o);var g={};c(g,{conf:()=>m,language:()=>u});var m={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}]},u={defaultToken:"",tokenPostfix:".ecl",ignoreCase:!0,brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],pounds:["append","break","declare","demangle","end","for","getdatatype","if","inmodule","loop","mangle","onwarning","option","set","stored","uniquename"].join("|"),keywords:["__compressed__","after","all","and","any","as","atmost","before","beginc","best","between","case","cluster","compressed","compression","const","counter","csv","default","descend","embed","encoding","encrypt","end","endc","endembed","endmacro","enum","escape","except","exclusive","expire","export","extend","fail","few","fileposition","first","flat","forward","from","full","function","functionmacro","group","grouped","heading","hole","ifblock","import","in","inner","interface","internal","joined","keep","keyed","last","left","limit","linkcounted","literal","little_endian","load","local","locale","lookup","lzw","macro","many","maxcount","maxlength","min skew","module","mofn","multiple","named","namespace","nocase","noroot","noscan","nosort","not","noxpath","of","onfail","only","opt","or","outer","overwrite","packed","partition","penalty","physicallength","pipe","prefetch","quote","record","repeat","retry","return","right","right1","right2","rows","rowset","scan","scope","self","separator","service","shared","skew","skip","smart","soapaction","sql","stable","store","terminator","thor","threshold","timelimit","timeout","token","transform","trim","type","unicodeorder","unordered","unsorted","unstable","update","use","validate","virtual","whole","width","wild","within","wnotrim","xml","xpath"],functions:["abs","acos","aggregate","allnodes","apply","ascii","asin","assert","asstring","atan","atan2","ave","build","buildindex","case","catch","choose","choosen","choosesets","clustersize","combine","correlation","cos","cosh","count","covariance","cron","dataset","dedup","define","denormalize","dictionary","distribute","distributed","distribution","ebcdic","enth","error","evaluate","event","eventextra","eventname","exists","exp","fail","failcode","failmessage","fetch","fromunicode","fromxml","getenv","getisvalid","global","graph","group","hash","hash32","hash64","hashcrc","hashmd5","having","httpcall","httpheader","if","iff","index","intformat","isvalid","iterate","join","keydiff","keypatch","keyunicode","length","library","limit","ln","loadxml","local","log","loop","map","matched","matchlength","matchposition","matchtext","matchunicode","max","merge","mergejoin","min","nofold","nolocal","nonempty","normalize","nothor","notify","output","parallel","parse","pipe","power","preload","process","project","pull","random","range","rank","ranked","realformat","recordof","regexfind","regexreplace","regroup","rejected","rollup","round","roundup","row","rowdiff","sample","sequential","set","sin","sinh","sizeof","soapcall","sort","sorted","sqrt","stepped","stored","sum","table","tan","tanh","thisnode","topn","tounicode","toxml","transfer","transform","trim","truncate","typeof","ungroup","unicodeorder","variance","wait","which","workunit","xmldecode","xmlencode","xmltext","xmlunicode"],typesint:["integer","unsigned"].join("|"),typesnum:["data","qstring","string","unicode","utf8","varstring","varunicode"],typesone:["ascii","big_endian","boolean","data","decimal","ebcdic","grouped","integer","linkcounted","pattern","qstring","real","record","rule","set of","streamed","string","token","udecimal","unicode","unsigned","utf8","varstring","varunicode"].join("|"),operators:["+","-","/",":=","<","<>","=",">","\\","and","in","not","or"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/[0-9_]*\.[0-9_]+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F_]+/,"number.hex"],[/0[bB][01]+/,"number.hex"],[/[0-9_]+/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\v\f\r\n]+/,""],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],string:[[/[^\\']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/'/,"string","@pop"]]}};return p(g);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/elixir/elixir.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/elixir/elixir", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var d=(t,e)=>{for(var i in e)o(t,i,{get:e[i],enumerable:!0})},c=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of s(e))!a.call(t,n)&&n!==i&&o(t,n,{get:()=>e[n],enumerable:!(r=l(e,n))||r.enumerable});return t};var m=t=>c(o({},"__esModule",{value:!0}),t);var p={};d(p,{conf:()=>u,language:()=>g});var u={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'"},{open:'"',close:'"'}],autoClosingPairs:[{open:"'",close:"'",notIn:["string","comment"]},{open:'"',close:'"',notIn:["comment"]},{open:'"""',close:'"""'},{open:"`",close:"`",notIn:["string","comment"]},{open:"(",close:")"},{open:"{",close:"}"},{open:"[",close:"]"},{open:"<<",close:">>"}],indentationRules:{increaseIndentPattern:/^\s*(after|else|catch|rescue|fn|[^#]*(do|<\-|\->|\{|\[|\=))\s*$/,decreaseIndentPattern:/^\s*((\}|\])\s*$|(after|else|catch|rescue|end)\b)/}},g={defaultToken:"source",tokenPostfix:".elixir",brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"<<",close:">>",token:"delimiter.angle.special"}],declarationKeywords:["def","defp","defn","defnp","defguard","defguardp","defmacro","defmacrop","defdelegate","defcallback","defmacrocallback","defmodule","defprotocol","defexception","defimpl","defstruct"],operatorKeywords:["and","in","not","or","when"],namespaceKeywords:["alias","import","require","use"],otherKeywords:["after","case","catch","cond","do","else","end","fn","for","if","quote","raise","receive","rescue","super","throw","try","unless","unquote_splicing","unquote","with"],constants:["true","false","nil"],nameBuiltin:["__MODULE__","__DIR__","__ENV__","__CALLER__","__STACKTRACE__"],operator:/-[->]?|!={0,2}|\*{1,2}|\/|\\\\|&{1,3}|\.\.?|\^(?:\^\^)?|\+\+?|<(?:-|<<|=|>|\|>|~>?)?|=~|={1,3}|>(?:=|>>)?|\|~>|\|>|\|{1,3}|~>>?|~~~|::/,variableName:/[a-z_][a-zA-Z0-9_]*[?!]?/,atomName:/[a-zA-Z_][a-zA-Z0-9_@]*[?!]?|@specialAtomName|@operator/,specialAtomName:/\.\.\.|<<>>|%\{\}|%|\{\}/,aliasPart:/[A-Z][a-zA-Z0-9_]*/,moduleName:/@aliasPart(?:\.@aliasPart)*/,sigilSymmetricDelimiter:/"""|'''|"|'|\/|\|/,sigilStartDelimiter:/@sigilSymmetricDelimiter|<|\{|\[|\(/,sigilEndDelimiter:/@sigilSymmetricDelimiter|>|\}|\]|\)/,sigilModifiers:/[a-zA-Z0-9]*/,decimal:/\d(?:_?\d)*/,hex:/[0-9a-fA-F](_?[0-9a-fA-F])*/,octal:/[0-7](_?[0-7])*/,binary:/[01](_?[01])*/,escape:/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}|\\./,tokenizer:{root:[{include:"@whitespace"},{include:"@comments"},{include:"@keywordsShorthand"},{include:"@numbers"},{include:"@identifiers"},{include:"@strings"},{include:"@atoms"},{include:"@sigils"},{include:"@attributes"},{include:"@symbols"}],whitespace:[[/\s+/,"white"]],comments:[[/(#)(.*)/,["comment.punctuation","comment"]]],keywordsShorthand:[[/(@atomName)(:)(\s+)/,["constant","constant.punctuation","white"]],[/"(?=([^"]|#\{.*?\}|\\")*":)/,{token:"constant.delimiter",next:"@doubleQuotedStringKeyword"}],[/'(?=([^']|#\{.*?\}|\\')*':)/,{token:"constant.delimiter",next:"@singleQuotedStringKeyword"}]],doubleQuotedStringKeyword:[[/":/,{token:"constant.delimiter",next:"@pop"}],{include:"@stringConstantContentInterpol"}],singleQuotedStringKeyword:[[/':/,{token:"constant.delimiter",next:"@pop"}],{include:"@stringConstantContentInterpol"}],numbers:[[/0b@binary/,"number.binary"],[/0o@octal/,"number.octal"],[/0x@hex/,"number.hex"],[/@decimal\.@decimal([eE]-?@decimal)?/,"number.float"],[/@decimal/,"number"]],identifiers:[[/\b(defp?|defnp?|defmacrop?|defguardp?|defdelegate)(\s+)(@variableName)(?!\s+@operator)/,["keyword.declaration","white",{cases:{unquote:"keyword","@default":"function"}}]],[/(@variableName)(?=\s*\.?\s*\()/,{cases:{"@declarationKeywords":"keyword.declaration","@namespaceKeywords":"keyword","@otherKeywords":"keyword","@default":"function.call"}}],[/(@moduleName)(\s*)(\.)(\s*)(@variableName)/,["type.identifier","white","operator","white","function.call"]],[/(:)(@atomName)(\s*)(\.)(\s*)(@variableName)/,["constant.punctuation","constant","white","operator","white","function.call"]],[/(\|>)(\s*)(@variableName)/,["operator","white",{cases:{"@otherKeywords":"keyword","@default":"function.call"}}]],[/(&)(\s*)(@variableName)/,["operator","white","function.call"]],[/@variableName/,{cases:{"@declarationKeywords":"keyword.declaration","@operatorKeywords":"keyword.operator","@namespaceKeywords":"keyword","@otherKeywords":"keyword","@constants":"constant.language","@nameBuiltin":"variable.language","_.*":"comment.unused","@default":"identifier"}}],[/@moduleName/,"type.identifier"]],strings:[[/"""/,{token:"string.delimiter",next:"@doubleQuotedHeredoc"}],[/'''/,{token:"string.delimiter",next:"@singleQuotedHeredoc"}],[/"/,{token:"string.delimiter",next:"@doubleQuotedString"}],[/'/,{token:"string.delimiter",next:"@singleQuotedString"}]],doubleQuotedHeredoc:[[/"""/,{token:"string.delimiter",next:"@pop"}],{include:"@stringContentInterpol"}],singleQuotedHeredoc:[[/'''/,{token:"string.delimiter",next:"@pop"}],{include:"@stringContentInterpol"}],doubleQuotedString:[[/"/,{token:"string.delimiter",next:"@pop"}],{include:"@stringContentInterpol"}],singleQuotedString:[[/'/,{token:"string.delimiter",next:"@pop"}],{include:"@stringContentInterpol"}],atoms:[[/(:)(@atomName)/,["constant.punctuation","constant"]],[/:"/,{token:"constant.delimiter",next:"@doubleQuotedStringAtom"}],[/:'/,{token:"constant.delimiter",next:"@singleQuotedStringAtom"}]],doubleQuotedStringAtom:[[/"/,{token:"constant.delimiter",next:"@pop"}],{include:"@stringConstantContentInterpol"}],singleQuotedStringAtom:[[/'/,{token:"constant.delimiter",next:"@pop"}],{include:"@stringConstantContentInterpol"}],sigils:[[/~[a-z]@sigilStartDelimiter/,{token:"@rematch",next:"@sigil.interpol"}],[/~([A-Z]+)@sigilStartDelimiter/,{token:"@rematch",next:"@sigil.noInterpol"}]],sigil:[[/~([a-z]|[A-Z]+)\{/,{token:"@rematch",switchTo:"@sigilStart.$S2.$1.{.}"}],[/~([a-z]|[A-Z]+)\[/,{token:"@rematch",switchTo:"@sigilStart.$S2.$1.[.]"}],[/~([a-z]|[A-Z]+)\(/,{token:"@rematch",switchTo:"@sigilStart.$S2.$1.(.)"}],[/~([a-z]|[A-Z]+)\"}],[/~([a-z]|[A-Z]+)(@sigilSymmetricDelimiter)/,{token:"@rematch",switchTo:"@sigilStart.$S2.$1.$2.$2"}]],"sigilStart.interpol.s":[[/~s@sigilStartDelimiter/,{token:"string.delimiter",switchTo:"@sigilContinue.$S2.$S3.$S4.$S5"}]],"sigilContinue.interpol.s":[[/(@sigilEndDelimiter)@sigilModifiers/,{cases:{"$1==$S5":{token:"string.delimiter",next:"@pop"},"@default":"string"}}],{include:"@stringContentInterpol"}],"sigilStart.noInterpol.S":[[/~S@sigilStartDelimiter/,{token:"string.delimiter",switchTo:"@sigilContinue.$S2.$S3.$S4.$S5"}]],"sigilContinue.noInterpol.S":[[/(^|[^\\])\\@sigilEndDelimiter/,"string"],[/(@sigilEndDelimiter)@sigilModifiers/,{cases:{"$1==$S5":{token:"string.delimiter",next:"@pop"},"@default":"string"}}],{include:"@stringContent"}],"sigilStart.interpol.r":[[/~r@sigilStartDelimiter/,{token:"regexp.delimiter",switchTo:"@sigilContinue.$S2.$S3.$S4.$S5"}]],"sigilContinue.interpol.r":[[/(@sigilEndDelimiter)@sigilModifiers/,{cases:{"$1==$S5":{token:"regexp.delimiter",next:"@pop"},"@default":"regexp"}}],{include:"@regexpContentInterpol"}],"sigilStart.noInterpol.R":[[/~R@sigilStartDelimiter/,{token:"regexp.delimiter",switchTo:"@sigilContinue.$S2.$S3.$S4.$S5"}]],"sigilContinue.noInterpol.R":[[/(^|[^\\])\\@sigilEndDelimiter/,"regexp"],[/(@sigilEndDelimiter)@sigilModifiers/,{cases:{"$1==$S5":{token:"regexp.delimiter",next:"@pop"},"@default":"regexp"}}],{include:"@regexpContent"}],"sigilStart.interpol":[[/~([a-z]|[A-Z]+)@sigilStartDelimiter/,{token:"sigil.delimiter",switchTo:"@sigilContinue.$S2.$S3.$S4.$S5"}]],"sigilContinue.interpol":[[/(@sigilEndDelimiter)@sigilModifiers/,{cases:{"$1==$S5":{token:"sigil.delimiter",next:"@pop"},"@default":"sigil"}}],{include:"@sigilContentInterpol"}],"sigilStart.noInterpol":[[/~([a-z]|[A-Z]+)@sigilStartDelimiter/,{token:"sigil.delimiter",switchTo:"@sigilContinue.$S2.$S3.$S4.$S5"}]],"sigilContinue.noInterpol":[[/(^|[^\\])\\@sigilEndDelimiter/,"sigil"],[/(@sigilEndDelimiter)@sigilModifiers/,{cases:{"$1==$S5":{token:"sigil.delimiter",next:"@pop"},"@default":"sigil"}}],{include:"@sigilContent"}],attributes:[[/\@(module|type)?doc (~[sS])?"""/,{token:"comment.block.documentation",next:"@doubleQuotedHeredocDocstring"}],[/\@(module|type)?doc (~[sS])?'''/,{token:"comment.block.documentation",next:"@singleQuotedHeredocDocstring"}],[/\@(module|type)?doc (~[sS])?"/,{token:"comment.block.documentation",next:"@doubleQuotedStringDocstring"}],[/\@(module|type)?doc (~[sS])?'/,{token:"comment.block.documentation",next:"@singleQuotedStringDocstring"}],[/\@(module|type)?doc false/,"comment.block.documentation"],[/\@(@variableName)/,"variable"]],doubleQuotedHeredocDocstring:[[/"""/,{token:"comment.block.documentation",next:"@pop"}],{include:"@docstringContent"}],singleQuotedHeredocDocstring:[[/'''/,{token:"comment.block.documentation",next:"@pop"}],{include:"@docstringContent"}],doubleQuotedStringDocstring:[[/"/,{token:"comment.block.documentation",next:"@pop"}],{include:"@docstringContent"}],singleQuotedStringDocstring:[[/'/,{token:"comment.block.documentation",next:"@pop"}],{include:"@docstringContent"}],symbols:[[/\?(\\.|[^\\\s])/,"number.constant"],[/&\d+/,"operator"],[/<<<|>>>/,"operator"],[/[()\[\]\{\}]|<<|>>/,"@brackets"],[/\.\.\./,"identifier"],[/=>/,"punctuation"],[/@operator/,"operator"],[/[:;,.%]/,"punctuation"]],stringContentInterpol:[{include:"@interpolation"},{include:"@escapeChar"},{include:"@stringContent"}],stringContent:[[/./,"string"]],stringConstantContentInterpol:[{include:"@interpolation"},{include:"@escapeChar"},{include:"@stringConstantContent"}],stringConstantContent:[[/./,"constant"]],regexpContentInterpol:[{include:"@interpolation"},{include:"@escapeChar"},{include:"@regexpContent"}],regexpContent:[[/(\s)(#)(\s.*)$/,["white","comment.punctuation","comment"]],[/./,"regexp"]],sigilContentInterpol:[{include:"@interpolation"},{include:"@escapeChar"},{include:"@sigilContent"}],sigilContent:[[/./,"sigil"]],docstringContent:[[/./,"comment.block.documentation"]],escapeChar:[[/@escape/,"constant.character.escape"]],interpolation:[[/#{/,{token:"delimiter.bracket.embed",next:"@interpolationContinue"}]],interpolationContinue:[[/}/,{token:"delimiter.bracket.embed",next:"@pop"}],{include:"@root"}]}};return m(p);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/flow9/flow9.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/flow9/flow9", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(o,e)=>{for(var t in e)s(o,t,{get:e[t],enumerable:!0})},m=(o,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of a(e))!l.call(o,n)&&n!==t&&s(o,n,{get:()=>e[n],enumerable:!(i=r(e,n))||i.enumerable});return o};var p=o=>m(s({},"__esModule",{value:!0}),o);var u={};c(u,{conf:()=>g,language:()=>f});var g={comments:{blockComment:["/*","*/"],lineComment:"//"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}",notIn:["string"]},{open:"[",close:"]",notIn:["string"]},{open:"(",close:")",notIn:["string"]},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}]},f={defaultToken:"",tokenPostfix:".flow",keywords:["import","require","export","forbid","native","if","else","cast","unsafe","switch","default"],types:["io","mutable","bool","int","double","string","flow","void","ref","true","false","with"],operators:["=",">","<","<=",">=","==","!","!=",":=","::=","&&","||","+","-","*","/","@","&","%",":","->","\\","$","??","^"],symbols:/[@$=>](?!@symbols)/,"delimiter"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]]}};return p(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/freemarker2/freemarker2.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/freemarker2/freemarker2", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var B=Object.create;var d=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,v=Object.prototype.hasOwnProperty;var w=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(n,i)=>(typeof require<"u"?require:n)[i]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var h=(t,n)=>()=>(n||t((n={exports:{}}).exports,n),n.exports),S=(t,n)=>{for(var i in n)d(t,i,{get:n[i],enumerable:!0})},s=(t,n,i,e)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of D(n))!v.call(t,o)&&o!==i&&d(t,o,{get:()=>n[o],enumerable:!(e=C(n,o))||e.enumerable});return t},m=(t,n,i)=>(s(t,n,"default"),i&&s(i,n,"default")),x=(t,n,i)=>(i=t!=null?B(T(t)):{},s(n||!t||!t.__esModule?d(i,"default",{value:t,enumerable:!0}):i,t)),I=t=>s(d({},"__esModule",{value:!0}),t);var F=h((q,f)=>{var y=x(w("vs/editor/editor.api"));f.exports=y});var M={};S(M,{TagAngleInterpolationBracket:()=>L,TagAngleInterpolationDollar:()=>R,TagAutoInterpolationBracket:()=>j,TagAutoInterpolationDollar:()=>Z,TagBracketInterpolationBracket:()=>O,TagBracketInterpolationDollar:()=>z});var _={};m(_,x(F()));var l=["assign","flush","ftl","return","global","import","include","break","continue","local","nested","nt","setting","stop","t","lt","rt","fallback"],k=["attempt","autoesc","autoEsc","compress","comment","escape","noescape","function","if","list","items","sep","macro","noparse","noParse","noautoesc","noAutoEsc","outputformat","switch","visit","recurse"],r={close:">",id:"angle",open:"<"},u={close:"\\]",id:"bracket",open:"\\["},P={close:"[>\\]]",id:"auto",open:"[<\\[]"},g={close:"\\}",id:"dollar",open1:"\\$",open2:"\\{"},A={close:"\\]",id:"bracket",open1:"\\[",open2:"="};function p(t){return{brackets:[["<",">"],["[","]"],["(",")"],["{","}"]],comments:{blockComment:[`${t.open}--`,`--${t.close}`]},autoCloseBefore:` \r }]),.:;=`,autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string"]}],surroundingPairs:[{open:'"',close:'"'},{open:"'",close:"'"},{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"}],folding:{markers:{start:new RegExp(`${t.open}#(?:${k.join("|")})([^/${t.close}]*(?!/)${t.close})[^${t.open}]*$`),end:new RegExp(`${t.open}/#(?:${k.join("|")})[\\r\\n\\t ]*>`)}},onEnterRules:[{beforeText:new RegExp(`${t.open}#(?!(?:${l.join("|")}))([a-zA-Z_]+)([^/${t.close}]*(?!/)${t.close})[^${t.open}]*$`),afterText:new RegExp(`^${t.open}/#([a-zA-Z_]+)[\\r\\n\\t ]*${t.close}$`),action:{indentAction:_.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(`${t.open}#(?!(?:${l.join("|")}))([a-zA-Z_]+)([^/${t.close}]*(?!/)${t.close})[^${t.open}]*$`),action:{indentAction:_.languages.IndentAction.Indent}}]}}function b(){return{brackets:[["<",">"],["[","]"],["(",")"],["{","}"]],autoCloseBefore:` \r }]),.:;=`,autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string"]}],surroundingPairs:[{open:'"',close:'"'},{open:"'",close:"'"},{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"}],folding:{markers:{start:new RegExp(`[<\\[]#(?:${k.join("|")})([^/>\\]]*(?!/)[>\\]])[^<\\[]*$`),end:new RegExp(`[<\\[]/#(?:${k.join("|")})[\\r\\n\\t ]*>`)}},onEnterRules:[{beforeText:new RegExp(`[<\\[]#(?!(?:${l.join("|")}))([a-zA-Z_]+)([^/>\\]]*(?!/)[>\\]])[^[<\\[]]*$`),afterText:new RegExp("^[<\\[]/#([a-zA-Z_]+)[\\r\\n\\t ]*[>\\]]$"),action:{indentAction:_.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(`[<\\[]#(?!(?:${l.join("|")}))([a-zA-Z_]+)([^/>\\]]*(?!/)[>\\]])[^[<\\[]]*$`),action:{indentAction:_.languages.IndentAction.Indent}}]}}function a(t,n){let i=`_${t.id}_${n.id}`,e=c=>c.replace(/__id__/g,i),o=c=>{let E=c.source.replace(/__id__/g,i);return new RegExp(E,c.flags)};return{unicode:!0,includeLF:!1,start:e("default__id__"),ignoreCase:!1,defaultToken:"invalid",tokenPostfix:".freemarker2",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],[e("open__id__")]:new RegExp(t.open),[e("close__id__")]:new RegExp(t.close),[e("iOpen1__id__")]:new RegExp(n.open1),[e("iOpen2__id__")]:new RegExp(n.open2),[e("iClose__id__")]:new RegExp(n.close),[e("startTag__id__")]:o(/(@open__id__)(#)/),[e("endTag__id__")]:o(/(@open__id__)(\/#)/),[e("startOrEndTag__id__")]:o(/(@open__id__)(\/?#)/),[e("closeTag1__id__")]:o(/((?:@blank)*)(@close__id__)/),[e("closeTag2__id__")]:o(/((?:@blank)*\/?)(@close__id__)/),blank:/[ \t\n\r]/,keywords:["false","true","in","as","using"],directiveStartCloseTag1:/attempt|recover|sep|auto[eE]sc|no(?:autoe|AutoE)sc|compress|default|no[eE]scape|comment|no[pP]arse/,directiveStartCloseTag2:/else|break|continue|return|stop|flush|t|lt|rt|nt|nested|recurse|fallback|ftl/,directiveStartBlank:/if|else[iI]f|list|for[eE]ach|switch|case|assign|global|local|include|import|function|macro|transform|visit|stop|return|call|setting|output[fF]ormat|nested|recurse|escape|ftl|items/,directiveEndCloseTag1:/if|list|items|sep|recover|attempt|for[eE]ach|local|global|assign|function|macro|output[fF]ormat|auto[eE]sc|no(?:autoe|AutoE)sc|compress|transform|switch|escape|no[eE]scape/,escapedChar:/\\(?:[ntrfbgla\\'"\{=]|(?:x[0-9A-Fa-f]{1,4}))/,asciiDigit:/[0-9]/,integer:/[0-9]+/,nonEscapedIdStartChar:/[\$@-Z_a-z\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u1FFF\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183-\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3006\u3031-\u3035\u303B-\u303C\u3040-\u318F\u31A0-\u31BA\u31F0-\u31FF\u3300-\u337F\u3400-\u4DB5\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/,escapedIdChar:/\\[\-\.:#]/,idStartChar:/(?:@nonEscapedIdStartChar)|(?:@escapedIdChar)/,id:/(?:@idStartChar)(?:(?:@idStartChar)|(?:@asciiDigit))*/,specialHashKeys:/\*\*|\*|false|true|in|as|using/,namedSymbols:/<=|>=|\\lte|\\lt|<|\\gte|\\gt|>|&&|\\and|->|->|==|!=|\+=|-=|\*=|\/=|%=|\+\+|--|<=|&&|\|\||:|\.\.\.|\.\.\*|\.\.<|\.\.!|\?\?|=|<|\+|-|\*|\/|%|\||\.\.|\?|!|&|\.|,|;/,arrows:["->","->"],delimiters:[";",":",",","."],stringOperators:["lte","lt","gte","gt"],noParseTags:["noparse","noParse","comment"],tokenizer:{[e("default__id__")]:[{include:e("@directive_token__id__")},{include:e("@interpolation_and_text_token__id__")}],[e("fmExpression__id__.directive")]:[{include:e("@blank_and_expression_comment_token__id__")},{include:e("@directive_end_token__id__")},{include:e("@expression_token__id__")}],[e("fmExpression__id__.interpolation")]:[{include:e("@blank_and_expression_comment_token__id__")},{include:e("@expression_token__id__")},{include:e("@greater_operators_token__id__")}],[e("inParen__id__.plain")]:[{include:e("@blank_and_expression_comment_token__id__")},{include:e("@directive_end_token__id__")},{include:e("@expression_token__id__")}],[e("inParen__id__.gt")]:[{include:e("@blank_and_expression_comment_token__id__")},{include:e("@expression_token__id__")},{include:e("@greater_operators_token__id__")}],[e("noSpaceExpression__id__")]:[{include:e("@no_space_expression_end_token__id__")},{include:e("@directive_end_token__id__")},{include:e("@expression_token__id__")}],[e("unifiedCall__id__")]:[{include:e("@unified_call_token__id__")}],[e("singleString__id__")]:[{include:e("@string_single_token__id__")}],[e("doubleString__id__")]:[{include:e("@string_double_token__id__")}],[e("rawSingleString__id__")]:[{include:e("@string_single_raw_token__id__")}],[e("rawDoubleString__id__")]:[{include:e("@string_double_raw_token__id__")}],[e("expressionComment__id__")]:[{include:e("@expression_comment_token__id__")}],[e("noParse__id__")]:[{include:e("@no_parse_token__id__")}],[e("terseComment__id__")]:[{include:e("@terse_comment_token__id__")}],[e("directive_token__id__")]:[[o(/(?:@startTag__id__)(@directiveStartCloseTag1)(?:@closeTag1__id__)/),t.id==="auto"?{cases:{"$1==<":{token:"@rematch",switchTo:`@default_angle_${n.id}`},"$1==[":{token:"@rematch",switchTo:`@default_bracket_${n.id}`}}}:[{token:"@brackets.directive"},{token:"delimiter.directive"},{cases:{"@noParseTags":{token:"tag",next:e("@noParse__id__.$3")},"@default":{token:"tag"}}},{token:"delimiter.directive"},{token:"@brackets.directive"}]],[o(/(?:@startTag__id__)(@directiveStartCloseTag2)(?:@closeTag2__id__)/),t.id==="auto"?{cases:{"$1==<":{token:"@rematch",switchTo:`@default_angle_${n.id}`},"$1==[":{token:"@rematch",switchTo:`@default_bracket_${n.id}`}}}:[{token:"@brackets.directive"},{token:"delimiter.directive"},{token:"tag"},{token:"delimiter.directive"},{token:"@brackets.directive"}]],[o(/(?:@startTag__id__)(@directiveStartBlank)(@blank)/),t.id==="auto"?{cases:{"$1==<":{token:"@rematch",switchTo:`@default_angle_${n.id}`},"$1==[":{token:"@rematch",switchTo:`@default_bracket_${n.id}`}}}:[{token:"@brackets.directive"},{token:"delimiter.directive"},{token:"tag"},{token:"",next:e("@fmExpression__id__.directive")}]],[o(/(?:@endTag__id__)(@directiveEndCloseTag1)(?:@closeTag1__id__)/),t.id==="auto"?{cases:{"$1==<":{token:"@rematch",switchTo:`@default_angle_${n.id}`},"$1==[":{token:"@rematch",switchTo:`@default_bracket_${n.id}`}}}:[{token:"@brackets.directive"},{token:"delimiter.directive"},{token:"tag"},{token:"delimiter.directive"},{token:"@brackets.directive"}]],[o(/(@open__id__)(@)/),t.id==="auto"?{cases:{"$1==<":{token:"@rematch",switchTo:`@default_angle_${n.id}`},"$1==[":{token:"@rematch",switchTo:`@default_bracket_${n.id}`}}}:[{token:"@brackets.directive"},{token:"delimiter.directive",next:e("@unifiedCall__id__")}]],[o(/(@open__id__)(\/@)((?:(?:@id)(?:\.(?:@id))*)?)(?:@closeTag1__id__)/),[{token:"@brackets.directive"},{token:"delimiter.directive"},{token:"tag"},{token:"delimiter.directive"},{token:"@brackets.directive"}]],[o(/(@open__id__)#--/),t.id==="auto"?{cases:{"$1==<":{token:"@rematch",switchTo:`@default_angle_${n.id}`},"$1==[":{token:"@rematch",switchTo:`@default_bracket_${n.id}`}}}:{token:"comment",next:e("@terseComment__id__")}],[o(/(?:@startOrEndTag__id__)([a-zA-Z_]+)/),t.id==="auto"?{cases:{"$1==<":{token:"@rematch",switchTo:`@default_angle_${n.id}`},"$1==[":{token:"@rematch",switchTo:`@default_bracket_${n.id}`}}}:[{token:"@brackets.directive"},{token:"delimiter.directive"},{token:"tag.invalid",next:e("@fmExpression__id__.directive")}]]],[e("interpolation_and_text_token__id__")]:[[o(/(@iOpen1__id__)(@iOpen2__id__)/),[{token:n.id==="bracket"?"@brackets.interpolation":"delimiter.interpolation"},{token:n.id==="bracket"?"delimiter.interpolation":"@brackets.interpolation",next:e("@fmExpression__id__.interpolation")}]],[/[\$#<\[\{]|(?:@blank)+|[^\$<#\[\{\n\r\t ]+/,{token:"source"}]],[e("string_single_token__id__")]:[[/[^'\\]/,{token:"string"}],[/@escapedChar/,{token:"string.escape"}],[/'/,{token:"string",next:"@pop"}]],[e("string_double_token__id__")]:[[/[^"\\]/,{token:"string"}],[/@escapedChar/,{token:"string.escape"}],[/"/,{token:"string",next:"@pop"}]],[e("string_single_raw_token__id__")]:[[/[^']+/,{token:"string.raw"}],[/'/,{token:"string.raw",next:"@pop"}]],[e("string_double_raw_token__id__")]:[[/[^"]+/,{token:"string.raw"}],[/"/,{token:"string.raw",next:"@pop"}]],[e("expression_token__id__")]:[[/(r?)(['"])/,{cases:{"r'":[{token:"keyword"},{token:"string.raw",next:e("@rawSingleString__id__")}],'r"':[{token:"keyword"},{token:"string.raw",next:e("@rawDoubleString__id__")}],"'":[{token:"source"},{token:"string",next:e("@singleString__id__")}],'"':[{token:"source"},{token:"string",next:e("@doubleString__id__")}]}}],[/(?:@integer)(?:\.(?:@integer))?/,{cases:{"(?:@integer)":{token:"number"},"@default":{token:"number.float"}}}],[/(\.)(@blank*)(@specialHashKeys)/,[{token:"delimiter"},{token:""},{token:"identifier"}]],[/(?:@namedSymbols)/,{cases:{"@arrows":{token:"meta.arrow"},"@delimiters":{token:"delimiter"},"@default":{token:"operators"}}}],[/@id/,{cases:{"@keywords":{token:"keyword.$0"},"@stringOperators":{token:"operators"},"@default":{token:"identifier"}}}],[/[\[\]\(\)\{\}]/,{cases:{"\\[":{cases:{"$S2==gt":{token:"@brackets",next:e("@inParen__id__.gt")},"@default":{token:"@brackets",next:e("@inParen__id__.plain")}}},"\\]":{cases:{...n.id==="bracket"?{"$S2==interpolation":{token:"@brackets.interpolation",next:"@popall"}}:{},...t.id==="bracket"?{"$S2==directive":{token:"@brackets.directive",next:"@popall"}}:{},[e("$S1==inParen__id__")]:{token:"@brackets",next:"@pop"},"@default":{token:"@brackets"}}},"\\(":{token:"@brackets",next:e("@inParen__id__.gt")},"\\)":{cases:{[e("$S1==inParen__id__")]:{token:"@brackets",next:"@pop"},"@default":{token:"@brackets"}}},"\\{":{cases:{"$S2==gt":{token:"@brackets",next:e("@inParen__id__.gt")},"@default":{token:"@brackets",next:e("@inParen__id__.plain")}}},"\\}":{cases:{...n.id==="bracket"?{}:{"$S2==interpolation":{token:"@brackets.interpolation",next:"@popall"}},[e("$S1==inParen__id__")]:{token:"@brackets",next:"@pop"},"@default":{token:"@brackets"}}}}}],[/\$\{/,{token:"delimiter.invalid"}]],[e("blank_and_expression_comment_token__id__")]:[[/(?:@blank)+/,{token:""}],[/[<\[][#!]--/,{token:"comment",next:e("@expressionComment__id__")}]],[e("directive_end_token__id__")]:[[/>/,t.id==="bracket"?{token:"operators"}:{token:"@brackets.directive",next:"@popall"}],[o(/(\/)(@close__id__)/),[{token:"delimiter.directive"},{token:"@brackets.directive",next:"@popall"}]]],[e("greater_operators_token__id__")]:[[/>/,{token:"operators"}],[/>=/,{token:"operators"}]],[e("no_space_expression_end_token__id__")]:[[/(?:@blank)+/,{token:"",switchTo:e("@fmExpression__id__.directive")}]],[e("unified_call_token__id__")]:[[/(@id)((?:@blank)+)/,[{token:"tag"},{token:"",next:e("@fmExpression__id__.directive")}]],[o(/(@id)(\/?)(@close__id__)/),[{token:"tag"},{token:"delimiter.directive"},{token:"@brackets.directive",next:"@popall"}]],[/./,{token:"@rematch",next:e("@noSpaceExpression__id__")}]],[e("no_parse_token__id__")]:[[o(/(@open__id__)(\/#?)([a-zA-Z]+)((?:@blank)*)(@close__id__)/),{cases:{"$S2==$3":[{token:"@brackets.directive"},{token:"delimiter.directive"},{token:"tag"},{token:""},{token:"@brackets.directive",next:"@popall"}],"$S2==comment":[{token:"comment"},{token:"comment"},{token:"comment"},{token:"comment"},{token:"comment"}],"@default":[{token:"source"},{token:"source"},{token:"source"},{token:"source"},{token:"source"}]}}],[/[^<\[\-]+|[<\[\-]/,{cases:{"$S2==comment":{token:"comment"},"@default":{token:"source"}}}]],[e("expression_comment_token__id__")]:[[/--[>\]]/,{token:"comment",next:"@pop"}],[/[^\->\]]+|[>\]\-]/,{token:"comment"}]],[e("terse_comment_token__id__")]:[[o(/--(?:@close__id__)/),{token:"comment",next:"@popall"}],[/[^<\[\-]+|[<\[\-]/,{token:"comment"}]]}}}function $(t){let n=a(r,t),i=a(u,t),e=a(P,t);return{...n,...i,...e,unicode:!0,includeLF:!1,start:`default_auto_${t.id}`,ignoreCase:!1,defaultToken:"invalid",tokenPostfix:".freemarker2",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],tokenizer:{...n.tokenizer,...i.tokenizer,...e.tokenizer}}}var R={conf:p(r),language:a(r,g)},z={conf:p(u),language:a(u,g)},L={conf:p(r),language:a(r,A)},O={conf:p(u),language:a(u,A)},Z={conf:b(),language:$(g)},j={conf:b(),language:$(A)};return I(M);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/fsharp/fsharp.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/fsharp/fsharp", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(n,e)=>{for(var o in e)s(n,o,{get:e[o],enumerable:!0})},g=(n,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of a(e))!l.call(n,t)&&t!==o&&s(n,t,{get:()=>e[t],enumerable:!(i=r(e,t))||i.enumerable});return n};var f=n=>g(s({},"__esModule",{value:!0}),n);var d={};c(d,{conf:()=>m,language:()=>u});var m={comments:{lineComment:"//",blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*//\\s*#region\\b|^\\s*\\(\\*\\s*#region(.*)\\*\\)"),end:new RegExp("^\\s*//\\s*#endregion\\b|^\\s*\\(\\*\\s*#endregion\\s*\\*\\)")}}},u={defaultToken:"",tokenPostfix:".fs",keywords:["abstract","and","atomic","as","assert","asr","base","begin","break","checked","component","const","constraint","constructor","continue","class","default","delegate","do","done","downcast","downto","elif","else","end","exception","eager","event","external","extern","false","finally","for","fun","function","fixed","functor","global","if","in","include","inherit","inline","interface","internal","land","lor","lsl","lsr","lxor","lazy","let","match","member","mod","module","mutable","namespace","method","mixin","new","not","null","of","open","or","object","override","private","parallel","process","protected","pure","public","rec","return","static","sealed","struct","sig","then","to","true","tailcall","trait","try","type","upcast","use","val","void","virtual","volatile","when","while","with","yield"],symbols:/[=>\]/,"annotation"],[/^#(if|else|endif)/,"keyword"],[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,"delimiter"],[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/,"number.float"],[/0x[0-9a-fA-F]+LF/,"number.float"],[/0x[0-9a-fA-F]+(@integersuffix)/,"number.hex"],[/0b[0-1]+(@integersuffix)/,"number.bin"],[/\d+(@integersuffix)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"""/,"string",'@string."""'],[/"/,"string",'@string."'],[/\@"/,{token:"string.quote",next:"@litstring"}],[/'[^\\']'B?/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\(\*(?!\))/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^*(]+/,"comment"],[/\*\)/,"comment","@pop"],[/\*/,"comment"],[/\(\*\)/,"comment"],[/\(/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/("""|"B?)/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]],litstring:[[/[^"]+/,"string"],[/""/,"string.escape"],[/"/,{token:"string.quote",next:"@pop"}]]}};return f(d);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/go/go.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/go/go", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(n,e)=>{for(var t in e)s(n,t,{get:e[t],enumerable:!0})},l=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of a(e))!c.call(n,o)&&o!==t&&s(n,o,{get:()=>e[o],enumerable:!(r=i(e,o))||r.enumerable});return n};var g=n=>l(s({},"__esModule",{value:!0}),n);var d={};m(d,{conf:()=>p,language:()=>u});var p={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"`",close:"`",notIn:["string"]},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"`",close:"`"},{open:'"',close:'"'},{open:"'",close:"'"}]},u={defaultToken:"",tokenPostfix:".go",keywords:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","switch","type","var","bool","true","false","uint8","uint16","uint32","uint64","int8","int16","int32","int64","float32","float64","complex64","complex128","byte","rune","uint","int","uintptr","string","nil"],operators:["+","-","*","/","%","&","|","^","<<",">>","&^","+=","-=","*=","/=","%=","&=","|=","^=","<<=",">>=","&^=","&&","||","<-","++","--","==","<",">","=","!","!=","<=",">=",":=","...","(",")","","]","{","}",",",";",".",":"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,"number.hex"],[/0[0-7']*[0-7]/,"number.octal"],[/0[bB][0-1']*[0-1]/,"number.binary"],[/\d[\d']*/,"number"],[/\d/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/`/,"string","@rawstring"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@doccomment"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],doccomment:[[/[^\/*]+/,"comment.doc"],[/\/\*/,"comment.doc.invalid"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],rawstring:[[/[^\`]/,"string"],[/`/,"string","@pop"]]}};return g(d);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/graphql/graphql.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/graphql/graphql", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(n,e)=>{for(var t in e)s(n,t,{get:e[t],enumerable:!0})},d=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of i(e))!l.call(n,o)&&o!==t&&s(n,o,{get:()=>e[o],enumerable:!(r=a(e,o))||r.enumerable});return n};var p=n=>d(s({},"__esModule",{value:!0}),n);var u={};c(u,{conf:()=>g,language:()=>I});var g={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"""',close:'"""',notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"""',close:'"""'},{open:'"',close:'"'}],folding:{offSide:!0}},I={defaultToken:"invalid",tokenPostfix:".gql",keywords:["null","true","false","query","mutation","subscription","extend","schema","directive","scalar","type","interface","union","enum","input","implements","fragment","on"],typeKeywords:["Int","Float","String","Boolean","ID"],directiveLocations:["SCHEMA","SCALAR","OBJECT","FIELD_DEFINITION","ARGUMENT_DEFINITION","INTERFACE","UNION","ENUM","ENUM_VALUE","INPUT_OBJECT","INPUT_FIELD_DEFINITION","QUERY","MUTATION","SUBSCRIPTION","FIELD","FRAGMENT_DEFINITION","FRAGMENT_SPREAD","INLINE_FRAGMENT","VARIABLE_DEFINITION"],operators:["=","!","?",":","&","|"],symbols:/[=!?:&|]+/,escapes:/\\(?:["\\\/bfnrt]|u[0-9A-Fa-f]{4})/,tokenizer:{root:[[/[a-z_][\w$]*/,{cases:{"@keywords":"keyword","@default":"key.identifier"}}],[/[$][\w$]*/,{cases:{"@keywords":"keyword","@default":"argument.identifier"}}],[/[A-Z][\w\$]*/,{cases:{"@typeKeywords":"keyword","@default":"type.identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,{token:"annotation",log:"annotation token: $0"}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F]+/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/"""/,{token:"string",next:"@mlstring",nextEmbedded:"markdown"}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,{token:"string.quote",bracket:"@open",next:"@string"}]],mlstring:[[/[^"]+/,"string"],['"""',{token:"string",next:"@pop",nextEmbedded:"@pop"}]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/#.*$/,"comment"]]}};return p(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/handlebars/handlebars.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/handlebars/handlebars", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var h=Object.create;var i=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var y=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var T=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),S=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},m=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of u(t))!k.call(e,r)&&r!==n&&i(e,r,{get:()=>t[r],enumerable:!(o=b(t,r))||o.enumerable});return e},l=(e,t,n)=>(m(e,t,"default"),n&&m(n,t,"default")),s=(e,t,n)=>(n=e!=null?h(x(e)):{},m(t||!e||!e.__esModule?i(n,"default",{value:e,enumerable:!0}):n,e)),E=e=>m(i({},"__esModule",{value:!0}),e);var c=T((I,d)=>{var w=s(y("vs/editor/editor.api"));d.exports=w});var f={};S(f,{conf:()=>g,language:()=>$});var a={};l(a,s(c()));var p=["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"],g={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,comments:{blockComment:["{{!--","--}}"]},brackets:[[""],["<",">"],["{{","}}"],["{","}"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"<",close:">"},{open:'"',close:'"'},{open:"'",close:"'"}],onEnterRules:[{beforeText:new RegExp(`<(?!(?:${p.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),afterText:/^<\/(\w[\w\d]*)\s*>$/i,action:{indentAction:a.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(`<(?!(?:${p.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),action:{indentAction:a.languages.IndentAction.Indent}}]},$={defaultToken:"",tokenPostfix:"",tokenizer:{root:[[/\{\{!--/,"comment.block.start.handlebars","@commentBlock"],[/\{\{!/,"comment.start.handlebars","@comment"],[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.root"}],[/)/,["delimiter.html","tag.html","delimiter.html"]],[/(<)(script)/,["delimiter.html",{token:"tag.html",next:"@script"}]],[/(<)(style)/,["delimiter.html",{token:"tag.html",next:"@style"}]],[/(<)([:\w]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/(<\/)(\w+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/]+/,"metatag.content.html"],[/>/,"metatag.html","@pop"]],comment:[[/\}\}/,"comment.end.handlebars","@pop"],[/./,"comment.content.handlebars"]],commentBlock:[[/--\}\}/,"comment.block.end.handlebars","@pop"],[/./,"comment.content.handlebars"]],commentHtml:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.comment"}],[/-->/,"comment.html","@pop"],[/[^-]+/,"comment.content.html"],[/./,"comment.content.html"]],otherTag:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.otherTag"}],[/\/?>/,"delimiter.html","@pop"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/]],script:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.script"}],[/type/,"attribute.name","@scriptAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/(<\/)(script\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],scriptAfterType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.scriptAfterType"}],[/=/,"delimiter","@scriptAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptAfterTypeEquals:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.scriptAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptWithCustomType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.scriptWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptEmbedded:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInEmbeddedState.scriptEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/script/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],style:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.style"}],[/type/,"attribute.name","@styleAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/(<\/)(style\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],styleAfterType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.styleAfterType"}],[/=/,"delimiter","@styleAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleAfterTypeEquals:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.styleAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleWithCustomType:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInSimpleState.styleWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleEmbedded:[[/\{\{/,{token:"@rematch",switchTo:"@handlebarsInEmbeddedState.styleEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/style/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],handlebarsInSimpleState:[[/\{\{\{?/,"delimiter.handlebars"],[/\}\}\}?/,{token:"delimiter.handlebars",switchTo:"@$S2.$S3"}],{include:"handlebarsRoot"}],handlebarsInEmbeddedState:[[/\{\{\{?/,"delimiter.handlebars"],[/\}\}\}?/,{token:"delimiter.handlebars",switchTo:"@$S2.$S3",nextEmbedded:"$S3"}],{include:"handlebarsRoot"}],handlebarsRoot:[[/"[^"]*"/,"string.handlebars"],[/[#/][^\s}]+/,"keyword.helper.handlebars"],[/else\b/,"keyword.helper.handlebars"],[/[\s]+/],[/[^}]/,"variable.parameter.handlebars"]]}};return E(f);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/hcl/hcl.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/hcl/hcl", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var o in e)r(t,o,{get:e[o],enumerable:!0})},d=(t,e,o,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of i(e))!c.call(t,s)&&s!==o&&r(t,s,{get:()=>e[s],enumerable:!(n=a(e,s))||n.enumerable});return t};var m=t=>d(r({},"__esModule",{value:!0}),t);var f={};l(f,{conf:()=>p,language:()=>g});var p={comments:{lineComment:"#",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}]},g={defaultToken:"",tokenPostfix:".hcl",keywords:["var","local","path","for_each","any","string","number","bool","true","false","null","if ","else ","endif ","for ","in","endfor"],operators:["=",">=","<=","==","!=","+","-","*","/","%","&&","||","!","<",">","?","...",":"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/\d[\d']*/,"number"],[/\d/,"number"],[/[;,.]/,"delimiter"],[/"/,"string","@string"],[/'/,"invalid"]],heredoc:[[/<<[-]*\s*["]?([\w\-]+)["]?/,{token:"string.heredoc.delimiter",next:"@heredocBody.$1"}]],heredocBody:[[/([\w\-]+)$/,{cases:{"$1==$S2":[{token:"string.heredoc.delimiter",next:"@popall"}],"@default":"string.heredoc"}}],[/./,"string.heredoc"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"],[/#.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],string:[[/\$\{/,{token:"delimiter",next:"@stringExpression"}],[/[^\\"\$]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@popall"]],stringInsideExpression:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],stringExpression:[[/\}/,{token:"delimiter",next:"@pop"}],[/"/,"string","@stringInsideExpression"],{include:"@terraform"}]}};return m(f);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/html/html.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/html/html", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var u=Object.create;var a=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty;var k=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var E=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),T=(e,t)=>{for(var n in t)a(e,n,{get:t[n],enumerable:!0})},o=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of x(t))!g.call(e,r)&&r!==n&&a(e,r,{get:()=>t[r],enumerable:!(s=b(t,r))||s.enumerable});return e},d=(e,t,n)=>(o(e,t,"default"),n&&o(n,t,"default")),m=(e,t,n)=>(n=e!=null?u(y(e)):{},o(t||!e||!e.__esModule?a(n,"default",{value:e,enumerable:!0}):n,e)),w=e=>o(a({},"__esModule",{value:!0}),e);var l=E((A,p)=>{var h=m(k("vs/editor/editor.api"));p.exports=h});var $={};T($,{conf:()=>v,language:()=>f});var i={};d(i,m(l()));var c=["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"],v={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,comments:{blockComment:[""]},brackets:[[""],["<",">"],["{","}"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:'"',close:'"'},{open:"'",close:"'"},{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"}],onEnterRules:[{beforeText:new RegExp(`<(?!(?:${c.join("|")}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),afterText:/^<\/([_:\w][_:\w-.\d]*)\s*>$/i,action:{indentAction:i.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(`<(?!(?:${c.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),action:{indentAction:i.languages.IndentAction.Indent}}],folding:{markers:{start:new RegExp("^\\s*"),end:new RegExp("^\\s*")}}},f={defaultToken:"",tokenPostfix:".html",ignoreCase:!0,tokenizer:{root:[[/)/,["delimiter","tag","","delimiter"]],[/(<)(script)/,["delimiter",{token:"tag",next:"@script"}]],[/(<)(style)/,["delimiter",{token:"tag",next:"@style"}]],[/(<)((?:[\w\-]+:)?[\w\-]+)/,["delimiter",{token:"tag",next:"@otherTag"}]],[/(<\/)((?:[\w\-]+:)?[\w\-]+)/,["delimiter",{token:"tag",next:"@otherTag"}]],[/]+/,"metatag.content"],[/>/,"metatag","@pop"]],comment:[[/-->/,"comment","@pop"],[/[^-]+/,"comment.content"],[/./,"comment.content"]],otherTag:[[/\/?>/,"delimiter","@pop"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/]],script:[[/type/,"attribute.name","@scriptAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/(<\/)(script\s*)(>)/,["delimiter","tag",{token:"delimiter",next:"@pop"}]]],scriptAfterType:[[/=/,"delimiter","@scriptAfterTypeEquals"],[/>/,{token:"delimiter",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptAfterTypeEquals:[[/"module"/,{token:"attribute.value",switchTo:"@scriptWithCustomType.text/javascript"}],[/'module'/,{token:"attribute.value",switchTo:"@scriptWithCustomType.text/javascript"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/>/,{token:"delimiter",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptWithCustomType:[[/>/,{token:"delimiter",next:"@scriptEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptEmbedded:[[/<\/script/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}],[/[^<]+/,""]],style:[[/type/,"attribute.name","@styleAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/(<\/)(style\s*)(>)/,["delimiter","tag",{token:"delimiter",next:"@pop"}]]],styleAfterType:[[/=/,"delimiter","@styleAfterTypeEquals"],[/>/,{token:"delimiter",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleAfterTypeEquals:[[/"([^"]*)"/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/>/,{token:"delimiter",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleWithCustomType:[[/>/,{token:"delimiter",next:"@styleEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleEmbedded:[[/<\/style/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}],[/[^<]+/,""]]}};return w($);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/ini/ini.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/ini/ini", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var t=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var c=(n,e)=>{for(var s in e)t(n,s,{get:e[s],enumerable:!0})},l=(n,e,s,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of r(e))!g.call(n,o)&&o!==s&&t(n,o,{get:()=>e[o],enumerable:!(a=i(e,o))||a.enumerable});return n};var p=n=>l(t({},"__esModule",{value:!0}),n);var f={};c(f,{conf:()=>u,language:()=>m});var u={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},m={defaultToken:"",tokenPostfix:".ini",escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^\[[^\]]*\]/,"metatag"],[/(^\w+)(\s*)(\=)/,["key","","delimiter"]],{include:"@whitespace"},[/\d+/,"number"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string",'@string."'],[/'/,"string","@string.'"]],whitespace:[[/[ \t\r\n]+/,""],[/^\s*[#;].*$/,"comment"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}};return p(f);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/java/java.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/java/java", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var o in e)s(t,o,{get:e[o],enumerable:!0})},d=(t,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of r(e))!c.call(t,n)&&n!==o&&s(t,n,{get:()=>e[n],enumerable:!(i=a(e,n))||i.enumerable});return t};var g=t=>d(s({},"__esModule",{value:!0}),t);var f={};l(f,{conf:()=>m,language:()=>p});var m={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}],folding:{markers:{start:new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:))")}}},p={defaultToken:"",tokenPostfix:".java",keywords:["abstract","continue","for","new","switch","assert","default","goto","package","synchronized","boolean","do","if","private","this","break","double","implements","protected","throw","byte","else","import","public","throws","case","enum","instanceof","return","transient","catch","extends","int","short","try","char","final","interface","static","void","class","finally","long","strictfp","volatile","const","float","native","super","while","true","false","yield","record","sealed","non-sealed","permits"],operators:["=",">","<","!","~","?",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>",">>>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>=",">>>="],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,"annotation"],[/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/,"number.float"],[/0[xX](@hexdigits)[Ll]?/,"number.hex"],[/0(@octaldigits)[Ll]?/,"number.octal"],[/0[bB](@binarydigits)[Ll]?/,"number.binary"],[/(@digits)[fFdD]/,"number.float"],[/(@digits)[lL]?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"""/,"string","@multistring"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@javadoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],javadoc:[[/[^\/*]+/,"comment.doc"],[/\/\*/,"comment.doc.invalid"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],multistring:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"""/,"string","@pop"],[/./,"string"]]}};return g(f);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/javascript/javascript.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/javascript/javascript", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var x=Object.create;var a=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var y=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var w=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),h=(e,t)=>{for(var n in t)a(e,n,{get:t[n],enumerable:!0})},s=(e,t,n,c)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of f(t))!k.call(e,r)&&r!==n&&a(e,r,{get:()=>t[r],enumerable:!(c=u(t,r))||c.enumerable});return e},g=(e,t,n)=>(s(e,t,"default"),n&&s(n,t,"default")),p=(e,t,n)=>(n=e!=null?x(b(e)):{},s(t||!e||!e.__esModule?a(n,"default",{value:e,enumerable:!0}):n,e)),v=e=>s(a({},"__esModule",{value:!0}),e);var d=w((C,l)=>{var A=p(y("vs/editor/editor.api"));l.exports=A});var _={};h(_,{conf:()=>$,language:()=>T});var i={};g(i,p(d()));var m={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],onEnterRules:[{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,afterText:/^\s*\*\/$/,action:{indentAction:i.languages.IndentAction.IndentOutdent,appendText:" * "}},{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,action:{indentAction:i.languages.IndentAction.None,appendText:" * "}},{beforeText:/^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,action:{indentAction:i.languages.IndentAction.None,appendText:"* "}},{beforeText:/^(\t|(\ \ ))*\ \*\/\s*$/,action:{indentAction:i.languages.IndentAction.None,removeText:1}}],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string","comment"]},{open:"`",close:"`",notIn:["string","comment"]},{open:"/**",close:" */",notIn:["string"]}],folding:{markers:{start:new RegExp("^\\s*//\\s*#?region\\b"),end:new RegExp("^\\s*//\\s*#?endregion\\b")}}},o={defaultToken:"invalid",tokenPostfix:".ts",keywords:["abstract","any","as","asserts","bigint","boolean","break","case","catch","class","continue","const","constructor","debugger","declare","default","delete","do","else","enum","export","extends","false","finally","for","from","function","get","if","implements","import","in","infer","instanceof","interface","is","keyof","let","module","namespace","never","new","null","number","object","out","package","private","protected","public","override","readonly","require","global","return","satisfies","set","static","string","super","switch","symbol","this","throw","true","try","type","typeof","undefined","unique","unknown","var","void","while","with","yield","async","await","of"],operators:["<=",">=","==","!=","===","!==","=>","+","-","**","*","/","%","++","--","<<",">",">>>","&","|","^","!","~","&&","||","??","?",":","=","+=","-=","*=","**=","/=","%=","<<=",">>=",">>>=","&=","|=","^=","@"],symbols:/[=>](?!@symbols)/,"@brackets"],[/!(?=([^=]|$))/,"delimiter"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/(@digits)[eE]([\-+]?(@digits))?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/,"number.float"],[/0[xX](@hexdigits)n?/,"number.hex"],[/0[oO]?(@octaldigits)n?/,"number.octal"],[/0[bB](@binarydigits)n?/,"number.binary"],[/(@digits)n?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string_double"],[/'/,"string","@string_single"],[/`/,"string","@string_backtick"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@jsdoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],jsdoc:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],regexp:[[/(\{)(\d+(?:,\d*)?)(\})/,["regexp.escape.control","regexp.escape.control","regexp.escape.control"]],[/(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/,["regexp.escape.control",{token:"regexp.escape.control",next:"@regexrange"}]],[/(\()(\?:|\?=|\?!)/,["regexp.escape.control","regexp.escape.control"]],[/[()]/,"regexp.escape.control"],[/@regexpctl/,"regexp.escape.control"],[/[^\\\/]/,"regexp"],[/@regexpesc/,"regexp.escape"],[/\\\./,"regexp.invalid"],[/(\/)([dgimsuy]*)/,[{token:"regexp",bracket:"@close",next:"@pop"},"keyword.other"]]],regexrange:[[/-/,"regexp.escape.control"],[/\^/,"regexp.invalid"],[/@regexpesc/,"regexp.escape"],[/[^\]]/,"regexp"],[/\]/,{token:"regexp.escape.control",next:"@pop",bracket:"@close"}]],string_double:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],string_single:[[/[^\\']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/'/,"string","@pop"]],string_backtick:[[/\$\{/,{token:"delimiter.bracket",next:"@bracketCounting"}],[/[^\\`$]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/`/,"string","@pop"]],bracketCounting:[[/\{/,"delimiter.bracket","@bracketCounting"],[/\}/,"delimiter.bracket","@pop"],{include:"common"}]}};var $=m,T={defaultToken:"invalid",tokenPostfix:".js",keywords:["break","case","catch","class","continue","const","constructor","debugger","default","delete","do","else","export","extends","false","finally","for","from","function","get","if","import","in","instanceof","let","new","null","return","set","static","super","switch","symbol","this","throw","true","try","typeof","undefined","var","void","while","with","yield","async","await","of"],typeKeywords:[],operators:o.operators,symbols:o.symbols,escapes:o.escapes,digits:o.digits,octaldigits:o.octaldigits,binarydigits:o.binarydigits,hexdigits:o.hexdigits,regexpctl:o.regexpctl,regexpesc:o.regexpesc,tokenizer:o.tokenizer};return v(_);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/julia/julia.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/julia/julia", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var c=(t,e)=>{for(var n in e)o(t,n,{get:e[n],enumerable:!0})},l=(t,e,n,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of s(e))!p.call(t,r)&&r!==n&&o(t,r,{get:()=>e[r],enumerable:!(a=i(e,r))||a.enumerable});return t};var d=t=>l(o({},"__esModule",{value:!0}),t);var u={};c(u,{conf:()=>g,language:()=>m});var g={brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},m={tokenPostfix:".julia",keywords:["begin","while","if","for","try","return","break","continue","function","macro","quote","let","local","global","const","do","struct","module","baremodule","using","import","export","end","else","elseif","catch","finally","mutable","primitive","abstract","type","in","isa","where","new"],types:["LinRange","LineNumberNode","LinearIndices","LoadError","MIME","Matrix","Method","MethodError","Missing","MissingException","Module","NTuple","NamedTuple","Nothing","Number","OrdinalRange","OutOfMemoryError","OverflowError","Pair","PartialQuickSort","PermutedDimsArray","Pipe","Ptr","QuoteNode","Rational","RawFD","ReadOnlyMemoryError","Real","ReentrantLock","Ref","Regex","RegexMatch","RoundingMode","SegmentationFault","Set","Signed","Some","StackOverflowError","StepRange","StepRangeLen","StridedArray","StridedMatrix","StridedVecOrMat","StridedVector","String","StringIndexError","SubArray","SubString","SubstitutionString","Symbol","SystemError","Task","Text","TextDisplay","Timer","Tuple","Type","TypeError","TypeVar","UInt","UInt128","UInt16","UInt32","UInt64","UInt8","UndefInitializer","AbstractArray","UndefKeywordError","AbstractChannel","UndefRefError","AbstractChar","UndefVarError","AbstractDict","Union","AbstractDisplay","UnionAll","AbstractFloat","UnitRange","AbstractIrrational","Unsigned","AbstractMatrix","AbstractRange","Val","AbstractSet","Vararg","AbstractString","VecElement","AbstractUnitRange","VecOrMat","AbstractVecOrMat","Vector","AbstractVector","VersionNumber","Any","WeakKeyDict","ArgumentError","WeakRef","Array","AssertionError","BigFloat","BigInt","BitArray","BitMatrix","BitSet","BitVector","Bool","BoundsError","CapturedException","CartesianIndex","CartesianIndices","Cchar","Cdouble","Cfloat","Channel","Char","Cint","Cintmax_t","Clong","Clonglong","Cmd","Colon","Complex","ComplexF16","ComplexF32","ComplexF64","CompositeException","Condition","Cptrdiff_t","Cshort","Csize_t","Cssize_t","Cstring","Cuchar","Cuint","Cuintmax_t","Culong","Culonglong","Cushort","Cvoid","Cwchar_t","Cwstring","DataType","DenseArray","DenseMatrix","DenseVecOrMat","DenseVector","Dict","DimensionMismatch","Dims","DivideError","DomainError","EOFError","Enum","ErrorException","Exception","ExponentialBackOff","Expr","Float16","Float32","Float64","Function","GlobalRef","HTML","IO","IOBuffer","IOContext","IOStream","IdDict","IndexCartesian","IndexLinear","IndexStyle","InexactError","InitError","Int","Int128","Int16","Int32","Int64","Int8","Integer","InterruptException","InvalidStateException","Irrational","KeyError"],keywordops:["<:",">:",":","=>","...",".","->","?"],allops:/[^\w\d\s()\[\]{}"'#]+/,constants:["true","false","nothing","missing","undef","Inf","pi","NaN","\u03C0","\u212F","ans","PROGRAM_FILE","ARGS","C_NULL","VERSION","DEPOT_PATH","LOAD_PATH"],operators:["!","!=","!==","%","&","*","+","-","/","//","<","<<","<=","==","===","=>",">",">=",">>",">>>","\\","^","|","|>","~","\xF7","\u2208","\u2209","\u220B","\u220C","\u2218","\u221A","\u221B","\u2229","\u222A","\u2248","\u2249","\u2260","\u2261","\u2262","\u2264","\u2265","\u2286","\u2287","\u2288","\u2289","\u228A","\u228B","\u22BB"],brackets:[{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"}],ident:/π|ℯ|\b(?!\d)\w+\b/,escape:/(?:[abefnrstv\\"'\n\r]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4})/,escapes:/\\(?:C\-(@escape|.)|c(@escape|.)|@escape)/,tokenizer:{root:[[/(::)\s*|\b(isa)\s+/,"keyword","@typeanno"],[/\b(isa)(\s*\(@ident\s*,\s*)/,["keyword",{token:"",next:"@typeanno"}]],[/\b(type|struct)[ \t]+/,"keyword","@typeanno"],[/^\s*:@ident[!?]?/,"metatag"],[/(return)(\s*:@ident[!?]?)/,["keyword","metatag"]],[/(\(|\[|\{|@allops)(\s*:@ident[!?]?)/,["","metatag"]],[/:\(/,"metatag","@quote"],[/r"""/,"regexp.delim","@tregexp"],[/r"/,"regexp.delim","@sregexp"],[/raw"""/,"string.delim","@rtstring"],[/[bv]?"""/,"string.delim","@dtstring"],[/raw"/,"string.delim","@rsstring"],[/[bv]?"/,"string.delim","@dsstring"],[/(@ident)\{/,{cases:{"$1@types":{token:"type",next:"@gen"},"@default":{token:"type",next:"@gen"}}}],[/@ident[!?'']?(?=\.?\()/,{cases:{"@types":"type","@keywords":"keyword","@constants":"variable","@default":"keyword.flow"}}],[/@ident[!?']?/,{cases:{"@types":"type","@keywords":"keyword","@constants":"variable","@default":"identifier"}}],[/\$\w+/,"key"],[/\$\(/,"key","@paste"],[/@@@ident/,"annotation"],{include:"@whitespace"},[/'(?:@escapes|.)'/,"string.character"],[/[()\[\]{}]/,"@brackets"],[/@allops/,{cases:{"@keywordops":"keyword","@operators":"operator"}}],[/[;,]/,"delimiter"],[/0[xX][0-9a-fA-F](_?[0-9a-fA-F])*/,"number.hex"],[/0[_oO][0-7](_?[0-7])*/,"number.octal"],[/0[bB][01](_?[01])*/,"number.binary"],[/[+\-]?\d+(\.\d+)?(im?|[eE][+\-]?\d+(\.\d+)?)?/,"number"]],typeanno:[[/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*\{/,"type","@gen"],[/([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(\s*<:\s*)/,["type","keyword"]],[/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*/,"type","@pop"],["","","@pop"]],gen:[[/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*\{/,"type","@push"],[/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*/,"type"],[/<:/,"keyword"],[/(\})(\s*<:\s*)/,["type",{token:"keyword",next:"@pop"}]],[/\}/,"type","@pop"],{include:"@root"}],quote:[[/\$\(/,"key","@paste"],[/\(/,"@brackets","@paren"],[/\)/,"metatag","@pop"],{include:"@root"}],paste:[[/:\(/,"metatag","@quote"],[/\(/,"@brackets","@paren"],[/\)/,"key","@pop"],{include:"@root"}],paren:[[/\$\(/,"key","@paste"],[/:\(/,"metatag","@quote"],[/\(/,"@brackets","@push"],[/\)/,"@brackets","@pop"],{include:"@root"}],sregexp:[[/^.*/,"invalid"],[/[^\\"()\[\]{}]/,"regexp"],[/[()\[\]{}]/,"@brackets"],[/\\./,"operator.scss"],[/"[imsx]*/,"regexp.delim","@pop"]],tregexp:[[/[^\\"()\[\]{}]/,"regexp"],[/[()\[\]{}]/,"@brackets"],[/\\./,"operator.scss"],[/"(?!"")/,"string"],[/"""[imsx]*/,"regexp.delim","@pop"]],rsstring:[[/^.*/,"invalid"],[/[^\\"]/,"string"],[/\\./,"string.escape"],[/"/,"string.delim","@pop"]],rtstring:[[/[^\\"]/,"string"],[/\\./,"string.escape"],[/"(?!"")/,"string"],[/"""/,"string.delim","@pop"]],dsstring:[[/^.*/,"invalid"],[/[^\\"\$]/,"string"],[/\$/,"","@interpolated"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string.delim","@pop"]],dtstring:[[/[^\\"\$]/,"string"],[/\$/,"","@interpolated"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"(?!"")/,"string"],[/"""/,"string.delim","@pop"]],interpolated:[[/\(/,{token:"",switchTo:"@interpolated_compound"}],[/[a-zA-Z_]\w*/,"identifier"],["","","@pop"]],interpolated_compound:[[/\)/,"","@pop"],{include:"@root"}],whitespace:[[/[ \t\r\n]+/,""],[/#=/,"comment","@multi_comment"],[/#.*$/,"comment"]],multi_comment:[[/#=/,"comment","@push"],[/=#/,"comment","@pop"],[/=(?!#)|#(?!=)/,"comment"],[/[^#=]+/,"comment"]]}};return d(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/kotlin/kotlin.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/kotlin/kotlin", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(n,e)=>{for(var i in e)o(n,i,{get:e[i],enumerable:!0})},d=(n,e,i,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of r(e))!c.call(n,t)&&t!==i&&o(n,t,{get:()=>e[t],enumerable:!(s=a(e,t))||s.enumerable});return n};var g=n=>d(o({},"__esModule",{value:!0}),n);var f={};l(f,{conf:()=>m,language:()=>p});var m={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}],folding:{markers:{start:new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:))")}}},p={defaultToken:"",tokenPostfix:".kt",keywords:["as","as?","break","class","continue","do","else","false","for","fun","if","in","!in","interface","is","!is","null","object","package","return","super","this","throw","true","try","typealias","val","var","when","while","by","catch","constructor","delegate","dynamic","field","file","finally","get","import","init","param","property","receiver","set","setparam","where","actual","abstract","annotation","companion","const","crossinline","data","enum","expect","external","final","infix","inline","inner","internal","lateinit","noinline","open","operator","out","override","private","protected","public","reified","sealed","suspend","tailrec","vararg","field","it"],operators:["+","-","*","/","%","=","+=","-=","*=","/=","%=","++","--","&&","||","!","==","!=","===","!==",">","<","<=",">=","[","]","!!","?.","?:","::","..",":","?","->","@",";","$","_"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,"annotation"],[/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/,"number.float"],[/0[xX](@hexdigits)[Ll]?/,"number.hex"],[/0(@octaldigits)[Ll]?/,"number.octal"],[/0[bB](@binarydigits)[Ll]?/,"number.binary"],[/(@digits)[fFdD]/,"number.float"],[/(@digits)[lL]?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"""/,"string","@multistring"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@javadoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\/\*/,"comment","@comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],javadoc:[[/[^\/*]+/,"comment.doc"],[/\/\*/,"comment.doc","@push"],[/\/\*/,"comment.doc.invalid"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],multistring:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"""/,"string","@pop"],[/./,"string"]]}};return g(f);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/less/less.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/less/less", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var d=(t,e)=>{for(var i in e)r(t,i,{get:e[i],enumerable:!0})},u=(t,e,i,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of a(e))!l.call(t,n)&&n!==i&&r(t,n,{get:()=>e[n],enumerable:!(o=s(e,n))||o.enumerable});return t};var c=t=>u(r({},"__esModule",{value:!0}),t);var p={};d(p,{conf:()=>m,language:()=>g});var m={wordPattern:/(#?-?\d*\.\d\w*%?)|([@#!.:]?[\w-?]+%?)|[@#!.]/g,comments:{blockComment:["/*","*/"],lineComment:"//"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]},{open:"'",close:"'",notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/"),end:new RegExp("^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/")}}},g={defaultToken:"",tokenPostfix:".less",identifier:"-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*",identifierPlus:"-?-?([a-zA-Z:.]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-:.]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.bracket"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],tokenizer:{root:[{include:"@nestedJSBegin"},["[ \\t\\r\\n]+",""],{include:"@comments"},{include:"@keyword"},{include:"@strings"},{include:"@numbers"},["[*_]?[a-zA-Z\\-\\s]+(?=:.*(;|(\\\\$)))","attribute.name","@attribute"],["url(\\-prefix)?\\(",{token:"tag",next:"@urldeclaration"}],["[{}()\\[\\]]","@brackets"],["[,:;]","delimiter"],["#@identifierPlus","tag.id"],["&","tag"],["\\.@identifierPlus(?=\\()","tag.class","@attribute"],["\\.@identifierPlus","tag.class"],["@identifierPlus","tag"],{include:"@operators"},["@(@identifier(?=[:,\\)]))","variable","@attribute"],["@(@identifier)","variable"],["@","key","@atRules"]],nestedJSBegin:[["``","delimiter.backtick"],["`",{token:"delimiter.backtick",next:"@nestedJSEnd",nextEmbedded:"text/javascript"}]],nestedJSEnd:[["`",{token:"delimiter.backtick",next:"@pop",nextEmbedded:"@pop"}]],operators:[["[<>=\\+\\-\\*\\/\\^\\|\\~]","operator"]],keyword:[["(@[\\s]*import|![\\s]*important|true|false|when|iscolor|isnumber|isstring|iskeyword|isurl|ispixel|ispercentage|isem|hue|saturation|lightness|alpha|lighten|darken|saturate|desaturate|fadein|fadeout|fade|spin|mix|round|ceil|floor|percentage)\\b","keyword"]],urldeclaration:[{include:"@strings"},[`[^)\r ]+`,"string"],["\\)",{token:"tag",next:"@pop"}]],attribute:[{include:"@nestedJSBegin"},{include:"@comments"},{include:"@strings"},{include:"@numbers"},{include:"@keyword"},["[a-zA-Z\\-]+(?=\\()","attribute.value","@attribute"],[">","operator","@pop"],["@identifier","attribute.value"],{include:"@operators"},["@(@identifier)","variable"],["[)\\}]","@brackets","@pop"],["[{}()\\[\\]>]","@brackets"],["[;]","delimiter","@pop"],["[,=:]","delimiter"],["\\s",""],[".","attribute.value"]],comments:[["\\/\\*","comment","@comment"],["\\/\\/+.*","comment"]],comment:[["\\*\\/","comment","@pop"],[".","comment"]],numbers:[["(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?",{token:"attribute.value.number",next:"@units"}],["#[0-9a-fA-F_]+(?!\\w)","attribute.value.hex"]],units:[["(em|ex|ch|rem|fr|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?","attribute.value.unit","@pop"]],strings:[['~?"',{token:"string.delimiter",next:"@stringsEndDoubleQuote"}],["~?'",{token:"string.delimiter",next:"@stringsEndQuote"}]],stringsEndDoubleQuote:[['\\\\"',"string"],['"',{token:"string.delimiter",next:"@popall"}],[".","string"]],stringsEndQuote:[["\\\\'","string"],["'",{token:"string.delimiter",next:"@popall"}],[".","string"]],atRules:[{include:"@comments"},{include:"@strings"},["[()]","delimiter"],["[\\{;]","delimiter","@pop"],[".","key"]]}};return c(p);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/lexon/lexon.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/lexon/lexon", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var n=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var i in e)n(t,i,{get:e[i],enumerable:!0})},p=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of d(e))!a.call(t,o)&&o!==i&&n(t,o,{get:()=>e[o],enumerable:!(r=s(e,o))||r.enumerable});return t};var c=t=>p(n({},"__esModule",{value:!0}),t);var k={};l(k,{conf:()=>m,language:()=>u});var m={comments:{lineComment:"COMMENT"},brackets:[["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:":",close:"."}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"`",close:"`"},{open:'"',close:'"'},{open:"'",close:"'"},{open:":",close:"."}],folding:{markers:{start:new RegExp("^\\s*(::\\s*|COMMENT\\s+)#region"),end:new RegExp("^\\s*(::\\s*|COMMENT\\s+)#endregion")}}},u={tokenPostfix:".lexon",ignoreCase:!0,keywords:["lexon","lex","clause","terms","contracts","may","pay","pays","appoints","into","to"],typeKeywords:["amount","person","key","time","date","asset","text"],operators:["less","greater","equal","le","gt","or","and","add","added","subtract","subtracted","multiply","multiplied","times","divide","divided","is","be","certified"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,"delimiter"],[/\d*\.\d*\.\d*/,"number.semver"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F]+/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"]],quoted_identifier:[[/[^\\"]+/,"identifier"],[/"/,{token:"identifier.quote",bracket:"@close",next:"@pop"}]],space_identifier_until_period:[[":","delimiter"],[" ",{token:"white",next:"@identifier_rest"}]],identifier_until_period:[{include:"@whitespace"},[":",{token:"delimiter",next:"@identifier_rest"}],[/[^\\.]+/,"identifier"],[/\./,{token:"delimiter",bracket:"@close",next:"@pop"}]],identifier_rest:[[/[^\\.]+/,"identifier"],[/\./,{token:"delimiter",bracket:"@close",next:"@pop"}]],semver:[{include:"@whitespace"},[":","delimiter"],[/\d*\.\d*\.\d*/,{token:"number.semver",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,"white"]]}};return c(k);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/liquid/liquid.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/liquid/liquid", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var p=Object.create;var a=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var h=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var f=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,i)=>(typeof require<"u"?require:t)[i]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var b=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),T=(e,t)=>{for(var i in t)a(e,i,{get:t[i],enumerable:!0})},r=(e,t,i,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of w(t))!q.call(e,o)&&o!==i&&a(e,o,{get:()=>t[o],enumerable:!(l=g(t,o))||l.enumerable});return e},d=(e,t,i)=>(r(e,t,"default"),i&&r(i,t,"default")),s=(e,t,i)=>(i=e!=null?p(h(e)):{},r(t||!e||!e.__esModule?a(i,"default",{value:e,enumerable:!0}):i,e)),k=e=>r(a({},"__esModule",{value:!0}),e);var c=b((y,u)=>{var _=s(f("vs/editor/editor.api"));u.exports=_});var $={};T($,{conf:()=>x,language:()=>S});var n={};d(n,s(c()));var m=["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"],x={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,brackets:[[""],["<",">"],["{{","}}"],["{%","%}"],["{","}"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"%",close:"%"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"<",close:">"},{open:'"',close:'"'},{open:"'",close:"'"}],onEnterRules:[{beforeText:new RegExp(`<(?!(?:${m.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),afterText:/^<\/(\w[\w\d]*)\s*>$/i,action:{indentAction:n.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(`<(?!(?:${m.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),action:{indentAction:n.languages.IndentAction.Indent}}]},S={defaultToken:"",tokenPostfix:"",builtinTags:["if","else","elseif","endif","render","assign","capture","endcapture","case","endcase","comment","endcomment","cycle","decrement","for","endfor","include","increment","layout","raw","endraw","render","tablerow","endtablerow","unless","endunless"],builtinFilters:["abs","append","at_least","at_most","capitalize","ceil","compact","date","default","divided_by","downcase","escape","escape_once","first","floor","join","json","last","lstrip","map","minus","modulo","newline_to_br","plus","prepend","remove","remove_first","replace","replace_first","reverse","round","rstrip","size","slice","sort","sort_natural","split","strip","strip_html","strip_newlines","times","truncate","truncatewords","uniq","upcase","url_decode","url_encode","where"],constants:["true","false"],operators:["==","!=",">","<",">=","<="],symbol:/[=>)/,["delimiter.html","tag.html","delimiter.html"]],[/(<)([:\w]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/(<\/)([\w\-]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[//,"delimiter.html","@pop"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/]],liquidState:[[/\{\{/,"delimiter.output.liquid"],[/\}\}/,{token:"delimiter.output.liquid",switchTo:"@$S2.$S3"}],[/\{\%/,"delimiter.tag.liquid"],[/raw\s*\%\}/,"delimiter.tag.liquid","@liquidRaw"],[/\%\}/,{token:"delimiter.tag.liquid",switchTo:"@$S2.$S3"}],{include:"liquidRoot"}],liquidRaw:[[/^(?!\{\%\s*endraw\s*\%\}).+/],[/\{\%/,"delimiter.tag.liquid"],[/@identifier/],[/\%\}/,{token:"delimiter.tag.liquid",next:"@root"}]],liquidRoot:[[/\d+(\.\d+)?/,"number.liquid"],[/"[^"]*"/,"string.liquid"],[/'[^']*'/,"string.liquid"],[/\s+/],[/@symbol/,{cases:{"@operators":"operator.liquid","@default":""}}],[/\./],[/@identifier/,{cases:{"@constants":"keyword.liquid","@builtinFilters":"predefined.liquid","@builtinTags":"predefined.liquid","@default":"variable.liquid"}}],[/[^}|%]/,"variable.liquid"]]}};return k($);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/lua/lua.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/lua/lua", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(o,e)=>{for(var t in e)s(o,t,{get:e[t],enumerable:!0})},m=(o,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of i(e))!l.call(o,n)&&n!==t&&s(o,n,{get:()=>e[n],enumerable:!(r=a(e,n))||r.enumerable});return o};var p=o=>m(s({},"__esModule",{value:!0}),o);var u={};c(u,{conf:()=>d,language:()=>g});var d={comments:{lineComment:"--",blockComment:["--[[","]]"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},g={defaultToken:"",tokenPostfix:".lua",keywords:["and","break","do","else","elseif","end","false","for","function","goto","if","in","local","nil","not","or","repeat","return","then","true","until","while"],brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"}],operators:["+","-","*","/","%","^","#","==","~=","<=",">=","<",">","=",";",":",",",".","..","..."],symbols:/[=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var R=(o,e)=>{for(var s in e)r(o,s,{get:e[s],enumerable:!0})},c=(o,e,s,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of a(e))!i.call(o,t)&&t!==s&&r(o,t,{get:()=>e[t],enumerable:!(n=E(e,t))||n.enumerable});return o};var m=o=>c(r({},"__esModule",{value:!0}),o);var N={};R(N,{conf:()=>A,language:()=>p});var A={comments:{blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"[",close:"]"},{open:"{",close:"}"},{open:"(",close:")"},{open:"(*",close:"*)"},{open:"<*",close:"*>"},{open:"'",close:"'",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]}]},p={defaultToken:"",tokenPostfix:".m3",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"}],keywords:["AND","ANY","ARRAY","AS","BEGIN","BITS","BRANDED","BY","CASE","CONST","DIV","DO","ELSE","ELSIF","END","EVAL","EXCEPT","EXCEPTION","EXIT","EXPORTS","FINALLY","FOR","FROM","GENERIC","IF","IMPORT","IN","INTERFACE","LOCK","LOOP","METHODS","MOD","MODULE","NOT","OBJECT","OF","OR","OVERRIDES","PROCEDURE","RAISE","RAISES","READONLY","RECORD","REF","REPEAT","RETURN","REVEAL","SET","THEN","TO","TRY","TYPE","TYPECASE","UNSAFE","UNTIL","UNTRACED","VALUE","VAR","WHILE","WITH"],reservedConstNames:["ABS","ADR","ADRSIZE","BITSIZE","BYTESIZE","CEILING","DEC","DISPOSE","FALSE","FIRST","FLOAT","FLOOR","INC","ISTYPE","LAST","LOOPHOLE","MAX","MIN","NARROW","NEW","NIL","NUMBER","ORD","ROUND","SUBARRAY","TRUE","TRUNC","TYPECODE","VAL"],reservedTypeNames:["ADDRESS","ANY","BOOLEAN","CARDINAL","CHAR","EXTENDED","INTEGER","LONGCARD","LONGINT","LONGREAL","MUTEX","NULL","REAL","REFANY","ROOT","TEXT"],operators:["+","-","*","/","&","^","."],relations:["=","#","<","<=",">",">=","<:",":"],delimiters:["|","..","=>",",",";",":="],symbols:/[>=<#.,:;+\-*/&^]+/,escapes:/\\(?:[\\fnrt"']|[0-7]{3})/,tokenizer:{root:[[/_\w*/,"invalid"],[/[a-zA-Z][a-zA-Z0-9_]*/,{cases:{"@keywords":{token:"keyword.$0"},"@reservedConstNames":{token:"constant.reserved.$0"},"@reservedTypeNames":{token:"type.reserved.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/[0-9]+\.[0-9]+(?:[DdEeXx][\+\-]?[0-9]+)?/,"number.float"],[/[0-9]+(?:\_[0-9a-fA-F]+)?L?/,"number"],[/@symbols/,{cases:{"@operators":"operators","@relations":"operators","@delimiters":"delimiter","@default":"invalid"}}],[/'[^\\']'/,"string.char"],[/(')(@escapes)(')/,["string.char","string.escape","string.char"]],[/'/,"invalid"],[/"([^"\\]|\\.)*$/,"invalid"],[/"/,"string.text","@text"]],text:[[/[^\\"]+/,"string.text"],[/@escapes/,"string.escape"],[/\\./,"invalid"],[/"/,"string.text","@pop"]],comment:[[/\(\*/,"comment","@push"],[/\*\)/,"comment","@pop"],[/./,"comment"]],pragma:[[/<\*/,"keyword.pragma","@push"],[/\*>/,"keyword.pragma","@pop"],[/./,"keyword.pragma"]],whitespace:[[/[ \t\r\n]+/,"white"],[/\(\*/,"comment","@comment"],[/<\*/,"keyword.pragma","@pragma"]]}};return m(N);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/markdown/markdown.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/markdown/markdown", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var o in e)s(t,o,{get:e[o],enumerable:!0})},m=(t,e,o,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of c(e))!i.call(t,n)&&n!==o&&s(t,n,{get:()=>e[n],enumerable:!(a=r(e,n))||a.enumerable});return t};var d=t=>m(s({},"__esModule",{value:!0}),t);var b={};l(b,{conf:()=>p,language:()=>g});var p={comments:{blockComment:[""]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">",notIn:["string"]}],surroundingPairs:[{open:"(",close:")"},{open:"[",close:"]"},{open:"`",close:"`"}],folding:{markers:{start:new RegExp("^\\s*"),end:new RegExp("^\\s*")}}},g={defaultToken:"",tokenPostfix:".md",control:/[\\`*_\[\]{}()#+\-\.!]/,noncontrol:/[^\\`*_\[\]{}()#+\-\.!]/,escapes:/\\(?:@control)/,jsescapes:/\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,empty:["area","base","basefont","br","col","frame","hr","img","input","isindex","link","meta","param"],tokenizer:{root:[[/^\s*\|/,"@rematch","@table_header"],[/^(\s{0,3})(#+)((?:[^\\#]|@escapes)+)((?:#+)?)/,["white","keyword","keyword","keyword"]],[/^\s*(=+|\-+)\s*$/,"keyword"],[/^\s*((\*[ ]?)+)\s*$/,"meta.separator"],[/^\s*>+/,"comment"],[/^\s*([\*\-+:]|\d+\.)\s/,"keyword"],[/^(\t|[ ]{4})[^ ].*$/,"string"],[/^\s*~~~\s*((?:\w|[\/\-#])+)?\s*$/,{token:"string",next:"@codeblock"}],[/^\s*```\s*((?:\w|[\/\-#])+).*$/,{token:"string",next:"@codeblockgh",nextEmbedded:"$1"}],[/^\s*```\s*$/,{token:"string",next:"@codeblock"}],{include:"@linecontent"}],table_header:[{include:"@table_common"},[/[^\|]+/,"keyword.table.header"]],table_body:[{include:"@table_common"},{include:"@linecontent"}],table_common:[[/\s*[\-:]+\s*/,{token:"keyword",switchTo:"table_body"}],[/^\s*\|/,"keyword.table.left"],[/^\s*[^\|]/,"@rematch","@pop"],[/^\s*$/,"@rematch","@pop"],[/\|/,{cases:{"@eos":"keyword.table.right","@default":"keyword.table.middle"}}]],codeblock:[[/^\s*~~~\s*$/,{token:"string",next:"@pop"}],[/^\s*```\s*$/,{token:"string",next:"@pop"}],[/.*$/,"variable.source"]],codeblockgh:[[/```\s*$/,{token:"string",next:"@pop",nextEmbedded:"@pop"}],[/[^`]+/,"variable.source"]],linecontent:[[/&\w+;/,"string.escape"],[/@escapes/,"escape"],[/\b__([^\\_]|@escapes|_(?!_))+__\b/,"strong"],[/\*\*([^\\*]|@escapes|\*(?!\*))+\*\*/,"strong"],[/\b_[^_]+_\b/,"emphasis"],[/\*([^\\*]|@escapes)+\*/,"emphasis"],[/`([^\\`]|@escapes)+`/,"variable"],[/\{+[^}]+\}+/,"string.target"],[/(!?\[)((?:[^\]\\]|@escapes)*)(\]\([^\)]+\))/,["string.link","","string.link"]],[/(!?\[)((?:[^\]\\]|@escapes)*)(\])/,"string.link"],{include:"html"}],html:[[/<(\w+)\/>/,"tag"],[/<(\w+)(\-|\w)*/,{cases:{"@empty":{token:"tag",next:"@tag.$1"},"@default":{token:"tag",next:"@tag.$1"}}}],[/<\/(\w+)(\-|\w)*\s*>/,{token:"tag"}],[//,"comment","@pop"],[//,"comment.html","@pop"],[/[^-]+/,"comment.content.html"],[/./,"comment.content.html"]],otherTag:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.otherTag"}],[/\/?>/,"delimiter.html","@pop"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/]],script:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.script"}],[/type/,"attribute.name","@scriptAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/(<\/)(script\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],scriptAfterType:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.scriptAfterType"}],[/=/,"delimiter","@scriptAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptAfterTypeEquals:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.scriptAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptWithCustomType:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.scriptWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptEmbedded:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInEmbeddedState.scriptEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/script/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],style:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.style"}],[/type/,"attribute.name","@styleAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/(<\/)(style\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],styleAfterType:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.styleAfterType"}],[/=/,"delimiter","@styleAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleAfterTypeEquals:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.styleAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleWithCustomType:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInSimpleState.styleWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleEmbedded:[[/<\?((php)|=)?/,{token:"@rematch",switchTo:"@phpInEmbeddedState.styleEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/style/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],phpInSimpleState:[[/<\?((php)|=)?/,"metatag.php"],[/\?>/,{token:"metatag.php",switchTo:"@$S2.$S3"}],{include:"phpRoot"}],phpInEmbeddedState:[[/<\?((php)|=)?/,"metatag.php"],[/\?>/,{token:"metatag.php",switchTo:"@$S2.$S3",nextEmbedded:"$S3"}],{include:"phpRoot"}],phpRoot:[[/[a-zA-Z_]\w*/,{cases:{"@phpKeywords":{token:"keyword.php"},"@phpCompileTimeConstants":{token:"constant.php"},"@default":"identifier.php"}}],[/[$a-zA-Z_]\w*/,{cases:{"@phpPreDefinedVariables":{token:"variable.predefined.php"},"@default":"variable.php"}}],[/[{}]/,"delimiter.bracket.php"],[/[\[\]]/,"delimiter.array.php"],[/[()]/,"delimiter.parenthesis.php"],[/[ \t\r\n]+/],[/(#|\/\/)$/,"comment.php"],[/(#|\/\/)/,"comment.php","@phpLineComment"],[/\/\*/,"comment.php","@phpComment"],[/"/,"string.php","@phpDoubleQuoteString"],[/'/,"string.php","@phpSingleQuoteString"],[/[\+\-\*\%\&\|\^\~\!\=\<\>\/\?\;\:\.\,\@]/,"delimiter.php"],[/\d*\d+[eE]([\-+]?\d+)?/,"number.float.php"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float.php"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,"number.hex.php"],[/0[0-7']*[0-7]/,"number.octal.php"],[/0[bB][0-1']*[0-1]/,"number.binary.php"],[/\d[\d']*/,"number.php"],[/\d/,"number.php"]],phpComment:[[/\*\//,"comment.php","@pop"],[/[^*]+/,"comment.php"],[/./,"comment.php"]],phpLineComment:[[/\?>/,{token:"@rematch",next:"@pop"}],[/.$/,"comment.php","@pop"],[/[^?]+$/,"comment.php","@pop"],[/[^?]+/,"comment.php"],[/./,"comment.php"]],phpDoubleQuoteString:[[/[^\\"]+/,"string.php"],[/@escapes/,"string.escape.php"],[/\\./,"string.escape.invalid.php"],[/"/,"string.php","@pop"]],phpSingleQuoteString:[[/[^\\']+/,"string.php"],[/@escapes/,"string.escape.php"],[/\\./,"string.escape.invalid.php"],[/'/,"string.php","@pop"]]},phpKeywords:["abstract","and","array","as","break","callable","case","catch","cfunction","class","clone","const","continue","declare","default","do","else","elseif","enddeclare","endfor","endforeach","endif","endswitch","endwhile","extends","false","final","for","foreach","function","global","goto","if","implements","interface","instanceof","insteadof","namespace","new","null","object","old_function","or","private","protected","public","resource","static","switch","throw","trait","try","true","use","var","while","xor","die","echo","empty","exit","eval","include","include_once","isset","list","require","require_once","return","print","unset","yield","__construct"],phpCompileTimeConstants:["__CLASS__","__DIR__","__FILE__","__LINE__","__NAMESPACE__","__METHOD__","__FUNCTION__","__TRAIT__"],phpPreDefinedVariables:["$GLOBALS","$_SERVER","$_GET","$_POST","$_FILES","$_REQUEST","$_SESSION","$_ENV","$_COOKIE","$php_errormsg","$HTTP_RAW_POST_DATA","$http_response_header","$argc","$argv"],escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/};return l(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/pla/pla.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/pla/pla", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var l=(o,e)=>{for(var n in e)s(o,n,{get:e[n],enumerable:!0})},c=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of r(e))!p.call(o,t)&&t!==n&&s(o,t,{get:()=>e[t],enumerable:!(i=a(e,t))||i.enumerable});return o};var d=o=>c(s({},"__esModule",{value:!0}),o);var u={};l(u,{conf:()=>k,language:()=>m});var k={comments:{lineComment:"#"},brackets:[["[","]"],["<",">"],["(",")"]],autoClosingPairs:[{open:"[",close:"]"},{open:"<",close:">"},{open:"(",close:")"}],surroundingPairs:[{open:"[",close:"]"},{open:"<",close:">"},{open:"(",close:")"}]},m={defaultToken:"",tokenPostfix:".pla",brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"<",close:">",token:"delimiter.angle"},{open:"(",close:")",token:"delimiter.parenthesis"}],keywords:[".i",".o",".mv",".ilb",".ob",".label",".type",".phase",".pair",".symbolic",".symbolic-output",".kiss",".p",".e",".end"],comment:/#.*$/,identifier:/[a-zA-Z]+[a-zA-Z0-9_\-]*/,plaContent:/[01\-~\|]+/,tokenizer:{root:[{include:"@whitespace"},[/@comment/,"comment"],[/\.([a-zA-Z_\-]+)/,{cases:{"@eos":{token:"keyword.$1"},"@keywords":{cases:{".type":{token:"keyword.$1",next:"@type"},"@default":{token:"keyword.$1",next:"@keywordArg"}}},"@default":{token:"keyword.$1"}}}],[/@identifier/,"identifier"],[/@plaContent/,"string"]],whitespace:[[/[ \t\r\n]+/,""]],type:[{include:"@whitespace"},[/\w+/,{token:"type",next:"@pop"}]],keywordArg:[[/[ \t\r\n]+/,{cases:{"@eos":{token:"",next:"@pop"},"@default":""}}],[/@comment/,"comment","@pop"],[/[<>()\[\]]/,{cases:{"@eos":{token:"@brackets",next:"@pop"},"@default":"@brackets"}}],[/\-?\d+/,{cases:{"@eos":{token:"number",next:"@pop"},"@default":"number"}}],[/@identifier/,{cases:{"@eos":{token:"identifier",next:"@pop"},"@default":"identifier"}}],[/[;=]/,{cases:{"@eos":{token:"delimiter",next:"@pop"},"@default":"delimiter"}}]]}};return d(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/postiats/postiats.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/postiats/postiats", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var i=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var p=(t,e)=>{for(var o in e)i(t,o,{get:e[o],enumerable:!0})},l=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of s(e))!c.call(t,n)&&n!==o&&i(t,n,{get:()=>e[n],enumerable:!(r=a(e,n))||r.enumerable});return t};var d=t=>l(i({},"__esModule",{value:!0}),t);var g={};p(g,{conf:()=>m,language:()=>x});var m={comments:{lineComment:"//",blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]}]},x={tokenPostfix:".pats",defaultToken:"invalid",keywords:["abstype","abst0ype","absprop","absview","absvtype","absviewtype","absvt0ype","absviewt0ype","as","and","assume","begin","classdec","datasort","datatype","dataprop","dataview","datavtype","dataviewtype","do","end","extern","extype","extvar","exception","fn","fnx","fun","prfn","prfun","praxi","castfn","if","then","else","ifcase","in","infix","infixl","infixr","prefix","postfix","implmnt","implement","primplmnt","primplement","import","let","local","macdef","macrodef","nonfix","symelim","symintr","overload","of","op","rec","sif","scase","sortdef","sta","stacst","stadef","static","staload","dynload","try","tkindef","typedef","propdef","viewdef","vtypedef","viewtypedef","prval","var","prvar","when","where","with","withtype","withprop","withview","withvtype","withviewtype"],keywords_dlr:["$delay","$ldelay","$arrpsz","$arrptrsize","$d2ctype","$effmask","$effmask_ntm","$effmask_exn","$effmask_ref","$effmask_wrt","$effmask_all","$extern","$extkind","$extype","$extype_struct","$extval","$extfcall","$extmcall","$literal","$myfilename","$mylocation","$myfunction","$lst","$lst_t","$lst_vt","$list","$list_t","$list_vt","$rec","$rec_t","$rec_vt","$record","$record_t","$record_vt","$tup","$tup_t","$tup_vt","$tuple","$tuple_t","$tuple_vt","$break","$continue","$raise","$showtype","$vcopyenv_v","$vcopyenv_vt","$tempenver","$solver_assert","$solver_verify"],keywords_srp:["#if","#ifdef","#ifndef","#then","#elif","#elifdef","#elifndef","#else","#endif","#error","#prerr","#print","#assert","#undef","#define","#include","#require","#pragma","#codegen2","#codegen3"],irregular_keyword_list:["val+","val-","val","case+","case-","case","addr@","addr","fold@","free@","fix@","fix","lam@","lam","llam@","llam","viewt@ype+","viewt@ype-","viewt@ype","viewtype+","viewtype-","viewtype","view+","view-","view@","view","type+","type-","type","vtype+","vtype-","vtype","vt@ype+","vt@ype-","vt@ype","viewt@ype+","viewt@ype-","viewt@ype","viewtype+","viewtype-","viewtype","prop+","prop-","prop","type+","type-","type","t@ype","t@ype+","t@ype-","abst@ype","abstype","absviewt@ype","absvt@ype","for*","for","while*","while"],keywords_types:["bool","double","byte","int","short","char","void","unit","long","float","string","strptr"],keywords_effects:["0","fun","clo","prf","funclo","cloptr","cloref","ref","ntm","1"],operators:["@","!","|","`",":","$",".","=","#","~","..","...","=>","=<>","=/=>","=>>","=/=>>","<",">","><",".<",">.",".<>.","->","-<>"],brackets:[{open:",(",close:")",token:"delimiter.parenthesis"},{open:"`(",close:")",token:"delimiter.parenthesis"},{open:"%(",close:")",token:"delimiter.parenthesis"},{open:"'(",close:")",token:"delimiter.parenthesis"},{open:"'{",close:"}",token:"delimiter.parenthesis"},{open:"@(",close:")",token:"delimiter.parenthesis"},{open:"@{",close:"}",token:"delimiter.brace"},{open:"@[",close:"]",token:"delimiter.square"},{open:"#[",close:"]",token:"delimiter.square"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],symbols:/[=>]/,digit:/[0-9]/,digitseq0:/@digit*/,xdigit:/[0-9A-Za-z]/,xdigitseq0:/@xdigit*/,INTSP:/[lLuU]/,FLOATSP:/[fFlL]/,fexponent:/[eE][+-]?[0-9]+/,fexponent_bin:/[pP][+-]?[0-9]+/,deciexp:/\.[0-9]*@fexponent?/,hexiexp:/\.[0-9a-zA-Z]*@fexponent_bin?/,irregular_keywords:/val[+-]?|case[+-]?|addr\@?|fold\@|free\@|fix\@?|lam\@?|llam\@?|prop[+-]?|type[+-]?|view[+-@]?|viewt@?ype[+-]?|t@?ype[+-]?|v(iew)?t@?ype[+-]?|abst@?ype|absv(iew)?t@?ype|for\*?|while\*?/,ESCHAR:/[ntvbrfa\\\?'"\(\[\{]/,start:"root",tokenizer:{root:[{regex:/[ \t\r\n]+/,action:{token:""}},{regex:/\(\*\)/,action:{token:"invalid"}},{regex:/\(\*/,action:{token:"comment",next:"lexing_COMMENT_block_ml"}},{regex:/\(/,action:"@brackets"},{regex:/\)/,action:"@brackets"},{regex:/\[/,action:"@brackets"},{regex:/\]/,action:"@brackets"},{regex:/\{/,action:"@brackets"},{regex:/\}/,action:"@brackets"},{regex:/,\(/,action:"@brackets"},{regex:/,/,action:{token:"delimiter.comma"}},{regex:/;/,action:{token:"delimiter.semicolon"}},{regex:/@\(/,action:"@brackets"},{regex:/@\[/,action:"@brackets"},{regex:/@\{/,action:"@brackets"},{regex:/:/,action:{token:"@rematch",next:"@pop"}}],lexing_EXTCODE:[{regex:/^%}/,action:{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}},{regex:/[^%]+/,action:""}],lexing_DQUOTE:[{regex:/"/,action:{token:"string.quote",next:"@pop"}},{regex:/(\{\$)(@IDENTFST@IDENTRST*)(\})/,action:[{token:"string.escape"},{token:"identifier"},{token:"string.escape"}]},{regex:/\\$/,action:{token:"string.escape"}},{regex:/\\(@ESCHAR|[xX]@xdigit+|@digit+)/,action:{token:"string.escape"}},{regex:/[^\\"]+/,action:{token:"string"}}]}};return d(g);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/powerquery/powerquery.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/powerquery/powerquery", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var i=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var T=(t,e)=>{for(var n in e)i(t,n,{get:e[n],enumerable:!0})},m=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of s(e))!l.call(t,a)&&a!==n&&i(t,a,{get:()=>e[a],enumerable:!(o=r(e,a))||o.enumerable});return t};var u=t=>m(i({},"__esModule",{value:!0}),t);var b={};T(b,{conf:()=>d,language:()=>c});var d={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["[","]"],["(",")"],["{","}"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment","identifier"]},{open:"[",close:"]",notIn:["string","comment","identifier"]},{open:"(",close:")",notIn:["string","comment","identifier"]},{open:"{",close:"}",notIn:["string","comment","identifier"]}]},c={defaultToken:"",tokenPostfix:".pq",ignoreCase:!1,brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"{",close:"}",token:"delimiter.brackets"},{open:"(",close:")",token:"delimiter.parenthesis"}],operatorKeywords:["and","not","or"],keywords:["as","each","else","error","false","if","in","is","let","meta","otherwise","section","shared","then","true","try","type"],constructors:["#binary","#date","#datetime","#datetimezone","#duration","#table","#time"],constants:["#infinity","#nan","#sections","#shared"],typeKeywords:["action","any","anynonnull","none","null","logical","number","time","date","datetime","datetimezone","duration","text","binary","list","record","table","function"],builtinFunctions:["Access.Database","Action.Return","Action.Sequence","Action.Try","ActiveDirectory.Domains","AdoDotNet.DataSource","AdoDotNet.Query","AdobeAnalytics.Cubes","AnalysisServices.Database","AnalysisServices.Databases","AzureStorage.BlobContents","AzureStorage.Blobs","AzureStorage.Tables","Binary.Buffer","Binary.Combine","Binary.Compress","Binary.Decompress","Binary.End","Binary.From","Binary.FromList","Binary.FromText","Binary.InferContentType","Binary.Length","Binary.ToList","Binary.ToText","BinaryFormat.7BitEncodedSignedInteger","BinaryFormat.7BitEncodedUnsignedInteger","BinaryFormat.Binary","BinaryFormat.Byte","BinaryFormat.ByteOrder","BinaryFormat.Choice","BinaryFormat.Decimal","BinaryFormat.Double","BinaryFormat.Group","BinaryFormat.Length","BinaryFormat.List","BinaryFormat.Null","BinaryFormat.Record","BinaryFormat.SignedInteger16","BinaryFormat.SignedInteger32","BinaryFormat.SignedInteger64","BinaryFormat.Single","BinaryFormat.Text","BinaryFormat.Transform","BinaryFormat.UnsignedInteger16","BinaryFormat.UnsignedInteger32","BinaryFormat.UnsignedInteger64","Byte.From","Character.FromNumber","Character.ToNumber","Combiner.CombineTextByDelimiter","Combiner.CombineTextByEachDelimiter","Combiner.CombineTextByLengths","Combiner.CombineTextByPositions","Combiner.CombineTextByRanges","Comparer.Equals","Comparer.FromCulture","Comparer.Ordinal","Comparer.OrdinalIgnoreCase","Csv.Document","Cube.AddAndExpandDimensionColumn","Cube.AddMeasureColumn","Cube.ApplyParameter","Cube.AttributeMemberId","Cube.AttributeMemberProperty","Cube.CollapseAndRemoveColumns","Cube.Dimensions","Cube.DisplayFolders","Cube.Measures","Cube.Parameters","Cube.Properties","Cube.PropertyKey","Cube.ReplaceDimensions","Cube.Transform","Currency.From","DB2.Database","Date.AddDays","Date.AddMonths","Date.AddQuarters","Date.AddWeeks","Date.AddYears","Date.Day","Date.DayOfWeek","Date.DayOfWeekName","Date.DayOfYear","Date.DaysInMonth","Date.EndOfDay","Date.EndOfMonth","Date.EndOfQuarter","Date.EndOfWeek","Date.EndOfYear","Date.From","Date.FromText","Date.IsInCurrentDay","Date.IsInCurrentMonth","Date.IsInCurrentQuarter","Date.IsInCurrentWeek","Date.IsInCurrentYear","Date.IsInNextDay","Date.IsInNextMonth","Date.IsInNextNDays","Date.IsInNextNMonths","Date.IsInNextNQuarters","Date.IsInNextNWeeks","Date.IsInNextNYears","Date.IsInNextQuarter","Date.IsInNextWeek","Date.IsInNextYear","Date.IsInPreviousDay","Date.IsInPreviousMonth","Date.IsInPreviousNDays","Date.IsInPreviousNMonths","Date.IsInPreviousNQuarters","Date.IsInPreviousNWeeks","Date.IsInPreviousNYears","Date.IsInPreviousQuarter","Date.IsInPreviousWeek","Date.IsInPreviousYear","Date.IsInYearToDate","Date.IsLeapYear","Date.Month","Date.MonthName","Date.QuarterOfYear","Date.StartOfDay","Date.StartOfMonth","Date.StartOfQuarter","Date.StartOfWeek","Date.StartOfYear","Date.ToRecord","Date.ToText","Date.WeekOfMonth","Date.WeekOfYear","Date.Year","DateTime.AddZone","DateTime.Date","DateTime.FixedLocalNow","DateTime.From","DateTime.FromFileTime","DateTime.FromText","DateTime.IsInCurrentHour","DateTime.IsInCurrentMinute","DateTime.IsInCurrentSecond","DateTime.IsInNextHour","DateTime.IsInNextMinute","DateTime.IsInNextNHours","DateTime.IsInNextNMinutes","DateTime.IsInNextNSeconds","DateTime.IsInNextSecond","DateTime.IsInPreviousHour","DateTime.IsInPreviousMinute","DateTime.IsInPreviousNHours","DateTime.IsInPreviousNMinutes","DateTime.IsInPreviousNSeconds","DateTime.IsInPreviousSecond","DateTime.LocalNow","DateTime.Time","DateTime.ToRecord","DateTime.ToText","DateTimeZone.FixedLocalNow","DateTimeZone.FixedUtcNow","DateTimeZone.From","DateTimeZone.FromFileTime","DateTimeZone.FromText","DateTimeZone.LocalNow","DateTimeZone.RemoveZone","DateTimeZone.SwitchZone","DateTimeZone.ToLocal","DateTimeZone.ToRecord","DateTimeZone.ToText","DateTimeZone.ToUtc","DateTimeZone.UtcNow","DateTimeZone.ZoneHours","DateTimeZone.ZoneMinutes","Decimal.From","Diagnostics.ActivityId","Diagnostics.Trace","DirectQueryCapabilities.From","Double.From","Duration.Days","Duration.From","Duration.FromText","Duration.Hours","Duration.Minutes","Duration.Seconds","Duration.ToRecord","Duration.ToText","Duration.TotalDays","Duration.TotalHours","Duration.TotalMinutes","Duration.TotalSeconds","Embedded.Value","Error.Record","Excel.CurrentWorkbook","Excel.Workbook","Exchange.Contents","Expression.Constant","Expression.Evaluate","Expression.Identifier","Facebook.Graph","File.Contents","Folder.Contents","Folder.Files","Function.From","Function.Invoke","Function.InvokeAfter","Function.IsDataSource","GoogleAnalytics.Accounts","Guid.From","HdInsight.Containers","HdInsight.Contents","HdInsight.Files","Hdfs.Contents","Hdfs.Files","Informix.Database","Int16.From","Int32.From","Int64.From","Int8.From","ItemExpression.From","Json.Document","Json.FromValue","Lines.FromBinary","Lines.FromText","Lines.ToBinary","Lines.ToText","List.Accumulate","List.AllTrue","List.Alternate","List.AnyTrue","List.Average","List.Buffer","List.Combine","List.Contains","List.ContainsAll","List.ContainsAny","List.Count","List.Covariance","List.DateTimeZones","List.DateTimes","List.Dates","List.Difference","List.Distinct","List.Durations","List.FindText","List.First","List.FirstN","List.Generate","List.InsertRange","List.Intersect","List.IsDistinct","List.IsEmpty","List.Last","List.LastN","List.MatchesAll","List.MatchesAny","List.Max","List.MaxN","List.Median","List.Min","List.MinN","List.Mode","List.Modes","List.NonNullCount","List.Numbers","List.PositionOf","List.PositionOfAny","List.Positions","List.Product","List.Random","List.Range","List.RemoveFirstN","List.RemoveItems","List.RemoveLastN","List.RemoveMatchingItems","List.RemoveNulls","List.RemoveRange","List.Repeat","List.ReplaceMatchingItems","List.ReplaceRange","List.ReplaceValue","List.Reverse","List.Select","List.Single","List.SingleOrDefault","List.Skip","List.Sort","List.StandardDeviation","List.Sum","List.Times","List.Transform","List.TransformMany","List.Union","List.Zip","Logical.From","Logical.FromText","Logical.ToText","MQ.Queue","MySQL.Database","Number.Abs","Number.Acos","Number.Asin","Number.Atan","Number.Atan2","Number.BitwiseAnd","Number.BitwiseNot","Number.BitwiseOr","Number.BitwiseShiftLeft","Number.BitwiseShiftRight","Number.BitwiseXor","Number.Combinations","Number.Cos","Number.Cosh","Number.Exp","Number.Factorial","Number.From","Number.FromText","Number.IntegerDivide","Number.IsEven","Number.IsNaN","Number.IsOdd","Number.Ln","Number.Log","Number.Log10","Number.Mod","Number.Permutations","Number.Power","Number.Random","Number.RandomBetween","Number.Round","Number.RoundAwayFromZero","Number.RoundDown","Number.RoundTowardZero","Number.RoundUp","Number.Sign","Number.Sin","Number.Sinh","Number.Sqrt","Number.Tan","Number.Tanh","Number.ToText","OData.Feed","Odbc.DataSource","Odbc.Query","OleDb.DataSource","OleDb.Query","Oracle.Database","Percentage.From","PostgreSQL.Database","RData.FromBinary","Record.AddField","Record.Combine","Record.Field","Record.FieldCount","Record.FieldNames","Record.FieldOrDefault","Record.FieldValues","Record.FromList","Record.FromTable","Record.HasFields","Record.RemoveFields","Record.RenameFields","Record.ReorderFields","Record.SelectFields","Record.ToList","Record.ToTable","Record.TransformFields","Replacer.ReplaceText","Replacer.ReplaceValue","RowExpression.Column","RowExpression.From","Salesforce.Data","Salesforce.Reports","SapBusinessWarehouse.Cubes","SapHana.Database","SharePoint.Contents","SharePoint.Files","SharePoint.Tables","Single.From","Soda.Feed","Splitter.SplitByNothing","Splitter.SplitTextByAnyDelimiter","Splitter.SplitTextByDelimiter","Splitter.SplitTextByEachDelimiter","Splitter.SplitTextByLengths","Splitter.SplitTextByPositions","Splitter.SplitTextByRanges","Splitter.SplitTextByRepeatedLengths","Splitter.SplitTextByWhitespace","Sql.Database","Sql.Databases","SqlExpression.SchemaFrom","SqlExpression.ToExpression","Sybase.Database","Table.AddColumn","Table.AddIndexColumn","Table.AddJoinColumn","Table.AddKey","Table.AggregateTableColumn","Table.AlternateRows","Table.Buffer","Table.Column","Table.ColumnCount","Table.ColumnNames","Table.ColumnsOfType","Table.Combine","Table.CombineColumns","Table.Contains","Table.ContainsAll","Table.ContainsAny","Table.DemoteHeaders","Table.Distinct","Table.DuplicateColumn","Table.ExpandListColumn","Table.ExpandRecordColumn","Table.ExpandTableColumn","Table.FillDown","Table.FillUp","Table.FilterWithDataTable","Table.FindText","Table.First","Table.FirstN","Table.FirstValue","Table.FromColumns","Table.FromList","Table.FromPartitions","Table.FromRecords","Table.FromRows","Table.FromValue","Table.Group","Table.HasColumns","Table.InsertRows","Table.IsDistinct","Table.IsEmpty","Table.Join","Table.Keys","Table.Last","Table.LastN","Table.MatchesAllRows","Table.MatchesAnyRows","Table.Max","Table.MaxN","Table.Min","Table.MinN","Table.NestedJoin","Table.Partition","Table.PartitionValues","Table.Pivot","Table.PositionOf","Table.PositionOfAny","Table.PrefixColumns","Table.Profile","Table.PromoteHeaders","Table.Range","Table.RemoveColumns","Table.RemoveFirstN","Table.RemoveLastN","Table.RemoveMatchingRows","Table.RemoveRows","Table.RemoveRowsWithErrors","Table.RenameColumns","Table.ReorderColumns","Table.Repeat","Table.ReplaceErrorValues","Table.ReplaceKeys","Table.ReplaceMatchingRows","Table.ReplaceRelationshipIdentity","Table.ReplaceRows","Table.ReplaceValue","Table.ReverseRows","Table.RowCount","Table.Schema","Table.SelectColumns","Table.SelectRows","Table.SelectRowsWithErrors","Table.SingleRow","Table.Skip","Table.Sort","Table.SplitColumn","Table.ToColumns","Table.ToList","Table.ToRecords","Table.ToRows","Table.TransformColumnNames","Table.TransformColumnTypes","Table.TransformColumns","Table.TransformRows","Table.Transpose","Table.Unpivot","Table.UnpivotOtherColumns","Table.View","Table.ViewFunction","TableAction.DeleteRows","TableAction.InsertRows","TableAction.UpdateRows","Tables.GetRelationships","Teradata.Database","Text.AfterDelimiter","Text.At","Text.BeforeDelimiter","Text.BetweenDelimiters","Text.Clean","Text.Combine","Text.Contains","Text.End","Text.EndsWith","Text.Format","Text.From","Text.FromBinary","Text.Insert","Text.Length","Text.Lower","Text.Middle","Text.NewGuid","Text.PadEnd","Text.PadStart","Text.PositionOf","Text.PositionOfAny","Text.Proper","Text.Range","Text.Remove","Text.RemoveRange","Text.Repeat","Text.Replace","Text.ReplaceRange","Text.Select","Text.Split","Text.SplitAny","Text.Start","Text.StartsWith","Text.ToBinary","Text.ToList","Text.Trim","Text.TrimEnd","Text.TrimStart","Text.Upper","Time.EndOfHour","Time.From","Time.FromText","Time.Hour","Time.Minute","Time.Second","Time.StartOfHour","Time.ToRecord","Time.ToText","Type.AddTableKey","Type.ClosedRecord","Type.Facets","Type.ForFunction","Type.ForRecord","Type.FunctionParameters","Type.FunctionRequiredParameters","Type.FunctionReturn","Type.Is","Type.IsNullable","Type.IsOpenRecord","Type.ListItem","Type.NonNullable","Type.OpenRecord","Type.RecordFields","Type.ReplaceFacets","Type.ReplaceTableKeys","Type.TableColumn","Type.TableKeys","Type.TableRow","Type.TableSchema","Type.Union","Uri.BuildQueryString","Uri.Combine","Uri.EscapeDataString","Uri.Parts","Value.Add","Value.As","Value.Compare","Value.Divide","Value.Equals","Value.Firewall","Value.FromText","Value.Is","Value.Metadata","Value.Multiply","Value.NativeQuery","Value.NullableEquals","Value.RemoveMetadata","Value.ReplaceMetadata","Value.ReplaceType","Value.Subtract","Value.Type","ValueAction.NativeStatement","ValueAction.Replace","Variable.Value","Web.Contents","Web.Page","WebAction.Request","Xml.Document","Xml.Tables"],builtinConstants:["BinaryEncoding.Base64","BinaryEncoding.Hex","BinaryOccurrence.Optional","BinaryOccurrence.Repeating","BinaryOccurrence.Required","ByteOrder.BigEndian","ByteOrder.LittleEndian","Compression.Deflate","Compression.GZip","CsvStyle.QuoteAfterDelimiter","CsvStyle.QuoteAlways","Culture.Current","Day.Friday","Day.Monday","Day.Saturday","Day.Sunday","Day.Thursday","Day.Tuesday","Day.Wednesday","ExtraValues.Error","ExtraValues.Ignore","ExtraValues.List","GroupKind.Global","GroupKind.Local","JoinAlgorithm.Dynamic","JoinAlgorithm.LeftHash","JoinAlgorithm.LeftIndex","JoinAlgorithm.PairwiseHash","JoinAlgorithm.RightHash","JoinAlgorithm.RightIndex","JoinAlgorithm.SortMerge","JoinKind.FullOuter","JoinKind.Inner","JoinKind.LeftAnti","JoinKind.LeftOuter","JoinKind.RightAnti","JoinKind.RightOuter","JoinSide.Left","JoinSide.Right","MissingField.Error","MissingField.Ignore","MissingField.UseNull","Number.E","Number.Epsilon","Number.NaN","Number.NegativeInfinity","Number.PI","Number.PositiveInfinity","Occurrence.All","Occurrence.First","Occurrence.Last","Occurrence.Optional","Occurrence.Repeating","Occurrence.Required","Order.Ascending","Order.Descending","Precision.Decimal","Precision.Double","QuoteStyle.Csv","QuoteStyle.None","RelativePosition.FromEnd","RelativePosition.FromStart","RoundingMode.AwayFromZero","RoundingMode.Down","RoundingMode.ToEven","RoundingMode.TowardZero","RoundingMode.Up","SapHanaDistribution.All","SapHanaDistribution.Connection","SapHanaDistribution.Off","SapHanaDistribution.Statement","SapHanaRangeOperator.Equals","SapHanaRangeOperator.GreaterThan","SapHanaRangeOperator.GreaterThanOrEquals","SapHanaRangeOperator.LessThan","SapHanaRangeOperator.LessThanOrEquals","SapHanaRangeOperator.NotEquals","TextEncoding.Ascii","TextEncoding.BigEndianUnicode","TextEncoding.Unicode","TextEncoding.Utf16","TextEncoding.Utf8","TextEncoding.Windows","TraceLevel.Critical","TraceLevel.Error","TraceLevel.Information","TraceLevel.Verbose","TraceLevel.Warning","WebMethod.Delete","WebMethod.Get","WebMethod.Head","WebMethod.Patch","WebMethod.Post","WebMethod.Put"],builtinTypes:["Action.Type","Any.Type","Binary.Type","BinaryEncoding.Type","BinaryOccurrence.Type","Byte.Type","ByteOrder.Type","Character.Type","Compression.Type","CsvStyle.Type","Currency.Type","Date.Type","DateTime.Type","DateTimeZone.Type","Day.Type","Decimal.Type","Double.Type","Duration.Type","ExtraValues.Type","Function.Type","GroupKind.Type","Guid.Type","Int16.Type","Int32.Type","Int64.Type","Int8.Type","JoinAlgorithm.Type","JoinKind.Type","JoinSide.Type","List.Type","Logical.Type","MissingField.Type","None.Type","Null.Type","Number.Type","Occurrence.Type","Order.Type","Password.Type","Percentage.Type","Precision.Type","QuoteStyle.Type","Record.Type","RelativePosition.Type","RoundingMode.Type","SapHanaDistribution.Type","SapHanaRangeOperator.Type","Single.Type","Table.Type","Text.Type","TextEncoding.Type","Time.Type","TraceLevel.Type","Type.Type","Uri.Type","WebMethod.Type"],tokenizer:{root:[[/#"[\w \.]+"/,"identifier.quote"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F]+/,"number.hex"],[/\d+([eE][\-+]?\d+)?/,"number"],[/(#?[a-z]+)\b/,{cases:{"@typeKeywords":"type","@keywords":"keyword","@constants":"constant","@constructors":"constructor","@operatorKeywords":"operators","@default":"identifier"}}],[/\b([A-Z][a-zA-Z0-9]+\.Type)\b/,{cases:{"@builtinTypes":"type","@default":"identifier"}}],[/\b([A-Z][a-zA-Z0-9]+\.[A-Z][a-zA-Z0-9]+)\b/,{cases:{"@builtinFunctions":"keyword.function","@builtinConstants":"constant","@default":"identifier"}}],[/\b([a-zA-Z_][\w\.]*)\b/,"identifier"],{include:"@whitespace"},{include:"@comments"},{include:"@strings"},[/[{}()\[\]]/,"@brackets"],[/([=\+<>\-\*&@\?\/!])|([<>]=)|(<>)|(=>)|(\.\.\.)|(\.\.)/,"operators"],[/[,;]/,"delimiter"]],whitespace:[[/\s+/,"white"]],comments:[["\\/\\*","comment","@comment"],["\\/\\/+.*","comment"]],comment:[["\\*\\/","comment","@pop"],[".","comment"]],strings:[['"',"string","@string"]],string:[['""',"string.escape"],['"',"string","@pop"],[".","string"]]}};return u(b);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/powershell/powershell.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/powershell/powershell", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(n,e)=>{for(var t in e)o(n,t,{get:e[t],enumerable:!0})},g=(n,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of i(e))!l.call(n,s)&&s!==t&&o(n,s,{get:()=>e[s],enumerable:!(a=r(e,s))||a.enumerable});return n};var p=n=>g(o({},"__esModule",{value:!0}),n);var u={};c(u,{conf:()=>d,language:()=>m});var d={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\#%\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"#",blockComment:["<#","#>"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*#region\\b"),end:new RegExp("^\\s*#endregion\\b")}}},m={defaultToken:"",ignoreCase:!0,tokenPostfix:".ps1",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.square",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"}],keywords:["begin","break","catch","class","continue","data","define","do","dynamicparam","else","elseif","end","exit","filter","finally","for","foreach","from","function","if","in","param","process","return","switch","throw","trap","try","until","using","var","while","workflow","parallel","sequence","inlinescript","configuration"],helpKeywords:/SYNOPSIS|DESCRIPTION|PARAMETER|EXAMPLE|INPUTS|OUTPUTS|NOTES|LINK|COMPONENT|ROLE|FUNCTIONALITY|FORWARDHELPTARGETNAME|FORWARDHELPCATEGORY|REMOTEHELPRUNSPACE|EXTERNALHELP/,symbols:/[=>/,"comment","@pop"],[/(\.)(@helpKeywords)(?!\w)/,{token:"comment.keyword.$2"}],[/[\.#]/,"comment"]]}};return p(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/protobuf/protobuf.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/protobuf/protobuf", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var p=(t,e)=>{for(var i in e)o(t,i,{get:e[i],enumerable:!0})},d=(t,e,i,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of c(e))!a.call(t,n)&&n!==i&&o(t,n,{get:()=>e[n],enumerable:!(s=r(e,n))||s.enumerable});return t};var l=t=>d(o({},"__esModule",{value:!0}),t);var m={};p(m,{conf:()=>u,language:()=>f});var k=["true","false"],u={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:'"',close:'"'},{open:"'",close:"'"}],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string"]}],autoCloseBefore:`.,=}])>' `,indentationRules:{increaseIndentPattern:new RegExp("^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$"),decreaseIndentPattern:new RegExp("^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$")}},f={defaultToken:"",tokenPostfix:".proto",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],symbols:/[=>/,{token:"@brackets",bracket:"@close",switchTo:"identifier"}]],field:[{include:"@whitespace"},["group",{cases:{"$S2==proto2":{token:"keyword",switchTo:"@groupDecl.$S2"}}}],[/(@identifier)(\s*)(=)/,["identifier","white",{token:"delimiter",next:"@pop"}]],[/@fullIdentifier|\./,{cases:{"@builtinTypes":"keyword","@default":"type.identifier"}}]],groupDecl:[{include:"@whitespace"},[/@identifier/,"identifier"],["=","operator"],[/{/,{token:"@brackets",bracket:"@open",switchTo:"@messageBody.$S2"}],{include:"@constant"}],type:[{include:"@whitespace"},[/@identifier/,"type.identifier","@pop"],[/./,"delimiter"]],identifier:[{include:"@whitespace"},[/@identifier/,"identifier","@pop"]],serviceDecl:[{include:"@whitespace"},[/@identifier/,"identifier"],[/{/,{token:"@brackets",bracket:"@open",switchTo:"@serviceBody.$S2"}]],serviceBody:[{include:"@whitespace"},{include:"@constant"},[/;/,"delimiter"],[/option\b/,"keyword","@option.$S2"],[/rpc\b/,"keyword","@rpc.$S2"],[/\[/,{token:"@brackets",bracket:"@open",next:"@options.$S2"}],[/}/,{token:"@brackets",bracket:"@close",next:"@pop"}]],rpc:[{include:"@whitespace"},[/@identifier/,"identifier"],[/\(/,{token:"@brackets",bracket:"@open",switchTo:"@request.$S2"}],[/{/,{token:"@brackets",bracket:"@open",next:"@methodOptions.$S2"}],[/;/,"delimiter","@pop"]],request:[{include:"@whitespace"},[/@messageType/,{cases:{stream:{token:"keyword",next:"@type.$S2"},"@default":"type.identifier"}}],[/\)/,{token:"@brackets",bracket:"@close",switchTo:"@returns.$S2"}]],returns:[{include:"@whitespace"},[/returns\b/,"keyword"],[/\(/,{token:"@brackets",bracket:"@open",switchTo:"@response.$S2"}]],response:[{include:"@whitespace"},[/@messageType/,{cases:{stream:{token:"keyword",next:"@type.$S2"},"@default":"type.identifier"}}],[/\)/,{token:"@brackets",bracket:"@close",switchTo:"@rpc.$S2"}]],methodOptions:[{include:"@whitespace"},{include:"@constant"},[/;/,"delimiter"],["option","keyword"],[/@optionName/,"annotation"],[/[()]/,"annotation.brackets"],[/=/,"operator"],[/}/,{token:"@brackets",bracket:"@close",next:"@pop"}]],comment:[[/[^\/*]+/,"comment"],[/\/\*/,"comment","@push"],["\\*/","comment","@pop"],[/[\/*]/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",bracket:"@close",next:"@pop"}]],stringSingle:[[/[^\\']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/'/,{token:"string.quote",bracket:"@close",next:"@pop"}]],constant:[["@boolLit","keyword.constant"],["@hexLit","number.hex"],["@octalLit","number.octal"],["@decimalLit","number"],["@floatLit","number.float"],[/("([^"\\]|\\.)*|'([^'\\]|\\.)*)$/,"string.invalid"],[/"/,{token:"string.quote",bracket:"@open",next:"@string"}],[/'/,{token:"string.quote",bracket:"@open",next:"@stringSingle"}],[/{/,{token:"@brackets",bracket:"@open",next:"@prototext"}],[/identifier/,"identifier"]],whitespace:[[/[ \t\r\n]+/,"white"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],prototext:[{include:"@whitespace"},{include:"@constant"},[/@identifier/,"identifier"],[/[:;]/,"delimiter"],[/}/,{token:"@brackets",bracket:"@close",next:"@pop"}]]}};return l(m);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/pug/pug.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/pug/pug", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var a=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var r=Object.prototype.hasOwnProperty;var p=(t,e)=>{for(var o in e)a(t,o,{get:e[o],enumerable:!0})},c=(t,e,o,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of l(e))!r.call(t,n)&&n!==o&&a(t,n,{get:()=>e[n],enumerable:!(s=i(e,n))||s.enumerable});return t};var d=t=>c(a({},"__esModule",{value:!0}),t);var g={};p(g,{conf:()=>m,language:()=>u});var m={comments:{lineComment:"//"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"'",close:"'",notIn:["string","comment"]},{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]}],folding:{offSide:!0}},u={defaultToken:"",tokenPostfix:".pug",ignoreCase:!0,brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"}],keywords:["append","block","case","default","doctype","each","else","extends","for","if","in","include","mixin","typeof","unless","var","when"],tags:["a","abbr","acronym","address","area","article","aside","audio","b","base","basefont","bdi","bdo","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","command","datalist","dd","del","details","dfn","div","dl","dt","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","keygen","kbd","label","li","link","map","mark","menu","meta","meter","nav","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strike","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","tracks","tt","u","ul","video","wbr"],symbols:/[\+\-\*\%\&\|\!\=\/\.\,\:]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^(\s*)([a-zA-Z_-][\w-]*)/,{cases:{"$2@tags":{cases:{"@eos":["","tag"],"@default":["",{token:"tag",next:"@tag.$1"}]}},"$2@keywords":["",{token:"keyword.$2"}],"@default":["",""]}}],[/^(\s*)(#[a-zA-Z_-][\w-]*)/,{cases:{"@eos":["","tag.id"],"@default":["",{token:"tag.id",next:"@tag.$1"}]}}],[/^(\s*)(\.[a-zA-Z_-][\w-]*)/,{cases:{"@eos":["","tag.class"],"@default":["",{token:"tag.class",next:"@tag.$1"}]}}],[/^(\s*)(\|.*)$/,""],{include:"@whitespace"},[/[a-zA-Z_$][\w$]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":""}}],[/[{}()\[\]]/,"@brackets"],[/@symbols/,"delimiter"],[/\d+\.\d+([eE][\-+]?\d+)?/,"number.float"],[/\d+/,"number"],[/"/,"string",'@string."'],[/'/,"string","@string.'"]],tag:[[/(\.)(\s*$)/,[{token:"delimiter",next:"@blockText.$S2."},""]],[/\s+/,{token:"",next:"@simpleText"}],[/#[a-zA-Z_-][\w-]*/,{cases:{"@eos":{token:"tag.id",next:"@pop"},"@default":"tag.id"}}],[/\.[a-zA-Z_-][\w-]*/,{cases:{"@eos":{token:"tag.class",next:"@pop"},"@default":"tag.class"}}],[/\(/,{token:"delimiter.parenthesis",next:"@attributeList"}]],simpleText:[[/[^#]+$/,{token:"",next:"@popall"}],[/[^#]+/,{token:""}],[/(#{)([^}]*)(})/,{cases:{"@eos":["interpolation.delimiter","interpolation",{token:"interpolation.delimiter",next:"@popall"}],"@default":["interpolation.delimiter","interpolation","interpolation.delimiter"]}}],[/#$/,{token:"",next:"@popall"}],[/#/,""]],attributeList:[[/\s+/,""],[/(\w+)(\s*=\s*)("|')/,["attribute.name","delimiter",{token:"attribute.value",next:"@value.$3"}]],[/\w+/,"attribute.name"],[/,/,{cases:{"@eos":{token:"attribute.delimiter",next:"@popall"},"@default":"attribute.delimiter"}}],[/\)$/,{token:"delimiter.parenthesis",next:"@popall"}],[/\)/,{token:"delimiter.parenthesis",next:"@pop"}]],whitespace:[[/^(\s*)(\/\/.*)$/,{token:"comment",next:"@blockText.$1.comment"}],[/[ \t\r\n]+/,""],[//,{token:"comment",next:"@pop"}],[/"]},brackets:[[""],["<",">"],["{","}"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}],onEnterRules:[{beforeText:new RegExp(`<(?!(?:${p.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),afterText:/^<\/(\w[\w\d]*)\s*>$/i,action:{indentAction:o.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(`<(?!(?:${p.join("|")}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`,"i"),action:{indentAction:o.languages.IndentAction.Indent}}]},E={defaultToken:"",tokenPostfix:"",tokenizer:{root:[[/@@@@/],[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.root"}],[/)/,["delimiter.html","tag.html","delimiter.html"]],[/(<)(script)/,["delimiter.html",{token:"tag.html",next:"@script"}]],[/(<)(style)/,["delimiter.html",{token:"tag.html",next:"@style"}]],[/(<)([:\w\-]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/(<\/)([\w\-]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/]+/,"metatag.content.html"],[/>/,"metatag.html","@pop"]],comment:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.comment"}],[/-->/,"comment.html","@pop"],[/[^-]+/,"comment.content.html"],[/./,"comment.content.html"]],otherTag:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.otherTag"}],[/\/?>/,"delimiter.html","@pop"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/]],script:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.script"}],[/type/,"attribute.name","@scriptAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/(<\/)(script\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],scriptAfterType:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.scriptAfterType"}],[/=/,"delimiter","@scriptAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptAfterTypeEquals:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.scriptAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@scriptWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.text/javascript",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptWithCustomType:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.scriptWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptEmbedded:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInEmbeddedState.scriptEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/script/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],style:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.style"}],[/type/,"attribute.name","@styleAfterType"],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/(<\/)(style\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],styleAfterType:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.styleAfterType"}],[/=/,"delimiter","@styleAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleAfterTypeEquals:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.styleAfterTypeEquals"}],[/"([^"]*)"/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value",switchTo:"@styleWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.text/css",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleWithCustomType:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInSimpleState.styleWithCustomType.$S2"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value"],[/'([^']*)'/,"attribute.value"],[/[\w\-]+/,"attribute.name"],[/=/,"delimiter"],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleEmbedded:[[/@[^@]/,{token:"@rematch",switchTo:"@razorInEmbeddedState.styleEmbedded.$S2",nextEmbedded:"@pop"}],[/<\/style/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}]],razorInSimpleState:[[/@\*/,"comment.cs","@razorBlockCommentTopLevel"],[/@[{(]/,"metatag.cs","@razorRootTopLevel"],[/(@)(\s*[\w]+)/,["metatag.cs",{token:"identifier.cs",switchTo:"@$S2.$S3"}]],[/[})]/,{token:"metatag.cs",switchTo:"@$S2.$S3"}],[/\*@/,{token:"comment.cs",switchTo:"@$S2.$S3"}]],razorInEmbeddedState:[[/@\*/,"comment.cs","@razorBlockCommentTopLevel"],[/@[{(]/,"metatag.cs","@razorRootTopLevel"],[/(@)(\s*[\w]+)/,["metatag.cs",{token:"identifier.cs",switchTo:"@$S2.$S3",nextEmbedded:"$S3"}]],[/[})]/,{token:"metatag.cs",switchTo:"@$S2.$S3",nextEmbedded:"$S3"}],[/\*@/,{token:"comment.cs",switchTo:"@$S2.$S3",nextEmbedded:"$S3"}]],razorBlockCommentTopLevel:[[/\*@/,"@rematch","@pop"],[/[^*]+/,"comment.cs"],[/./,"comment.cs"]],razorBlockComment:[[/\*@/,"comment.cs","@pop"],[/[^*]+/,"comment.cs"],[/./,"comment.cs"]],razorRootTopLevel:[[/\{/,"delimiter.bracket.cs","@razorRoot"],[/\(/,"delimiter.parenthesis.cs","@razorRoot"],[/[})]/,"@rematch","@pop"],{include:"razorCommon"}],razorRoot:[[/\{/,"delimiter.bracket.cs","@razorRoot"],[/\(/,"delimiter.parenthesis.cs","@razorRoot"],[/\}/,"delimiter.bracket.cs","@pop"],[/\)/,"delimiter.parenthesis.cs","@pop"],{include:"razorCommon"}],razorCommon:[[/[a-zA-Z_]\w*/,{cases:{"@razorKeywords":{token:"keyword.cs"},"@default":"identifier.cs"}}],[/[\[\]]/,"delimiter.array.cs"],[/[ \t\r\n]+/],[/\/\/.*$/,"comment.cs"],[/@\*/,"comment.cs","@razorBlockComment"],[/"([^"]*)"/,"string.cs"],[/'([^']*)'/,"string.cs"],[/(<)([\w\-]+)(\/>)/,["delimiter.html","tag.html","delimiter.html"]],[/(<)([\w\-]+)(>)/,["delimiter.html","tag.html","delimiter.html"]],[/(<\/)([\w\-]+)(>)/,["delimiter.html","tag.html","delimiter.html"]],[/[\+\-\*\%\&\|\^\~\!\=\<\>\/\?\;\:\.\,]/,"delimiter.cs"],[/\d*\d+[eE]([\-+]?\d+)?/,"number.float.cs"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float.cs"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,"number.hex.cs"],[/0[0-7']*[0-7]/,"number.octal.cs"],[/0[bB][0-1']*[0-1]/,"number.binary.cs"],[/\d[\d']*/,"number.cs"],[/\d/,"number.cs"]]},razorKeywords:["abstract","as","async","await","base","bool","break","by","byte","case","catch","char","checked","class","const","continue","decimal","default","delegate","do","double","descending","explicit","event","extern","else","enum","false","finally","fixed","float","for","foreach","from","goto","group","if","implicit","in","int","interface","internal","into","is","lock","long","nameof","new","null","namespace","object","operator","out","override","orderby","params","private","protected","public","readonly","ref","return","switch","struct","sbyte","sealed","short","sizeof","stackalloc","static","string","select","this","throw","true","try","typeof","uint","ulong","unchecked","unsafe","ushort","using","var","virtual","volatile","void","when","while","where","yield","model","inject"],escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/};return g(z);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/redis/redis.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/redis/redis", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var R=Object.defineProperty;var n=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var A=(S,E)=>{for(var T in E)R(S,T,{get:E[T],enumerable:!0})},O=(S,E,T,o)=>{if(E&&typeof E=="object"||typeof E=="function")for(let e of N(E))!s.call(S,e)&&e!==T&&R(S,e,{get:()=>E[e],enumerable:!(o=n(E,e))||o.enumerable});return S};var L=S=>O(R({},"__esModule",{value:!0}),S);var r={};A(r,{conf:()=>I,language:()=>i});var I={brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},i={defaultToken:"",tokenPostfix:".redis",ignoreCase:!0,brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"}],keywords:["APPEND","AUTH","BGREWRITEAOF","BGSAVE","BITCOUNT","BITFIELD","BITOP","BITPOS","BLPOP","BRPOP","BRPOPLPUSH","CLIENT","KILL","LIST","GETNAME","PAUSE","REPLY","SETNAME","CLUSTER","ADDSLOTS","COUNT-FAILURE-REPORTS","COUNTKEYSINSLOT","DELSLOTS","FAILOVER","FORGET","GETKEYSINSLOT","INFO","KEYSLOT","MEET","NODES","REPLICATE","RESET","SAVECONFIG","SET-CONFIG-EPOCH","SETSLOT","SLAVES","SLOTS","COMMAND","COUNT","GETKEYS","CONFIG","GET","REWRITE","SET","RESETSTAT","DBSIZE","DEBUG","OBJECT","SEGFAULT","DECR","DECRBY","DEL","DISCARD","DUMP","ECHO","EVAL","EVALSHA","EXEC","EXISTS","EXPIRE","EXPIREAT","FLUSHALL","FLUSHDB","GEOADD","GEOHASH","GEOPOS","GEODIST","GEORADIUS","GEORADIUSBYMEMBER","GETBIT","GETRANGE","GETSET","HDEL","HEXISTS","HGET","HGETALL","HINCRBY","HINCRBYFLOAT","HKEYS","HLEN","HMGET","HMSET","HSET","HSETNX","HSTRLEN","HVALS","INCR","INCRBY","INCRBYFLOAT","KEYS","LASTSAVE","LINDEX","LINSERT","LLEN","LPOP","LPUSH","LPUSHX","LRANGE","LREM","LSET","LTRIM","MGET","MIGRATE","MONITOR","MOVE","MSET","MSETNX","MULTI","PERSIST","PEXPIRE","PEXPIREAT","PFADD","PFCOUNT","PFMERGE","PING","PSETEX","PSUBSCRIBE","PUBSUB","PTTL","PUBLISH","PUNSUBSCRIBE","QUIT","RANDOMKEY","READONLY","READWRITE","RENAME","RENAMENX","RESTORE","ROLE","RPOP","RPOPLPUSH","RPUSH","RPUSHX","SADD","SAVE","SCARD","SCRIPT","FLUSH","LOAD","SDIFF","SDIFFSTORE","SELECT","SETBIT","SETEX","SETNX","SETRANGE","SHUTDOWN","SINTER","SINTERSTORE","SISMEMBER","SLAVEOF","SLOWLOG","SMEMBERS","SMOVE","SORT","SPOP","SRANDMEMBER","SREM","STRLEN","SUBSCRIBE","SUNION","SUNIONSTORE","SWAPDB","SYNC","TIME","TOUCH","TTL","TYPE","UNSUBSCRIBE","UNLINK","UNWATCH","WAIT","WATCH","ZADD","ZCARD","ZCOUNT","ZINCRBY","ZINTERSTORE","ZLEXCOUNT","ZRANGE","ZRANGEBYLEX","ZREVRANGEBYLEX","ZRANGEBYSCORE","ZRANK","ZREM","ZREMRANGEBYLEX","ZREMRANGEBYRANK","ZREMRANGEBYSCORE","ZREVRANGE","ZREVRANGEBYSCORE","ZREVRANK","ZSCORE","ZUNIONSTORE","SCAN","SSCAN","HSCAN","ZSCAN"],operators:[],builtinFunctions:[],builtinVariables:[],pseudoColumns:[],tokenizer:{root:[{include:"@whitespace"},{include:"@pseudoColumns"},{include:"@numbers"},{include:"@strings"},{include:"@scopes"},[/[;,.]/,"delimiter"],[/[()]/,"@brackets"],[/[\w@#$]+/,{cases:{"@keywords":"keyword","@operators":"operator","@builtinVariables":"predefined","@builtinFunctions":"predefined","@default":"identifier"}}],[/[<>=!%&+\-*/|~^]/,"operator"]],whitespace:[[/\s+/,"white"]],pseudoColumns:[[/[$][A-Za-z_][\w@#$]*/,{cases:{"@pseudoColumns":"predefined","@default":"identifier"}}]],numbers:[[/0[xX][0-9a-fA-F]*/,"number"],[/[$][+-]*\d*(\.\d*)?/,"number"],[/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/,"number"]],strings:[[/'/,{token:"string",next:"@string"}],[/"/,{token:"string.double",next:"@stringDouble"}]],string:[[/[^']+/,"string"],[/''/,"string"],[/'/,{token:"string",next:"@pop"}]],stringDouble:[[/[^"]+/,"string.double"],[/""/,"string.double"],[/"/,{token:"string.double",next:"@pop"}]],scopes:[]}};return L(r);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/redshift/redshift.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/redshift/redshift", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var i=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var o=Object.getOwnPropertyNames;var n=Object.prototype.hasOwnProperty;var p=(_,e)=>{for(var r in e)i(_,r,{get:e[r],enumerable:!0})},l=(_,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of o(e))!n.call(_,t)&&t!==r&&i(_,t,{get:()=>e[t],enumerable:!(a=s(e,t))||a.enumerable});return _};var g=_=>l(i({},"__esModule",{value:!0}),_);var m={};p(m,{conf:()=>c,language:()=>d});var c={comments:{lineComment:"--",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},d={defaultToken:"",tokenPostfix:".sql",ignoreCase:!0,brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"}],keywords:["AES128","AES256","ALL","ALLOWOVERWRITE","ANALYSE","ANALYZE","AND","ANY","ARRAY","AS","ASC","AUTHORIZATION","AZ64","BACKUP","BETWEEN","BINARY","BLANKSASNULL","BOTH","BYTEDICT","BZIP2","CASE","CAST","CHECK","COLLATE","COLUMN","CONSTRAINT","CREATE","CREDENTIALS","CROSS","CURRENT_DATE","CURRENT_TIME","CURRENT_TIMESTAMP","CURRENT_USER","CURRENT_USER_ID","DEFAULT","DEFERRABLE","DEFLATE","DEFRAG","DELTA","DELTA32K","DESC","DISABLE","DISTINCT","DO","ELSE","EMPTYASNULL","ENABLE","ENCODE","ENCRYPT","ENCRYPTION","END","EXCEPT","EXPLICIT","FALSE","FOR","FOREIGN","FREEZE","FROM","FULL","GLOBALDICT256","GLOBALDICT64K","GRANT","GROUP","GZIP","HAVING","IDENTITY","IGNORE","ILIKE","IN","INITIALLY","INNER","INTERSECT","INTO","IS","ISNULL","JOIN","LANGUAGE","LEADING","LEFT","LIKE","LIMIT","LOCALTIME","LOCALTIMESTAMP","LUN","LUNS","LZO","LZOP","MINUS","MOSTLY16","MOSTLY32","MOSTLY8","NATURAL","NEW","NOT","NOTNULL","NULL","NULLS","OFF","OFFLINE","OFFSET","OID","OLD","ON","ONLY","OPEN","OR","ORDER","OUTER","OVERLAPS","PARALLEL","PARTITION","PERCENT","PERMISSIONS","PLACING","PRIMARY","RAW","READRATIO","RECOVER","REFERENCES","RESPECT","REJECTLOG","RESORT","RESTORE","RIGHT","SELECT","SESSION_USER","SIMILAR","SNAPSHOT","SOME","SYSDATE","SYSTEM","TABLE","TAG","TDES","TEXT255","TEXT32K","THEN","TIMESTAMP","TO","TOP","TRAILING","TRUE","TRUNCATECOLUMNS","UNION","UNIQUE","USER","USING","VERBOSE","WALLET","WHEN","WHERE","WITH","WITHOUT"],operators:["AND","BETWEEN","IN","LIKE","NOT","OR","IS","NULL","INTERSECT","UNION","INNER","JOIN","LEFT","OUTER","RIGHT"],builtinFunctions:["current_schema","current_schemas","has_database_privilege","has_schema_privilege","has_table_privilege","age","current_time","current_timestamp","localtime","isfinite","now","ascii","get_bit","get_byte","set_bit","set_byte","to_ascii","approximate percentile_disc","avg","count","listagg","max","median","min","percentile_cont","stddev_samp","stddev_pop","sum","var_samp","var_pop","bit_and","bit_or","bool_and","bool_or","cume_dist","first_value","lag","last_value","lead","nth_value","ratio_to_report","dense_rank","ntile","percent_rank","rank","row_number","case","coalesce","decode","greatest","least","nvl","nvl2","nullif","add_months","at time zone","convert_timezone","current_date","date_cmp","date_cmp_timestamp","date_cmp_timestamptz","date_part_year","dateadd","datediff","date_part","date_trunc","extract","getdate","interval_cmp","last_day","months_between","next_day","sysdate","timeofday","timestamp_cmp","timestamp_cmp_date","timestamp_cmp_timestamptz","timestamptz_cmp","timestamptz_cmp_date","timestamptz_cmp_timestamp","timezone","to_timestamp","trunc","abs","acos","asin","atan","atan2","cbrt","ceil","ceiling","checksum","cos","cot","degrees","dexp","dlog1","dlog10","exp","floor","ln","log","mod","pi","power","radians","random","round","sin","sign","sqrt","tan","to_hex","bpcharcmp","btrim","bttext_pattern_cmp","char_length","character_length","charindex","chr","concat","crc32","func_sha1","initcap","left and rights","len","length","lower","lpad and rpads","ltrim","md5","octet_length","position","quote_ident","quote_literal","regexp_count","regexp_instr","regexp_replace","regexp_substr","repeat","replace","replicate","reverse","rtrim","split_part","strpos","strtol","substring","textlen","translate","trim","upper","cast","convert","to_char","to_date","to_number","json_array_length","json_extract_array_element_text","json_extract_path_text","current_setting","pg_cancel_backend","pg_terminate_backend","set_config","current_database","current_user","current_user_id","pg_backend_pid","pg_last_copy_count","pg_last_copy_id","pg_last_query_id","pg_last_unload_count","session_user","slice_num","user","version","abbrev","acosd","any","area","array_agg","array_append","array_cat","array_dims","array_fill","array_length","array_lower","array_ndims","array_position","array_positions","array_prepend","array_remove","array_replace","array_to_json","array_to_string","array_to_tsvector","array_upper","asind","atan2d","atand","bit","bit_length","bound_box","box","brin_summarize_new_values","broadcast","cardinality","center","circle","clock_timestamp","col_description","concat_ws","convert_from","convert_to","corr","cosd","cotd","covar_pop","covar_samp","current_catalog","current_query","current_role","currval","cursor_to_xml","diameter","div","encode","enum_first","enum_last","enum_range","every","family","format","format_type","generate_series","generate_subscripts","get_current_ts_config","gin_clean_pending_list","grouping","has_any_column_privilege","has_column_privilege","has_foreign_data_wrapper_privilege","has_function_privilege","has_language_privilege","has_sequence_privilege","has_server_privilege","has_tablespace_privilege","has_type_privilege","height","host","hostmask","inet_client_addr","inet_client_port","inet_merge","inet_same_family","inet_server_addr","inet_server_port","isclosed","isempty","isopen","json_agg","json_object","json_object_agg","json_populate_record","json_populate_recordset","json_to_record","json_to_recordset","jsonb_agg","jsonb_object_agg","justify_days","justify_hours","justify_interval","lastval","left","line","localtimestamp","lower_inc","lower_inf","lpad","lseg","make_date","make_interval","make_time","make_timestamp","make_timestamptz","masklen","mode","netmask","network","nextval","npoints","num_nonnulls","num_nulls","numnode","obj_description","overlay","parse_ident","path","pclose","percentile_disc","pg_advisory_lock","pg_advisory_lock_shared","pg_advisory_unlock","pg_advisory_unlock_all","pg_advisory_unlock_shared","pg_advisory_xact_lock","pg_advisory_xact_lock_shared","pg_backup_start_time","pg_blocking_pids","pg_client_encoding","pg_collation_is_visible","pg_column_size","pg_conf_load_time","pg_control_checkpoint","pg_control_init","pg_control_recovery","pg_control_system","pg_conversion_is_visible","pg_create_logical_replication_slot","pg_create_physical_replication_slot","pg_create_restore_point","pg_current_xlog_flush_location","pg_current_xlog_insert_location","pg_current_xlog_location","pg_database_size","pg_describe_object","pg_drop_replication_slot","pg_export_snapshot","pg_filenode_relation","pg_function_is_visible","pg_get_constraintdef","pg_get_expr","pg_get_function_arguments","pg_get_function_identity_arguments","pg_get_function_result","pg_get_functiondef","pg_get_indexdef","pg_get_keywords","pg_get_object_address","pg_get_owned_sequence","pg_get_ruledef","pg_get_serial_sequence","pg_get_triggerdef","pg_get_userbyid","pg_get_viewdef","pg_has_role","pg_identify_object","pg_identify_object_as_address","pg_index_column_has_property","pg_index_has_property","pg_indexam_has_property","pg_indexes_size","pg_is_in_backup","pg_is_in_recovery","pg_is_other_temp_schema","pg_is_xlog_replay_paused","pg_last_committed_xact","pg_last_xact_replay_timestamp","pg_last_xlog_receive_location","pg_last_xlog_replay_location","pg_listening_channels","pg_logical_emit_message","pg_logical_slot_get_binary_changes","pg_logical_slot_get_changes","pg_logical_slot_peek_binary_changes","pg_logical_slot_peek_changes","pg_ls_dir","pg_my_temp_schema","pg_notification_queue_usage","pg_opclass_is_visible","pg_operator_is_visible","pg_opfamily_is_visible","pg_options_to_table","pg_postmaster_start_time","pg_read_binary_file","pg_read_file","pg_relation_filenode","pg_relation_filepath","pg_relation_size","pg_reload_conf","pg_replication_origin_create","pg_replication_origin_drop","pg_replication_origin_oid","pg_replication_origin_progress","pg_replication_origin_session_is_setup","pg_replication_origin_session_progress","pg_replication_origin_session_reset","pg_replication_origin_session_setup","pg_replication_origin_xact_reset","pg_replication_origin_xact_setup","pg_rotate_logfile","pg_size_bytes","pg_size_pretty","pg_sleep","pg_sleep_for","pg_sleep_until","pg_start_backup","pg_stat_file","pg_stop_backup","pg_switch_xlog","pg_table_is_visible","pg_table_size","pg_tablespace_databases","pg_tablespace_location","pg_tablespace_size","pg_total_relation_size","pg_trigger_depth","pg_try_advisory_lock","pg_try_advisory_lock_shared","pg_try_advisory_xact_lock","pg_try_advisory_xact_lock_shared","pg_ts_config_is_visible","pg_ts_dict_is_visible","pg_ts_parser_is_visible","pg_ts_template_is_visible","pg_type_is_visible","pg_typeof","pg_xact_commit_timestamp","pg_xlog_location_diff","pg_xlog_replay_pause","pg_xlog_replay_resume","pg_xlogfile_name","pg_xlogfile_name_offset","phraseto_tsquery","plainto_tsquery","point","polygon","popen","pqserverversion","query_to_xml","querytree","quote_nullable","radius","range_merge","regexp_matches","regexp_split_to_array","regexp_split_to_table","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","right","row_security_active","row_to_json","rpad","scale","set_masklen","setseed","setval","setweight","shobj_description","sind","sprintf","statement_timestamp","stddev","string_agg","string_to_array","strip","substr","table_to_xml","table_to_xml_and_xmlschema","tand","text","to_json","to_regclass","to_regnamespace","to_regoper","to_regoperator","to_regproc","to_regprocedure","to_regrole","to_regtype","to_tsquery","to_tsvector","transaction_timestamp","ts_debug","ts_delete","ts_filter","ts_headline","ts_lexize","ts_parse","ts_rank","ts_rank_cd","ts_rewrite","ts_stat","ts_token_type","tsquery_phrase","tsvector_to_array","tsvector_update_trigger","tsvector_update_trigger_column","txid_current","txid_current_snapshot","txid_snapshot_xip","txid_snapshot_xmax","txid_snapshot_xmin","txid_visible_in_snapshot","unnest","upper_inc","upper_inf","variance","width","width_bucket","xml_is_well_formed","xml_is_well_formed_content","xml_is_well_formed_document","xmlagg","xmlcomment","xmlconcat","xmlelement","xmlexists","xmlforest","xmlparse","xmlpi","xmlroot","xmlserialize","xpath","xpath_exists"],builtinVariables:[],pseudoColumns:[],tokenizer:{root:[{include:"@comments"},{include:"@whitespace"},{include:"@pseudoColumns"},{include:"@numbers"},{include:"@strings"},{include:"@complexIdentifiers"},{include:"@scopes"},[/[;,.]/,"delimiter"],[/[()]/,"@brackets"],[/[\w@#$]+/,{cases:{"@keywords":"keyword","@operators":"operator","@builtinVariables":"predefined","@builtinFunctions":"predefined","@default":"identifier"}}],[/[<>=!%&+\-*/|~^]/,"operator"]],whitespace:[[/\s+/,"white"]],comments:[[/--+.*/,"comment"],[/\/\*/,{token:"comment.quote",next:"@comment"}]],comment:[[/[^*/]+/,"comment"],[/\*\//,{token:"comment.quote",next:"@pop"}],[/./,"comment"]],pseudoColumns:[[/[$][A-Za-z_][\w@#$]*/,{cases:{"@pseudoColumns":"predefined","@default":"identifier"}}]],numbers:[[/0[xX][0-9a-fA-F]*/,"number"],[/[$][+-]*\d*(\.\d*)?/,"number"],[/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/,"number"]],strings:[[/'/,{token:"string",next:"@string"}]],string:[[/[^']+/,"string"],[/''/,"string"],[/'/,{token:"string",next:"@pop"}]],complexIdentifiers:[[/"/,{token:"identifier.quote",next:"@quotedIdentifier"}]],quotedIdentifier:[[/[^"]+/,"identifier"],[/""/,"identifier"],[/"/,{token:"identifier.quote",next:"@pop"}]],scopes:[]}};return g(m);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/restructuredtext/restructuredtext.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/restructuredtext/restructuredtext", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var t=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var r=Object.prototype.hasOwnProperty;var k=(n,e)=>{for(var i in e)t(n,i,{get:e[i],enumerable:!0})},c=(n,e,i,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of l(e))!r.call(n,s)&&s!==i&&t(n,s,{get:()=>e[s],enumerable:!(o=a(e,s))||o.enumerable});return n};var p=n=>c(t({},"__esModule",{value:!0}),n);var g={};k(g,{conf:()=>u,language:()=>m});var u={brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">",notIn:["string"]}],surroundingPairs:[{open:"(",close:")"},{open:"[",close:"]"},{open:"`",close:"`"}],folding:{markers:{start:new RegExp("^\\s*"),end:new RegExp("^\\s*")}}},m={defaultToken:"",tokenPostfix:".rst",control:/[\\`*_\[\]{}()#+\-\.!]/,escapes:/\\(?:@control)/,empty:["area","base","basefont","br","col","frame","hr","img","input","isindex","link","meta","param"],alphanumerics:/[A-Za-z0-9]/,simpleRefNameWithoutBq:/(?:@alphanumerics[-_+:.]*@alphanumerics)+|(?:@alphanumerics+)/,simpleRefName:/(?:`@phrase`|@simpleRefNameWithoutBq)/,phrase:/@simpleRefNameWithoutBq(?:\s@simpleRefNameWithoutBq)*/,citationName:/[A-Za-z][A-Za-z0-9-_.]*/,blockLiteralStart:/(?:[!"#$%&'()*+,-./:;<=>?@\[\]^_`{|}~]|[\s])/,precedingChars:/(?:[ -:/'"<([{])/,followingChars:/(?:[ -.,:;!?/'")\]}>]|$)/,punctuation:/(=|-|~|`|#|"|\^|\+|\*|:|\.|'|_|\+)/,tokenizer:{root:[[/^(@punctuation{3,}$){1,1}?/,"keyword"],[/^\s*([\*\-+‣•]|[a-zA-Z0-9]+\.|\([a-zA-Z0-9]+\)|[a-zA-Z0-9]+\))\s/,"keyword"],[/([ ]::)\s*$/,"keyword","@blankLineOfLiteralBlocks"],[/(::)\s*$/,"keyword","@blankLineOfLiteralBlocks"],{include:"@tables"},{include:"@explicitMarkupBlocks"},{include:"@inlineMarkup"}],explicitMarkupBlocks:[{include:"@citations"},{include:"@footnotes"},[/^(\.\.\s)(@simpleRefName)(::\s)(.*)$/,[{token:"",next:"subsequentLines"},"keyword","",""]],[/^(\.\.)(\s+)(_)(@simpleRefName)(:)(\s+)(.*)/,[{token:"",next:"hyperlinks"},"","","string.link","","","string.link"]],[/^((?:(?:\.\.)(?:\s+))?)(__)(:)(\s+)(.*)/,[{token:"",next:"subsequentLines"},"","","","string.link"]],[/^(__\s+)(.+)/,["","string.link"]],[/^(\.\.)( \|)([^| ]+[^|]*[^| ]*)(\| )(@simpleRefName)(:: .*)/,[{token:"",next:"subsequentLines"},"","string.link","","keyword",""],"@rawBlocks"],[/(\|)([^| ]+[^|]*[^| ]*)(\|_{0,2})/,["","string.link",""]],[/^(\.\.)([ ].*)$/,[{token:"",next:"@comments"},"comment"]]],inlineMarkup:[{include:"@citationsReference"},{include:"@footnotesReference"},[/(@simpleRefName)(_{1,2})/,["string.link",""]],[/(`)([^<`]+\s+)(<)(.*)(>)(`)(_)/,["","string.link","","string.link","","",""]],[/\*\*([^\\*]|\*(?!\*))+\*\*/,"strong"],[/\*[^*]+\*/,"emphasis"],[/(``)((?:[^`]|\`(?!`))+)(``)/,["","keyword",""]],[/(__\s+)(.+)/,["","keyword"]],[/(:)((?:@simpleRefNameWithoutBq)?)(:`)([^`]+)(`)/,["","keyword","","",""]],[/(`)([^`]+)(`:)((?:@simpleRefNameWithoutBq)?)(:)/,["","","","keyword",""]],[/(`)([^`]+)(`)/,""],[/(_`)(@phrase)(`)/,["","string.link",""]]],citations:[[/^(\.\.\s+\[)((?:@citationName))(\]\s+)(.*)/,[{token:"",next:"@subsequentLines"},"string.link","",""]]],citationsReference:[[/(\[)(@citationName)(\]_)/,["","string.link",""]]],footnotes:[[/^(\.\.\s+\[)((?:[0-9]+))(\]\s+.*)/,[{token:"",next:"@subsequentLines"},"string.link",""]],[/^(\.\.\s+\[)((?:#@simpleRefName?))(\]\s+)(.*)/,[{token:"",next:"@subsequentLines"},"string.link","",""]],[/^(\.\.\s+\[)((?:\*))(\]\s+)(.*)/,[{token:"",next:"@subsequentLines"},"string.link","",""]]],footnotesReference:[[/(\[)([0-9]+)(\])(_)/,["","string.link","",""]],[/(\[)(#@simpleRefName?)(\])(_)/,["","string.link","",""]],[/(\[)(\*)(\])(_)/,["","string.link","",""]]],blankLineOfLiteralBlocks:[[/^$/,"","@subsequentLinesOfLiteralBlocks"],[/^.*$/,"","@pop"]],subsequentLinesOfLiteralBlocks:[[/(@blockLiteralStart+)(.*)/,["keyword",""]],[/^(?!blockLiteralStart)/,"","@popall"]],subsequentLines:[[/^[\s]+.*/,""],[/^(?!\s)/,"","@pop"]],hyperlinks:[[/^[\s]+.*/,"string.link"],[/^(?!\s)/,"","@pop"]],comments:[[/^[\s]+.*/,"comment"],[/^(?!\s)/,"","@pop"]],tables:[[/\+-[+-]+/,"keyword"],[/\+=[+=]+/,"keyword"]]}};return p(g);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/ruby/ruby.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/ruby/ruby", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var p=(t,e)=>{for(var r in e)o(t,r,{get:e[r],enumerable:!0})},l=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of c(e))!d.call(t,n)&&n!==r&&o(t,n,{get:()=>e[n],enumerable:!(s=i(e,n))||s.enumerable});return t};var a=t=>l(o({},"__esModule",{value:!0}),t);var m={};p(m,{conf:()=>g,language:()=>x});var g={comments:{lineComment:"#",blockComment:["=begin","=end"]},brackets:[["(",")"],["{","}"],["[","]"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],indentationRules:{increaseIndentPattern:new RegExp(`^\\s*((begin|class|(private|protected)\\s+def|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|while|case)|([^#]*\\sdo\\b)|([^#]*=\\s*(case|if|unless)))\\b([^#\\{;]|("|'|/).*\\4)*(#.*)?$`),decreaseIndentPattern:new RegExp("^\\s*([}\\]]([,)]?\\s*(#|$)|\\.[a-zA-Z_]\\w*\\b)|(end|rescue|ensure|else|elsif|when)\\b)")}},x={tokenPostfix:".ruby",keywords:["__LINE__","__ENCODING__","__FILE__","BEGIN","END","alias","and","begin","break","case","class","def","defined?","do","else","elsif","end","ensure","for","false","if","in","module","next","nil","not","or","redo","rescue","retry","return","self","super","then","true","undef","unless","until","when","while","yield"],keywordops:["::","..","...","?",":","=>"],builtins:["require","public","private","include","extend","attr_reader","protected","private_class_method","protected_class_method","new"],declarations:["module","class","def","case","do","begin","for","if","while","until","unless"],linedecls:["def","case","do","begin","for","if","while","until","unless"],operators:["^","&","|","<=>","==","===","!~","=~",">",">=","<","<=","<<",">>","+","-","*","/","%","**","~","+@","-@","[]","[]=","`","+=","-=","*=","**=","/=","^=","%=","<<=",">>=","&=","&&=","||=","|="],brackets:[{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"}],symbols:/[=>"}],[/%([qws])(@delim)/,{token:"string.$1.delim",switchTo:"@qstring.$1.$2.$2"}],[/%r\(/,{token:"regexp.delim",switchTo:"@pregexp.(.)"}],[/%r\[/,{token:"regexp.delim",switchTo:"@pregexp.[.]"}],[/%r\{/,{token:"regexp.delim",switchTo:"@pregexp.{.}"}],[/%r"}],[/%r(@delim)/,{token:"regexp.delim",switchTo:"@pregexp.$1.$1"}],[/%(x|W|Q?)\(/,{token:"string.$1.delim",switchTo:"@qqstring.$1.(.)"}],[/%(x|W|Q?)\[/,{token:"string.$1.delim",switchTo:"@qqstring.$1.[.]"}],[/%(x|W|Q?)\{/,{token:"string.$1.delim",switchTo:"@qqstring.$1.{.}"}],[/%(x|W|Q?)"}],[/%(x|W|Q?)(@delim)/,{token:"string.$1.delim",switchTo:"@qqstring.$1.$2.$2"}],[/%([rqwsxW]|Q?)./,{token:"invalid",next:"@pop"}],[/./,{token:"invalid",next:"@pop"}]],qstring:[[/\\$/,"string.$S2.escape"],[/\\./,"string.$S2.escape"],[/./,{cases:{"$#==$S4":{token:"string.$S2.delim",next:"@pop"},"$#==$S3":{token:"string.$S2.delim",next:"@push"},"@default":"string.$S2"}}]],qqstring:[[/#/,"string.$S2.escape","@interpolated"],{include:"@qstring"}],whitespace:[[/[ \t\r\n]+/,""],[/^\s*=begin\b/,"comment","@comment"],[/#.*$/,"comment"]],comment:[[/[^=]+/,"comment"],[/^\s*=begin\b/,"comment.invalid"],[/^\s*=end\b.*/,"comment","@pop"],[/[=]/,"comment"]]}};return a(m);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/rust/rust.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/rust/rust", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var _=(t,e)=>{for(var n in e)r(t,n,{get:e[n],enumerable:!0})},u=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of a(e))!c.call(t,o)&&o!==n&&r(t,o,{get:()=>e[o],enumerable:!(s=i(e,o))||s.enumerable});return t};var l=t=>u(r({},"__esModule",{value:!0}),t);var m={};_(m,{conf:()=>f,language:()=>p});var f={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"[",close:"]"},{open:"{",close:"}"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*#pragma\\s+region\\b"),end:new RegExp("^\\s*#pragma\\s+endregion\\b")}}},p={tokenPostfix:".rust",defaultToken:"invalid",keywords:["as","async","await","box","break","const","continue","crate","dyn","else","enum","extern","false","fn","for","if","impl","in","let","loop","match","mod","move","mut","pub","ref","return","self","static","struct","super","trait","true","try","type","unsafe","use","where","while","catch","default","union","static","abstract","alignof","become","do","final","macro","offsetof","override","priv","proc","pure","sizeof","typeof","unsized","virtual","yield"],typeKeywords:["Self","m32","m64","m128","f80","f16","f128","int","uint","float","char","bool","u8","u16","u32","u64","f32","f64","i8","i16","i32","i64","str","Option","Either","c_float","c_double","c_void","FILE","fpos_t","DIR","dirent","c_char","c_schar","c_uchar","c_short","c_ushort","c_int","c_uint","c_long","c_ulong","size_t","ptrdiff_t","clock_t","time_t","c_longlong","c_ulonglong","intptr_t","uintptr_t","off_t","dev_t","ino_t","pid_t","mode_t","ssize_t"],constants:["true","false","Some","None","Left","Right","Ok","Err"],supportConstants:["EXIT_FAILURE","EXIT_SUCCESS","RAND_MAX","EOF","SEEK_SET","SEEK_CUR","SEEK_END","_IOFBF","_IONBF","_IOLBF","BUFSIZ","FOPEN_MAX","FILENAME_MAX","L_tmpnam","TMP_MAX","O_RDONLY","O_WRONLY","O_RDWR","O_APPEND","O_CREAT","O_EXCL","O_TRUNC","S_IFIFO","S_IFCHR","S_IFBLK","S_IFDIR","S_IFREG","S_IFMT","S_IEXEC","S_IWRITE","S_IREAD","S_IRWXU","S_IXUSR","S_IWUSR","S_IRUSR","F_OK","R_OK","W_OK","X_OK","STDIN_FILENO","STDOUT_FILENO","STDERR_FILENO"],supportMacros:["format!","print!","println!","panic!","format_args!","unreachable!","write!","writeln!"],operators:["!","!=","%","%=","&","&=","&&","*","*=","+","+=","-","-=","->",".","..","...","/","/=",":",";","<<","<<=","<","<=","=","==","=>",">",">=",">>",">>=","@","^","^=","|","|=","||","_","?","#"],escapes:/\\([nrt0\"''\\]|x\h{2}|u\{\h{1,6}\})/,delimiters:/[,]/,symbols:/[\#\!\%\&\*\+\-\.\/\:\;\<\=\>\@\^\|_\?]+/,intSuffixes:/[iu](8|16|32|64|128|size)/,floatSuffixes:/f(32|64)/,tokenizer:{root:[[/r(#*)"/,{token:"string.quote",bracket:"@open",next:"@stringraw.$1"}],[/[a-zA-Z][a-zA-Z0-9_]*!?|_[a-zA-Z0-9_]+/,{cases:{"@typeKeywords":"keyword.type","@keywords":"keyword","@supportConstants":"keyword","@supportMacros":"keyword","@constants":"keyword","@default":"identifier"}}],[/\$/,"identifier"],[/'[a-zA-Z_][a-zA-Z0-9_]*(?=[^\'])/,"identifier"],[/'(\S|@escapes)'/,"string.byteliteral"],[/"/,{token:"string.quote",bracket:"@open",next:"@string"}],{include:"@numbers"},{include:"@whitespace"},[/@delimiters/,{cases:{"@keywords":"keyword","@default":"delimiter"}}],[/[{}()\[\]<>]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":""}}]],whitespace:[[/[ \t\r\n]+/,"white"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\/\*/,"comment","@push"],["\\*/","comment","@pop"],[/[\/*]/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",bracket:"@close",next:"@pop"}]],stringraw:[[/[^"#]+/,{token:"string"}],[/"(#*)/,{cases:{"$1==$S2":{token:"string.quote",bracket:"@close",next:"@pop"},"@default":{token:"string"}}}],[/["#]/,{token:"string"}]],numbers:[[/(0o[0-7_]+)(@intSuffixes)?/,{token:"number"}],[/(0b[0-1_]+)(@intSuffixes)?/,{token:"number"}],[/[\d][\d_]*(\.[\d][\d_]*)?[eE][+-][\d_]+(@floatSuffixes)?/,{token:"number"}],[/\b(\d\.?[\d_]*)(@floatSuffixes)?\b/,{token:"number"}],[/(0x[\da-fA-F]+)_?(@intSuffixes)?/,{token:"number"}],[/[\d][\d_]*(@intSuffixes?)?/,{token:"number"}]]}};return l(m);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/sb/sb.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/sb/sb", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var d=(o,e)=>{for(var t in e)r(o,t,{get:e[t],enumerable:!0})},c=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of a(e))!l.call(o,n)&&n!==t&&r(o,n,{get:()=>e[n],enumerable:!(s=i(e,n))||s.enumerable});return o};var g=o=>c(r({},"__esModule",{value:!0}),o);var m={};d(m,{conf:()=>p,language:()=>f});var p={comments:{lineComment:"'"},brackets:[["(",")"],["[","]"],["If","EndIf"],["While","EndWhile"],["For","EndFor"],["Sub","EndSub"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]}]},f={defaultToken:"",tokenPostfix:".sb",ignoreCase:!0,brackets:[{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"keyword.tag-if",open:"If",close:"EndIf"},{token:"keyword.tag-while",open:"While",close:"EndWhile"},{token:"keyword.tag-for",open:"For",close:"EndFor"},{token:"keyword.tag-sub",open:"Sub",close:"EndSub"}],keywords:["Else","ElseIf","EndFor","EndIf","EndSub","EndWhile","For","Goto","If","Step","Sub","Then","To","While"],tagwords:["If","Sub","While","For"],operators:[">","<","<>","<=",">=","And","Or","+","-","*","/","="],identifier:/[a-zA-Z_][\w]*/,symbols:/[=><:+\-*\/%\.,]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:"@whitespace"},[/(@identifier)(?=[.])/,"type"],[/@identifier/,{cases:{"@keywords":{token:"keyword.$0"},"@operators":"operator","@default":"variable.name"}}],[/([.])(@identifier)/,{cases:{$2:["delimiter","type.member"],"@default":""}}],[/\d*\.\d+/,"number.float"],[/\d+/,"number"],[/[()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":"delimiter"}}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],whitespace:[[/[ \t\r\n]+/,""],[/(\').*$/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"C?/,"string","@pop"]]}};return g(m);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/scala/scala.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/scala/scala", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var n=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var r in e)n(t,r,{get:e[r],enumerable:!0})},c=(t,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of i(e))!d.call(t,o)&&o!==r&&n(t,o,{get:()=>e[o],enumerable:!(a=s(e,o))||a.enumerable});return t};var g=t=>c(n({},"__esModule",{value:!0}),t);var m={};l(m,{conf:()=>p,language:()=>w});var p={wordPattern:/(unary_[@~!#%^&*()\-=+\\|:<>\/?]+)|([a-zA-Z_$][\w$]*?_=)|(`[^`]+`)|([a-zA-Z_$][\w$]*)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:))")}}},w={tokenPostfix:".scala",keywords:["asInstanceOf","catch","class","classOf","def","do","else","extends","finally","for","foreach","forSome","if","import","isInstanceOf","macro","match","new","object","package","return","throw","trait","try","type","until","val","var","while","with","yield","given","enum","then"],softKeywords:["as","export","extension","end","derives","on"],constants:["true","false","null","this","super"],modifiers:["abstract","final","implicit","lazy","override","private","protected","sealed"],softModifiers:["inline","opaque","open","transparent","using"],name:/(?:[a-z_$][\w$]*|`[^`]+`)/,type:/(?:[A-Z][\w$]*)/,symbols:/[=>))/,["@brackets","white","variable"]],[/@name/,{cases:{"@keywords":"keyword","@softKeywords":"keyword","@modifiers":"keyword.modifier","@softModifiers":"keyword.modifier","@constants":{token:"constant",next:"@allowMethod"},"@default":{token:"identifier",next:"@allowMethod"}}}],[/@type/,"type","@allowMethod"],{include:"@whitespace"},[/@[a-zA-Z_$][\w$]*(?:\.[a-zA-Z_$][\w$]*)*/,"annotation"],[/[{(]/,"@brackets"],[/[})]/,"@brackets","@allowMethod"],[/\[/,"operator.square"],[/](?!\s*(?:va[rl]|def|type)\b)/,"operator.square","@allowMethod"],[/]/,"operator.square"],[/([=-]>|<-|>:|<:|:>|<%)(?=[\s\w()[\]{},\."'`])/,"keyword"],[/@symbols/,"operator"],[/[;,\.]/,"delimiter"],[/'[a-zA-Z$][\w$]*(?!')/,"attribute.name"],[/'[^\\']'/,"string","@allowMethod"],[/(')(@escapes)(')/,["string","string.escape",{token:"string",next:"@allowMethod"}]],[/'/,"string.invalid"]],import:[[/;/,"delimiter","@pop"],[/^|$/,"","@pop"],[/[ \t]+/,"white"],[/[\n\r]+/,"white","@pop"],[/\/\*/,"comment","@comment"],[/@name|@type/,"type"],[/[(){}]/,"@brackets"],[/[[\]]/,"operator.square"],[/[\.,]/,"delimiter"]],allowMethod:[[/^|$/,"","@pop"],[/[ \t]+/,"white"],[/[\n\r]+/,"white","@pop"],[/\/\*/,"comment","@comment"],[/(?==>[\s\w([{])/,"keyword","@pop"],[/(@name|@symbols)(?=[ \t]*[[({"'`]|[ \t]+(?:[+-]?\.?\d|\w))/,{cases:{"@keywords":{token:"keyword",next:"@pop"},"->|<-|>:|<:|<%":{token:"keyword",next:"@pop"},"@default":{token:"@rematch",next:"@pop"}}}],["","","@pop"]],comment:[[/[^\/*]+/,"comment"],[/\/\*/,"comment","@push"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],case:[[/\b_\*/,"key"],[/\b(_|true|false|null|this|super)\b/,"keyword","@allowMethod"],[/\bif\b|=>/,"keyword","@pop"],[/`[^`]+`/,"identifier","@allowMethod"],[/@name/,"variable","@allowMethod"],[/:::?|\||@(?![a-z_$])/,"keyword"],{include:"@root"}],vardef:[[/\b_\*/,"key"],[/\b(_|true|false|null|this|super)\b/,"keyword"],[/@name/,"variable"],[/:::?|\||@(?![a-z_$])/,"keyword"],[/=|:(?!:)/,"operator","@pop"],[/$/,"white","@pop"],{include:"@root"}],string:[[/[^\\"\n\r]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}]],stringt:[[/[^\\"\n\r]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"(?=""")/,"string"],[/"""/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}],[/"/,"string"]],fstring:[[/@escapes/,"string.escape"],[/"/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}],[/\$\$/,"string"],[/(\$)([a-z_]\w*)/,["operator","identifier"]],[/\$\{/,"operator","@interp"],[/%%/,"string"],[/(%)([\-#+ 0,(])(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/,["metatag","keyword.modifier","number","metatag"]],[/(%)(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/,["metatag","number","metatag"]],[/(%)([\-#+ 0,(])(@fstring_conv)/,["metatag","keyword.modifier","metatag"]],[/(%)(@fstring_conv)/,["metatag","metatag"]],[/./,"string"]],fstringt:[[/@escapes/,"string.escape"],[/"(?=""")/,"string"],[/"""/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}],[/\$\$/,"string"],[/(\$)([a-z_]\w*)/,["operator","identifier"]],[/\$\{/,"operator","@interp"],[/%%/,"string"],[/(%)([\-#+ 0,(])(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/,["metatag","keyword.modifier","number","metatag"]],[/(%)(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/,["metatag","number","metatag"]],[/(%)([\-#+ 0,(])(@fstring_conv)/,["metatag","keyword.modifier","metatag"]],[/(%)(@fstring_conv)/,["metatag","metatag"]],[/./,"string"]],sstring:[[/@escapes/,"string.escape"],[/"/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}],[/\$\$/,"string"],[/(\$)([a-z_]\w*)/,["operator","identifier"]],[/\$\{/,"operator","@interp"],[/./,"string"]],sstringt:[[/@escapes/,"string.escape"],[/"(?=""")/,"string"],[/"""/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}],[/\$\$/,"string"],[/(\$)([a-z_]\w*)/,["operator","identifier"]],[/\$\{/,"operator","@interp"],[/./,"string"]],interp:[[/{/,"operator","@push"],[/}/,"operator","@pop"],{include:"@root"}],rawstring:[[/[^"]/,"string"],[/"/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}]],rawstringt:[[/[^"]/,"string"],[/"(?=""")/,"string"],[/"""/,{token:"string.quote",bracket:"@close",switchTo:"@allowMethod"}],[/"/,"string"]],whitespace:[[/[ \t\r\n]+/,"white"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]]}};return g(m);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/scheme/scheme.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/scheme/scheme", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(o,e)=>{for(var t in e)s(o,t,{get:e[t],enumerable:!0})},m=(o,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of i(e))!l.call(o,n)&&n!==t&&s(o,n,{get:()=>e[n],enumerable:!(a=r(e,n))||a.enumerable});return o};var p=o=>m(s({},"__esModule",{value:!0}),o);var u={};c(u,{conf:()=>d,language:()=>g});var d={comments:{lineComment:";",blockComment:["#|","|#"]},brackets:[["(",")"],["{","}"],["[","]"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}]},g={defaultToken:"",ignoreCase:!0,tokenPostfix:".scheme",brackets:[{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"}],keywords:["case","do","let","loop","if","else","when","cons","car","cdr","cond","lambda","lambda*","syntax-rules","format","set!","quote","eval","append","list","list?","member?","load"],constants:["#t","#f"],operators:["eq?","eqv?","equal?","and","or","not","null?"],tokenizer:{root:[[/#[xXoObB][0-9a-fA-F]+/,"number.hex"],[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?/,"number.float"],[/(?:\b(?:(define|define-syntax|define-macro))\b)(\s+)((?:\w|\-|\!|\?)*)/,["keyword","white","variable"]],{include:"@whitespace"},{include:"@strings"},[/[a-zA-Z_#][a-zA-Z0-9_\-\?\!\*]*/,{cases:{"@keywords":"keyword","@constants":"constant","@operators":"operators","@default":"identifier"}}]],comment:[[/[^\|#]+/,"comment"],[/#\|/,"comment","@push"],[/\|#/,"comment","@pop"],[/[\|#]/,"comment"]],whitespace:[[/[ \t\r\n]+/,"white"],[/#\|/,"comment","@comment"],[/;.*$/,"comment"]],strings:[[/"$/,"string","@popall"],[/"(?=.)/,"string","@multiLineString"]],multiLineString:[[/[^\\"]+$/,"string","@popall"],[/[^\\"]+/,"string"],[/\\./,"string.escape"],[/"/,"string","@popall"],[/\\$/,"string"]]}};return p(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/scss/scss.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/scss/scss", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var i=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var c=(t,e)=>{for(var o in e)i(t,o,{get:e[o],enumerable:!0})},m=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of l(e))!d.call(t,n)&&n!==o&&i(t,n,{get:()=>e[n],enumerable:!(r=a(e,n))||r.enumerable});return t};var s=t=>m(i({},"__esModule",{value:!0}),t);var k={};c(k,{conf:()=>u,language:()=>p});var u={wordPattern:/(#?-?\d*\.\d\w*%?)|([@$#!.:]?[\w-?]+%?)|[@#!.]/g,comments:{blockComment:["/*","*/"],lineComment:"//"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]},{open:"'",close:"'",notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{markers:{start:new RegExp("^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/"),end:new RegExp("^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/")}}},p={defaultToken:"",tokenPostfix:".scss",ws:`[ \r\f]*`,identifier:"-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.bracket"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],tokenizer:{root:[{include:"@selector"}],selector:[{include:"@comments"},{include:"@import"},{include:"@variabledeclaration"},{include:"@warndebug"},["[@](include)",{token:"keyword",next:"@includedeclaration"}],["[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)",{token:"keyword",next:"@keyframedeclaration"}],["[@](page|content|font-face|-moz-document)",{token:"keyword"}],["[@](charset|namespace)",{token:"keyword",next:"@declarationbody"}],["[@](function)",{token:"keyword",next:"@functiondeclaration"}],["[@](mixin)",{token:"keyword",next:"@mixindeclaration"}],["url(\\-prefix)?\\(",{token:"meta",next:"@urldeclaration"}],{include:"@controlstatement"},{include:"@selectorname"},["[&\\*]","tag"],["[>\\+,]","delimiter"],["\\[",{token:"delimiter.bracket",next:"@selectorattribute"}],["{",{token:"delimiter.curly",next:"@selectorbody"}]],selectorbody:[["[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))","attribute.name","@rulevalue"],{include:"@selector"},["[@](extend)",{token:"keyword",next:"@extendbody"}],["[@](return)",{token:"keyword",next:"@declarationbody"}],["}",{token:"delimiter.curly",next:"@pop"}]],selectorname:[["#{",{token:"meta",next:"@variableinterpolation"}],["(\\.|#(?=[^{])|%|(@identifier)|:)+","tag"]],selectorattribute:[{include:"@term"},["]",{token:"delimiter.bracket",next:"@pop"}]],term:[{include:"@comments"},["url(\\-prefix)?\\(",{token:"meta",next:"@urldeclaration"}],{include:"@functioninvocation"},{include:"@numbers"},{include:"@strings"},{include:"@variablereference"},["(and\\b|or\\b|not\\b)","operator"],{include:"@name"},["([<>=\\+\\-\\*\\/\\^\\|\\~,])","operator"],[",","delimiter"],["!default","literal"],["\\(",{token:"delimiter.parenthesis",next:"@parenthizedterm"}]],rulevalue:[{include:"@term"},["!important","literal"],[";","delimiter","@pop"],["{",{token:"delimiter.curly",switchTo:"@nestedproperty"}],["(?=})",{token:"",next:"@pop"}]],nestedproperty:[["[*_]?@identifier@ws:","attribute.name","@rulevalue"],{include:"@comments"},["}",{token:"delimiter.curly",next:"@pop"}]],warndebug:[["[@](warn|debug)",{token:"keyword",next:"@declarationbody"}]],import:[["[@](import)",{token:"keyword",next:"@declarationbody"}]],variabledeclaration:[["\\$@identifier@ws:","variable.decl","@declarationbody"]],urldeclaration:[{include:"@strings"},[`[^)\r ]+`,"string"],["\\)",{token:"meta",next:"@pop"}]],parenthizedterm:[{include:"@term"},["\\)",{token:"delimiter.parenthesis",next:"@pop"}]],declarationbody:[{include:"@term"},[";","delimiter","@pop"],["(?=})",{token:"",next:"@pop"}]],extendbody:[{include:"@selectorname"},["!optional","literal"],[";","delimiter","@pop"],["(?=})",{token:"",next:"@pop"}]],variablereference:[["\\$@identifier","variable.ref"],["\\.\\.\\.","operator"],["#{",{token:"meta",next:"@variableinterpolation"}]],variableinterpolation:[{include:"@variablereference"},["}",{token:"meta",next:"@pop"}]],comments:[["\\/\\*","comment","@comment"],["\\/\\/+.*","comment"]],comment:[["\\*\\/","comment","@pop"],[".","comment"]],name:[["@identifier","attribute.value"]],numbers:[["(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?",{token:"number",next:"@units"}],["#[0-9a-fA-F_]+(?!\\w)","number.hex"]],units:[["(em|ex|ch|rem|fr|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?","number","@pop"]],functiondeclaration:[["@identifier@ws\\(",{token:"meta",next:"@parameterdeclaration"}],["{",{token:"delimiter.curly",switchTo:"@functionbody"}]],mixindeclaration:[["@identifier@ws\\(",{token:"meta",next:"@parameterdeclaration"}],["@identifier","meta"],["{",{token:"delimiter.curly",switchTo:"@selectorbody"}]],parameterdeclaration:[["\\$@identifier@ws:","variable.decl"],["\\.\\.\\.","operator"],[",","delimiter"],{include:"@term"},["\\)",{token:"meta",next:"@pop"}]],includedeclaration:[{include:"@functioninvocation"},["@identifier","meta"],[";","delimiter","@pop"],["(?=})",{token:"",next:"@pop"}],["{",{token:"delimiter.curly",switchTo:"@selectorbody"}]],keyframedeclaration:[["@identifier","meta"],["{",{token:"delimiter.curly",switchTo:"@keyframebody"}]],keyframebody:[{include:"@term"},["{",{token:"delimiter.curly",next:"@selectorbody"}],["}",{token:"delimiter.curly",next:"@pop"}]],controlstatement:[["[@](if|else|for|while|each|media)",{token:"keyword.flow",next:"@controlstatementdeclaration"}]],controlstatementdeclaration:[["(in|from|through|if|to)\\b",{token:"keyword.flow"}],{include:"@term"},["{",{token:"delimiter.curly",switchTo:"@selectorbody"}]],functionbody:[["[@](return)",{token:"keyword"}],{include:"@variabledeclaration"},{include:"@term"},{include:"@controlstatement"},[";","delimiter"],["}",{token:"delimiter.curly",next:"@pop"}]],functioninvocation:[["@identifier\\(",{token:"meta",next:"@functionarguments"}]],functionarguments:[["\\$@identifier@ws:","attribute.name"],["[,]","delimiter"],{include:"@term"},["\\)",{token:"meta",next:"@pop"}]],strings:[['~?"',{token:"string.delimiter",next:"@stringenddoublequote"}],["~?'",{token:"string.delimiter",next:"@stringendquote"}]],stringenddoublequote:[["\\\\.","string"],['"',{token:"string.delimiter",next:"@pop"}],[".","string"]],stringendquote:[["\\\\.","string"],["'",{token:"string.delimiter",next:"@pop"}],[".","string"]]}};return s(k);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/shell/shell.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/shell/shell", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var a=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var n=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(r,e)=>{for(var i in e)a(r,i,{get:e[i],enumerable:!0})},d=(r,e,i,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of n(e))!l.call(r,t)&&t!==i&&a(r,t,{get:()=>e[t],enumerable:!(o=s(e,t))||o.enumerable});return r};var p=r=>d(a({},"__esModule",{value:!0}),r);var g={};c(g,{conf:()=>m,language:()=>u});var m={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}]},u={defaultToken:"",ignoreCase:!0,tokenPostfix:".shell",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"}],keywords:["if","then","do","else","elif","while","until","for","in","esac","fi","fin","fil","done","exit","set","unset","export","function"],builtins:["ab","awk","bash","beep","cat","cc","cd","chown","chmod","chroot","clear","cp","curl","cut","diff","echo","find","gawk","gcc","get","git","grep","hg","kill","killall","ln","ls","make","mkdir","openssl","mv","nc","node","npm","ping","ps","restart","rm","rmdir","sed","service","sh","shopt","shred","source","sort","sleep","ssh","start","stop","su","sudo","svn","tee","telnet","top","touch","vi","vim","wall","wc","wget","who","write","yes","zsh"],startingWithDash:/\-+\w+/,identifiersWithDashes:/[a-zA-Z]\w+(?:@startingWithDash)+/,symbols:/[=>{ "use strict";var moduleExports=(()=>{var f=Object.defineProperty;var t=Object.getOwnPropertyDescriptor;var n=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var o=(e,x)=>{for(var d in x)f(e,d,{get:x[d],enumerable:!0})},r=(e,x,d,u)=>{if(x&&typeof x=="object"||typeof x=="function")for(let i of n(x))!s.call(e,i)&&i!==d&&f(e,i,{get:()=>x[i],enumerable:!(u=t(x,i))||u.enumerable});return e};var a=e=>r(f({},"__esModule",{value:!0}),e);var l={};o(l,{conf:()=>c,language:()=>m});var c={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]}]},m={defaultToken:"",tokenPostfix:".sol",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"},{token:"delimiter.angle",open:"<",close:">"}],keywords:["pragma","solidity","contract","library","using","struct","function","modifier","constructor","address","string","bool","Int","Uint","Byte","Fixed","Ufixed","int","int8","int16","int24","int32","int40","int48","int56","int64","int72","int80","int88","int96","int104","int112","int120","int128","int136","int144","int152","int160","int168","int176","int184","int192","int200","int208","int216","int224","int232","int240","int248","int256","uint","uint8","uint16","uint24","uint32","uint40","uint48","uint56","uint64","uint72","uint80","uint88","uint96","uint104","uint112","uint120","uint128","uint136","uint144","uint152","uint160","uint168","uint176","uint184","uint192","uint200","uint208","uint216","uint224","uint232","uint240","uint248","uint256","byte","bytes","bytes1","bytes2","bytes3","bytes4","bytes5","bytes6","bytes7","bytes8","bytes9","bytes10","bytes11","bytes12","bytes13","bytes14","bytes15","bytes16","bytes17","bytes18","bytes19","bytes20","bytes21","bytes22","bytes23","bytes24","bytes25","bytes26","bytes27","bytes28","bytes29","bytes30","bytes31","bytes32","fixed","fixed0x8","fixed0x16","fixed0x24","fixed0x32","fixed0x40","fixed0x48","fixed0x56","fixed0x64","fixed0x72","fixed0x80","fixed0x88","fixed0x96","fixed0x104","fixed0x112","fixed0x120","fixed0x128","fixed0x136","fixed0x144","fixed0x152","fixed0x160","fixed0x168","fixed0x176","fixed0x184","fixed0x192","fixed0x200","fixed0x208","fixed0x216","fixed0x224","fixed0x232","fixed0x240","fixed0x248","fixed0x256","fixed8x8","fixed8x16","fixed8x24","fixed8x32","fixed8x40","fixed8x48","fixed8x56","fixed8x64","fixed8x72","fixed8x80","fixed8x88","fixed8x96","fixed8x104","fixed8x112","fixed8x120","fixed8x128","fixed8x136","fixed8x144","fixed8x152","fixed8x160","fixed8x168","fixed8x176","fixed8x184","fixed8x192","fixed8x200","fixed8x208","fixed8x216","fixed8x224","fixed8x232","fixed8x240","fixed8x248","fixed16x8","fixed16x16","fixed16x24","fixed16x32","fixed16x40","fixed16x48","fixed16x56","fixed16x64","fixed16x72","fixed16x80","fixed16x88","fixed16x96","fixed16x104","fixed16x112","fixed16x120","fixed16x128","fixed16x136","fixed16x144","fixed16x152","fixed16x160","fixed16x168","fixed16x176","fixed16x184","fixed16x192","fixed16x200","fixed16x208","fixed16x216","fixed16x224","fixed16x232","fixed16x240","fixed24x8","fixed24x16","fixed24x24","fixed24x32","fixed24x40","fixed24x48","fixed24x56","fixed24x64","fixed24x72","fixed24x80","fixed24x88","fixed24x96","fixed24x104","fixed24x112","fixed24x120","fixed24x128","fixed24x136","fixed24x144","fixed24x152","fixed24x160","fixed24x168","fixed24x176","fixed24x184","fixed24x192","fixed24x200","fixed24x208","fixed24x216","fixed24x224","fixed24x232","fixed32x8","fixed32x16","fixed32x24","fixed32x32","fixed32x40","fixed32x48","fixed32x56","fixed32x64","fixed32x72","fixed32x80","fixed32x88","fixed32x96","fixed32x104","fixed32x112","fixed32x120","fixed32x128","fixed32x136","fixed32x144","fixed32x152","fixed32x160","fixed32x168","fixed32x176","fixed32x184","fixed32x192","fixed32x200","fixed32x208","fixed32x216","fixed32x224","fixed40x8","fixed40x16","fixed40x24","fixed40x32","fixed40x40","fixed40x48","fixed40x56","fixed40x64","fixed40x72","fixed40x80","fixed40x88","fixed40x96","fixed40x104","fixed40x112","fixed40x120","fixed40x128","fixed40x136","fixed40x144","fixed40x152","fixed40x160","fixed40x168","fixed40x176","fixed40x184","fixed40x192","fixed40x200","fixed40x208","fixed40x216","fixed48x8","fixed48x16","fixed48x24","fixed48x32","fixed48x40","fixed48x48","fixed48x56","fixed48x64","fixed48x72","fixed48x80","fixed48x88","fixed48x96","fixed48x104","fixed48x112","fixed48x120","fixed48x128","fixed48x136","fixed48x144","fixed48x152","fixed48x160","fixed48x168","fixed48x176","fixed48x184","fixed48x192","fixed48x200","fixed48x208","fixed56x8","fixed56x16","fixed56x24","fixed56x32","fixed56x40","fixed56x48","fixed56x56","fixed56x64","fixed56x72","fixed56x80","fixed56x88","fixed56x96","fixed56x104","fixed56x112","fixed56x120","fixed56x128","fixed56x136","fixed56x144","fixed56x152","fixed56x160","fixed56x168","fixed56x176","fixed56x184","fixed56x192","fixed56x200","fixed64x8","fixed64x16","fixed64x24","fixed64x32","fixed64x40","fixed64x48","fixed64x56","fixed64x64","fixed64x72","fixed64x80","fixed64x88","fixed64x96","fixed64x104","fixed64x112","fixed64x120","fixed64x128","fixed64x136","fixed64x144","fixed64x152","fixed64x160","fixed64x168","fixed64x176","fixed64x184","fixed64x192","fixed72x8","fixed72x16","fixed72x24","fixed72x32","fixed72x40","fixed72x48","fixed72x56","fixed72x64","fixed72x72","fixed72x80","fixed72x88","fixed72x96","fixed72x104","fixed72x112","fixed72x120","fixed72x128","fixed72x136","fixed72x144","fixed72x152","fixed72x160","fixed72x168","fixed72x176","fixed72x184","fixed80x8","fixed80x16","fixed80x24","fixed80x32","fixed80x40","fixed80x48","fixed80x56","fixed80x64","fixed80x72","fixed80x80","fixed80x88","fixed80x96","fixed80x104","fixed80x112","fixed80x120","fixed80x128","fixed80x136","fixed80x144","fixed80x152","fixed80x160","fixed80x168","fixed80x176","fixed88x8","fixed88x16","fixed88x24","fixed88x32","fixed88x40","fixed88x48","fixed88x56","fixed88x64","fixed88x72","fixed88x80","fixed88x88","fixed88x96","fixed88x104","fixed88x112","fixed88x120","fixed88x128","fixed88x136","fixed88x144","fixed88x152","fixed88x160","fixed88x168","fixed96x8","fixed96x16","fixed96x24","fixed96x32","fixed96x40","fixed96x48","fixed96x56","fixed96x64","fixed96x72","fixed96x80","fixed96x88","fixed96x96","fixed96x104","fixed96x112","fixed96x120","fixed96x128","fixed96x136","fixed96x144","fixed96x152","fixed96x160","fixed104x8","fixed104x16","fixed104x24","fixed104x32","fixed104x40","fixed104x48","fixed104x56","fixed104x64","fixed104x72","fixed104x80","fixed104x88","fixed104x96","fixed104x104","fixed104x112","fixed104x120","fixed104x128","fixed104x136","fixed104x144","fixed104x152","fixed112x8","fixed112x16","fixed112x24","fixed112x32","fixed112x40","fixed112x48","fixed112x56","fixed112x64","fixed112x72","fixed112x80","fixed112x88","fixed112x96","fixed112x104","fixed112x112","fixed112x120","fixed112x128","fixed112x136","fixed112x144","fixed120x8","fixed120x16","fixed120x24","fixed120x32","fixed120x40","fixed120x48","fixed120x56","fixed120x64","fixed120x72","fixed120x80","fixed120x88","fixed120x96","fixed120x104","fixed120x112","fixed120x120","fixed120x128","fixed120x136","fixed128x8","fixed128x16","fixed128x24","fixed128x32","fixed128x40","fixed128x48","fixed128x56","fixed128x64","fixed128x72","fixed128x80","fixed128x88","fixed128x96","fixed128x104","fixed128x112","fixed128x120","fixed128x128","fixed136x8","fixed136x16","fixed136x24","fixed136x32","fixed136x40","fixed136x48","fixed136x56","fixed136x64","fixed136x72","fixed136x80","fixed136x88","fixed136x96","fixed136x104","fixed136x112","fixed136x120","fixed144x8","fixed144x16","fixed144x24","fixed144x32","fixed144x40","fixed144x48","fixed144x56","fixed144x64","fixed144x72","fixed144x80","fixed144x88","fixed144x96","fixed144x104","fixed144x112","fixed152x8","fixed152x16","fixed152x24","fixed152x32","fixed152x40","fixed152x48","fixed152x56","fixed152x64","fixed152x72","fixed152x80","fixed152x88","fixed152x96","fixed152x104","fixed160x8","fixed160x16","fixed160x24","fixed160x32","fixed160x40","fixed160x48","fixed160x56","fixed160x64","fixed160x72","fixed160x80","fixed160x88","fixed160x96","fixed168x8","fixed168x16","fixed168x24","fixed168x32","fixed168x40","fixed168x48","fixed168x56","fixed168x64","fixed168x72","fixed168x80","fixed168x88","fixed176x8","fixed176x16","fixed176x24","fixed176x32","fixed176x40","fixed176x48","fixed176x56","fixed176x64","fixed176x72","fixed176x80","fixed184x8","fixed184x16","fixed184x24","fixed184x32","fixed184x40","fixed184x48","fixed184x56","fixed184x64","fixed184x72","fixed192x8","fixed192x16","fixed192x24","fixed192x32","fixed192x40","fixed192x48","fixed192x56","fixed192x64","fixed200x8","fixed200x16","fixed200x24","fixed200x32","fixed200x40","fixed200x48","fixed200x56","fixed208x8","fixed208x16","fixed208x24","fixed208x32","fixed208x40","fixed208x48","fixed216x8","fixed216x16","fixed216x24","fixed216x32","fixed216x40","fixed224x8","fixed224x16","fixed224x24","fixed224x32","fixed232x8","fixed232x16","fixed232x24","fixed240x8","fixed240x16","fixed248x8","ufixed","ufixed0x8","ufixed0x16","ufixed0x24","ufixed0x32","ufixed0x40","ufixed0x48","ufixed0x56","ufixed0x64","ufixed0x72","ufixed0x80","ufixed0x88","ufixed0x96","ufixed0x104","ufixed0x112","ufixed0x120","ufixed0x128","ufixed0x136","ufixed0x144","ufixed0x152","ufixed0x160","ufixed0x168","ufixed0x176","ufixed0x184","ufixed0x192","ufixed0x200","ufixed0x208","ufixed0x216","ufixed0x224","ufixed0x232","ufixed0x240","ufixed0x248","ufixed0x256","ufixed8x8","ufixed8x16","ufixed8x24","ufixed8x32","ufixed8x40","ufixed8x48","ufixed8x56","ufixed8x64","ufixed8x72","ufixed8x80","ufixed8x88","ufixed8x96","ufixed8x104","ufixed8x112","ufixed8x120","ufixed8x128","ufixed8x136","ufixed8x144","ufixed8x152","ufixed8x160","ufixed8x168","ufixed8x176","ufixed8x184","ufixed8x192","ufixed8x200","ufixed8x208","ufixed8x216","ufixed8x224","ufixed8x232","ufixed8x240","ufixed8x248","ufixed16x8","ufixed16x16","ufixed16x24","ufixed16x32","ufixed16x40","ufixed16x48","ufixed16x56","ufixed16x64","ufixed16x72","ufixed16x80","ufixed16x88","ufixed16x96","ufixed16x104","ufixed16x112","ufixed16x120","ufixed16x128","ufixed16x136","ufixed16x144","ufixed16x152","ufixed16x160","ufixed16x168","ufixed16x176","ufixed16x184","ufixed16x192","ufixed16x200","ufixed16x208","ufixed16x216","ufixed16x224","ufixed16x232","ufixed16x240","ufixed24x8","ufixed24x16","ufixed24x24","ufixed24x32","ufixed24x40","ufixed24x48","ufixed24x56","ufixed24x64","ufixed24x72","ufixed24x80","ufixed24x88","ufixed24x96","ufixed24x104","ufixed24x112","ufixed24x120","ufixed24x128","ufixed24x136","ufixed24x144","ufixed24x152","ufixed24x160","ufixed24x168","ufixed24x176","ufixed24x184","ufixed24x192","ufixed24x200","ufixed24x208","ufixed24x216","ufixed24x224","ufixed24x232","ufixed32x8","ufixed32x16","ufixed32x24","ufixed32x32","ufixed32x40","ufixed32x48","ufixed32x56","ufixed32x64","ufixed32x72","ufixed32x80","ufixed32x88","ufixed32x96","ufixed32x104","ufixed32x112","ufixed32x120","ufixed32x128","ufixed32x136","ufixed32x144","ufixed32x152","ufixed32x160","ufixed32x168","ufixed32x176","ufixed32x184","ufixed32x192","ufixed32x200","ufixed32x208","ufixed32x216","ufixed32x224","ufixed40x8","ufixed40x16","ufixed40x24","ufixed40x32","ufixed40x40","ufixed40x48","ufixed40x56","ufixed40x64","ufixed40x72","ufixed40x80","ufixed40x88","ufixed40x96","ufixed40x104","ufixed40x112","ufixed40x120","ufixed40x128","ufixed40x136","ufixed40x144","ufixed40x152","ufixed40x160","ufixed40x168","ufixed40x176","ufixed40x184","ufixed40x192","ufixed40x200","ufixed40x208","ufixed40x216","ufixed48x8","ufixed48x16","ufixed48x24","ufixed48x32","ufixed48x40","ufixed48x48","ufixed48x56","ufixed48x64","ufixed48x72","ufixed48x80","ufixed48x88","ufixed48x96","ufixed48x104","ufixed48x112","ufixed48x120","ufixed48x128","ufixed48x136","ufixed48x144","ufixed48x152","ufixed48x160","ufixed48x168","ufixed48x176","ufixed48x184","ufixed48x192","ufixed48x200","ufixed48x208","ufixed56x8","ufixed56x16","ufixed56x24","ufixed56x32","ufixed56x40","ufixed56x48","ufixed56x56","ufixed56x64","ufixed56x72","ufixed56x80","ufixed56x88","ufixed56x96","ufixed56x104","ufixed56x112","ufixed56x120","ufixed56x128","ufixed56x136","ufixed56x144","ufixed56x152","ufixed56x160","ufixed56x168","ufixed56x176","ufixed56x184","ufixed56x192","ufixed56x200","ufixed64x8","ufixed64x16","ufixed64x24","ufixed64x32","ufixed64x40","ufixed64x48","ufixed64x56","ufixed64x64","ufixed64x72","ufixed64x80","ufixed64x88","ufixed64x96","ufixed64x104","ufixed64x112","ufixed64x120","ufixed64x128","ufixed64x136","ufixed64x144","ufixed64x152","ufixed64x160","ufixed64x168","ufixed64x176","ufixed64x184","ufixed64x192","ufixed72x8","ufixed72x16","ufixed72x24","ufixed72x32","ufixed72x40","ufixed72x48","ufixed72x56","ufixed72x64","ufixed72x72","ufixed72x80","ufixed72x88","ufixed72x96","ufixed72x104","ufixed72x112","ufixed72x120","ufixed72x128","ufixed72x136","ufixed72x144","ufixed72x152","ufixed72x160","ufixed72x168","ufixed72x176","ufixed72x184","ufixed80x8","ufixed80x16","ufixed80x24","ufixed80x32","ufixed80x40","ufixed80x48","ufixed80x56","ufixed80x64","ufixed80x72","ufixed80x80","ufixed80x88","ufixed80x96","ufixed80x104","ufixed80x112","ufixed80x120","ufixed80x128","ufixed80x136","ufixed80x144","ufixed80x152","ufixed80x160","ufixed80x168","ufixed80x176","ufixed88x8","ufixed88x16","ufixed88x24","ufixed88x32","ufixed88x40","ufixed88x48","ufixed88x56","ufixed88x64","ufixed88x72","ufixed88x80","ufixed88x88","ufixed88x96","ufixed88x104","ufixed88x112","ufixed88x120","ufixed88x128","ufixed88x136","ufixed88x144","ufixed88x152","ufixed88x160","ufixed88x168","ufixed96x8","ufixed96x16","ufixed96x24","ufixed96x32","ufixed96x40","ufixed96x48","ufixed96x56","ufixed96x64","ufixed96x72","ufixed96x80","ufixed96x88","ufixed96x96","ufixed96x104","ufixed96x112","ufixed96x120","ufixed96x128","ufixed96x136","ufixed96x144","ufixed96x152","ufixed96x160","ufixed104x8","ufixed104x16","ufixed104x24","ufixed104x32","ufixed104x40","ufixed104x48","ufixed104x56","ufixed104x64","ufixed104x72","ufixed104x80","ufixed104x88","ufixed104x96","ufixed104x104","ufixed104x112","ufixed104x120","ufixed104x128","ufixed104x136","ufixed104x144","ufixed104x152","ufixed112x8","ufixed112x16","ufixed112x24","ufixed112x32","ufixed112x40","ufixed112x48","ufixed112x56","ufixed112x64","ufixed112x72","ufixed112x80","ufixed112x88","ufixed112x96","ufixed112x104","ufixed112x112","ufixed112x120","ufixed112x128","ufixed112x136","ufixed112x144","ufixed120x8","ufixed120x16","ufixed120x24","ufixed120x32","ufixed120x40","ufixed120x48","ufixed120x56","ufixed120x64","ufixed120x72","ufixed120x80","ufixed120x88","ufixed120x96","ufixed120x104","ufixed120x112","ufixed120x120","ufixed120x128","ufixed120x136","ufixed128x8","ufixed128x16","ufixed128x24","ufixed128x32","ufixed128x40","ufixed128x48","ufixed128x56","ufixed128x64","ufixed128x72","ufixed128x80","ufixed128x88","ufixed128x96","ufixed128x104","ufixed128x112","ufixed128x120","ufixed128x128","ufixed136x8","ufixed136x16","ufixed136x24","ufixed136x32","ufixed136x40","ufixed136x48","ufixed136x56","ufixed136x64","ufixed136x72","ufixed136x80","ufixed136x88","ufixed136x96","ufixed136x104","ufixed136x112","ufixed136x120","ufixed144x8","ufixed144x16","ufixed144x24","ufixed144x32","ufixed144x40","ufixed144x48","ufixed144x56","ufixed144x64","ufixed144x72","ufixed144x80","ufixed144x88","ufixed144x96","ufixed144x104","ufixed144x112","ufixed152x8","ufixed152x16","ufixed152x24","ufixed152x32","ufixed152x40","ufixed152x48","ufixed152x56","ufixed152x64","ufixed152x72","ufixed152x80","ufixed152x88","ufixed152x96","ufixed152x104","ufixed160x8","ufixed160x16","ufixed160x24","ufixed160x32","ufixed160x40","ufixed160x48","ufixed160x56","ufixed160x64","ufixed160x72","ufixed160x80","ufixed160x88","ufixed160x96","ufixed168x8","ufixed168x16","ufixed168x24","ufixed168x32","ufixed168x40","ufixed168x48","ufixed168x56","ufixed168x64","ufixed168x72","ufixed168x80","ufixed168x88","ufixed176x8","ufixed176x16","ufixed176x24","ufixed176x32","ufixed176x40","ufixed176x48","ufixed176x56","ufixed176x64","ufixed176x72","ufixed176x80","ufixed184x8","ufixed184x16","ufixed184x24","ufixed184x32","ufixed184x40","ufixed184x48","ufixed184x56","ufixed184x64","ufixed184x72","ufixed192x8","ufixed192x16","ufixed192x24","ufixed192x32","ufixed192x40","ufixed192x48","ufixed192x56","ufixed192x64","ufixed200x8","ufixed200x16","ufixed200x24","ufixed200x32","ufixed200x40","ufixed200x48","ufixed200x56","ufixed208x8","ufixed208x16","ufixed208x24","ufixed208x32","ufixed208x40","ufixed208x48","ufixed216x8","ufixed216x16","ufixed216x24","ufixed216x32","ufixed216x40","ufixed224x8","ufixed224x16","ufixed224x24","ufixed224x32","ufixed232x8","ufixed232x16","ufixed232x24","ufixed240x8","ufixed240x16","ufixed248x8","event","enum","let","mapping","private","public","external","inherited","payable","true","false","var","import","constant","if","else","for","else","for","while","do","break","continue","throw","returns","return","suicide","new","is","this","super"],operators:["=",">","<","!","~","?",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>",">>>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>=",">>>="],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/,"number.float"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/,"number.hex"],[/0[0-7']*[0-7](@integersuffix)/,"number.octal"],[/0[bB][0-1']*[0-1](@integersuffix)/,"number.binary"],[/\d[\d']*\d(@integersuffix)/,"number"],[/\d(@integersuffix)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@doccomment"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],doccomment:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]]}};return a(l);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/sophia/sophia.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/sophia/sophia", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var l=(t,e)=>{for(var o in e)s(t,o,{get:e[o],enumerable:!0})},m=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of a(e))!c.call(t,n)&&n!==o&&s(t,n,{get:()=>e[n],enumerable:!(r=i(e,n))||r.enumerable});return t};var d=t=>m(s({},"__esModule",{value:!0}),t);var u={};l(u,{conf:()=>f,language:()=>g});var f={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]}]},g={defaultToken:"",tokenPostfix:".aes",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"},{token:"delimiter.angle",open:"<",close:">"}],keywords:["contract","library","entrypoint","function","stateful","state","hash","signature","tuple","list","address","string","bool","int","record","datatype","type","option","oracle","oracle_query","Call","Bits","Bytes","Oracle","String","Crypto","Address","Auth","Chain","None","Some","bits","bytes","event","let","map","private","public","true","false","var","if","else","throw"],operators:["=",">","<","!","~","?","::",":","==","<=",">=","!=","&&","||","++","--","+","-","*","/","&","|","^","%","<<",">>",">>>","+=","-=","*=","/=","&=","|=","^=","%=","<<=",">>=",">>>="],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/,"number.float"],[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/,"number.float"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/,"number.hex"],[/0[0-7']*[0-7](@integersuffix)/,"number.octal"],[/0[bB][0-1']*[0-1](@integersuffix)/,"number.binary"],[/\d[\d']*\d(@integersuffix)/,"number"],[/\d(@integersuffix)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@doccomment"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],doccomment:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]]}};return d(u);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/sparql/sparql.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/sparql/sparql", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var o=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var d=(s,e)=>{for(var n in e)o(s,n,{get:e[n],enumerable:!0})},c=(s,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of a(e))!l.call(s,t)&&t!==n&&o(s,t,{get:()=>e[t],enumerable:!(r=i(e,t))||r.enumerable});return s};var g=s=>c(o({},"__esModule",{value:!0}),s);var m={};d(m,{conf:()=>u,language:()=>p});var u={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"'",close:"'",notIn:["string"]},{open:'"',close:'"',notIn:["string"]},{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"}]},p={defaultToken:"",tokenPostfix:".rq",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"},{token:"delimiter.angle",open:"<",close:">"}],keywords:["add","as","asc","ask","base","by","clear","construct","copy","create","data","delete","desc","describe","distinct","drop","false","filter","from","graph","group","having","in","insert","limit","load","minus","move","named","not","offset","optional","order","prefix","reduced","select","service","silent","to","true","undef","union","using","values","where","with"],builtinFunctions:["a","abs","avg","bind","bnode","bound","ceil","coalesce","concat","contains","count","datatype","day","encode_for_uri","exists","floor","group_concat","hours","if","iri","isblank","isiri","isliteral","isnumeric","isuri","lang","langmatches","lcase","max","md5","min","minutes","month","now","rand","regex","replace","round","sameterm","sample","seconds","sha1","sha256","sha384","sha512","str","strafter","strbefore","strdt","strends","strlang","strlen","strstarts","struuid","substr","sum","timezone","tz","ucase","uri","uuid","year"],ignoreCase:!0,tokenizer:{root:[[/<[^\s\u00a0>]*>?/,"tag"],{include:"@strings"},[/#.*/,"comment"],[/[{}()\[\]]/,"@brackets"],[/[;,.]/,"delimiter"],[/[_\w\d]+:(\.(?=[\w_\-\\%])|[:\w_-]|\\[-\\_~.!$&'()*+,;=/?#@%]|%[a-f\d][a-f\d])*/,"tag"],[/:(\.(?=[\w_\-\\%])|[:\w_-]|\\[-\\_~.!$&'()*+,;=/?#@%]|%[a-f\d][a-f\d])+/,"tag"],[/[$?]?[_\w\d]+/,{cases:{"@keywords":{token:"keyword"},"@builtinFunctions":{token:"predefined.sql"},"@default":"identifier"}}],[/\^\^/,"operator.sql"],[/\^[*+\-<>=&|^\/!?]*/,"operator.sql"],[/[*+\-<>=&|\/!?]/,"operator.sql"],[/@[a-z\d\-]*/,"metatag.html"],[/\s+/,"white"]],strings:[[/'([^'\\]|\\.)*$/,"string.invalid"],[/'$/,"string.sql","@pop"],[/'/,"string.sql","@stringBody"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"$/,"string.sql","@pop"],[/"/,"string.sql","@dblStringBody"]],stringBody:[[/[^\\']+/,"string.sql"],[/\\./,"string.escape"],[/'/,"string.sql","@pop"]],dblStringBody:[[/[^\\"]+/,"string.sql"],[/\\./,"string.escape"],[/"/,"string.sql","@pop"]]}};return g(m);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/sql/sql.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/sql/sql", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var I=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var L=(T,E)=>{for(var A in E)I(T,A,{get:E[A],enumerable:!0})},e=(T,E,A,N)=>{if(E&&typeof E=="object"||typeof E=="function")for(let R of O(E))!C.call(T,R)&&R!==A&&I(T,R,{get:()=>E[R],enumerable:!(N=S(E,R))||N.enumerable});return T};var P=T=>e(I({},"__esModule",{value:!0}),T);var M={};L(M,{conf:()=>D,language:()=>U});var D={comments:{lineComment:"--",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},U={defaultToken:"",tokenPostfix:".sql",ignoreCase:!0,brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"}],keywords:["ABORT","ABSOLUTE","ACTION","ADA","ADD","AFTER","ALL","ALLOCATE","ALTER","ALWAYS","ANALYZE","AND","ANY","ARE","AS","ASC","ASSERTION","AT","ATTACH","AUTHORIZATION","AUTOINCREMENT","AVG","BACKUP","BEFORE","BEGIN","BETWEEN","BIT","BIT_LENGTH","BOTH","BREAK","BROWSE","BULK","BY","CASCADE","CASCADED","CASE","CAST","CATALOG","CHAR","CHARACTER","CHARACTER_LENGTH","CHAR_LENGTH","CHECK","CHECKPOINT","CLOSE","CLUSTERED","COALESCE","COLLATE","COLLATION","COLUMN","COMMIT","COMPUTE","CONFLICT","CONNECT","CONNECTION","CONSTRAINT","CONSTRAINTS","CONTAINS","CONTAINSTABLE","CONTINUE","CONVERT","CORRESPONDING","COUNT","CREATE","CROSS","CURRENT","CURRENT_DATE","CURRENT_TIME","CURRENT_TIMESTAMP","CURRENT_USER","CURSOR","DATABASE","DATE","DAY","DBCC","DEALLOCATE","DEC","DECIMAL","DECLARE","DEFAULT","DEFERRABLE","DEFERRED","DELETE","DENY","DESC","DESCRIBE","DESCRIPTOR","DETACH","DIAGNOSTICS","DISCONNECT","DISK","DISTINCT","DISTRIBUTED","DO","DOMAIN","DOUBLE","DROP","DUMP","EACH","ELSE","END","END-EXEC","ERRLVL","ESCAPE","EXCEPT","EXCEPTION","EXCLUDE","EXCLUSIVE","EXEC","EXECUTE","EXISTS","EXIT","EXPLAIN","EXTERNAL","EXTRACT","FAIL","FALSE","FETCH","FILE","FILLFACTOR","FILTER","FIRST","FLOAT","FOLLOWING","FOR","FOREIGN","FORTRAN","FOUND","FREETEXT","FREETEXTTABLE","FROM","FULL","FUNCTION","GENERATED","GET","GLOB","GLOBAL","GO","GOTO","GRANT","GROUP","GROUPS","HAVING","HOLDLOCK","HOUR","IDENTITY","IDENTITYCOL","IDENTITY_INSERT","IF","IGNORE","IMMEDIATE","IN","INCLUDE","INDEX","INDEXED","INDICATOR","INITIALLY","INNER","INPUT","INSENSITIVE","INSERT","INSTEAD","INT","INTEGER","INTERSECT","INTERVAL","INTO","IS","ISNULL","ISOLATION","JOIN","KEY","KILL","LANGUAGE","LAST","LEADING","LEFT","LEVEL","LIKE","LIMIT","LINENO","LOAD","LOCAL","LOWER","MATCH","MATERIALIZED","MAX","MERGE","MIN","MINUTE","MODULE","MONTH","NAMES","NATIONAL","NATURAL","NCHAR","NEXT","NO","NOCHECK","NONCLUSTERED","NONE","NOT","NOTHING","NOTNULL","NULL","NULLIF","NULLS","NUMERIC","OCTET_LENGTH","OF","OFF","OFFSET","OFFSETS","ON","ONLY","OPEN","OPENDATASOURCE","OPENQUERY","OPENROWSET","OPENXML","OPTION","OR","ORDER","OTHERS","OUTER","OUTPUT","OVER","OVERLAPS","PAD","PARTIAL","PARTITION","PASCAL","PERCENT","PIVOT","PLAN","POSITION","PRAGMA","PRECEDING","PRECISION","PREPARE","PRESERVE","PRIMARY","PRINT","PRIOR","PRIVILEGES","PROC","PROCEDURE","PUBLIC","QUERY","RAISE","RAISERROR","RANGE","READ","READTEXT","REAL","RECONFIGURE","RECURSIVE","REFERENCES","REGEXP","REINDEX","RELATIVE","RELEASE","RENAME","REPLACE","REPLICATION","RESTORE","RESTRICT","RETURN","RETURNING","REVERT","REVOKE","RIGHT","ROLLBACK","ROW","ROWCOUNT","ROWGUIDCOL","ROWS","RULE","SAVE","SAVEPOINT","SCHEMA","SCROLL","SECOND","SECTION","SECURITYAUDIT","SELECT","SEMANTICKEYPHRASETABLE","SEMANTICSIMILARITYDETAILSTABLE","SEMANTICSIMILARITYTABLE","SESSION","SESSION_USER","SET","SETUSER","SHUTDOWN","SIZE","SMALLINT","SOME","SPACE","SQL","SQLCA","SQLCODE","SQLERROR","SQLSTATE","SQLWARNING","STATISTICS","SUBSTRING","SUM","SYSTEM_USER","TABLE","TABLESAMPLE","TEMP","TEMPORARY","TEXTSIZE","THEN","TIES","TIME","TIMESTAMP","TIMEZONE_HOUR","TIMEZONE_MINUTE","TO","TOP","TRAILING","TRAN","TRANSACTION","TRANSLATE","TRANSLATION","TRIGGER","TRIM","TRUE","TRUNCATE","TRY_CONVERT","TSEQUAL","UNBOUNDED","UNION","UNIQUE","UNKNOWN","UNPIVOT","UPDATE","UPDATETEXT","UPPER","USAGE","USE","USER","USING","VACUUM","VALUE","VALUES","VARCHAR","VARYING","VIEW","VIRTUAL","WAITFOR","WHEN","WHENEVER","WHERE","WHILE","WINDOW","WITH","WITHIN GROUP","WITHOUT","WORK","WRITE","WRITETEXT","YEAR","ZONE"],operators:["ALL","AND","ANY","BETWEEN","EXISTS","IN","LIKE","NOT","OR","SOME","EXCEPT","INTERSECT","UNION","APPLY","CROSS","FULL","INNER","JOIN","LEFT","OUTER","RIGHT","CONTAINS","FREETEXT","IS","NULL","PIVOT","UNPIVOT","MATCHED"],builtinFunctions:["AVG","CHECKSUM_AGG","COUNT","COUNT_BIG","GROUPING","GROUPING_ID","MAX","MIN","SUM","STDEV","STDEVP","VAR","VARP","CUME_DIST","FIRST_VALUE","LAG","LAST_VALUE","LEAD","PERCENTILE_CONT","PERCENTILE_DISC","PERCENT_RANK","COLLATE","COLLATIONPROPERTY","TERTIARY_WEIGHTS","FEDERATION_FILTERING_VALUE","CAST","CONVERT","PARSE","TRY_CAST","TRY_CONVERT","TRY_PARSE","ASYMKEY_ID","ASYMKEYPROPERTY","CERTPROPERTY","CERT_ID","CRYPT_GEN_RANDOM","DECRYPTBYASYMKEY","DECRYPTBYCERT","DECRYPTBYKEY","DECRYPTBYKEYAUTOASYMKEY","DECRYPTBYKEYAUTOCERT","DECRYPTBYPASSPHRASE","ENCRYPTBYASYMKEY","ENCRYPTBYCERT","ENCRYPTBYKEY","ENCRYPTBYPASSPHRASE","HASHBYTES","IS_OBJECTSIGNED","KEY_GUID","KEY_ID","KEY_NAME","SIGNBYASYMKEY","SIGNBYCERT","SYMKEYPROPERTY","VERIFYSIGNEDBYCERT","VERIFYSIGNEDBYASYMKEY","CURSOR_STATUS","DATALENGTH","IDENT_CURRENT","IDENT_INCR","IDENT_SEED","IDENTITY","SQL_VARIANT_PROPERTY","CURRENT_TIMESTAMP","DATEADD","DATEDIFF","DATEFROMPARTS","DATENAME","DATEPART","DATETIME2FROMPARTS","DATETIMEFROMPARTS","DATETIMEOFFSETFROMPARTS","DAY","EOMONTH","GETDATE","GETUTCDATE","ISDATE","MONTH","SMALLDATETIMEFROMPARTS","SWITCHOFFSET","SYSDATETIME","SYSDATETIMEOFFSET","SYSUTCDATETIME","TIMEFROMPARTS","TODATETIMEOFFSET","YEAR","CHOOSE","COALESCE","IIF","NULLIF","ABS","ACOS","ASIN","ATAN","ATN2","CEILING","COS","COT","DEGREES","EXP","FLOOR","LOG","LOG10","PI","POWER","RADIANS","RAND","ROUND","SIGN","SIN","SQRT","SQUARE","TAN","APP_NAME","APPLOCK_MODE","APPLOCK_TEST","ASSEMBLYPROPERTY","COL_LENGTH","COL_NAME","COLUMNPROPERTY","DATABASE_PRINCIPAL_ID","DATABASEPROPERTYEX","DB_ID","DB_NAME","FILE_ID","FILE_IDEX","FILE_NAME","FILEGROUP_ID","FILEGROUP_NAME","FILEGROUPPROPERTY","FILEPROPERTY","FULLTEXTCATALOGPROPERTY","FULLTEXTSERVICEPROPERTY","INDEX_COL","INDEXKEY_PROPERTY","INDEXPROPERTY","OBJECT_DEFINITION","OBJECT_ID","OBJECT_NAME","OBJECT_SCHEMA_NAME","OBJECTPROPERTY","OBJECTPROPERTYEX","ORIGINAL_DB_NAME","PARSENAME","SCHEMA_ID","SCHEMA_NAME","SCOPE_IDENTITY","SERVERPROPERTY","STATS_DATE","TYPE_ID","TYPE_NAME","TYPEPROPERTY","DENSE_RANK","NTILE","RANK","ROW_NUMBER","PUBLISHINGSERVERNAME","OPENDATASOURCE","OPENQUERY","OPENROWSET","OPENXML","CERTENCODED","CERTPRIVATEKEY","CURRENT_USER","HAS_DBACCESS","HAS_PERMS_BY_NAME","IS_MEMBER","IS_ROLEMEMBER","IS_SRVROLEMEMBER","LOGINPROPERTY","ORIGINAL_LOGIN","PERMISSIONS","PWDENCRYPT","PWDCOMPARE","SESSION_USER","SESSIONPROPERTY","SUSER_ID","SUSER_NAME","SUSER_SID","SUSER_SNAME","SYSTEM_USER","USER","USER_ID","USER_NAME","ASCII","CHAR","CHARINDEX","CONCAT","DIFFERENCE","FORMAT","LEFT","LEN","LOWER","LTRIM","NCHAR","PATINDEX","QUOTENAME","REPLACE","REPLICATE","REVERSE","RIGHT","RTRIM","SOUNDEX","SPACE","STR","STUFF","SUBSTRING","UNICODE","UPPER","BINARY_CHECKSUM","CHECKSUM","CONNECTIONPROPERTY","CONTEXT_INFO","CURRENT_REQUEST_ID","ERROR_LINE","ERROR_NUMBER","ERROR_MESSAGE","ERROR_PROCEDURE","ERROR_SEVERITY","ERROR_STATE","FORMATMESSAGE","GETANSINULL","GET_FILESTREAM_TRANSACTION_CONTEXT","HOST_ID","HOST_NAME","ISNULL","ISNUMERIC","MIN_ACTIVE_ROWVERSION","NEWID","NEWSEQUENTIALID","ROWCOUNT_BIG","XACT_STATE","TEXTPTR","TEXTVALID","COLUMNS_UPDATED","EVENTDATA","TRIGGER_NESTLEVEL","UPDATE","CHANGETABLE","CHANGE_TRACKING_CONTEXT","CHANGE_TRACKING_CURRENT_VERSION","CHANGE_TRACKING_IS_COLUMN_IN_MASK","CHANGE_TRACKING_MIN_VALID_VERSION","CONTAINSTABLE","FREETEXTTABLE","SEMANTICKEYPHRASETABLE","SEMANTICSIMILARITYDETAILSTABLE","SEMANTICSIMILARITYTABLE","FILETABLEROOTPATH","GETFILENAMESPACEPATH","GETPATHLOCATOR","PATHNAME","GET_TRANSMISSION_STATUS"],builtinVariables:["@@DATEFIRST","@@DBTS","@@LANGID","@@LANGUAGE","@@LOCK_TIMEOUT","@@MAX_CONNECTIONS","@@MAX_PRECISION","@@NESTLEVEL","@@OPTIONS","@@REMSERVER","@@SERVERNAME","@@SERVICENAME","@@SPID","@@TEXTSIZE","@@VERSION","@@CURSOR_ROWS","@@FETCH_STATUS","@@DATEFIRST","@@PROCID","@@ERROR","@@IDENTITY","@@ROWCOUNT","@@TRANCOUNT","@@CONNECTIONS","@@CPU_BUSY","@@IDLE","@@IO_BUSY","@@PACKET_ERRORS","@@PACK_RECEIVED","@@PACK_SENT","@@TIMETICKS","@@TOTAL_ERRORS","@@TOTAL_READ","@@TOTAL_WRITE"],pseudoColumns:["$ACTION","$IDENTITY","$ROWGUID","$PARTITION"],tokenizer:{root:[{include:"@comments"},{include:"@whitespace"},{include:"@pseudoColumns"},{include:"@numbers"},{include:"@strings"},{include:"@complexIdentifiers"},{include:"@scopes"},[/[;,.]/,"delimiter"],[/[()]/,"@brackets"],[/[\w@#$]+/,{cases:{"@operators":"operator","@builtinVariables":"predefined","@builtinFunctions":"predefined","@keywords":"keyword","@default":"identifier"}}],[/[<>=!%&+\-*/|~^]/,"operator"]],whitespace:[[/\s+/,"white"]],comments:[[/--+.*/,"comment"],[/\/\*/,{token:"comment.quote",next:"@comment"}]],comment:[[/[^*/]+/,"comment"],[/\*\//,{token:"comment.quote",next:"@pop"}],[/./,"comment"]],pseudoColumns:[[/[$][A-Za-z_][\w@#$]*/,{cases:{"@pseudoColumns":"predefined","@default":"identifier"}}]],numbers:[[/0[xX][0-9a-fA-F]*/,"number"],[/[$][+-]*\d*(\.\d*)?/,"number"],[/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/,"number"]],strings:[[/N'/,{token:"string",next:"@string"}],[/'/,{token:"string",next:"@string"}]],string:[[/[^']+/,"string"],[/''/,"string"],[/'/,{token:"string",next:"@pop"}]],complexIdentifiers:[[/\[/,{token:"identifier.quote",next:"@bracketedIdentifier"}],[/"/,{token:"identifier.quote",next:"@quotedIdentifier"}]],bracketedIdentifier:[[/[^\]]+/,"identifier"],[/]]/,"identifier"],[/]/,{token:"identifier.quote",next:"@pop"}]],quotedIdentifier:[[/[^"]+/,"identifier"],[/""/,"identifier"],[/"/,{token:"identifier.quote",next:"@pop"}]],scopes:[[/BEGIN\s+(DISTRIBUTED\s+)?TRAN(SACTION)?\b/i,"keyword"],[/BEGIN\s+TRY\b/i,{token:"keyword.try"}],[/END\s+TRY\b/i,{token:"keyword.try"}],[/BEGIN\s+CATCH\b/i,{token:"keyword.catch"}],[/END\s+CATCH\b/i,{token:"keyword.catch"}],[/(BEGIN|CASE)\b/i,{token:"keyword.block"}],[/END\b/i,{token:"keyword.block"}],[/WHEN\b/i,{token:"keyword.choice"}],[/THEN\b/i,{token:"keyword.choice"}]]}};return P(M);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/st/st.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/st/st", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var d=(n,e)=>{for(var t in e)r(n,t,{get:e[t],enumerable:!0})},l=(n,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of c(e))!i.call(n,o)&&o!==t&&r(n,o,{get:()=>e[o],enumerable:!(a=s(e,o))||a.enumerable});return n};var _=n=>l(r({},"__esModule",{value:!0}),n);var m={};d(m,{conf:()=>p,language:()=>u});var p={comments:{lineComment:"//",blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"],["var","end_var"],["var_input","end_var"],["var_output","end_var"],["var_in_out","end_var"],["var_temp","end_var"],["var_global","end_var"],["var_access","end_var"],["var_external","end_var"],["type","end_type"],["struct","end_struct"],["program","end_program"],["function","end_function"],["function_block","end_function_block"],["action","end_action"],["step","end_step"],["initial_step","end_step"],["transaction","end_transaction"],["configuration","end_configuration"],["tcp","end_tcp"],["recource","end_recource"],["channel","end_channel"],["library","end_library"],["folder","end_folder"],["binaries","end_binaries"],["includes","end_includes"],["sources","end_sources"]],autoClosingPairs:[{open:"[",close:"]"},{open:"{",close:"}"},{open:"(",close:")"},{open:"/*",close:"*/"},{open:"'",close:"'",notIn:["string_sq"]},{open:'"',close:'"',notIn:["string_dq"]},{open:"var_input",close:"end_var"},{open:"var_output",close:"end_var"},{open:"var_in_out",close:"end_var"},{open:"var_temp",close:"end_var"},{open:"var_global",close:"end_var"},{open:"var_access",close:"end_var"},{open:"var_external",close:"end_var"},{open:"type",close:"end_type"},{open:"struct",close:"end_struct"},{open:"program",close:"end_program"},{open:"function",close:"end_function"},{open:"function_block",close:"end_function_block"},{open:"action",close:"end_action"},{open:"step",close:"end_step"},{open:"initial_step",close:"end_step"},{open:"transaction",close:"end_transaction"},{open:"configuration",close:"end_configuration"},{open:"tcp",close:"end_tcp"},{open:"recource",close:"end_recource"},{open:"channel",close:"end_channel"},{open:"library",close:"end_library"},{open:"folder",close:"end_folder"},{open:"binaries",close:"end_binaries"},{open:"includes",close:"end_includes"},{open:"sources",close:"end_sources"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"var",close:"end_var"},{open:"var_input",close:"end_var"},{open:"var_output",close:"end_var"},{open:"var_in_out",close:"end_var"},{open:"var_temp",close:"end_var"},{open:"var_global",close:"end_var"},{open:"var_access",close:"end_var"},{open:"var_external",close:"end_var"},{open:"type",close:"end_type"},{open:"struct",close:"end_struct"},{open:"program",close:"end_program"},{open:"function",close:"end_function"},{open:"function_block",close:"end_function_block"},{open:"action",close:"end_action"},{open:"step",close:"end_step"},{open:"initial_step",close:"end_step"},{open:"transaction",close:"end_transaction"},{open:"configuration",close:"end_configuration"},{open:"tcp",close:"end_tcp"},{open:"recource",close:"end_recource"},{open:"channel",close:"end_channel"},{open:"library",close:"end_library"},{open:"folder",close:"end_folder"},{open:"binaries",close:"end_binaries"},{open:"includes",close:"end_includes"},{open:"sources",close:"end_sources"}],folding:{markers:{start:new RegExp("^\\s*#pragma\\s+region\\b"),end:new RegExp("^\\s*#pragma\\s+endregion\\b")}}},u={defaultToken:"",tokenPostfix:".st",ignoreCase:!0,brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"}],keywords:["if","end_if","elsif","else","case","of","to","__try","__catch","__finally","do","with","by","while","repeat","end_while","end_repeat","end_case","for","end_for","task","retain","non_retain","constant","with","at","exit","return","interval","priority","address","port","on_channel","then","iec","file","uses","version","packagetype","displayname","copyright","summary","vendor","common_source","from","extends","implements"],constant:["false","true","null"],defineKeywords:["var","var_input","var_output","var_in_out","var_temp","var_global","var_access","var_external","end_var","type","end_type","struct","end_struct","program","end_program","function","end_function","function_block","end_function_block","interface","end_interface","method","end_method","property","end_property","namespace","end_namespace","configuration","end_configuration","tcp","end_tcp","resource","end_resource","channel","end_channel","library","end_library","folder","end_folder","binaries","end_binaries","includes","end_includes","sources","end_sources","action","end_action","step","initial_step","end_step","transaction","end_transaction"],typeKeywords:["int","sint","dint","lint","usint","uint","udint","ulint","real","lreal","time","date","time_of_day","date_and_time","string","bool","byte","word","dword","array","pointer","lword"],operators:["=",">","<",":",":=","<=",">=","<>","&","+","-","*","**","MOD","^","or","and","not","xor","abs","acos","asin","atan","cos","exp","expt","ln","log","sin","sqrt","tan","sel","max","min","limit","mux","shl","shr","rol","ror","indexof","sizeof","adr","adrinst","bitadr","is_valid","ref","ref_to"],builtinVariables:[],builtinFunctions:["sr","rs","tp","ton","tof","eq","ge","le","lt","ne","round","trunc","ctd","\u0441tu","ctud","r_trig","f_trig","move","concat","delete","find","insert","left","len","replace","right","rtc"],symbols:/[=>{ "use strict";var moduleExports=(()=>{var i=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(o,e)=>{for(var n in e)i(o,n,{get:e[n],enumerable:!0})},u=(o,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of s(e))!l.call(o,t)&&t!==n&&i(o,t,{get:()=>e[t],enumerable:!(r=a(e,t))||r.enumerable});return o};var d=o=>u(i({},"__esModule",{value:!0}),o);var f={};c(f,{conf:()=>p,language:()=>m});var p={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}]},m={defaultToken:"",tokenPostfix:".swift",identifier:/[a-zA-Z_][\w$]*/,attributes:["@GKInspectable","@IBAction","@IBDesignable","@IBInspectable","@IBOutlet","@IBSegueAction","@NSApplicationMain","@NSCopying","@NSManaged","@Sendable","@UIApplicationMain","@autoclosure","@actorIndependent","@asyncHandler","@available","@convention","@derivative","@differentiable","@discardableResult","@dynamicCallable","@dynamicMemberLookup","@escaping","@frozen","@globalActor","@inlinable","@inline","@main","@noDerivative","@nonobjc","@noreturn","@objc","@objcMembers","@preconcurrency","@propertyWrapper","@requires_stored_property_inits","@resultBuilder","@testable","@unchecked","@unknown","@usableFromInline","@warn_unqualified_access"],accessmodifiers:["open","public","internal","fileprivate","private"],keywords:["#available","#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warning","Any","Protocol","Self","Type","actor","as","assignment","associatedtype","associativity","async","await","break","case","catch","class","continue","convenience","default","defer","deinit","didSet","do","dynamic","dynamicType","else","enum","extension","fallthrough","false","fileprivate","final","for","func","get","guard","higherThan","if","import","in","indirect","infix","init","inout","internal","is","isolated","lazy","left","let","lowerThan","mutating","nil","none","nonisolated","nonmutating","open","operator","optional","override","postfix","precedence","precedencegroup","prefix","private","protocol","public","repeat","required","rethrows","return","right","safe","self","set","some","static","struct","subscript","super","switch","throw","throws","true","try","typealias","unowned","unsafe","var","weak","where","while","willSet","__consuming","__owned"],symbols:/[=(){}\[\].,:;@#\_&\-<>`?!+*\\\/]/,operatorstart:/[\/=\-+!*%<>&|^~?\u00A1-\u00A7\u00A9\u00AB\u00AC\u00AE\u00B0-\u00B1\u00B6\u00BB\u00BF\u00D7\u00F7\u2016-\u2017\u2020-\u2027\u2030-\u203E\u2041-\u2053\u2055-\u205E\u2190-\u23FF\u2500-\u2775\u2794-\u2BFF\u2E00-\u2E7F\u3001-\u3003\u3008-\u3030]/,operatorend:/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE00-\uFE0F\uFE20-\uFE2F\uE0100-\uE01EF]/,operators:/(@operatorstart)((@operatorstart)|(@operatorend))*/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:"@whitespace"},{include:"@comment"},{include:"@attribute"},{include:"@literal"},{include:"@keyword"},{include:"@invokedmethod"},{include:"@symbol"}],whitespace:[[/\s+/,"white"],[/"""/,"string.quote","@endDblDocString"]],endDblDocString:[[/[^"]+/,"string"],[/\\"/,"string"],[/"""/,"string.quote","@popall"],[/"/,"string"]],symbol:[[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/[.]/,"delimiter"],[/@operators/,"operator"],[/@symbols/,"operator"]],comment:[[/\/\/\/.*$/,"comment.doc"],[/\/\*\*/,"comment.doc","@commentdocbody"],[/\/\/.*$/,"comment"],[/\/\*/,"comment","@commentbody"]],commentdocbody:[[/\/\*/,"comment","@commentbody"],[/\*\//,"comment.doc","@pop"],[/\:[a-zA-Z]+\:/,"comment.doc.param"],[/./,"comment.doc"]],commentbody:[[/\/\*/,"comment","@commentbody"],[/\*\//,"comment","@pop"],[/./,"comment"]],attribute:[[/@@@identifier/,{cases:{"@attributes":"keyword.control","@default":""}}]],literal:[[/"/,{token:"string.quote",next:"@stringlit"}],[/0[b]([01]_?)+/,"number.binary"],[/0[o]([0-7]_?)+/,"number.octal"],[/0[x]([0-9a-fA-F]_?)+([pP][\-+](\d_?)+)?/,"number.hex"],[/(\d_?)*\.(\d_?)+([eE][\-+]?(\d_?)+)?/,"number.float"],[/(\d_?)+/,"number"]],stringlit:[[/\\\(/,{token:"operator",next:"@interpolatedexpression"}],[/@escapes/,"string"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",next:"@pop"}],[/./,"string"]],interpolatedexpression:[[/\(/,{token:"operator",next:"@interpolatedexpression"}],[/\)/,{token:"operator",next:"@pop"}],{include:"@literal"},{include:"@keyword"},{include:"@symbol"}],keyword:[[/`/,{token:"operator",next:"@escapedkeyword"}],[/@identifier/,{cases:{"@keywords":"keyword","[A-Z][a-zA-Z0-9$]*":"type.identifier","@default":"identifier"}}]],escapedkeyword:[[/`/,{token:"operator",next:"@pop"}],[/./,"identifier"]],invokedmethod:[[/([.])(@identifier)/,{cases:{$2:["delimeter","type.identifier"],"@default":""}}]]}};return d(f);})(); /*!--------------------------------------------------------------------------------------------- * Copyright (C) David Owens II, owensd.io. All rights reserved. *--------------------------------------------------------------------------------------------*/ return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/systemverilog/systemverilog.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/systemverilog/systemverilog", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var d=(n,e)=>{for(var t in e)r(n,t,{get:e[t],enumerable:!0})},l=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of a(e))!c.call(n,i)&&i!==t&&r(n,i,{get:()=>e[i],enumerable:!(o=s(e,i))||o.enumerable});return n};var p=n=>l(r({},"__esModule",{value:!0}),n);var f={};d(f,{conf:()=>u,language:()=>m});var u={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"],["begin","end"],["case","endcase"],["casex","endcase"],["casez","endcase"],["checker","endchecker"],["class","endclass"],["clocking","endclocking"],["config","endconfig"],["function","endfunction"],["generate","endgenerate"],["group","endgroup"],["interface","endinterface"],["module","endmodule"],["package","endpackage"],["primitive","endprimitive"],["program","endprogram"],["property","endproperty"],["specify","endspecify"],["sequence","endsequence"],["table","endtable"],["task","endtask"]],autoClosingPairs:[{open:"[",close:"]"},{open:"{",close:"}"},{open:"(",close:")"},{open:"'",close:"'",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{offSide:!1,markers:{start:new RegExp("^(?:\\s*|.*(?!\\/[\\/\\*])[^\\w])(?:begin|case(x|z)?|class|clocking|config|covergroup|function|generate|interface|module|package|primitive|property|program|sequence|specify|table|task)\\b"),end:new RegExp("^(?:\\s*|.*(?!\\/[\\/\\*])[^\\w])(?:end|endcase|endclass|endclocking|endconfig|endgroup|endfunction|endgenerate|endinterface|endmodule|endpackage|endprimitive|endproperty|endprogram|endsequence|endspecify|endtable|endtask)\\b")}}},m={defaultToken:"",tokenPostfix:".sv",brackets:[{token:"delimiter.curly",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"},{token:"delimiter.angle",open:"<",close:">"}],keywords:["accept_on","alias","always","always_comb","always_ff","always_latch","and","assert","assign","assume","automatic","before","begin","bind","bins","binsof","bit","break","buf","bufif0","bufif1","byte","case","casex","casez","cell","chandle","checker","class","clocking","cmos","config","const","constraint","context","continue","cover","covergroup","coverpoint","cross","deassign","default","defparam","design","disable","dist","do","edge","else","end","endcase","endchecker","endclass","endclocking","endconfig","endfunction","endgenerate","endgroup","endinterface","endmodule","endpackage","endprimitive","endprogram","endproperty","endspecify","endsequence","endtable","endtask","enum","event","eventually","expect","export","extends","extern","final","first_match","for","force","foreach","forever","fork","forkjoin","function","generate","genvar","global","highz0","highz1","if","iff","ifnone","ignore_bins","illegal_bins","implements","implies","import","incdir","include","initial","inout","input","inside","instance","int","integer","interconnect","interface","intersect","join","join_any","join_none","large","let","liblist","library","local","localparam","logic","longint","macromodule","matches","medium","modport","module","nand","negedge","nettype","new","nexttime","nmos","nor","noshowcancelled","not","notif0","notif1","null","or","output","package","packed","parameter","pmos","posedge","primitive","priority","program","property","protected","pull0","pull1","pulldown","pullup","pulsestyle_ondetect","pulsestyle_onevent","pure","rand","randc","randcase","randsequence","rcmos","real","realtime","ref","reg","reject_on","release","repeat","restrict","return","rnmos","rpmos","rtran","rtranif0","rtranif1","s_always","s_eventually","s_nexttime","s_until","s_until_with","scalared","sequence","shortint","shortreal","showcancelled","signed","small","soft","solve","specify","specparam","static","string","strong","strong0","strong1","struct","super","supply0","supply1","sync_accept_on","sync_reject_on","table","tagged","task","this","throughout","time","timeprecision","timeunit","tran","tranif0","tranif1","tri","tri0","tri1","triand","trior","trireg","type","typedef","union","unique","unique0","unsigned","until","until_with","untyped","use","uwire","var","vectored","virtual","void","wait","wait_order","wand","weak","weak0","weak1","while","wildcard","wire","with","within","wor","xnor","xor"],builtin_gates:["and","nand","nor","or","xor","xnor","buf","not","bufif0","bufif1","notif1","notif0","cmos","nmos","pmos","rcmos","rnmos","rpmos","tran","tranif1","tranif0","rtran","rtranif1","rtranif0"],operators:["=","+=","-=","*=","/=","%=","&=","|=","^=","<<=",">>+","<<<=",">>>=","?",":","+","-","!","~","&","~&","|","~|","^","~^","^~","+","-","*","/","%","==","!=","===","!==","==?","!=?","&&","||","**","<","<=",">",">=","&","|","^",">>","<<",">>>","<<<","++","--","->","<->","inside","dist","::","+:","-:","*>","&&&","|->","|=>","#=#"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],{include:"@numbers"},[/[;,.]/,"delimiter"],{include:"@strings"}],identifier_or_keyword:[[/@identifier/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}]],numbers:[[/\d+?[\d_]*(?:\.[\d_]+)?[eE][\-+]?\d+/,"number.float"],[/\d+?[\d_]*\.[\d_]+(?:\s*@timeunits)?/,"number.float"],[/(?:\d+?[\d_]*\s*)?'[sS]?[dD]\s*[0-9xXzZ?]+?[0-9xXzZ?_]*/,"number"],[/(?:\d+?[\d_]*\s*)?'[sS]?[bB]\s*[0-1xXzZ?]+?[0-1xXzZ?_]*/,"number.binary"],[/(?:\d+?[\d_]*\s*)?'[sS]?[oO]\s*[0-7xXzZ?]+?[0-7xXzZ?_]*/,"number.octal"],[/(?:\d+?[\d_]*\s*)?'[sS]?[hH]\s*[0-9a-fA-FxXzZ?]+?[0-9a-fA-FxXzZ?_]*/,"number.hex"],[/1step/,"number"],[/[\dxXzZ]+?[\dxXzZ_]*(?:\s*@timeunits)?/,"number"],[/'[01xXzZ]+/,"number"]],module_instance:[{include:"@whitespace"},[/(#?)(\()/,["",{token:"@brackets",next:"@port_connection"}]],[/@identifier\s*[;={}\[\],]/,{token:"@rematch",next:"@pop"}],[/@symbols|[;={}\[\],]/,{token:"@rematch",next:"@pop"}],[/@identifier/,"type"],[/;/,"delimiter","@pop"]],port_connection:[{include:"@identifier_or_keyword"},{include:"@whitespace"},[/@systemcall/,"variable.predefined"],{include:"@numbers"},{include:"@strings"},[/[,]/,"delimiter"],[/\(/,"@brackets","@port_connection"],[/\)/,"@brackets","@pop"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],strings:[[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],include:[[/(\s*)(")([\w*\/*]*)(.\w*)(")/,["","string.include.identifier","string.include.identifier","string.include.identifier",{token:"string.include.identifier",next:"@pop"}]],[/(\s*)(<)([\w*\/*]*)(.\w*)(>)/,["","string.include.identifier","string.include.identifier","string.include.identifier",{token:"string.include.identifier",next:"@pop"}]]],table:[{include:"@whitespace"},[/[()]/,"@brackets"],[/[:;]/,"delimiter"],[/[01\-*?xXbBrRfFpPnN]/,"variable.predefined"],["endtable","keyword.endtable","@pop"]]}};return p(f);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/tcl/tcl.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/tcl/tcl", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(t,e)=>{for(var o in e)s(t,o,{get:e[o],enumerable:!0})},p=(t,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of a(e))!l.call(t,n)&&n!==o&&s(t,n,{get:()=>e[n],enumerable:!(i=r(e,n))||i.enumerable});return t};var u=t=>p(s({},"__esModule",{value:!0}),t);var g={};c(g,{conf:()=>k,language:()=>d});var k={brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},d={tokenPostfix:".tcl",specialFunctions:["set","unset","rename","variable","proc","coroutine","foreach","incr","append","lappend","linsert","lreplace"],mainFunctions:["if","then","elseif","else","case","switch","while","for","break","continue","return","package","namespace","catch","exit","eval","expr","uplevel","upvar"],builtinFunctions:["file","info","concat","join","lindex","list","llength","lrange","lsearch","lsort","split","array","parray","binary","format","regexp","regsub","scan","string","subst","dict","cd","clock","exec","glob","pid","pwd","close","eof","fblocked","fconfigure","fcopy","fileevent","flush","gets","open","puts","read","seek","socket","tell","interp","after","auto_execok","auto_load","auto_mkindex","auto_reset","bgerror","error","global","history","load","source","time","trace","unknown","unset","update","vwait","winfo","wm","bind","event","pack","place","grid","font","bell","clipboard","destroy","focus","grab","lower","option","raise","selection","send","tk","tkwait","tk_bisque","tk_focusNext","tk_focusPrev","tk_focusFollowsMouse","tk_popup","tk_setPalette"],symbols:/[=>{ "use strict";var moduleExports=(()=>{var m=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var n=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var s=(e,t)=>{for(var r in t)m(e,r,{get:t[r],enumerable:!0})},d=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of n(t))!a.call(e,i)&&i!==r&&m(e,i,{get:()=>t[i],enumerable:!(o=l(t,i))||o.enumerable});return e};var p=e=>d(m({},"__esModule",{value:!0}),e);var g={};s(g,{conf:()=>h,language:()=>c});var h={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,comments:{blockComment:["{#","#}"]},brackets:[["{#","#}"],["{%","%}"],["{{","}}"],["(",")"],["[","]"],[""],["<",">"]],autoClosingPairs:[{open:"{# ",close:" #}"},{open:"{% ",close:" %}"},{open:"{{ ",close:" }}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}]},c={defaultToken:"",tokenPostfix:"",ignoreCase:!0,keywords:["apply","autoescape","block","deprecated","do","embed","extends","flush","for","from","if","import","include","macro","sandbox","set","use","verbatim","with","endapply","endautoescape","endblock","endembed","endfor","endif","endmacro","endsandbox","endset","endwith","true","false"],tokenizer:{root:[[/\s+/],[/{#/,"comment.twig","@commentState"],[/{%[-~]?/,"delimiter.twig","@blockState"],[/{{[-~]?/,"delimiter.twig","@variableState"],[/)/,["delimiter.html","tag.html","","delimiter.html"]],[/(<)(script)/,["delimiter.html",{token:"tag.html",next:"@script"}]],[/(<)(style)/,["delimiter.html",{token:"tag.html",next:"@style"}]],[/(<)((?:[\w\-]+:)?[\w\-]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/(<\/)((?:[\w\-]+:)?[\w\-]+)/,["delimiter.html",{token:"tag.html",next:"@otherTag"}]],[/|>=|<=/,"operators.twig"],[/(starts with|ends with|matches)(\s+)/,["operators.twig",""]],[/(in)(\s+)/,["operators.twig",""]],[/(is)(\s+)/,["operators.twig",""]],[/\||~|:|\.{1,2}|\?{1,2}/,"operators.twig"],[/[^\W\d][\w]*/,{cases:{"@keywords":"keyword.twig","@default":"variable.twig"}}],[/\d+(\.\d+)?/,"number.twig"],[/\(|\)|\[|\]|{|}|,/,"delimiter.twig"],[/"([^#"\\]*(?:\\.[^#"\\]*)*)"|\'([^\'\\]*(?:\\.[^\'\\]*)*)\'/,"string.twig"],[/"/,"string.twig","@stringState"],[/=>/,"operators.twig"],[/=/,"operators.twig"]],doctype:[[/[^>]+/,"metatag.content.html"],[/>/,"metatag.html","@pop"]],comment:[[/-->/,"comment.html","@pop"],[/[^-]+/,"comment.content.html"],[/./,"comment.content.html"]],otherTag:[[/\/?>/,"delimiter.html","@pop"],[/"([^"]*)"/,"attribute.value.html"],[/'([^']*)'/,"attribute.value.html"],[/[\w\-]+/,"attribute.name.html"],[/=/,"delimiter.html"],[/[ \t\r\n]+/]],script:[[/type/,"attribute.name.html","@scriptAfterType"],[/"([^"]*)"/,"attribute.value.html"],[/'([^']*)'/,"attribute.value.html"],[/[\w\-]+/,"attribute.name.html"],[/=/,"delimiter.html"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/(<\/)(script\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],scriptAfterType:[[/=/,"delimiter.html","@scriptAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptAfterTypeEquals:[[/"([^"]*)"/,{token:"attribute.value.html",switchTo:"@scriptWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value.html",switchTo:"@scriptWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@scriptEmbedded",nextEmbedded:"text/javascript"}],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptWithCustomType:[[/>/,{token:"delimiter.html",next:"@scriptEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value.html"],[/'([^']*)'/,"attribute.value.html"],[/[\w\-]+/,"attribute.name.html"],[/=/,"delimiter.html"],[/[ \t\r\n]+/],[/<\/script\s*>/,{token:"@rematch",next:"@pop"}]],scriptEmbedded:[[/<\/script/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}],[/[^<]+/,""]],style:[[/type/,"attribute.name.html","@styleAfterType"],[/"([^"]*)"/,"attribute.value.html"],[/'([^']*)'/,"attribute.value.html"],[/[\w\-]+/,"attribute.name.html"],[/=/,"delimiter.html"],[/>/,{token:"delimiter.html",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/(<\/)(style\s*)(>)/,["delimiter.html","tag.html",{token:"delimiter.html",next:"@pop"}]]],styleAfterType:[[/=/,"delimiter.html","@styleAfterTypeEquals"],[/>/,{token:"delimiter.html",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleAfterTypeEquals:[[/"([^"]*)"/,{token:"attribute.value.html",switchTo:"@styleWithCustomType.$1"}],[/'([^']*)'/,{token:"attribute.value.html",switchTo:"@styleWithCustomType.$1"}],[/>/,{token:"delimiter.html",next:"@styleEmbedded",nextEmbedded:"text/css"}],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleWithCustomType:[[/>/,{token:"delimiter.html",next:"@styleEmbedded.$S2",nextEmbedded:"$S2"}],[/"([^"]*)"/,"attribute.value.html"],[/'([^']*)'/,"attribute.value.html"],[/[\w\-]+/,"attribute.name.html"],[/=/,"delimiter.html"],[/[ \t\r\n]+/],[/<\/style\s*>/,{token:"@rematch",next:"@pop"}]],styleEmbedded:[[/<\/style/,{token:"@rematch",next:"@pop",nextEmbedded:"@pop"}],[/[^<]+/,""]]}};return p(g);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/typescript/typescript.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/typescript/typescript", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var l=Object.create;var s=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty;var f=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var k=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),y=(e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})},i=(e,t,n,c)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of x(t))!u.call(e,r)&&r!==n&&s(e,r,{get:()=>t[r],enumerable:!(c=m(t,r))||c.enumerable});return e},a=(e,t,n)=>(i(e,t,"default"),n&&i(n,t,"default")),p=(e,t,n)=>(n=e!=null?l(b(e)):{},i(t||!e||!e.__esModule?s(n,"default",{value:e,enumerable:!0}):n,e)),w=e=>i(s({},"__esModule",{value:!0}),e);var d=k((T,g)=>{var A=p(f("vs/editor/editor.api"));g.exports=A});var h={};y(h,{conf:()=>v,language:()=>$});var o={};a(o,p(d()));var v={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],onEnterRules:[{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,afterText:/^\s*\*\/$/,action:{indentAction:o.languages.IndentAction.IndentOutdent,appendText:" * "}},{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,action:{indentAction:o.languages.IndentAction.None,appendText:" * "}},{beforeText:/^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,action:{indentAction:o.languages.IndentAction.None,appendText:"* "}},{beforeText:/^(\t|(\ \ ))*\ \*\/\s*$/,action:{indentAction:o.languages.IndentAction.None,removeText:1}}],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string","comment"]},{open:"`",close:"`",notIn:["string","comment"]},{open:"/**",close:" */",notIn:["string"]}],folding:{markers:{start:new RegExp("^\\s*//\\s*#?region\\b"),end:new RegExp("^\\s*//\\s*#?endregion\\b")}}},$={defaultToken:"invalid",tokenPostfix:".ts",keywords:["abstract","any","as","asserts","bigint","boolean","break","case","catch","class","continue","const","constructor","debugger","declare","default","delete","do","else","enum","export","extends","false","finally","for","from","function","get","if","implements","import","in","infer","instanceof","interface","is","keyof","let","module","namespace","never","new","null","number","object","out","package","private","protected","public","override","readonly","require","global","return","satisfies","set","static","string","super","switch","symbol","this","throw","true","try","type","typeof","undefined","unique","unknown","var","void","while","with","yield","async","await","of"],operators:["<=",">=","==","!=","===","!==","=>","+","-","**","*","/","%","++","--","<<",">",">>>","&","|","^","!","~","&&","||","??","?",":","=","+=","-=","*=","**=","/=","%=","<<=",">>=",">>>=","&=","|=","^=","@"],symbols:/[=>](?!@symbols)/,"@brackets"],[/!(?=([^=]|$))/,"delimiter"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/(@digits)[eE]([\-+]?(@digits))?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/,"number.float"],[/0[xX](@hexdigits)n?/,"number.hex"],[/0[oO]?(@octaldigits)n?/,"number.octal"],[/0[bB](@binarydigits)n?/,"number.binary"],[/(@digits)n?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string_double"],[/'/,"string","@string_single"],[/`/,"string","@string_backtick"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@jsdoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],jsdoc:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],regexp:[[/(\{)(\d+(?:,\d*)?)(\})/,["regexp.escape.control","regexp.escape.control","regexp.escape.control"]],[/(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/,["regexp.escape.control",{token:"regexp.escape.control",next:"@regexrange"}]],[/(\()(\?:|\?=|\?!)/,["regexp.escape.control","regexp.escape.control"]],[/[()]/,"regexp.escape.control"],[/@regexpctl/,"regexp.escape.control"],[/[^\\\/]/,"regexp"],[/@regexpesc/,"regexp.escape"],[/\\\./,"regexp.invalid"],[/(\/)([dgimsuy]*)/,[{token:"regexp",bracket:"@close",next:"@pop"},"keyword.other"]]],regexrange:[[/-/,"regexp.escape.control"],[/\^/,"regexp.invalid"],[/@regexpesc/,"regexp.escape"],[/[^\]]/,"regexp"],[/\]/,{token:"regexp.escape.control",next:"@pop",bracket:"@close"}]],string_double:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],string_single:[[/[^\\']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/'/,"string","@pop"]],string_backtick:[[/\$\{/,{token:"delimiter.bracket",next:"@bracketCounting"}],[/[^\\`$]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/`/,"string","@pop"]],bracketCounting:[[/\{/,"delimiter.bracket","@bracketCounting"],[/\}/,"delimiter.bracket","@pop"],{include:"common"}]}};return w(h);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/typespec/typespec.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/typespec/typespec", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var i=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var m=(e,n)=>{for(var o in n)i(e,o,{get:n[o],enumerable:!0})},p=(e,n,o,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of l(n))!k.call(e,t)&&t!==o&&i(e,t,{get:()=>n[t],enumerable:!(r=g(n,t))||r.enumerable});return e};var x=e=>p(i({},"__esModule",{value:!0}),e);var P={};m(P,{conf:()=>L,language:()=>y});var c=e=>`\\b${e}\\b`,s=e=>`(?!${e})`,d="[_a-zA-Z]",u="[_a-zA-Z0-9]",a=c(`${d}${u}*`),f=c("[_a-zA-Z-0-9]+"),$=["import","model","scalar","namespace","op","interface","union","using","is","extends","enum","alias","return","void","if","else","projection","dec","extern","fn"],b=["true","false","null","unknown","never"],w="[ \\t\\r\\n]",C="[0-9]+",L={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"/**",close:" */",notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],indentationRules:{decreaseIndentPattern:new RegExp("^((?!.*?/\\*).*\\*/)?\\s*[\\}\\]].*$"),increaseIndentPattern:new RegExp("^((?!//).)*(\\{([^}\"'`/]*|(\\t|[ ])*//.*)|\\([^)\"'`/]*|\\[[^\\]\"'`/]*)$"),unIndentedLinePattern:new RegExp("^(\\t|[ ])*[ ]\\*[^/]*\\*/\\s*$|^(\\t|[ ])*[ ]\\*/\\s*$|^(\\t|[ ])*[ ]\\*([ ]([^\\*]|\\*(?!/))*)?$")}},y={defaultToken:"",tokenPostfix:".tsp",brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"}],symbols:/[=:;<>]+/,keywords:$,namedLiterals:b,escapes:'\\\\(u{[0-9A-Fa-f]+}|n|r|t|\\\\|"|\\${)',tokenizer:{root:[{include:"@expression"},{include:"@whitespace"}],stringVerbatim:[{regex:'(|"|"")[^"]',action:{token:"string"}},{regex:`"""${s('"')}`,action:{token:"string",next:"@pop"}}],stringLiteral:[{regex:"\\${",action:{token:"delimiter.bracket",next:"@bracketCounting"}},{regex:'[^\\\\"$]+',action:{token:"string"}},{regex:"@escapes",action:{token:"string.escape"}},{regex:"\\\\.",action:{token:"string.escape.invalid"}},{regex:'"',action:{token:"string",next:"@pop"}}],bracketCounting:[{regex:"{",action:{token:"delimiter.bracket",next:"@bracketCounting"}},{regex:"}",action:{token:"delimiter.bracket",next:"@pop"}},{include:"@expression"}],comment:[{regex:"[^\\*]+",action:{token:"comment"}},{regex:"\\*\\/",action:{token:"comment",next:"@pop"}},{regex:"[\\/*]",action:{token:"comment"}}],whitespace:[{regex:w},{regex:"\\/\\*",action:{token:"comment",next:"@comment"}},{regex:"\\/\\/.*$",action:{token:"comment"}}],expression:[{regex:'"""',action:{token:"string",next:"@stringVerbatim"}},{regex:`"${s('""')}`,action:{token:"string",next:"@stringLiteral"}},{regex:C,action:{token:"number"}},{regex:a,action:{cases:{"@keywords":{token:"keyword"},"@namedLiterals":{token:"keyword"},"@default":{token:"identifier"}}}},{regex:`@${a}`,action:{token:"tag"}},{regex:`#${f}`,action:{token:"directive"}}]}};return x(P);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/vb/vb.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/vb/vb", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var r=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var i=(n,e)=>{for(var t in e)r(n,t,{get:e[t],enumerable:!0})},c=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of d(e))!l.call(n,o)&&o!==t&&r(n,o,{get:()=>e[o],enumerable:!(s=a(e,o))||s.enumerable});return n};var u=n=>c(r({},"__esModule",{value:!0}),n);var k={};i(k,{conf:()=>g,language:()=>p});var g={comments:{lineComment:"'",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"],["addhandler","end addhandler"],["class","end class"],["enum","end enum"],["event","end event"],["function","end function"],["get","end get"],["if","end if"],["interface","end interface"],["module","end module"],["namespace","end namespace"],["operator","end operator"],["property","end property"],["raiseevent","end raiseevent"],["removehandler","end removehandler"],["select","end select"],["set","end set"],["structure","end structure"],["sub","end sub"],["synclock","end synclock"],["try","end try"],["while","end while"],["with","end with"],["using","end using"],["do","loop"],["for","next"]],autoClosingPairs:[{open:"{",close:"}",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]},{open:"<",close:">",notIn:["string","comment"]}],folding:{markers:{start:new RegExp("^\\s*#Region\\b"),end:new RegExp("^\\s*#End Region\\b")}}},p={defaultToken:"",tokenPostfix:".vb",ignoreCase:!0,brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.angle",open:"<",close:">"},{token:"keyword.tag-addhandler",open:"addhandler",close:"end addhandler"},{token:"keyword.tag-class",open:"class",close:"end class"},{token:"keyword.tag-enum",open:"enum",close:"end enum"},{token:"keyword.tag-event",open:"event",close:"end event"},{token:"keyword.tag-function",open:"function",close:"end function"},{token:"keyword.tag-get",open:"get",close:"end get"},{token:"keyword.tag-if",open:"if",close:"end if"},{token:"keyword.tag-interface",open:"interface",close:"end interface"},{token:"keyword.tag-module",open:"module",close:"end module"},{token:"keyword.tag-namespace",open:"namespace",close:"end namespace"},{token:"keyword.tag-operator",open:"operator",close:"end operator"},{token:"keyword.tag-property",open:"property",close:"end property"},{token:"keyword.tag-raiseevent",open:"raiseevent",close:"end raiseevent"},{token:"keyword.tag-removehandler",open:"removehandler",close:"end removehandler"},{token:"keyword.tag-select",open:"select",close:"end select"},{token:"keyword.tag-set",open:"set",close:"end set"},{token:"keyword.tag-structure",open:"structure",close:"end structure"},{token:"keyword.tag-sub",open:"sub",close:"end sub"},{token:"keyword.tag-synclock",open:"synclock",close:"end synclock"},{token:"keyword.tag-try",open:"try",close:"end try"},{token:"keyword.tag-while",open:"while",close:"end while"},{token:"keyword.tag-with",open:"with",close:"end with"},{token:"keyword.tag-using",open:"using",close:"end using"},{token:"keyword.tag-do",open:"do",close:"loop"},{token:"keyword.tag-for",open:"for",close:"next"}],keywords:["AddHandler","AddressOf","Alias","And","AndAlso","As","Async","Boolean","ByRef","Byte","ByVal","Call","Case","Catch","CBool","CByte","CChar","CDate","CDbl","CDec","Char","CInt","Class","CLng","CObj","Const","Continue","CSByte","CShort","CSng","CStr","CType","CUInt","CULng","CUShort","Date","Decimal","Declare","Default","Delegate","Dim","DirectCast","Do","Double","Each","Else","ElseIf","End","EndIf","Enum","Erase","Error","Event","Exit","False","Finally","For","Friend","Function","Get","GetType","GetXMLNamespace","Global","GoSub","GoTo","Handles","If","Implements","Imports","In","Inherits","Integer","Interface","Is","IsNot","Let","Lib","Like","Long","Loop","Me","Mod","Module","MustInherit","MustOverride","MyBase","MyClass","NameOf","Namespace","Narrowing","New","Next","Not","Nothing","NotInheritable","NotOverridable","Object","Of","On","Operator","Option","Optional","Or","OrElse","Out","Overloads","Overridable","Overrides","ParamArray","Partial","Private","Property","Protected","Public","RaiseEvent","ReadOnly","ReDim","RemoveHandler","Resume","Return","SByte","Select","Set","Shadows","Shared","Short","Single","Static","Step","Stop","String","Structure","Sub","SyncLock","Then","Throw","To","True","Try","TryCast","TypeOf","UInteger","ULong","UShort","Using","Variant","Wend","When","While","Widening","With","WithEvents","WriteOnly","Xor"],tagwords:["If","Sub","Select","Try","Class","Enum","Function","Get","Interface","Module","Namespace","Operator","Set","Structure","Using","While","With","Do","Loop","For","Next","Property","Continue","AddHandler","RemoveHandler","Event","RaiseEvent","SyncLock"],symbols:/[=>{ "use strict";var moduleExports=(()=>{var s=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var p=(t,e)=>{for(var a in e)s(t,a,{get:e[a],enumerable:!0})},d=(t,e,a,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of l(e))!u.call(t,i)&&i!==a&&s(t,i,{get:()=>e[i],enumerable:!(o=m(e,i))||o.enumerable});return t};var x=t=>d(s({},"__esModule",{value:!0}),t);var F={};p(F,{conf:()=>f,language:()=>L});var f={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"[",close:"]"},{open:"{",close:"}"},{open:"(",close:")"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"}]};function r(t){let e=[],a=t.split(/\t+|\r+|\n+| +/);for(let o=0;o0&&e.push(a[o]);return e}var g=r("true false"),_=r(` alias break case const const_assert continue continuing default diagnostic discard else enable fn for if let loop override requires return struct switch var while `),h=r(` NULL Self abstract active alignas alignof as asm asm_fragment async attribute auto await become binding_array cast catch class co_await co_return co_yield coherent column_major common compile compile_fragment concept const_cast consteval constexpr constinit crate debugger decltype delete demote demote_to_helper do dynamic_cast enum explicit export extends extern external fallthrough filter final finally friend from fxgroup get goto groupshared highp impl implements import inline instanceof interface layout lowp macro macro_rules match mediump meta mod module move mut mutable namespace new nil noexcept noinline nointerpolation noperspective null nullptr of operator package packoffset partition pass patch pixelfragment precise precision premerge priv protected pub public readonly ref regardless register reinterpret_cast require resource restrict self set shared sizeof smooth snorm static static_assert static_cast std subroutine super target template this thread_local throw trait try type typedef typeid typename typeof union unless unorm unsafe unsized use using varying virtual volatile wgsl where with writeonly yield `),b=r(` read write read_write function private workgroup uniform storage perspective linear flat center centroid sample vertex_index instance_index position front_facing frag_depth local_invocation_id local_invocation_index global_invocation_id workgroup_id num_workgroups sample_index sample_mask rgba8unorm rgba8snorm rgba8uint rgba8sint rgba16uint rgba16sint rgba16float r32uint r32sint r32float rg32uint rg32sint rg32float rgba32uint rgba32sint rgba32float bgra8unorm `),v=r(` bool f16 f32 i32 sampler sampler_comparison texture_depth_2d texture_depth_2d_array texture_depth_cube texture_depth_cube_array texture_depth_multisampled_2d texture_external texture_external u32 `),y=r(` array atomic mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4 ptr texture_1d texture_2d texture_2d_array texture_3d texture_cube texture_cube_array texture_multisampled_2d texture_storage_1d texture_storage_2d texture_storage_2d_array texture_storage_3d vec2 vec3 vec4 `),k=r(` vec2i vec3i vec4i vec2u vec3u vec4u vec2f vec3f vec4f vec2h vec3h vec4h mat2x2f mat2x3f mat2x4f mat3x2f mat3x3f mat3x4f mat4x2f mat4x3f mat4x4f mat2x2h mat2x3h mat2x4h mat3x2h mat3x3h mat3x4h mat4x2h mat4x3h mat4x4h `),w=r(` bitcast all any select arrayLength abs acos acosh asin asinh atan atanh atan2 ceil clamp cos cosh countLeadingZeros countOneBits countTrailingZeros cross degrees determinant distance dot exp exp2 extractBits faceForward firstLeadingBit firstTrailingBit floor fma fract frexp inverseBits inverseSqrt ldexp length log log2 max min mix modf normalize pow quantizeToF16 radians reflect refract reverseBits round saturate sign sin sinh smoothstep sqrt step tan tanh transpose trunc dpdx dpdxCoarse dpdxFine dpdy dpdyCoarse dpdyFine fwidth fwidthCoarse fwidthFine textureDimensions textureGather textureGatherCompare textureLoad textureNumLayers textureNumLevels textureNumSamples textureSample textureSampleBias textureSampleCompare textureSampleCompareLevel textureSampleGrad textureSampleLevel textureSampleBaseClampToEdge textureStore atomicLoad atomicStore atomicAdd atomicSub atomicMax atomicMin atomicAnd atomicOr atomicXor atomicExchange atomicCompareExchangeWeak pack4x8snorm pack4x8unorm pack2x16snorm pack2x16unorm pack2x16float unpack4x8snorm unpack4x8unorm unpack2x16snorm unpack2x16unorm unpack2x16float storageBarrier workgroupBarrier workgroupUniformLoad `),S=r(` & && -> / = == != > >= < <= % - -- + ++ | || * << >> += -= *= /= %= &= |= ^= >>= <<= `),C=/enable|requires|diagnostic/,c=/[_\p{XID_Start}]\p{XID_Continue}*/u,n="variable.predefined",L={tokenPostfix:".wgsl",defaultToken:"invalid",unicode:!0,atoms:g,keywords:_,reserved:h,predeclared_enums:b,predeclared_types:v,predeclared_type_generators:y,predeclared_type_aliases:k,predeclared_intrinsics:w,operators:S,symbols:/[!%&*+\-\.\/:;<=>^|_~,]+/,tokenizer:{root:[[C,"keyword","@directive"],[c,{cases:{"@atoms":n,"@keywords":"keyword","@reserved":"invalid","@predeclared_enums":n,"@predeclared_types":n,"@predeclared_type_generators":n,"@predeclared_type_aliases":n,"@predeclared_intrinsics":n,"@default":"identifier"}}],{include:"@commentOrSpace"},{include:"@numbers"},[/[{}()\[\]]/,"@brackets"],["@","annotation","@attribute"],[/@symbols/,{cases:{"@operators":"operator","@default":"delimiter"}}],[/./,"invalid"]],commentOrSpace:[[/\s+/,"white"],[/\/\*/,"comment","@blockComment"],[/\/\/.*$/,"comment"]],blockComment:[[/[^\/*]+/,"comment"],[/\/\*/,"comment","@push"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],attribute:[{include:"@commentOrSpace"},[/\w+/,"annotation","@pop"]],directive:[{include:"@commentOrSpace"},[/[()]/,"@brackets"],[/,/,"delimiter"],[c,"meta.content"],[/;/,"delimiter","@pop"]],numbers:[[/0[fh]/,"number.float"],[/[1-9][0-9]*[fh]/,"number.float"],[/[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[fh]?/,"number.float"],[/[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?[fh]?/,"number.float"],[/[0-9]+[eE][+-]?[0-9]+[fh]?/,"number.float"],[/0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+(?:[pP][+-]?[0-9]+[fh]?)?/,"number.hex"],[/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*(?:[pP][+-]?[0-9]+[fh]?)?/,"number.hex"],[/0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?/,"number.hex"],[/0[xX][0-9a-fA-F]+[iu]?/,"number.hex"],[/[1-9][0-9]*[iu]?/,"number"],[/0[iu]?/,"number"]]}};return x(F);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/basic-languages/xml/xml.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/xml/xml", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var u=Object.create;var m=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var k=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var f=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var w=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),b=(e,t)=>{for(var n in t)m(e,n,{get:t[n],enumerable:!0})},i=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of p(t))!x.call(e,o)&&o!==n&&m(e,o,{get:()=>t[o],enumerable:!(r=g(t,o))||r.enumerable});return e},l=(e,t,n)=>(i(e,t,"default"),n&&i(n,t,"default")),c=(e,t,n)=>(n=e!=null?u(k(e)):{},i(t||!e||!e.__esModule?m(n,"default",{value:e,enumerable:!0}):n,e)),q=e=>i(m({},"__esModule",{value:!0}),e);var s=w((v,d)=>{var N=c(f("vs/editor/editor.api"));d.exports=N});var I={};b(I,{conf:()=>A,language:()=>C});var a={};l(a,c(s()));var A={comments:{blockComment:[""]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],onEnterRules:[{beforeText:new RegExp("<([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$","i"),afterText:/^<\/([_:\w][_:\w-.\d]*)\s*>$/i,action:{indentAction:a.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp("<(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),action:{indentAction:a.languages.IndentAction.Indent}}]},C={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[//,{token:"comment",next:"@pop"}],[/"),typeof Re!="string"&&!dt(Re))if(typeof Re.toString=="function"){if(Re=Re.toString(),typeof Re!="string")throw Pt("dirty is not a string, aborting")}else throw Pt("toString is not a function");if(!e.isSupported)return Re;if(ue||xe(Se),e.removed=[],typeof Re=="string"&&($=!1),$){if(Re.nodeName){const rt=Oe(Re.nodeName);if(!x[rt]||z[rt])throw Pt("root node is forbidden and cannot be sanitized in-place")}}else if(Re instanceof m)We=je(""),qe=We.ownerDocument.importNode(Re,!0),qe.nodeType===Ft.element&&qe.nodeName==="BODY"||qe.nodeName==="HTML"?We=qe:We.appendChild(qe);else{if(!pe&&!R&&!ie&&Re.indexOf("<")===-1)return r&&ee?r.createHTML(Re):Re;if(We=je(Re),!We)return pe?null:ee?u:""}We&&he&&He(We.firstChild);const tt=Xe($?Re:We);for(;Ue=tt.nextNode();)st(Ue)||(Ue.content instanceof E&&Ie(Ue.content),De(Ue));if($)return Re;if(pe){if(ae)for(Je=h.call(We.ownerDocument);We.firstChild;)Je.appendChild(We.firstChild);else Je=We;return(V.shadowroot||V.shadowrootmode)&&(Je=w.call(k,Je,!0)),Je}let Qe=ie?We.outerHTML:We.innerHTML;return ie&&x["!doctype"]&&We.ownerDocument&&We.ownerDocument.doctype&&We.ownerDocument.doctype.name&&_t(ai,We.ownerDocument.doctype.name)&&(Qe=" `+Qe),R&&Wt([L,D,T],rt=>{Qe=Rt(Qe,rt," ")}),r&&ee?r.createHTML(Qe):Qe},e.setConfig=function(){let Re=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};xe(Re),ue=!0},e.clearConfig=function(){Fe=null,ue=!1},e.isValidAttribute=function(Re,Se,We){Fe||xe({});const qe=Oe(Re),Ue=Oe(Se);return pt(qe,Ue,We)},e.addHook=function(Re,Se){typeof Se=="function"&&(S[Re]=S[Re]||[],At(S[Re],Se))},e.removeHook=function(Re){if(S[Re])return ei(S[Re])},e.removeHooks=function(Re){S[Re]&&(S[Re]=[])},e.removeAllHooks=function(){S={}},e}var xi=di();define("vs/base/browser/dompurify/dompurify",function(){return xi}),define(ne[39],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FastDomNode=void 0,e.createFastDomNode=I;class d{constructor(y){this.domNode=y,this._maxWidth="",this._width="",this._height="",this._top="",this._left="",this._bottom="",this._right="",this._paddingLeft="",this._fontFamily="",this._fontWeight="",this._fontSize="",this._fontStyle="",this._fontFeatureSettings="",this._fontVariationSettings="",this._textDecoration="",this._lineHeight="",this._letterSpacing="",this._className="",this._display="",this._position="",this._visibility="",this._color="",this._backgroundColor="",this._layerHint=!1,this._contain="none",this._boxShadow=""}setMaxWidth(y){const m=k(y);this._maxWidth!==m&&(this._maxWidth=m,this.domNode.style.maxWidth=this._maxWidth)}setWidth(y){const m=k(y);this._width!==m&&(this._width=m,this.domNode.style.width=this._width)}setHeight(y){const m=k(y);this._height!==m&&(this._height=m,this.domNode.style.height=this._height)}setTop(y){const m=k(y);this._top!==m&&(this._top=m,this.domNode.style.top=this._top)}setLeft(y){const m=k(y);this._left!==m&&(this._left=m,this.domNode.style.left=this._left)}setBottom(y){const m=k(y);this._bottom!==m&&(this._bottom=m,this.domNode.style.bottom=this._bottom)}setRight(y){const m=k(y);this._right!==m&&(this._right=m,this.domNode.style.right=this._right)}setPaddingLeft(y){const m=k(y);this._paddingLeft!==m&&(this._paddingLeft=m,this.domNode.style.paddingLeft=this._paddingLeft)}setFontFamily(y){this._fontFamily!==y&&(this._fontFamily=y,this.domNode.style.fontFamily=this._fontFamily)}setFontWeight(y){this._fontWeight!==y&&(this._fontWeight=y,this.domNode.style.fontWeight=this._fontWeight)}setFontSize(y){const m=k(y);this._fontSize!==m&&(this._fontSize=m,this.domNode.style.fontSize=this._fontSize)}setFontStyle(y){this._fontStyle!==y&&(this._fontStyle=y,this.domNode.style.fontStyle=this._fontStyle)}setFontFeatureSettings(y){this._fontFeatureSettings!==y&&(this._fontFeatureSettings=y,this.domNode.style.fontFeatureSettings=this._fontFeatureSettings)}setFontVariationSettings(y){this._fontVariationSettings!==y&&(this._fontVariationSettings=y,this.domNode.style.fontVariationSettings=this._fontVariationSettings)}setTextDecoration(y){this._textDecoration!==y&&(this._textDecoration=y,this.domNode.style.textDecoration=this._textDecoration)}setLineHeight(y){const m=k(y);this._lineHeight!==m&&(this._lineHeight=m,this.domNode.style.lineHeight=this._lineHeight)}setLetterSpacing(y){const m=k(y);this._letterSpacing!==m&&(this._letterSpacing=m,this.domNode.style.letterSpacing=this._letterSpacing)}setClassName(y){this._className!==y&&(this._className=y,this.domNode.className=this._className)}toggleClassName(y,m){this.domNode.classList.toggle(y,m),this._className=this.domNode.className}setDisplay(y){this._display!==y&&(this._display=y,this.domNode.style.display=this._display)}setPosition(y){this._position!==y&&(this._position=y,this.domNode.style.position=this._position)}setVisibility(y){this._visibility!==y&&(this._visibility=y,this.domNode.style.visibility=this._visibility)}setColor(y){this._color!==y&&(this._color=y,this.domNode.style.color=this._color)}setBackgroundColor(y){this._backgroundColor!==y&&(this._backgroundColor=y,this.domNode.style.backgroundColor=this._backgroundColor)}setLayerHinting(y){this._layerHint!==y&&(this._layerHint=y,this.domNode.style.transform=this._layerHint?"translate3d(0px, 0px, 0px)":"")}setBoxShadow(y){this._boxShadow!==y&&(this._boxShadow=y,this.domNode.style.boxShadow=y)}setContain(y){this._contain!==y&&(this._contain=y,this.domNode.style.contain=this._contain)}setAttribute(y,m){this.domNode.setAttribute(y,m)}removeAttribute(y){this.domNode.removeAttribute(y)}appendChild(y){this.domNode.appendChild(y.domNode)}removeChild(y){this.domNode.removeChild(y.domNode)}}e.FastDomNode=d;function k(E){return typeof E=="number"?`${E}px`:E}function I(E){return new d(E)}}),define(ne[441],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IframeUtils=void 0;const d=new WeakMap;function k(E){if(!E.parent||E.parent===E)return null;try{const y=E.location,m=E.parent.location;if(y.origin!=="null"&&m.origin!=="null"&&y.origin!==m.origin)return null}catch{return null}return E.parent}class I{static getSameOriginWindowChain(y){let m=d.get(y);if(!m){m=[],d.set(y,m);let _=y,b;do b=k(_),b?m.push({window:new WeakRef(_),iframeElement:_.frameElement||null}):m.push({window:new WeakRef(_),iframeElement:null}),_=b;while(_)}return m.slice(0)}static getPositionOfChildWindowRelativeToAncestorWindow(y,m){if(!m||y===m)return{top:0,left:0};let _=0,b=0;const p=this.getSameOriginWindowChain(y);for(const n of p){const o=n.window.deref();if(_+=o?.scrollY??0,b+=o?.scrollX??0,o===m||!n.iframeElement)break;const t=n.iframeElement.getBoundingClientRect();_+=t.top,b+=t.left}return{top:_,left:b}}}e.IframeUtils=I}),define(ne[296],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.inputLatency=void 0;var d;(function(k){const I={total:0,min:Number.MAX_VALUE,max:0},E={...I},y={...I},m={...I};let _=0;const b={keydown:0,input:0,render:0};function p(){r(),performance.mark("inputlatency/start"),performance.mark("keydown/start"),b.keydown=1,queueMicrotask(n)}k.onKeyDown=p;function n(){b.keydown===1&&(performance.mark("keydown/end"),b.keydown=2)}function o(){performance.mark("input/start"),b.input=1,a()}k.onBeforeInput=o;function t(){b.input===0&&o(),queueMicrotask(i)}k.onInput=t;function i(){b.input===1&&(performance.mark("input/end"),b.input=2)}function s(){r()}k.onKeyUp=s;function g(){r()}k.onSelectionChange=g;function c(){b.keydown===2&&b.input===2&&b.render===0&&(performance.mark("render/start"),b.render=1,queueMicrotask(l),a())}k.onRenderStart=c;function l(){b.render===1&&(performance.mark("render/end"),b.render=2)}function a(){setTimeout(r)}function r(){b.keydown===2&&b.input===2&&b.render===2&&(performance.mark("inputlatency/end"),performance.measure("keydown","keydown/start","keydown/end"),performance.measure("input","input/start","input/end"),performance.measure("render","render/start","render/end"),performance.measure("inputlatency","inputlatency/start","inputlatency/end"),u("keydown",I),u("input",E),u("render",y),u("inputlatency",m),_++,C())}function u(w,S){const L=performance.getEntriesByName(w)[0].duration;S.total+=L,S.min=Math.min(S.min,L),S.max=Math.max(S.max,L)}function C(){performance.clearMarks("keydown/start"),performance.clearMarks("keydown/end"),performance.clearMarks("input/start"),performance.clearMarks("input/end"),performance.clearMarks("render/start"),performance.clearMarks("render/end"),performance.clearMarks("inputlatency/start"),performance.clearMarks("inputlatency/end"),performance.clearMeasures("keydown"),performance.clearMeasures("input"),performance.clearMeasures("render"),performance.clearMeasures("inputlatency"),b.keydown=0,b.input=0,b.render=0}function f(){if(_===0)return;const w={keydown:h(I),input:h(E),render:h(y),total:h(m),sampleCount:_};return v(I),v(E),v(y),v(m),_=0,w}k.getAndClearMeasurements=f;function h(w){return{average:w.total/_,max:w.max,min:w.min}}function v(w){w.total=0,w.min=Number.MAX_VALUE,w.max=0}})(d||(e.inputLatency=d={}))}),define(ne[81],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setBaseLayerHoverDelegate=k,e.getBaseLayerHoverDelegate=I;let d={showHover:()=>{},hideHover:()=>{},showAndFocusLastHover:()=>{},setupManagedHover:()=>null,showManagedHover:()=>{}};function k(E){d=E}function I(){return d}}),define(ne[442],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ListError=void 0;class d extends Error{constructor(I,E){super(`ListError [${I}] ${E}`)}}e.ListError=d}),define(ne[443],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CombinedSpliceable=void 0;class d{constructor(I){this.spliceables=I}splice(I,E,y){this.spliceables.forEach(m=>m.splice(I,E,y))}}e.CombinedSpliceable=d}),define(ne[223],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ScrollbarState=void 0;const d=20;class k{constructor(E,y,m,_,b,p){this._scrollbarSize=Math.round(y),this._oppositeScrollbarSize=Math.round(m),this._arrowSize=Math.round(E),this._visibleSize=_,this._scrollSize=b,this._scrollPosition=p,this._computedAvailableSize=0,this._computedIsNeeded=!1,this._computedSliderSize=0,this._computedSliderRatio=0,this._computedSliderPosition=0,this._refreshComputedValues()}clone(){return new k(this._arrowSize,this._scrollbarSize,this._oppositeScrollbarSize,this._visibleSize,this._scrollSize,this._scrollPosition)}setVisibleSize(E){const y=Math.round(E);return this._visibleSize!==y?(this._visibleSize=y,this._refreshComputedValues(),!0):!1}setScrollSize(E){const y=Math.round(E);return this._scrollSize!==y?(this._scrollSize=y,this._refreshComputedValues(),!0):!1}setScrollPosition(E){const y=Math.round(E);return this._scrollPosition!==y?(this._scrollPosition=y,this._refreshComputedValues(),!0):!1}setScrollbarSize(E){this._scrollbarSize=Math.round(E)}setOppositeScrollbarSize(E){this._oppositeScrollbarSize=Math.round(E)}static _computeValues(E,y,m,_,b){const p=Math.max(0,m-E),n=Math.max(0,p-2*y),o=_>0&&_>m;if(!o)return{computedAvailableSize:Math.round(p),computedIsNeeded:o,computedSliderSize:Math.round(n),computedSliderRatio:0,computedSliderPosition:0};const t=Math.round(Math.max(d,Math.floor(m*n/_))),i=(n-t)/(_-m),s=b*i;return{computedAvailableSize:Math.round(p),computedIsNeeded:o,computedSliderSize:Math.round(t),computedSliderRatio:i,computedSliderPosition:Math.round(s)}}_refreshComputedValues(){const E=k._computeValues(this._oppositeScrollbarSize,this._arrowSize,this._visibleSize,this._scrollSize,this._scrollPosition);this._computedAvailableSize=E.computedAvailableSize,this._computedIsNeeded=E.computedIsNeeded,this._computedSliderSize=E.computedSliderSize,this._computedSliderRatio=E.computedSliderRatio,this._computedSliderPosition=E.computedSliderPosition}getArrowSize(){return this._arrowSize}getScrollPosition(){return this._scrollPosition}getRectangleLargeSize(){return this._computedAvailableSize}getRectangleSmallSize(){return this._scrollbarSize}isNeeded(){return this._computedIsNeeded}getSliderSize(){return this._computedSliderSize}getSliderPosition(){return this._computedSliderPosition}getDesiredScrollPositionFromOffset(E){if(!this._computedIsNeeded)return 0;const y=E-this._arrowSize-this._computedSliderSize/2;return Math.round(y/this._computedSliderRatio)}getDesiredScrollPositionFromOffsetPaged(E){if(!this._computedIsNeeded)return 0;const y=E-this._arrowSize;let m=this._scrollPosition;return yI})}e.mainWindow=window}),define(ne[64],se([1,0,52]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isAndroid=e.isElectron=e.isWebkitWebView=e.isSafari=e.isChrome=e.isWebKit=e.isFirefox=void 0,e.addMatchMediaChangeListener=I,e.getZoomFactor=E,e.isStandalone=_;class k{constructor(){this.mapWindowIdToZoomFactor=new Map}static{this.INSTANCE=new k}getZoomFactor(p){return this.mapWindowIdToZoomFactor.get(this.getWindowId(p))??1}getWindowId(p){return p.vscodeWindowId}}function I(b,p,n){typeof p=="string"&&(p=b.matchMedia(p)),p.addEventListener("change",n)}function E(b){return k.INSTANCE.getZoomFactor(b)}const y=navigator.userAgent;e.isFirefox=y.indexOf("Firefox")>=0,e.isWebKit=y.indexOf("AppleWebKit")>=0,e.isChrome=y.indexOf("Chrome")>=0,e.isSafari=!e.isChrome&&y.indexOf("Safari")>=0,e.isWebkitWebView=!e.isChrome&&!e.isSafari&&e.isWebKit,e.isElectron=y.indexOf("Electron/")>=0,e.isAndroid=y.indexOf("Android")>=0;let m=!1;if(typeof d.mainWindow.matchMedia=="function"){const b=d.mainWindow.matchMedia("(display-mode: standalone) or (display-mode: window-controls-overlay)"),p=d.mainWindow.matchMedia("(display-mode: fullscreen)");m=b.matches,I(d.mainWindow,b,({matches:n})=>{m&&p.matches||(m=n)})}function _(){return m}}),define(ne[13],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Permutation=e.CallbackIterable=e.ArrayQueue=e.booleanComparator=e.numberComparator=e.CompareResult=void 0,e.tail=d,e.tail2=k,e.equals=I,e.removeFastWithoutKeepingOrder=E,e.binarySearch=y,e.binarySearch2=m,e.quickSelect=_,e.groupBy=b,e.groupAdjacentBy=p,e.forEachAdjacent=n,e.forEachWithNeighbors=o,e.coalesce=t,e.coalesceInPlace=i,e.isFalsyOrEmpty=s,e.isNonEmptyArray=g,e.distinct=c,e.firstOrDefault=l,e.range=a,e.arrayInsert=r,e.pushToStart=u,e.pushToEnd=C,e.pushMany=f,e.asArray=h,e.insertInto=v,e.splice=w,e.compareBy=D,e.tieBreakComparators=T,e.reverseOrder=P;function d(x,W=0){return x[x.length-(1+W)]}function k(x){if(x.length===0)throw new Error("Invalid tail call");return[x.slice(0,x.length-1),x[x.length-1]]}function I(x,W,V=(q,H)=>q===H){if(x===W)return!0;if(!x||!W||x.length!==W.length)return!1;for(let q=0,H=x.length;qV(x[q],W))}function m(x,W){let V=0,q=x-1;for(;V<=q;){const H=(V+q)/2|0,z=W(H);if(z<0)V=H+1;else if(z>0)q=H-1;else return H}return-(V+1)}function _(x,W,V){if(x=x|0,x>=W.length)throw new TypeError("invalid index");const q=W[Math.floor(W.length*Math.random())],H=[],z=[],U=[];for(const j of W){const Y=V(j,q);Y<0?H.push(j):Y>0?z.push(j):U.push(j)}return x!!W)}function i(x){let W=0;for(let V=0;V0}function c(x,W=V=>V){const V=new Set;return x.filter(q=>{const H=W(q);return V.has(H)?!1:(V.add(H),!0)})}function l(x,W){return x.length>0?x[0]:W}function a(x,W){let V=typeof W=="number"?x:0;typeof W=="number"?V=x:(V=0,W=x);const q=[];if(V<=W)for(let H=V;HW;H--)q.push(H);return q}function r(x,W,V){const q=x.slice(0,W),H=x.slice(W);return q.concat(V,H)}function u(x,W){const V=x.indexOf(W);V>-1&&(x.splice(V,1),x.unshift(W))}function C(x,W){const V=x.indexOf(W);V>-1&&(x.splice(V,1),x.push(W))}function f(x,W){for(const V of W)x.push(V)}function h(x){return Array.isArray(x)?x:[x]}function v(x,W,V){const q=S(x,W),H=x.length,z=V.length;x.length=H+z;for(let U=H-1;U>=q;U--)x[U+z]=x[U];for(let U=0;U0}x.isGreaterThan=q;function H(z){return z===0}x.isNeitherLessOrGreaterThan=H,x.greaterThan=1,x.lessThan=-1,x.neitherLessOrGreaterThan=0})(L||(e.CompareResult=L={}));function D(x,W){return(V,q)=>W(x(V),x(q))}function T(...x){return(W,V)=>{for(const q of x){const H=q(W,V);if(!L.isNeitherLessOrGreaterThan(H))return H}return L.neitherLessOrGreaterThan}}const M=(x,W)=>x-W;e.numberComparator=M;const A=(x,W)=>(0,e.numberComparator)(x?1:0,W?1:0);e.booleanComparator=A;function P(x){return(W,V)=>-x(W,V)}class N{constructor(W){this.items=W,this.firstIdx=0,this.lastIdx=this.items.length-1}get length(){return this.lastIdx-this.firstIdx+1}takeWhile(W){let V=this.firstIdx;for(;V=0&&W(this.items[V]);)V--;const q=V===this.lastIdx?null:this.items.slice(V+1,this.lastIdx+1);return this.lastIdx=V,q}peek(){if(this.length!==0)return this.items[this.firstIdx]}dequeue(){const W=this.items[this.firstIdx];return this.firstIdx++,W}takeCount(W){const V=this.items.slice(this.firstIdx,this.firstIdx+W);return this.firstIdx+=W,V}}e.ArrayQueue=N;class O{static{this.empty=new O(W=>{})}constructor(W){this.iterate=W}toArray(){const W=[];return this.iterate(V=>(W.push(V),!0)),W}filter(W){return new O(V=>this.iterate(q=>W(q)?V(q):!0))}map(W){return new O(V=>this.iterate(q=>V(W(q))))}findLast(W){let V;return this.iterate(q=>(W(q)&&(V=q),!0)),V}findLastMaxBy(W){let V,q=!0;return this.iterate(H=>((q||L.isGreaterThan(W(H,V)))&&(q=!1,V=H),!0)),V}}e.CallbackIterable=O;class F{constructor(W){this._indexMap=W}static createSortPermutation(W,V){const q=Array.from(W.keys()).sort((H,z)=>V(W[H],W[z]));return new F(q)}apply(W){return W.map((V,q)=>W[this._indexMap[q]])}inverse(){const W=this._indexMap.slice();for(let V=0;V=0;c--){const l=i[c];if(s(l))return c}return-1}function I(i,s){const g=E(i,s);return g===-1?void 0:i[g]}function E(i,s,g=0,c=i.length){let l=g,a=c;for(;l0&&(g=l)}return g}function p(i,s){if(i.length===0)return;let g=i[0];for(let c=1;c=0&&(g=l)}return g}function n(i,s){return b(i,(g,c)=>-s(g,c))}function o(i,s){if(i.length===0)return-1;let g=0;for(let c=1;c0&&(g=c)}return g}function t(i,s){for(const g of i){const c=s(g);if(c!==void 0)return c}}}),define(ne[297],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CachedFunction=e.LRUCachedFunction=void 0,e.identity=d;function d(E){return E}class k{constructor(y,m){this.lastCache=void 0,this.lastArgKey=void 0,typeof y=="function"?(this._fn=y,this._computeKey=d):(this._fn=m,this._computeKey=y.getCacheKey)}get(y){const m=this._computeKey(y);return this.lastArgKey!==m&&(this.lastArgKey=m,this.lastCache=this._fn(y)),this.lastCache}}e.LRUCachedFunction=k;class I{get cachedValues(){return this._map}constructor(y,m){this._map=new Map,this._map2=new Map,typeof y=="function"?(this._fn=y,this._computeKey=d):(this._fn=m,this._computeKey=y.getCacheKey)}get(y){const m=this._computeKey(y);if(this._map2.has(m))return this._map2.get(m);const _=this._fn(y);return this._map.set(y,_),this._map2.set(m,_),_}}e.CachedFunction=I}),define(ne[298],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.diffSets=d,e.intersection=k;function d(I,E){const y=[],m=[];for(const _ of I)E.has(_)||y.push(_);for(const _ of E)I.has(_)||m.push(_);return{removed:y,added:m}}function k(I,E){const y=new Set;for(const m of E)I.has(m)&&y.add(m);return y}}),define(ne[33],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Color=e.HSVA=e.HSLA=e.RGBA=void 0;function d(m,_){const b=Math.pow(10,_);return Math.round(m*b)/b}class k{constructor(_,b,p,n=1){this._rgbaBrand=void 0,this.r=Math.min(255,Math.max(0,_))|0,this.g=Math.min(255,Math.max(0,b))|0,this.b=Math.min(255,Math.max(0,p))|0,this.a=d(Math.max(Math.min(1,n),0),3)}static equals(_,b){return _.r===b.r&&_.g===b.g&&_.b===b.b&&_.a===b.a}}e.RGBA=k;class I{constructor(_,b,p,n){this._hslaBrand=void 0,this.h=Math.max(Math.min(360,_),0)|0,this.s=d(Math.max(Math.min(1,b),0),3),this.l=d(Math.max(Math.min(1,p),0),3),this.a=d(Math.max(Math.min(1,n),0),3)}static equals(_,b){return _.h===b.h&&_.s===b.s&&_.l===b.l&&_.a===b.a}static fromRGBA(_){const b=_.r/255,p=_.g/255,n=_.b/255,o=_.a,t=Math.max(b,p,n),i=Math.min(b,p,n);let s=0,g=0;const c=(i+t)/2,l=t-i;if(l>0){switch(g=Math.min(c<=.5?l/(2*c):l/(2-2*c),1),t){case b:s=(p-n)/l+(p1&&(p-=1),p<1/6?_+(b-_)*6*p:p<1/2?b:p<2/3?_+(b-_)*(2/3-p)*6:_}static toRGBA(_){const b=_.h/360,{s:p,l:n,a:o}=_;let t,i,s;if(p===0)t=i=s=n;else{const g=n<.5?n*(1+p):n+p-n*p,c=2*n-g;t=I._hue2rgb(c,g,b+1/3),i=I._hue2rgb(c,g,b),s=I._hue2rgb(c,g,b-1/3)}return new k(Math.round(t*255),Math.round(i*255),Math.round(s*255),o)}}e.HSLA=I;class E{constructor(_,b,p,n){this._hsvaBrand=void 0,this.h=Math.max(Math.min(360,_),0)|0,this.s=d(Math.max(Math.min(1,b),0),3),this.v=d(Math.max(Math.min(1,p),0),3),this.a=d(Math.max(Math.min(1,n),0),3)}static equals(_,b){return _.h===b.h&&_.s===b.s&&_.v===b.v&&_.a===b.a}static fromRGBA(_){const b=_.r/255,p=_.g/255,n=_.b/255,o=Math.max(b,p,n),t=Math.min(b,p,n),i=o-t,s=o===0?0:i/o;let g;return i===0?g=0:o===b?g=((p-n)/i%6+6)%6:o===p?g=(n-b)/i+2:g=(b-p)/i+4,new E(Math.round(g*60),s,o,_.a)}static toRGBA(_){const{h:b,s:p,v:n,a:o}=_,t=n*p,i=t*(1-Math.abs(b/60%2-1)),s=n-t;let[g,c,l]=[0,0,0];return b<60?(g=t,c=i):b<120?(g=i,c=t):b<180?(c=t,l=i):b<240?(c=i,l=t):b<300?(g=i,l=t):b<=360&&(g=t,l=i),g=Math.round((g+s)*255),c=Math.round((c+s)*255),l=Math.round((l+s)*255),new k(g,c,l,o)}}e.HSVA=E;class y{static fromHex(_){return y.Format.CSS.parseHex(_)||y.red}static equals(_,b){return!_&&!b?!0:!_||!b?!1:_.equals(b)}get hsla(){return this._hsla?this._hsla:I.fromRGBA(this.rgba)}get hsva(){return this._hsva?this._hsva:E.fromRGBA(this.rgba)}constructor(_){if(_)if(_ instanceof k)this.rgba=_;else if(_ instanceof I)this._hsla=_,this.rgba=I.toRGBA(_);else if(_ instanceof E)this._hsva=_,this.rgba=E.toRGBA(_);else throw new Error("Invalid color ctor argument");else throw new Error("Color needs a value")}equals(_){return!!_&&k.equals(this.rgba,_.rgba)&&I.equals(this.hsla,_.hsla)&&E.equals(this.hsva,_.hsva)}getRelativeLuminance(){const _=y._relativeLuminanceForComponent(this.rgba.r),b=y._relativeLuminanceForComponent(this.rgba.g),p=y._relativeLuminanceForComponent(this.rgba.b),n=.2126*_+.7152*b+.0722*p;return d(n,4)}static _relativeLuminanceForComponent(_){const b=_/255;return b<=.03928?b/12.92:Math.pow((b+.055)/1.055,2.4)}isLighter(){return(this.rgba.r*299+this.rgba.g*587+this.rgba.b*114)/1e3>=128}isLighterThan(_){const b=this.getRelativeLuminance(),p=_.getRelativeLuminance();return b>p}isDarkerThan(_){const b=this.getRelativeLuminance(),p=_.getRelativeLuminance();return bb===p;e.strictEquals=k;function I(b=e.strictEquals){return(p,n)=>d.equals(p,n,b)}function E(){return(b,p)=>b.equals(p)}function y(b,p,n){if(n!==void 0){const o=b;return o==null||p===void 0||p===null?p===o:n(o,p)}else{const o=b;return(t,i)=>t==null||i===void 0||i===null?i===t:o(t,i)}}function m(b,p){if(b===p)return!0;if(Array.isArray(b)&&Array.isArray(p)){if(b.length!==p.length)return!1;for(let n=0;n{throw g.stack?t.isErrorNoTelemetry(g)?new t(g.message+` `+g.stack):new Error(g.message+` `+g.stack):g},0)}}emit(g){this.listeners.forEach(c=>{c(g)})}onUnexpectedError(g){this.unexpectedErrorHandler(g),this.emit(g)}onUnexpectedExternalError(g){this.unexpectedErrorHandler(g)}}e.ErrorHandler=d,e.errorHandler=new d;function k(s){m(s)||e.errorHandler.onUnexpectedError(s)}function I(s){m(s)||e.errorHandler.onUnexpectedExternalError(s)}function E(s){if(s instanceof Error){const{name:g,message:c}=s,l=s.stacktrace||s.stack;return{$isError:!0,name:g,message:c,stack:l,noTelemetry:t.isErrorNoTelemetry(s)}}return s}const y="Canceled";function m(s){return s instanceof _?!0:s instanceof Error&&s.name===y&&s.message===y}class _ extends Error{constructor(){super(y),this.name=this.message}}e.CancellationError=_;function b(){const s=new Error(y);return s.name=s.message,s}function p(s){return s?new Error(`Illegal argument: ${s}`):new Error("Illegal argument")}function n(s){return s?new Error(`Illegal state: ${s}`):new Error("Illegal state")}class o extends Error{constructor(g){super("NotSupported"),g&&(this.message=g)}}e.NotSupportedError=o;class t extends Error{constructor(g){super(g),this.name="CodeExpectedError"}static fromError(g){if(g instanceof t)return g;const c=new t;return c.message=g.message,c.stack=g.stack,c}static isErrorNoTelemetry(g){return g.name==="CodeExpectedError"}}e.ErrorNoTelemetry=t;class i extends Error{constructor(g){super(g||"An unexpected bug occurred."),Object.setPrototypeOf(this,i.prototype)}}e.BugIndicatingError=i}),define(ne[103],se([1,0,8]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.createTrustedTypesPolicy=k;function k(I,E){const y=globalThis.MonacoEnvironment;if(y?.createTrustedTypesPolicy)try{return y.createTrustedTypesPolicy(I,E)}catch(m){(0,d.onUnexpectedError)(m);return}try{return globalThis.trustedTypes?.createPolicy(I,E)}catch(m){(0,d.onUnexpectedError)(m);return}}}),define(ne[90],se([1,0,8]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ok=k,e.assertNever=I,e.softAssert=E,e.assertFn=y,e.checkAdjacentItems=m;function k(_,b){if(!_)throw new Error(b?`Assertion failed (${b})`:"Assertion Failed")}function I(_,b="Unreachable"){throw new Error(b)}function E(_){_||(0,d.onUnexpectedError)(new d.BugIndicatingError("Soft Assertion Failed"))}function y(_){if(!_()){debugger;_(),(0,d.onUnexpectedError)(new d.BugIndicatingError("Assertion Failed"))}}function m(_,b){let p=0;for(;p<_.length-1;){const n=_[p],o=_[p+1];if(!b(n,o))return!1;p++}return!0}}),define(ne[127],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.createSingleCallFunction=d;function d(k,I){const E=this;let y=!1,m;return function(){if(y)return m;if(y=!0,I)try{m=k.apply(E,arguments)}finally{I()}else m=k.apply(E,arguments);return m}}}),define(ne[91],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HierarchicalKind=void 0;class d{static{this.sep="."}static{this.None=new d("@@none@@")}static{this.Empty=new d("")}constructor(I){this.value=I}equals(I){return this.value===I.value}contains(I){return this.equals(I)||this.value===""||I.value.startsWith(this.value+d.sep)}intersects(I){return this.contains(I)||I.contains(this)}append(...I){return new d((this.value?[this.value,...I]:I).join(d.sep))}}e.HierarchicalKind=d}),define(ne[187],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.defaultGenerator=e.IdGenerator=void 0;class d{constructor(I){this._prefix=I,this._lastId=0}nextId(){return this._prefix+ ++this._lastId}}e.IdGenerator=d,e.defaultGenerator=new d("id#")}),define(ne[53],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Iterable=void 0;var d;(function(k){function I(f){return f&&typeof f=="object"&&typeof f[Symbol.iterator]=="function"}k.is=I;const E=Object.freeze([]);function y(){return E}k.empty=y;function*m(f){yield f}k.single=m;function _(f){return I(f)?f:m(f)}k.wrap=_;function b(f){return f||E}k.from=b;function*p(f){for(let h=f.length-1;h>=0;h--)yield f[h]}k.reverse=p;function n(f){return!f||f[Symbol.iterator]().next().done===!0}k.isEmpty=n;function o(f){return f[Symbol.iterator]().next().value}k.first=o;function t(f,h){let v=0;for(const w of f)if(h(w,v++))return!0;return!1}k.some=t;function i(f,h){for(const v of f)if(h(v))return v}k.find=i;function*s(f,h){for(const v of f)h(v)&&(yield v)}k.filter=s;function*g(f,h){let v=0;for(const w of f)yield h(w,v++)}k.map=g;function*c(f,h){let v=0;for(const w of f)yield*h(w,v++)}k.flatMap=c;function*l(...f){for(const h of f)yield*h}k.concat=l;function a(f,h,v){let w=v;for(const S of f)w=h(w,S);return w}k.reduce=a;function*r(f,h,v=f.length){for(h<0&&(h+=f.length),v<0?v+=f.length:v>f.length&&(v=f.length);h=98&&l<=113)return null;switch(l){case 16:return"Up";case 18:return"Down";case 15:return"Left";case 17:return"Right"}return k.keyCodeToStr(l)}n.toElectronAccelerator=c})(b||(e.KeyCodeUtils=b={}));function p(n,o){const t=(o&65535)<<16>>>0;return(n|t)>>>0}}),define(ne[140],se([1,0,8]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ResolvedKeybinding=e.ResolvedChord=e.Keybinding=e.ScanCodeChord=e.KeyCodeChord=void 0,e.decodeKeybinding=k,e.createSimpleKeybinding=I;function k(p,n){if(typeof p=="number"){if(p===0)return null;const o=(p&65535)>>>0,t=(p&4294901760)>>>16;return t!==0?new m([I(o,n),I(t,n)]):new m([I(o,n)])}else{const o=[];for(let t=0;t({get delay(){return-1},dispose:()=>{},showHover:()=>{}});const E=new d.Lazy(()=>I("mouse",!1)),y=new d.Lazy(()=>I("element",!1));function m(p){I=p}function _(p){return p==="element"?y.value:E.value}function b(){return I("element",!0)}}),define(ne[160],se([1,0,98]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.VSBuffer=void 0,e.readUInt16LE=m,e.writeUInt16LE=_,e.readUInt32BE=b,e.writeUInt32BE=p,e.readUInt8=n,e.writeUInt8=o;const k=typeof Buffer<"u",I=new d.Lazy(()=>new Uint8Array(256));let E;class y{static wrap(i){return k&&!Buffer.isBuffer(i)&&(i=Buffer.from(i.buffer,i.byteOffset,i.byteLength)),new y(i)}constructor(i){this.buffer=i,this.byteLength=this.buffer.byteLength}toString(){return k?this.buffer.toString():(E||(E=new TextDecoder),E.decode(this.buffer))}}e.VSBuffer=y;function m(t,i){return t[i+0]<<0>>>0|t[i+1]<<8>>>0}function _(t,i,s){t[s+0]=i&255,i=i>>>8,t[s+1]=i&255}function b(t,i){return t[i]*2**24+t[i+1]*2**16+t[i+2]*2**8+t[i+3]}function p(t,i,s){t[s+3]=i,i=i>>>8,t[s+2]=i,i=i>>>8,t[s+1]=i,i=i>>>8,t[s]=i}function n(t,i){return t[i]}function o(t,i,s){t[s]=i}}),define(ne[445],se([1,0,98]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.compareFileNames=y,e.compareAnything=m,e.compareByPrefix=_;const k=new d.Lazy(()=>{const b=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});return{collator:b,collatorIsNumeric:b.resolvedOptions().numeric}}),I=new d.Lazy(()=>({collator:new Intl.Collator(void 0,{numeric:!0})})),E=new d.Lazy(()=>({collator:new Intl.Collator(void 0,{numeric:!0,sensitivity:"accent"})}));function y(b,p,n=!1){const o=b||"",t=p||"",i=k.value.collator.compare(o,t);return k.value.collatorIsNumeric&&i===0&&o!==t?ot.length)return 1}return 0}}),define(ne[2],se([1,0,127,53]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DisposableMap=e.ImmortalReference=e.RefCountedDisposable=e.MutableDisposable=e.Disposable=e.DisposableStore=void 0,e.setDisposableTracker=y,e.trackDisposable=m,e.markAsDisposed=_,e.markAsSingleton=n,e.isDisposable=o,e.dispose=t,e.combinedDisposable=i,e.toDisposable=s;const I=!1;let E=null;function y(C){E=C}if(I){const C="__is_disposable_tracked__";y(new class{trackDisposable(f){const h=new Error("Potentially leaked disposable").stack;setTimeout(()=>{f[C]||console.log(h)},3e3)}setParent(f,h){if(f&&f!==c.None)try{f[C]=!0}catch{}}markAsDisposed(f){if(f&&f!==c.None)try{f[C]=!0}catch{}}markAsSingleton(f){}})}function m(C){return E?.trackDisposable(C),C}function _(C){E?.markAsDisposed(C)}function b(C,f){E?.setParent(C,f)}function p(C,f){if(E)for(const h of C)E.setParent(h,f)}function n(C){return E?.markAsSingleton(C),C}function o(C){return typeof C=="object"&&C!==null&&typeof C.dispose=="function"&&C.dispose.length===0}function t(C){if(k.Iterable.is(C)){const f=[];for(const h of C)if(h)try{h.dispose()}catch(v){f.push(v)}if(f.length===1)throw f[0];if(f.length>1)throw new AggregateError(f,"Encountered errors while disposing of store");return Array.isArray(C)?[]:C}else if(C)return C.dispose(),C}function i(...C){const f=s(()=>t(C));return p(C,f),f}function s(C){const f=m({dispose:(0,d.createSingleCallFunction)(()=>{_(f),C()})});return f}class g{static{this.DISABLE_DISPOSED_WARNING=!1}constructor(){this._toDispose=new Set,this._isDisposed=!1,m(this)}dispose(){this._isDisposed||(_(this),this._isDisposed=!0,this.clear())}get isDisposed(){return this._isDisposed}clear(){if(this._toDispose.size!==0)try{t(this._toDispose)}finally{this._toDispose.clear()}}add(f){if(!f)return f;if(f===this)throw new Error("Cannot register a disposable on itself!");return b(f,this),this._isDisposed?g.DISABLE_DISPOSED_WARNING||console.warn(new Error("Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!").stack):this._toDispose.add(f),f}deleteAndLeak(f){f&&this._toDispose.has(f)&&(this._toDispose.delete(f),b(f,null))}}e.DisposableStore=g;class c{static{this.None=Object.freeze({dispose(){}})}constructor(){this._store=new g,m(this),b(this._store,this)}dispose(){_(this),this._store.dispose()}_register(f){if(f===this)throw new Error("Cannot register a disposable on itself!");return this._store.add(f)}}e.Disposable=c;class l{constructor(){this._isDisposed=!1,m(this)}get value(){return this._isDisposed?void 0:this._value}set value(f){this._isDisposed||f===this._value||(this._value?.dispose(),f&&b(f,this),this._value=f)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,_(this),this._value?.dispose(),this._value=void 0}}e.MutableDisposable=l;class a{constructor(f){this._disposable=f,this._counter=1}acquire(){return this._counter++,this}release(){return--this._counter===0&&this._disposable.dispose(),this}}e.RefCountedDisposable=a;class r{constructor(f){this.object=f}dispose(){}}e.ImmortalReference=r;class u{constructor(){this._store=new Map,this._isDisposed=!1,m(this)}dispose(){_(this),this._isDisposed=!0,this.clearAndDisposeAll()}clearAndDisposeAll(){if(this._store.size)try{t(this._store.values())}finally{this._store.clear()}}get(f){return this._store.get(f)}set(f,h,v=!1){this._isDisposed&&console.warn(new Error("Trying to add a disposable to a DisposableMap that has already been disposed of. The added object will be leaked!").stack),v||this._store.get(f)?.dispose(),this._store.set(f,h)}deleteAndDispose(f){this._store.get(f)?.dispose(),this._store.delete(f)}[Symbol.iterator](){return this._store[Symbol.iterator]()}}e.DisposableMap=u}),define(ne[73],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LinkedList=void 0;class d{static{this.Undefined=new d(void 0)}constructor(E){this.element=E,this.next=d.Undefined,this.prev=d.Undefined}}class k{constructor(){this._first=d.Undefined,this._last=d.Undefined,this._size=0}get size(){return this._size}isEmpty(){return this._first===d.Undefined}clear(){let E=this._first;for(;E!==d.Undefined;){const y=E.next;E.prev=d.Undefined,E.next=d.Undefined,E=y}this._first=d.Undefined,this._last=d.Undefined,this._size=0}unshift(E){return this._insert(E,!1)}push(E){return this._insert(E,!0)}_insert(E,y){const m=new d(E);if(this._first===d.Undefined)this._first=m,this._last=m;else if(y){const b=this._last;this._last=m,m.prev=b,b.next=m}else{const b=this._first;this._first=m,m.next=b,b.prev=m}this._size+=1;let _=!1;return()=>{_||(_=!0,this._remove(m))}}shift(){if(this._first!==d.Undefined){const E=this._first.element;return this._remove(this._first),E}}pop(){if(this._last!==d.Undefined){const E=this._last.element;return this._remove(this._last),E}}_remove(E){if(E.prev!==d.Undefined&&E.next!==d.Undefined){const y=E.prev;y.next=E.next,E.next.prev=y}else E.prev===d.Undefined&&E.next===d.Undefined?(this._first=d.Undefined,this._last=d.Undefined):E.next===d.Undefined?(this._last=this._last.prev,this._last.next=d.Undefined):E.prev===d.Undefined&&(this._first=this._first.next,this._first.prev=d.Undefined);this._size-=1}*[Symbol.iterator](){let E=this._first;for(;E!==d.Undefined;)yield E.element,E=E.next}}e.LinkedList=k});var ke=this&&this.__decorate||function(oe,e,d,k){var I=arguments.length,E=I<3?e:k===null?k=Object.getOwnPropertyDescriptor(e,d):k,y;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")E=Reflect.decorate(oe,e,d,k);else for(var m=oe.length-1;m>=0;m--)(y=oe[m])&&(E=(I<3?y(E):I>3?y(e,d,E):y(e,d))||E);return I>3&&E&&Object.defineProperty(e,d,E),E};define(ne[446],se([1,0,126]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LinkedText=void 0,e.parseLinkedText=E;class k{constructor(m){this.nodes=m}toString(){return this.nodes.map(m=>typeof m=="string"?m:m.label).join("")}}e.LinkedText=k,ke([d.memoize],k.prototype,"toString",null);const I=/\[([^\]]+)\]\(((?:https?:\/\/|command:|file:)[^\)\s]+)(?: (["'])(.+?)(\3))?\)/gi;function E(y){const m=[];let _=0,b;for(;b=I.exec(y);){b.index-_>0&&m.push(y.substring(_,b.index));const[,p,n,,o]=b;o?m.push({label:p,href:n,title:o}):m.push({label:p,href:n}),_=b.index+b[0].length}return _t.toString()}constructor(t,i){if(this[d]="ResourceMap",t instanceof y)this.map=new Map(t.map),this.toKey=i??y.defaultToKey;else if(E(t)){this.map=new Map,this.toKey=i??y.defaultToKey;for(const[s,g]of t)this.set(s,g)}else this.map=new Map,this.toKey=t??y.defaultToKey}set(t,i){return this.map.set(this.toKey(t),new I(t,i)),this}get(t){return this.map.get(this.toKey(t))?.value}has(t){return this.map.has(this.toKey(t))}get size(){return this.map.size}clear(){this.map.clear()}delete(t){return this.map.delete(this.toKey(t))}forEach(t,i){typeof i<"u"&&(t=t.bind(i));for(const[s,g]of this.map)t(g.value,g.uri,this)}*values(){for(const t of this.map.values())yield t.value}*keys(){for(const t of this.map.values())yield t.uri}*entries(){for(const t of this.map.values())yield[t.uri,t.value]}*[(d=Symbol.toStringTag,Symbol.iterator)](){for(const[,t]of this.map)yield[t.uri,t.value]}}e.ResourceMap=y;class m{constructor(){this[k]="LinkedMap",this._map=new Map,this._head=void 0,this._tail=void 0,this._size=0,this._state=0}clear(){this._map.clear(),this._head=void 0,this._tail=void 0,this._size=0,this._state++}isEmpty(){return!this._head&&!this._tail}get size(){return this._size}get first(){return this._head?.value}get last(){return this._tail?.value}has(t){return this._map.has(t)}get(t,i=0){const s=this._map.get(t);if(s)return i!==0&&this.touch(s,i),s.value}set(t,i,s=0){let g=this._map.get(t);if(g)g.value=i,s!==0&&this.touch(g,s);else{switch(g={key:t,value:i,next:void 0,previous:void 0},s){case 0:this.addItemLast(g);break;case 1:this.addItemFirst(g);break;case 2:this.addItemLast(g);break;default:this.addItemLast(g);break}this._map.set(t,g),this._size++}return this}delete(t){return!!this.remove(t)}remove(t){const i=this._map.get(t);if(i)return this._map.delete(t),this.removeItem(i),this._size--,i.value}shift(){if(!this._head&&!this._tail)return;if(!this._head||!this._tail)throw new Error("Invalid list");const t=this._head;return this._map.delete(t.key),this.removeItem(t),this._size--,t.value}forEach(t,i){const s=this._state;let g=this._head;for(;g;){if(i?t.bind(i)(g.value,g.key,this):t(g.value,g.key,this),this._state!==s)throw new Error("LinkedMap got modified during iteration.");g=g.next}}keys(){const t=this,i=this._state;let s=this._head;const g={[Symbol.iterator](){return g},next(){if(t._state!==i)throw new Error("LinkedMap got modified during iteration.");if(s){const c={value:s.key,done:!1};return s=s.next,c}else return{value:void 0,done:!0}}};return g}values(){const t=this,i=this._state;let s=this._head;const g={[Symbol.iterator](){return g},next(){if(t._state!==i)throw new Error("LinkedMap got modified during iteration.");if(s){const c={value:s.value,done:!1};return s=s.next,c}else return{value:void 0,done:!0}}};return g}entries(){const t=this,i=this._state;let s=this._head;const g={[Symbol.iterator](){return g},next(){if(t._state!==i)throw new Error("LinkedMap got modified during iteration.");if(s){const c={value:[s.key,s.value],done:!1};return s=s.next,c}else return{value:void 0,done:!0}}};return g}[(k=Symbol.toStringTag,Symbol.iterator)](){return this.entries()}trimOld(t){if(t>=this.size)return;if(t===0){this.clear();return}let i=this._head,s=this.size;for(;i&&s>t;)this._map.delete(i.key),i=i.next,s--;this._head=i,this._size=s,i&&(i.previous=void 0),this._state++}trimNew(t){if(t>=this.size)return;if(t===0){this.clear();return}let i=this._tail,s=this.size;for(;i&&s>t;)this._map.delete(i.key),i=i.previous,s--;this._tail=i,this._size=s,i&&(i.next=void 0),this._state++}addItemFirst(t){if(!this._head&&!this._tail)this._tail=t;else if(this._head)t.next=this._head,this._head.previous=t;else throw new Error("Invalid list");this._head=t,this._state++}addItemLast(t){if(!this._head&&!this._tail)this._head=t;else if(this._tail)t.previous=this._tail,this._tail.next=t;else throw new Error("Invalid list");this._tail=t,this._state++}removeItem(t){if(t===this._head&&t===this._tail)this._head=void 0,this._tail=void 0;else if(t===this._head){if(!t.next)throw new Error("Invalid list");t.next.previous=void 0,this._head=t.next}else if(t===this._tail){if(!t.previous)throw new Error("Invalid list");t.previous.next=void 0,this._tail=t.previous}else{const i=t.next,s=t.previous;if(!i||!s)throw new Error("Invalid list");i.previous=s,s.next=i}t.next=void 0,t.previous=void 0,this._state++}touch(t,i){if(!this._head||!this._tail)throw new Error("Invalid list");if(!(i!==1&&i!==2)){if(i===1){if(t===this._head)return;const s=t.next,g=t.previous;t===this._tail?(g.next=void 0,this._tail=g):(s.previous=g,g.next=s),t.previous=void 0,t.next=this._head,this._head.previous=t,this._head=t,this._state++}else if(i===2){if(t===this._tail)return;const s=t.next,g=t.previous;t===this._head?(s.previous=void 0,this._head=s):(s.previous=g,g.next=s),t.next=void 0,t.previous=this._tail,this._tail.next=t,this._tail=t,this._state++}}}toJSON(){const t=[];return this.forEach((i,s)=>{t.push([s,i])}),t}fromJSON(t){this.clear();for(const[i,s]of t)this.set(i,s)}}e.LinkedMap=m;class _ extends m{constructor(t,i=1){super(),this._limit=t,this._ratio=Math.min(Math.max(0,i),1)}get limit(){return this._limit}set limit(t){this._limit=t,this.checkTrim()}get(t,i=2){return super.get(t,i)}peek(t){return super.get(t,0)}set(t,i){return super.set(t,i,2),this}checkTrim(){this.size>this._limit&&this.trim(Math.round(this._limit*this._ratio))}}class b extends _{constructor(t,i=1){super(t,i)}trim(t){this.trimOld(t)}set(t,i){return super.set(t,i),this.checkTrim(),this}}e.LRUCache=b;class p{constructor(t){if(this._m1=new Map,this._m2=new Map,t)for(const[i,s]of t)this.set(i,s)}clear(){this._m1.clear(),this._m2.clear()}set(t,i){this._m1.set(t,i),this._m2.set(i,t)}get(t){return this._m1.get(t)}getKey(t){return this._m2.get(t)}delete(t){const i=this._m1.get(t);return i===void 0?!1:(this._m1.delete(t),this._m2.delete(i),!0)}keys(){return this._m1.keys()}values(){return this._m1.values()}}e.BidirectionalMap=p;class n{constructor(){this.map=new Map}add(t,i){let s=this.map.get(t);s||(s=new Set,this.map.set(t,s)),s.add(i)}delete(t,i){const s=this.map.get(t);s&&(s.delete(i),s.size===0&&this.map.delete(t))}forEach(t,i){const s=this.map.get(t);s&&s.forEach(i)}get(t){const i=this.map.get(t);return i||new Set}}e.SetMap=n}),function(oe,e){typeof define=="function"&&define.amd?define(ne[447],se([0]),e):typeof exports=="object"&&typeof module<"u"?e(exports):(oe=typeof globalThis<"u"?globalThis:oe||self,e(oe.marked={}))}(this,function(oe){"use strict";function e(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}oe.defaults=e();function d(xe){oe.defaults=xe}const k=/[&<>"']/,I=new RegExp(k.source,"g"),E=/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,y=new RegExp(E.source,"g"),m={"&":"&","<":"<",">":">",'"':""","'":"'"},_=xe=>m[xe];function b(xe,be){if(be){if(k.test(xe))return xe.replace(I,_)}else if(E.test(xe))return xe.replace(y,_);return xe}const p=/(^|[^\[])\^/g;function n(xe,be){let ve=typeof xe=="string"?xe:xe.source;be=be||"";const we={replace:(Te,Pe)=>{let Be=typeof Pe=="string"?Pe:Pe.source;return Be=Be.replace(p,"$1"),ve=ve.replace(Te,Be),we},getRegex:()=>new RegExp(ve,be)};return we}function o(xe){try{xe=encodeURI(xe).replace(/%25/g,"%")}catch{return null}return xe}const t={exec:()=>null};function i(xe,be){const ve=xe.replace(/\|/g,(Pe,Be,He)=>{let $e=!1,je=Be;for(;--je>=0&&He[je]==="\\";)$e=!$e;return $e?"|":" |"}),we=ve.split(/ \|/);let Te=0;if(we[0].trim()||we.shift(),we.length>0&&!we[we.length-1].trim()&&we.pop(),be)if(we.length>be)we.splice(be);else for(;we.length{const Pe=Te.match(/^\s+/);if(Pe===null)return Te;const[Be]=Pe;return Be.length>=we.length?Te.slice(we.length):Te}).join(` `)}class a{options;rules;lexer;constructor(be){this.options=be||oe.defaults}space(be){const ve=this.rules.block.newline.exec(be);if(ve&&ve[0].length>0)return{type:"space",raw:ve[0]}}code(be){const ve=this.rules.block.code.exec(be);if(ve){const we=ve[0].replace(/^ {1,4}/gm,"");return{type:"code",raw:ve[0],codeBlockStyle:"indented",text:this.options.pedantic?we:s(we,` `)}}}fences(be){const ve=this.rules.block.fences.exec(be);if(ve){const we=ve[0],Te=l(we,ve[3]||"");return{type:"code",raw:we,lang:ve[2]?ve[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):ve[2],text:Te}}}heading(be){const ve=this.rules.block.heading.exec(be);if(ve){let we=ve[2].trim();if(/#$/.test(we)){const Te=s(we,"#");(this.options.pedantic||!Te||/ $/.test(Te))&&(we=Te.trim())}return{type:"heading",raw:ve[0],depth:ve[1].length,text:we,tokens:this.lexer.inline(we)}}}hr(be){const ve=this.rules.block.hr.exec(be);if(ve)return{type:"hr",raw:s(ve[0],` `)}}blockquote(be){const ve=this.rules.block.blockquote.exec(be);if(ve){let we=s(ve[0],` `).split(` `),Te="",Pe="";const Be=[];for(;we.length>0;){let He=!1;const $e=[];let je;for(je=0;je/.test(we[je]))$e.push(we[je]),He=!0;else if(!He)$e.push(we[je]);else break;we=we.slice(je);const Xe=$e.join(` `),et=Xe.replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,` $1`).replace(/^ {0,3}>[ \t]?/gm,"");Te=Te?`${Te} ${Xe}`:Xe,Pe=Pe?`${Pe} ${et}`:et;const dt=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(et,Be,!0),this.lexer.state.top=dt,we.length===0)break;const at=Be[Be.length-1];if(at?.type==="code")break;if(at?.type==="blockquote"){const st=at,pt=st.raw+` `+we.join(` `),bt=this.blockquote(pt);Be[Be.length-1]=bt,Te=Te.substring(0,Te.length-st.raw.length)+bt.raw,Pe=Pe.substring(0,Pe.length-st.text.length)+bt.text;break}else if(at?.type==="list"){const st=at,pt=st.raw+` `+we.join(` `),bt=this.list(pt);Be[Be.length-1]=bt,Te=Te.substring(0,Te.length-at.raw.length)+bt.raw,Pe=Pe.substring(0,Pe.length-st.raw.length)+bt.raw,we=pt.substring(Be[Be.length-1].raw.length).split(` `);continue}}return{type:"blockquote",raw:Te,tokens:Be,text:Pe}}}list(be){let ve=this.rules.block.list.exec(be);if(ve){let we=ve[1].trim();const Te=we.length>1,Pe={type:"list",raw:"",ordered:Te,start:Te?+we.slice(0,-1):"",loose:!1,items:[]};we=Te?`\\d{1,9}\\${we.slice(-1)}`:`\\${we}`,this.options.pedantic&&(we=Te?we:"[*+-]");const Be=new RegExp(`^( {0,3}${we})((?:[ ][^\\n]*)?(?:\\n|$))`);let He=!1;for(;be;){let $e=!1,je="",Xe="";if(!(ve=Be.exec(be))||this.rules.block.hr.test(be))break;je=ve[0],be=be.substring(je.length);let et=ve[2].split(` `,1)[0].replace(/^\t+/,De=>" ".repeat(3*De.length)),dt=be.split(` `,1)[0],at=!et.trim(),st=0;if(this.options.pedantic?(st=2,Xe=et.trimStart()):at?st=ve[1].length+1:(st=ve[2].search(/[^ ]/),st=st>4?1:st,Xe=et.slice(st),st+=ve[1].length),at&&/^ *$/.test(dt)&&(je+=dt+` `,be=be.substring(dt.length+1),$e=!0),!$e){const De=new RegExp(`^ {0,${Math.min(3,st-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),Ie=new RegExp(`^ {0,${Math.min(3,st-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),Re=new RegExp(`^ {0,${Math.min(3,st-1)}}(?:\`\`\`|~~~)`),Se=new RegExp(`^ {0,${Math.min(3,st-1)}}#`);for(;be;){const We=be.split(` `,1)[0];if(dt=We,this.options.pedantic&&(dt=dt.replace(/^ {1,4}(?=( {4})*[^ ])/g," ")),Re.test(dt)||Se.test(dt)||De.test(dt)||Ie.test(be))break;if(dt.search(/[^ ]/)>=st||!dt.trim())Xe+=` `+dt.slice(st);else{if(at||et.search(/[^ ]/)>=4||Re.test(et)||Se.test(et)||Ie.test(et))break;Xe+=` `+dt}!at&&!dt.trim()&&(at=!0),je+=We+` `,be=be.substring(We.length+1),et=dt.slice(st)}}Pe.loose||(He?Pe.loose=!0:/\n *\n *$/.test(je)&&(He=!0));let pt=null,bt;this.options.gfm&&(pt=/^\[[ xX]\] /.exec(Xe),pt&&(bt=pt[0]!=="[ ] ",Xe=Xe.replace(/^\[[ xX]\] +/,""))),Pe.items.push({type:"list_item",raw:je,task:!!pt,checked:bt,loose:!1,text:Xe,tokens:[]}),Pe.raw+=je}Pe.items[Pe.items.length-1].raw=Pe.items[Pe.items.length-1].raw.trimEnd(),Pe.items[Pe.items.length-1].text=Pe.items[Pe.items.length-1].text.trimEnd(),Pe.raw=Pe.raw.trimEnd();for(let $e=0;$eet.type==="space"),Xe=je.length>0&&je.some(et=>/\n.*\n/.test(et.raw));Pe.loose=Xe}if(Pe.loose)for(let $e=0;$e$/,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",Pe=ve[3]?ve[3].substring(1,ve[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):ve[3];return{type:"def",tag:we,raw:ve[0],href:Te,title:Pe}}}table(be){const ve=this.rules.block.table.exec(be);if(!ve||!/[:|]/.test(ve[2]))return;const we=i(ve[1]),Te=ve[2].replace(/^\||\| *$/g,"").split("|"),Pe=ve[3]&&ve[3].trim()?ve[3].replace(/\n[ \t]*$/,"").split(` `):[],Be={type:"table",raw:ve[0],header:[],align:[],rows:[]};if(we.length===Te.length){for(const He of Te)/^ *-+: *$/.test(He)?Be.align.push("right"):/^ *:-+: *$/.test(He)?Be.align.push("center"):/^ *:-+ *$/.test(He)?Be.align.push("left"):Be.align.push(null);for(let He=0;He({text:$e,tokens:this.lexer.inline($e),header:!1,align:Be.align[je]})));return Be}}lheading(be){const ve=this.rules.block.lheading.exec(be);if(ve)return{type:"heading",raw:ve[0],depth:ve[2].charAt(0)==="="?1:2,text:ve[1],tokens:this.lexer.inline(ve[1])}}paragraph(be){const ve=this.rules.block.paragraph.exec(be);if(ve){const we=ve[1].charAt(ve[1].length-1)===` `?ve[1].slice(0,-1):ve[1];return{type:"paragraph",raw:ve[0],text:we,tokens:this.lexer.inline(we)}}}text(be){const ve=this.rules.block.text.exec(be);if(ve)return{type:"text",raw:ve[0],text:ve[0],tokens:this.lexer.inline(ve[0])}}escape(be){const ve=this.rules.inline.escape.exec(be);if(ve)return{type:"escape",raw:ve[0],text:b(ve[1])}}tag(be){const ve=this.rules.inline.tag.exec(be);if(ve)return!this.lexer.state.inLink&&/^/i.test(ve[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(ve[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(ve[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:ve[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:ve[0]}}link(be){const ve=this.rules.inline.link.exec(be);if(ve){const we=ve[2].trim();if(!this.options.pedantic&&/^$/.test(we))return;const Be=s(we.slice(0,-1),"\\");if((we.length-Be.length)%2===0)return}else{const Be=g(ve[2],"()");if(Be>-1){const $e=(ve[0].indexOf("!")===0?5:4)+ve[1].length+Be;ve[2]=ve[2].substring(0,Be),ve[0]=ve[0].substring(0,$e).trim(),ve[3]=""}}let Te=ve[2],Pe="";if(this.options.pedantic){const Be=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(Te);Be&&(Te=Be[1],Pe=Be[3])}else Pe=ve[3]?ve[3].slice(1,-1):"";return Te=Te.trim(),/^$/.test(we)?Te=Te.slice(1):Te=Te.slice(1,-1)),c(ve,{href:Te&&Te.replace(this.rules.inline.anyPunctuation,"$1"),title:Pe&&Pe.replace(this.rules.inline.anyPunctuation,"$1")},ve[0],this.lexer)}}reflink(be,ve){let we;if((we=this.rules.inline.reflink.exec(be))||(we=this.rules.inline.nolink.exec(be))){const Te=(we[2]||we[1]).replace(/\s+/g," "),Pe=ve[Te.toLowerCase()];if(!Pe){const Be=we[0].charAt(0);return{type:"text",raw:Be,text:Be}}return c(we,Pe,we[0],this.lexer)}}emStrong(be,ve,we=""){let Te=this.rules.inline.emStrongLDelim.exec(be);if(!Te||Te[3]&&we.match(/[\p{L}\p{N}]/u))return;if(!(Te[1]||Te[2]||"")||!we||this.rules.inline.punctuation.exec(we)){const Be=[...Te[0]].length-1;let He,$e,je=Be,Xe=0;const et=Te[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(et.lastIndex=0,ve=ve.slice(-1*be.length+Be);(Te=et.exec(ve))!=null;){if(He=Te[1]||Te[2]||Te[3]||Te[4]||Te[5]||Te[6],!He)continue;if($e=[...He].length,Te[3]||Te[4]){je+=$e;continue}else if((Te[5]||Te[6])&&Be%3&&!((Be+$e)%3)){Xe+=$e;continue}if(je-=$e,je>0)continue;$e=Math.min($e,$e+je+Xe);const dt=[...Te[0]][0].length,at=be.slice(0,Be+Te.index+dt+$e);if(Math.min(Be,$e)%2){const pt=at.slice(1,-1);return{type:"em",raw:at,text:pt,tokens:this.lexer.inlineTokens(pt)}}const st=at.slice(2,-2);return{type:"strong",raw:at,text:st,tokens:this.lexer.inlineTokens(st)}}}}codespan(be){const ve=this.rules.inline.code.exec(be);if(ve){let we=ve[2].replace(/\n/g," ");const Te=/[^ ]/.test(we),Pe=/^ /.test(we)&&/ $/.test(we);return Te&&Pe&&(we=we.substring(1,we.length-1)),we=b(we,!0),{type:"codespan",raw:ve[0],text:we}}}br(be){const ve=this.rules.inline.br.exec(be);if(ve)return{type:"br",raw:ve[0]}}del(be){const ve=this.rules.inline.del.exec(be);if(ve)return{type:"del",raw:ve[0],text:ve[2],tokens:this.lexer.inlineTokens(ve[2])}}autolink(be){const ve=this.rules.inline.autolink.exec(be);if(ve){let we,Te;return ve[2]==="@"?(we=b(ve[1]),Te="mailto:"+we):(we=b(ve[1]),Te=we),{type:"link",raw:ve[0],text:we,href:Te,tokens:[{type:"text",raw:we,text:we}]}}}url(be){let ve;if(ve=this.rules.inline.url.exec(be)){let we,Te;if(ve[2]==="@")we=b(ve[0]),Te="mailto:"+we;else{let Pe;do Pe=ve[0],ve[0]=this.rules.inline._backpedal.exec(ve[0])?.[0]??"";while(Pe!==ve[0]);we=b(ve[0]),ve[1]==="www."?Te="http://"+ve[0]:Te=ve[0]}return{type:"link",raw:ve[0],text:we,href:Te,tokens:[{type:"text",raw:we,text:we}]}}}inlineText(be){const ve=this.rules.inline.text.exec(be);if(ve){let we;return this.lexer.state.inRawBlock?we=ve[0]:we=b(ve[0]),{type:"text",raw:ve[0],text:we}}}}const r=/^(?: *(?:\n|$))+/,u=/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,C=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,f=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,h=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,v=/(?:[*+-]|\d{1,9}[.)])/,w=n(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g,v).replace(/blockCode/g,/ {4}/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).getRegex(),S=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,L=/^[^\n]+/,D=/(?!\s*\])(?:\\.|[^\[\]\\])+/,T=n(/^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/).replace("label",D).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),M=n(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,v).getRegex(),A="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",P=/|$))/,N=n("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))","i").replace("comment",P).replace("tag",A).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),O=n(S).replace("hr",f).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),x={blockquote:n(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",O).getRegex(),code:u,def:T,fences:C,heading:h,hr:f,html:N,lheading:w,list:M,newline:r,paragraph:O,table:t,text:L},W=n("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",f).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),V={...x,table:W,paragraph:n(S).replace("hr",f).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",W).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex()},q={...x,html:n(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",P).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:t,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:n(S).replace("hr",f).replace("heading",` *#{1,6} *[^ ]`).replace("lheading",w).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},H=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,z=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,U=/^( {2,}|\\)\n(?!\s*$)/,j=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\]*?>/g,R=n(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,"u").replace(/punct/g,Y).getRegex(),J=n("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])","gu").replace(/punct/g,Y).getRegex(),ie=n("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])","gu").replace(/punct/g,Y).getRegex(),ue=n(/\\([punct])/,"gu").replace(/punct/g,Y).getRegex(),he=n(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),pe=n(P).replace("(?:-->|$)","-->").getRegex(),ae=n("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",pe).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),ee=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,de=n(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",ee).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ge=n(/^!?\[(label)\]\[(ref)\]/).replace("label",ee).replace("ref",D).getRegex(),X=n(/^!?\[(ref)\](?:\[\])?/).replace("ref",D).getRegex(),B=n("reflink|nolink(?!\\()","g").replace("reflink",ge).replace("nolink",X).getRegex(),$={_backpedal:t,anyPunctuation:ue,autolink:he,blockSkip:K,br:U,code:z,del:t,emStrongLDelim:R,emStrongRDelimAst:J,emStrongRDelimUnd:ie,escape:H,link:de,nolink:X,punctuation:G,reflink:ge,reflinkSearch:B,tag:ae,text:j,url:t},Q={...$,link:n(/^!?\[(label)\]\((.*?)\)/).replace("label",ee).getRegex(),reflink:n(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",ee).getRegex()},Z={...$,escape:n(H).replace("])","~|])").getRegex(),url:n(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,"i").replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\$e+" ".repeat(je.length));let Te,Pe,Be;for(;be;)if(!(this.options.extensions&&this.options.extensions.block&&this.options.extensions.block.some(He=>(Te=He.call({lexer:this},be,ve))?(be=be.substring(Te.raw.length),ve.push(Te),!0):!1))){if(Te=this.tokenizer.space(be)){be=be.substring(Te.raw.length),Te.raw.length===1&&ve.length>0?ve[ve.length-1].raw+=` `:ve.push(Te);continue}if(Te=this.tokenizer.code(be)){be=be.substring(Te.raw.length),Pe=ve[ve.length-1],Pe&&(Pe.type==="paragraph"||Pe.type==="text")?(Pe.raw+=` `+Te.raw,Pe.text+=` `+Te.text,this.inlineQueue[this.inlineQueue.length-1].src=Pe.text):ve.push(Te);continue}if(Te=this.tokenizer.fences(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Te=this.tokenizer.heading(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Te=this.tokenizer.hr(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Te=this.tokenizer.blockquote(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Te=this.tokenizer.list(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Te=this.tokenizer.html(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Te=this.tokenizer.def(be)){be=be.substring(Te.raw.length),Pe=ve[ve.length-1],Pe&&(Pe.type==="paragraph"||Pe.type==="text")?(Pe.raw+=` `+Te.raw,Pe.text+=` `+Te.raw,this.inlineQueue[this.inlineQueue.length-1].src=Pe.text):this.tokens.links[Te.tag]||(this.tokens.links[Te.tag]={href:Te.href,title:Te.title});continue}if(Te=this.tokenizer.table(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Te=this.tokenizer.lheading(be)){be=be.substring(Te.raw.length),ve.push(Te);continue}if(Be=be,this.options.extensions&&this.options.extensions.startBlock){let He=1/0;const $e=be.slice(1);let je;this.options.extensions.startBlock.forEach(Xe=>{je=Xe.call({lexer:this},$e),typeof je=="number"&&je>=0&&(He=Math.min(He,je))}),He<1/0&&He>=0&&(Be=be.substring(0,He+1))}if(this.state.top&&(Te=this.tokenizer.paragraph(Be))){Pe=ve[ve.length-1],we&&Pe?.type==="paragraph"?(Pe.raw+=` `+Te.raw,Pe.text+=` `+Te.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=Pe.text):ve.push(Te),we=Be.length!==be.length,be=be.substring(Te.raw.length);continue}if(Te=this.tokenizer.text(be)){be=be.substring(Te.raw.length),Pe=ve[ve.length-1],Pe&&Pe.type==="text"?(Pe.raw+=` `+Te.raw,Pe.text+=` `+Te.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=Pe.text):ve.push(Te);continue}if(be){const He="Infinite loop on byte: "+be.charCodeAt(0);if(this.options.silent){console.error(He);break}else throw new Error(He)}}return this.state.top=!0,ve}inline(be,ve=[]){return this.inlineQueue.push({src:be,tokens:ve}),ve}inlineTokens(be,ve=[]){let we,Te,Pe,Be=be,He,$e,je;if(this.tokens.links){const Xe=Object.keys(this.tokens.links);if(Xe.length>0)for(;(He=this.tokenizer.rules.inline.reflinkSearch.exec(Be))!=null;)Xe.includes(He[0].slice(He[0].lastIndexOf("[")+1,-1))&&(Be=Be.slice(0,He.index)+"["+"a".repeat(He[0].length-2)+"]"+Be.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(He=this.tokenizer.rules.inline.blockSkip.exec(Be))!=null;)Be=Be.slice(0,He.index)+"["+"a".repeat(He[0].length-2)+"]"+Be.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;(He=this.tokenizer.rules.inline.anyPunctuation.exec(Be))!=null;)Be=Be.slice(0,He.index)+"++"+Be.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;be;)if($e||(je=""),$e=!1,!(this.options.extensions&&this.options.extensions.inline&&this.options.extensions.inline.some(Xe=>(we=Xe.call({lexer:this},be,ve))?(be=be.substring(we.raw.length),ve.push(we),!0):!1))){if(we=this.tokenizer.escape(be)){be=be.substring(we.raw.length),ve.push(we);continue}if(we=this.tokenizer.tag(be)){be=be.substring(we.raw.length),Te=ve[ve.length-1],Te&&we.type==="text"&&Te.type==="text"?(Te.raw+=we.raw,Te.text+=we.text):ve.push(we);continue}if(we=this.tokenizer.link(be)){be=be.substring(we.raw.length),ve.push(we);continue}if(we=this.tokenizer.reflink(be,this.tokens.links)){be=be.substring(we.raw.length),Te=ve[ve.length-1],Te&&we.type==="text"&&Te.type==="text"?(Te.raw+=we.raw,Te.text+=we.text):ve.push(we);continue}if(we=this.tokenizer.emStrong(be,Be,je)){be=be.substring(we.raw.length),ve.push(we);continue}if(we=this.tokenizer.codespan(be)){be=be.substring(we.raw.length),ve.push(we);continue}if(we=this.tokenizer.br(be)){be=be.substring(we.raw.length),ve.push(we);continue}if(we=this.tokenizer.del(be)){be=be.substring(we.raw.length),ve.push(we);continue}if(we=this.tokenizer.autolink(be)){be=be.substring(we.raw.length),ve.push(we);continue}if(!this.state.inLink&&(we=this.tokenizer.url(be))){be=be.substring(we.raw.length),ve.push(we);continue}if(Pe=be,this.options.extensions&&this.options.extensions.startInline){let Xe=1/0;const et=be.slice(1);let dt;this.options.extensions.startInline.forEach(at=>{dt=at.call({lexer:this},et),typeof dt=="number"&&dt>=0&&(Xe=Math.min(Xe,dt))}),Xe<1/0&&Xe>=0&&(Pe=be.substring(0,Xe+1))}if(we=this.tokenizer.inlineText(Pe)){be=be.substring(we.raw.length),we.raw.slice(-1)!=="_"&&(je=we.raw.slice(-1)),$e=!0,Te=ve[ve.length-1],Te&&Te.type==="text"?(Te.raw+=we.raw,Te.text+=we.text):ve.push(we);continue}if(be){const Xe="Infinite loop on byte: "+be.charCodeAt(0);if(this.options.silent){console.error(Xe);break}else throw new Error(Xe)}}return ve}}class Ce{options;parser;constructor(be){this.options=be||oe.defaults}space(be){return""}code({text:be,lang:ve,escaped:we}){const Te=(ve||"").match(/^\S*/)?.[0],Pe=be.replace(/\n$/,"")+` `;return Te?'
      '+(we?Pe:b(Pe,!0))+`
      `:"
      "+(we?Pe:b(Pe,!0))+`
      `}blockquote({tokens:be}){return`
      ${this.parser.parse(be)}
      `}html({text:be}){return be}heading({tokens:be,depth:ve}){return`${this.parser.parseInline(be)} `}hr(be){return`
      `}list(be){const ve=be.ordered,we=be.start;let Te="";for(let He=0;He `+Te+" `}listitem(be){let ve="";if(be.task){const we=this.checkbox({checked:!!be.checked});be.loose?be.tokens.length>0&&be.tokens[0].type==="paragraph"?(be.tokens[0].text=we+" "+be.tokens[0].text,be.tokens[0].tokens&&be.tokens[0].tokens.length>0&&be.tokens[0].tokens[0].type==="text"&&(be.tokens[0].tokens[0].text=we+" "+be.tokens[0].tokens[0].text)):be.tokens.unshift({type:"text",raw:we+" ",text:we+" "}):ve+=we+" "}return ve+=this.parser.parse(be.tokens,!!be.loose),`
    2. ${ve}
    3. `}checkbox({checked:be}){return"'}paragraph({tokens:be}){return`

      ${this.parser.parseInline(be)}

      `}table(be){let ve="",we="";for(let Pe=0;Pe${Te}`),` `+ve+` `+Te+`
      `}tablerow({text:be}){return` ${be} `}tablecell(be){const ve=this.parser.parseInline(be.tokens),we=be.header?"th":"td";return(be.align?`<${we} align="${be.align}">`:`<${we}>`)+ve+` `}strong({tokens:be}){return`${this.parser.parseInline(be)}`}em({tokens:be}){return`${this.parser.parseInline(be)}`}codespan({text:be}){return`${be}`}br(be){return"
      "}del({tokens:be}){return`${this.parser.parseInline(be)}`}link({href:be,title:ve,tokens:we}){const Te=this.parser.parseInline(we),Pe=o(be);if(Pe===null)return Te;be=Pe;let Be='
      ",Be}image({href:be,title:ve,text:we}){const Te=o(be);if(Te===null)return we;be=Te;let Pe=`${we}{const He=Pe[Be].flat(1/0);we=we.concat(this.walkTokens(He,ve))}):Pe.tokens&&(we=we.concat(this.walkTokens(Pe.tokens,ve)))}}return we}use(...be){const ve=this.defaults.extensions||{renderers:{},childTokens:{}};return be.forEach(we=>{const Te={...we};if(Te.async=this.defaults.async||Te.async||!1,we.extensions&&(we.extensions.forEach(Pe=>{if(!Pe.name)throw new Error("extension name required");if("renderer"in Pe){const Be=ve.renderers[Pe.name];Be?ve.renderers[Pe.name]=function(...He){let $e=Pe.renderer.apply(this,He);return $e===!1&&($e=Be.apply(this,He)),$e}:ve.renderers[Pe.name]=Pe.renderer}if("tokenizer"in Pe){if(!Pe.level||Pe.level!=="block"&&Pe.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");const Be=ve[Pe.level];Be?Be.unshift(Pe.tokenizer):ve[Pe.level]=[Pe.tokenizer],Pe.start&&(Pe.level==="block"?ve.startBlock?ve.startBlock.push(Pe.start):ve.startBlock=[Pe.start]:Pe.level==="inline"&&(ve.startInline?ve.startInline.push(Pe.start):ve.startInline=[Pe.start]))}"childTokens"in Pe&&Pe.childTokens&&(ve.childTokens[Pe.name]=Pe.childTokens)}),Te.extensions=ve),we.renderer){const Pe=this.defaults.renderer||new Ce(this.defaults);for(const Be in we.renderer){if(!(Be in Pe))throw new Error(`renderer '${Be}' does not exist`);if(["options","parser"].includes(Be))continue;const He=Be,$e=we.renderer[He],je=Pe[He];Pe[He]=(...Xe)=>{let et=$e.apply(Pe,Xe);return et===!1&&(et=je.apply(Pe,Xe)),et||""}}Te.renderer=Pe}if(we.tokenizer){const Pe=this.defaults.tokenizer||new a(this.defaults);for(const Be in we.tokenizer){if(!(Be in Pe))throw new Error(`tokenizer '${Be}' does not exist`);if(["options","rules","lexer"].includes(Be))continue;const He=Be,$e=we.tokenizer[He],je=Pe[He];Pe[He]=(...Xe)=>{let et=$e.apply(Pe,Xe);return et===!1&&(et=je.apply(Pe,Xe)),et}}Te.tokenizer=Pe}if(we.hooks){const Pe=this.defaults.hooks||new Ee;for(const Be in we.hooks){if(!(Be in Pe))throw new Error(`hook '${Be}' does not exist`);if(Be==="options")continue;const He=Be,$e=we.hooks[He],je=Pe[He];Ee.passThroughHooks.has(Be)?Pe[He]=Xe=>{if(this.defaults.async)return Promise.resolve($e.call(Pe,Xe)).then(dt=>je.call(Pe,dt));const et=$e.call(Pe,Xe);return je.call(Pe,et)}:Pe[He]=(...Xe)=>{let et=$e.apply(Pe,Xe);return et===!1&&(et=je.apply(Pe,Xe)),et}}Te.hooks=Pe}if(we.walkTokens){const Pe=this.defaults.walkTokens,Be=we.walkTokens;Te.walkTokens=function(He){let $e=[];return $e.push(Be.call(this,He)),Pe&&($e=$e.concat(Pe.call(this,He))),$e}}this.defaults={...this.defaults,...Te}}),this}setOptions(be){return this.defaults={...this.defaults,...be},this}lexer(be,ve){return me.lex(be,ve??this.defaults)}parser(be,ve){return Le.parse(be,ve??this.defaults)}parseMarkdown(be,ve){return(Te,Pe)=>{const Be={...Pe},He={...this.defaults,...Be},$e=this.onError(!!He.silent,!!He.async);if(this.defaults.async===!0&&Be.async===!1)return $e(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof Te>"u"||Te===null)return $e(new Error("marked(): input parameter is undefined or null"));if(typeof Te!="string")return $e(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(Te)+", string expected"));if(He.hooks&&(He.hooks.options=He),He.async)return Promise.resolve(He.hooks?He.hooks.preprocess(Te):Te).then(je=>be(je,He)).then(je=>He.hooks?He.hooks.processAllTokens(je):je).then(je=>He.walkTokens?Promise.all(this.walkTokens(je,He.walkTokens)).then(()=>je):je).then(je=>ve(je,He)).then(je=>He.hooks?He.hooks.postprocess(je):je).catch($e);try{He.hooks&&(Te=He.hooks.preprocess(Te));let je=be(Te,He);He.hooks&&(je=He.hooks.processAllTokens(je)),He.walkTokens&&this.walkTokens(je,He.walkTokens);let Xe=ve(je,He);return He.hooks&&(Xe=He.hooks.postprocess(Xe)),Xe}catch(je){return $e(je)}}}onError(be,ve){return we=>{if(we.message+=` Please report this to https://github.com/markedjs/marked.`,be){const Te="

      An error occurred:

      "+b(we.message+"",!0)+"
      ";return ve?Promise.resolve(Te):Te}if(ve)return Promise.reject(we);throw we}}}const Ae=new Me;function Ne(xe,be){return Ae.parse(xe,be)}Ne.options=Ne.setOptions=function(xe){return Ae.setOptions(xe),Ne.defaults=Ae.defaults,d(Ne.defaults),Ne},Ne.getDefaults=e,Ne.defaults=oe.defaults,Ne.use=function(...xe){return Ae.use(...xe),Ne.defaults=Ae.defaults,d(Ne.defaults),Ne},Ne.walkTokens=function(xe,be){return Ae.walkTokens(xe,be)},Ne.parseInline=Ae.parseInline,Ne.Parser=Le,Ne.parser=Le.parse,Ne.Renderer=Ce,Ne.TextRenderer=ye,Ne.Lexer=me,Ne.lexer=me.lex,Ne.Tokenizer=a,Ne.Hooks=Ee,Ne.parse=Ne;const Ke=Ne.options,ze=Ne.setOptions,Ge=Ne.use,it=Ne.walkTokens,Oe=Ne.parseInline,Fe=Ne,fe=Le.parse,_e=me.lex;oe.Hooks=Ee,oe.Lexer=me,oe.Marked=Me,oe.Parser=Le,oe.Renderer=Ce,oe.TextRenderer=ye,oe.Tokenizer=a,oe.getDefaults=e,oe.lexer=_e,oe.marked=Ne,oe.options=Ke,oe.parse=Fe,oe.parseInline=Oe,oe.parser=fe,oe.setOptions=ze,oe.use=Ge,oe.walkTokens=it}),define(ne[128],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Mimes=void 0,e.Mimes=Object.freeze({text:"text/plain",binary:"application/octet-stream",unknown:"application/unknown",markdown:"text/markdown",latex:"text/latex",uriList:"text/uri-list"})}),define(ne[224],se([1,0,128]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DataTransfers=void 0,e.DataTransfers={RESOURCES:"ResourceURLs",DOWNLOAD_URL:"DownloadURL",FILES:"Files",TEXT:d.Mimes.text,INTERNAL_URI_LIST:"application/vnd.code.uri-list"}}),define(ne[448],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getKoreanAltChars=d;function d(o){const t=E(o);if(t&&t.length>0)return new Uint32Array(t)}let k=0;const I=new Uint32Array(10);function E(o){if(k=0,y(o,_,4352),k>0||(y(o,b,4449),k>0)||(y(o,p,4520),k>0)||(y(o,n,12593),k))return I.subarray(0,k);if(o>=44032&&o<=55203){const t=o-44032,i=t%588,s=Math.floor(t/588),g=Math.floor(i/28),c=i%28-1;if(s<_.length?y(s,_,0):4352+s-12593=0&&(c0)return I.subarray(0,k)}}function y(o,t,i){o>=i&&o>8&&(I[k++]=o>>8&255),o>>16&&(I[k++]=o>>16&255))}const _=new Uint8Array([114,82,115,101,69,102,97,113,81,116,84,100,119,87,99,122,120,118,103]),b=new Uint16Array([107,111,105,79,106,112,117,80,104,27496,28520,27752,121,110,27246,28782,27758,98,109,27757,108]),p=new Uint16Array([114,82,29810,115,30579,26483,101,102,29286,24934,29030,29798,30822,30310,26470,97,113,29809,116,84,100,119,99,122,120,118,103]),n=new Uint16Array([114,82,29810,115,30579,26483,101,69,102,29286,24934,29030,29798,30822,30310,26470,97,113,81,29809,116,84,100,119,87,99,122,120,118,103,107,111,105,79,106,112,117,80,104,27496,28520,27752,121,110,27246,28782,27758,98,109,27757,108])}),define(ne[449],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ArrayNavigator=void 0;class d{constructor(I,E=0,y=I.length,m=E-1){this.items=I,this.start=E,this.end=y,this.index=m}current(){return this.index===this.start-1||this.index===this.end?null:this.items[this.index]}next(){return this.index=Math.min(this.index+1,this.end),this.current()}previous(){return this.index=Math.max(this.index-1,this.start-1),this.current()}first(){return this.index=this.start,this.current()}last(){return this.index=this.end-1,this.current()}}e.ArrayNavigator=d}),define(ne[450],se([1,0,449]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HistoryNavigator=void 0;class k{constructor(E=[],y=10){this._initialize(E),this._limit=y,this._onChange()}getHistory(){return this._elements}add(E){this._history.delete(E),this._history.add(E),this._onChange()}next(){return this._navigator.next()}previous(){return this._currentPosition()!==0?this._navigator.previous():null}current(){return this._navigator.current()}first(){return this._navigator.first()}last(){return this._navigator.last()}isLast(){return this._currentPosition()>=this._elements.length-1}isNowhere(){return this._navigator.current()===null}has(E){return this._history.has(E)}_onChange(){this._reduceToLimit();const E=this._elements;this._navigator=new d.ArrayNavigator(E,0,E.length,E.length)}_reduceToLimit(){const E=this._elements;E.length>this._limit&&this._initialize(E.slice(E.length-this._limit))}_currentPosition(){const E=this._navigator.current();return E?this._elements.indexOf(E):-1}_initialize(E){this._history=new Set;for(const y of E)this._history.add(y)}get _elements(){const E=[];return this._history.forEach(y=>E.push(y)),E}}e.HistoryNavigator=k}),define(ne[141],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SlidingWindowAverage=e.MovingAverage=void 0,e.clamp=d;function d(E,y,m){return Math.min(Math.max(E,y),m)}class k{constructor(){this._n=1,this._val=0}update(y){return this._val=this._val+(y-this._val)/this._n,this._n+=1,this._val}get value(){return this._val}}e.MovingAverage=k;class I{constructor(y){this._n=0,this._val=0,this._values=[],this._index=0,this._sum=0,this._values=new Array(y),this._values.fill(0,0,y)}update(y){const m=this._values[this._index];return this._values[this._index]=y,this._index=(this._index+1)%this._values.length,this._sum-=m,this._sum+=y,this._nc.debugName).join(", ")+")",{color:"gray"})}handleDerivedCreated(g){const c=g.handleChange;this.changedObservablesSets.set(g,new Set),g.handleChange=(l,a)=>(this.changedObservablesSets.get(g).add(l),c.apply(g,[l,a]))}handleDerivedRecomputed(g,c){const l=this.changedObservablesSets.get(g);console.log(...this.textToConsoleArgs([_("derived recomputed"),b(g.debugName,{color:"BlueViolet"}),...this.formatInfo(c),this.formatChanges(l),{data:[{fn:g._debugNameData.referenceFn??g._computeFn}]}])),l.clear()}handleFromEventObservableTriggered(g,c){console.log(...this.textToConsoleArgs([_("observable from event triggered"),b(g.debugName,{color:"BlueViolet"}),...this.formatInfo(c),{data:[{fn:g._getValue}]}]))}handleAutorunCreated(g){const c=g.handleChange;this.changedObservablesSets.set(g,new Set),g.handleChange=(l,a)=>(this.changedObservablesSets.get(g).add(l),c.apply(g,[l,a]))}handleAutorunTriggered(g){const c=this.changedObservablesSets.get(g);console.log(...this.textToConsoleArgs([_("autorun"),b(g.debugName,{color:"BlueViolet"}),this.formatChanges(c),{data:[{fn:g._debugNameData.referenceFn??g._runFn}]}])),c.clear(),this.indentation++}handleAutorunFinished(g){this.indentation--}handleBeginTransaction(g){let c=g.getDebugName();c===void 0&&(c=""),console.log(...this.textToConsoleArgs([_("transaction"),b(c,{color:"BlueViolet"}),{data:[{fn:g._fn}]}])),this.indentation++}handleEndTransaction(){this.indentation--}}e.ConsoleObservableLogger=E;function y(s){const g=new Array,c=[];let l="";function a(u){if("length"in u)for(const C of u)C&&a(C);else"text"in u?(l+=`%c${u.text}`,g.push(u.style),u.data&&c.push(...u.data)):"data"in u&&c.push(...u.data)}a(s);const r=[l,...g];return r.push(...c),r}function m(s){return b(s,{color:"black"})}function _(s){return b(i(`${s}: `,10),{color:"black",bold:!0})}function b(s,g={color:"black"}){function c(a){return Object.entries(a).reduce((r,[u,C])=>`${r}${u}:${C};`,"")}const l={color:g.color};return g.strikeThrough&&(l["text-decoration"]="line-through"),g.bold&&(l["font-weight"]="bold"),{text:s,style:c(l)}}function p(s,g){switch(typeof s){case"number":return""+s;case"string":return s.length+2<=g?`"${s}"`:`"${s.substr(0,g-7)}"+...`;case"boolean":return s?"true":"false";case"undefined":return"undefined";case"object":return s===null?"null":Array.isArray(s)?n(s,g):o(s,g);case"symbol":return s.toString();case"function":return`[[Function${s.name?" "+s.name:""}]]`;default:return""+s}}function n(s,g){let c="[ ",l=!0;for(const a of s){if(l||(c+=", "),c.length-5>g){c+="...";break}l=!1,c+=`${p(a,g-c.length)}`}return c+=" ]",c}function o(s,g){let c="{ ",l=!0;for(const[a,r]of Object.entries(s)){if(l||(c+=", "),c.length-5>g){c+="...";break}l=!1,c+=`${a}: ${p(r,g-c.length)}`}return c+=" }",c}function t(s,g){let c="";for(let l=1;l<=g;l++)c+=s;return c}function i(s,g){for(;s.length{i.clear(),t(g,c,i)});return(0,k.toDisposable)(()=>{s.dispose(),i.dispose()})}function p(o){const t=new k.DisposableStore,i=m({owner:void 0,debugName:void 0,debugReferenceFn:o},s=>{t.clear(),o(s,t)});return(0,k.toDisposable)(()=>{i.dispose(),t.dispose()})}class n{get debugName(){return this._debugNameData.getDebugName(this)??"(anonymous)"}constructor(t,i,s,g){this._debugNameData=t,this._runFn=i,this.createChangeSummary=s,this._handleChange=g,this.state=2,this.updateCount=0,this.disposed=!1,this.dependencies=new Set,this.dependenciesToBeRemoved=new Set,this.changeSummary=this.createChangeSummary?.(),(0,E.getLogger)()?.handleAutorunCreated(this),this._runIfNeeded(),(0,k.trackDisposable)(this)}dispose(){this.disposed=!0;for(const t of this.dependencies)t.removeObserver(this);this.dependencies.clear(),(0,k.markAsDisposed)(this)}_runIfNeeded(){if(this.state===3)return;const t=this.dependenciesToBeRemoved;this.dependenciesToBeRemoved=this.dependencies,this.dependencies=t,this.state=3;const i=this.disposed;try{if(!i){(0,E.getLogger)()?.handleAutorunTriggered(this);const s=this.changeSummary;this.changeSummary=this.createChangeSummary?.(),this._runFn(this,s)}}finally{i||(0,E.getLogger)()?.handleAutorunFinished(this);for(const s of this.dependenciesToBeRemoved)s.removeObserver(this);this.dependenciesToBeRemoved.clear()}}toString(){return`Autorun<${this.debugName}>`}beginUpdate(){this.state===3&&(this.state=1),this.updateCount++}endUpdate(){if(this.updateCount===1)do{if(this.state===1){this.state=3;for(const t of this.dependencies)if(t.reportChanges(),this.state===2)break}this._runIfNeeded()}while(this.state!==3);this.updateCount--,(0,d.assertFn)(()=>this.updateCount>=0)}handlePossibleChange(t){this.state===3&&this.dependencies.has(t)&&!this.dependenciesToBeRemoved.has(t)&&(this.state=1)}handleChange(t,i){this.dependencies.has(t)&&!this.dependenciesToBeRemoved.has(t)&&(!this._handleChange||this._handleChange({changedObservable:t,change:i,didChange:g=>g===t},this.changeSummary))&&(this.state=2)}readObservable(t){if(this.disposed)return t.get();t.addObserver(this);const i=t.get();return this.dependencies.add(t),this.dependenciesToBeRemoved.delete(t),i}}e.AutorunObserver=n,function(o){o.Observer=n}(y||(e.autorun=y={}))}),define(ne[92],se([1,0,102,161,162]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DisposableObservableValue=e.ObservableValue=e.TransactionImpl=e.BaseObservable=e.ConvenientObservable=void 0,e._setRecomputeInitiallyAndOnChange=y,e._setKeepObserved=_,e._setDerivedOpts=p,e.transaction=t,e.globalTransaction=s,e.asyncTransaction=g,e.subtransaction=c,e.observableValue=a,e.disposableObservableValue=u;let E;function y(f){E=f}let m;function _(f){m=f}let b;function p(f){b=f}class n{get TChange(){return null}reportChanges(){this.get()}read(h){return h?h.readObservable(this):this.get()}map(h,v){const w=v===void 0?void 0:h,S=v===void 0?h:v;return b({owner:w,debugName:()=>{const L=(0,k.getFunctionName)(S);if(L!==void 0)return L;const T=/^\s*\(?\s*([a-zA-Z_$][a-zA-Z_$0-9]*)\s*\)?\s*=>\s*\1(?:\??)\.([a-zA-Z_$][a-zA-Z_$0-9]*)\s*$/.exec(S.toString());if(T)return`${this.debugName}.${T[2]}`;if(!w)return`${this.debugName} (mapped)`},debugReferenceFn:S},L=>S(this.read(L),L))}flatten(){return b({owner:void 0,debugName:()=>`${this.debugName} (flattened)`},h=>this.read(h).read(h))}recomputeInitiallyAndOnChange(h,v){return h.add(E(this,v)),this}keepObserved(h){return h.add(m(this)),this}}e.ConvenientObservable=n;class o extends n{constructor(){super(...arguments),this.observers=new Set}addObserver(h){const v=this.observers.size;this.observers.add(h),v===0&&this.onFirstObserverAdded()}removeObserver(h){this.observers.delete(h)&&this.observers.size===0&&this.onLastObserverRemoved()}onFirstObserverAdded(){}onLastObserverRemoved(){}}e.BaseObservable=o;function t(f,h){const v=new l(f,h);try{f(v)}finally{v.finish()}}let i;function s(f){if(i)f(i);else{const h=new l(f,void 0);i=h;try{f(h)}finally{h.finish(),i=void 0}}}async function g(f,h){const v=new l(f,h);try{await f(v)}finally{v.finish()}}function c(f,h,v){f?h(f):t(h,v)}class l{constructor(h,v){this._fn=h,this._getDebugName=v,this.updatingObservers=[],(0,I.getLogger)()?.handleBeginTransaction(this)}getDebugName(){return this._getDebugName?this._getDebugName():(0,k.getFunctionName)(this._fn)}updateObserver(h,v){this.updatingObservers.push({observer:h,observable:v}),h.beginUpdate(v)}finish(){const h=this.updatingObservers;for(let v=0;v{},()=>`Setting ${this.debugName}`));try{const L=this._value;this._setValue(h),(0,I.getLogger)()?.handleObservableChanged(this,{oldValue:L,newValue:h,change:w,didChange:!0,hadValue:!0});for(const D of this.observers)v.updateObserver(D,this),D.handleChange(this,w)}finally{S&&S.finish()}}toString(){return`${this.debugName}: ${this._value}`}_setValue(h){this._value=h}}e.ObservableValue=r;function u(f,h){let v;return typeof f=="string"?v=new k.DebugNameData(void 0,f,void 0):v=new k.DebugNameData(f,void 0,void 0),new C(v,h,d.strictEquals)}class C extends r{_setValue(h){this._value!==h&&(this._value&&this._value.dispose(),this._value=h)}dispose(){this._value?.dispose()}}e.DisposableObservableValue=C}),define(ne[65],se([1,0,90,102,2,92,161,162]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DerivedWithSetter=e.Derived=void 0,e.derived=_,e.derivedWithSetter=b,e.derivedOpts=p,e.derivedHandleChanges=n,e.derivedWithStore=o,e.derivedDisposable=t;function _(g,c){return c!==void 0?new i(new y.DebugNameData(g,void 0,c),c,void 0,void 0,void 0,k.strictEquals):new i(new y.DebugNameData(void 0,void 0,g),g,void 0,void 0,void 0,k.strictEquals)}function b(g,c,l){return new s(new y.DebugNameData(g,void 0,c),c,void 0,void 0,void 0,k.strictEquals,l)}function p(g,c){return new i(new y.DebugNameData(g.owner,g.debugName,g.debugReferenceFn),c,void 0,void 0,g.onLastObserverRemoved,g.equalsFn??k.strictEquals)}(0,E._setDerivedOpts)(p);function n(g,c){return new i(new y.DebugNameData(g.owner,g.debugName,void 0),c,g.createEmptyChangeSummary,g.handleChange,void 0,g.equalityComparer??k.strictEquals)}function o(g,c){let l,a;c===void 0?(l=g,a=void 0):(a=g,l=c);const r=new I.DisposableStore;return new i(new y.DebugNameData(a,void 0,l),u=>(r.clear(),l(u,r)),void 0,void 0,()=>r.dispose(),k.strictEquals)}function t(g,c){let l,a;c===void 0?(l=g,a=void 0):(a=g,l=c);let r;return new i(new y.DebugNameData(a,void 0,l),u=>{r?r.clear():r=new I.DisposableStore;const C=l(u);return C&&r.add(C),C},void 0,void 0,()=>{r&&(r.dispose(),r=void 0)},k.strictEquals)}class i extends E.BaseObservable{get debugName(){return this._debugNameData.getDebugName(this)??"(anonymous)"}constructor(c,l,a,r,u=void 0,C){super(),this._debugNameData=c,this._computeFn=l,this.createChangeSummary=a,this._handleChange=r,this._handleLastObserverRemoved=u,this._equalityComparator=C,this.state=0,this.value=void 0,this.updateCount=0,this.dependencies=new Set,this.dependenciesToBeRemoved=new Set,this.changeSummary=void 0,this.changeSummary=this.createChangeSummary?.(),(0,m.getLogger)()?.handleDerivedCreated(this)}onLastObserverRemoved(){this.state=0,this.value=void 0;for(const c of this.dependencies)c.removeObserver(this);this.dependencies.clear(),this._handleLastObserverRemoved?.()}get(){if(this.observers.size===0){const c=this._computeFn(this,this.createChangeSummary?.());return this.onLastObserverRemoved(),c}else{do{if(this.state===1){for(const c of this.dependencies)if(c.reportChanges(),this.state===2)break}this.state===1&&(this.state=3),this._recomputeIfNeeded()}while(this.state!==3);return this.value}}_recomputeIfNeeded(){if(this.state===3)return;const c=this.dependenciesToBeRemoved;this.dependenciesToBeRemoved=this.dependencies,this.dependencies=c;const l=this.state!==0,a=this.value;this.state=3;const r=this.changeSummary;this.changeSummary=this.createChangeSummary?.();try{this.value=this._computeFn(this,r)}finally{for(const C of this.dependenciesToBeRemoved)C.removeObserver(this);this.dependenciesToBeRemoved.clear()}const u=l&&!this._equalityComparator(a,this.value);if((0,m.getLogger)()?.handleDerivedRecomputed(this,{oldValue:a,newValue:this.value,change:void 0,didChange:u,hadValue:l}),u)for(const C of this.observers)C.handleChange(this,void 0)}toString(){return`LazyDerived<${this.debugName}>`}beginUpdate(c){this.updateCount++;const l=this.updateCount===1;if(this.state===3&&(this.state=1,!l))for(const a of this.observers)a.handlePossibleChange(this);if(l)for(const a of this.observers)a.beginUpdate(this)}endUpdate(c){if(this.updateCount--,this.updateCount===0){const l=[...this.observers];for(const a of l)a.endUpdate(this)}(0,d.assertFn)(()=>this.updateCount>=0)}handlePossibleChange(c){if(this.state===3&&this.dependencies.has(c)&&!this.dependenciesToBeRemoved.has(c)){this.state=1;for(const l of this.observers)l.handlePossibleChange(this)}}handleChange(c,l){if(this.dependencies.has(c)&&!this.dependenciesToBeRemoved.has(c)){const a=this._handleChange?this._handleChange({changedObservable:c,change:l,didChange:u=>u===c},this.changeSummary):!0,r=this.state===3;if(a&&(this.state===1||r)&&(this.state=2,r))for(const u of this.observers)u.handlePossibleChange(this)}}readObservable(c){c.addObserver(this);const l=c.get();return this.dependencies.add(c),this.dependenciesToBeRemoved.delete(c),l}addObserver(c){const l=!this.observers.has(c)&&this.updateCount>0;super.addObserver(c),l&&c.beginUpdate(this)}removeObserver(c){const l=this.observers.has(c)&&this.updateCount>0;super.removeObserver(c),l&&c.endUpdate(this)}}e.Derived=i;class s extends i{constructor(c,l,a,r,u=void 0,C,f){super(c,l,a,r,u,C),this.set=f}}e.DerivedWithSetter=s}),define(ne[451],se([1,0,92]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LazyObservableValue=void 0;class k extends d.BaseObservable{get debugName(){return this._debugNameData.getDebugName(this)??"LazyObservableValue"}constructor(E,y,m){super(),this._debugNameData=E,this._equalityComparator=m,this._isUpToDate=!0,this._deltas=[],this._updateCounter=0,this._value=y}get(){return this._update(),this._value}_update(){if(!this._isUpToDate)if(this._isUpToDate=!0,this._deltas.length>0){for(const E of this.observers)for(const y of this._deltas)E.handleChange(this,y);this._deltas.length=0}else for(const E of this.observers)E.handleChange(this,void 0)}_beginUpdate(){if(this._updateCounter++,this._updateCounter===1)for(const E of this.observers)E.beginUpdate(this)}_endUpdate(){if(this._updateCounter--,this._updateCounter===0){this._update();const E=[...this.observers];for(const y of E)y.endUpdate(this)}}addObserver(E){const y=!this.observers.has(E)&&this._updateCounter>0;super.addObserver(E),y&&E.beginUpdate(this)}removeObserver(E){const y=this.observers.has(E)&&this._updateCounter>0;super.removeObserver(E),y&&E.endUpdate(this)}set(E,y,m){if(m===void 0&&this._equalityComparator(this._value,E))return;let _;y||(y=_=new d.TransactionImpl(()=>{},()=>`Setting ${this.debugName}`));try{if(this._isUpToDate=!1,this._setValue(E),m!==void 0&&this._deltas.push(m),y.updateObserver({beginUpdate:()=>this._beginUpdate(),endUpdate:()=>this._endUpdate(),handleChange:(b,p)=>{},handlePossibleChange:b=>{}},this),this._updateCounter>1)for(const b of this.observers)b.handlePossibleChange(this)}finally{_&&_.finish()}}toString(){return`${this.debugName}: ${this._value}`}_setValue(E){this._value=E}}e.LazyObservableValue=k}),define(ne[452],se([1,0,102,92,161,451]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.observableValueOpts=y;function y(m,_){return m.lazy?new E.LazyObservableValue(new I.DebugNameData(m.owner,m.debugName,void 0),_,m.equalsFn??d.strictEquals):new k.ObservableValue(new I.DebugNameData(m.owner,m.debugName,void 0),_,m.equalsFn??d.strictEquals)}}),define(ne[453],se([1,0,299,92,8]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PromiseResult=e.ObservablePromise=void 0,e.waitForState=m;class E{static fromFn(b){return new E(b())}constructor(b){this._value=(0,k.observableValue)(this,void 0),this.promiseResult=this._value,this.promise=b.then(p=>((0,k.transaction)(n=>{this._value.set(new y(p,void 0),n)}),p),p=>{throw(0,k.transaction)(n=>{this._value.set(new y(void 0,p),n)}),p})}}e.ObservablePromise=E;class y{constructor(b,p){this.data=b,this.error=p}}e.PromiseResult=y;function m(_,b,p,n){return b||(b=o=>o!=null),new Promise((o,t)=>{let i=!0,s=!1;const g=_.map(l=>({isFinished:b(l),error:p?p(l):!1,state:l})),c=(0,d.autorun)(l=>{const{isFinished:a,error:r,state:u}=g.read(l);(a||r)&&(i?s=!0:c.dispose(),r?t(r===!0?u:r):o(u))});if(n){const l=n.onCancellationRequested(()=>{c.dispose(),l.dispose(),t(new I.CancellationError)});if(n.isCancellationRequested){c.dispose(),l.dispose(),t(new I.CancellationError);return}}i=!1,s&&c.dispose()})}}),define(ne[188],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Range=void 0;var d;(function(k){function I(_,b){if(_.start>=b.end||b.start>=_.end)return{start:0,end:0};const p=Math.max(_.start,b.start),n=Math.min(_.end,b.end);return n-p<=0?{start:0,end:0}:{start:p,end:n}}k.intersect=I;function E(_){return _.end-_.start<=0}k.isEmpty=E;function y(_,b){return!E(I(_,b))}k.intersects=y;function m(_,b){const p=[],n={start:_.start,end:Math.min(b.start,_.end)},o={start:Math.max(b.end,_.start),end:_.end};return E(n)||p.push(n),E(o)||p.push(o),p}k.relativeComplement=m})(d||(e.Range=d={}))}),define(ne[454],se([1,0,188]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RangeMap=void 0,e.groupIntersect=k,e.shift=I,e.consolidate=E;function k(_,b){const p=[];for(const n of b){if(_.start>=n.range.end)continue;if(_.endb.concat(p),[]))}class m{get paddingTop(){return this._paddingTop}set paddingTop(b){this._size=this._size+b-this._paddingTop,this._paddingTop=b}constructor(b){this.groups=[],this._size=0,this._paddingTop=0,this._paddingTop=b??0,this._size=this._paddingTop}splice(b,p,n=[]){const o=n.length-p,t=k({start:0,end:b},this.groups),i=k({start:b+p,end:Number.POSITIVE_INFINITY},this.groups).map(g=>({range:I(g.range,o),size:g.size})),s=n.map((g,c)=>({range:{start:b+c,end:b+c+1},size:g.size}));this.groups=y(t,s,i),this._size=this._paddingTop+this.groups.reduce((g,c)=>g+c.size*(c.range.end-c.range.start),0)}get count(){const b=this.groups.length;return b?this.groups[b-1].range.end:0}get size(){return this._size}indexAt(b){if(b<0)return-1;if(bI.Disposable.None;function M($){if(b){const{onDidAddListener:Q}=$,Z=i.create();let te=0;$.onDidAddListener=()=>{++te===2&&(console.warn("snapshotted emitter LIKELY used public and SHOULD HAVE BEEN created with DisposableStore. snapshotted here"),Z.print()),Q?.()}}}function A($,Q){return U($,()=>{},0,void 0,!0,void 0,Q)}T.defer=A;function P($){return(Q,Z=null,te)=>{let re=!1,le;return le=$(me=>{if(!re)return le?le.dispose():re=!0,Q.call(Z,me)},null,te),re&&le.dispose(),le}}T.once=P;function N($,Q){return T.once(T.filter($,Q))}T.onceIf=N;function O($,Q,Z){return H((te,re=null,le)=>$(me=>te.call(re,Q(me)),null,le),Z)}T.map=O;function F($,Q,Z){return H((te,re=null,le)=>$(me=>{Q(me),te.call(re,me)},null,le),Z)}T.forEach=F;function x($,Q,Z){return H((te,re=null,le)=>$(me=>Q(me)&&te.call(re,me),null,le),Z)}T.filter=x;function W($){return $}T.signal=W;function V(...$){return(Q,Z=null,te)=>{const re=(0,I.combinedDisposable)(...$.map(le=>le(me=>Q.call(Z,me))));return z(re,te)}}T.any=V;function q($,Q,Z,te){let re=Z;return O($,le=>(re=Q(re,le),re),te)}T.reduce=q;function H($,Q){let Z;const te={onWillAddFirstListener(){Z=$(re.fire,re)},onDidRemoveLastListener(){Z?.dispose()}};Q||M(te);const re=new u(te);return Q?.add(re),re.event}function z($,Q){return Q instanceof Array?Q.push($):Q&&Q.add($),$}function U($,Q,Z=100,te=!1,re=!1,le,me){let Ce,ye,Le,Ee=0,Me;const Ae={leakWarningThreshold:le,onWillAddFirstListener(){Ce=$(Ke=>{Ee++,ye=Q(ye,Ke),te&&!Le&&(Ne.fire(ye),ye=void 0),Me=()=>{const ze=ye;ye=void 0,Le=void 0,(!te||Ee>1)&&Ne.fire(ze),Ee=0},typeof Z=="number"?(clearTimeout(Le),Le=setTimeout(Me,Z)):Le===void 0&&(Le=0,queueMicrotask(Me))})},onWillRemoveListener(){re&&Ee>0&&Me?.()},onDidRemoveLastListener(){Me=void 0,Ce.dispose()}};me||M(Ae);const Ne=new u(Ae);return me?.add(Ne),Ne.event}T.debounce=U;function j($,Q=0,Z){return T.debounce($,(te,re)=>te?(te.push(re),te):[re],Q,void 0,!0,void 0,Z)}T.accumulate=j;function Y($,Q=(te,re)=>te===re,Z){let te=!0,re;return x($,le=>{const me=te||!Q(le,re);return te=!1,re=le,me},Z)}T.latch=Y;function G($,Q,Z){return[T.filter($,Q,Z),T.filter($,te=>!Q(te),Z)]}T.split=G;function K($,Q=!1,Z=[],te){let re=Z.slice(),le=$(ye=>{re?re.push(ye):Ce.fire(ye)});te&&te.add(le);const me=()=>{re?.forEach(ye=>Ce.fire(ye)),re=null},Ce=new u({onWillAddFirstListener(){le||(le=$(ye=>Ce.fire(ye)),te&&te.add(le))},onDidAddFirstListener(){re&&(Q?setTimeout(me):me())},onDidRemoveLastListener(){le&&le.dispose(),le=null}});return te&&te.add(Ce),Ce.event}T.buffer=K;function R($,Q){return(te,re,le)=>{const me=Q(new ie);return $(function(Ce){const ye=me.evaluate(Ce);ye!==J&&te.call(re,ye)},void 0,le)}}T.chain=R;const J=Symbol("HaltChainable");class ie{constructor(){this.steps=[]}map(Q){return this.steps.push(Q),this}forEach(Q){return this.steps.push(Z=>(Q(Z),Z)),this}filter(Q){return this.steps.push(Z=>Q(Z)?Z:J),this}reduce(Q,Z){let te=Z;return this.steps.push(re=>(te=Q(te,re),te)),this}latch(Q=(Z,te)=>Z===te){let Z=!0,te;return this.steps.push(re=>{const le=Z||!Q(re,te);return Z=!1,te=re,le?re:J}),this}evaluate(Q){for(const Z of this.steps)if(Q=Z(Q),Q===J)break;return Q}}function ue($,Q,Z=te=>te){const te=(...Ce)=>me.fire(Z(...Ce)),re=()=>$.on(Q,te),le=()=>$.removeListener(Q,te),me=new u({onWillAddFirstListener:re,onDidRemoveLastListener:le});return me.event}T.fromNodeEventEmitter=ue;function he($,Q,Z=te=>te){const te=(...Ce)=>me.fire(Z(...Ce)),re=()=>$.addEventListener(Q,te),le=()=>$.removeEventListener(Q,te),me=new u({onWillAddFirstListener:re,onDidRemoveLastListener:le});return me.event}T.fromDOMEventEmitter=he;function pe($){return new Promise(Q=>P($)(Q))}T.toPromise=pe;function ae($){const Q=new u;return $.then(Z=>{Q.fire(Z)},()=>{Q.fire(void 0)}).finally(()=>{Q.dispose()}),Q.event}T.fromPromise=ae;function ee($,Q){return $(Z=>Q.fire(Z))}T.forward=ee;function de($,Q,Z){return Q(Z),$(te=>Q(te))}T.runAndSubscribe=de;class ge{constructor(Q,Z){this._observable=Q,this._counter=0,this._hasChanged=!1;const te={onWillAddFirstListener:()=>{Q.addObserver(this),this._observable.reportChanges()},onDidRemoveLastListener:()=>{Q.removeObserver(this)}};Z||M(te),this.emitter=new u(te),Z&&Z.add(this.emitter)}beginUpdate(Q){this._counter++}handlePossibleChange(Q){}handleChange(Q,Z){this._hasChanged=!0}endUpdate(Q){this._counter--,this._counter===0&&(this._observable.reportChanges(),this._hasChanged&&(this._hasChanged=!1,this.emitter.fire(this._observable.get())))}}function X($,Q){return new ge($,Q).emitter.event}T.fromObservable=X;function B($){return(Q,Z,te)=>{let re=0,le=!1;const me={beginUpdate(){re++},endUpdate(){re--,re===0&&($.reportChanges(),le&&(le=!1,Q.call(Z)))},handlePossibleChange(){},handleChange(){le=!0}};$.addObserver(me),$.reportChanges();const Ce={dispose(){$.removeObserver(me)}};return te instanceof I.DisposableStore?te.add(Ce):Array.isArray(te)&&te.push(Ce),Ce}}T.fromObservableLight=B})(p||(e.Event=p={}));class n{static{this.all=new Set}static{this._idPool=0}constructor(M){this.listenerCount=0,this.invocationCount=0,this.elapsedOverall=0,this.durations=[],this.name=`${M}_${n._idPool++}`,n.all.add(this)}start(M){this._stopWatch=new y.StopWatch,this.listenerCount=M}stop(){if(this._stopWatch){const M=this._stopWatch.elapsed();this.durations.push(M),this.elapsedOverall+=M,this.invocationCount+=1,this._stopWatch=void 0}}}e.EventProfiling=n;let o=-1;class t{static{this._idPool=1}constructor(M,A,P=(t._idPool++).toString(16).padStart(3,"0")){this._errorHandler=M,this.threshold=A,this.name=P,this._warnCountdown=0}dispose(){this._stacks?.clear()}check(M,A){const P=this.threshold;if(P<=0||A{const O=this._stacks.get(M.value)||0;this._stacks.set(M.value,O-1)}}getMostFrequentStack(){if(!this._stacks)return;let M,A=0;for(const[P,N]of this._stacks)(!M||A{if(T instanceof c)M(T);else for(let A=0;A{T.length!==0&&(console.warn("[LEAKING LISTENERS] GC'ed these listeners that were NOT yet disposed:"),console.warn(T.join(` `)),T.length=0)},3e3),r=new FinalizationRegistry(M=>{typeof M=="string"&&T.push(M)})}class u{constructor(M){this._size=0,this._options=M,this._leakageMon=o>0||this._options?.leakWarningThreshold?new t(M?.onListenerError??d.onUnexpectedError,this._options?.leakWarningThreshold??o):void 0,this._perfMon=this._options?._profName?new n(this._options._profName):void 0,this._deliveryQueue=this._options?.deliveryQueue}dispose(){if(!this._disposed){if(this._disposed=!0,this._deliveryQueue?.current===this&&this._deliveryQueue.reset(),this._listeners){if(_){const M=this._listeners;queueMicrotask(()=>{a(M,A=>A.stack?.print())})}this._listeners=void 0,this._size=0}this._options?.onDidRemoveLastListener?.(),this._leakageMon?.dispose()}}get event(){return this._event??=(M,A,P)=>{if(this._leakageMon&&this._size>this._leakageMon.threshold**2){const W=`[${this._leakageMon.name}] REFUSES to accept new listeners because it exceeded its threshold by far (${this._size} vs ${this._leakageMon.threshold})`;console.warn(W);const V=this._leakageMon.getMostFrequentStack()??["UNKNOWN stack",-1],q=new g(`${W}. HINT: Stack shows most frequent listener (${V[1]}-times)`,V[0]);return(this._options?.onListenerError||d.onUnexpectedError)(q),I.Disposable.None}if(this._disposed)return I.Disposable.None;A&&(M=M.bind(A));const N=new c(M);let O,F;this._leakageMon&&this._size>=Math.ceil(this._leakageMon.threshold*.2)&&(N.stack=i.create(),O=this._leakageMon.check(N.stack,this._size+1)),_&&(N.stack=F??i.create()),this._listeners?this._listeners instanceof c?(this._deliveryQueue??=new f,this._listeners=[this._listeners,N]):this._listeners.push(N):(this._options?.onWillAddFirstListener?.(this),this._listeners=N,this._options?.onDidAddFirstListener?.(this)),this._size++;const x=(0,I.toDisposable)(()=>{r?.unregister(x),O?.(),this._removeListener(N)});if(P instanceof I.DisposableStore?P.add(x):Array.isArray(P)&&P.push(x),r){const W=new Error().stack.split(` `).slice(2,3).join(` `).trim(),V=/(file:|vscode-file:\/\/vscode-app)?(\/[^:]*:\d+:\d+)/.exec(W);r.register(x,V?.[2]??W,x)}return x},this._event}_removeListener(M){if(this._options?.onWillRemoveListener?.(this),!this._listeners)return;if(this._size===1){this._listeners=void 0,this._options?.onDidRemoveLastListener?.(this),this._size=0;return}const A=this._listeners,P=A.indexOf(M);if(P===-1)throw console.log("disposed?",this._disposed),console.log("size?",this._size),console.log("arr?",JSON.stringify(this._listeners)),new Error("Attempted to dispose unknown listener");this._size--,A[P]=void 0;const N=this._deliveryQueue.current===this;if(this._size*l<=A.length){let O=0;for(let F=0;F0}}e.Emitter=u;const C=()=>new f;e.createEventDeliveryQueue=C;class f{constructor(){this.i=-1,this.end=0}enqueue(M,A,P){this.i=0,this.end=P,this.current=M,this.value=A}reset(){this.i=this.end,this.current=void 0,this.value=void 0}}class h extends u{constructor(M){super(M),this._isPaused=0,this._eventQueue=new E.LinkedList,this._mergeFn=M?.merge}pause(){this._isPaused++}resume(){if(this._isPaused!==0&&--this._isPaused===0)if(this._mergeFn){if(this._eventQueue.size>0){const M=Array.from(this._eventQueue);this._eventQueue.clear(),super.fire(this._mergeFn(M))}}else for(;!this._isPaused&&this._eventQueue.size!==0;)super.fire(this._eventQueue.shift())}fire(M){this._size&&(this._isPaused!==0?this._eventQueue.push(M):super.fire(M))}}e.PauseableEmitter=h;class v extends h{constructor(M){super(M),this._delay=M.delay??100}fire(M){this._handle||(this.pause(),this._handle=setTimeout(()=>{this._handle=void 0,this.resume()},this._delay)),super.fire(M)}}e.DebounceEmitter=v;class w extends u{constructor(M){super(M),this._queuedEvents=[],this._mergeFn=M?.merge}fire(M){this.hasListeners()&&(this._queuedEvents.push(M),this._queuedEvents.length===1&&queueMicrotask(()=>{this._mergeFn?super.fire(this._mergeFn(this._queuedEvents)):this._queuedEvents.forEach(A=>super.fire(A)),this._queuedEvents=[]}))}}e.MicrotaskEmitter=w;class S{constructor(){this.hasListeners=!1,this.events=[],this.emitter=new u({onWillAddFirstListener:()=>this.onFirstListenerAdd(),onDidRemoveLastListener:()=>this.onLastListenerRemove()})}get event(){return this.emitter.event}add(M){const A={event:M,listener:null};this.events.push(A),this.hasListeners&&this.hook(A);const P=()=>{this.hasListeners&&this.unhook(A);const N=this.events.indexOf(A);this.events.splice(N,1)};return(0,I.toDisposable)((0,k.createSingleCallFunction)(P))}onFirstListenerAdd(){this.hasListeners=!0,this.events.forEach(M=>this.hook(M))}onLastListenerRemove(){this.hasListeners=!1,this.events.forEach(M=>this.unhook(M))}hook(M){M.listener=M.event(A=>this.emitter.fire(A))}unhook(M){M.listener?.dispose(),M.listener=null}dispose(){this.emitter.dispose();for(const M of this.events)M.listener?.dispose();this.events=[]}}e.EventMultiplexer=S;class L{constructor(){this.data=[]}wrapEvent(M,A,P){return(N,O,F)=>M(x=>{const W=this.data[this.data.length-1];if(!A){W?W.buffers.push(()=>N.call(O,x)):N.call(O,x);return}const V=W;if(!V){N.call(O,A(P,x));return}V.items??=[],V.items.push(x),V.buffers.length===0&&W.buffers.push(()=>{V.reducedResult??=P?V.items.reduce(A,P):V.items.reduce(A),N.call(O,V.reducedResult)})},void 0,F)}bufferEvents(M){const A={buffers:new Array};this.data.push(A);const P=M();return this.data.pop(),A.buffers.forEach(N=>N()),P}}e.EventBufferer=L;class D{constructor(){this.listening=!1,this.inputEvent=p.None,this.inputEventListener=I.Disposable.None,this.emitter=new u({onDidAddFirstListener:()=>{this.listening=!0,this.inputEventListener=this.inputEvent(this.emitter.fire,this.emitter)},onDidRemoveLastListener:()=>{this.listening=!1,this.inputEventListener.dispose()}}),this.event=this.emitter.event}set input(M){this.inputEvent=M,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=M(this.emitter.fire,this.emitter))}dispose(){this.inputEventListener.dispose(),this.emitter.dispose()}}e.Relay=D}),define(ne[93],se([1,0,6]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DomEmitter=void 0;class k{get event(){return this.emitter.event}constructor(E,y,m){const _=b=>this.emitter.fire(b);this.emitter=new d.Emitter({onWillAddFirstListener:()=>E.addEventListener(y,_,m),onDidRemoveLastListener:()=>E.removeEventListener(y,_,m)})}dispose(){this.emitter.dispose()}}e.DomEmitter=k}),define(ne[18],se([1,0,6]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CancellationTokenSource=e.CancellationToken=void 0,e.cancelOnDispose=m;const k=Object.freeze(function(_,b){const p=setTimeout(_.bind(b),0);return{dispose(){clearTimeout(p)}}});var I;(function(_){function b(p){return p===_.None||p===_.Cancelled||p instanceof E?!0:!p||typeof p!="object"?!1:typeof p.isCancellationRequested=="boolean"&&typeof p.onCancellationRequested=="function"}_.isCancellationToken=b,_.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:d.Event.None}),_.Cancelled=Object.freeze({isCancellationRequested:!0,onCancellationRequested:k})})(I||(e.CancellationToken=I={}));class E{constructor(){this._isCancelled=!1,this._emitter=null}cancel(){this._isCancelled||(this._isCancelled=!0,this._emitter&&(this._emitter.fire(void 0),this.dispose()))}get isCancellationRequested(){return this._isCancelled}get onCancellationRequested(){return this._isCancelled?k:(this._emitter||(this._emitter=new d.Emitter),this._emitter.event)}dispose(){this._emitter&&(this._emitter.dispose(),this._emitter=null)}}class y{constructor(b){this._token=void 0,this._parentListener=void 0,this._parentListener=b&&b.onCancellationRequested(this.cancel,this)}get token(){return this._token||(this._token=new E),this._token}cancel(){this._token?this._token instanceof E&&this._token.cancel():this._token=I.Cancelled}dispose(b=!1){b&&this.cancel(),this._parentListener?.dispose(),this._token?this._token instanceof E&&this._token.dispose():this._token=I.None}}e.CancellationTokenSource=y;function m(_){const b=new y;return _.add({dispose(){b.cancel()}}),b.token}}),define(ne[300],se([1,0,6]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IME=e.IMEImpl=void 0;class k{constructor(){this._onDidChange=new d.Emitter,this.onDidChange=this._onDidChange.event,this._enabled=!0}get enabled(){return this._enabled}enable(){this._enabled=!0,this._onDidChange.fire()}disable(){this._enabled=!1,this._onDidChange.fire()}}e.IMEImpl=k,e.IME=new k}),define(ne[189],se([1,0,6,2,92,161,65,162,102]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ValueWithChangeEventFromObservable=e.KeepAliveObserver=e.FromEventObservable=void 0,e.constObservable=b,e.observableFromEvent=n,e.observableFromEventOpts=o,e.observableSignalFromEvent=i,e.observableSignal=g,e.keepObserved=l,e.recomputeInitiallyAndOnChange=a,e.derivedObservableWithCache=u,e.derivedObservableWithWritableCache=C,e.mapObservableArrayCached=f,e.observableFromValueWithChangeEvent=w,e.derivedConstOnceDefined=S;function b(L){return new p(L)}class p extends I.ConvenientObservable{constructor(D){super(),this.value=D}get debugName(){return this.toString()}get(){return this.value}addObserver(D){}removeObserver(D){}toString(){return`Const: ${this.value}`}}function n(...L){let D,T,M;return L.length===3?[D,T,M]=L:[T,M]=L,new t(new E.DebugNameData(D,void 0,M),T,M,()=>t.globalTransaction,_.strictEquals)}function o(L,D,T){return new t(new E.DebugNameData(L.owner,L.debugName,L.debugReferenceFn??T),D,T,()=>t.globalTransaction,L.equalsFn??_.strictEquals)}class t extends I.BaseObservable{constructor(D,T,M,A,P){super(),this._debugNameData=D,this.event=T,this._getValue=M,this._getTransaction=A,this._equalityComparator=P,this.hasValue=!1,this.handleEvent=N=>{const O=this._getValue(N),F=this.value,x=!this.hasValue||!this._equalityComparator(F,O);let W=!1;x&&(this.value=O,this.hasValue&&(W=!0,(0,I.subtransaction)(this._getTransaction(),V=>{(0,m.getLogger)()?.handleFromEventObservableTriggered(this,{oldValue:F,newValue:O,change:void 0,didChange:x,hadValue:this.hasValue});for(const q of this.observers)V.updateObserver(q,this),q.handleChange(this,void 0)},()=>{const V=this.getDebugName();return"Event fired"+(V?`: ${V}`:"")})),this.hasValue=!0),W||(0,m.getLogger)()?.handleFromEventObservableTriggered(this,{oldValue:F,newValue:O,change:void 0,didChange:x,hadValue:this.hasValue})}}getDebugName(){return this._debugNameData.getDebugName(this)}get debugName(){const D=this.getDebugName();return"From Event"+(D?`: ${D}`:"")}onFirstObserverAdded(){this.subscription=this.event(this.handleEvent)}onLastObserverRemoved(){this.subscription.dispose(),this.subscription=void 0,this.hasValue=!1,this.value=void 0}get(){return this.subscription?(this.hasValue||this.handleEvent(void 0),this.value):this._getValue(void 0)}}e.FromEventObservable=t,function(L){L.Observer=t;function D(T,M){let A=!1;t.globalTransaction===void 0&&(t.globalTransaction=T,A=!0);try{M()}finally{A&&(t.globalTransaction=void 0)}}L.batchEventsGlobally=D}(n||(e.observableFromEvent=n={}));function i(L,D){return new s(L,D)}class s extends I.BaseObservable{constructor(D,T){super(),this.debugName=D,this.event=T,this.handleEvent=()=>{(0,I.transaction)(M=>{for(const A of this.observers)M.updateObserver(A,this),A.handleChange(this,void 0)},()=>this.debugName)}}onFirstObserverAdded(){this.subscription=this.event(this.handleEvent)}onLastObserverRemoved(){this.subscription.dispose(),this.subscription=void 0}get(){}}function g(L){return typeof L=="string"?new c(L):new c(void 0,L)}class c extends I.BaseObservable{get debugName(){return new E.DebugNameData(this._owner,this._debugName,void 0).getDebugName(this)??"Observable Signal"}toString(){return this.debugName}constructor(D,T){super(),this._debugName=D,this._owner=T}trigger(D,T){if(!D){(0,I.transaction)(M=>{this.trigger(M,T)},()=>`Trigger signal ${this.debugName}`);return}for(const M of this.observers)D.updateObserver(M,this),M.handleChange(this,T)}get(){}}function l(L){const D=new r(!1,void 0);return L.addObserver(D),(0,k.toDisposable)(()=>{L.removeObserver(D)})}(0,I._setKeepObserved)(l);function a(L,D){const T=new r(!0,D);return L.addObserver(T),D?D(L.get()):L.reportChanges(),(0,k.toDisposable)(()=>{L.removeObserver(T)})}(0,I._setRecomputeInitiallyAndOnChange)(a);class r{constructor(D,T){this._forceRecompute=D,this._handleValue=T,this._counter=0}beginUpdate(D){this._counter++}endUpdate(D){this._counter--,this._counter===0&&this._forceRecompute&&(this._handleValue?this._handleValue(D.get()):D.reportChanges())}handlePossibleChange(D){}handleChange(D,T){}}e.KeepAliveObserver=r;function u(L,D){let T;return(0,y.derivedOpts)({owner:L,debugReferenceFn:D},A=>(T=D(A,T),T))}function C(L,D){let T;const M=g("derivedObservableWithWritableCache"),A=(0,y.derived)(L,P=>(M.read(P),T=D(P,T),T));return Object.assign(A,{clearCache:P=>{T=void 0,M.trigger(P)},setCache:(P,N)=>{T=P,M.trigger(N)}})}function f(L,D,T,M){let A=new h(T,M);return(0,y.derivedOpts)({debugReferenceFn:T,owner:L,onLastObserverRemoved:()=>{A.dispose(),A=new h(T)}},N=>(A.setItems(D.read(N)),A.getItems()))}class h{constructor(D,T){this._map=D,this._keySelector=T,this._cache=new Map,this._items=[]}dispose(){this._cache.forEach(D=>D.store.dispose()),this._cache.clear()}setItems(D){const T=[],M=new Set(this._cache.keys());for(const A of D){const P=this._keySelector?this._keySelector(A):A;let N=this._cache.get(P);if(N)M.delete(P);else{const O=new k.DisposableStore;N={out:this._map(A,O),store:O},this._cache.set(P,N)}T.push(N.out)}for(const A of M)this._cache.get(A).store.dispose(),this._cache.delete(A);this._items=T}getItems(){return this._items}}class v{constructor(D){this.observable=D}get onDidChange(){return d.Event.fromObservableLight(this.observable)}get value(){return this.observable.get()}}e.ValueWithChangeEventFromObservable=v;function w(L,D){return D instanceof v?D.observable:n(L,D.onDidChange,()=>D.value)}function S(L,D){return u(L,(T,M)=>M??D(T))}}),define(ne[21],se([1,0,92,65,299,189,453,452,162]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.observableValueOpts=e.waitForState=e.PromiseResult=e.ObservablePromise=e.observableSignalFromEvent=e.observableSignal=e.observableFromEvent=e.recomputeInitiallyAndOnChange=e.keepObserved=e.derivedObservableWithWritableCache=e.derivedObservableWithCache=e.constObservable=e.autorunWithStoreHandleChanges=e.autorunOpts=e.autorunWithStore=e.autorunHandleChanges=e.autorun=e.derivedWithStore=e.derivedHandleChanges=e.derivedOpts=e.derived=e.subtransaction=e.transaction=e.disposableObservableValue=e.observableValue=void 0,Object.defineProperty(e,"observableValue",{enumerable:!0,get:function(){return d.observableValue}}),Object.defineProperty(e,"disposableObservableValue",{enumerable:!0,get:function(){return d.disposableObservableValue}}),Object.defineProperty(e,"transaction",{enumerable:!0,get:function(){return d.transaction}}),Object.defineProperty(e,"subtransaction",{enumerable:!0,get:function(){return d.subtransaction}}),Object.defineProperty(e,"derived",{enumerable:!0,get:function(){return k.derived}}),Object.defineProperty(e,"derivedOpts",{enumerable:!0,get:function(){return k.derivedOpts}}),Object.defineProperty(e,"derivedHandleChanges",{enumerable:!0,get:function(){return k.derivedHandleChanges}}),Object.defineProperty(e,"derivedWithStore",{enumerable:!0,get:function(){return k.derivedWithStore}}),Object.defineProperty(e,"autorun",{enumerable:!0,get:function(){return I.autorun}}),Object.defineProperty(e,"autorunHandleChanges",{enumerable:!0,get:function(){return I.autorunHandleChanges}}),Object.defineProperty(e,"autorunWithStore",{enumerable:!0,get:function(){return I.autorunWithStore}}),Object.defineProperty(e,"autorunOpts",{enumerable:!0,get:function(){return I.autorunOpts}}),Object.defineProperty(e,"autorunWithStoreHandleChanges",{enumerable:!0,get:function(){return I.autorunWithStoreHandleChanges}}),Object.defineProperty(e,"constObservable",{enumerable:!0,get:function(){return E.constObservable}}),Object.defineProperty(e,"derivedObservableWithCache",{enumerable:!0,get:function(){return E.derivedObservableWithCache}}),Object.defineProperty(e,"derivedObservableWithWritableCache",{enumerable:!0,get:function(){return E.derivedObservableWithWritableCache}}),Object.defineProperty(e,"keepObserved",{enumerable:!0,get:function(){return E.keepObserved}}),Object.defineProperty(e,"recomputeInitiallyAndOnChange",{enumerable:!0,get:function(){return E.recomputeInitiallyAndOnChange}}),Object.defineProperty(e,"observableFromEvent",{enumerable:!0,get:function(){return E.observableFromEvent}}),Object.defineProperty(e,"observableSignal",{enumerable:!0,get:function(){return E.observableSignal}}),Object.defineProperty(e,"observableSignalFromEvent",{enumerable:!0,get:function(){return E.observableSignalFromEvent}}),Object.defineProperty(e,"ObservablePromise",{enumerable:!0,get:function(){return y.ObservablePromise}}),Object.defineProperty(e,"PromiseResult",{enumerable:!0,get:function(){return y.PromiseResult}}),Object.defineProperty(e,"waitForState",{enumerable:!0,get:function(){return y.waitForState}}),Object.defineProperty(e,"observableValueOpts",{enumerable:!0,get:function(){return m.observableValueOpts}}),!1&&(0,_.setLogger)(new _.ConsoleObservableLogger)}),define(ne[163],se([1,0,6,2]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SmoothScrollingOperation=e.SmoothScrollingUpdate=e.Scrollable=e.ScrollState=void 0;class I{constructor(t,i,s,g,c,l,a){this._forceIntegerValues=t,this._scrollStateBrand=void 0,this._forceIntegerValues&&(i=i|0,s=s|0,g=g|0,c=c|0,l=l|0,a=a|0),this.rawScrollLeft=g,this.rawScrollTop=a,i<0&&(i=0),g+i>s&&(g=s-i),g<0&&(g=0),c<0&&(c=0),a+c>l&&(a=l-c),a<0&&(a=0),this.width=i,this.scrollWidth=s,this.scrollLeft=g,this.height=c,this.scrollHeight=l,this.scrollTop=a}equals(t){return this.rawScrollLeft===t.rawScrollLeft&&this.rawScrollTop===t.rawScrollTop&&this.width===t.width&&this.scrollWidth===t.scrollWidth&&this.scrollLeft===t.scrollLeft&&this.height===t.height&&this.scrollHeight===t.scrollHeight&&this.scrollTop===t.scrollTop}withScrollDimensions(t,i){return new I(this._forceIntegerValues,typeof t.width<"u"?t.width:this.width,typeof t.scrollWidth<"u"?t.scrollWidth:this.scrollWidth,i?this.rawScrollLeft:this.scrollLeft,typeof t.height<"u"?t.height:this.height,typeof t.scrollHeight<"u"?t.scrollHeight:this.scrollHeight,i?this.rawScrollTop:this.scrollTop)}withScrollPosition(t){return new I(this._forceIntegerValues,this.width,this.scrollWidth,typeof t.scrollLeft<"u"?t.scrollLeft:this.rawScrollLeft,this.height,this.scrollHeight,typeof t.scrollTop<"u"?t.scrollTop:this.rawScrollTop)}createScrollEvent(t,i){const s=this.width!==t.width,g=this.scrollWidth!==t.scrollWidth,c=this.scrollLeft!==t.scrollLeft,l=this.height!==t.height,a=this.scrollHeight!==t.scrollHeight,r=this.scrollTop!==t.scrollTop;return{inSmoothScrolling:i,oldWidth:t.width,oldScrollWidth:t.scrollWidth,oldScrollLeft:t.scrollLeft,width:this.width,scrollWidth:this.scrollWidth,scrollLeft:this.scrollLeft,oldHeight:t.height,oldScrollHeight:t.scrollHeight,oldScrollTop:t.scrollTop,height:this.height,scrollHeight:this.scrollHeight,scrollTop:this.scrollTop,widthChanged:s,scrollWidthChanged:g,scrollLeftChanged:c,heightChanged:l,scrollHeightChanged:a,scrollTopChanged:r}}}e.ScrollState=I;class E extends k.Disposable{constructor(t){super(),this._scrollableBrand=void 0,this._onScroll=this._register(new d.Emitter),this.onScroll=this._onScroll.event,this._smoothScrollDuration=t.smoothScrollDuration,this._scheduleAtNextAnimationFrame=t.scheduleAtNextAnimationFrame,this._state=new I(t.forceIntegerValues,0,0,0,0,0,0),this._smoothScrolling=null}dispose(){this._smoothScrolling&&(this._smoothScrolling.dispose(),this._smoothScrolling=null),super.dispose()}setSmoothScrollDuration(t){this._smoothScrollDuration=t}validateScrollPosition(t){return this._state.withScrollPosition(t)}getScrollDimensions(){return this._state}setScrollDimensions(t,i){const s=this._state.withScrollDimensions(t,i);this._setState(s,!!this._smoothScrolling),this._smoothScrolling?.acceptScrollDimensions(this._state)}getFutureScrollPosition(){return this._smoothScrolling?this._smoothScrolling.to:this._state}getCurrentScrollPosition(){return this._state}setScrollPositionNow(t){const i=this._state.withScrollPosition(t);this._smoothScrolling&&(this._smoothScrolling.dispose(),this._smoothScrolling=null),this._setState(i,!1)}setScrollPositionSmooth(t,i){if(this._smoothScrollDuration===0)return this.setScrollPositionNow(t);if(this._smoothScrolling){t={scrollLeft:typeof t.scrollLeft>"u"?this._smoothScrolling.to.scrollLeft:t.scrollLeft,scrollTop:typeof t.scrollTop>"u"?this._smoothScrolling.to.scrollTop:t.scrollTop};const s=this._state.withScrollPosition(t);if(this._smoothScrolling.to.scrollLeft===s.scrollLeft&&this._smoothScrolling.to.scrollTop===s.scrollTop)return;let g;i?g=new b(this._smoothScrolling.from,s,this._smoothScrolling.startTime,this._smoothScrolling.duration):g=this._smoothScrolling.combine(this._state,s,this._smoothScrollDuration),this._smoothScrolling.dispose(),this._smoothScrolling=g}else{const s=this._state.withScrollPosition(t);this._smoothScrolling=b.start(this._state,s,this._smoothScrollDuration)}this._smoothScrolling.animationFrameDisposable=this._scheduleAtNextAnimationFrame(()=>{this._smoothScrolling&&(this._smoothScrolling.animationFrameDisposable=null,this._performSmoothScrolling())})}hasPendingScrollAnimation(){return!!this._smoothScrolling}_performSmoothScrolling(){if(!this._smoothScrolling)return;const t=this._smoothScrolling.tick(),i=this._state.withScrollPosition(t);if(this._setState(i,!0),!!this._smoothScrolling){if(t.isDone){this._smoothScrolling.dispose(),this._smoothScrolling=null;return}this._smoothScrolling.animationFrameDisposable=this._scheduleAtNextAnimationFrame(()=>{this._smoothScrolling&&(this._smoothScrolling.animationFrameDisposable=null,this._performSmoothScrolling())})}}_setState(t,i){const s=this._state;s.equals(t)||(this._state=t,this._onScroll.fire(this._state.createScrollEvent(s,i)))}}e.Scrollable=E;class y{constructor(t,i,s){this.scrollLeft=t,this.scrollTop=i,this.isDone=s}}e.SmoothScrollingUpdate=y;function m(o,t){const i=t-o;return function(s){return o+i*n(s)}}function _(o,t,i){return function(s){return s2.5*s){let c,l;return t=te.length?re:te[me]})}function m(Z){return Z.replace(/[<>"'&]/g,te=>{switch(te){case"<":return"<";case">":return">";case'"':return""";case"'":return"'";case"&":return"&"}return te})}function _(Z){return Z.replace(/[<>&]/g,function(te){switch(te){case"<":return"<";case">":return">";case"&":return"&";default:return te}})}function b(Z){return Z.replace(/[\\\{\}\*\+\?\|\^\$\.\[\]\(\)]/g,"\\$&")}function p(Z,te=" "){const re=n(Z,te);return o(re,te)}function n(Z,te){if(!Z||!te)return Z;const re=te.length;if(re===0||Z.length===0)return Z;let le=0;for(;Z.indexOf(te,le)===le;)le=le+re;return Z.substring(le)}function o(Z,te){if(!Z||!te)return Z;const re=te.length,le=Z.length;if(re===0||le===0)return Z;let me=le,Ce=-1;for(;Ce=Z.lastIndexOf(te,me-1),!(Ce===-1||Ce+re!==me);){if(Ce===0)return"";me=Ce}return Z.substring(0,me)}function t(Z){return Z.replace(/[\-\\\{\}\+\?\|\^\$\.\,\[\]\(\)\#\s]/g,"\\$&").replace(/[\*]/g,".*")}function i(Z){return Z.replace(/\*/g,"")}function s(Z,te,re={}){if(!Z)throw new Error("Cannot create regex from empty string");te||(Z=b(Z)),re.wholeWord&&(/\B/.test(Z.charAt(0))||(Z="\\b"+Z),/\B/.test(Z.charAt(Z.length-1))||(Z=Z+"\\b"));let le="";return re.global&&(le+="g"),re.matchCase||(le+="i"),re.multiline&&(le+="m"),re.unicode&&(le+="u"),new RegExp(Z,le)}function g(Z){return Z.source==="^"||Z.source==="^$"||Z.source==="$"||Z.source==="^\\s*$"?!1:!!(Z.exec("")&&Z.lastIndex===0)}function c(Z){return Z.split(/\r\n|\r|\n/)}function l(Z){const te=[],re=Z.split(/(\r\n|\r|\n)/);for(let le=0;le=0;re--){const le=Z.charCodeAt(re);if(le!==32&&le!==9)return re}return-1}function C(Z,te){return Zte?1:0}function f(Z,te,re=0,le=Z.length,me=0,Ce=te.length){for(;reMe)return 1}const ye=le-re,Le=Ce-me;return yeLe?1:0}function h(Z,te){return v(Z,te,0,Z.length,0,te.length)}function v(Z,te,re=0,le=Z.length,me=0,Ce=te.length){for(;re=128||Me>=128)return f(Z.toLowerCase(),te.toLowerCase(),re,le,me,Ce);S(Ee)&&(Ee-=32),S(Me)&&(Me-=32);const Ae=Ee-Me;if(Ae!==0)return Ae}const ye=le-re,Le=Ce-me;return yeLe?1:0}function w(Z){return Z>=48&&Z<=57}function S(Z){return Z>=97&&Z<=122}function L(Z){return Z>=65&&Z<=90}function D(Z,te){return Z.length===te.length&&v(Z,te)===0}function T(Z,te){const re=te.length;return te.length>Z.length?!1:v(Z,te,0,re)===0}function M(Z,te){const re=Math.min(Z.length,te.length);let le;for(le=0;le1){const le=Z.charCodeAt(te-2);if(P(le))return O(le,re)}return re}class W{get offset(){return this._offset}constructor(te,re=0){this._str=te,this._len=te.length,this._offset=re}setOffset(te){this._offset=te}prevCodePoint(){const te=x(this._str,this._offset);return this._offset-=te>=65536?2:1,te}nextCodePoint(){const te=F(this._str,this._len,this._offset);return this._offset+=te>=65536?2:1,te}eol(){return this._offset>=this._len}}e.CodePointIterator=W;class V{get offset(){return this._iterator.offset}constructor(te,re=0){this._iterator=new W(te,re)}nextGraphemeLength(){const te=ee.getInstance(),re=this._iterator,le=re.offset;let me=te.getGraphemeBreakType(re.nextCodePoint());for(;!re.eol();){const Ce=re.offset,ye=te.getGraphemeBreakType(re.nextCodePoint());if(ae(me,ye)){re.setOffset(Ce);break}me=ye}return re.offset-le}prevGraphemeLength(){const te=ee.getInstance(),re=this._iterator,le=re.offset;let me=te.getGraphemeBreakType(re.prevCodePoint());for(;re.offset>0;){const Ce=re.offset,ye=te.getGraphemeBreakType(re.prevCodePoint());if(ae(ye,me)){re.setOffset(Ce);break}me=ye}return le-re.offset}eol(){return this._iterator.eol()}}e.GraphemeIterator=V;function q(Z,te){return new V(Z,te).nextGraphemeLength()}function H(Z,te){return new V(Z,te).prevGraphemeLength()}function z(Z,te){te>0&&N(Z.charCodeAt(te))&&te--;const re=te+q(Z,te);return[re-H(Z,re),re]}let U;function j(){return/(?:[\u05BE\u05C0\u05C3\u05C6\u05D0-\u05F4\u0608\u060B\u060D\u061B-\u064A\u066D-\u066F\u0671-\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u0710\u0712-\u072F\u074D-\u07A5\u07B1-\u07EA\u07F4\u07F5\u07FA\u07FE-\u0815\u081A\u0824\u0828\u0830-\u0858\u085E-\u088E\u08A0-\u08C9\u200F\uFB1D\uFB1F-\uFB28\uFB2A-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFC\uFE70-\uFEFC]|\uD802[\uDC00-\uDD1B\uDD20-\uDE00\uDE10-\uDE35\uDE40-\uDEE4\uDEEB-\uDF35\uDF40-\uDFFF]|\uD803[\uDC00-\uDD23\uDE80-\uDEA9\uDEAD-\uDF45\uDF51-\uDF81\uDF86-\uDFF6]|\uD83A[\uDC00-\uDCCF\uDD00-\uDD43\uDD4B-\uDFFF]|\uD83B[\uDC00-\uDEBB])/}function Y(Z){return U||(U=j()),U.test(Z)}const G=/^[\t\n\r\x20-\x7E]*$/;function K(Z){return G.test(Z)}e.UNUSUAL_LINE_TERMINATORS=/[\u2028\u2029]/;function R(Z){return e.UNUSUAL_LINE_TERMINATORS.test(Z)}function J(Z){return Z>=11904&&Z<=55215||Z>=63744&&Z<=64255||Z>=65281&&Z<=65374}function ie(Z){return Z>=127462&&Z<=127487||Z===8986||Z===8987||Z===9200||Z===9203||Z>=9728&&Z<=10175||Z===11088||Z===11093||Z>=127744&&Z<=128591||Z>=128640&&Z<=128764||Z>=128992&&Z<=129008||Z>=129280&&Z<=129535||Z>=129648&&Z<=129782}e.UTF8_BOM_CHARACTER="\uFEFF";function ue(Z){return!!(Z&&Z.length>0&&Z.charCodeAt(0)===65279)}function he(Z,te=!1){return Z?(te&&(Z=Z.replace(/\\./g,"")),Z.toLowerCase()!==Z):!1}function pe(Z){return Z=Z%(2*26),Z<26?String.fromCharCode(97+Z):String.fromCharCode(65+Z-26)}function ae(Z,te){return Z===0?te!==5&&te!==7:Z===2&&te===3?!1:Z===4||Z===2||Z===3||te===4||te===2||te===3?!0:!(Z===8&&(te===8||te===9||te===11||te===12)||(Z===11||Z===9)&&(te===9||te===10)||(Z===12||Z===10)&&te===10||te===5||te===13||te===7||Z===1||Z===13&&te===14||Z===6&&te===6)}class ee{static{this._INSTANCE=null}static getInstance(){return ee._INSTANCE||(ee._INSTANCE=new ee),ee._INSTANCE}constructor(){this._data=de()}getGraphemeBreakType(te){if(te<32)return te===10?3:te===13?2:4;if(te<127)return 0;const re=this._data,le=re.length/3;let me=1;for(;me<=le;)if(tere[3*me+1])me=2*me+1;else return re[3*me+2];return 0}}function de(){return JSON.parse("[0,0,0,51229,51255,12,44061,44087,12,127462,127487,6,7083,7085,5,47645,47671,12,54813,54839,12,128678,128678,14,3270,3270,5,9919,9923,14,45853,45879,12,49437,49463,12,53021,53047,12,71216,71218,7,128398,128399,14,129360,129374,14,2519,2519,5,4448,4519,9,9742,9742,14,12336,12336,14,44957,44983,12,46749,46775,12,48541,48567,12,50333,50359,12,52125,52151,12,53917,53943,12,69888,69890,5,73018,73018,5,127990,127990,14,128558,128559,14,128759,128760,14,129653,129655,14,2027,2035,5,2891,2892,7,3761,3761,5,6683,6683,5,8293,8293,4,9825,9826,14,9999,9999,14,43452,43453,5,44509,44535,12,45405,45431,12,46301,46327,12,47197,47223,12,48093,48119,12,48989,49015,12,49885,49911,12,50781,50807,12,51677,51703,12,52573,52599,12,53469,53495,12,54365,54391,12,65279,65279,4,70471,70472,7,72145,72147,7,119173,119179,5,127799,127818,14,128240,128244,14,128512,128512,14,128652,128652,14,128721,128722,14,129292,129292,14,129445,129450,14,129734,129743,14,1476,1477,5,2366,2368,7,2750,2752,7,3076,3076,5,3415,3415,5,4141,4144,5,6109,6109,5,6964,6964,5,7394,7400,5,9197,9198,14,9770,9770,14,9877,9877,14,9968,9969,14,10084,10084,14,43052,43052,5,43713,43713,5,44285,44311,12,44733,44759,12,45181,45207,12,45629,45655,12,46077,46103,12,46525,46551,12,46973,46999,12,47421,47447,12,47869,47895,12,48317,48343,12,48765,48791,12,49213,49239,12,49661,49687,12,50109,50135,12,50557,50583,12,51005,51031,12,51453,51479,12,51901,51927,12,52349,52375,12,52797,52823,12,53245,53271,12,53693,53719,12,54141,54167,12,54589,54615,12,55037,55063,12,69506,69509,5,70191,70193,5,70841,70841,7,71463,71467,5,72330,72342,5,94031,94031,5,123628,123631,5,127763,127765,14,127941,127941,14,128043,128062,14,128302,128317,14,128465,128467,14,128539,128539,14,128640,128640,14,128662,128662,14,128703,128703,14,128745,128745,14,129004,129007,14,129329,129330,14,129402,129402,14,129483,129483,14,129686,129704,14,130048,131069,14,173,173,4,1757,1757,1,2200,2207,5,2434,2435,7,2631,2632,5,2817,2817,5,3008,3008,5,3201,3201,5,3387,3388,5,3542,3542,5,3902,3903,7,4190,4192,5,6002,6003,5,6439,6440,5,6765,6770,7,7019,7027,5,7154,7155,7,8205,8205,13,8505,8505,14,9654,9654,14,9757,9757,14,9792,9792,14,9852,9853,14,9890,9894,14,9937,9937,14,9981,9981,14,10035,10036,14,11035,11036,14,42654,42655,5,43346,43347,7,43587,43587,5,44006,44007,7,44173,44199,12,44397,44423,12,44621,44647,12,44845,44871,12,45069,45095,12,45293,45319,12,45517,45543,12,45741,45767,12,45965,45991,12,46189,46215,12,46413,46439,12,46637,46663,12,46861,46887,12,47085,47111,12,47309,47335,12,47533,47559,12,47757,47783,12,47981,48007,12,48205,48231,12,48429,48455,12,48653,48679,12,48877,48903,12,49101,49127,12,49325,49351,12,49549,49575,12,49773,49799,12,49997,50023,12,50221,50247,12,50445,50471,12,50669,50695,12,50893,50919,12,51117,51143,12,51341,51367,12,51565,51591,12,51789,51815,12,52013,52039,12,52237,52263,12,52461,52487,12,52685,52711,12,52909,52935,12,53133,53159,12,53357,53383,12,53581,53607,12,53805,53831,12,54029,54055,12,54253,54279,12,54477,54503,12,54701,54727,12,54925,54951,12,55149,55175,12,68101,68102,5,69762,69762,7,70067,70069,7,70371,70378,5,70720,70721,7,71087,71087,5,71341,71341,5,71995,71996,5,72249,72249,7,72850,72871,5,73109,73109,5,118576,118598,5,121505,121519,5,127245,127247,14,127568,127569,14,127777,127777,14,127872,127891,14,127956,127967,14,128015,128016,14,128110,128172,14,128259,128259,14,128367,128368,14,128424,128424,14,128488,128488,14,128530,128532,14,128550,128551,14,128566,128566,14,128647,128647,14,128656,128656,14,128667,128673,14,128691,128693,14,128715,128715,14,128728,128732,14,128752,128752,14,128765,128767,14,129096,129103,14,129311,129311,14,129344,129349,14,129394,129394,14,129413,129425,14,129466,129471,14,129511,129535,14,129664,129666,14,129719,129722,14,129760,129767,14,917536,917631,5,13,13,2,1160,1161,5,1564,1564,4,1807,1807,1,2085,2087,5,2307,2307,7,2382,2383,7,2497,2500,5,2563,2563,7,2677,2677,5,2763,2764,7,2879,2879,5,2914,2915,5,3021,3021,5,3142,3144,5,3263,3263,5,3285,3286,5,3398,3400,7,3530,3530,5,3633,3633,5,3864,3865,5,3974,3975,5,4155,4156,7,4229,4230,5,5909,5909,7,6078,6085,7,6277,6278,5,6451,6456,7,6744,6750,5,6846,6846,5,6972,6972,5,7074,7077,5,7146,7148,7,7222,7223,5,7416,7417,5,8234,8238,4,8417,8417,5,9000,9000,14,9203,9203,14,9730,9731,14,9748,9749,14,9762,9763,14,9776,9783,14,9800,9811,14,9831,9831,14,9872,9873,14,9882,9882,14,9900,9903,14,9929,9933,14,9941,9960,14,9974,9974,14,9989,9989,14,10006,10006,14,10062,10062,14,10160,10160,14,11647,11647,5,12953,12953,14,43019,43019,5,43232,43249,5,43443,43443,5,43567,43568,7,43696,43696,5,43765,43765,7,44013,44013,5,44117,44143,12,44229,44255,12,44341,44367,12,44453,44479,12,44565,44591,12,44677,44703,12,44789,44815,12,44901,44927,12,45013,45039,12,45125,45151,12,45237,45263,12,45349,45375,12,45461,45487,12,45573,45599,12,45685,45711,12,45797,45823,12,45909,45935,12,46021,46047,12,46133,46159,12,46245,46271,12,46357,46383,12,46469,46495,12,46581,46607,12,46693,46719,12,46805,46831,12,46917,46943,12,47029,47055,12,47141,47167,12,47253,47279,12,47365,47391,12,47477,47503,12,47589,47615,12,47701,47727,12,47813,47839,12,47925,47951,12,48037,48063,12,48149,48175,12,48261,48287,12,48373,48399,12,48485,48511,12,48597,48623,12,48709,48735,12,48821,48847,12,48933,48959,12,49045,49071,12,49157,49183,12,49269,49295,12,49381,49407,12,49493,49519,12,49605,49631,12,49717,49743,12,49829,49855,12,49941,49967,12,50053,50079,12,50165,50191,12,50277,50303,12,50389,50415,12,50501,50527,12,50613,50639,12,50725,50751,12,50837,50863,12,50949,50975,12,51061,51087,12,51173,51199,12,51285,51311,12,51397,51423,12,51509,51535,12,51621,51647,12,51733,51759,12,51845,51871,12,51957,51983,12,52069,52095,12,52181,52207,12,52293,52319,12,52405,52431,12,52517,52543,12,52629,52655,12,52741,52767,12,52853,52879,12,52965,52991,12,53077,53103,12,53189,53215,12,53301,53327,12,53413,53439,12,53525,53551,12,53637,53663,12,53749,53775,12,53861,53887,12,53973,53999,12,54085,54111,12,54197,54223,12,54309,54335,12,54421,54447,12,54533,54559,12,54645,54671,12,54757,54783,12,54869,54895,12,54981,55007,12,55093,55119,12,55243,55291,10,66045,66045,5,68325,68326,5,69688,69702,5,69817,69818,5,69957,69958,7,70089,70092,5,70198,70199,5,70462,70462,5,70502,70508,5,70750,70750,5,70846,70846,7,71100,71101,5,71230,71230,7,71351,71351,5,71737,71738,5,72000,72000,7,72160,72160,5,72273,72278,5,72752,72758,5,72882,72883,5,73031,73031,5,73461,73462,7,94192,94193,7,119149,119149,7,121403,121452,5,122915,122916,5,126980,126980,14,127358,127359,14,127535,127535,14,127759,127759,14,127771,127771,14,127792,127793,14,127825,127867,14,127897,127899,14,127945,127945,14,127985,127986,14,128000,128007,14,128021,128021,14,128066,128100,14,128184,128235,14,128249,128252,14,128266,128276,14,128335,128335,14,128379,128390,14,128407,128419,14,128444,128444,14,128481,128481,14,128499,128499,14,128526,128526,14,128536,128536,14,128543,128543,14,128556,128556,14,128564,128564,14,128577,128580,14,128643,128645,14,128649,128649,14,128654,128654,14,128660,128660,14,128664,128664,14,128675,128675,14,128686,128689,14,128695,128696,14,128705,128709,14,128717,128719,14,128725,128725,14,128736,128741,14,128747,128748,14,128755,128755,14,128762,128762,14,128981,128991,14,129009,129023,14,129160,129167,14,129296,129304,14,129320,129327,14,129340,129342,14,129356,129356,14,129388,129392,14,129399,129400,14,129404,129407,14,129432,129442,14,129454,129455,14,129473,129474,14,129485,129487,14,129648,129651,14,129659,129660,14,129671,129679,14,129709,129711,14,129728,129730,14,129751,129753,14,129776,129782,14,917505,917505,4,917760,917999,5,10,10,3,127,159,4,768,879,5,1471,1471,5,1536,1541,1,1648,1648,5,1767,1768,5,1840,1866,5,2070,2073,5,2137,2139,5,2274,2274,1,2363,2363,7,2377,2380,7,2402,2403,5,2494,2494,5,2507,2508,7,2558,2558,5,2622,2624,7,2641,2641,5,2691,2691,7,2759,2760,5,2786,2787,5,2876,2876,5,2881,2884,5,2901,2902,5,3006,3006,5,3014,3016,7,3072,3072,5,3134,3136,5,3157,3158,5,3260,3260,5,3266,3266,5,3274,3275,7,3328,3329,5,3391,3392,7,3405,3405,5,3457,3457,5,3536,3537,7,3551,3551,5,3636,3642,5,3764,3772,5,3895,3895,5,3967,3967,7,3993,4028,5,4146,4151,5,4182,4183,7,4226,4226,5,4253,4253,5,4957,4959,5,5940,5940,7,6070,6070,7,6087,6088,7,6158,6158,4,6432,6434,5,6448,6449,7,6679,6680,5,6742,6742,5,6754,6754,5,6783,6783,5,6912,6915,5,6966,6970,5,6978,6978,5,7042,7042,7,7080,7081,5,7143,7143,7,7150,7150,7,7212,7219,5,7380,7392,5,7412,7412,5,8203,8203,4,8232,8232,4,8265,8265,14,8400,8412,5,8421,8432,5,8617,8618,14,9167,9167,14,9200,9200,14,9410,9410,14,9723,9726,14,9733,9733,14,9745,9745,14,9752,9752,14,9760,9760,14,9766,9766,14,9774,9774,14,9786,9786,14,9794,9794,14,9823,9823,14,9828,9828,14,9833,9850,14,9855,9855,14,9875,9875,14,9880,9880,14,9885,9887,14,9896,9897,14,9906,9916,14,9926,9927,14,9935,9935,14,9939,9939,14,9962,9962,14,9972,9972,14,9978,9978,14,9986,9986,14,9997,9997,14,10002,10002,14,10017,10017,14,10055,10055,14,10071,10071,14,10133,10135,14,10548,10549,14,11093,11093,14,12330,12333,5,12441,12442,5,42608,42610,5,43010,43010,5,43045,43046,5,43188,43203,7,43302,43309,5,43392,43394,5,43446,43449,5,43493,43493,5,43571,43572,7,43597,43597,7,43703,43704,5,43756,43757,5,44003,44004,7,44009,44010,7,44033,44059,12,44089,44115,12,44145,44171,12,44201,44227,12,44257,44283,12,44313,44339,12,44369,44395,12,44425,44451,12,44481,44507,12,44537,44563,12,44593,44619,12,44649,44675,12,44705,44731,12,44761,44787,12,44817,44843,12,44873,44899,12,44929,44955,12,44985,45011,12,45041,45067,12,45097,45123,12,45153,45179,12,45209,45235,12,45265,45291,12,45321,45347,12,45377,45403,12,45433,45459,12,45489,45515,12,45545,45571,12,45601,45627,12,45657,45683,12,45713,45739,12,45769,45795,12,45825,45851,12,45881,45907,12,45937,45963,12,45993,46019,12,46049,46075,12,46105,46131,12,46161,46187,12,46217,46243,12,46273,46299,12,46329,46355,12,46385,46411,12,46441,46467,12,46497,46523,12,46553,46579,12,46609,46635,12,46665,46691,12,46721,46747,12,46777,46803,12,46833,46859,12,46889,46915,12,46945,46971,12,47001,47027,12,47057,47083,12,47113,47139,12,47169,47195,12,47225,47251,12,47281,47307,12,47337,47363,12,47393,47419,12,47449,47475,12,47505,47531,12,47561,47587,12,47617,47643,12,47673,47699,12,47729,47755,12,47785,47811,12,47841,47867,12,47897,47923,12,47953,47979,12,48009,48035,12,48065,48091,12,48121,48147,12,48177,48203,12,48233,48259,12,48289,48315,12,48345,48371,12,48401,48427,12,48457,48483,12,48513,48539,12,48569,48595,12,48625,48651,12,48681,48707,12,48737,48763,12,48793,48819,12,48849,48875,12,48905,48931,12,48961,48987,12,49017,49043,12,49073,49099,12,49129,49155,12,49185,49211,12,49241,49267,12,49297,49323,12,49353,49379,12,49409,49435,12,49465,49491,12,49521,49547,12,49577,49603,12,49633,49659,12,49689,49715,12,49745,49771,12,49801,49827,12,49857,49883,12,49913,49939,12,49969,49995,12,50025,50051,12,50081,50107,12,50137,50163,12,50193,50219,12,50249,50275,12,50305,50331,12,50361,50387,12,50417,50443,12,50473,50499,12,50529,50555,12,50585,50611,12,50641,50667,12,50697,50723,12,50753,50779,12,50809,50835,12,50865,50891,12,50921,50947,12,50977,51003,12,51033,51059,12,51089,51115,12,51145,51171,12,51201,51227,12,51257,51283,12,51313,51339,12,51369,51395,12,51425,51451,12,51481,51507,12,51537,51563,12,51593,51619,12,51649,51675,12,51705,51731,12,51761,51787,12,51817,51843,12,51873,51899,12,51929,51955,12,51985,52011,12,52041,52067,12,52097,52123,12,52153,52179,12,52209,52235,12,52265,52291,12,52321,52347,12,52377,52403,12,52433,52459,12,52489,52515,12,52545,52571,12,52601,52627,12,52657,52683,12,52713,52739,12,52769,52795,12,52825,52851,12,52881,52907,12,52937,52963,12,52993,53019,12,53049,53075,12,53105,53131,12,53161,53187,12,53217,53243,12,53273,53299,12,53329,53355,12,53385,53411,12,53441,53467,12,53497,53523,12,53553,53579,12,53609,53635,12,53665,53691,12,53721,53747,12,53777,53803,12,53833,53859,12,53889,53915,12,53945,53971,12,54001,54027,12,54057,54083,12,54113,54139,12,54169,54195,12,54225,54251,12,54281,54307,12,54337,54363,12,54393,54419,12,54449,54475,12,54505,54531,12,54561,54587,12,54617,54643,12,54673,54699,12,54729,54755,12,54785,54811,12,54841,54867,12,54897,54923,12,54953,54979,12,55009,55035,12,55065,55091,12,55121,55147,12,55177,55203,12,65024,65039,5,65520,65528,4,66422,66426,5,68152,68154,5,69291,69292,5,69633,69633,5,69747,69748,5,69811,69814,5,69826,69826,5,69932,69932,7,70016,70017,5,70079,70080,7,70095,70095,5,70196,70196,5,70367,70367,5,70402,70403,7,70464,70464,5,70487,70487,5,70709,70711,7,70725,70725,7,70833,70834,7,70843,70844,7,70849,70849,7,71090,71093,5,71103,71104,5,71227,71228,7,71339,71339,5,71344,71349,5,71458,71461,5,71727,71735,5,71985,71989,7,71998,71998,5,72002,72002,7,72154,72155,5,72193,72202,5,72251,72254,5,72281,72283,5,72344,72345,5,72766,72766,7,72874,72880,5,72885,72886,5,73023,73029,5,73104,73105,5,73111,73111,5,92912,92916,5,94095,94098,5,113824,113827,4,119142,119142,7,119155,119162,4,119362,119364,5,121476,121476,5,122888,122904,5,123184,123190,5,125252,125258,5,127183,127183,14,127340,127343,14,127377,127386,14,127491,127503,14,127548,127551,14,127744,127756,14,127761,127761,14,127769,127769,14,127773,127774,14,127780,127788,14,127796,127797,14,127820,127823,14,127869,127869,14,127894,127895,14,127902,127903,14,127943,127943,14,127947,127950,14,127972,127972,14,127988,127988,14,127992,127994,14,128009,128011,14,128019,128019,14,128023,128041,14,128064,128064,14,128102,128107,14,128174,128181,14,128238,128238,14,128246,128247,14,128254,128254,14,128264,128264,14,128278,128299,14,128329,128330,14,128348,128359,14,128371,128377,14,128392,128393,14,128401,128404,14,128421,128421,14,128433,128434,14,128450,128452,14,128476,128478,14,128483,128483,14,128495,128495,14,128506,128506,14,128519,128520,14,128528,128528,14,128534,128534,14,128538,128538,14,128540,128542,14,128544,128549,14,128552,128555,14,128557,128557,14,128560,128563,14,128565,128565,14,128567,128576,14,128581,128591,14,128641,128642,14,128646,128646,14,128648,128648,14,128650,128651,14,128653,128653,14,128655,128655,14,128657,128659,14,128661,128661,14,128663,128663,14,128665,128666,14,128674,128674,14,128676,128677,14,128679,128685,14,128690,128690,14,128694,128694,14,128697,128702,14,128704,128704,14,128710,128714,14,128716,128716,14,128720,128720,14,128723,128724,14,128726,128727,14,128733,128735,14,128742,128744,14,128746,128746,14,128749,128751,14,128753,128754,14,128756,128758,14,128761,128761,14,128763,128764,14,128884,128895,14,128992,129003,14,129008,129008,14,129036,129039,14,129114,129119,14,129198,129279,14,129293,129295,14,129305,129310,14,129312,129319,14,129328,129328,14,129331,129338,14,129343,129343,14,129351,129355,14,129357,129359,14,129375,129387,14,129393,129393,14,129395,129398,14,129401,129401,14,129403,129403,14,129408,129412,14,129426,129431,14,129443,129444,14,129451,129453,14,129456,129465,14,129472,129472,14,129475,129482,14,129484,129484,14,129488,129510,14,129536,129647,14,129652,129652,14,129656,129658,14,129661,129663,14,129667,129670,14,129680,129685,14,129705,129708,14,129712,129718,14,129723,129727,14,129731,129733,14,129744,129750,14,129754,129759,14,129768,129775,14,129783,129791,14,917504,917504,4,917506,917535,4,917632,917759,4,918000,921599,4,0,9,4,11,12,4,14,31,4,169,169,14,174,174,14,1155,1159,5,1425,1469,5,1473,1474,5,1479,1479,5,1552,1562,5,1611,1631,5,1750,1756,5,1759,1764,5,1770,1773,5,1809,1809,5,1958,1968,5,2045,2045,5,2075,2083,5,2089,2093,5,2192,2193,1,2250,2273,5,2275,2306,5,2362,2362,5,2364,2364,5,2369,2376,5,2381,2381,5,2385,2391,5,2433,2433,5,2492,2492,5,2495,2496,7,2503,2504,7,2509,2509,5,2530,2531,5,2561,2562,5,2620,2620,5,2625,2626,5,2635,2637,5,2672,2673,5,2689,2690,5,2748,2748,5,2753,2757,5,2761,2761,7,2765,2765,5,2810,2815,5,2818,2819,7,2878,2878,5,2880,2880,7,2887,2888,7,2893,2893,5,2903,2903,5,2946,2946,5,3007,3007,7,3009,3010,7,3018,3020,7,3031,3031,5,3073,3075,7,3132,3132,5,3137,3140,7,3146,3149,5,3170,3171,5,3202,3203,7,3262,3262,7,3264,3265,7,3267,3268,7,3271,3272,7,3276,3277,5,3298,3299,5,3330,3331,7,3390,3390,5,3393,3396,5,3402,3404,7,3406,3406,1,3426,3427,5,3458,3459,7,3535,3535,5,3538,3540,5,3544,3550,7,3570,3571,7,3635,3635,7,3655,3662,5,3763,3763,7,3784,3789,5,3893,3893,5,3897,3897,5,3953,3966,5,3968,3972,5,3981,3991,5,4038,4038,5,4145,4145,7,4153,4154,5,4157,4158,5,4184,4185,5,4209,4212,5,4228,4228,7,4237,4237,5,4352,4447,8,4520,4607,10,5906,5908,5,5938,5939,5,5970,5971,5,6068,6069,5,6071,6077,5,6086,6086,5,6089,6099,5,6155,6157,5,6159,6159,5,6313,6313,5,6435,6438,7,6441,6443,7,6450,6450,5,6457,6459,5,6681,6682,7,6741,6741,7,6743,6743,7,6752,6752,5,6757,6764,5,6771,6780,5,6832,6845,5,6847,6862,5,6916,6916,7,6965,6965,5,6971,6971,7,6973,6977,7,6979,6980,7,7040,7041,5,7073,7073,7,7078,7079,7,7082,7082,7,7142,7142,5,7144,7145,5,7149,7149,5,7151,7153,5,7204,7211,7,7220,7221,7,7376,7378,5,7393,7393,7,7405,7405,5,7415,7415,7,7616,7679,5,8204,8204,5,8206,8207,4,8233,8233,4,8252,8252,14,8288,8292,4,8294,8303,4,8413,8416,5,8418,8420,5,8482,8482,14,8596,8601,14,8986,8987,14,9096,9096,14,9193,9196,14,9199,9199,14,9201,9202,14,9208,9210,14,9642,9643,14,9664,9664,14,9728,9729,14,9732,9732,14,9735,9741,14,9743,9744,14,9746,9746,14,9750,9751,14,9753,9756,14,9758,9759,14,9761,9761,14,9764,9765,14,9767,9769,14,9771,9773,14,9775,9775,14,9784,9785,14,9787,9791,14,9793,9793,14,9795,9799,14,9812,9822,14,9824,9824,14,9827,9827,14,9829,9830,14,9832,9832,14,9851,9851,14,9854,9854,14,9856,9861,14,9874,9874,14,9876,9876,14,9878,9879,14,9881,9881,14,9883,9884,14,9888,9889,14,9895,9895,14,9898,9899,14,9904,9905,14,9917,9918,14,9924,9925,14,9928,9928,14,9934,9934,14,9936,9936,14,9938,9938,14,9940,9940,14,9961,9961,14,9963,9967,14,9970,9971,14,9973,9973,14,9975,9977,14,9979,9980,14,9982,9985,14,9987,9988,14,9992,9996,14,9998,9998,14,10000,10001,14,10004,10004,14,10013,10013,14,10024,10024,14,10052,10052,14,10060,10060,14,10067,10069,14,10083,10083,14,10085,10087,14,10145,10145,14,10175,10175,14,11013,11015,14,11088,11088,14,11503,11505,5,11744,11775,5,12334,12335,5,12349,12349,14,12951,12951,14,42607,42607,5,42612,42621,5,42736,42737,5,43014,43014,5,43043,43044,7,43047,43047,7,43136,43137,7,43204,43205,5,43263,43263,5,43335,43345,5,43360,43388,8,43395,43395,7,43444,43445,7,43450,43451,7,43454,43456,7,43561,43566,5,43569,43570,5,43573,43574,5,43596,43596,5,43644,43644,5,43698,43700,5,43710,43711,5,43755,43755,7,43758,43759,7,43766,43766,5,44005,44005,5,44008,44008,5,44012,44012,7,44032,44032,11,44060,44060,11,44088,44088,11,44116,44116,11,44144,44144,11,44172,44172,11,44200,44200,11,44228,44228,11,44256,44256,11,44284,44284,11,44312,44312,11,44340,44340,11,44368,44368,11,44396,44396,11,44424,44424,11,44452,44452,11,44480,44480,11,44508,44508,11,44536,44536,11,44564,44564,11,44592,44592,11,44620,44620,11,44648,44648,11,44676,44676,11,44704,44704,11,44732,44732,11,44760,44760,11,44788,44788,11,44816,44816,11,44844,44844,11,44872,44872,11,44900,44900,11,44928,44928,11,44956,44956,11,44984,44984,11,45012,45012,11,45040,45040,11,45068,45068,11,45096,45096,11,45124,45124,11,45152,45152,11,45180,45180,11,45208,45208,11,45236,45236,11,45264,45264,11,45292,45292,11,45320,45320,11,45348,45348,11,45376,45376,11,45404,45404,11,45432,45432,11,45460,45460,11,45488,45488,11,45516,45516,11,45544,45544,11,45572,45572,11,45600,45600,11,45628,45628,11,45656,45656,11,45684,45684,11,45712,45712,11,45740,45740,11,45768,45768,11,45796,45796,11,45824,45824,11,45852,45852,11,45880,45880,11,45908,45908,11,45936,45936,11,45964,45964,11,45992,45992,11,46020,46020,11,46048,46048,11,46076,46076,11,46104,46104,11,46132,46132,11,46160,46160,11,46188,46188,11,46216,46216,11,46244,46244,11,46272,46272,11,46300,46300,11,46328,46328,11,46356,46356,11,46384,46384,11,46412,46412,11,46440,46440,11,46468,46468,11,46496,46496,11,46524,46524,11,46552,46552,11,46580,46580,11,46608,46608,11,46636,46636,11,46664,46664,11,46692,46692,11,46720,46720,11,46748,46748,11,46776,46776,11,46804,46804,11,46832,46832,11,46860,46860,11,46888,46888,11,46916,46916,11,46944,46944,11,46972,46972,11,47000,47000,11,47028,47028,11,47056,47056,11,47084,47084,11,47112,47112,11,47140,47140,11,47168,47168,11,47196,47196,11,47224,47224,11,47252,47252,11,47280,47280,11,47308,47308,11,47336,47336,11,47364,47364,11,47392,47392,11,47420,47420,11,47448,47448,11,47476,47476,11,47504,47504,11,47532,47532,11,47560,47560,11,47588,47588,11,47616,47616,11,47644,47644,11,47672,47672,11,47700,47700,11,47728,47728,11,47756,47756,11,47784,47784,11,47812,47812,11,47840,47840,11,47868,47868,11,47896,47896,11,47924,47924,11,47952,47952,11,47980,47980,11,48008,48008,11,48036,48036,11,48064,48064,11,48092,48092,11,48120,48120,11,48148,48148,11,48176,48176,11,48204,48204,11,48232,48232,11,48260,48260,11,48288,48288,11,48316,48316,11,48344,48344,11,48372,48372,11,48400,48400,11,48428,48428,11,48456,48456,11,48484,48484,11,48512,48512,11,48540,48540,11,48568,48568,11,48596,48596,11,48624,48624,11,48652,48652,11,48680,48680,11,48708,48708,11,48736,48736,11,48764,48764,11,48792,48792,11,48820,48820,11,48848,48848,11,48876,48876,11,48904,48904,11,48932,48932,11,48960,48960,11,48988,48988,11,49016,49016,11,49044,49044,11,49072,49072,11,49100,49100,11,49128,49128,11,49156,49156,11,49184,49184,11,49212,49212,11,49240,49240,11,49268,49268,11,49296,49296,11,49324,49324,11,49352,49352,11,49380,49380,11,49408,49408,11,49436,49436,11,49464,49464,11,49492,49492,11,49520,49520,11,49548,49548,11,49576,49576,11,49604,49604,11,49632,49632,11,49660,49660,11,49688,49688,11,49716,49716,11,49744,49744,11,49772,49772,11,49800,49800,11,49828,49828,11,49856,49856,11,49884,49884,11,49912,49912,11,49940,49940,11,49968,49968,11,49996,49996,11,50024,50024,11,50052,50052,11,50080,50080,11,50108,50108,11,50136,50136,11,50164,50164,11,50192,50192,11,50220,50220,11,50248,50248,11,50276,50276,11,50304,50304,11,50332,50332,11,50360,50360,11,50388,50388,11,50416,50416,11,50444,50444,11,50472,50472,11,50500,50500,11,50528,50528,11,50556,50556,11,50584,50584,11,50612,50612,11,50640,50640,11,50668,50668,11,50696,50696,11,50724,50724,11,50752,50752,11,50780,50780,11,50808,50808,11,50836,50836,11,50864,50864,11,50892,50892,11,50920,50920,11,50948,50948,11,50976,50976,11,51004,51004,11,51032,51032,11,51060,51060,11,51088,51088,11,51116,51116,11,51144,51144,11,51172,51172,11,51200,51200,11,51228,51228,11,51256,51256,11,51284,51284,11,51312,51312,11,51340,51340,11,51368,51368,11,51396,51396,11,51424,51424,11,51452,51452,11,51480,51480,11,51508,51508,11,51536,51536,11,51564,51564,11,51592,51592,11,51620,51620,11,51648,51648,11,51676,51676,11,51704,51704,11,51732,51732,11,51760,51760,11,51788,51788,11,51816,51816,11,51844,51844,11,51872,51872,11,51900,51900,11,51928,51928,11,51956,51956,11,51984,51984,11,52012,52012,11,52040,52040,11,52068,52068,11,52096,52096,11,52124,52124,11,52152,52152,11,52180,52180,11,52208,52208,11,52236,52236,11,52264,52264,11,52292,52292,11,52320,52320,11,52348,52348,11,52376,52376,11,52404,52404,11,52432,52432,11,52460,52460,11,52488,52488,11,52516,52516,11,52544,52544,11,52572,52572,11,52600,52600,11,52628,52628,11,52656,52656,11,52684,52684,11,52712,52712,11,52740,52740,11,52768,52768,11,52796,52796,11,52824,52824,11,52852,52852,11,52880,52880,11,52908,52908,11,52936,52936,11,52964,52964,11,52992,52992,11,53020,53020,11,53048,53048,11,53076,53076,11,53104,53104,11,53132,53132,11,53160,53160,11,53188,53188,11,53216,53216,11,53244,53244,11,53272,53272,11,53300,53300,11,53328,53328,11,53356,53356,11,53384,53384,11,53412,53412,11,53440,53440,11,53468,53468,11,53496,53496,11,53524,53524,11,53552,53552,11,53580,53580,11,53608,53608,11,53636,53636,11,53664,53664,11,53692,53692,11,53720,53720,11,53748,53748,11,53776,53776,11,53804,53804,11,53832,53832,11,53860,53860,11,53888,53888,11,53916,53916,11,53944,53944,11,53972,53972,11,54000,54000,11,54028,54028,11,54056,54056,11,54084,54084,11,54112,54112,11,54140,54140,11,54168,54168,11,54196,54196,11,54224,54224,11,54252,54252,11,54280,54280,11,54308,54308,11,54336,54336,11,54364,54364,11,54392,54392,11,54420,54420,11,54448,54448,11,54476,54476,11,54504,54504,11,54532,54532,11,54560,54560,11,54588,54588,11,54616,54616,11,54644,54644,11,54672,54672,11,54700,54700,11,54728,54728,11,54756,54756,11,54784,54784,11,54812,54812,11,54840,54840,11,54868,54868,11,54896,54896,11,54924,54924,11,54952,54952,11,54980,54980,11,55008,55008,11,55036,55036,11,55064,55064,11,55092,55092,11,55120,55120,11,55148,55148,11,55176,55176,11,55216,55238,9,64286,64286,5,65056,65071,5,65438,65439,5,65529,65531,4,66272,66272,5,68097,68099,5,68108,68111,5,68159,68159,5,68900,68903,5,69446,69456,5,69632,69632,7,69634,69634,7,69744,69744,5,69759,69761,5,69808,69810,7,69815,69816,7,69821,69821,1,69837,69837,1,69927,69931,5,69933,69940,5,70003,70003,5,70018,70018,7,70070,70078,5,70082,70083,1,70094,70094,7,70188,70190,7,70194,70195,7,70197,70197,7,70206,70206,5,70368,70370,7,70400,70401,5,70459,70460,5,70463,70463,7,70465,70468,7,70475,70477,7,70498,70499,7,70512,70516,5,70712,70719,5,70722,70724,5,70726,70726,5,70832,70832,5,70835,70840,5,70842,70842,5,70845,70845,5,70847,70848,5,70850,70851,5,71088,71089,7,71096,71099,7,71102,71102,7,71132,71133,5,71219,71226,5,71229,71229,5,71231,71232,5,71340,71340,7,71342,71343,7,71350,71350,7,71453,71455,5,71462,71462,7,71724,71726,7,71736,71736,7,71984,71984,5,71991,71992,7,71997,71997,7,71999,71999,1,72001,72001,1,72003,72003,5,72148,72151,5,72156,72159,7,72164,72164,7,72243,72248,5,72250,72250,1,72263,72263,5,72279,72280,7,72324,72329,1,72343,72343,7,72751,72751,7,72760,72765,5,72767,72767,5,72873,72873,7,72881,72881,7,72884,72884,7,73009,73014,5,73020,73021,5,73030,73030,1,73098,73102,7,73107,73108,7,73110,73110,7,73459,73460,5,78896,78904,4,92976,92982,5,94033,94087,7,94180,94180,5,113821,113822,5,118528,118573,5,119141,119141,5,119143,119145,5,119150,119154,5,119163,119170,5,119210,119213,5,121344,121398,5,121461,121461,5,121499,121503,5,122880,122886,5,122907,122913,5,122918,122922,5,123566,123566,5,125136,125142,5,126976,126979,14,126981,127182,14,127184,127231,14,127279,127279,14,127344,127345,14,127374,127374,14,127405,127461,14,127489,127490,14,127514,127514,14,127538,127546,14,127561,127567,14,127570,127743,14,127757,127758,14,127760,127760,14,127762,127762,14,127766,127768,14,127770,127770,14,127772,127772,14,127775,127776,14,127778,127779,14,127789,127791,14,127794,127795,14,127798,127798,14,127819,127819,14,127824,127824,14,127868,127868,14,127870,127871,14,127892,127893,14,127896,127896,14,127900,127901,14,127904,127940,14,127942,127942,14,127944,127944,14,127946,127946,14,127951,127955,14,127968,127971,14,127973,127984,14,127987,127987,14,127989,127989,14,127991,127991,14,127995,127999,5,128008,128008,14,128012,128014,14,128017,128018,14,128020,128020,14,128022,128022,14,128042,128042,14,128063,128063,14,128065,128065,14,128101,128101,14,128108,128109,14,128173,128173,14,128182,128183,14,128236,128237,14,128239,128239,14,128245,128245,14,128248,128248,14,128253,128253,14,128255,128258,14,128260,128263,14,128265,128265,14,128277,128277,14,128300,128301,14,128326,128328,14,128331,128334,14,128336,128347,14,128360,128366,14,128369,128370,14,128378,128378,14,128391,128391,14,128394,128397,14,128400,128400,14,128405,128406,14,128420,128420,14,128422,128423,14,128425,128432,14,128435,128443,14,128445,128449,14,128453,128464,14,128468,128475,14,128479,128480,14,128482,128482,14,128484,128487,14,128489,128494,14,128496,128498,14,128500,128505,14,128507,128511,14,128513,128518,14,128521,128525,14,128527,128527,14,128529,128529,14,128533,128533,14,128535,128535,14,128537,128537,14]")}function ge(Z,te){if(Z===0)return 0;const re=X(Z,te);if(re!==void 0)return re;const le=new W(te,Z);return le.prevCodePoint(),le.offset}function X(Z,te){const re=new W(te,Z);let le=re.prevCodePoint();for(;B(le)||le===65039||le===8419;){if(re.offset===0)return;le=re.prevCodePoint()}if(!ie(le))return;let me=re.offset;return me>0&&re.prevCodePoint()===8205&&(me=re.offset),me}function B(Z){return 127995<=Z&&Z<=127999}e.noBreakWhitespace="\xA0";class ${static{this.ambiguousCharacterData=new k.Lazy(()=>JSON.parse('{"_common":[8232,32,8233,32,5760,32,8192,32,8193,32,8194,32,8195,32,8196,32,8197,32,8198,32,8200,32,8201,32,8202,32,8287,32,8199,32,8239,32,2042,95,65101,95,65102,95,65103,95,8208,45,8209,45,8210,45,65112,45,1748,45,8259,45,727,45,8722,45,10134,45,11450,45,1549,44,1643,44,8218,44,184,44,42233,44,894,59,2307,58,2691,58,1417,58,1795,58,1796,58,5868,58,65072,58,6147,58,6153,58,8282,58,1475,58,760,58,42889,58,8758,58,720,58,42237,58,451,33,11601,33,660,63,577,63,2429,63,5038,63,42731,63,119149,46,8228,46,1793,46,1794,46,42510,46,68176,46,1632,46,1776,46,42232,46,1373,96,65287,96,8219,96,8242,96,1370,96,1523,96,8175,96,65344,96,900,96,8189,96,8125,96,8127,96,8190,96,697,96,884,96,712,96,714,96,715,96,756,96,699,96,701,96,700,96,702,96,42892,96,1497,96,2036,96,2037,96,5194,96,5836,96,94033,96,94034,96,65339,91,10088,40,10098,40,12308,40,64830,40,65341,93,10089,41,10099,41,12309,41,64831,41,10100,123,119060,123,10101,125,65342,94,8270,42,1645,42,8727,42,66335,42,5941,47,8257,47,8725,47,8260,47,9585,47,10187,47,10744,47,119354,47,12755,47,12339,47,11462,47,20031,47,12035,47,65340,92,65128,92,8726,92,10189,92,10741,92,10745,92,119311,92,119355,92,12756,92,20022,92,12034,92,42872,38,708,94,710,94,5869,43,10133,43,66203,43,8249,60,10094,60,706,60,119350,60,5176,60,5810,60,5120,61,11840,61,12448,61,42239,61,8250,62,10095,62,707,62,119351,62,5171,62,94015,62,8275,126,732,126,8128,126,8764,126,65372,124,65293,45,120784,50,120794,50,120804,50,120814,50,120824,50,130034,50,42842,50,423,50,1000,50,42564,50,5311,50,42735,50,119302,51,120785,51,120795,51,120805,51,120815,51,120825,51,130035,51,42923,51,540,51,439,51,42858,51,11468,51,1248,51,94011,51,71882,51,120786,52,120796,52,120806,52,120816,52,120826,52,130036,52,5070,52,71855,52,120787,53,120797,53,120807,53,120817,53,120827,53,130037,53,444,53,71867,53,120788,54,120798,54,120808,54,120818,54,120828,54,130038,54,11474,54,5102,54,71893,54,119314,55,120789,55,120799,55,120809,55,120819,55,120829,55,130039,55,66770,55,71878,55,2819,56,2538,56,2666,56,125131,56,120790,56,120800,56,120810,56,120820,56,120830,56,130040,56,547,56,546,56,66330,56,2663,57,2920,57,2541,57,3437,57,120791,57,120801,57,120811,57,120821,57,120831,57,130041,57,42862,57,11466,57,71884,57,71852,57,71894,57,9082,97,65345,97,119834,97,119886,97,119938,97,119990,97,120042,97,120094,97,120146,97,120198,97,120250,97,120302,97,120354,97,120406,97,120458,97,593,97,945,97,120514,97,120572,97,120630,97,120688,97,120746,97,65313,65,119808,65,119860,65,119912,65,119964,65,120016,65,120068,65,120120,65,120172,65,120224,65,120276,65,120328,65,120380,65,120432,65,913,65,120488,65,120546,65,120604,65,120662,65,120720,65,5034,65,5573,65,42222,65,94016,65,66208,65,119835,98,119887,98,119939,98,119991,98,120043,98,120095,98,120147,98,120199,98,120251,98,120303,98,120355,98,120407,98,120459,98,388,98,5071,98,5234,98,5551,98,65314,66,8492,66,119809,66,119861,66,119913,66,120017,66,120069,66,120121,66,120173,66,120225,66,120277,66,120329,66,120381,66,120433,66,42932,66,914,66,120489,66,120547,66,120605,66,120663,66,120721,66,5108,66,5623,66,42192,66,66178,66,66209,66,66305,66,65347,99,8573,99,119836,99,119888,99,119940,99,119992,99,120044,99,120096,99,120148,99,120200,99,120252,99,120304,99,120356,99,120408,99,120460,99,7428,99,1010,99,11429,99,43951,99,66621,99,128844,67,71922,67,71913,67,65315,67,8557,67,8450,67,8493,67,119810,67,119862,67,119914,67,119966,67,120018,67,120174,67,120226,67,120278,67,120330,67,120382,67,120434,67,1017,67,11428,67,5087,67,42202,67,66210,67,66306,67,66581,67,66844,67,8574,100,8518,100,119837,100,119889,100,119941,100,119993,100,120045,100,120097,100,120149,100,120201,100,120253,100,120305,100,120357,100,120409,100,120461,100,1281,100,5095,100,5231,100,42194,100,8558,68,8517,68,119811,68,119863,68,119915,68,119967,68,120019,68,120071,68,120123,68,120175,68,120227,68,120279,68,120331,68,120383,68,120435,68,5024,68,5598,68,5610,68,42195,68,8494,101,65349,101,8495,101,8519,101,119838,101,119890,101,119942,101,120046,101,120098,101,120150,101,120202,101,120254,101,120306,101,120358,101,120410,101,120462,101,43826,101,1213,101,8959,69,65317,69,8496,69,119812,69,119864,69,119916,69,120020,69,120072,69,120124,69,120176,69,120228,69,120280,69,120332,69,120384,69,120436,69,917,69,120492,69,120550,69,120608,69,120666,69,120724,69,11577,69,5036,69,42224,69,71846,69,71854,69,66182,69,119839,102,119891,102,119943,102,119995,102,120047,102,120099,102,120151,102,120203,102,120255,102,120307,102,120359,102,120411,102,120463,102,43829,102,42905,102,383,102,7837,102,1412,102,119315,70,8497,70,119813,70,119865,70,119917,70,120021,70,120073,70,120125,70,120177,70,120229,70,120281,70,120333,70,120385,70,120437,70,42904,70,988,70,120778,70,5556,70,42205,70,71874,70,71842,70,66183,70,66213,70,66853,70,65351,103,8458,103,119840,103,119892,103,119944,103,120048,103,120100,103,120152,103,120204,103,120256,103,120308,103,120360,103,120412,103,120464,103,609,103,7555,103,397,103,1409,103,119814,71,119866,71,119918,71,119970,71,120022,71,120074,71,120126,71,120178,71,120230,71,120282,71,120334,71,120386,71,120438,71,1292,71,5056,71,5107,71,42198,71,65352,104,8462,104,119841,104,119945,104,119997,104,120049,104,120101,104,120153,104,120205,104,120257,104,120309,104,120361,104,120413,104,120465,104,1211,104,1392,104,5058,104,65320,72,8459,72,8460,72,8461,72,119815,72,119867,72,119919,72,120023,72,120179,72,120231,72,120283,72,120335,72,120387,72,120439,72,919,72,120494,72,120552,72,120610,72,120668,72,120726,72,11406,72,5051,72,5500,72,42215,72,66255,72,731,105,9075,105,65353,105,8560,105,8505,105,8520,105,119842,105,119894,105,119946,105,119998,105,120050,105,120102,105,120154,105,120206,105,120258,105,120310,105,120362,105,120414,105,120466,105,120484,105,618,105,617,105,953,105,8126,105,890,105,120522,105,120580,105,120638,105,120696,105,120754,105,1110,105,42567,105,1231,105,43893,105,5029,105,71875,105,65354,106,8521,106,119843,106,119895,106,119947,106,119999,106,120051,106,120103,106,120155,106,120207,106,120259,106,120311,106,120363,106,120415,106,120467,106,1011,106,1112,106,65322,74,119817,74,119869,74,119921,74,119973,74,120025,74,120077,74,120129,74,120181,74,120233,74,120285,74,120337,74,120389,74,120441,74,42930,74,895,74,1032,74,5035,74,5261,74,42201,74,119844,107,119896,107,119948,107,120000,107,120052,107,120104,107,120156,107,120208,107,120260,107,120312,107,120364,107,120416,107,120468,107,8490,75,65323,75,119818,75,119870,75,119922,75,119974,75,120026,75,120078,75,120130,75,120182,75,120234,75,120286,75,120338,75,120390,75,120442,75,922,75,120497,75,120555,75,120613,75,120671,75,120729,75,11412,75,5094,75,5845,75,42199,75,66840,75,1472,108,8739,73,9213,73,65512,73,1633,108,1777,73,66336,108,125127,108,120783,73,120793,73,120803,73,120813,73,120823,73,130033,73,65321,73,8544,73,8464,73,8465,73,119816,73,119868,73,119920,73,120024,73,120128,73,120180,73,120232,73,120284,73,120336,73,120388,73,120440,73,65356,108,8572,73,8467,108,119845,108,119897,108,119949,108,120001,108,120053,108,120105,73,120157,73,120209,73,120261,73,120313,73,120365,73,120417,73,120469,73,448,73,120496,73,120554,73,120612,73,120670,73,120728,73,11410,73,1030,73,1216,73,1493,108,1503,108,1575,108,126464,108,126592,108,65166,108,65165,108,1994,108,11599,73,5825,73,42226,73,93992,73,66186,124,66313,124,119338,76,8556,76,8466,76,119819,76,119871,76,119923,76,120027,76,120079,76,120131,76,120183,76,120235,76,120287,76,120339,76,120391,76,120443,76,11472,76,5086,76,5290,76,42209,76,93974,76,71843,76,71858,76,66587,76,66854,76,65325,77,8559,77,8499,77,119820,77,119872,77,119924,77,120028,77,120080,77,120132,77,120184,77,120236,77,120288,77,120340,77,120392,77,120444,77,924,77,120499,77,120557,77,120615,77,120673,77,120731,77,1018,77,11416,77,5047,77,5616,77,5846,77,42207,77,66224,77,66321,77,119847,110,119899,110,119951,110,120003,110,120055,110,120107,110,120159,110,120211,110,120263,110,120315,110,120367,110,120419,110,120471,110,1400,110,1404,110,65326,78,8469,78,119821,78,119873,78,119925,78,119977,78,120029,78,120081,78,120185,78,120237,78,120289,78,120341,78,120393,78,120445,78,925,78,120500,78,120558,78,120616,78,120674,78,120732,78,11418,78,42208,78,66835,78,3074,111,3202,111,3330,111,3458,111,2406,111,2662,111,2790,111,3046,111,3174,111,3302,111,3430,111,3664,111,3792,111,4160,111,1637,111,1781,111,65359,111,8500,111,119848,111,119900,111,119952,111,120056,111,120108,111,120160,111,120212,111,120264,111,120316,111,120368,111,120420,111,120472,111,7439,111,7441,111,43837,111,959,111,120528,111,120586,111,120644,111,120702,111,120760,111,963,111,120532,111,120590,111,120648,111,120706,111,120764,111,11423,111,4351,111,1413,111,1505,111,1607,111,126500,111,126564,111,126596,111,65259,111,65260,111,65258,111,65257,111,1726,111,64428,111,64429,111,64427,111,64426,111,1729,111,64424,111,64425,111,64423,111,64422,111,1749,111,3360,111,4125,111,66794,111,71880,111,71895,111,66604,111,1984,79,2534,79,2918,79,12295,79,70864,79,71904,79,120782,79,120792,79,120802,79,120812,79,120822,79,130032,79,65327,79,119822,79,119874,79,119926,79,119978,79,120030,79,120082,79,120134,79,120186,79,120238,79,120290,79,120342,79,120394,79,120446,79,927,79,120502,79,120560,79,120618,79,120676,79,120734,79,11422,79,1365,79,11604,79,4816,79,2848,79,66754,79,42227,79,71861,79,66194,79,66219,79,66564,79,66838,79,9076,112,65360,112,119849,112,119901,112,119953,112,120005,112,120057,112,120109,112,120161,112,120213,112,120265,112,120317,112,120369,112,120421,112,120473,112,961,112,120530,112,120544,112,120588,112,120602,112,120646,112,120660,112,120704,112,120718,112,120762,112,120776,112,11427,112,65328,80,8473,80,119823,80,119875,80,119927,80,119979,80,120031,80,120083,80,120187,80,120239,80,120291,80,120343,80,120395,80,120447,80,929,80,120504,80,120562,80,120620,80,120678,80,120736,80,11426,80,5090,80,5229,80,42193,80,66197,80,119850,113,119902,113,119954,113,120006,113,120058,113,120110,113,120162,113,120214,113,120266,113,120318,113,120370,113,120422,113,120474,113,1307,113,1379,113,1382,113,8474,81,119824,81,119876,81,119928,81,119980,81,120032,81,120084,81,120188,81,120240,81,120292,81,120344,81,120396,81,120448,81,11605,81,119851,114,119903,114,119955,114,120007,114,120059,114,120111,114,120163,114,120215,114,120267,114,120319,114,120371,114,120423,114,120475,114,43847,114,43848,114,7462,114,11397,114,43905,114,119318,82,8475,82,8476,82,8477,82,119825,82,119877,82,119929,82,120033,82,120189,82,120241,82,120293,82,120345,82,120397,82,120449,82,422,82,5025,82,5074,82,66740,82,5511,82,42211,82,94005,82,65363,115,119852,115,119904,115,119956,115,120008,115,120060,115,120112,115,120164,115,120216,115,120268,115,120320,115,120372,115,120424,115,120476,115,42801,115,445,115,1109,115,43946,115,71873,115,66632,115,65331,83,119826,83,119878,83,119930,83,119982,83,120034,83,120086,83,120138,83,120190,83,120242,83,120294,83,120346,83,120398,83,120450,83,1029,83,1359,83,5077,83,5082,83,42210,83,94010,83,66198,83,66592,83,119853,116,119905,116,119957,116,120009,116,120061,116,120113,116,120165,116,120217,116,120269,116,120321,116,120373,116,120425,116,120477,116,8868,84,10201,84,128872,84,65332,84,119827,84,119879,84,119931,84,119983,84,120035,84,120087,84,120139,84,120191,84,120243,84,120295,84,120347,84,120399,84,120451,84,932,84,120507,84,120565,84,120623,84,120681,84,120739,84,11430,84,5026,84,42196,84,93962,84,71868,84,66199,84,66225,84,66325,84,119854,117,119906,117,119958,117,120010,117,120062,117,120114,117,120166,117,120218,117,120270,117,120322,117,120374,117,120426,117,120478,117,42911,117,7452,117,43854,117,43858,117,651,117,965,117,120534,117,120592,117,120650,117,120708,117,120766,117,1405,117,66806,117,71896,117,8746,85,8899,85,119828,85,119880,85,119932,85,119984,85,120036,85,120088,85,120140,85,120192,85,120244,85,120296,85,120348,85,120400,85,120452,85,1357,85,4608,85,66766,85,5196,85,42228,85,94018,85,71864,85,8744,118,8897,118,65366,118,8564,118,119855,118,119907,118,119959,118,120011,118,120063,118,120115,118,120167,118,120219,118,120271,118,120323,118,120375,118,120427,118,120479,118,7456,118,957,118,120526,118,120584,118,120642,118,120700,118,120758,118,1141,118,1496,118,71430,118,43945,118,71872,118,119309,86,1639,86,1783,86,8548,86,119829,86,119881,86,119933,86,119985,86,120037,86,120089,86,120141,86,120193,86,120245,86,120297,86,120349,86,120401,86,120453,86,1140,86,11576,86,5081,86,5167,86,42719,86,42214,86,93960,86,71840,86,66845,86,623,119,119856,119,119908,119,119960,119,120012,119,120064,119,120116,119,120168,119,120220,119,120272,119,120324,119,120376,119,120428,119,120480,119,7457,119,1121,119,1309,119,1377,119,71434,119,71438,119,71439,119,43907,119,71919,87,71910,87,119830,87,119882,87,119934,87,119986,87,120038,87,120090,87,120142,87,120194,87,120246,87,120298,87,120350,87,120402,87,120454,87,1308,87,5043,87,5076,87,42218,87,5742,120,10539,120,10540,120,10799,120,65368,120,8569,120,119857,120,119909,120,119961,120,120013,120,120065,120,120117,120,120169,120,120221,120,120273,120,120325,120,120377,120,120429,120,120481,120,5441,120,5501,120,5741,88,9587,88,66338,88,71916,88,65336,88,8553,88,119831,88,119883,88,119935,88,119987,88,120039,88,120091,88,120143,88,120195,88,120247,88,120299,88,120351,88,120403,88,120455,88,42931,88,935,88,120510,88,120568,88,120626,88,120684,88,120742,88,11436,88,11613,88,5815,88,42219,88,66192,88,66228,88,66327,88,66855,88,611,121,7564,121,65369,121,119858,121,119910,121,119962,121,120014,121,120066,121,120118,121,120170,121,120222,121,120274,121,120326,121,120378,121,120430,121,120482,121,655,121,7935,121,43866,121,947,121,8509,121,120516,121,120574,121,120632,121,120690,121,120748,121,1199,121,4327,121,71900,121,65337,89,119832,89,119884,89,119936,89,119988,89,120040,89,120092,89,120144,89,120196,89,120248,89,120300,89,120352,89,120404,89,120456,89,933,89,978,89,120508,89,120566,89,120624,89,120682,89,120740,89,11432,89,1198,89,5033,89,5053,89,42220,89,94019,89,71844,89,66226,89,119859,122,119911,122,119963,122,120015,122,120067,122,120119,122,120171,122,120223,122,120275,122,120327,122,120379,122,120431,122,120483,122,7458,122,43923,122,71876,122,66293,90,71909,90,65338,90,8484,90,8488,90,119833,90,119885,90,119937,90,119989,90,120041,90,120197,90,120249,90,120301,90,120353,90,120405,90,120457,90,918,90,120493,90,120551,90,120609,90,120667,90,120725,90,5059,90,42204,90,71849,90,65282,34,65284,36,65285,37,65286,38,65290,42,65291,43,65294,46,65295,47,65296,48,65297,49,65298,50,65299,51,65300,52,65301,53,65302,54,65303,55,65304,56,65305,57,65308,60,65309,61,65310,62,65312,64,65316,68,65318,70,65319,71,65324,76,65329,81,65330,82,65333,85,65334,86,65335,87,65343,95,65346,98,65348,100,65350,102,65355,107,65357,109,65358,110,65361,113,65362,114,65364,116,65365,117,65367,119,65370,122,65371,123,65373,125,119846,109],"_default":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"cs":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"de":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"es":[8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"fr":[65374,126,65306,58,65281,33,8216,96,8245,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"it":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"ja":[8211,45,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65292,44,65307,59],"ko":[8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"pl":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"pt-BR":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"qps-ploc":[160,32,8211,45,65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"ru":[65374,126,65306,58,65281,33,8216,96,8217,96,8245,96,180,96,12494,47,305,105,921,73,1009,112,215,120,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"tr":[160,32,8211,45,65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65288,40,65289,41,65292,44,65307,59,65311,63],"zh-hans":[65374,126,65306,58,65281,33,8245,96,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65288,40,65289,41],"zh-hant":[8211,45,65374,126,180,96,12494,47,1047,51,1073,54,1072,97,1040,65,1068,98,1042,66,1089,99,1057,67,1077,101,1045,69,1053,72,305,105,1050,75,921,73,1052,77,1086,111,1054,79,1009,112,1088,112,1056,80,1075,114,1058,84,215,120,1093,120,1061,88,1091,121,1059,89,65283,35,65307,59]}'))}static{this.cache=new d.LRUCachedFunction({getCacheKey:JSON.stringify},te=>{function re(Ae){const Ne=new Map;for(let Ke=0;Ke!Ae.startsWith("_")&&Ae in Ce);ye.length===0&&(ye=["_default"]);let Le;for(const Ae of ye){const Ne=re(Ce[Ae]);Le=me(Le,Ne)}const Ee=re(Ce._common),Me=le(Ee,Le);return new $(Me)})}static getInstance(te){return $.cache.get(Array.from(te))}static{this._locales=new k.Lazy(()=>Object.keys($.ambiguousCharacterData.value).filter(te=>!te.startsWith("_")))}static getLocales(){return $._locales.value}constructor(te){this.confusableDictionary=te}isAmbiguous(te){return this.confusableDictionary.has(te)}getPrimaryConfusable(te){return this.confusableDictionary.get(te)}getConfusableCodePoints(){return new Set(this.confusableDictionary.keys())}}e.AmbiguousCharacters=$;class Q{static getRawData(){return JSON.parse("[9,10,11,12,13,32,127,160,173,847,1564,4447,4448,6068,6069,6155,6156,6157,6158,7355,7356,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8234,8235,8236,8237,8238,8239,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,10240,12288,12644,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65279,65440,65520,65521,65522,65523,65524,65525,65526,65527,65528,65532,78844,119155,119156,119157,119158,119159,119160,119161,119162,917504,917505,917506,917507,917508,917509,917510,917511,917512,917513,917514,917515,917516,917517,917518,917519,917520,917521,917522,917523,917524,917525,917526,917527,917528,917529,917530,917531,917532,917533,917534,917535,917536,917537,917538,917539,917540,917541,917542,917543,917544,917545,917546,917547,917548,917549,917550,917551,917552,917553,917554,917555,917556,917557,917558,917559,917560,917561,917562,917563,917564,917565,917566,917567,917568,917569,917570,917571,917572,917573,917574,917575,917576,917577,917578,917579,917580,917581,917582,917583,917584,917585,917586,917587,917588,917589,917590,917591,917592,917593,917594,917595,917596,917597,917598,917599,917600,917601,917602,917603,917604,917605,917606,917607,917608,917609,917610,917611,917612,917613,917614,917615,917616,917617,917618,917619,917620,917621,917622,917623,917624,917625,917626,917627,917628,917629,917630,917631,917760,917761,917762,917763,917764,917765,917766,917767,917768,917769,917770,917771,917772,917773,917774,917775,917776,917777,917778,917779,917780,917781,917782,917783,917784,917785,917786,917787,917788,917789,917790,917791,917792,917793,917794,917795,917796,917797,917798,917799,917800,917801,917802,917803,917804,917805,917806,917807,917808,917809,917810,917811,917812,917813,917814,917815,917816,917817,917818,917819,917820,917821,917822,917823,917824,917825,917826,917827,917828,917829,917830,917831,917832,917833,917834,917835,917836,917837,917838,917839,917840,917841,917842,917843,917844,917845,917846,917847,917848,917849,917850,917851,917852,917853,917854,917855,917856,917857,917858,917859,917860,917861,917862,917863,917864,917865,917866,917867,917868,917869,917870,917871,917872,917873,917874,917875,917876,917877,917878,917879,917880,917881,917882,917883,917884,917885,917886,917887,917888,917889,917890,917891,917892,917893,917894,917895,917896,917897,917898,917899,917900,917901,917902,917903,917904,917905,917906,917907,917908,917909,917910,917911,917912,917913,917914,917915,917916,917917,917918,917919,917920,917921,917922,917923,917924,917925,917926,917927,917928,917929,917930,917931,917932,917933,917934,917935,917936,917937,917938,917939,917940,917941,917942,917943,917944,917945,917946,917947,917948,917949,917950,917951,917952,917953,917954,917955,917956,917957,917958,917959,917960,917961,917962,917963,917964,917965,917966,917967,917968,917969,917970,917971,917972,917973,917974,917975,917976,917977,917978,917979,917980,917981,917982,917983,917984,917985,917986,917987,917988,917989,917990,917991,917992,917993,917994,917995,917996,917997,917998,917999]")}static{this._data=void 0}static getData(){return this._data||(this._data=new Set(Q.getRawData())),this._data}static isInvisibleCharacter(te){return Q.getData().has(te)}static get codePoints(){return Q.getData()}}e.InvisibleCharacters=Q}),define(ne[82],se([1,0,45,448,11]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FuzzyScoreOptions=e.FuzzyScore=e.matchesPrefix=e.matchesStrictPrefix=void 0,e.or=E,e.matchesContiguousSubString=m,e.matchesSubString=_,e.isUpper=n,e.matchesCamelCase=S,e.matchesWords=L,e.matchesFuzzy=N,e.matchesFuzzy2=O,e.anyScore=F,e.createMatches=x,e.isPatternInWord=he,e.fuzzyScore=ee,e.fuzzyScoreGracefulAggressive=X;function E(...Q){return function(Z,te){for(let re=0,le=Q.length;re0?[{start:0,end:Z.length}]:[]:null}function m(Q,Z){const te=Z.toLowerCase().indexOf(Q.toLowerCase());return te===-1?null:[{start:te,end:te+Q.length}]}function _(Q,Z){return b(Q.toLowerCase(),Z.toLowerCase(),0,0)}function b(Q,Z,te,re){if(te===Q.length)return[];if(re===Z.length)return null;if(Q[te]===Z[re]){let le=null;return(le=b(Q,Z,te+1,re+1))?r({start:re,end:re+1},le):null}return b(Q,Z,te,re+1)}function p(Q){return 97<=Q&&Q<=122}function n(Q){return 65<=Q&&Q<=90}function o(Q){return 48<=Q&&Q<=57}function t(Q){return Q===32||Q===9||Q===10||Q===13}const i=new Set;"()[]{}<>`'\"-/;:,.?!".split("").forEach(Q=>i.add(Q.charCodeAt(0)));function s(Q){return t(Q)||i.has(Q)}function g(Q,Z){return Q===Z||s(Q)&&s(Z)}const c=new Map;function l(Q){if(c.has(Q))return c.get(Q);let Z;const te=(0,k.getKoreanAltChars)(Q);return te&&(Z=te),c.set(Q,Z),Z}function a(Q){return p(Q)||n(Q)||o(Q)}function r(Q,Z){return Z.length===0?Z=[Q]:Q.end===Z[0].start?Z[0].start=Q.start:Z.unshift(Q),Z}function u(Q,Z){for(let te=Z;te0&&!a(Q.charCodeAt(te-1)))return te}return Q.length}function C(Q,Z,te,re){if(te===Q.length)return[];if(re===Z.length)return null;if(Q[te]!==Z[re].toLowerCase())return null;{let le=null,me=re+1;for(le=C(Q,Z,te+1,re+1);!le&&(me=u(Z,me)).6}function v(Q){const{upperPercent:Z,lowerPercent:te,alphaPercent:re,numericPercent:le}=Q;return te>.2&&Z<.8&&re>.6&&le<.2}function w(Q){let Z=0,te=0,re=0,le=0;for(let me=0;me60&&(Z=Z.substring(0,60));const te=f(Z);if(!v(te)){if(!h(te))return null;Z=Z.toLowerCase()}let re=null,le=0;for(Q=Q.toLowerCase();le0&&s(Q.charCodeAt(te-1)))return te;return Q.length}const M=E(e.matchesPrefix,S,m),A=E(e.matchesPrefix,S,_),P=new d.LRUCache(1e4);function N(Q,Z,te=!1){if(typeof Q!="string"||typeof Z!="string")return null;let re=P.get(Q);re||(re=new RegExp(I.convertSimple2RegExpPattern(Q),"i"),P.set(Q,re));const le=re.exec(Z);return le?[{start:le.index,end:le.index+le[0].length}]:te?A(Q,Z):M(Q,Z)}function O(Q,Z){const te=ee(Q,Q.toLowerCase(),0,Z,Z.toLowerCase(),0,{firstMatchCanBeWeak:!0,boostFullMatch:!0});return te?x(te):null}function F(Q,Z,te,re,le,me){const Ce=Math.min(13,Q.length);for(;te"u")return[];const Z=[],te=Q[1];for(let re=Q.length-1;re>1;re--){const le=Q[re]+te,me=Z[Z.length-1];me&&me.end===le?me.end=le+1:Z.push({start:le,end:le+1})}return Z}const W=128;function V(){const Q=[],Z=[];for(let te=0;te<=W;te++)Z[te]=0;for(let te=0;te<=W;te++)Q.push(Z.slice(0));return Q}function q(Q){const Z=[];for(let te=0;te<=Q;te++)Z[te]=0;return Z}const H=q(2*W),z=q(2*W),U=V(),j=V(),Y=V(),G=!1;function K(Q,Z,te,re,le){function me(ye,Le,Ee=" "){for(;ye.lengthme(ye,3)).join("|")} `;for(let ye=0;ye<=te;ye++)ye===0?Ce+=" |":Ce+=`${Z[ye-1]}|`,Ce+=Q[ye].slice(0,le+1).map(Le=>me(Le.toString(),3)).join("|")+` `;return Ce}function R(Q,Z,te,re){Q=Q.substr(Z),te=te.substr(re),console.log(K(j,Q,Q.length,te,te.length)),console.log(K(Y,Q,Q.length,te,te.length)),console.log(K(U,Q,Q.length,te,te.length))}function J(Q,Z){if(Z<0||Z>=Q.length)return!1;const te=Q.codePointAt(Z);switch(te){case 95:case 45:case 46:case 32:case 47:case 92:case 39:case 34:case 58:case 36:case 60:case 62:case 40:case 41:case 91:case 93:case 123:case 125:return!0;case void 0:return!1;default:return!!I.isEmojiImprecise(te)}}function ie(Q,Z){if(Z<0||Z>=Q.length)return!1;switch(Q.charCodeAt(Z)){case 32:case 9:return!0;default:return!1}}function ue(Q,Z,te){return Z[Q]!==te[Q]}function he(Q,Z,te,re,le,me,Ce=!1){for(;ZW?W:Q.length,Le=re.length>W?W:re.length;if(te>=ye||me>=Le||ye-te>Le-me||!he(Z,te,ye,le,me,Le,!0))return;de(ye,Le,te,me,Z,le);let Ee=1,Me=1,Ae=te,Ne=me;const Ke=[!1];for(Ee=1,Ae=te;AeFe,Te=we?j[Ee][Me-1]+(U[Ee][Me-1]>0?-5:0):0,Pe=Ne>Fe+1&&U[Ee][Me-1]>0,Be=Pe?j[Ee][Me-2]+(U[Ee][Me-2]>0?-5:0):0;if(Pe&&(!we||Be>=Te)&&(!be||Be>=ve))j[Ee][Me]=Be,Y[Ee][Me]=3,U[Ee][Me]=0;else if(we&&(!be||Te>=ve))j[Ee][Me]=Te,Y[Ee][Me]=2,U[Ee][Me]=0;else if(be)j[Ee][Me]=ve,Y[Ee][Me]=1,U[Ee][Me]=U[Ee-1][Me-1]+1;else throw new Error("not possible")}}if(G&&R(Q,te,re,me),!Ke[0]&&!Ce.firstMatchCanBeWeak)return;Ee--,Me--;const ze=[j[Ee][Me],me];let Ge=0,it=0;for(;Ee>=1;){let Fe=Me;do{const fe=Y[Ee][Fe];if(fe===3)Fe=Fe-2;else if(fe===2)Fe=Fe-1;else break}while(Fe>=1);Ge>1&&Z[te+Ee-1]===le[me+Me-1]&&!ue(Fe+me-1,re,le)&&Ge+1>U[Ee][Fe]&&(Fe=Me),Fe===Me?Ge++:Ge=1,it||(it=Fe),Ee--,Me=Fe-1,ze.push(Me)}Le-me===ye&&Ce.boostFullMatch&&(ze[0]+=2);const Oe=it-ye;return ze[0]-=Oe,ze}function de(Q,Z,te,re,le,me){let Ce=Q-1,ye=Z-1;for(;Ce>=te&&ye>=re;)le[Ce]===me[ye]&&(z[Ce]=ye,Ce--),ye--}function ge(Q,Z,te,re,le,me,Ce,ye,Le,Ee,Me){if(Z[te]!==me[Ce])return Number.MIN_SAFE_INTEGER;let Ae=1,Ne=!1;return Ce===te-re?Ae=Q[te]===le[Ce]?7:5:ue(Ce,le,me)&&(Ce===0||!ue(Ce-1,le,me))?(Ae=Q[te]===le[Ce]?7:5,Ne=!0):J(me,Ce)&&(Ce===0||!J(me,Ce-1))?Ae=5:(J(me,Ce-1)||ie(me,Ce-1))&&(Ae=5,Ne=!0),Ae>1&&te===re&&(Me[0]=!0),Ne||(Ne=ue(Ce,le,me)||J(me,Ce-1)||ie(me,Ce-1)),te===re?Ce>Le&&(Ae-=Ne?3:5):Ee?Ae+=Ne?2:0:Ae+=Ne?0:1,Ce+1===ye&&(Ae-=Ne?3:5),Ae}function X(Q,Z,te,re,le,me,Ce){return B(Q,Z,te,re,le,me,!0,Ce)}function B(Q,Z,te,re,le,me,Ce,ye){let Le=ee(Q,Z,te,re,le,me,ye);if(Le&&!Ce)return Le;if(Q.length>=3){const Ee=Math.min(7,Q.length-1);for(let Me=te+1;MeLe[0])&&(Le=Ne))}}}return Le}function $(Q,Z){if(Z+1>=Q.length)return;const te=Q[Z],re=Q[Z+1];if(te!==re)return Q.slice(0,Z)+re+te+Q.slice(Z+2)}}),define(ne[129],se([1,0,11]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StringSHA1=void 0,e.hash=k,e.doHash=I,e.numberHash=E,e.stringHash=m,e.toHexString=t;function k(s){return I(s,0)}function I(s,g){switch(typeof s){case"object":return s===null?E(349,g):Array.isArray(s)?_(s,g):b(s,g);case"string":return m(s,g);case"boolean":return y(s,g);case"number":return E(s,g);case"undefined":return E(937,g);default:return E(617,g)}}function E(s,g){return(g<<5)-g+s|0}function y(s,g){return E(s?433:863,g)}function m(s,g){g=E(149417,g);for(let c=0,l=s.length;cI(l,c),g)}function b(s,g){return g=E(181387,g),Object.keys(s).sort().reduce((c,l)=>(c=m(l,c),I(s[l],c)),g)}function p(s,g,c=32){const l=c-g,a=~((1<>>l)>>>0}function n(s,g=0,c=s.byteLength,l=0){for(let a=0;ac.toString(16).padStart(2,"0")).join(""):o((s>>>0).toString(16),g/4)}class i{static{this._bigBlock32=new DataView(new ArrayBuffer(320))}constructor(){this._h0=1732584193,this._h1=4023233417,this._h2=2562383102,this._h3=271733878,this._h4=3285377520,this._buff=new Uint8Array(67),this._buffDV=new DataView(this._buff.buffer),this._buffLen=0,this._totalLen=0,this._leftoverHighSurrogate=0,this._finished=!1}update(g){const c=g.length;if(c===0)return;const l=this._buff;let a=this._buffLen,r=this._leftoverHighSurrogate,u,C;for(r!==0?(u=r,C=-1,r=0):(u=g.charCodeAt(0),C=0);;){let f=u;if(d.isHighSurrogate(u))if(C+1>>6,g[c++]=128|(l&63)>>>0):l<65536?(g[c++]=224|(l&61440)>>>12,g[c++]=128|(l&4032)>>>6,g[c++]=128|(l&63)>>>0):(g[c++]=240|(l&1835008)>>>18,g[c++]=128|(l&258048)>>>12,g[c++]=128|(l&4032)>>>6,g[c++]=128|(l&63)>>>0),c>=64&&(this._step(),c-=64,this._totalLen+=64,g[0]=g[64],g[1]=g[65],g[2]=g[66]),c}digest(){return this._finished||(this._finished=!0,this._leftoverHighSurrogate&&(this._leftoverHighSurrogate=0,this._buffLen=this._push(this._buff,this._buffLen,65533)),this._totalLen+=this._buffLen,this._wrapUp()),t(this._h0)+t(this._h1)+t(this._h2)+t(this._h3)+t(this._h4)}_wrapUp(){this._buff[this._buffLen++]=128,n(this._buff,this._buffLen),this._buffLen>56&&(this._step(),n(this._buff));const g=8*this._totalLen;this._buffDV.setUint32(56,Math.floor(g/4294967296),!1),this._buffDV.setUint32(60,g%4294967296,!1),this._step()}_step(){const g=i._bigBlock32,c=this._buffDV;for(let w=0;w<64;w+=4)g.setUint32(w,c.getUint32(w,!1),!1);for(let w=64;w<320;w+=4)g.setUint32(w,p(g.getUint32(w-12,!1)^g.getUint32(w-32,!1)^g.getUint32(w-56,!1)^g.getUint32(w-64,!1),1),!1);let l=this._h0,a=this._h1,r=this._h2,u=this._h3,C=this._h4,f,h,v;for(let w=0;w<80;w++)w<20?(f=a&r|~a&u,h=1518500249):w<40?(f=a^r^u,h=1859775393):w<60?(f=a&r|a&u|r&u,h=2400959708):(f=a^r^u,h=3395469782),v=p(l,5)+f+C+h+g.getUint32(w*4,!1)&4294967295,C=u,u=r,r=p(a,30),a=l,l=v;this._h0=this._h0+l&4294967295,this._h1=this._h1+a&4294967295,this._h2=this._h2+r&4294967295,this._h3=this._h3+u&4294967295,this._h4=this._h4+C&4294967295}}e.StringSHA1=i}),define(ne[190],se([1,0,444,129]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LcsDiff=e.StringDiffSequence=void 0,e.stringDiff=E;class I{constructor(n){this.source=n}getElements(){const n=this.source,o=new Int32Array(n.length);for(let t=0,i=n.length;t0||this.m_modifiedCount>0)&&this.m_changes.push(new d.DiffChange(this.m_originalStart,this.m_originalCount,this.m_modifiedStart,this.m_modifiedCount)),this.m_originalCount=0,this.m_modifiedCount=0,this.m_originalStart=1073741824,this.m_modifiedStart=1073741824}AddOriginalElement(n,o){this.m_originalStart=Math.min(this.m_originalStart,n),this.m_modifiedStart=Math.min(this.m_modifiedStart,o),this.m_originalCount++}AddModifiedElement(n,o){this.m_originalStart=Math.min(this.m_originalStart,n),this.m_modifiedStart=Math.min(this.m_modifiedStart,o),this.m_modifiedCount++}getChanges(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes}getReverseChanges(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes.reverse(),this.m_changes}}class b{constructor(n,o,t=null){this.ContinueProcessingPredicate=t,this._originalSequence=n,this._modifiedSequence=o;const[i,s,g]=b._getElements(n),[c,l,a]=b._getElements(o);this._hasStrings=g&&a,this._originalStringElements=i,this._originalElementsOrHash=s,this._modifiedStringElements=c,this._modifiedElementsOrHash=l,this.m_forwardHistory=[],this.m_reverseHistory=[]}static _isStringArray(n){return n.length>0&&typeof n[0]=="string"}static _getElements(n){const o=n.getElements();if(b._isStringArray(o)){const t=new Int32Array(o.length);for(let i=0,s=o.length;i=n&&i>=t&&this.ElementsAreEqual(o,i);)o--,i--;if(n>o||t>i){let u;return t<=i?(y.Assert(n===o+1,"originalStart should only be one more than originalEnd"),u=[new d.DiffChange(n,0,t,i-t+1)]):n<=o?(y.Assert(t===i+1,"modifiedStart should only be one more than modifiedEnd"),u=[new d.DiffChange(n,o-n+1,t,0)]):(y.Assert(n===o+1,"originalStart should only be one more than originalEnd"),y.Assert(t===i+1,"modifiedStart should only be one more than modifiedEnd"),u=[]),u}const g=[0],c=[0],l=this.ComputeRecursionPoint(n,o,t,i,g,c,s),a=g[0],r=c[0];if(l!==null)return l;if(!s[0]){const u=this.ComputeDiffRecursive(n,a,t,r,s);let C=[];return s[0]?C=[new d.DiffChange(a+1,o-(a+1)+1,r+1,i-(r+1)+1)]:C=this.ComputeDiffRecursive(a+1,o,r+1,i,s),this.ConcatenateChanges(u,C)}return[new d.DiffChange(n,o-n+1,t,i-t+1)]}WALKTRACE(n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L){let D=null,T=null,M=new _,A=o,P=t,N=f[0]-w[0]-i,O=-1073741824,F=this.m_forwardHistory.length-1;do{const x=N+n;x===A||x=0&&(a=this.m_forwardHistory[F],n=a[0],A=1,P=a.length-1)}while(--F>=-1);if(D=M.getReverseChanges(),L[0]){let x=f[0]+1,W=w[0]+1;if(D!==null&&D.length>0){const V=D[D.length-1];x=Math.max(x,V.getOriginalEnd()),W=Math.max(W,V.getModifiedEnd())}T=[new d.DiffChange(x,C-x+1,W,v-W+1)]}else{M=new _,A=g,P=c,N=f[0]-w[0]-l,O=1073741824,F=S?this.m_reverseHistory.length-1:this.m_reverseHistory.length-2;do{const x=N+s;x===A||x=r[x+1]?(u=r[x+1]-1,h=u-N-l,u>O&&M.MarkNextChange(),O=u+1,M.AddOriginalElement(u+1,h+1),N=x+1-s):(u=r[x-1],h=u-N-l,u>O&&M.MarkNextChange(),O=u,M.AddModifiedElement(u+1,h+1),N=x-1-s),F>=0&&(r=this.m_reverseHistory[F],s=r[0],A=1,P=r.length-1)}while(--F>=-1);T=M.getChanges()}return this.ConcatenateChanges(D,T)}ComputeRecursionPoint(n,o,t,i,s,g,c){let l=0,a=0,r=0,u=0,C=0,f=0;n--,t--,s[0]=0,g[0]=0,this.m_forwardHistory=[],this.m_reverseHistory=[];const h=o-n+(i-t),v=h+1,w=new Int32Array(v),S=new Int32Array(v),L=i-t,D=o-n,T=n-t,M=o-i,P=(D-L)%2===0;w[L]=n,S[D]=o,c[0]=!1;for(let N=1;N<=h/2+1;N++){let O=0,F=0;r=this.ClipDiagonalBound(L-N,N,L,v),u=this.ClipDiagonalBound(L+N,N,L,v);for(let W=r;W<=u;W+=2){W===r||WO+F&&(O=l,F=a),!P&&Math.abs(W-D)<=N-1&&l>=S[W])return s[0]=l,g[0]=a,V<=S[W]&&N<=1448?this.WALKTRACE(L,r,u,T,D,C,f,M,w,S,l,o,s,a,i,g,P,c):null}const x=(O-n+(F-t)-N)/2;if(this.ContinueProcessingPredicate!==null&&!this.ContinueProcessingPredicate(O,x))return c[0]=!0,s[0]=O,g[0]=F,x>0&&N<=1448?this.WALKTRACE(L,r,u,T,D,C,f,M,w,S,l,o,s,a,i,g,P,c):(n++,t++,[new d.DiffChange(n,o-n+1,t,i-t+1)]);C=this.ClipDiagonalBound(D-N,N,D,v),f=this.ClipDiagonalBound(D+N,N,D,v);for(let W=C;W<=f;W+=2){W===C||W=S[W+1]?l=S[W+1]-1:l=S[W-1],a=l-(W-D)-M;const V=l;for(;l>n&&a>t&&this.ElementsAreEqual(l,a);)l--,a--;if(S[W]=l,P&&Math.abs(W-L)<=N&&l<=w[W])return s[0]=l,g[0]=a,V>=w[W]&&N<=1448?this.WALKTRACE(L,r,u,T,D,C,f,M,w,S,l,o,s,a,i,g,P,c):null}if(N<=1447){let W=new Int32Array(u-r+2);W[0]=L-r+1,m.Copy2(w,r,W,1,u-r+1),this.m_forwardHistory.push(W),W=new Int32Array(f-C+2),W[0]=D-C+1,m.Copy2(S,C,W,1,f-C+1),this.m_reverseHistory.push(W)}}return this.WALKTRACE(L,r,u,T,D,C,f,M,w,S,l,o,s,a,i,g,P,c)}PrettifyChanges(n){for(let o=0;o0,c=t.modifiedLength>0;for(;t.originalStart+t.originalLength=0;o--){const t=n[o];let i=0,s=0;if(o>0){const u=n[o-1];i=u.originalStart+u.originalLength,s=u.modifiedStart+u.modifiedLength}const g=t.originalLength>0,c=t.modifiedLength>0;let l=0,a=this._boundaryScore(t.originalStart,t.originalLength,t.modifiedStart,t.modifiedLength);for(let u=1;;u++){const C=t.originalStart-u,f=t.modifiedStart-u;if(Ca&&(a=v,l=u)}t.originalStart-=l,t.modifiedStart-=l;const r=[null];if(o>0&&this.ChangesOverlap(n[o-1],n[o],r)){n[o-1]=r[0],n.splice(o,1),o++;continue}}if(this._hasStrings)for(let o=1,t=n.length;o0&&f>l&&(l=f,a=u,r=C)}return l>0?[a,r]:null}_contiguousSequenceScore(n,o,t){let i=0;for(let s=0;s=this._originalElementsOrHash.length-1?!0:this._hasStrings&&/^\s*$/.test(this._originalStringElements[n])}_OriginalRegionIsBoundary(n,o){if(this._OriginalIsBoundary(n)||this._OriginalIsBoundary(n-1))return!0;if(o>0){const t=n+o;if(this._OriginalIsBoundary(t-1)||this._OriginalIsBoundary(t))return!0}return!1}_ModifiedIsBoundary(n){return n<=0||n>=this._modifiedElementsOrHash.length-1?!0:this._hasStrings&&/^\s*$/.test(this._modifiedStringElements[n])}_ModifiedRegionIsBoundary(n,o){if(this._ModifiedIsBoundary(n)||this._ModifiedIsBoundary(n-1))return!0;if(o>0){const t=n+o;if(this._ModifiedIsBoundary(t-1)||this._ModifiedIsBoundary(t))return!0}return!1}_boundaryScore(n,o,t,i){const s=this._OriginalRegionIsBoundary(n,o)?1:0,g=this._ModifiedRegionIsBoundary(t,i)?1:0;return s+g}ConcatenateChanges(n,o){const t=[];if(n.length===0||o.length===0)return o.length>0?o:n;if(this.ChangesOverlap(n[n.length-1],o[0],t)){const i=new Array(n.length+o.length-1);return m.Copy(n,0,i,0,n.length-1),i[n.length-1]=t[0],m.Copy(o,1,i,n.length,o.length-1),i}else{const i=new Array(n.length+o.length);return m.Copy(n,0,i,0,n.length),m.Copy(o,0,i,n.length,o.length),i}}ChangesOverlap(n,o,t){if(y.Assert(n.originalStart<=o.originalStart,"Left change is not less than or equal to right change"),y.Assert(n.modifiedStart<=o.modifiedStart,"Left change is not less than or equal to right change"),n.originalStart+n.originalLength>=o.originalStart||n.modifiedStart+n.modifiedLength>=o.modifiedStart){const i=n.originalStart;let s=n.originalLength;const g=n.modifiedStart;let c=n.modifiedLength;return n.originalStart+n.originalLength>=o.originalStart&&(s=o.originalStart+o.originalLength-n.originalStart),n.modifiedStart+n.modifiedLength>=o.modifiedStart&&(c=o.modifiedStart+o.modifiedLength-n.modifiedStart),t[0]=new d.DiffChange(i,s,g,c),!0}else return t[0]=null,!1}ClipDiagonalBound(n,o,t,i){if(n>=0&&n0?m[0].toUpperCase()+m.substr(1):y[0][0].toUpperCase()!==y[0][0]&&m.length>0?m[0].toLowerCase()+m.substr(1):m}else return m}function I(y,m,_){return y[0].indexOf(_)!==-1&&m.indexOf(_)!==-1&&y[0].split(_).length===m.split(_).length}function E(y,m,_){const b=m.split(_),p=y[0].split(_);let n="";return b.forEach((o,t)=>{n+=k([p[t]],o)+_}),n.slice(0,-1)}}),define(ne[111],se([1,0,11]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var k;(function(I){I[I.Ignore=0]="Ignore",I[I.Info=1]="Info",I[I.Warning=2]="Warning",I[I.Error=3]="Error"})(k||(k={})),function(I){const E="error",y="warning",m="warn",_="info",b="ignore";function p(o){return o?d.equalsIgnoreCase(E,o)?I.Error:d.equalsIgnoreCase(y,o)||d.equalsIgnoreCase(m,o)?I.Warning:d.equalsIgnoreCase(_,o)?I.Info:I.Ignore:I.Ignore}I.fromValue=p;function n(o){switch(o){case I.Error:return E;case I.Warning:return y;case I.Info:return _;default:return b}}I.toString=n}(k||(k={})),e.default=k}),define(ne[301],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MicrotaskDelay=void 0,e.MicrotaskDelay=Symbol("MicrotaskDelay")}),define(ne[225],se([1,0,11]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TernarySearchTree=e.UriIterator=e.PathIterator=e.ConfigKeysIterator=e.StringIterator=void 0;class k{constructor(){this._value="",this._pos=0}reset(p){return this._value=p,this._pos=0,this}next(){return this._pos+=1,this}hasNext(){return this._pos=0;n--,this._valueLen--){const o=this._value.charCodeAt(n);if(!(o===47||this._splitOnBackslash&&o===92))break}return this.next()}hasNext(){return this._to!1,n=()=>!1){return new _(new y(p,n))}static forStrings(){return new _(new k)}static forConfigKeys(){return new _(new I)}constructor(p){this._iter=p}clear(){this._root=void 0}set(p,n){const o=this._iter.reset(p);let t;this._root||(this._root=new m,this._root.segment=o.value());const i=[];for(t=this._root;;){const g=o.cmp(t.segment);if(g>0)t.left||(t.left=new m,t.left.segment=o.value()),i.push([-1,t]),t=t.left;else if(g<0)t.right||(t.right=new m,t.right.segment=o.value()),i.push([1,t]),t=t.right;else if(o.hasNext())o.next(),t.mid||(t.mid=new m,t.mid.segment=o.value()),i.push([0,t]),t=t.mid;else break}const s=t.value;t.value=n,t.key=p;for(let g=i.length-1;g>=0;g--){const c=i[g][1];c.updateHeight();const l=c.balanceFactor();if(l<-1||l>1){const a=i[g][0],r=i[g+1][0];if(a===1&&r===1)i[g][1]=c.rotateLeft();else if(a===-1&&r===-1)i[g][1]=c.rotateRight();else if(a===1&&r===-1)c.right=i[g+1][1]=i[g+1][1].rotateRight(),i[g][1]=c.rotateLeft();else if(a===-1&&r===1)c.left=i[g+1][1]=i[g+1][1].rotateLeft(),i[g][1]=c.rotateRight();else throw new Error;if(g>0)switch(i[g-1][0]){case-1:i[g-1][1].left=i[g][1];break;case 1:i[g-1][1].right=i[g][1];break;case 0:i[g-1][1].mid=i[g][1];break}else this._root=i[0][1]}}return s}get(p){return this._getNode(p)?.value}_getNode(p){const n=this._iter.reset(p);let o=this._root;for(;o;){const t=n.cmp(o.segment);if(t>0)o=o.left;else if(t<0)o=o.right;else if(n.hasNext())n.next(),o=o.mid;else break}return o}has(p){const n=this._getNode(p);return!(n?.value===void 0&&n?.mid===void 0)}delete(p){return this._delete(p,!1)}deleteSuperstr(p){return this._delete(p,!0)}_delete(p,n){const o=this._iter.reset(p),t=[];let i=this._root;for(;i;){const s=o.cmp(i.segment);if(s>0)t.push([-1,i]),i=i.left;else if(s<0)t.push([1,i]),i=i.right;else if(o.hasNext())o.next(),t.push([0,i]),i=i.mid;else break}if(i){if(n?(i.left=void 0,i.mid=void 0,i.right=void 0,i.height=1):(i.key=void 0,i.value=void 0),!i.mid&&!i.value)if(i.left&&i.right){const s=this._min(i.right);if(s.key){const{key:g,value:c,segment:l}=s;this._delete(s.key,!1),i.key=g,i.value=c,i.segment=l}}else{const s=i.left??i.right;if(t.length>0){const[g,c]=t[t.length-1];switch(g){case-1:c.left=s;break;case 0:c.mid=s;break;case 1:c.right=s;break}}else this._root=s}for(let s=t.length-1;s>=0;s--){const g=t[s][1];g.updateHeight();const c=g.balanceFactor();if(c>1?(g.right.balanceFactor()>=0||(g.right=g.right.rotateRight()),t[s][1]=g.rotateLeft()):c<-1&&(g.left.balanceFactor()<=0||(g.left=g.left.rotateLeft()),t[s][1]=g.rotateRight()),s>0)switch(t[s-1][0]){case-1:t[s-1][1].left=t[s][1];break;case 1:t[s-1][1].right=t[s][1];break;case 0:t[s-1][1].mid=t[s][1];break}else this._root=t[0][1]}}}_min(p){for(;p.left;)p=p.left;return p}findSubstr(p){const n=this._iter.reset(p);let o=this._root,t;for(;o;){const i=n.cmp(o.segment);if(i>0)o=o.left;else if(i<0)o=o.right;else if(n.hasNext())n.next(),t=o.value||t,o=o.mid;else break}return o&&o.value||t}findSuperstr(p){return this._findSuperstrOrElement(p,!1)}_findSuperstrOrElement(p,n){const o=this._iter.reset(p);let t=this._root;for(;t;){const i=o.cmp(t.segment);if(i>0)t=t.left;else if(i<0)t=t.right;else if(o.hasNext())o.next(),t=t.mid;else return t.mid?this._entries(t.mid):n?t.value:void 0}}forEach(p){for(const[n,o]of this)p(o,n)}*[Symbol.iterator](){yield*this._entries(this._root)}_entries(p){const n=[];return this._dfsEntries(p,n),n[Symbol.iterator]()}_dfsEntries(p,n){p&&(p.left&&this._dfsEntries(p.left,n),p.value&&n.push([p.key,p.value]),p.mid&&this._dfsEntries(p.mid,n),p.right&&this._dfsEntries(p.right,n))}}e.TernarySearchTree=_}),define(ne[456],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TfIdfCalculator=void 0,e.normalizeTfIdfScores=I;function d(E){const y=new Map;for(const m of E)y.set(m,(y.get(m)??0)+1);return y}class k{constructor(){this.chunkCount=0,this.chunkOccurrences=new Map,this.documents=new Map}calculateScores(y,m){const _=this.computeEmbedding(y),b=new Map,p=[];for(const[n,o]of this.documents){if(m.isCancellationRequested)return[];for(const t of o.chunks){const i=this.computeSimilarityScore(t,_,b);i>0&&p.push({key:n,score:i})}}return p}static termFrequencies(y){return d(k.splitTerms(y))}static*splitTerms(y){const m=_=>_.toLowerCase();for(const[_]of y.matchAll(/\b\p{Letter}[\p{Letter}\d]{2,}\b/gu)){yield m(_);const b=_.replace(/([a-z])([A-Z])/g,"$1 $2").split(/\s+/g);if(b.length>1)for(const p of b)p.length>2&&/\p{Letter}{3,}/gu.test(p)&&(yield m(p))}}updateDocuments(y){for(const{key:m}of y)this.deleteDocument(m);for(const m of y){const _=[];for(const b of m.textChunks){const p=k.termFrequencies(b);for(const n of p.keys())this.chunkOccurrences.set(n,(this.chunkOccurrences.get(n)??0)+1);_.push({text:b,tf:p})}this.chunkCount+=_.length,this.documents.set(m.key,{chunks:_})}return this}deleteDocument(y){const m=this.documents.get(y);if(m){this.documents.delete(y),this.chunkCount-=m.chunks.length;for(const _ of m.chunks)for(const b of _.tf.keys()){const p=this.chunkOccurrences.get(b);if(typeof p=="number"){const n=p-1;n<=0?this.chunkOccurrences.delete(b):this.chunkOccurrences.set(b,n)}}}}computeSimilarityScore(y,m,_){let b=0;for(const[p,n]of Object.entries(m)){const o=y.tf.get(p);if(!o)continue;let t=_.get(p);typeof t!="number"&&(t=this.computeIdf(p),_.set(p,t));const i=o*t;b+=i*n}return b}computeEmbedding(y){const m=k.termFrequencies(y);return this.computeTfidf(m)}computeIdf(y){const m=this.chunkOccurrences.get(y)??0;return m>0?Math.log((this.chunkCount+1)/m):0}computeTfidf(y){const m=Object.create(null);for(const[_,b]of y){const p=this.computeIdf(_);p>0&&(m[_]=b*p)}return m}}e.TfIdfCalculator=k;function I(E){const y=E.slice(0);y.sort((_,b)=>b.score-_.score);const m=y[0]?.score??0;if(m>0)for(const _ of y)_.score/=m;return y}}),define(ne[19],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isString=d,e.isObject=k,e.isTypedArray=I,e.isNumber=E,e.isIterable=y,e.isBoolean=m,e.isUndefined=_,e.isDefined=b,e.isUndefinedOrNull=p,e.assertType=n,e.assertIsDefined=o,e.isFunction=t,e.validateConstraints=i,e.validateConstraint=s;function d(g){return typeof g=="string"}function k(g){return typeof g=="object"&&g!==null&&!Array.isArray(g)&&!(g instanceof RegExp)&&!(g instanceof Date)}function I(g){const c=Object.getPrototypeOf(Uint8Array);return typeof g=="object"&&g instanceof c}function E(g){return typeof g=="number"&&!isNaN(g)}function y(g){return!!g&&typeof g[Symbol.iterator]=="function"}function m(g){return g===!0||g===!1}function _(g){return typeof g>"u"}function b(g){return!p(g)}function p(g){return _(g)||g===null}function n(g,c){if(!g)throw new Error(c?`Unexpected type, expected '${c}'`:"Unexpected type")}function o(g){if(p(g))throw new Error("Assertion Failed: argument is undefined or null");return g}function t(g){return typeof g=="function"}function i(g,c){const l=Math.min(g.length,c.length);for(let a=0;a{i[s]=g&&typeof g=="object"?k(g):g}),i}function I(t){if(!t||typeof t!="object")return t;const i=[t];for(;i.length>0;){const s=i.shift();Object.freeze(s);for(const g in s)if(E.call(s,g)){const c=s[g];typeof c=="object"&&!Object.isFrozen(c)&&!(0,d.isTypedArray)(c)&&i.push(c)}}return t}const E=Object.prototype.hasOwnProperty;function y(t,i){return m(t,i,new Set)}function m(t,i,s){if((0,d.isUndefinedOrNull)(t))return t;const g=i(t);if(typeof g<"u")return g;if(Array.isArray(t)){const c=[];for(const l of t)c.push(m(l,i,s));return c}if((0,d.isObject)(t)){if(s.has(t))throw new Error("Cannot clone recursive data-structure");s.add(t);const c={};for(const l in t)E.call(t,l)&&(c[l]=m(t[l],i,s));return s.delete(t),c}return t}function _(t,i,s=!0){return(0,d.isObject)(t)?((0,d.isObject)(i)&&Object.keys(i).forEach(g=>{g in t?s&&((0,d.isObject)(t[g])&&(0,d.isObject)(i[g])?_(t[g],i[g],s):t[g]=i[g]):t[g]=i[g]}),t):i}function b(t,i){if(t===i)return!0;if(t==null||i===null||i===void 0||typeof t!=typeof i||typeof t!="object"||Array.isArray(t)!==Array.isArray(i))return!1;let s,g;if(Array.isArray(t)){if(t.length!==i.length)return!1;for(s=0;sfunction(){const l=Array.prototype.slice.call(arguments,0);return i(c,l)},g={};for(const c of t)g[c]=s(c);return g}}),define(ne[30],se([1,0,26]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ThemeIcon=e.ThemeColor=void 0;var k;(function(E){function y(m){return m&&typeof m=="object"&&typeof m.id=="string"}E.isThemeColor=y})(k||(e.ThemeColor=k={}));var I;(function(E){E.iconNameSegment="[A-Za-z0-9]+",E.iconNameExpression="[A-Za-z0-9-]+",E.iconModifierExpression="~[A-Za-z]+",E.iconNameCharacter="[A-Za-z0-9~-]";const y=new RegExp(`^(${E.iconNameExpression})(${E.iconModifierExpression})?$`);function m(c){const l=y.exec(c.id);if(!l)return m(d.Codicon.error);const[,a,r]=l,u=["codicon","codicon-"+a];return r&&u.push("codicon-modifier-"+r.substring(1)),u}E.asClassNameArray=m;function _(c){return m(c).join(" ")}E.asClassName=_;function b(c){return"."+m(c).join(".")}E.asCSSSelector=b;function p(c){return c&&typeof c=="object"&&typeof c.id=="string"&&(typeof c.color>"u"||k.isThemeColor(c.color))}E.isThemeIcon=p;const n=new RegExp(`^\\$\\((${E.iconNameExpression}(?:${E.iconModifierExpression})?)\\)$`);function o(c){const l=n.exec(c);if(!l)return;const[,a]=l;return{id:a}}E.fromString=o;function t(c){return{id:c}}E.fromId=t;function i(c,l){let a=c.id;const r=a.lastIndexOf("~");return r!==-1&&(a=a.substring(0,r)),l&&(a=`${a}~${l}`),{id:a}}E.modify=i;function s(c){const l=c.id.lastIndexOf("~");if(l!==-1)return c.id.substring(l+1)}E.getModifier=s;function g(c,l){return c.id===l.id&&c.color?.id===l.color?.id}E.isEqual=g})(I||(e.ThemeIcon=I={}))}),define(ne[142],se([1,0,82,11,30]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.escapeIcons=_,e.markdownEscapeEscapedIcons=p,e.stripIcons=o,e.getCodiconAriaLabel=t,e.parseLabelWithIcons=s,e.matchesFuzzyIconAware=g;const E="$(",y=new RegExp(`\\$\\(${I.ThemeIcon.iconNameExpression}(?:${I.ThemeIcon.iconModifierExpression})?\\)`,"g"),m=new RegExp(`(\\\\)?${y.source}`,"g");function _(c){return c.replace(m,(l,a)=>a?l:`\\${l}`)}const b=new RegExp(`\\\\${y.source}`,"g");function p(c){return c.replace(b,l=>`\\${l}`)}const n=new RegExp(`(\\s)?(\\\\)?${y.source}(\\s)?`,"g");function o(c){return c.indexOf(E)===-1?c:c.replace(n,(l,a,r,u)=>r?l:a||u||"")}function t(c){return c?c.replace(/\$\((.*?)\)/g,(l,a)=>` ${a} `).trim():""}const i=new RegExp(`\\$\\(${I.ThemeIcon.iconNameCharacter}+\\)`,"g");function s(c){i.lastIndex=0;let l="";const a=[];let r=0;for(;;){const u=i.lastIndex,C=i.exec(c),f=c.substring(u,C?.index);if(f.length>0){l+=f;for(let h=0;h255?255:I|0}function k(I){return I<0?0:I>4294967295?4294967295:I|0}}),define(ne[193],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.generateUuid=void 0,e.generateUuid=function(){if(typeof crypto=="object"&&typeof crypto.randomUUID=="function")return crypto.randomUUID.bind(crypto);let d;typeof crypto=="object"&&typeof crypto.getRandomValues=="function"?d=crypto.getRandomValues.bind(crypto):d=function(E){for(let y=0;yn,asFile:()=>{},value:typeof n=="string"?n:void 0}}function y(n,o,t){const i={id:(0,I.generateUuid)(),name:n,uri:o,data:t};return{asString:async()=>"",asFile:()=>i,value:void 0}}class m{constructor(){this._entries=new Map}get size(){let o=0;for(const t of this._entries)o++;return o}has(o){return this._entries.has(this.toKey(o))}matches(o){const t=[...this._entries.keys()];return k.Iterable.some(this,([i,s])=>s.asFile())&&t.push("files"),p(_(o),t)}get(o){return this._entries.get(this.toKey(o))?.[0]}append(o,t){const i=this._entries.get(o);i?i.push(t):this._entries.set(this.toKey(o),[t])}replace(o,t){this._entries.set(this.toKey(o),[t])}delete(o){this._entries.delete(this.toKey(o))}*[Symbol.iterator](){for(const[o,t]of this._entries)for(const i of t)yield[o,i]}toKey(o){return _(o)}}e.VSDataTransfer=m;function _(n){return n.toLowerCase()}function b(n,o){return p(_(n),o.map(_))}function p(n,o){if(n==="*/*")return o.length>0;if(o.includes(n))return!0;const t=n.match(/^([a-z]+)\/([a-z]+|\*)$/i);if(!t)return!1;const[i,s,g]=t;return g==="*"?o.some(c=>c.startsWith(s+"/")):!1}e.UriList=Object.freeze({create:n=>(0,d.distinct)(n.map(o=>o.toString())).join(`\r `),split:n=>n.split(`\r `),parse:n=>e.UriList.split(n).filter(o=>!o.startsWith("#"))})}),define(ne[302],se([10]),{}),define(ne[458],se([10]),{}),define(ne[459],se([10]),{}),define(ne[460],se([10]),{}),define(ne[461],se([10]),{}),define(ne[195],se([1,0,460,461]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0})}),define(ne[462],se([10]),{}),define(ne[463],se([10]),{}),define(ne[303],se([10]),{}),define(ne[304],se([10]),{}),define(ne[464],se([10]),{}),define(ne[465],se([10]),{}),define(ne[466],se([10]),{}),define(ne[467],se([10]),{}),define(ne[305],se([10]),{}),define(ne[468],se([10]),{}),define(ne[226],se([1,0,468]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME=void 0,e.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME="monaco-mouse-cursor-text"}),define(ne[469],se([10]),{}),define(ne[470],se([10]),{}),define(ne[471],se([10]),{}),define(ne[472],se([10]),{}),define(ne[473],se([10]),{}),define(ne[474],se([10]),{}),define(ne[475],se([10]),{}),define(ne[476],se([10]),{}),define(ne[477],se([10]),{}),define(ne[478],se([10]),{}),define(ne[479],se([10]),{}),define(ne[480],se([10]),{}),define(ne[481],se([10]),{}),define(ne[482],se([10]),{}),define(ne[483],se([10]),{}),define(ne[484],se([10]),{}),define(ne[485],se([10]),{}),define(ne[486],se([10]),{}),define(ne[487],se([10]),{}),define(ne[488],se([10]),{}),define(ne[489],se([10]),{}),define(ne[490],se([10]),{}),define(ne[491],se([10]),{}),define(ne[492],se([10]),{}),define(ne[493],se([10]),{}),define(ne[494],se([10]),{}),define(ne[495],se([10]),{}),define(ne[496],se([10]),{}),define(ne[497],se([10]),{}),define(ne[498],se([10]),{}),define(ne[499],se([10]),{}),define(ne[500],se([10]),{}),define(ne[501],se([10]),{}),define(ne[502],se([10]),{}),define(ne[503],se([10]),{}),define(ne[504],se([10]),{}),define(ne[505],se([10]),{}),define(ne[506],se([10]),{}),define(ne[227],se([10]),{}),define(ne[507],se([10]),{}),define(ne[508],se([10]),{}),define(ne[509],se([10]),{}),define(ne[510],se([10]),{}),define(ne[511],se([10]),{}),define(ne[512],se([10]),{}),define(ne[513],se([10]),{}),define(ne[514],se([10]),{}),define(ne[196],se([10]),{}),define(ne[515],se([10]),{}),define(ne[516],se([10]),{}),define(ne[517],se([10]),{}),define(ne[518],se([10]),{}),define(ne[519],se([10]),{}),define(ne[520],se([10]),{}),define(ne[521],se([10]),{}),define(ne[522],se([10]),{}),define(ne[523],se([10]),{}),define(ne[524],se([10]),{}),define(ne[525],se([10]),{}),define(ne[526],se([10]),{}),define(ne[527],se([10]),{}),define(ne[528],se([10]),{}),define(ne[529],se([10]),{}),define(ne[530],se([10]),{}),define(ne[531],se([10]),{}),define(ne[532],se([10]),{}),define(ne[533],se([10]),{}),define(ne[534],se([10]),{}),define(ne[535],se([10]),{}),define(ne[536],se([10]),{}),define(ne[537],se([10]),{}),define(ne[538],se([10]),{}),define(ne[539],se([10]),{}),define(ne[540],se([10]),{}),define(ne[541],se([10]),{}),define(ne[306],se([10]),{}),define(ne[542],se([10]),{}),define(ne[543],se([10]),{}),define(ne[228],se([10]),{}),define(ne[544],se([10]),{}),define(ne[74],se([1,0,39]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.applyFontInfo=k;function k(I,E){I instanceof d.FastDomNode?(I.setFontFamily(E.getMassagedFontFamily()),I.setFontWeight(E.fontWeight),I.setFontSize(E.fontSize),I.setFontFeatureSettings(E.fontFeatureSettings),I.setFontVariationSettings(E.fontVariationSettings),I.setLineHeight(E.lineHeight),I.setLetterSpacing(E.letterSpacing)):(I.style.fontFamily=E.getMassagedFontFamily(),I.style.fontWeight=E.fontWeight,I.style.fontSize=E.fontSize+"px",I.style.fontFeatureSettings=E.fontFeatureSettings,I.style.fontVariationSettings=E.fontVariationSettings,I.style.lineHeight=E.lineHeight+"px",I.style.letterSpacing=E.letterSpacing+"px")}}),define(ne[545],se([1,0,74]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CharWidthRequest=void 0,e.readCharWidths=E;class k{constructor(m,_){this.chr=m,this.type=_,this.width=0}fulfill(m){this.width=m}}e.CharWidthRequest=k;class I{constructor(m,_){this._bareFontInfo=m,this._requests=_,this._container=null,this._testElements=null}read(m){this._createDomElements(),m.document.body.appendChild(this._container),this._readFromDomElements(),this._container?.remove(),this._container=null,this._testElements=null}_createDomElements(){const m=document.createElement("div");m.style.position="absolute",m.style.top="-50000px",m.style.width="50000px";const _=document.createElement("div");(0,d.applyFontInfo)(_,this._bareFontInfo),m.appendChild(_);const b=document.createElement("div");(0,d.applyFontInfo)(b,this._bareFontInfo),b.style.fontWeight="bold",m.appendChild(b);const p=document.createElement("div");(0,d.applyFontInfo)(p,this._bareFontInfo),p.style.fontStyle="italic",m.appendChild(p);const n=[];for(const o of this._requests){let t;o.type===0&&(t=_),o.type===2&&(t=b),o.type===1&&(t=p),t.appendChild(document.createElement("br"));const i=document.createElement("span");I._render(i,o),t.appendChild(i),n.push(i)}this._container=m,this._testElements=n}static _render(m,_){if(_.chr===" "){let b="\xA0";for(let p=0;p<8;p++)b+=b;m.innerText=b}else{let b=_.chr;for(let p=0;p<8;p++)b+=b;m.textContent=b}}_readFromDomElements(){for(let m=0,_=this._requests.length;m<_;m++){const b=this._requests[m],p=this._testElements[m];b.fulfill(p.offsetWidth/256)}}}function E(y,m,_){new I(m,_).read(y)}}),define(ne[546],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorSettingMigration=void 0,e.migrateOptions=E;class d{static{this.items=[]}constructor(_,b){this.key=_,this.migrate=b}apply(_){const b=d._read(_,this.key),p=o=>d._read(_,o),n=(o,t)=>d._write(_,o,t);this.migrate(b,p,n)}static _read(_,b){if(typeof _>"u")return;const p=b.indexOf(".");if(p>=0){const n=b.substring(0,p);return this._read(_[n],b.substring(p+1))}return _[b]}static _write(_,b,p){const n=b.indexOf(".");if(n>=0){const o=b.substring(0,n);_[o]=_[o]||{},this._write(_[o],b.substring(n+1),p);return}_[b]=p}}e.EditorSettingMigration=d;function k(m,_){d.items.push(new d(m,_))}function I(m,_){k(m,(b,p,n)=>{if(typeof b<"u"){for(const[o,t]of _)if(b===o){n(m,t);return}}})}function E(m){d.items.forEach(_=>_.apply(m))}I("wordWrap",[[!0,"on"],[!1,"off"]]),I("lineNumbers",[[!0,"on"],[!1,"off"]]),I("cursorBlinking",[["visible","solid"]]),I("renderWhitespace",[[!0,"boundary"],[!1,"none"]]),I("renderLineHighlight",[[!0,"line"],[!1,"none"]]),I("acceptSuggestionOnEnter",[[!0,"on"],[!1,"off"]]),I("tabCompletion",[[!1,"off"],[!0,"onlySnippets"]]),I("hover",[[!0,{enabled:!0}],[!1,{enabled:!1}]]),I("parameterHints",[[!0,{enabled:!0}],[!1,{enabled:!1}]]),I("autoIndent",[[!1,"advanced"],[!0,"full"]]),I("matchBrackets",[[!0,"always"],[!1,"never"]]),I("renderFinalNewline",[[!0,"on"],[!1,"off"]]),I("cursorSmoothCaretAnimation",[[!0,"on"],[!1,"off"]]),I("occurrencesHighlight",[[!0,"singleFile"],[!1,"off"]]),I("wordBasedSuggestions",[[!0,"matchingDocuments"],[!1,"off"]]),k("autoClosingBrackets",(m,_,b)=>{m===!1&&(b("autoClosingBrackets","never"),typeof _("autoClosingQuotes")>"u"&&b("autoClosingQuotes","never"),typeof _("autoSurround")>"u"&&b("autoSurround","never"))}),k("renderIndentGuides",(m,_,b)=>{typeof m<"u"&&(b("renderIndentGuides",void 0),typeof _("guides.indentation")>"u"&&b("guides.indentation",!!m))}),k("highlightActiveIndentGuide",(m,_,b)=>{typeof m<"u"&&(b("highlightActiveIndentGuide",void 0),typeof _("guides.highlightActiveIndentation")>"u"&&b("guides.highlightActiveIndentation",!!m))});const y={method:"showMethods",function:"showFunctions",constructor:"showConstructors",deprecated:"showDeprecated",field:"showFields",variable:"showVariables",class:"showClasses",struct:"showStructs",interface:"showInterfaces",module:"showModules",property:"showProperties",event:"showEvents",operator:"showOperators",unit:"showUnits",value:"showValues",constant:"showConstants",enum:"showEnums",enumMember:"showEnumMembers",keyword:"showKeywords",text:"showWords",color:"showColors",file:"showFiles",reference:"showReferences",folder:"showFolders",typeParameter:"showTypeParameters",snippet:"showSnippets"};k("suggest.filteredTypes",(m,_,b)=>{if(m&&typeof m=="object"){for(const p of Object.entries(y))m[p[0]]===!1&&typeof _(`suggest.${p[1]}`)>"u"&&b(`suggest.${p[1]}`,!1);b("suggest.filteredTypes",void 0)}}),k("quickSuggestions",(m,_,b)=>{if(typeof m=="boolean"){const p=m?"on":"off";b("quickSuggestions",{comments:p,strings:p,other:p})}}),k("experimental.stickyScroll.enabled",(m,_,b)=>{typeof m=="boolean"&&(b("experimental.stickyScroll.enabled",void 0),typeof _("stickyScroll.enabled")>"u"&&b("stickyScroll.enabled",m))}),k("experimental.stickyScroll.maxLineCount",(m,_,b)=>{typeof m=="number"&&(b("experimental.stickyScroll.maxLineCount",void 0),typeof _("stickyScroll.maxLineCount")>"u"&&b("stickyScroll.maxLineCount",m))}),k("codeActionsOnSave",(m,_,b)=>{if(m&&typeof m=="object"){let p=!1;const n={};for(const o of Object.entries(m))typeof o[1]=="boolean"?(p=!0,n[o[0]]=o[1]?"explicit":"never"):n[o[0]]=o[1];p&&b("codeActionsOnSave",n)}}),k("codeActionWidget.includeNearbyQuickfixes",(m,_,b)=>{typeof m=="boolean"&&(b("codeActionWidget.includeNearbyQuickfixes",void 0),typeof _("codeActionWidget.includeNearbyQuickFixes")>"u"&&b("codeActionWidget.includeNearbyQuickFixes",m))}),k("lightbulb.enabled",(m,_,b)=>{typeof m=="boolean"&&b("lightbulb.enabled",m?void 0:"off")})}),define(ne[229],se([1,0,6]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TabFocus=void 0;class k{constructor(){this._tabFocus=!1,this._onDidChangeTabFocus=new d.Emitter,this.onDidChangeTabFocus=this._onDidChangeTabFocus.event}getTabFocusMode(){return this._tabFocus}setTabFocusMode(E){this._tabFocus=E,this._onDidChangeTabFocus.fire(this._tabFocus)}}e.TabFocus=new k}),define(ne[143],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StableEditorScrollState=void 0;class d{static capture(I){if(I.getScrollTop()===0||I.hasPendingScrollAnimation())return new d(I.getScrollTop(),I.getContentHeight(),null,0,null);let E=null,y=0;const m=I.getVisibleRanges();if(m.length>0){E=m[0].getStartPosition();const _=I.getTopForPosition(E.lineNumber,E.column);y=I.getScrollTop()-_}return new d(I.getScrollTop(),I.getContentHeight(),E,y,I.getPosition())}constructor(I,E,y,m,_){this._initialScrollTop=I,this._initialContentHeight=E,this._visiblePosition=y,this._visiblePositionScrollDelta=m,this._cursorPosition=_}restore(I){if(!(this._initialContentHeight===I.getContentHeight()&&this._initialScrollTop===I.getScrollTop())&&this._visiblePosition){const E=I.getTopForPosition(this._visiblePosition.lineNumber,this._visiblePosition.column);I.setScrollTop(E+this._visiblePositionScrollDelta)}}restoreRelativeVerticalPositionOfCursor(I){if(this._initialContentHeight===I.getContentHeight()&&this._initialScrollTop===I.getScrollTop())return;const E=I.getPosition();if(!this._cursorPosition||!E)return;const y=I.getTopForLineNumber(E.lineNumber)-I.getTopForLineNumber(this._cursorPosition.lineNumber);I.setScrollTop(I.getScrollTop()+y,1)}}e.StableEditorScrollState=d}),define(ne[164],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.VisibleRanges=e.HorizontalPosition=e.FloatHorizontalRange=e.HorizontalRange=e.LineVisibleRanges=e.RenderingContext=e.RestrictedRenderingContext=void 0;class d{constructor(p,n){this._restrictedRenderingContextBrand=void 0,this._viewLayout=p,this.viewportData=n,this.scrollWidth=this._viewLayout.getScrollWidth(),this.scrollHeight=this._viewLayout.getScrollHeight(),this.visibleRange=this.viewportData.visibleRange,this.bigNumbersDelta=this.viewportData.bigNumbersDelta;const o=this._viewLayout.getCurrentViewport();this.scrollTop=o.top,this.scrollLeft=o.left,this.viewportWidth=o.width,this.viewportHeight=o.height}getScrolledTopFromAbsoluteTop(p){return p-this.scrollTop}getVerticalOffsetForLineNumber(p,n){return this._viewLayout.getVerticalOffsetForLineNumber(p,n)}getVerticalOffsetAfterLineNumber(p,n){return this._viewLayout.getVerticalOffsetAfterLineNumber(p,n)}getDecorationsInViewport(){return this.viewportData.getDecorationsInViewport()}}e.RestrictedRenderingContext=d;class k extends d{constructor(p,n,o){super(p,n),this._renderingContextBrand=void 0,this._viewLines=o}linesVisibleRangesForRange(p,n){return this._viewLines.linesVisibleRangesForRange(p,n)}visibleRangeForPosition(p){return this._viewLines.visibleRangeForPosition(p)}}e.RenderingContext=k;class I{constructor(p,n,o,t){this.outsideRenderedLine=p,this.lineNumber=n,this.ranges=o,this.continuesOnNextLine=t}}e.LineVisibleRanges=I;class E{static from(p){const n=new Array(p.length);for(let o=0,t=p.length;o=n.left?_.width=Math.max(_.width,n.left+n.width-_.left):(y[m++]=_,_=n)}return y[m++]=_,y}static _createHorizontalRangesFromClientRects(E,y,m){if(!E||E.length===0)return null;const _=[];for(let b=0,p=E.length;bo)return null;if(y=Math.min(o,Math.max(0,y)),_=Math.min(o,Math.max(0,_)),y===_&&m===b&&m===0&&!E.children[y].firstChild){const g=E.children[y].getClientRects();return p.markDidDomLayout(),this._createHorizontalRangesFromClientRects(g,p.clientRectDeltaLeft,p.clientRectScale)}y!==_&&_>0&&b===0&&(_--,b=1073741824);let t=E.children[y].firstChild,i=E.children[_].firstChild;if((!t||!i)&&(!t&&m===0&&y>0&&(t=E.children[y-1].firstChild,m=1073741824),!i&&b===0&&_>0&&(i=E.children[_-1].firstChild,b=1073741824)),!t||!i)return null;m=Math.min(t.textContent.length,Math.max(0,m)),b=Math.min(i.textContent.length,Math.max(0,b));const s=this._readClientRects(t,m,i,b,p.endNode);return p.markDidDomLayout(),this._createHorizontalRangesFromClientRects(s,p.clientRectDeltaLeft,p.clientRectScale)}}e.RangeUtil=k}),define(ne[307],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getCharIndex=e.allCharCodes=void 0,e.allCharCodes=(()=>{const k=[];for(let I=32;I<=126;I++)k.push(I);return k.push(65533),k})();const d=(k,I)=>(k-=32,k<0||k>96?I<=2?(k+96)%96:95:k);e.getCharIndex=d}),define(ne[549],se([1,0,307,192]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MinimapCharRenderer=void 0;class I{constructor(y,m){this.scale=m,this._minimapCharRendererBrand=void 0,this.charDataNormal=I.soften(y,12/15),this.charDataLight=I.soften(y,50/60)}static soften(y,m){const _=new Uint8ClampedArray(y.length);for(let b=0,p=y.length;by.width||_+a>y.height){console.warn("bad render request outside image data");return}const r=s?this.charDataLight:this.charDataNormal,u=(0,d.getCharIndex)(b,i),C=y.width*4,f=o.r,h=o.g,v=o.b,w=p.r-f,S=p.g-h,L=p.b-v,D=Math.max(n,t),T=y.data;let M=u*c*l,A=_*C+m*4;for(let P=0;Py.width||_+g>y.height){console.warn("bad render request outside image data");return}const c=y.width*4,l=.5*(p/255),a=n.r,r=n.g,u=n.b,C=b.r-a,f=b.g-r,h=b.b-u,v=a+C*l,w=r+f*l,S=u+h*l,L=Math.max(p,o),D=y.data;let T=_*c+m*4;for(let M=0;M{const y=new Uint8ClampedArray(E.length/2);for(let m=0;m>1]=k[E[m]]<<4|k[E[m+1]]&15;return y};e.prebakedMiniMaps={1:(0,d.createSingleCallFunction)(()=>I("0000511D6300CF609C709645A78432005642574171487021003C451900274D35D762755E8B629C5BA856AF57BA649530C167D1512A272A3F6038604460398526BCA2A968DB6F8957C768BE5FBE2FB467CF5D8D5B795DC7625B5DFF50DE64C466DB2FC47CD860A65E9A2EB96CB54CE06DA763AB2EA26860524D3763536601005116008177A8705E53AB738E6A982F88BAA35B5F5B626D9C636B449B737E5B7B678598869A662F6B5B8542706C704C80736A607578685B70594A49715A4522E792")),2:(0,d.createSingleCallFunction)(()=>I("000000000000000055394F383D2800008B8B1F210002000081B1CBCBCC820000847AAF6B9AAF2119BE08B8881AD60000A44FD07DCCF107015338130C00000000385972265F390B406E2437634B4B48031B12B8A0847000001E15B29A402F0000000000004B33460B00007A752C2A0000000000004D3900000084394B82013400ABA5CFC7AD9C0302A45A3E5A98AB000089A43382D97900008BA54AA087A70A0248A6A7AE6DBE0000BF6F94987EA40A01A06DCFA7A7A9030496C32F77891D0000A99FB1A0AFA80603B29AB9CA75930D010C0948354D3900000C0948354F37460D0028BE673D8400000000AF9D7B6E00002B007AA8933400007AA642675C2700007984CFB9C3985B768772A8A6B7B20000CAAECAAFC4B700009F94A6009F840009D09F9BA4CA9C0000CC8FC76DC87F0000C991C472A2000000A894A48CA7B501079BA2C9C69BA20000B19A5D3FA89000005CA6009DA2960901B0A7F0669FB200009D009E00B7890000DAD0F5D092820000D294D4C48BD10000B5A7A4A3B1A50402CAB6CBA6A2000000B5A7A4A3B1A8044FCDADD19D9CB00000B7778F7B8AAE0803C9AB5D3F5D3F00009EA09EA0BAB006039EA0989A8C7900009B9EF4D6B7C00000A9A7816CACA80000ABAC84705D3F000096DA635CDC8C00006F486F266F263D4784006124097B00374F6D2D6D2D6D4A3A95872322000000030000000000008D8939130000000000002E22A5C9CBC70600AB25C0B5C9B400061A2DB04CA67001082AA6BEBEBFC606002321DACBC19E03087AA08B6768380000282FBAC0B8CA7A88AD25BBA5A29900004C396C5894A6000040485A6E356E9442A32CD17EADA70000B4237923628600003E2DE9C1D7B500002F25BBA5A2990000231DB6AFB4A804023025C0B5CAB588062B2CBDBEC0C706882435A75CA20000002326BD6A82A908048B4B9A5A668000002423A09CB4BB060025259C9D8A7900001C1FCAB2C7C700002A2A9387ABA200002626A4A47D6E9D14333163A0C87500004B6F9C2D643A257049364936493647358A34438355497F1A0000A24C1D590000D38DFFBDD4CD3126"))}}),define(ne[551],se([1,0,549,307,550,192]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MinimapCharRendererFactory=void 0;class y{static create(_,b){if(this.lastCreated&&_===this.lastCreated.scale&&b===this.lastFontFamily)return this.lastCreated;let p;return I.prebakedMiniMaps[_]?p=new d.MinimapCharRenderer(I.prebakedMiniMaps[_](),_):p=y.createFromSampleData(y.createSampleData(b).data,_),this.lastFontFamily=b,this.lastCreated=p,p}static createSampleData(_){const b=document.createElement("canvas"),p=b.getContext("2d");b.style.height="16px",b.height=16,b.width=96*10,b.style.width=96*10+"px",p.fillStyle="#ffffff",p.font=`bold 16px ${_}`,p.textBaseline="middle";let n=0;for(const o of k.allCharCodes)p.fillText(String.fromCharCode(o),n,16/2),n+=10;return p.getImageData(0,0,96*10,16)}static createFromSampleData(_,b){if(_.length!==61440)throw new Error("Unexpected source in MinimapCharRenderer");const n=y._downsample(_,b);return new d.MinimapCharRenderer(n,b)}static _downsampleChar(_,b,p,n,o){const t=1*o,i=2*o;let s=n,g=0;for(let c=0;c0){const g=255/s;for(let c=0;cthis._itemData.get(m).getId()===I.getId())??y[0],this._unused.delete(E),this._itemData.set(E,I),E.setData(I)}return this._used.add(E),{object:E,dispose:()=>{this._used.delete(E),this._unused.size>5?E.dispose():this._unused.add(E)}}}dispose(){for(const I of this._used)I.dispose();for(const I of this._unused)I.dispose();this._used.clear(),this._unused.clear()}}e.ObjectPool=d}),define(ne[308],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.diffEditorDefaultOptions=void 0,e.diffEditorDefaultOptions={enableSplitViewResizing:!0,splitViewDefaultRatio:.5,renderSideBySide:!0,renderMarginRevertIcon:!0,renderGutterMenu:!0,maxComputationTime:5e3,maxFileSize:50,ignoreTrimWhitespace:!0,renderIndicators:!0,originalEditable:!1,diffCodeLens:!1,renderOverviewRuler:!0,diffWordWrap:"inherit",diffAlgorithm:"advanced",accessibilityVerbose:!1,experimental:{showMoves:!1,showEmptyDecorations:!0,useTrueInlineView:!1},hideUnchangedRegions:{enabled:!1,contextLineCount:3,minimumLineCount:3,revealLineCount:20},isInEmbeddedEditor:!1,onlyShowAccessibleDiffViewer:!1,renderSideBySideInlineBreakpoint:900,useInlineViewWhenSpaceIsLimited:!0,compactMode:!1}}),define(ne[165],se([1,0,6]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorZoom=void 0,e.EditorZoom=new class{constructor(){this._zoomLevel=0,this._onDidChangeZoomLevel=new d.Emitter,this.onDidChangeZoomLevel=this._onDidChangeZoomLevel.event}getZoomLevel(){return this._zoomLevel}setZoomLevel(k){k=Math.min(Math.max(-5,k),20),this._zoomLevel!==k&&(this._zoomLevel=k,this._onDidChangeZoomLevel.fire(this._zoomLevel))}}}),define(ne[144],se([1,0,192]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CharacterSet=e.CharacterClassifier=void 0;class k{constructor(y){const m=(0,d.toUint8)(y);this._defaultValue=m,this._asciiMap=k._createAsciiMap(m),this._map=new Map}static _createAsciiMap(y){const m=new Uint8Array(256);return m.fill(y),m}set(y,m){const _=(0,d.toUint8)(m);y>=0&&y<256?this._asciiMap[y]=_:this._map.set(y,_)}get(y){return y>=0&&y<256?this._asciiMap[y]:this._map.get(y)||this._defaultValue}clear(){this._asciiMap.fill(this._defaultValue),this._map.clear()}}e.CharacterClassifier=k;class I{constructor(){this._actual=new k(0)}add(y){this._actual.set(y,1)}has(y){return this._actual.get(y)===1}clear(){return this._actual.clear()}}e.CharacterSet=I}),define(ne[94],se([1,0,11]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CursorColumns=void 0;class k{static _nextVisibleColumn(E,y,m){return E===9?k.nextRenderTabStop(y,m):d.isFullWidthCharacter(E)||d.isEmojiImprecise(E)?y+2:y+1}static visibleColumnFromColumn(E,y,m){const _=Math.min(y-1,E.length),b=E.substring(0,_),p=new d.GraphemeIterator(b);let n=0;for(;!p.eol();){const o=d.getNextCodePoint(b,_,p.offset);p.nextGraphemeLength(),n=this._nextVisibleColumn(o,n,m)}return n}static columnFromVisibleColumn(E,y,m){if(y<=0)return 1;const _=E.length,b=new d.GraphemeIterator(E);let p=0,n=1;for(;!b.eol();){const o=d.getNextCodePoint(E,_,b.offset);b.nextGraphemeLength();const t=this._nextVisibleColumn(o,p,m),i=b.offset+1;if(t>=y){const s=y-p;return t-ym))return new k(y,m)}static ofLength(y){return new k(0,y)}static ofStartAndLength(y,m){return new k(y,y+m)}constructor(y,m){if(this.start=y,this.endExclusive=m,y>m)throw new d.BugIndicatingError(`Invalid range: ${this.toString()}`)}get isEmpty(){return this.start===this.endExclusive}delta(y){return new k(this.start+y,this.endExclusive+y)}deltaStart(y){return new k(this.start+y,this.endExclusive)}deltaEnd(y){return new k(this.start,this.endExclusive+y)}get length(){return this.endExclusive-this.start}toString(){return`[${this.start}, ${this.endExclusive})`}contains(y){return this.start<=y&&y=y.endExclusive}slice(y){return y.slice(this.start,this.endExclusive)}substring(y){return y.substring(this.start,this.endExclusive)}clip(y){if(this.isEmpty)throw new d.BugIndicatingError(`Invalid clipping range: ${this.toString()}`);return Math.max(this.start,Math.min(this.endExclusive-1,y))}clipCyclic(y){if(this.isEmpty)throw new d.BugIndicatingError(`Invalid clipping range: ${this.toString()}`);return y=this.endExclusive?this.start+(y-this.start)%this.length:y}forEach(y){for(let m=this.start;my.toString()).join(", ")}intersectsStrict(y){let m=0;for(;my+m.length,0)}}e.OffsetRangeSet=I}),define(ne[9],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Position=void 0;class d{constructor(I,E){this.lineNumber=I,this.column=E}with(I=this.lineNumber,E=this.column){return I===this.lineNumber&&E===this.column?this:new d(I,E)}delta(I=0,E=0){return this.with(this.lineNumber+I,this.column+E)}equals(I){return d.equals(this,I)}static equals(I,E){return!I&&!E?!0:!!I&&!!E&&I.lineNumber===E.lineNumber&&I.column===E.column}isBefore(I){return d.isBefore(this,I)}static isBefore(I,E){return I.lineNumberm||E===m&&y>_?(this.startLineNumber=m,this.startColumn=_,this.endLineNumber=E,this.endColumn=y):(this.startLineNumber=E,this.startColumn=y,this.endLineNumber=m,this.endColumn=_)}isEmpty(){return k.isEmpty(this)}static isEmpty(E){return E.startLineNumber===E.endLineNumber&&E.startColumn===E.endColumn}containsPosition(E){return k.containsPosition(this,E)}static containsPosition(E,y){return!(y.lineNumberE.endLineNumber||y.lineNumber===E.startLineNumber&&y.columnE.endColumn)}static strictContainsPosition(E,y){return!(y.lineNumberE.endLineNumber||y.lineNumber===E.startLineNumber&&y.column<=E.startColumn||y.lineNumber===E.endLineNumber&&y.column>=E.endColumn)}containsRange(E){return k.containsRange(this,E)}static containsRange(E,y){return!(y.startLineNumberE.endLineNumber||y.endLineNumber>E.endLineNumber||y.startLineNumber===E.startLineNumber&&y.startColumnE.endColumn)}strictContainsRange(E){return k.strictContainsRange(this,E)}static strictContainsRange(E,y){return!(y.startLineNumberE.endLineNumber||y.endLineNumber>E.endLineNumber||y.startLineNumber===E.startLineNumber&&y.startColumn<=E.startColumn||y.endLineNumber===E.endLineNumber&&y.endColumn>=E.endColumn)}plusRange(E){return k.plusRange(this,E)}static plusRange(E,y){let m,_,b,p;return y.startLineNumberE.endLineNumber?(b=y.endLineNumber,p=y.endColumn):y.endLineNumber===E.endLineNumber?(b=y.endLineNumber,p=Math.max(y.endColumn,E.endColumn)):(b=E.endLineNumber,p=E.endColumn),new k(m,_,b,p)}intersectRanges(E){return k.intersectRanges(this,E)}static intersectRanges(E,y){let m=E.startLineNumber,_=E.startColumn,b=E.endLineNumber,p=E.endColumn;const n=y.startLineNumber,o=y.startColumn,t=y.endLineNumber,i=y.endColumn;return mt?(b=t,p=i):b===t&&(p=Math.min(p,i)),m>b||m===b&&_>p?null:new k(m,_,b,p)}equalsRange(E){return k.equalsRange(this,E)}static equalsRange(E,y){return!E&&!y?!0:!!E&&!!y&&E.startLineNumber===y.startLineNumber&&E.startColumn===y.startColumn&&E.endLineNumber===y.endLineNumber&&E.endColumn===y.endColumn}getEndPosition(){return k.getEndPosition(this)}static getEndPosition(E){return new d.Position(E.endLineNumber,E.endColumn)}getStartPosition(){return k.getStartPosition(this)}static getStartPosition(E){return new d.Position(E.startLineNumber,E.startColumn)}toString(){return"["+this.startLineNumber+","+this.startColumn+" -> "+this.endLineNumber+","+this.endColumn+"]"}setEndPosition(E,y){return new k(this.startLineNumber,this.startColumn,E,y)}setStartPosition(E,y){return new k(E,y,this.endLineNumber,this.endColumn)}collapseToStart(){return k.collapseToStart(this)}static collapseToStart(E){return new k(E.startLineNumber,E.startColumn,E.startLineNumber,E.startColumn)}collapseToEnd(){return k.collapseToEnd(this)}static collapseToEnd(E){return new k(E.endLineNumber,E.endColumn,E.endLineNumber,E.endColumn)}delta(E){return new k(this.startLineNumber+E,this.startColumn,this.endLineNumber+E,this.endColumn)}static fromPositions(E,y=E){return new k(E.lineNumber,E.column,y.lineNumber,y.column)}static lift(E){return E?new k(E.startLineNumber,E.startColumn,E.endLineNumber,E.endColumn):null}static isIRange(E){return E&&typeof E.startLineNumber=="number"&&typeof E.startColumn=="number"&&typeof E.endLineNumber=="number"&&typeof E.endColumn=="number"}static areIntersectingOrTouching(E,y){return!(E.endLineNumberE.startLineNumber}toJSON(){return this}}e.Range=k}),define(ne[310],se([1,0,11,4]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PagedScreenReaderStrategy=e.TextAreaState=e._debugComposition=void 0,e._debugComposition=!1;class I{static{this.EMPTY=new I("",0,0,null,void 0)}constructor(m,_,b,p,n){this.value=m,this.selectionStart=_,this.selectionEnd=b,this.selection=p,this.newlineCountBeforeSelection=n}toString(){return`[ <${this.value}>, selectionStart: ${this.selectionStart}, selectionEnd: ${this.selectionEnd}]`}static readFromTextArea(m,_){const b=m.getValue(),p=m.getSelectionStart(),n=m.getSelectionEnd();let o;if(_){const t=b.substring(0,p),i=_.value.substring(0,_.selectionStart);t===i&&(o=_.newlineCountBeforeSelection)}return new I(b,p,n,null,o)}collapseSelection(){return this.selectionStart===this.value.length?this:new I(this.value,this.value.length,this.value.length,null,void 0)}writeToTextArea(m,_,b){e._debugComposition&&console.log(`writeToTextArea ${m}: ${this.toString()}`),_.setValue(m,this.value),b&&_.setSelectionRange(m,this.selectionStart,this.selectionEnd)}deduceEditorPosition(m){if(m<=this.selectionStart){const p=this.value.substring(m,this.selectionStart);return this._finishDeduceEditorPosition(this.selection?.getStartPosition()??null,p,-1)}if(m>=this.selectionEnd){const p=this.value.substring(this.selectionEnd,m);return this._finishDeduceEditorPosition(this.selection?.getEndPosition()??null,p,1)}const _=this.value.substring(this.selectionStart,m);if(_.indexOf("\u2026")===-1)return this._finishDeduceEditorPosition(this.selection?.getStartPosition()??null,_,1);const b=this.value.substring(m,this.selectionEnd);return this._finishDeduceEditorPosition(this.selection?.getEndPosition()??null,b,-1)}_finishDeduceEditorPosition(m,_,b){let p=0,n=-1;for(;(n=_.indexOf(` `,n+1))!==-1;)p++;return[m,b*_.length,p]}static deduceInput(m,_,b){if(!m)return{text:"",replacePrevCharCnt:0,replaceNextCharCnt:0,positionDelta:0};e._debugComposition&&(console.log("------------------------deduceInput"),console.log(`PREVIOUS STATE: ${m.toString()}`),console.log(`CURRENT STATE: ${_.toString()}`));const p=Math.min(d.commonPrefixLength(m.value,_.value),m.selectionStart,_.selectionStart),n=Math.min(d.commonSuffixLength(m.value,_.value),m.value.length-m.selectionEnd,_.value.length-_.selectionEnd),o=m.value.substring(p,m.value.length-n),t=_.value.substring(p,_.value.length-n),i=m.selectionStart-p,s=m.selectionEnd-p,g=_.selectionStart-p,c=_.selectionEnd-p;if(e._debugComposition&&(console.log(`AFTER DIFFING PREVIOUS STATE: <${o}>, selectionStart: ${i}, selectionEnd: ${s}`),console.log(`AFTER DIFFING CURRENT STATE: <${t}>, selectionStart: ${g}, selectionEnd: ${c}`)),g===c){const a=m.selectionStart-p;return e._debugComposition&&console.log(`REMOVE PREVIOUS: ${a} chars`),{text:t,replacePrevCharCnt:a,replaceNextCharCnt:0,positionDelta:0}}const l=s-i;return{text:t,replacePrevCharCnt:l,replaceNextCharCnt:0,positionDelta:0}}static deduceAndroidCompositionInput(m,_){if(!m)return{text:"",replacePrevCharCnt:0,replaceNextCharCnt:0,positionDelta:0};if(e._debugComposition&&(console.log("------------------------deduceAndroidCompositionInput"),console.log(`PREVIOUS STATE: ${m.toString()}`),console.log(`CURRENT STATE: ${_.toString()}`)),m.value===_.value)return{text:"",replacePrevCharCnt:0,replaceNextCharCnt:0,positionDelta:_.selectionEnd-m.selectionEnd};const b=Math.min(d.commonPrefixLength(m.value,_.value),m.selectionEnd),p=Math.min(d.commonSuffixLength(m.value,_.value),m.value.length-m.selectionEnd),n=m.value.substring(b,m.value.length-p),o=_.value.substring(b,_.value.length-p),t=m.selectionStart-b,i=m.selectionEnd-b,s=_.selectionStart-b,g=_.selectionEnd-b;return e._debugComposition&&(console.log(`AFTER DIFFING PREVIOUS STATE: <${n}>, selectionStart: ${t}, selectionEnd: ${i}`),console.log(`AFTER DIFFING CURRENT STATE: <${o}>, selectionStart: ${s}, selectionEnd: ${g}`)),{text:o,replacePrevCharCnt:i,replaceNextCharCnt:n.length-i,positionDelta:g-o.length}}}e.TextAreaState=I;class E{static _getPageOfLine(m,_){return Math.floor((m-1)/_)}static _getRangeForPage(m,_){const b=m*_,p=b+1,n=b+_;return new k.Range(p,1,n+1,1)}static fromEditorSelection(m,_,b,p){const o=E._getPageOfLine(_.startLineNumber,b),t=E._getRangeForPage(o,b),i=E._getPageOfLine(_.endLineNumber,b),s=E._getRangeForPage(i,b);let g=t.intersectRanges(new k.Range(1,1,_.startLineNumber,_.startColumn));if(p&&m.getValueLengthInRange(g,1)>500){const f=m.modifyPosition(g.getEndPosition(),-500);g=k.Range.fromPositions(f,g.getEndPosition())}const c=m.getValueInRange(g,1),l=m.getLineCount(),a=m.getLineMaxColumn(l);let r=s.intersectRanges(new k.Range(_.endLineNumber,_.endColumn,l,a));if(p&&m.getValueLengthInRange(r,1)>500){const f=m.modifyPosition(r.getStartPosition(),500);r=k.Range.fromPositions(r.getStartPosition(),f)}const u=m.getValueInRange(r,1);let C;if(o===i||o+1===i)C=m.getValueInRange(_,1);else{const f=t.intersectRanges(_),h=s.intersectRanges(_);C=m.getValueInRange(f,1)+"\u2026"+m.getValueInRange(h,1)}return p&&C.length>2*500&&(C=C.substring(0,500)+"\u2026"+C.substring(C.length-500,C.length)),new I(c+C+u,c.length,c.length+C.length,_,g.endLineNumber-g.startLineNumber)}}e.PagedScreenReaderStrategy=E}),define(ne[75],se([1,0,4]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditOperation=void 0;class k{static insert(E,y){return{range:new d.Range(E.lineNumber,E.column,E.lineNumber,E.column),text:y,forceMoveMarkers:!0}}static delete(E){return{range:E,text:null}}static replace(E,y){return{range:E,text:y}}static replaceMove(E,y){return{range:E,text:y,forceMoveMarkers:!0}}}e.EditOperation=k}),define(ne[554],se([1,0,11,75,4]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TrimTrailingWhitespaceCommand=void 0,e.trimTrailingWhitespace=y;class E{constructor(_,b,p){this._selection=_,this._cursors=b,this._selectionId=null,this._trimInRegexesAndStrings=p}getEditOperations(_,b){const p=y(_,this._cursors,this._trimInRegexesAndStrings);for(let n=0,o=p.length;ni.lineNumber===s.lineNumber?i.column-s.column:i.lineNumber-s.lineNumber);for(let i=_.length-2;i>=0;i--)_[i].lineNumber===_[i+1].lineNumber&&_.splice(i,1);const p=[];let n=0,o=0;const t=_.length;for(let i=1,s=m.getLineCount();i<=s;i++){const g=m.getLineContent(i),c=g.length+1;let l=0;if(op)throw new d.BugIndicatingError(`startLineNumber ${b} cannot be after endLineNumberExclusive ${p}`);this.startLineNumber=b,this.endLineNumberExclusive=p}contains(b){return this.startLineNumber<=b&&bo.endLineNumberExclusive>=b.startLineNumber),n=(0,E.findLastIdxMonotonous)(this._normalizedRanges,o=>o.startLineNumber<=b.endLineNumberExclusive)+1;if(p===n)this._normalizedRanges.splice(p,0,b);else if(p===n-1){const o=this._normalizedRanges[p];this._normalizedRanges[p]=o.join(b)}else{const o=this._normalizedRanges[p].join(this._normalizedRanges[n-1]).join(b);this._normalizedRanges.splice(p,n-p,o)}}contains(b){const p=(0,E.findLastMonotonous)(this._normalizedRanges,n=>n.startLineNumber<=b);return!!p&&p.endLineNumberExclusive>b}intersects(b){const p=(0,E.findLastMonotonous)(this._normalizedRanges,n=>n.startLineNumberb.startLineNumber}getUnion(b){if(this._normalizedRanges.length===0)return b;if(b._normalizedRanges.length===0)return this;const p=[];let n=0,o=0,t=null;for(;n=i.startLineNumber?t=new y(t.startLineNumber,Math.max(t.endLineNumberExclusive,i.endLineNumberExclusive)):(p.push(t),t=i)}return t!==null&&p.push(t),new m(p)}subtractFrom(b){const p=(0,E.findFirstIdxMonotonousOrArrLen)(this._normalizedRanges,i=>i.endLineNumberExclusive>=b.startLineNumber),n=(0,E.findLastIdxMonotonous)(this._normalizedRanges,i=>i.startLineNumber<=b.endLineNumberExclusive)+1;if(p===n)return new m([b]);const o=[];let t=b.startLineNumber;for(let i=p;it&&o.push(new y(t,s.startLineNumber)),t=s.endLineNumberExclusive}return tb.toString()).join(", ")}getIntersection(b){const p=[];let n=0,o=0;for(;np.delta(b)))}}e.LineRangeSet=m}),define(ne[311],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RGBA8=void 0;class d{static{this.Empty=new d(0,0,0,0)}constructor(I,E,y,m){this._rgba8Brand=void 0,this.r=d._clamp(I),this.g=d._clamp(E),this.b=d._clamp(y),this.a=d._clamp(m)}equals(I){return this.r===I.r&&this.g===I.g&&this.b===I.b&&this.a===I.a}static _clamp(I){return I<0?0:I>255?255:I|0}}e.RGBA8=d}),define(ne[23],se([1,0,9,4]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Selection=void 0;class I extends k.Range{constructor(y,m,_,b){super(y,m,_,b),this.selectionStartLineNumber=y,this.selectionStartColumn=m,this.positionLineNumber=_,this.positionColumn=b}toString(){return"["+this.selectionStartLineNumber+","+this.selectionStartColumn+" -> "+this.positionLineNumber+","+this.positionColumn+"]"}equalsSelection(y){return I.selectionsEqual(this,y)}static selectionsEqual(y,m){return y.selectionStartLineNumber===m.selectionStartLineNumber&&y.selectionStartColumn===m.selectionStartColumn&&y.positionLineNumber===m.positionLineNumber&&y.positionColumn===m.positionColumn}getDirection(){return this.selectionStartLineNumber===this.startLineNumber&&this.selectionStartColumn===this.startColumn?0:1}setEndPosition(y,m){return this.getDirection()===0?new I(this.startLineNumber,this.startColumn,y,m):new I(y,m,this.startLineNumber,this.startColumn)}getPosition(){return new d.Position(this.positionLineNumber,this.positionColumn)}getSelectionStart(){return new d.Position(this.selectionStartLineNumber,this.selectionStartColumn)}setStartPosition(y,m){return this.getDirection()===0?new I(y,m,this.endLineNumber,this.endColumn):new I(this.endLineNumber,this.endColumn,y,m)}static fromPositions(y,m=y){return new I(y.lineNumber,y.column,m.lineNumber,m.column)}static fromRange(y,m){return m===0?new I(y.startLineNumber,y.startColumn,y.endLineNumber,y.endColumn):new I(y.endLineNumber,y.endColumn,y.startLineNumber,y.startColumn)}static liftSelection(y){return new I(y.selectionStartLineNumber,y.selectionStartColumn,y.positionLineNumber,y.positionColumn)}static selectionsArrEqual(y,m){if(y&&!m||!y&&m)return!1;if(!y&&!m)return!0;if(y.length!==m.length)return!1;for(let _=0,b=y.length;_{const g=b._map.get(t);g&&(b._map.delete(t),g.dispose(),s.dispose())})}return i}_beginUpdate(){this._updateCounter++,this._updateCounter===1&&(this._currentTransaction=new E.TransactionImpl(()=>{}))}_endUpdate(){if(this._updateCounter--,this._updateCounter===0){const t=this._currentTransaction;this._currentTransaction=void 0,t.finish()}}constructor(t){super(),this.editor=t,this._updateCounter=0,this._currentTransaction=void 0,this._model=(0,I.observableValue)(this,this.editor.getModel()),this.model=this._model,this.isReadonly=(0,I.observableFromEvent)(this,this.editor.onDidChangeConfiguration,()=>this.editor.getOption(92)),this._versionId=(0,I.observableValueOpts)({owner:this,lazy:!0},this.editor.getModel()?.getVersionId()??null),this.versionId=this._versionId,this._selections=(0,I.observableValueOpts)({owner:this,equalsFn:(0,d.equalsIfDefined)((0,d.itemsEquals)(m.Selection.selectionsEqual)),lazy:!0},this.editor.getSelections()??null),this.selections=this._selections,this.isFocused=(0,I.observableFromEvent)(this,i=>{const s=this.editor.onDidFocusEditorWidget(i),g=this.editor.onDidBlurEditorWidget(i);return{dispose(){s.dispose(),g.dispose()}}},()=>this.editor.hasWidgetFocus()),this.value=(0,y.derivedWithSetter)(this,i=>(this.versionId.read(i),this.model.read(i)?.getValue()??""),(i,s)=>{const g=this.model.get();g!==null&&i!==g.getValue()&&g.setValue(i)}),this.valueIsEmpty=(0,I.derived)(this,i=>(this.versionId.read(i),this.editor.getModel()?.getValueLength()===0)),this.cursorSelection=(0,I.derivedOpts)({owner:this,equalsFn:(0,d.equalsIfDefined)(m.Selection.selectionsEqual)},i=>this.selections.read(i)?.[0]??null),this.onDidType=(0,I.observableSignal)(this),this.scrollTop=(0,I.observableFromEvent)(this.editor.onDidScrollChange,()=>this.editor.getScrollTop()),this.scrollLeft=(0,I.observableFromEvent)(this.editor.onDidScrollChange,()=>this.editor.getScrollLeft()),this.layoutInfo=(0,I.observableFromEvent)(this.editor.onDidLayoutChange,()=>this.editor.getLayoutInfo()),this.layoutInfoContentLeft=this.layoutInfo.map(i=>i.contentLeft),this.layoutInfoDecorationsLeft=this.layoutInfo.map(i=>i.decorationsLeft),this.contentWidth=(0,I.observableFromEvent)(this.editor.onDidContentSizeChange,()=>this.editor.getContentWidth()),this._overlayWidgetCounter=0,this._register(this.editor.onBeginUpdate(()=>this._beginUpdate())),this._register(this.editor.onEndUpdate(()=>this._endUpdate())),this._register(this.editor.onDidChangeModel(()=>{this._beginUpdate();try{this._model.set(this.editor.getModel(),this._currentTransaction),this._forceUpdate()}finally{this._endUpdate()}})),this._register(this.editor.onDidType(i=>{this._beginUpdate();try{this._forceUpdate(),this.onDidType.trigger(this._currentTransaction,i)}finally{this._endUpdate()}})),this._register(this.editor.onDidChangeModelContent(i=>{this._beginUpdate();try{this._versionId.set(this.editor.getModel()?.getVersionId()??null,this._currentTransaction,i),this._forceUpdate()}finally{this._endUpdate()}})),this._register(this.editor.onDidChangeCursorSelection(i=>{this._beginUpdate();try{this._selections.set(this.editor.getSelections(),this._currentTransaction,i),this._forceUpdate()}finally{this._endUpdate()}}))}forceUpdate(t){this._beginUpdate();try{return this._forceUpdate(),t?t(this._currentTransaction):void 0}finally{this._endUpdate()}}_forceUpdate(){this._beginUpdate();try{this._model.set(this.editor.getModel(),this._currentTransaction),this._versionId.set(this.editor.getModel()?.getVersionId()??null,this._currentTransaction,void 0),this._selections.set(this.editor.getSelections(),this._currentTransaction,void 0)}finally{this._endUpdate()}}getOption(t){return(0,I.observableFromEvent)(this,i=>this.editor.onDidChangeConfiguration(s=>{s.hasChanged(t)&&i(void 0)}),()=>this.editor.getOption(t))}setDecorations(t){const i=new k.DisposableStore,s=this.editor.createDecorationsCollection();return i.add((0,I.autorunOpts)({owner:this,debugName:()=>`Apply decorations from ${t.debugName}`},g=>{const c=t.read(g);s.set(c)})),i.add({dispose:()=>{s.clear()}}),i}createOverlayWidget(t){const i="observableOverlayWidget"+this._overlayWidgetCounter++,s={getDomNode:()=>t.domNode,getPosition:()=>t.position.get(),getId:()=>i,allowEditorOverflow:t.allowEditorOverflow,getMinContentWidthInPx:()=>t.minContentWidthInPx.get()};this.editor.addOverlayWidget(s);const g=(0,I.autorun)(c=>{t.position.read(c),t.minContentWidthInPx.read(c),this.editor.layoutOverlayWidget(s)});return(0,k.toDisposable)(()=>{g.dispose(),this.editor.removeOverlayWidget(s)})}}e.ObservableCodeEditor=b;function p(o,t){return(0,I.autorunWithStoreHandleChanges)({createEmptyChangeSummary:()=>({deltas:[],didChange:!1}),handleChange:(i,s)=>{if(i.didChange(o)){const g=i.change;g!==void 0&&s.deltas.push(g),s.didChange=!0}return!0}},(i,s)=>{const g=o.read(i);s.didChange&&t(g,s.deltas)})}function n(o,t){const i=new k.DisposableStore,s=p(o,(g,c)=>{i.clear(),t(g,c,i)});return{dispose(){s.dispose(),i.dispose()}}}}),define(ne[146],se([1,0,23]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ReplaceCommandThatPreservesSelection=e.ReplaceCommandWithOffsetCursorState=e.ReplaceCommandWithoutChangingPosition=e.ReplaceCommandThatSelectsText=e.ReplaceCommand=void 0;class k{constructor(b,p,n=!1){this._range=b,this._text=p,this.insertsAutoWhitespace=n}getEditOperations(b,p){p.addTrackedEditOperation(this._range,this._text)}computeCursorState(b,p){const o=p.getInverseEditOperations()[0].range;return d.Selection.fromPositions(o.getEndPosition())}}e.ReplaceCommand=k;class I{constructor(b,p){this._range=b,this._text=p}getEditOperations(b,p){p.addTrackedEditOperation(this._range,this._text)}computeCursorState(b,p){const o=p.getInverseEditOperations()[0].range;return d.Selection.fromRange(o,0)}}e.ReplaceCommandThatSelectsText=I;class E{constructor(b,p,n=!1){this._range=b,this._text=p,this.insertsAutoWhitespace=n}getEditOperations(b,p){p.addTrackedEditOperation(this._range,this._text)}computeCursorState(b,p){const o=p.getInverseEditOperations()[0].range;return d.Selection.fromPositions(o.getStartPosition())}}e.ReplaceCommandWithoutChangingPosition=E;class y{constructor(b,p,n,o,t=!1){this._range=b,this._text=p,this._columnDeltaOffset=o,this._lineNumberDeltaOffset=n,this.insertsAutoWhitespace=t}getEditOperations(b,p){p.addTrackedEditOperation(this._range,this._text)}computeCursorState(b,p){const o=p.getInverseEditOperations()[0].range;return d.Selection.fromPositions(o.getEndPosition().delta(this._lineNumberDeltaOffset,this._columnDeltaOffset))}}e.ReplaceCommandWithOffsetCursorState=y;class m{constructor(b,p,n,o=!1){this._range=b,this._text=p,this._initialSelection=n,this._forceMoveMarkers=o,this._selectionId=null}getEditOperations(b,p){p.addTrackedEditOperation(this._range,this._text,this._forceMoveMarkers),this._selectionId=p.trackSelection(this._initialSelection)}computeCursorState(b,p){return p.getTrackedSelection(this._selectionId)}}e.ReplaceCommandThatPreservesSelection=m}),define(ne[312],se([1,0,4,23]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CompositionSurroundSelectionCommand=e.SurroundSelectionCommand=void 0;class I{constructor(m,_,b){this._range=m,this._charBeforeSelection=_,this._charAfterSelection=b}getEditOperations(m,_){_.addTrackedEditOperation(new d.Range(this._range.startLineNumber,this._range.startColumn,this._range.startLineNumber,this._range.startColumn),this._charBeforeSelection),_.addTrackedEditOperation(new d.Range(this._range.endLineNumber,this._range.endColumn,this._range.endLineNumber,this._range.endColumn),this._charAfterSelection)}computeCursorState(m,_){const b=_.getInverseEditOperations(),p=b[0].range,n=b[1].range;return new k.Selection(p.endLineNumber,p.endColumn,n.endLineNumber,n.endColumn-this._charAfterSelection.length)}}e.SurroundSelectionCommand=I;class E{constructor(m,_,b){this._position=m,this._text=_,this._charAfter=b}getEditOperations(m,_){_.addTrackedEditOperation(new d.Range(this._position.lineNumber,this._position.column,this._position.lineNumber,this._position.column),this._text+this._charAfter)}computeCursorState(m,_){const p=_.getInverseEditOperations()[0].range;return new k.Selection(p.endLineNumber,p.startColumn,p.endLineNumber,p.endColumn-this._charAfter.length)}}e.CompositionSurroundSelectionCommand=E}),define(ne[113],se([1,0,9,4]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TextLength=void 0;class I{static{this.zero=new I(0,0)}static betweenPositions(y,m){return y.lineNumber===m.lineNumber?new I(0,m.column-y.column):new I(m.lineNumber-y.lineNumber,m.column-1)}static ofRange(y){return I.betweenPositions(y.getStartPosition(),y.getEndPosition())}static ofText(y){let m=0,_=0;for(const b of y)b===` `?(m++,_=0):_++;return new I(m,_)}constructor(y,m){this.lineCount=y,this.columnCount=m}isGreaterThanOrEqualTo(y){return this.lineCount!==y.lineCount?this.lineCount>y.lineCount:this.columnCount>=y.columnCount}createRange(y){return this.lineCount===0?new k.Range(y.lineNumber,y.column,y.lineNumber,y.column+this.columnCount):new k.Range(y.lineNumber,y.column,y.lineNumber+this.lineCount,this.columnCount+1)}addToPosition(y){return this.lineCount===0?new d.Position(y.lineNumber,y.column+this.columnCount):new d.Position(y.lineNumber+this.lineCount,this.columnCount+1)}toString(){return`${this.lineCount},${this.columnCount}`}}e.TextLength=I}),define(ne[555],se([1,0,68,113]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PositionOffsetTransformer=void 0;class I{constructor(y){this.text=y,this.lineStartOffsetByLineIdx=[],this.lineStartOffsetByLineIdx.push(0);for(let m=0;m(0,d.checkAdjacentItems)(i,(s,g)=>s.range.getEndPosition().isBeforeOrEqual(g.range.getStartPosition())))}apply(i){let s="",g=new I.Position(1,1);for(const l of this.edits){const a=l.range,r=a.getStartPosition(),u=a.getEndPosition(),C=p(g,r);C.isEmpty()||(s+=i.getValueOfRange(C)),s+=l.text,g=u}const c=p(g,i.endPositionExclusive);return c.isEmpty()||(s+=i.getValueOfRange(c)),s}applyToString(i){const s=new o(i);return this.apply(s)}getNewRanges(){const i=[];let s=0,g=0,c=0;for(const l of this.edits){const a=m.TextLength.ofText(l.text),r=I.Position.lift({lineNumber:l.range.startLineNumber+g,column:l.range.startColumn+(l.range.startLineNumber===s?c:0)}),u=a.createRange(r);i.push(u),g=u.endLineNumber-l.range.endLineNumber,c=u.endColumn-l.range.endColumn,s=l.range.endLineNumber}return i}}e.TextEdit=_;class b{constructor(i,s){this.range=i,this.text=s}toSingleEditOperation(){return{range:this.range,text:this.text}}}e.SingleTextEdit=b;function p(t,i){if(t.lineNumber===i.lineNumber&&t.column===Number.MAX_SAFE_INTEGER)return y.Range.fromPositions(i,i);if(!t.isBeforeOrEqual(i))throw new k.BugIndicatingError("start must be before end");return new y.Range(t.lineNumber,t.column,i.lineNumber,i.column)}class n{get endPositionExclusive(){return this.length.addToPosition(new I.Position(1,1))}}e.AbstractText=n;class o extends n{constructor(i){super(),this.value=i,this._t=new E.PositionOffsetTransformer(this.value)}getValueOfRange(i){return this._t.getOffsetRange(i).substring(this.value)}get length(){return this._t.textLength}}e.StringText=o}),define(ne[197],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EDITOR_MODEL_DEFAULTS=void 0,e.EDITOR_MODEL_DEFAULTS={tabSize:4,indentSize:4,insertSpaces:!0,detectIndentation:!0,trimAutoWhitespace:!0,largeFileOptimizations:!0,bracketPairColorizationOptions:{enabled:!0,independentColorPoolPerBracketType:!1}}}),define(ne[166],se([1,0,45,144]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.WordCharacterClassifier=void 0,e.getMapForWordSeparators=y;class I extends k.CharacterClassifier{constructor(_,b){super(0),this._segmenter=null,this._cachedLine=null,this._cachedSegments=[],this.intlSegmenterLocales=b,this.intlSegmenterLocales.length>0?this._segmenter=new Intl.Segmenter(this.intlSegmenterLocales,{granularity:"word"}):this._segmenter=null;for(let p=0,n=_.length;pb)break;p=n}return p}findNextIntlWordAtOrAfterOffset(_,b){for(const p of this._getIntlSegmenterWordsOnLine(_))if(!(p.index/?";function I(b=""){let p="(-?\\d*\\.\\d\\w*)|([^";for(const n of e.USUAL_WORD_SEPARATORS)b.indexOf(n)>=0||(p+="\\"+n);return p+="\\s]+)",new RegExp(p,"g")}e.DEFAULT_WORD_REGEXP=I();function E(b){let p=e.DEFAULT_WORD_REGEXP;if(b&&b instanceof RegExp)if(b.global)p=b;else{let n="g";b.ignoreCase&&(n+="i"),b.multiline&&(n+="m"),b.unicode&&(n+="u"),p=new RegExp(b.source,n)}return p.lastIndex=0,p}const y=new k.LinkedList;y.unshift({maxLen:1e3,windowSize:15,timeBudget:150});function m(b,p,n,o,t){if(p=E(p),t||(t=d.Iterable.first(y)),n.length>t.maxLen){let l=b-t.maxLen/2;return l<0?l=0:o+=l,n=n.substring(l,b+t.maxLen/2),m(b,p,n,o,t)}const i=Date.now(),s=b-1-o;let g=-1,c=null;for(let l=1;!(Date.now()-i>=t.timeBudget);l++){const a=s-t.windowSize*l;p.lastIndex=Math.max(0,a);const r=_(p,n,s,g);if(!r&&c||(c=r,a<=0))break;g=a}if(c){const l={word:c[0],startColumn:o+1+c.index,endColumn:o+1+c.index+c[0].length};return p.lastIndex=0,l}return null}function _(b,p,n,o){let t;for(;t=b.exec(p);){const i=t.index||0;if(i<=n&&b.lastIndex>=n)return t;if(o>0&&i>o)return null}return null}}),define(ne[313],se([1,0,94]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AtomicTabMoveOperations=void 0;class k{static whitespaceVisibleColumn(E,y,m){const _=E.length;let b=0,p=-1,n=-1;for(let o=0;o<_;o++){if(o===y)return[p,n,b];switch(b%m===0&&(p=o,n=b),E.charCodeAt(o)){case 32:b+=1;break;case 9:b=d.CursorColumns.nextRenderTabStop(b,m);break;default:return[-1,-1,-1]}}return y===_?[p,n,b]:[-1,-1,-1]}static atomicPosition(E,y,m,_){const b=E.length,[p,n,o]=k.whitespaceVisibleColumn(E,y,m);if(o===-1)return-1;let t;switch(_){case 0:t=!0;break;case 1:t=!1;break;case 2:if(o%m===0)return y;t=o%m<=m/2;break}if(t){if(p===-1)return-1;let g=n;for(let c=p;c{t.push(y.fromOffsetPairs(i?i.getEndExclusives():m.zero,s?s.getStarts():new m(o,(i?i.seq2Range.endExclusive-i.seq1Range.endExclusive:0)+o)))}),t}static fromOffsetPairs(n,o){return new y(new I.OffsetRange(n.offset1,o.offset1),new I.OffsetRange(n.offset2,o.offset2))}static assertSorted(n){let o;for(const t of n){if(o&&!(o.seq1Range.endExclusive<=t.seq1Range.start&&o.seq2Range.endExclusive<=t.seq2Range.start))throw new k.BugIndicatingError("Sequence diffs must be sorted");o=t}}constructor(n,o){this.seq1Range=n,this.seq2Range=o}swap(){return new y(this.seq2Range,this.seq1Range)}toString(){return`${this.seq1Range} <-> ${this.seq2Range}`}join(n){return new y(this.seq1Range.join(n.seq1Range),this.seq2Range.join(n.seq2Range))}delta(n){return n===0?this:new y(this.seq1Range.delta(n),this.seq2Range.delta(n))}deltaStart(n){return n===0?this:new y(this.seq1Range.deltaStart(n),this.seq2Range.deltaStart(n))}deltaEnd(n){return n===0?this:new y(this.seq1Range.deltaEnd(n),this.seq2Range.deltaEnd(n))}intersect(n){const o=this.seq1Range.intersect(n.seq1Range),t=this.seq2Range.intersect(n.seq2Range);if(!(!o||!t))return new y(o,t)}getStarts(){return new m(this.seq1Range.start,this.seq2Range.start)}getEndExclusives(){return new m(this.seq1Range.endExclusive,this.seq2Range.endExclusive)}}e.SequenceDiff=y;class m{static{this.zero=new m(0,0)}static{this.max=new m(Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER)}constructor(n,o){this.offset1=n,this.offset2=o}toString(){return`${this.offset1} <-> ${this.offset2}`}delta(n){return n===0?this:new m(this.offset1+n,this.offset2+n)}equals(n){return this.offset1===n.offset1&&this.offset2===n.offset2}}e.OffsetPair=m;class _{static{this.instance=new _}isValid(){return!0}}e.InfiniteTimeout=_;class b{constructor(n){if(this.timeout=n,this.startTime=Date.now(),this.valid=!0,n<=0)throw new k.BugIndicatingError("timeout must be positive")}isValid(){if(!(Date.now()-this.startTimeo.length||D>t.length)continue;const T=i(L,D);g.set(l,T);const M=L===w?c.get(l+1):c.get(l-1);if(c.set(l,T!==L?new E(M,L,D,T-L):M),g.get(l)===o.length&&g.get(l)-l===t.length)break e}}let a=c.get(l);const r=[];let u=o.length,C=t.length;for(;;){const f=a?a.x+a.length:0,h=a?a.y+a.length:0;if((f!==u||h!==C)&&r.push(new k.SequenceDiff(new d.OffsetRange(f,u),new d.OffsetRange(h,C))),!a)break;u=a.x,C=a.y,a=a.prev}return r.reverse(),new k.DiffAlgorithmResult(r,!1)}}e.MyersDiffAlgorithm=I;class E{constructor(b,p,n,o){this.prev=b,this.x=p,this.y=n,this.length=o}}class y{constructor(){this.positiveArr=new Int32Array(10),this.negativeArr=new Int32Array(10)}get(b){return b<0?(b=-b-1,this.negativeArr[b]):this.positiveArr[b]}set(b,p){if(b<0){if(b=-b-1,b>=this.negativeArr.length){const n=this.negativeArr;this.negativeArr=new Int32Array(n.length*2),this.negativeArr.set(n)}this.negativeArr[b]=p}else{if(b>=this.positiveArr.length){const n=this.positiveArr;this.positiveArr=new Int32Array(n.length*2),this.positiveArr.set(n)}this.positiveArr[b]=p}}}class m{constructor(){this.positiveArr=[],this.negativeArr=[]}get(b){return b<0?(b=-b-1,this.negativeArr[b]):this.positiveArr[b]}set(b,p){b<0?(b=-b-1,this.negativeArr[b]=p):this.positiveArr[b]=p}}}),define(ne[315],se([1,0,13,68,167]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.optimizeSequenceDiffs=E,e.removeShortMatches=b,e.extendDiffsToEntireWordIfAppropriate=p,e.removeVeryShortMatchingLinesBetweenDiffs=o,e.removeVeryShortMatchingTextBetweenLongDiffs=t;function E(i,s,g){let c=g;return c=y(i,s,c),c=y(i,s,c),c=m(i,s,c),c}function y(i,s,g){if(g.length===0)return g;const c=[];c.push(g[0]);for(let a=1;a0&&(u=u.delta(f))}l.push(u)}return c.length>0&&l.push(c[c.length-1]),l}function m(i,s,g){if(!i.getBoundaryScore||!s.getBoundaryScore)return g;for(let c=0;c0?g[c-1]:void 0,a=g[c],r=c+1=c.start&&i.seq2Range.start-r>=l.start&&g.isStronglyEqual(i.seq2Range.start-r,i.seq2Range.endExclusive-r)&&r<100;)r++;r--;let u=0;for(;i.seq1Range.start+uf&&(f=L,C=h)}return i.delta(C)}function b(i,s,g){const c=[];for(const l of g){const a=c[c.length-1];if(!a){c.push(l);continue}l.seq1Range.start-a.seq1Range.endExclusive<=2||l.seq2Range.start-a.seq2Range.endExclusive<=2?c[c.length-1]=new I.SequenceDiff(a.seq1Range.join(l.seq1Range),a.seq2Range.join(l.seq2Range)):c.push(l)}return c}function p(i,s,g){const c=I.SequenceDiff.invert(g,i.length),l=[];let a=new I.OffsetPair(0,0);function r(C,f){if(C.offset10;){const T=c[0];if(!(T.seq1Range.intersects(w.seq1Range)||T.seq2Range.intersects(w.seq2Range)))break;const A=i.findWordContaining(T.seq1Range.start),P=s.findWordContaining(T.seq2Range.start),N=new I.SequenceDiff(A,P),O=N.intersect(T);if(L+=O.seq1Range.length,D+=O.seq2Range.length,w=w.join(N),w.seq1Range.endExclusive>=T.seq1Range.endExclusive)c.shift();else break}L+D<(w.seq1Range.length+w.seq2Range.length)*2/3&&l.push(w),a=w.getEndExclusives()}for(;c.length>0;){const C=c.shift();C.seq1Range.isEmpty||(r(C.getStarts(),C),r(C.getEndExclusives().delta(-1),C))}return n(g,l)}function n(i,s){const g=[];for(;i.length>0||s.length>0;){const c=i[0],l=s[0];let a;c&&(!l||c.seq1Range.start0&&g[g.length-1].seq1Range.endExclusive>=a.seq1Range.start?g[g.length-1]=g[g.length-1].join(a):g.push(a)}return g}function o(i,s,g){let c=g;if(c.length===0)return c;let l=0,a;do{a=!1;const r=[c[0]];for(let u=1;u5||S.seq1Range.length+S.seq2Range.length>5)};const C=c[u],f=r[r.length-1];h(f,C)?(a=!0,r[r.length-1]=r[r.length-1].join(C)):r.push(C)}c=r}while(l++<10&&a);return c}function t(i,s,g){let c=g;if(c.length===0)return c;let l=0,a;do{a=!1;const u=[c[0]];for(let C=1;C5||D.length>500)return!1;const M=i.getText(D).trim();if(M.length>20||M.split(/\r\n|\r|\n/).length>1)return!1;const A=i.countLinesIn(S.seq1Range),P=S.seq1Range.length,N=s.countLinesIn(S.seq2Range),O=S.seq2Range.length,F=i.countLinesIn(L.seq1Range),x=L.seq1Range.length,W=s.countLinesIn(L.seq2Range),V=L.seq2Range.length,q=2*40+50;function H(z){return Math.min(z,q)}return Math.pow(Math.pow(H(A*40+P),1.5)+Math.pow(H(N*40+O),1.5),1.5)+Math.pow(Math.pow(H(F*40+x),1.5)+Math.pow(H(W*40+V),1.5),1.5)>(q**1.5)**1.5*1.3};const f=c[C],h=u[u.length-1];v(h,f)?(a=!0,u[u.length-1]=u[u.length-1].join(f)):u.push(f)}c=u}while(l++<10&&a);const r=[];return(0,d.forEachWithNeighbors)(c,(u,C,f)=>{let h=C;function v(M){return M.length>0&&M.trim().length<=3&&C.seq1Range.length+C.seq2Range.length>100}const w=i.extendToFullLines(C.seq1Range),S=i.getText(new k.OffsetRange(w.start,C.seq1Range.start));v(S)&&(h=h.deltaStart(-S.length));const L=i.getText(new k.OffsetRange(C.seq1Range.endExclusive,w.endExclusive));v(L)&&(h=h.deltaEnd(L.length));const D=I.SequenceDiff.fromOffsetPairs(u?u.getEndExclusives():I.OffsetPair.zero,f?f.getStarts():I.OffsetPair.max),T=h.intersect(D);r.length>0&&T.getStarts().equals(r[r.length-1].getEndExclusives())?r[r.length-1]=r[r.length-1].join(T):r.push(T)}),r}}),define(ne[557],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LineSequence=void 0;class d{constructor(E,y){this.trimmedHash=E,this.lines=y}getElement(E){return this.trimmedHash[E]}get length(){return this.trimmedHash.length}getBoundaryScore(E){const y=E===0?0:k(this.lines[E-1]),m=E===this.lines.length?0:k(this.lines[E]);return 1e3-(y+m)}getText(E){return this.lines.slice(E.start,E.endExclusive).join(` `)}isStronglyEqual(E,y){return this.lines[E]===this.lines[y]}}e.LineSequence=d;function k(I){let E=0;for(;E0&&u>0&&o.get(r-1,u-1)===3&&(h+=t.get(r-1,u-1)),h+=p?p(r,u):1):h=-1;const v=Math.max(C,f,h);if(v===h){const w=r>0&&u>0?t.get(r-1,u-1):0;t.set(r,u,w+1),o.set(r,u,3)}else v===C?(t.set(r,u,0),o.set(r,u,1)):v===f&&(t.set(r,u,0),o.set(r,u,2));n.set(r,u,v)}const i=[];let s=m.length,g=_.length;function c(r,u){(r+1!==s||u+1!==g)&&i.push(new k.SequenceDiff(new d.OffsetRange(r+1,s),new d.OffsetRange(u+1,g))),s=r,g=u}let l=m.length-1,a=_.length-1;for(;l>=0&&a>=0;)o.get(l,a)===3?(c(l,a),l--,a--):o.get(l,a)===1?l--:a--;return c(-1,-1),i.reverse(),new k.DiffAlgorithmResult(i,!1)}}e.DynamicProgrammingDiffing=E}),define(ne[316],se([1,0,67,68,9,4,231]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LinesSliceCharSequence=void 0;class m{constructor(t,i,s){this.lines=t,this.range=i,this.considerWhitespaceChanges=s,this.elements=[],this.firstElementOffsetByLineIdx=[],this.lineStartOffsets=[],this.trimmedWsLengthsByLineIdx=[],this.firstElementOffsetByLineIdx.push(0);for(let g=this.range.startLineNumber;g<=this.range.endLineNumber;g++){let c=t[g-1],l=0;g===this.range.startLineNumber&&this.range.startColumn>1&&(l=this.range.startColumn-1,c=c.substring(l)),this.lineStartOffsets.push(l);let a=0;if(!s){const u=c.trimStart();a=c.length-u.length,c=u.trimEnd()}this.trimmedWsLengthsByLineIdx.push(a);const r=g===this.range.endLineNumber?Math.min(this.range.endColumn-1-l-a,c.length):c.length;for(let u=0;uString.fromCharCode(i)).join("")}getElement(t){return this.elements[t]}get length(){return this.elements.length}getBoundaryScore(t){const i=n(t>0?this.elements[t-1]:-1),s=n(tc<=t),g=t-this.firstElementOffsetByLineIdx[s];return new I.Position(this.range.startLineNumber+s,1+this.lineStartOffsets[s]+g+(g===0&&i==="left"?0:this.trimmedWsLengthsByLineIdx[s]))}translateRange(t){const i=this.translateOffset(t.start,"right"),s=this.translateOffset(t.endExclusive,"left");return s.isBefore(i)?E.Range.fromPositions(s,s):E.Range.fromPositions(i,s)}findWordContaining(t){if(t<0||t>=this.elements.length||!_(this.elements[t]))return;let i=t;for(;i>0&&_(this.elements[i-1]);)i--;let s=t;for(;sg<=t.start)??0,s=(0,d.findFirstMonotonous)(this.firstElementOffsetByLineIdx,g=>t.endExclusive<=g)??this.elements.length;return new k.OffsetRange(i,s)}}e.LinesSliceCharSequence=m;function _(o){return o>=97&&o<=122||o>=65&&o<=90||o>=48&&o<=57}const b={0:0,1:0,2:0,3:10,4:2,5:30,6:3,7:10,8:10};function p(o){return b[o]}function n(o){return o===10?8:o===13?7:(0,y.isSpace)(o)?6:o>=97&&o<=122?0:o>=65&&o<=90?1:o>=48&&o<=57?2:o===-1?3:o===44||o===59?5:4}}),define(ne[232],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MovedText=e.LinesDiff=void 0;class d{constructor(E,y,m){this.changes=E,this.moves=y,this.hitTimeout=m}}e.LinesDiff=d;class k{constructor(E,y){this.lineRangeMapping=E,this.changes=y}}e.MovedText=k}),define(ne[105],se([1,0,8,55,9,4,104]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RangeMapping=e.DetailedLineRangeMapping=e.LineRangeMapping=void 0;class m{static inverse(t,i,s){const g=[];let c=1,l=1;for(const r of t){const u=new m(new k.LineRange(c,r.original.startLineNumber),new k.LineRange(l,r.modified.startLineNumber));u.modified.isEmpty||g.push(u),c=r.original.endLineNumberExclusive,l=r.modified.endLineNumberExclusive}const a=new m(new k.LineRange(c,i+1),new k.LineRange(l,s+1));return a.modified.isEmpty||g.push(a),g}static clip(t,i,s){const g=[];for(const c of t){const l=c.original.intersect(i),a=c.modified.intersect(s);l&&!l.isEmpty&&a&&!a.isEmpty&&g.push(new m(l,a))}return g}constructor(t,i){this.original=t,this.modified=i}toString(){return`{${this.original.toString()}->${this.modified.toString()}}`}flip(){return new m(this.modified,this.original)}join(t){return new m(this.original.join(t.original),this.modified.join(t.modified))}toRangeMapping(){const t=this.original.toInclusiveRange(),i=this.modified.toInclusiveRange();if(t&&i)return new n(t,i);if(this.original.startLineNumber===1||this.modified.startLineNumber===1){if(!(this.modified.startLineNumber===1&&this.original.startLineNumber===1))throw new d.BugIndicatingError("not a valid diff");return new n(new E.Range(this.original.startLineNumber,1,this.original.endLineNumberExclusive,1),new E.Range(this.modified.startLineNumber,1,this.modified.endLineNumberExclusive,1))}else return new n(new E.Range(this.original.startLineNumber-1,Number.MAX_SAFE_INTEGER,this.original.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),new E.Range(this.modified.startLineNumber-1,Number.MAX_SAFE_INTEGER,this.modified.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER))}toRangeMapping2(t,i){if(b(this.original.endLineNumberExclusive,t)&&b(this.modified.endLineNumberExclusive,i))return new n(new E.Range(this.original.startLineNumber,1,this.original.endLineNumberExclusive,1),new E.Range(this.modified.startLineNumber,1,this.modified.endLineNumberExclusive,1));if(!this.original.isEmpty&&!this.modified.isEmpty)return new n(E.Range.fromPositions(new I.Position(this.original.startLineNumber,1),_(new I.Position(this.original.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),t)),E.Range.fromPositions(new I.Position(this.modified.startLineNumber,1),_(new I.Position(this.modified.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),i)));if(this.original.startLineNumber>1&&this.modified.startLineNumber>1)return new n(E.Range.fromPositions(_(new I.Position(this.original.startLineNumber-1,Number.MAX_SAFE_INTEGER),t),_(new I.Position(this.original.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),t)),E.Range.fromPositions(_(new I.Position(this.modified.startLineNumber-1,Number.MAX_SAFE_INTEGER),i),_(new I.Position(this.modified.endLineNumberExclusive-1,Number.MAX_SAFE_INTEGER),i)));throw new d.BugIndicatingError}}e.LineRangeMapping=m;function _(o,t){if(o.lineNumber<1)return new I.Position(1,1);if(o.lineNumber>t.length)return new I.Position(t.length,t[t.length-1].length+1);const i=t[o.lineNumber-1];return o.column>i.length+1?new I.Position(o.lineNumber,i.length+1):o}function b(o,t){return o>=1&&o<=t.length}class p extends m{static fromRangeMappings(t){const i=k.LineRange.join(t.map(g=>k.LineRange.fromRangeInclusive(g.originalRange))),s=k.LineRange.join(t.map(g=>k.LineRange.fromRangeInclusive(g.modifiedRange)));return new p(i,s,t)}constructor(t,i,s){super(t,i),this.innerChanges=s}flip(){return new p(this.modified,this.original,this.innerChanges?.map(t=>t.flip()))}withInnerChangesFromLineRanges(){return new p(this.original,this.modified,[this.toRangeMapping()])}}e.DetailedLineRangeMapping=p;class n{static assertSorted(t){for(let i=1;i${this.modifiedRange.toString()}}`}flip(){return new n(this.modifiedRange,this.originalRange)}toTextEdit(t){const i=t.getValueOfRange(this.modifiedRange);return new y.SingleTextEdit(this.originalRange,i)}}e.RangeMapping=n}),define(ne[559],se([1,0,167,105,13,67,45,55,316,231,314,4]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.computeMovedLines=o;function o(a,r,u,C,f,h){let{moves:v,excludedChanges:w}=i(a,r,u,h);if(!h.isValid())return[];const S=a.filter(D=>!w.has(D)),L=s(S,C,f,r,u,h);return(0,I.pushMany)(v,L),v=c(v),v=v.filter(D=>{const T=D.original.toOffsetRange().slice(r).map(A=>A.trim());return T.join(` `).length>=15&&t(T,A=>A.length>=2)>=2}),v=l(a,v),v}function t(a,r){let u=0;for(const C of a)r(C)&&u++;return u}function i(a,r,u,C){const f=[],h=a.filter(S=>S.modified.isEmpty&&S.original.length>=3).map(S=>new b.LineRangeFragment(S.original,r,S)),v=new Set(a.filter(S=>S.original.isEmpty&&S.modified.length>=3).map(S=>new b.LineRangeFragment(S.modified,u,S))),w=new Set;for(const S of h){let L=-1,D;for(const T of v){const M=S.computeSimilarity(T);M>L&&(L=M,D=T)}if(L>.9&&D&&(v.delete(D),f.push(new k.LineRangeMapping(S.range,D.range)),w.add(S.source),w.add(D.source)),!C.isValid())return{moves:f,excludedChanges:w}}return{moves:f,excludedChanges:w}}function s(a,r,u,C,f,h){const v=[],w=new y.SetMap;for(const M of a)for(let A=M.original.startLineNumber;AM.modified.startLineNumber,I.numberComparator));for(const M of a){let A=[];for(let P=M.modified.startLineNumber;P{for(const V of A)if(V.originalLineRange.endLineNumberExclusive+1===x.endLineNumberExclusive&&V.modifiedLineRange.endLineNumberExclusive+1===O.endLineNumberExclusive){V.originalLineRange=new m.LineRange(V.originalLineRange.startLineNumber,x.endLineNumberExclusive),V.modifiedLineRange=new m.LineRange(V.modifiedLineRange.startLineNumber,O.endLineNumberExclusive),F.push(V);return}const W={modifiedLineRange:O,originalLineRange:x};S.push(W),F.push(W)}),A=F}if(!h.isValid())return[]}S.sort((0,I.reverseOrder)((0,I.compareBy)(M=>M.modifiedLineRange.length,I.numberComparator)));const L=new m.LineRangeSet,D=new m.LineRangeSet;for(const M of S){const A=M.modifiedLineRange.startLineNumber-M.originalLineRange.startLineNumber,P=L.subtractFrom(M.modifiedLineRange),N=D.subtractFrom(M.originalLineRange).getWithDelta(A),O=P.getIntersection(N);for(const F of O.ranges){if(F.length<3)continue;const x=F,W=F.delta(-A);v.push(new k.LineRangeMapping(W,x)),L.addRange(x),D.addRange(W)}}v.sort((0,I.compareBy)(M=>M.original.startLineNumber,I.numberComparator));const T=new E.MonotonousArray(a);for(let M=0;MH.original.startLineNumber<=A.original.startLineNumber),N=(0,E.findLastMonotonous)(a,H=>H.modified.startLineNumber<=A.modified.startLineNumber),O=Math.max(A.original.startLineNumber-P.original.startLineNumber,A.modified.startLineNumber-N.modified.startLineNumber),F=T.findLastMonotonous(H=>H.original.startLineNumberH.modified.startLineNumberC.length||z>f.length||L.contains(z)||D.contains(H)||!g(C[H-1],f[z-1],h))break}V>0&&(D.addRange(new m.LineRange(A.original.startLineNumber-V,A.original.startLineNumber)),L.addRange(new m.LineRange(A.modified.startLineNumber-V,A.modified.startLineNumber)));let q;for(q=0;qC.length||z>f.length||L.contains(z)||D.contains(H)||!g(C[H-1],f[z-1],h))break}q>0&&(D.addRange(new m.LineRange(A.original.endLineNumberExclusive,A.original.endLineNumberExclusive+q)),L.addRange(new m.LineRange(A.modified.endLineNumberExclusive,A.modified.endLineNumberExclusive+q))),(V>0||q>0)&&(v[M]=new k.LineRangeMapping(new m.LineRange(A.original.startLineNumber-V,A.original.endLineNumberExclusive+q),new m.LineRange(A.modified.startLineNumber-V,A.modified.endLineNumberExclusive+q)))}return v}function g(a,r,u){if(a.trim()===r.trim())return!0;if(a.length>300&&r.length>300)return!1;const f=new p.MyersDiffAlgorithm().compute(new _.LinesSliceCharSequence([a],new n.Range(1,1,1,a.length),!1),new _.LinesSliceCharSequence([r],new n.Range(1,1,1,r.length),!1),u);let h=0;const v=d.SequenceDiff.invert(f.diffs,a.length);for(const D of v)D.seq1Range.forEach(T=>{(0,b.isSpace)(a.charCodeAt(T))||h++});function w(D){let T=0;for(let M=0;Mr.length?a:r);return h/S>.6&&S>10}function c(a){if(a.length===0)return a;a.sort((0,I.compareBy)(u=>u.original.startLineNumber,I.numberComparator));const r=[a[0]];for(let u=1;u=0&&v>=0&&h+v<=2){r[r.length-1]=C.join(f);continue}r.push(f)}return r}function l(a,r){const u=new E.MonotonousArray(a);return r=r.filter(C=>{const f=u.findLastMonotonous(w=>w.original.startLineNumberw.modified.startLineNumberH===z))return new i.LinesDiff([],[],!1);if(u.length===1&&u[0].length===0||C.length===1&&C[0].length===0)return new i.LinesDiff([new s.DetailedLineRangeMapping(new I.LineRange(1,u.length+1),new I.LineRange(1,C.length+1),[new s.RangeMapping(new y.Range(1,1,u.length,u[u.length-1].length+1),new y.Range(1,1,C.length,C[C.length-1].length+1))])],[],!1);const h=f.maxComputationTimeMs===0?m.InfiniteTimeout.instance:new m.DateTimeout(f.maxComputationTimeMs),v=!f.ignoreTrimWhitespace,w=new Map;function S(H){let z=w.get(H);return z===void 0&&(z=w.size,w.set(H,z)),z}const L=u.map(H=>S(H.trim())),D=C.map(H=>S(H.trim())),T=new o.LineSequence(L,u),M=new o.LineSequence(D,C),A=T.length+M.length<1700?this.dynamicProgrammingDiffing.compute(T,M,h,(H,z)=>u[H]===C[z]?C[z].length===0?.1:1+Math.log(1+C[z].length):.99):this.myersDiffingAlgorithm.compute(T,M,h);let P=A.diffs,N=A.hitTimeout;P=(0,n.optimizeSequenceDiffs)(T,M,P),P=(0,n.removeVeryShortMatchingLinesBetweenDiffs)(T,M,P);const O=[],F=H=>{if(v)for(let z=0;zH.seq1Range.start-x===H.seq2Range.start-W);const z=H.seq1Range.start-x;F(z),x=H.seq1Range.endExclusive,W=H.seq2Range.endExclusive;const U=this.refineDiff(u,C,H,h,v);U.hitTimeout&&(N=!0);for(const j of U.mappings)O.push(j)}F(u.length-x);const V=c(O,u,C);let q=[];return f.computeMoves&&(q=this.computeMoves(V,u,C,L,D,h,v)),(0,k.assertFn)(()=>{function H(U,j){if(U.lineNumber<1||U.lineNumber>j.length)return!1;const Y=j[U.lineNumber-1];return!(U.column<1||U.column>Y.length+1)}function z(U,j){return!(U.startLineNumber<1||U.startLineNumber>j.length+1||U.endLineNumberExclusive<1||U.endLineNumberExclusive>j.length+1)}for(const U of V){if(!U.innerChanges)return!1;for(const j of U.innerChanges)if(!(H(j.modifiedRange.getStartPosition(),C)&&H(j.modifiedRange.getEndPosition(),C)&&H(j.originalRange.getStartPosition(),u)&&H(j.originalRange.getEndPosition(),u)))return!1;if(!z(U.modified,C)||!z(U.original,u))return!1}return!0}),new i.LinesDiff(V,q,N)}computeMoves(u,C,f,h,v,w,S){return(0,p.computeMovedLines)(u,C,f,h,v,w).map(T=>{const M=this.refineDiff(C,f,new m.SequenceDiff(T.original.toOffsetRange(),T.modified.toOffsetRange()),w,S),A=c(M.mappings,C,f,!0);return new i.MovedText(T,A)})}refineDiff(u,C,f,h,v){const S=a(f).toRangeMapping2(u,C),L=new t.LinesSliceCharSequence(u,S.originalRange,v),D=new t.LinesSliceCharSequence(C,S.modifiedRange,v),T=L.length+D.length<500?this.dynamicProgrammingDiffing.compute(L,D,h):this.myersDiffingAlgorithm.compute(L,D,h),M=!1;let A=T.diffs;M&&m.SequenceDiff.assertSorted(A),A=(0,n.optimizeSequenceDiffs)(L,D,A),M&&m.SequenceDiff.assertSorted(A),A=(0,n.extendDiffsToEntireWordIfAppropriate)(L,D,A),M&&m.SequenceDiff.assertSorted(A),A=(0,n.removeShortMatches)(L,D,A),M&&m.SequenceDiff.assertSorted(A),A=(0,n.removeVeryShortMatchingTextBetweenLongDiffs)(L,D,A),M&&m.SequenceDiff.assertSorted(A);const P=A.map(N=>new s.RangeMapping(L.translateRange(N.seq1Range),D.translateRange(N.seq2Range)));return M&&s.RangeMapping.assertSorted(P),{mappings:P,hitTimeout:T.hitTimeout}}}e.DefaultLinesDiffComputer=g;function c(r,u,C,f=!1){const h=[];for(const v of(0,d.groupAdjacentBy)(r.map(w=>l(w,u,C)),(w,S)=>w.original.overlapOrTouch(S.original)||w.modified.overlapOrTouch(S.modified))){const w=v[0],S=v[v.length-1];h.push(new s.DetailedLineRangeMapping(w.original.join(S.original),w.modified.join(S.modified),v.map(L=>L.innerChanges[0])))}return(0,k.assertFn)(()=>!f&&h.length>0&&(h[0].modified.startLineNumber!==h[0].original.startLineNumber||C.length-h[h.length-1].modified.endLineNumberExclusive!==u.length-h[h.length-1].original.endLineNumberExclusive)?!1:(0,k.checkAdjacentItems)(h,(v,w)=>w.original.startLineNumber-v.original.endLineNumberExclusive===w.modified.startLineNumber-v.modified.endLineNumberExclusive&&v.original.endLineNumberExclusive=C[r.modifiedRange.startLineNumber-1].length&&r.originalRange.startColumn-1>=u[r.originalRange.startLineNumber-1].length&&r.originalRange.startLineNumber<=r.originalRange.endLineNumber+h&&r.modifiedRange.startLineNumber<=r.modifiedRange.endLineNumber+h&&(f=1);const v=new I.LineRange(r.originalRange.startLineNumber+f,r.originalRange.endLineNumber+1+h),w=new I.LineRange(r.modifiedRange.startLineNumber+f,r.modifiedRange.endLineNumber+1+h);return new s.DetailedLineRangeMapping(v,w,[r])}function a(r){return new s.LineRangeMapping(new I.LineRange(r.seq1Range.start+1,r.seq1Range.endExclusive+1),new I.LineRange(r.seq2Range.start+1,r.seq2Range.endExclusive+1))}}),define(ne[560],se([1,0,190,232,105,11,4,90,55]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffComputer=e.LegacyLinesDiffComputer=void 0;const b=3;class p{computeDiff(C,f,h){const w=new c(C,f,{maxComputationTime:h.maxComputationTimeMs,shouldIgnoreTrimWhitespace:h.ignoreTrimWhitespace,shouldComputeCharChanges:!0,shouldMakePrettyDiff:!0,shouldPostProcessCharChanges:!0}).computeDiff(),S=[];let L=null;for(const D of w.changes){let T;D.originalEndLineNumber===0?T=new _.LineRange(D.originalStartLineNumber+1,D.originalStartLineNumber+1):T=new _.LineRange(D.originalStartLineNumber,D.originalEndLineNumber+1);let M;D.modifiedEndLineNumber===0?M=new _.LineRange(D.modifiedStartLineNumber+1,D.modifiedStartLineNumber+1):M=new _.LineRange(D.modifiedStartLineNumber,D.modifiedEndLineNumber+1);let A=new I.DetailedLineRangeMapping(T,M,D.charChanges?.map(P=>new I.RangeMapping(new y.Range(P.originalStartLineNumber,P.originalStartColumn,P.originalEndLineNumber,P.originalEndColumn),new y.Range(P.modifiedStartLineNumber,P.modifiedStartColumn,P.modifiedEndLineNumber,P.modifiedEndColumn))));L&&(L.modified.endLineNumberExclusive===A.modified.startLineNumber||L.original.endLineNumberExclusive===A.original.startLineNumber)&&(A=new I.DetailedLineRangeMapping(L.original.join(A.original),L.modified.join(A.modified),L.innerChanges&&A.innerChanges?L.innerChanges.concat(A.innerChanges):void 0),S.pop()),S.push(A),L=A}return(0,m.assertFn)(()=>(0,m.checkAdjacentItems)(S,(D,T)=>T.original.startLineNumber-D.original.endLineNumberExclusive===T.modified.startLineNumber-D.modified.endLineNumberExclusive&&D.original.endLineNumberExclusive(C===10?"\\n":String.fromCharCode(C))+`-(${this._lineNumbers[f]},${this._columns[f]})`).join(", ")+"]"}_assertIndex(C,f){if(C<0||C>=f.length)throw new Error("Illegal index")}getElements(){return this._charCodes}getStartLineNumber(C){return C>0&&C===this._lineNumbers.length?this.getEndLineNumber(C-1):(this._assertIndex(C,this._lineNumbers),this._lineNumbers[C])}getEndLineNumber(C){return C===-1?this.getStartLineNumber(C+1):(this._assertIndex(C,this._lineNumbers),this._charCodes[C]===10?this._lineNumbers[C]+1:this._lineNumbers[C])}getStartColumn(C){return C>0&&C===this._columns.length?this.getEndColumn(C-1):(this._assertIndex(C,this._columns),this._columns[C])}getEndColumn(C){return C===-1?this.getStartColumn(C+1):(this._assertIndex(C,this._columns),this._charCodes[C]===10?1:this._columns[C]+1)}}class i{constructor(C,f,h,v,w,S,L,D){this.originalStartLineNumber=C,this.originalStartColumn=f,this.originalEndLineNumber=h,this.originalEndColumn=v,this.modifiedStartLineNumber=w,this.modifiedStartColumn=S,this.modifiedEndLineNumber=L,this.modifiedEndColumn=D}static createFromDiffChange(C,f,h){const v=f.getStartLineNumber(C.originalStart),w=f.getStartColumn(C.originalStart),S=f.getEndLineNumber(C.originalStart+C.originalLength-1),L=f.getEndColumn(C.originalStart+C.originalLength-1),D=h.getStartLineNumber(C.modifiedStart),T=h.getStartColumn(C.modifiedStart),M=h.getEndLineNumber(C.modifiedStart+C.modifiedLength-1),A=h.getEndColumn(C.modifiedStart+C.modifiedLength-1);return new i(v,w,S,L,D,T,M,A)}}function s(u){if(u.length<=1)return u;const C=[u[0]];let f=C[0];for(let h=1,v=u.length;h0&&f.originalLength<20&&f.modifiedLength>0&&f.modifiedLength<20&&w()){const N=h.createCharSequence(C,f.originalStart,f.originalStart+f.originalLength-1),O=v.createCharSequence(C,f.modifiedStart,f.modifiedStart+f.modifiedLength-1);if(N.getElements().length>0&&O.getElements().length>0){let F=n(N,O,w,!0).changes;L&&(F=s(F)),P=[];for(let x=0,W=F.length;x1&&F>1;){const x=P.charCodeAt(O-2),W=N.charCodeAt(F-2);if(x!==W)break;O--,F--}(O>1||F>1)&&this._pushTrimWhitespaceCharChange(v,w+1,1,O,S+1,1,F)}{let O=a(P,1),F=a(N,1);const x=P.length+1,W=N.length+1;for(;O!0;const C=Date.now();return()=>Date.now()-Cnew d.LegacyLinesDiffComputer,getDefault:()=>new k.DefaultLinesDiffComputer}}),define(ne[318],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InternalEditorAction=void 0;class d{constructor(I,E,y,m,_,b,p){this.id=I,this.label=E,this.alias=y,this.metadata=m,this._precondition=_,this._run=b,this._contextKeyService=p}isSupported(){return this._contextKeyService.contextMatchesRules(this._precondition)}run(I){return this.isSupported()?this._run(I):Promise.resolve(void 0)}}e.InternalEditorAction=d}),define(ne[198],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorType=void 0,e.EditorType={ICodeEditor:"vs.editor.ICodeEditor",IDiffEditor:"vs.editor.IDiffEditor"}}),define(ne[168],se([1,0,198]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isCodeEditor=k,e.isDiffEditor=I,e.isCompositeEditor=E,e.getCodeEditor=y;function k(m){return m&&typeof m.getEditorType=="function"?m.getEditorType()===d.EditorType.ICodeEditor:!1}function I(m){return m&&typeof m.getEditorType=="function"?m.getEditorType()===d.EditorType.IDiffEditor:!1}function E(m){return!!m&&typeof m=="object"&&typeof m.onDidChangeActiveEditor=="function"}function y(m){return k(m)?m:I(m)?m.getModifiedEditor():E(m)&&k(m.activeCodeEditor)?m.activeCodeEditor:null}}),define(ne[130],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.registerEditorFeature=k,e.getEditorFeatures=I;const d=[];function k(E){d.push(E)}function I(){return d.slice(0)}}),define(ne[562],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorTheme=void 0;class d{get type(){return this._theme.type}get value(){return this._theme}constructor(I){this._theme=I}update(I){this._theme=I}getColor(I){return this._theme.getColor(I)}}e.EditorTheme=d}),define(ne[148],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TokenMetadata=void 0;class d{static getLanguageId(I){return(I&255)>>>0}static getTokenType(I){return(I&768)>>>8}static containsBalancedBrackets(I){return(I&1024)!==0}static getFontStyle(I){return(I&30720)>>>11}static getForeground(I){return(I&16744448)>>>15}static getBackground(I){return(I&4278190080)>>>24}static getClassNameFromMetadata(I){let y="mtk"+this.getForeground(I);const m=this.getFontStyle(I);return m&1&&(y+=" mtki"),m&2&&(y+=" mtkb"),m&4&&(y+=" mtku"),m&8&&(y+=" mtks"),y}static getInlineStyleFromMetadata(I,E){const y=this.getForeground(I),m=this.getFontStyle(I);let _=`color: ${E[y]};`;m&1&&(_+="font-style: italic;"),m&2&&(_+="font-weight: bold;");let b="";return m&4&&(b+=" underline"),m&8&&(b+=" line-through"),b&&(_+=`text-decoration:${b};`),_}static getPresentationFromMetadata(I){const E=this.getForeground(I),y=this.getFontStyle(I);return{foreground:E,italic:!!(y&1),bold:!!(y&2),underline:!!(y&4),strikethrough:!!(y&8)}}}e.TokenMetadata=d}),define(ne[563],se([1,0,33]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.computeDefaultDocumentColors=n;function k(o){const t=[];for(const i of o){const s=Number(i);(s||s===0&&i.replace(/\s/g,"")!=="")&&t.push(s)}return t}function I(o,t,i,s){return{red:o/255,blue:i/255,green:t/255,alpha:s}}function E(o,t){const i=t.index,s=t[0].length;if(!i)return;const g=o.positionAt(i);return{startLineNumber:g.lineNumber,startColumn:g.column,endLineNumber:g.lineNumber,endColumn:g.column+s}}function y(o,t){if(!o)return;const i=d.Color.Format.CSS.parseHex(t);if(i)return{range:o,color:I(i.rgba.r,i.rgba.g,i.rgba.b,i.rgba.a)}}function m(o,t,i){if(!o||t.length!==1)return;const g=t[0].values(),c=k(g);return{range:o,color:I(c[0],c[1],c[2],i?c[3]:1)}}function _(o,t,i){if(!o||t.length!==1)return;const g=t[0].values(),c=k(g),l=new d.Color(new d.HSLA(c[0],c[1]/100,c[2]/100,i?c[3]:1));return{range:o,color:I(l.rgba.r,l.rgba.g,l.rgba.b,l.rgba.a)}}function b(o,t){return typeof o=="string"?[...o.matchAll(t)]:o.findMatches(t)}function p(o){const t=[],s=b(o,/\b(rgb|rgba|hsl|hsla)(\([0-9\s,.\%]*\))|(#)([A-Fa-f0-9]{3})\b|(#)([A-Fa-f0-9]{4})\b|(#)([A-Fa-f0-9]{6})\b|(#)([A-Fa-f0-9]{8})\b/gm);if(s.length>0)for(const g of s){const c=g.filter(u=>u!==void 0),l=c[1],a=c[2];if(!a)continue;let r;if(l==="rgb"){const u=/^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*\)$/gm;r=m(E(o,g),b(a,u),!1)}else if(l==="rgba"){const u=/^\(\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\s*,\s*(0[.][0-9]+|[.][0-9]+|[01][.]|[01])\s*\)$/gm;r=m(E(o,g),b(a,u),!0)}else if(l==="hsl"){const u=/^\(\s*(36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*\)$/gm;r=_(E(o,g),b(a,u),!1)}else if(l==="hsla"){const u=/^\(\s*(36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*,\s*(100|\d{1,2}[.]\d*|\d{1,2})%\s*,\s*(0[.][0-9]+|[.][0-9]+|[01][.]|[01])\s*\)$/gm;r=_(E(o,g),b(a,u),!0)}else l==="#"&&(r=y(E(o,g),l+a));r&&t.push(r)}return t}function n(o){return!o||typeof o.getValue!="function"||typeof o.positionAt!="function"?[]:p(o)}}),define(ne[131],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AutoClosingPairs=e.StandardAutoClosingPairConditional=e.IndentAction=void 0;var d;(function(y){y[y.None=0]="None",y[y.Indent=1]="Indent",y[y.IndentOutdent=2]="IndentOutdent",y[y.Outdent=3]="Outdent"})(d||(e.IndentAction=d={}));class k{constructor(m){if(this._neutralCharacter=null,this._neutralCharacterSearched=!1,this.open=m.open,this.close=m.close,this._inString=!0,this._inComment=!0,this._inRegEx=!0,Array.isArray(m.notIn))for(let _=0,b=m.notIn.length;_t&&(t=a),l>i&&(i=l),r>i&&(i=r)}t++,i++;const s=new k(i,t,0);for(let g=0,c=o.length;g=this._maxCharCode?0:this._states.get(o,t)}}e.StateMachine=I;let E=null;function y(){return E===null&&(E=new I([[1,104,2],[1,72,2],[1,102,6],[1,70,6],[2,116,3],[2,84,3],[3,116,4],[3,84,4],[4,112,5],[4,80,5],[5,115,9],[5,83,9],[5,58,10],[6,105,7],[6,73,7],[7,108,8],[7,76,8],[8,101,9],[8,69,9],[9,58,10],[10,47,11],[11,47,12]])),E}let m=null;function _(){if(m===null){m=new d.CharacterClassifier(0);const n=` <>'"\u3001\u3002\uFF61\uFF64\uFF0C\uFF0E\uFF1A\uFF1B\u2018\u3008\u300C\u300E\u3014\uFF08\uFF3B\uFF5B\uFF62\uFF63\uFF5D\uFF3D\uFF09\u3015\u300F\u300D\u3009\u2019\uFF40\uFF5E\u2026`;for(let t=0;ts);if(s>0){const l=t.charCodeAt(s-1),a=t.charCodeAt(c);(l===40&&a===41||l===91&&a===93||l===123&&a===125)&&c--}return{range:{startLineNumber:i,startColumn:s+1,endLineNumber:i,endColumn:c+2},url:t.substring(s,c+1)}}static computeLinks(o,t=y()){const i=_(),s=[];for(let g=1,c=o.getLineCount();g<=c;g++){const l=o.getLineContent(g),a=l.length;let r=0,u=0,C=0,f=1,h=!1,v=!1,w=!1,S=!1;for(;r0&&E.getLanguageId(n-1)===b;)n--;return new k(E,b,n,p+1,E.getStartOffset(n),E.getEndOffset(p))}class k{constructor(y,m,_,b,p,n){this._scopedLineTokensBrand=void 0,this._actual=y,this.languageId=m,this._firstTokenIndex=_,this._lastTokenIndex=b,this.firstCharOffset=p,this._lastCharOffset=n,this.languageIdCodec=y.languageIdCodec}getLineContent(){return this._actual.getLineContent().substring(this.firstCharOffset,this._lastCharOffset)}getLineLength(){return this._lastCharOffset-this.firstCharOffset}getActualLineContentBefore(y){return this._actual.getLineContent().substring(0,this.firstCharOffset+y)}getTokenCount(){return this._lastTokenIndex-this._firstTokenIndex}findTokenIndexAtOffset(y){return this._actual.findTokenIndexAtOffset(y+this.firstCharOffset)-this._firstTokenIndex}getStandardTokenType(y){return this._actual.getStandardTokenType(y+this._firstTokenIndex)}toIViewLineTokens(){return this._actual.sliceAndInflate(this.firstCharOffset,this._lastCharOffset,0)}}e.ScopedLineTokens=k;function I(E){return(E&3)!==0}}),define(ne[76],se([1,0,9,4,23,169,94,230]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditOperationResult=e.SingleCursorState=e.PartialViewCursorState=e.PartialModelCursorState=e.CursorState=e.CursorConfiguration=void 0,e.isQuote=c;const _=()=>!0,b=()=>!1,p=l=>l===" "||l===" ";class n{static shouldRecreate(a){return a.hasChanged(146)||a.hasChanged(132)||a.hasChanged(37)||a.hasChanged(77)||a.hasChanged(79)||a.hasChanged(80)||a.hasChanged(6)||a.hasChanged(7)||a.hasChanged(11)||a.hasChanged(9)||a.hasChanged(10)||a.hasChanged(14)||a.hasChanged(129)||a.hasChanged(50)||a.hasChanged(92)||a.hasChanged(131)}constructor(a,r,u,C){this.languageConfigurationService=C,this._cursorMoveConfigurationBrand=void 0,this._languageId=a;const f=u.options,h=f.get(146),v=f.get(50);this.readOnly=f.get(92),this.tabSize=r.tabSize,this.indentSize=r.indentSize,this.insertSpaces=r.insertSpaces,this.stickyTabStops=f.get(117),this.lineHeight=v.lineHeight,this.typicalHalfwidthCharacterWidth=v.typicalHalfwidthCharacterWidth,this.pageSize=Math.max(1,Math.floor(h.height/this.lineHeight)-2),this.useTabStops=f.get(129),this.wordSeparators=f.get(132),this.emptySelectionClipboard=f.get(37),this.copyWithSyntaxHighlighting=f.get(25),this.multiCursorMergeOverlapping=f.get(77),this.multiCursorPaste=f.get(79),this.multiCursorLimit=f.get(80),this.autoClosingBrackets=f.get(6),this.autoClosingComments=f.get(7),this.autoClosingQuotes=f.get(11),this.autoClosingDelete=f.get(9),this.autoClosingOvertype=f.get(10),this.autoSurround=f.get(14),this.autoIndent=f.get(12),this.wordSegmenterLocales=f.get(131),this.surroundingPairs={},this._electricChars=null,this.shouldAutoCloseBefore={quote:this._getShouldAutoClose(a,this.autoClosingQuotes,!0),comment:this._getShouldAutoClose(a,this.autoClosingComments,!1),bracket:this._getShouldAutoClose(a,this.autoClosingBrackets,!1)},this.autoClosingPairs=this.languageConfigurationService.getLanguageConfiguration(a).getAutoClosingPairs();const w=this.languageConfigurationService.getLanguageConfiguration(a).getSurroundingPairs();if(w)for(const L of w)this.surroundingPairs[L.open]=L.close;const S=this.languageConfigurationService.getLanguageConfiguration(a).comments;this.blockCommentStartToken=S?.blockCommentStartToken??null}get electricChars(){if(!this._electricChars){this._electricChars={};const a=this.languageConfigurationService.getLanguageConfiguration(this._languageId).electricCharacter?.getElectricCharacters();if(a)for(const r of a)this._electricChars[r]=!0}return this._electricChars}onElectricCharacter(a,r,u){const C=(0,E.createScopedLineTokens)(r,u-1),f=this.languageConfigurationService.getLanguageConfiguration(C.languageId).electricCharacter;return f?f.onElectricCharacter(a,C,u-C.firstCharOffset):null}normalizeIndentation(a){return(0,m.normalizeIndentation)(a,this.indentSize,this.insertSpaces)}_getShouldAutoClose(a,r,u){switch(r){case"beforeWhitespace":return p;case"languageDefined":return this._getLanguageDefinedShouldAutoClose(a,u);case"always":return _;case"never":return b}}_getLanguageDefinedShouldAutoClose(a,r){const u=this.languageConfigurationService.getLanguageConfiguration(a).getAutoCloseBeforeSet(r);return C=>u.indexOf(C)!==-1}visibleColumnFromColumn(a,r){return y.CursorColumns.visibleColumnFromColumn(a.getLineContent(r.lineNumber),r.column,this.tabSize)}columnFromVisibleColumn(a,r,u){const C=y.CursorColumns.columnFromVisibleColumn(a.getLineContent(r),u,this.tabSize),f=a.getLineMinColumn(r);if(Ch?h:C}}e.CursorConfiguration=n;class o{static fromModelState(a){return new t(a)}static fromViewState(a){return new i(a)}static fromModelSelection(a){const r=I.Selection.liftSelection(a),u=new s(k.Range.fromPositions(r.getSelectionStart()),0,0,r.getPosition(),0);return o.fromModelState(u)}static fromModelSelections(a){const r=[];for(let u=0,C=a.length;un,s=p>o,g=po||fp||C0&&p--,E.columnSelect(m,_,b.fromViewLineNumber,b.fromViewVisualColumn,b.toViewLineNumber,p)}static columnSelectRight(m,_,b){let p=0;const n=Math.min(b.fromViewLineNumber,b.toViewLineNumber),o=Math.max(b.fromViewLineNumber,b.toViewLineNumber);for(let i=n;i<=o;i++){const s=_.getLineMaxColumn(i),g=m.visibleColumnFromColumn(_,new k.Position(i,s));p=Math.max(p,g)}let t=b.toViewVisualColumn;return tn.getLineMinColumn(o.lineNumber))return o.delta(void 0,-d.prevCharLength(n.getLineContent(o.lineNumber),o.column-1));if(o.lineNumber>1){const t=o.lineNumber-1;return new I.Position(t,n.getLineMaxColumn(t))}else return o}static leftPositionAtomicSoftTabs(n,o,t){if(o.column<=n.getLineIndentColumn(o.lineNumber)){const i=n.getLineMinColumn(o.lineNumber),s=n.getLineContent(o.lineNumber),g=y.AtomicTabMoveOperations.atomicPosition(s,o.column-1,t,0);if(g!==-1&&g+1>=i)return new I.Position(o.lineNumber,g+1)}return this.leftPosition(n,o)}static left(n,o,t){const i=n.stickyTabStops?b.leftPositionAtomicSoftTabs(o,t,n.tabSize):b.leftPosition(o,t);return new _(i.lineNumber,i.column,0)}static moveLeft(n,o,t,i,s){let g,c;if(t.hasSelection()&&!i)g=t.selection.startLineNumber,c=t.selection.startColumn;else{const l=t.position.delta(void 0,-(s-1)),a=o.normalizePosition(b.clipPositionColumn(l,o),0),r=b.left(n,o,a);g=r.lineNumber,c=r.column}return t.move(i,g,c,0)}static clipPositionColumn(n,o){return new I.Position(n.lineNumber,b.clipRange(n.column,o.getLineMinColumn(n.lineNumber),o.getLineMaxColumn(n.lineNumber)))}static clipRange(n,o,t){return nt?t:n}static rightPosition(n,o,t){return tr?(t=r,c?i=o.getLineMaxColumn(t):i=Math.min(o.getLineMaxColumn(t),i)):i=n.columnFromVisibleColumn(o,t,a),f?s=0:s=a-k.CursorColumns.visibleColumnFromColumn(o.getLineContent(t),i,n.tabSize),l!==void 0){const h=new I.Position(t,i),v=o.normalizePosition(h,l);s=s+(i-v.column),t=v.lineNumber,i=v.column}return new _(t,i,s)}static down(n,o,t,i,s,g,c){return this.vertical(n,o,t,i,s,t+g,c,4)}static moveDown(n,o,t,i,s){let g,c;t.hasSelection()&&!i?(g=t.selection.endLineNumber,c=t.selection.endColumn):(g=t.position.lineNumber,c=t.position.column);let l=0,a;do if(a=b.down(n,o,g+l,c,t.leftoverVisibleColumns,s,!0),o.normalizePosition(new I.Position(a.lineNumber,a.column),2).lineNumber>g)break;while(l++<10&&g+l1&&this._isBlankLine(o,s);)s--;for(;s>1&&!this._isBlankLine(o,s);)s--;return t.move(i,s,o.getLineMinColumn(s),0)}static moveToNextBlankLine(n,o,t,i){const s=o.getLineCount();let g=t.position.lineNumber;for(;g=C.length+1)return!1;const f=C.charAt(u.column-2),h=i.get(f);if(!h)return!1;if((0,I.isQuote)(f)){if(t==="never")return!1}else if(o==="never")return!1;const v=C.charAt(u.column-1);let w=!1;for(const S of h)S.open===f&&S.close===v&&(w=!0);if(!w)return!1;if(n==="auto"){let S=!1;for(let L=0,D=c.length;L1){const s=o.getLineContent(i.lineNumber),g=d.firstNonWhitespaceIndex(s),c=g===-1?s.length+1:g+1;if(i.column<=c){const l=t.visibleColumnFromColumn(o,i),a=E.CursorColumns.prevIndentTabStop(l,t.indentSize),r=t.columnFromVisibleColumn(o,i.lineNumber,a);return new m.Range(i.lineNumber,r,i.lineNumber,i.column)}}return m.Range.fromPositions(b.getPositionAfterDeleteLeft(i,o),i)}static getPositionAfterDeleteLeft(n,o){if(n.column>1){const t=d.getLeftDeleteOffset(n.column-1,o.getLineContent(n.lineNumber));return n.with(void 0,t+1)}else if(n.lineNumber>1){const t=n.lineNumber-1;return new _.Position(t,o.getLineMaxColumn(t))}else return n}static cut(n,o,t){const i=[];let s=null;t.sort((g,c)=>_.Position.compare(g.getStartPosition(),c.getEndPosition()));for(let g=0,c=t.length;g1&&s?.endLineNumber!==a.lineNumber?(r=a.lineNumber-1,u=o.getLineMaxColumn(a.lineNumber-1),C=a.lineNumber,f=o.getLineMaxColumn(a.lineNumber)):(r=a.lineNumber,u=1,C=a.lineNumber,f=o.getLineMaxColumn(a.lineNumber));const h=new m.Range(r,u,C,f);s=h,h.isEmpty()?i[g]=null:i[g]=new k.ReplaceCommand(h,"")}else i[g]=null;else i[g]=new k.ReplaceCommand(l,"")}return new I.EditOperationResult(0,i,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!0})}}e.DeleteOperations=b}),define(ne[199],se([1,0,11,76,234,166,9,4]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.WordPartOperations=e.WordOperations=void 0;class _{static _createWord(o,t,i,s,g){return{start:s,end:g,wordType:t,nextCharClass:i}}static _createIntlWord(o,t){return{start:o.index,end:o.index+o.segment.length,wordType:1,nextCharClass:t}}static _findPreviousWordOnLine(o,t,i){const s=t.getLineContent(i.lineNumber);return this._doFindPreviousWordOnLine(s,o,i)}static _doFindPreviousWordOnLine(o,t,i){let s=0;const g=t.findPrevIntlWordBeforeOrAtOffset(o,i.column-2);for(let c=i.column-2;c>=0;c--){const l=o.charCodeAt(c),a=t.get(l);if(g&&c===g.index)return this._createIntlWord(g,a);if(a===0){if(s===2)return this._createWord(o,s,a,c+1,this._findEndOfWord(o,t,s,c+1));s=1}else if(a===2){if(s===1)return this._createWord(o,s,a,c+1,this._findEndOfWord(o,t,s,c+1));s=2}else if(a===1&&s!==0)return this._createWord(o,s,a,c+1,this._findEndOfWord(o,t,s,c+1))}return s!==0?this._createWord(o,s,1,0,this._findEndOfWord(o,t,s,0)):null}static _findEndOfWord(o,t,i,s){const g=t.findNextIntlWordAtOrAfterOffset(o,s),c=o.length;for(let l=s;l=0;c--){const l=o.charCodeAt(c),a=t.get(l);if(g&&c===g.index)return c;if(a===1||i===1&&a===2||i===2&&a===0)return c+1}return 0}static moveWordLeft(o,t,i,s,g){let c=i.lineNumber,l=i.column;l===1&&c>1&&(c=c-1,l=t.getLineMaxColumn(c));let a=_._findPreviousWordOnLine(o,t,new y.Position(c,l));if(s===0)return new y.Position(c,a?a.start+1:1);if(s===1)return!g&&a&&a.wordType===2&&a.end-a.start===1&&a.nextCharClass===0&&(a=_._findPreviousWordOnLine(o,t,new y.Position(c,a.start+1))),new y.Position(c,a?a.start+1:1);if(s===3){for(;a&&a.wordType===2;)a=_._findPreviousWordOnLine(o,t,new y.Position(c,a.start+1));return new y.Position(c,a?a.start+1:1)}return a&&l<=a.end+1&&(a=_._findPreviousWordOnLine(o,t,new y.Position(c,a.start+1))),new y.Position(c,a?a.end+1:1)}static _moveWordPartLeft(o,t){const i=t.lineNumber,s=o.getLineMaxColumn(i);if(t.column===1)return i>1?new y.Position(i-1,o.getLineMaxColumn(i-1)):t;const g=o.getLineContent(i);for(let c=t.column-1;c>1;c--){const l=g.charCodeAt(c-2),a=g.charCodeAt(c-1);if(l===95&&a!==95)return new y.Position(i,c);if(l===45&&a!==45)return new y.Position(i,c);if((d.isLowerAsciiLetter(l)||d.isAsciiDigit(l))&&d.isUpperAsciiLetter(a))return new y.Position(i,c);if(d.isUpperAsciiLetter(l)&&d.isUpperAsciiLetter(a)&&c+1=a.start+1&&(a=_._findNextWordOnLine(o,t,new y.Position(g,a.end+1))),a?c=a.start+1:c=t.getLineMaxColumn(g);return new y.Position(g,c)}static _moveWordPartRight(o,t){const i=t.lineNumber,s=o.getLineMaxColumn(i);if(t.column===s)return i1?r=1:(a--,r=s.getLineMaxColumn(a)):(u&&r<=u.end+1&&(u=_._findPreviousWordOnLine(i,s,new y.Position(a,u.start+1))),u?r=u.end+1:r>1?r=1:(a--,r=s.getLineMaxColumn(a))),new m.Range(a,r,l.lineNumber,l.column)}static deleteInsideWord(o,t,i){if(!i.isEmpty())return i;const s=new y.Position(i.positionLineNumber,i.positionColumn),g=this._deleteInsideWordWhitespace(t,s);return g||this._deleteInsideWordDetermineDeleteRange(o,t,s)}static _charAtIsWhitespace(o,t){const i=o.charCodeAt(t);return i===32||i===9}static _deleteInsideWordWhitespace(o,t){const i=o.getLineContent(t.lineNumber),s=i.length;if(s===0)return null;let g=Math.max(t.column-2,0);if(!this._charAtIsWhitespace(i,g))return null;let c=Math.min(t.column-1,s-1);if(!this._charAtIsWhitespace(i,c))return null;for(;g>0&&this._charAtIsWhitespace(i,g-1);)g--;for(;c+11?new m.Range(i.lineNumber-1,t.getLineMaxColumn(i.lineNumber-1),i.lineNumber,1):i.lineNumberC.start+1<=i.column&&i.column<=C.end+1,l=(C,f)=>(C=Math.min(C,i.column),f=Math.max(f,i.column),new m.Range(i.lineNumber,C,i.lineNumber,f)),a=C=>{let f=C.start+1,h=C.end+1,v=!1;for(;h-11&&this._charAtIsWhitespace(s,f-2);)f--;return l(f,h)},r=_._findPreviousWordOnLine(o,t,i);if(r&&c(r))return a(r);const u=_._findNextWordOnLine(o,t,i);return u&&c(u)?a(u):r&&u?l(r.end+1,u.start+1):r?l(r.start+1,r.end+1):u?l(u.start+1,u.end+1):l(1,g+1)}static _deleteWordPartLeft(o,t){if(!t.isEmpty())return t;const i=t.getPosition(),s=_._moveWordPartLeft(o,i);return new m.Range(i.lineNumber,i.column,s.lineNumber,s.column)}static _findFirstNonWhitespaceChar(o,t){const i=o.length;for(let s=t;s=f.start+1&&(f=_._findNextWordOnLine(i,s,new y.Position(a,f.end+1))),f?r=f.start+1:r!!o)}}),define(ne[235],se([1,0,19,76,233,199,9,4]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CursorMove=e.CursorMoveCommands=void 0;class _{static addCursorDown(n,o,t){const i=[];let s=0;for(let g=0,c=o.length;ga&&(r=a,u=n.model.getLineMaxColumn(r)),k.CursorState.fromModelState(new k.SingleCursorState(new m.Range(g.lineNumber,1,r,u),2,0,new y.Position(r,u),0))}const l=o.modelState.selectionStart.getStartPosition().lineNumber;if(g.lineNumberl){const a=n.getLineCount();let r=c.lineNumber+1,u=1;return r>a&&(r=a,u=n.getLineMaxColumn(r)),k.CursorState.fromViewState(o.viewState.move(!0,r,u,0))}else{const a=o.modelState.selectionStart.getEndPosition();return k.CursorState.fromModelState(o.modelState.move(!0,a.lineNumber,a.column,0))}}static word(n,o,t,i){const s=n.model.validatePosition(i);return k.CursorState.fromModelState(E.WordOperations.word(n.cursorConfig,n.model,o.modelState,t,s))}static cancelSelection(n,o){if(!o.modelState.hasSelection())return new k.CursorState(o.modelState,o.viewState);const t=o.viewState.position.lineNumber,i=o.viewState.position.column;return k.CursorState.fromViewState(new k.SingleCursorState(new m.Range(t,i,t,i),0,0,new y.Position(t,i),0))}static moveTo(n,o,t,i,s){if(t){if(o.modelState.selectionStartKind===1)return this.word(n,o,t,i);if(o.modelState.selectionStartKind===2)return this.line(n,o,t,i,s)}const g=n.model.validatePosition(i),c=s?n.coordinatesConverter.validateViewPosition(new y.Position(s.lineNumber,s.column),g):n.coordinatesConverter.convertModelPositionToViewPosition(g);return k.CursorState.fromViewState(o.viewState.move(t,c.lineNumber,c.column,0))}static simpleMove(n,o,t,i,s,g){switch(t){case 0:return g===4?this._moveHalfLineLeft(n,o,i):this._moveLeft(n,o,i,s);case 1:return g===4?this._moveHalfLineRight(n,o,i):this._moveRight(n,o,i,s);case 2:return g===2?this._moveUpByViewLines(n,o,i,s):this._moveUpByModelLines(n,o,i,s);case 3:return g===2?this._moveDownByViewLines(n,o,i,s):this._moveDownByModelLines(n,o,i,s);case 4:return g===2?o.map(c=>k.CursorState.fromViewState(I.MoveOperations.moveToPrevBlankLine(n.cursorConfig,n,c.viewState,i))):o.map(c=>k.CursorState.fromModelState(I.MoveOperations.moveToPrevBlankLine(n.cursorConfig,n.model,c.modelState,i)));case 5:return g===2?o.map(c=>k.CursorState.fromViewState(I.MoveOperations.moveToNextBlankLine(n.cursorConfig,n,c.viewState,i))):o.map(c=>k.CursorState.fromModelState(I.MoveOperations.moveToNextBlankLine(n.cursorConfig,n.model,c.modelState,i)));case 6:return this._moveToViewMinColumn(n,o,i);case 7:return this._moveToViewFirstNonWhitespaceColumn(n,o,i);case 8:return this._moveToViewCenterColumn(n,o,i);case 9:return this._moveToViewMaxColumn(n,o,i);case 10:return this._moveToViewLastNonWhitespaceColumn(n,o,i);default:return null}}static viewportMove(n,o,t,i,s){const g=n.getCompletelyVisibleViewRange(),c=n.coordinatesConverter.convertViewRangeToModelRange(g);switch(t){case 11:{const l=this._firstLineNumberInRange(n.model,c,s),a=n.model.getLineFirstNonWhitespaceColumn(l);return[this._moveToModelPosition(n,o[0],i,l,a)]}case 13:{const l=this._lastLineNumberInRange(n.model,c,s),a=n.model.getLineFirstNonWhitespaceColumn(l);return[this._moveToModelPosition(n,o[0],i,l,a)]}case 12:{const l=Math.round((c.startLineNumber+c.endLineNumber)/2),a=n.model.getLineFirstNonWhitespaceColumn(l);return[this._moveToModelPosition(n,o[0],i,l,a)]}case 14:{const l=[];for(let a=0,r=o.length;at.endLineNumber-1?g=t.endLineNumber-1:sk.CursorState.fromViewState(I.MoveOperations.moveLeft(n.cursorConfig,n,s.viewState,t,i)))}static _moveHalfLineLeft(n,o,t){const i=[];for(let s=0,g=o.length;sk.CursorState.fromViewState(I.MoveOperations.moveRight(n.cursorConfig,n,s.viewState,t,i)))}static _moveHalfLineRight(n,o,t){const i=[];for(let s=0,g=o.length;sn.readSelectionFromMarkers(this.context))}getAll(){return this.cursors.map(n=>n.asCursorState())}getViewPositions(){return this.cursors.map(n=>n.viewState.position)}getTopMostViewPosition(){return(0,k.findFirstMin)(this.cursors,(0,d.compareBy)(n=>n.viewState.position,y.Position.compare)).viewState.position}getBottomMostViewPosition(){return(0,k.findLastMax)(this.cursors,(0,d.compareBy)(n=>n.viewState.position,y.Position.compare)).viewState.position}getSelections(){return this.cursors.map(n=>n.modelState.selection)}getViewSelections(){return this.cursors.map(n=>n.viewState.selection)}setSelections(n){this.setStates(I.CursorState.fromModelSelections(n))}getPrimaryCursor(){return this.cursors[0].asCursorState()}setStates(n){n!==null&&(this.cursors[0].setState(this.context,n[0].modelState,n[0].viewState),this._setSecondaryStates(n.slice(1)))}_setSecondaryStates(n){const o=this.cursors.length-1,t=n.length;if(ot){const i=o-t;for(let s=0;s=n+1&&this.lastAddedCursorIndex--,this.cursors[n+1].dispose(this.context),this.cursors.splice(n+1,1)}normalize(){if(this.cursors.length===1)return;const n=this.cursors.slice(0),o=[];for(let t=0,i=n.length;tt.selection,m.Range.compareRangesUsingStarts));for(let t=0;tu&&v.index--;n.splice(u,1),o.splice(r,1),this._removeSecondaryCursor(u-1),t--}}}}e.CursorCollection=b}),define(ne[568],se([1,0,131]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CharacterPairSupport=void 0;class k{static{this.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED_QUOTES=`;:.,=}])> `}static{this.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED_BRACKETS=`'"\`;:.,=}])> `}constructor(E){if(E.autoClosingPairs?this._autoClosingPairs=E.autoClosingPairs.map(y=>new d.StandardAutoClosingPairConditional(y)):E.brackets?this._autoClosingPairs=E.brackets.map(y=>new d.StandardAutoClosingPairConditional({open:y[0],close:y[1]})):this._autoClosingPairs=[],E.__electricCharacterSupport&&E.__electricCharacterSupport.docComment){const y=E.__electricCharacterSupport.docComment;this._autoClosingPairs.push(new d.StandardAutoClosingPairConditional({open:y.open,close:y.close||""}))}this._autoCloseBeforeForQuotes=typeof E.autoCloseBefore=="string"?E.autoCloseBefore:k.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED_QUOTES,this._autoCloseBeforeForBrackets=typeof E.autoCloseBefore=="string"?E.autoCloseBefore:k.DEFAULT_AUTOCLOSE_BEFORE_LANGUAGE_DEFINED_BRACKETS,this._surroundingPairs=E.surroundingPairs||this._autoClosingPairs}getAutoClosingPairs(){return this._autoClosingPairs}getAutoCloseBeforeSet(E){return E?this._autoCloseBeforeForQuotes:this._autoCloseBeforeForBrackets}getSurroundingPairs(){return this._surroundingPairs}}e.CharacterPairSupport=k}),define(ne[569],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IndentRulesSupport=void 0;function d(I){return I.global&&(I.lastIndex=0),!0}class k{constructor(E){this._indentationRules=E}shouldIncrease(E){return!!(this._indentationRules&&this._indentationRules.increaseIndentPattern&&d(this._indentationRules.increaseIndentPattern)&&this._indentationRules.increaseIndentPattern.test(E))}shouldDecrease(E){return!!(this._indentationRules&&this._indentationRules.decreaseIndentPattern&&d(this._indentationRules.decreaseIndentPattern)&&this._indentationRules.decreaseIndentPattern.test(E))}shouldIndentNextLine(E){return!!(this._indentationRules&&this._indentationRules.indentNextLinePattern&&d(this._indentationRules.indentNextLinePattern)&&this._indentationRules.indentNextLinePattern.test(E))}shouldIgnore(E){return!!(this._indentationRules&&this._indentationRules.unIndentedLinePattern&&d(this._indentationRules.unIndentedLinePattern)&&this._indentationRules.unIndentedLinePattern.test(E))}getIndentMetadata(E){let y=0;return this.shouldIncrease(E)&&(y+=1),this.shouldDecrease(E)&&(y+=2),this.shouldIndentNextLine(E)&&(y+=4),this.shouldIgnore(E)&&(y+=8),y}}e.IndentRulesSupport=k}),define(ne[570],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BasicInplaceReplace=void 0;class d{constructor(){this._defaultValueSet=[["true","false"],["True","False"],["Private","Public","Friend","ReadOnly","Partial","Protected","WriteOnly"],["public","protected","private"]]}static{this.INSTANCE=new d}navigateValueSet(I,E,y,m,_){if(I&&E){const b=this.doNavigateValueSet(E,_);if(b)return{range:I,value:b}}if(y&&m){const b=this.doNavigateValueSet(m,_);if(b)return{range:y,value:b}}return null}doNavigateValueSet(I,E){const y=this.numberReplace(I,E);return y!==null?y:this.textReplace(I,E)}numberReplace(I,E){const y=Math.pow(10,I.length-(I.lastIndexOf(".")+1));let m=Number(I);const _=parseFloat(I);return!isNaN(m)&&!isNaN(_)&&m===_?m===0&&!E?null:(m=Math.floor(m*y),m+=E?y:-y,String(m/y)):null}textReplace(I,E){return this.valueSetsReplace(this._defaultValueSet,I,E)}valueSetsReplace(I,E,y){let m=null;for(let _=0,b=I.length;m===null&&_=0?(m+=y?1:-1,m<0?m=I.length-1:m%=I.length,I[m]):null}}e.BasicInplaceReplace=d}),define(ne[571],se([1,0,8,11,131]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OnEnterSupport=void 0;class E{constructor(m){m=m||{},m.brackets=m.brackets||[["(",")"],["{","}"],["[","]"]],this._brackets=[],m.brackets.forEach(_=>{const b=E._createOpenBracketRegExp(_[0]),p=E._createCloseBracketRegExp(_[1]);b&&p&&this._brackets.push({open:_[0],openRegExp:b,close:_[1],closeRegExp:p})}),this._regExpRules=m.onEnterRules||[]}onEnter(m,_,b,p){if(m>=3)for(let n=0,o=this._regExpRules.length;ns.reg?(s.reg.lastIndex=0,s.reg.test(s.text)):!0))return t.action}if(m>=2&&b.length>0&&p.length>0)for(let n=0,o=this._brackets.length;n=2&&b.length>0){for(let n=0,o=this._brackets.length;n{const S=n(v.token,w.token);return S!==0?S:v.index-w.index});let c=0,l="000000",a="ffffff";for(;s.length>=1&&s[0].token==="";){const v=s.shift();v.fontStyle!==-1&&(c=v.fontStyle),v.foreground!==null&&(l=v.foreground),v.background!==null&&(a=v.background)}const r=new m;for(const v of g)r.getId(v);const u=r.getId(l),C=r.getId(a),f=new o(c,u,C),h=new t(f);for(let v=0,w=s.length;v"u"){const a=this._match(c),r=p(c);l=(a.metadata|r<<8)>>>0,this._cache.set(c,l)}return(l|g<<0)>>>0}}e.TokenTheme=_;const b=/\b(comment|string|regex|regexp)\b/;function p(s){const g=s.match(b);if(!g)return 0;switch(g[1]){case"comment":return 1;case"string":return 2;case"regex":return 3;case"regexp":return 3}throw new Error("Unexpected match for standard token type!")}function n(s,g){return sg?1:0}class o{constructor(g,c,l){this._themeTrieElementRuleBrand=void 0,this._fontStyle=g,this._foreground=c,this._background=l,this.metadata=(this._fontStyle<<11|this._foreground<<15|this._background<<24)>>>0}clone(){return new o(this._fontStyle,this._foreground,this._background)}acceptOverwrite(g,c,l){g!==-1&&(this._fontStyle=g),c!==0&&(this._foreground=c),l!==0&&(this._background=l),this.metadata=(this._fontStyle<<11|this._foreground<<15|this._background<<24)>>>0}}e.ThemeTrieElementRule=o;class t{constructor(g){this._themeTrieElementBrand=void 0,this._mainRule=g,this._children=new Map}match(g){if(g==="")return this._mainRule;const c=g.indexOf(".");let l,a;c===-1?(l=g,a=""):(l=g.substring(0,c),a=g.substring(c+1));const r=this._children.get(l);return typeof r<"u"?r.match(a):this._mainRule}insert(g,c,l,a){if(g===""){this._mainRule.acceptOverwrite(c,l,a);return}const r=g.indexOf(".");let u,C;r===-1?(u=g,C=""):(u=g.substring(0,r),C=g.substring(r+1));let f=this._children.get(u);typeof f>"u"&&(f=new t(this._mainRule.clone()),this._children.set(u,f)),f.insert(C,c,l,a)}}e.ThemeTrieElement=t;function i(s){const g=[];for(let c=1,l=s.length;c=m&&(h=h-C%m),h}function t(C,f){return C.reduce((h,v)=>o(h,f(v)),e.lengthZero)}function i(C,f){return C===f}function s(C,f){const h=C,v=f;if(v-h<=0)return e.lengthZero;const S=Math.floor(h/m),L=Math.floor(v/m),D=v-L*m;if(S===L){const T=h-S*m;return _(0,D-T)}else return _(L-S,D)}function g(C,f){return C=f}function a(C){return _(C.lineNumber-1,C.column-1)}function r(C,f){const h=C,v=Math.floor(h/m),w=h-v*m,S=f,L=Math.floor(S/m),D=S-L*m;return new k.Range(v+1,w+1,L+1,D+1)}function u(C){const f=(0,d.splitLines)(C);return _(f.length-1,f[f.length-1].length)}}),define(ne[200],se([1,0,4,106]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BeforeEditPositionMapper=e.TextEditInfo=void 0;class I{static fromModelContentChanges(_){return _.map(p=>{const n=d.Range.lift(p.range);return new I((0,k.positionToLength)(n.getStartPosition()),(0,k.positionToLength)(n.getEndPosition()),(0,k.lengthOfString)(p.text))}).reverse()}constructor(_,b,p){this.startOffset=_,this.endOffset=b,this.newLength=p}toString(){return`[${(0,k.lengthToObj)(this.startOffset)}...${(0,k.lengthToObj)(this.endOffset)}) -> ${(0,k.lengthToObj)(this.newLength)}`}}e.TextEditInfo=I;class E{constructor(_){this.nextEditIdx=0,this.deltaOldToNewLineCount=0,this.deltaOldToNewColumnCount=0,this.deltaLineIdxInOld=-1,this.edits=_.map(b=>y.from(b))}getOffsetBeforeChange(_){return this.adjustNextEdit(_),this.translateCurToOld(_)}getDistanceToNextChange(_){this.adjustNextEdit(_);const b=this.edits[this.nextEditIdx],p=b?this.translateOldToCur(b.offsetObj):null;return p===null?null:(0,k.lengthDiffNonNegative)(_,p)}translateOldToCur(_){return _.lineCount===this.deltaLineIdxInOld?(0,k.toLength)(_.lineCount+this.deltaOldToNewLineCount,_.columnCount+this.deltaOldToNewColumnCount):(0,k.toLength)(_.lineCount+this.deltaOldToNewLineCount,_.columnCount)}translateCurToOld(_){const b=(0,k.lengthToObj)(_);return b.lineCount-this.deltaOldToNewLineCount===this.deltaLineIdxInOld?(0,k.toLength)(b.lineCount-this.deltaOldToNewLineCount,b.columnCount-this.deltaOldToNewColumnCount):(0,k.toLength)(b.lineCount-this.deltaOldToNewLineCount,b.columnCount)}adjustNextEdit(_){for(;this.nextEditIdx!0)||[];return o&&a.unshift(o),a}const l=[];for(;o&&!(0,I.lengthIsZero)(c);){const[a,r]=o.splitAt(c);l.push(a),c=(0,I.lengthDiffNonNegative)(a.lengthAfter,c),o=r??p.dequeue()}return(0,I.lengthIsZero)(c)||l.push(new y(!1,c,c)),l}const i=[];function s(c,l,a){if(i.length>0&&(0,I.lengthEquals)(i[i.length-1].endOffset,c)){const r=i[i.length-1];i[i.length-1]=new k.TextEditInfo(r.startOffset,l,(0,I.lengthAdd)(r.newLength,a))}else i.push({startOffset:c,endOffset:l,newLength:a})}let g=I.lengthZero;for(const c of n){const l=t(c.lengthBefore);if(c.modified){const a=(0,I.sumLengths)(l,u=>u.lengthBefore),r=(0,I.lengthAdd)(g,a);s(g,r,c.lengthAfter),g=r}else for(const a of l){const r=g;g=(0,I.lengthAdd)(g,a.lengthBefore),a.modified&&s(r,g,a.lengthAfter)}}return i}class y{constructor(b,p,n){this.modified=b,this.lengthBefore=p,this.lengthAfter=n}splitAt(b){const p=(0,I.lengthDiffNonNegative)(b,this.lengthAfter);return(0,I.lengthEquals)(p,I.lengthZero)?[this,void 0]:this.modified?[new y(this.modified,this.lengthBefore,b),new y(this.modified,I.lengthZero,p)]:[new y(this.modified,b,b),new y(this.modified,p,p)]}toString(){return`${this.modified?"M":"U"}:${(0,I.lengthToObj)(this.lengthBefore)} -> ${(0,I.lengthToObj)(this.lengthAfter)}`}}function m(_){const b=[];let p=I.lengthZero;for(const n of _){const o=(0,I.lengthDiffNonNegative)(p,n.startOffset);(0,I.lengthIsZero)(o)||b.push(new y(!1,o,o));const t=(0,I.lengthDiffNonNegative)(n.startOffset,n.endOffset);b.push(new y(!0,t,n.newLength)),p=n.endOffset}return b}}),define(ne[573],se([1,0,106]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.NodeReader=void 0;class k{constructor(m){this.lastOffset=d.lengthZero,this.nextNodes=[m],this.offsets=[d.lengthZero],this.idxs=[]}readLongestNodeAt(m,_){if((0,d.lengthLessThan)(m,this.lastOffset))throw new Error("Invalid offset");for(this.lastOffset=m;;){const b=E(this.nextNodes);if(!b)return;const p=E(this.offsets);if((0,d.lengthLessThan)(m,p))return;if((0,d.lengthLessThan)(p,m))if((0,d.lengthAdd)(p,b.length)<=m)this.nextNodeAfterCurrent();else{const n=I(b);n!==-1?(this.nextNodes.push(b.getChild(n)),this.offsets.push(p),this.idxs.push(n)):this.nextNodeAfterCurrent()}else{if(_(b))return this.nextNodeAfterCurrent(),b;{const n=I(b);if(n===-1){this.nextNodeAfterCurrent();return}else this.nextNodes.push(b.getChild(n)),this.offsets.push(p),this.idxs.push(n)}}}}nextNodeAfterCurrent(){for(;;){const m=E(this.offsets),_=E(this.nextNodes);if(this.nextNodes.pop(),this.offsets.pop(),this.idxs.length===0)break;const b=E(this.nextNodes),p=I(b,this.idxs[this.idxs.length-1]);if(p!==-1){this.nextNodes.push(b.getChild(p)),this.offsets.push((0,d.lengthAdd)(m,_.length)),this.idxs[this.idxs.length-1]=p;break}else this.idxs.pop()}}}e.NodeReader=k;function I(y,m=-1){for(;;){if(m++,m>=y.childrenLength)return-1;if(y.getChild(m))return m}}function E(y){return y.length>0?y[y.length-1]:void 0}}),define(ne[149],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DenseKeyProvider=e.identityKeyProvider=e.SmallImmutableSet=void 0;const d=[];class k{static{this.cache=new Array(129)}static create(y,m){if(y<=128&&m.length===0){let _=k.cache[y];return _||(_=new k(y,m),k.cache[y]=_),_}return new k(y,m)}static{this.empty=k.create(0,d)}static getEmpty(){return this.empty}constructor(y,m){this.items=y,this.additionalItems=m}add(y,m){const _=m.getKey(y);let b=_>>5;if(b===0){const n=1<<_|this.items;return n===this.items?this:k.create(n,this.additionalItems)}b--;const p=this.additionalItems.slice(0);for(;p.length=b.length)return null;const s=p,g=b[s].listHeight;for(p++;p=2?I(s===0&&p===b.length?b:b.slice(s,p),!1):b[s]}let o=n(),t=n();if(!t)return o;for(let s=n();s;s=n())E(o,t)<=E(t,s)?(o=y(o,t),t=s):t=y(t,s);return y(o,t)}function I(b,p=!1){if(b.length===0)return null;if(b.length===1)return b[0];let n=b.length;for(;n>3;){const o=n>>1;for(let t=0;t=3?b[2]:null,p)}function E(b,p){return Math.abs(b.listHeight-p.listHeight)}function y(b,p){return b.listHeight===p.listHeight?d.ListAstNode.create23(b,p,null,!1):b.listHeight>p.listHeight?m(b,p):_(p,b)}function m(b,p){b=b.toMutable();let n=b;const o=[];let t;for(;;){if(p.listHeight===n.listHeight){t=p;break}if(n.kind!==4)throw new Error("unexpected");o.push(n),n=n.makeLastElementMutable()}for(let i=o.length-1;i>=0;i--){const s=o[i];t?s.childrenLength>=3?t=d.ListAstNode.create23(s.unappendChild(),t,null,!1):(s.appendChildOfSameHeight(t),t=void 0):s.handleChildrenChanged()}return t?d.ListAstNode.create23(b,t,null,!1):b}function _(b,p){b=b.toMutable();let n=b;const o=[];for(;p.listHeight!==n.listHeight;){if(n.kind!==4)throw new Error("unexpected");o.push(n),n=n.makeFirstElementMutable()}let t=p;for(let i=o.length-1;i>=0;i--){const s=o[i];t?s.childrenLength>=3?t=d.ListAstNode.create23(t,s.unprependChild(),null,!1):(s.prependChildOfSameHeight(t),t=void 0):s.handleChildrenChanged()}return t?d.ListAstNode.create23(t,b,null,!1):b}}),define(ne[320],se([1,0,201,200,149,106,574,573]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.parseDocument=_;function _(p,n,o,t){return new b(p,n,o,t).parseDocument()}class b{constructor(n,o,t,i){if(this.tokenizer=n,this.createImmutableLists=i,this._itemsConstructed=0,this._itemsFromCache=0,t&&i)throw new Error("Not supported");this.oldNodeReader=t?new m.NodeReader(t):void 0,this.positionMapper=new k.BeforeEditPositionMapper(o)}parseDocument(){this._itemsConstructed=0,this._itemsFromCache=0;let n=this.parseList(I.SmallImmutableSet.getEmpty(),0);return n||(n=d.ListAstNode.getEmpty()),n}parseList(n,o){const t=[];for(;;){let s=this.tryReadChildFromCache(n);if(!s){const g=this.tokenizer.peek();if(!g||g.kind===2&&g.bracketIds.intersects(n))break;s=this.parseChild(n,o+1)}s.kind===4&&s.childrenLength===0||t.push(s)}return this.oldNodeReader?(0,y.concat23Trees)(t):(0,y.concat23TreesOfSameHeight)(t,this.createImmutableLists)}tryReadChildFromCache(n){if(this.oldNodeReader){const o=this.positionMapper.getDistanceToNextChange(this.tokenizer.offset);if(o===null||!(0,E.lengthIsZero)(o)){const t=this.oldNodeReader.readLongestNodeAt(this.positionMapper.getOffsetBeforeChange(this.tokenizer.offset),i=>o!==null&&!(0,E.lengthLessThan)(i.length,o)?!1:i.canBeReused(n));if(t)return this._itemsFromCache++,this.tokenizer.skip(t.length),t}}}parseChild(n,o){this._itemsConstructed++;const t=this.tokenizer.read();switch(t.kind){case 2:return new d.InvalidBracketAstNode(t.bracketIds,t.length);case 0:return t.astNode;case 1:{if(o>300)return new d.TextAstNode(t.length);const i=n.merge(t.bracketIds),s=this.parseList(i,o+1),g=this.tokenizer.peek();return g&&g.kind===2&&(g.bracketId===t.bracketId||g.bracketIds.intersects(t.bracketIds))?(this.tokenizer.read(),d.PairAstNode.create(t.astNode,s,g.astNode)):d.PairAstNode.create(t.astNode,s,null)}default:throw new Error("unexpected")}}}}),define(ne[236],se([1,0,8,148,201,106,149]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FastTokenizer=e.TextBufferTokenizer=e.Token=void 0;class m{constructor(o,t,i,s,g){this.length=o,this.kind=t,this.bracketId=i,this.bracketIds=s,this.astNode=g}}e.Token=m;class _{constructor(o,t){this.textModel=o,this.bracketTokens=t,this.reader=new b(this.textModel,this.bracketTokens),this._offset=E.lengthZero,this.didPeek=!1,this.peeked=null,this.textBufferLineCount=o.getLineCount(),this.textBufferLastLineLength=o.getLineLength(this.textBufferLineCount)}get offset(){return this._offset}get length(){return(0,E.toLength)(this.textBufferLineCount-1,this.textBufferLastLineLength)}skip(o){this.didPeek=!1,this._offset=(0,E.lengthAdd)(this._offset,o);const t=(0,E.lengthToObj)(this._offset);this.reader.setPosition(t.lineCount,t.columnCount)}read(){let o;return this.peeked?(this.didPeek=!1,o=this.peeked):o=this.reader.read(),o&&(this._offset=(0,E.lengthAdd)(this._offset,o.length)),o}peek(){return this.didPeek||(this.peeked=this.reader.read(),this.didPeek=!0),this.peeked}}e.TextBufferTokenizer=_;class b{constructor(o,t){this.textModel=o,this.bracketTokens=t,this.lineIdx=0,this.line=null,this.lineCharOffset=0,this.lineTokens=null,this.lineTokenOffset=0,this.peekedToken=null,this.textBufferLineCount=o.getLineCount(),this.textBufferLastLineLength=o.getLineLength(this.textBufferLineCount)}setPosition(o,t){o===this.lineIdx?(this.lineCharOffset=t,this.line!==null&&(this.lineTokenOffset=this.lineCharOffset===0?0:this.lineTokens.findTokenIndexAtOffset(this.lineCharOffset))):(this.lineIdx=o,this.lineCharOffset=t,this.line=null),this.peekedToken=null}read(){if(this.peekedToken){const g=this.peekedToken;return this.peekedToken=null,this.lineCharOffset+=(0,E.lengthGetColumnCountIfZeroLineCount)(g.length),g}if(this.lineIdx>this.textBufferLineCount-1||this.lineIdx===this.textBufferLineCount-1&&this.lineCharOffset>=this.textBufferLastLineLength)return null;this.line===null&&(this.lineTokens=this.textModel.tokenization.getLineTokens(this.lineIdx+1),this.line=this.lineTokens.getLineContent(),this.lineTokenOffset=this.lineCharOffset===0?0:this.lineTokens.findTokenIndexAtOffset(this.lineCharOffset));const o=this.lineIdx,t=this.lineCharOffset;let i=0;for(;;){const g=this.lineTokens,c=g.getCount();let l=null;if(this.lineTokenOffset1e3))break;if(i>1500)break}const s=(0,E.lengthDiff)(o,t,this.lineIdx,this.lineCharOffset);return new m(s,0,-1,y.SmallImmutableSet.getEmpty(),new I.TextAstNode(s))}}class p{constructor(o,t){this.text=o,this._offset=E.lengthZero,this.idx=0;const i=t.getRegExpStr(),s=i?new RegExp(i+`| `,"gi"):null,g=[];let c,l=0,a=0,r=0,u=0;const C=[];for(let v=0;v<60;v++)C.push(new m((0,E.toLength)(0,v),0,-1,y.SmallImmutableSet.getEmpty(),new I.TextAstNode((0,E.toLength)(0,v))));const f=[];for(let v=0;v<60;v++)f.push(new m((0,E.toLength)(1,v),0,-1,y.SmallImmutableSet.getEmpty(),new I.TextAstNode((0,E.toLength)(1,v))));if(s)for(s.lastIndex=0;(c=s.exec(o))!==null;){const v=c.index,w=c[0];if(w===` `)l++,a=v+1;else{if(r!==v){let S;if(u===l){const L=v-r;if(L_(o)).join("|")}}get regExpGlobal(){if(!this.hasRegExp){const n=this.getRegExpStr();this._regExpGlobal=n?new RegExp(n,"gi"):null,this.hasRegExp=!0}return this._regExpGlobal}getToken(n){return this.map.get(n.toLowerCase())}findClosingTokenText(n){for(const[o,t]of this.map)if(t.kind===2&&t.bracketIds.intersects(n))return o}get isEmpty(){return this.map.size===0}}e.BracketTokens=m;function _(p){let n=(0,d.escapeRegExpCharacters)(p);return/^[\w ]+/.test(p)&&(n=`\\b${n}`),/[\w ]+$/.test(p)&&(n=`${n}\\b`),n}class b{constructor(n,o){this.denseKeyProvider=n,this.getLanguageConfiguration=o,this.languageIdToBracketTokens=new Map}didLanguageChange(n){return this.languageIdToBracketTokens.has(n)}getSingleLanguageBracketTokens(n){let o=this.languageIdToBracketTokens.get(n);return o||(o=m.createFromLanguage(this.getLanguageConfiguration(n),this.denseKeyProvider),this.languageIdToBracketTokens.set(n,o)),o}}e.LanguageAgnosticBracketTokens=b}),define(ne[575],se([1,0,321,106,320,149,236]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.fixBracketsInLine=m;function m(b,p){const n=new E.DenseKeyProvider,o=new d.LanguageAgnosticBracketTokens(n,l=>p.getLanguageConfiguration(l)),t=new y.TextBufferTokenizer(new _([b]),o),i=(0,I.parseDocument)(t,[],void 0,!0);let s="";const g=b.getLineContent();function c(l,a){if(l.kind===2)if(c(l.openingBracket,a),a=(0,k.lengthAdd)(a,l.openingBracket.length),l.child&&(c(l.child,a),a=(0,k.lengthAdd)(a,l.child.length)),l.closingBracket)c(l.closingBracket,a),a=(0,k.lengthAdd)(a,l.closingBracket.length);else{const u=o.getSingleLanguageBracketTokens(l.openingBracket.languageId).findClosingTokenText(l.openingBracket.bracketIds);s+=u}else if(l.kind!==3){if(l.kind===0||l.kind===1)s+=g.substring((0,k.lengthGetColumnCountIfZeroLineCount)(a),(0,k.lengthGetColumnCountIfZeroLineCount)((0,k.lengthAdd)(a,l.length)));else if(l.kind===4)for(const r of l.children)c(r,a),a=(0,k.lengthAdd)(a,r.length)}}return c(i,k.lengthZero),s}class _{constructor(p){this.lines=p,this.tokenization={getLineTokens:n=>this.lines[n-1]}}getLineCount(){return this.lines.length}getLineLength(p){return this.lines[p-1].getLineContent().length}}}),define(ne[576],se([1,0,13]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FixedArray=void 0;class k{constructor(y){this._default=y,this._store=[]}get(y){return y=this._store.length;)this._store[this._store.length]=this._default;this._store[y]=m}replace(y,m,_){if(y>=this._store.length)return;if(m===0){this.insert(y,_);return}else if(_===0){this.delete(y,m);return}const b=this._store.slice(0,y),p=this._store.slice(y+m),n=I(_,this._default);this._store=b.concat(n,p)}delete(y,m){m===0||y>=this._store.length||this._store.splice(y,m)}insert(y,m){if(m===0||y>=this._store.length)return;const _=[];for(let b=0;b0&&o>0||t>0&&i>0)return;const s=Math.abs(o-i),g=Math.abs(n-t);if(s===0){b.spacesDiff=g,g>0&&0<=t-1&&t-10?b++:v>1&&p++,k(n,o,u,h,g),g.looksLikeAlignment&&!(m&&y===g.spacesDiff)))continue;const S=g.spacesDiff;S<=i&&s[S]++,n=u,o=h}let c=m;b!==p&&(c=b{const u=s[r];u>a&&(a=u,l=r)}),l===4&&s[4]>0&&s[2]>0&&s[2]>=s[4]/2&&(l=2)}return{insertSpaces:c,tabSize:l}}}),define(ne[578],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IntervalTree=e.SENTINEL=e.IntervalNode=void 0,e.getNodeColor=d,e.nodeAcceptEdit=l,e.recomputeMaxEnd=P,e.intervalCompare=O;function d(F){return(F.metadata&1)>>>0}function k(F,x){F.metadata=F.metadata&254|x<<0}function I(F){return(F.metadata&2)>>>1===1}function E(F,x){F.metadata=F.metadata&253|(x?1:0)<<1}function y(F){return(F.metadata&4)>>>2===1}function m(F,x){F.metadata=F.metadata&251|(x?1:0)<<2}function _(F){return(F.metadata&64)>>>6===1}function b(F,x){F.metadata=F.metadata&191|(x?1:0)<<6}function p(F){return(F.metadata&24)>>>3}function n(F,x){F.metadata=F.metadata&231|x<<3}function o(F){return(F.metadata&32)>>>5===1}function t(F,x){F.metadata=F.metadata&223|(x?1:0)<<5}class i{constructor(x,W,V){this.metadata=0,this.parent=this,this.left=this,this.right=this,k(this,1),this.start=W,this.end=V,this.delta=0,this.maxEnd=V,this.id=x,this.ownerId=0,this.options=null,m(this,!1),b(this,!1),n(this,1),t(this,!1),this.cachedVersionId=0,this.cachedAbsoluteStart=W,this.cachedAbsoluteEnd=V,this.range=null,E(this,!1)}reset(x,W,V,q){this.start=W,this.end=V,this.maxEnd=V,this.cachedVersionId=x,this.cachedAbsoluteStart=W,this.cachedAbsoluteEnd=V,this.range=q}setOptions(x){this.options=x;const W=this.options.className;m(this,W==="squiggly-error"||W==="squiggly-warning"||W==="squiggly-info"),b(this,this.options.glyphMarginClassName!==null),n(this,this.options.stickiness),t(this,this.options.collapseOnReplaceEdit)}setCachedOffsets(x,W,V){this.cachedVersionId!==V&&(this.range=null),this.cachedVersionId=V,this.cachedAbsoluteStart=x,this.cachedAbsoluteEnd=W}detach(){this.parent=null,this.left=null,this.right=null}}e.IntervalNode=i,e.SENTINEL=new i(null,0,0),e.SENTINEL.parent=e.SENTINEL,e.SENTINEL.left=e.SENTINEL,e.SENTINEL.right=e.SENTINEL,k(e.SENTINEL,0);class s{constructor(){this.root=e.SENTINEL,this.requestNormalizeDelta=!1}intervalSearch(x,W,V,q,H,z){return this.root===e.SENTINEL?[]:h(this,x,W,V,q,H,z)}search(x,W,V,q){return this.root===e.SENTINEL?[]:f(this,x,W,V,q)}collectNodesFromOwner(x){return u(this,x)}collectNodesPostOrder(){return C(this)}insert(x){v(this,x),this._normalizeDeltaIfNecessary()}delete(x){S(this,x),this._normalizeDeltaIfNecessary()}resolveNode(x,W){const V=x;let q=0;for(;x!==this.root;)x===x.parent.right&&(q+=x.parent.delta),x=x.parent;const H=V.start+q,z=V.end+q;V.setCachedOffsets(H,z,W)}acceptReplace(x,W,V,q){const H=a(this,x,x+W);for(let z=0,U=H.length;zW||V===1?!1:V===2?!0:x}function l(F,x,W,V,q){const H=p(F),z=H===0||H===2,U=H===1||H===2,j=W-x,Y=V,G=Math.min(j,Y),K=F.start;let R=!1;const J=F.end;let ie=!1;x<=K&&J<=W&&o(F)&&(F.start=x,R=!0,F.end=x,ie=!0);{const he=q?1:j>0?2:0;!R&&c(K,z,x,he)&&(R=!0),!ie&&c(J,U,x,he)&&(ie=!0)}if(G>0&&!q){const he=j>Y?2:0;!R&&c(K,z,x+G,he)&&(R=!0),!ie&&c(J,U,x+G,he)&&(ie=!0)}{const he=q?1:0;!R&&c(K,z,W,he)&&(F.start=x+Y,R=!0),!ie&&c(J,U,W,he)&&(F.end=x+Y,ie=!0)}const ue=Y-j;R||(F.start=Math.max(0,K+ue)),ie||(F.end=Math.max(0,J+ue)),F.start>F.end&&(F.end=F.start)}function a(F,x,W){let V=F.root,q=0,H=0,z=0,U=0;const j=[];let Y=0;for(;V!==e.SENTINEL;){if(I(V)){E(V.left,!1),E(V.right,!1),V===V.parent.right&&(q-=V.parent.delta),V=V.parent;continue}if(!I(V.left)){if(H=q+V.maxEnd,HW){E(V,!0);continue}if(U=q+V.end,U>=x&&(V.setCachedOffsets(z,U,0),j[Y++]=V),E(V,!0),V.right!==e.SENTINEL&&!I(V.right)){q+=V.delta,V=V.right;continue}}return E(F.root,!1),j}function r(F,x,W,V){let q=F.root,H=0,z=0,U=0;const j=V-(W-x);for(;q!==e.SENTINEL;){if(I(q)){E(q.left,!1),E(q.right,!1),q===q.parent.right&&(H-=q.parent.delta),P(q),q=q.parent;continue}if(!I(q.left)){if(z=H+q.maxEnd,zW){q.start+=j,q.end+=j,q.delta+=j,(q.delta<-1073741824||q.delta>1073741824)&&(F.requestNormalizeDelta=!0),E(q,!0);continue}if(E(q,!0),q.right!==e.SENTINEL&&!I(q.right)){H+=q.delta,q=q.right;continue}}E(F.root,!1)}function u(F,x){let W=F.root;const V=[];let q=0;for(;W!==e.SENTINEL;){if(I(W)){E(W.left,!1),E(W.right,!1),W=W.parent;continue}if(W.left!==e.SENTINEL&&!I(W.left)){W=W.left;continue}if(W.ownerId===x&&(V[q++]=W),E(W,!0),W.right!==e.SENTINEL&&!I(W.right)){W=W.right;continue}}return E(F.root,!1),V}function C(F){let x=F.root;const W=[];let V=0;for(;x!==e.SENTINEL;){if(I(x)){E(x.left,!1),E(x.right,!1),x=x.parent;continue}if(x.left!==e.SENTINEL&&!I(x.left)){x=x.left;continue}if(x.right!==e.SENTINEL&&!I(x.right)){x=x.right;continue}W[V++]=x,E(x,!0)}return E(F.root,!1),W}function f(F,x,W,V,q){let H=F.root,z=0,U=0,j=0;const Y=[];let G=0;for(;H!==e.SENTINEL;){if(I(H)){E(H.left,!1),E(H.right,!1),H===H.parent.right&&(z-=H.parent.delta),H=H.parent;continue}if(H.left!==e.SENTINEL&&!I(H.left)){H=H.left;continue}U=z+H.start,j=z+H.end,H.setCachedOffsets(U,j,V);let K=!0;if(x&&H.ownerId&&H.ownerId!==x&&(K=!1),W&&y(H)&&(K=!1),q&&!_(H)&&(K=!1),K&&(Y[G++]=H),E(H,!0),H.right!==e.SENTINEL&&!I(H.right)){z+=H.delta,H=H.right;continue}}return E(F.root,!1),Y}function h(F,x,W,V,q,H,z){let U=F.root,j=0,Y=0,G=0,K=0;const R=[];let J=0;for(;U!==e.SENTINEL;){if(I(U)){E(U.left,!1),E(U.right,!1),U===U.parent.right&&(j-=U.parent.delta),U=U.parent;continue}if(!I(U.left)){if(Y=j+U.maxEnd,YW){E(U,!0);continue}if(K=j+U.end,K>=x){U.setCachedOffsets(G,K,H);let ie=!0;V&&U.ownerId&&U.ownerId!==V&&(ie=!1),q&&y(U)&&(ie=!1),z&&!_(U)&&(ie=!1),ie&&(R[J++]=U)}if(E(U,!0),U.right!==e.SENTINEL&&!I(U.right)){j+=U.delta,U=U.right;continue}}return E(F.root,!1),R}function v(F,x){if(F.root===e.SENTINEL)return x.parent=e.SENTINEL,x.left=e.SENTINEL,x.right=e.SENTINEL,k(x,0),F.root=x,F.root;w(F,x),N(x.parent);let W=x;for(;W!==F.root&&d(W.parent)===1;)if(W.parent===W.parent.parent.left){const V=W.parent.parent.right;d(V)===1?(k(W.parent,0),k(V,0),k(W.parent.parent,1),W=W.parent.parent):(W===W.parent.right&&(W=W.parent,T(F,W)),k(W.parent,0),k(W.parent.parent,1),M(F,W.parent.parent))}else{const V=W.parent.parent.left;d(V)===1?(k(W.parent,0),k(V,0),k(W.parent.parent,1),W=W.parent.parent):(W===W.parent.left&&(W=W.parent,M(F,W)),k(W.parent,0),k(W.parent.parent,1),T(F,W.parent.parent))}return k(F.root,0),x}function w(F,x){let W=0,V=F.root;const q=x.start,H=x.end;for(;;)if(O(q,H,V.start+W,V.end+W)<0)if(V.left===e.SENTINEL){x.start-=W,x.end-=W,x.maxEnd-=W,V.left=x;break}else V=V.left;else if(V.right===e.SENTINEL){x.start-=W+V.delta,x.end-=W+V.delta,x.maxEnd-=W+V.delta,V.right=x;break}else W+=V.delta,V=V.right;x.parent=V,x.left=e.SENTINEL,x.right=e.SENTINEL,k(x,1)}function S(F,x){let W,V;if(x.left===e.SENTINEL?(W=x.right,V=x,W.delta+=x.delta,(W.delta<-1073741824||W.delta>1073741824)&&(F.requestNormalizeDelta=!0),W.start+=x.delta,W.end+=x.delta):x.right===e.SENTINEL?(W=x.left,V=x):(V=L(x.right),W=V.right,W.start+=V.delta,W.end+=V.delta,W.delta+=V.delta,(W.delta<-1073741824||W.delta>1073741824)&&(F.requestNormalizeDelta=!0),V.start+=x.delta,V.end+=x.delta,V.delta=x.delta,(V.delta<-1073741824||V.delta>1073741824)&&(F.requestNormalizeDelta=!0)),V===F.root){F.root=W,k(W,0),x.detach(),D(),P(W),F.root.parent=e.SENTINEL;return}const q=d(V)===1;if(V===V.parent.left?V.parent.left=W:V.parent.right=W,V===x?W.parent=V.parent:(V.parent===x?W.parent=V:W.parent=V.parent,V.left=x.left,V.right=x.right,V.parent=x.parent,k(V,d(x)),x===F.root?F.root=V:x===x.parent.left?x.parent.left=V:x.parent.right=V,V.left!==e.SENTINEL&&(V.left.parent=V),V.right!==e.SENTINEL&&(V.right.parent=V)),x.detach(),q){N(W.parent),V!==x&&(N(V),N(V.parent)),D();return}N(W),N(W.parent),V!==x&&(N(V),N(V.parent));let H;for(;W!==F.root&&d(W)===0;)W===W.parent.left?(H=W.parent.right,d(H)===1&&(k(H,0),k(W.parent,1),T(F,W.parent),H=W.parent.right),d(H.left)===0&&d(H.right)===0?(k(H,1),W=W.parent):(d(H.right)===0&&(k(H.left,0),k(H,1),M(F,H),H=W.parent.right),k(H,d(W.parent)),k(W.parent,0),k(H.right,0),T(F,W.parent),W=F.root)):(H=W.parent.left,d(H)===1&&(k(H,0),k(W.parent,1),M(F,W.parent),H=W.parent.left),d(H.left)===0&&d(H.right)===0?(k(H,1),W=W.parent):(d(H.left)===0&&(k(H.right,0),k(H,1),T(F,H),H=W.parent.left),k(H,d(W.parent)),k(W.parent,0),k(H.left,0),M(F,W.parent),W=F.root));k(W,0),D()}function L(F){for(;F.left!==e.SENTINEL;)F=F.left;return F}function D(){e.SENTINEL.parent=e.SENTINEL,e.SENTINEL.delta=0,e.SENTINEL.start=0,e.SENTINEL.end=0}function T(F,x){const W=x.right;W.delta+=x.delta,(W.delta<-1073741824||W.delta>1073741824)&&(F.requestNormalizeDelta=!0),W.start+=x.delta,W.end+=x.delta,x.right=W.left,W.left!==e.SENTINEL&&(W.left.parent=x),W.parent=x.parent,x.parent===e.SENTINEL?F.root=W:x===x.parent.left?x.parent.left=W:x.parent.right=W,W.left=x,x.parent=W,P(x),P(W)}function M(F,x){const W=x.left;x.delta-=W.delta,(x.delta<-1073741824||x.delta>1073741824)&&(F.requestNormalizeDelta=!0),x.start-=W.delta,x.end-=W.delta,x.left=W.right,W.right!==e.SENTINEL&&(W.right.parent=x),W.parent=x.parent,x.parent===e.SENTINEL?F.root=W:x===x.parent.right?x.parent.right=W:x.parent.left=W,W.right=x,x.parent=W,P(x),P(W)}function A(F){let x=F.end;if(F.left!==e.SENTINEL){const W=F.left.maxEnd;W>x&&(x=W)}if(F.right!==e.SENTINEL){const W=F.right.maxEnd+F.delta;W>x&&(x=W)}return x}function P(F){F.maxEnd=A(F)}function N(F){for(;F!==e.SENTINEL;){const x=A(F);if(F.maxEnd===x)return;F.maxEnd=x,F=F.parent}}function O(F,x,W,V){return F===W?x-V:F-W}}),define(ne[579],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SENTINEL=e.TreeNode=void 0,e.leftest=k,e.righttest=I,e.leftRotate=_,e.rightRotate=b,e.rbDelete=p,e.fixInsert=n,e.updateTreeMetadata=o,e.recomputeTreeMetadata=t;class d{constructor(s,g){this.piece=s,this.color=g,this.size_left=0,this.lf_left=0,this.parent=this,this.left=this,this.right=this}next(){if(this.right!==e.SENTINEL)return k(this.right);let s=this;for(;s.parent!==e.SENTINEL&&s.parent.left!==s;)s=s.parent;return s.parent===e.SENTINEL?e.SENTINEL:s.parent}prev(){if(this.left!==e.SENTINEL)return I(this.left);let s=this;for(;s.parent!==e.SENTINEL&&s.parent.right!==s;)s=s.parent;return s.parent===e.SENTINEL?e.SENTINEL:s.parent}detach(){this.parent=null,this.left=null,this.right=null}}e.TreeNode=d,e.SENTINEL=new d(null,0),e.SENTINEL.parent=e.SENTINEL,e.SENTINEL.left=e.SENTINEL,e.SENTINEL.right=e.SENTINEL,e.SENTINEL.color=0;function k(i){for(;i.left!==e.SENTINEL;)i=i.left;return i}function I(i){for(;i.right!==e.SENTINEL;)i=i.right;return i}function E(i){return i===e.SENTINEL?0:i.size_left+i.piece.length+E(i.right)}function y(i){return i===e.SENTINEL?0:i.lf_left+i.piece.lineFeedCnt+y(i.right)}function m(){e.SENTINEL.parent=e.SENTINEL}function _(i,s){const g=s.right;g.size_left+=s.size_left+(s.piece?s.piece.length:0),g.lf_left+=s.lf_left+(s.piece?s.piece.lineFeedCnt:0),s.right=g.left,g.left!==e.SENTINEL&&(g.left.parent=s),g.parent=s.parent,s.parent===e.SENTINEL?i.root=g:s.parent.left===s?s.parent.left=g:s.parent.right=g,g.left=s,s.parent=g}function b(i,s){const g=s.left;s.left=g.right,g.right!==e.SENTINEL&&(g.right.parent=s),g.parent=s.parent,s.size_left-=g.size_left+(g.piece?g.piece.length:0),s.lf_left-=g.lf_left+(g.piece?g.piece.lineFeedCnt:0),s.parent===e.SENTINEL?i.root=g:s===s.parent.right?s.parent.right=g:s.parent.left=g,g.right=s,s.parent=g}function p(i,s){let g,c;if(s.left===e.SENTINEL?(c=s,g=c.right):s.right===e.SENTINEL?(c=s,g=c.left):(c=k(s.right),g=c.right),c===i.root){i.root=g,g.color=0,s.detach(),m(),i.root.parent=e.SENTINEL;return}const l=c.color===1;if(c===c.parent.left?c.parent.left=g:c.parent.right=g,c===s?(g.parent=c.parent,t(i,g)):(c.parent===s?g.parent=c:g.parent=c.parent,t(i,g),c.left=s.left,c.right=s.right,c.parent=s.parent,c.color=s.color,s===i.root?i.root=c:s===s.parent.left?s.parent.left=c:s.parent.right=c,c.left!==e.SENTINEL&&(c.left.parent=c),c.right!==e.SENTINEL&&(c.right.parent=c),c.size_left=s.size_left,c.lf_left=s.lf_left,t(i,c)),s.detach(),g.parent.left===g){const r=E(g),u=y(g);if(r!==g.parent.size_left||u!==g.parent.lf_left){const C=r-g.parent.size_left,f=u-g.parent.lf_left;g.parent.size_left=r,g.parent.lf_left=u,o(i,g.parent,C,f)}}if(t(i,g.parent),l){m();return}let a;for(;g!==i.root&&g.color===0;)g===g.parent.left?(a=g.parent.right,a.color===1&&(a.color=0,g.parent.color=1,_(i,g.parent),a=g.parent.right),a.left.color===0&&a.right.color===0?(a.color=1,g=g.parent):(a.right.color===0&&(a.left.color=0,a.color=1,b(i,a),a=g.parent.right),a.color=g.parent.color,g.parent.color=0,a.right.color=0,_(i,g.parent),g=i.root)):(a=g.parent.left,a.color===1&&(a.color=0,g.parent.color=1,b(i,g.parent),a=g.parent.left),a.left.color===0&&a.right.color===0?(a.color=1,g=g.parent):(a.left.color===0&&(a.right.color=0,a.color=1,_(i,a),a=g.parent.left),a.color=g.parent.color,g.parent.color=0,a.left.color=0,b(i,g.parent),g=i.root));g.color=0,m()}function n(i,s){for(t(i,s);s!==i.root&&s.parent.color===1;)if(s.parent===s.parent.parent.left){const g=s.parent.parent.right;g.color===1?(s.parent.color=0,g.color=0,s.parent.parent.color=1,s=s.parent.parent):(s===s.parent.right&&(s=s.parent,_(i,s)),s.parent.color=0,s.parent.parent.color=1,b(i,s.parent.parent))}else{const g=s.parent.parent.left;g.color===1?(s.parent.color=0,g.color=0,s.parent.parent.color=1,s=s.parent.parent):(s===s.parent.left&&(s=s.parent,b(i,s)),s.parent.color=0,s.parent.parent.color=1,_(i,s.parent.parent))}i.root.color=0}function o(i,s,g,c){for(;s!==i.root&&s!==e.SENTINEL;)s.parent.left===s&&(s.parent.size_left+=g,s.parent.lf_left+=c),s=s.parent}function t(i,s){let g=0,c=0;if(s!==i.root){for(;s!==i.root&&s===s.parent.right;)s=s.parent;if(s!==i.root)for(s=s.parent,g=E(s.left)-s.size_left,c=y(s.left)-s.lf_left,s.size_left+=g,s.lf_left+=c;s!==i.root&&(g!==0||c!==0);)s.parent.left===s&&(s.parent.size_left+=g,s.parent.lf_left+=c),s=s.parent}}}),define(ne[322],se([1,0,13,192]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PrefixSumIndexOfResult=e.ConstantTimePrefixSumComputer=e.PrefixSumComputer=void 0;class I{constructor(_){this.values=_,this.prefixSum=new Uint32Array(_.length),this.prefixSumValidIndex=new Int32Array(1),this.prefixSumValidIndex[0]=-1}insertValues(_,b){_=(0,k.toUint32)(_);const p=this.values,n=this.prefixSum,o=b.length;return o===0?!1:(this.values=new Uint32Array(p.length+o),this.values.set(p.subarray(0,_),0),this.values.set(p.subarray(_),_+o),this.values.set(b,_),_-1=0&&this.prefixSum.set(n.subarray(0,this.prefixSumValidIndex[0]+1)),!0)}setValue(_,b){return _=(0,k.toUint32)(_),b=(0,k.toUint32)(b),this.values[_]===b?!1:(this.values[_]=b,_-1=p.length)return!1;const o=p.length-_;return b>=o&&(b=o),b===0?!1:(this.values=new Uint32Array(p.length-b),this.values.set(p.subarray(0,_),0),this.values.set(p.subarray(_+b),_),this.prefixSum=new Uint32Array(this.values.length),_-1=0&&this.prefixSum.set(n.subarray(0,this.prefixSumValidIndex[0]+1)),!0)}getTotalSum(){return this.values.length===0?0:this._getPrefixSum(this.values.length-1)}getPrefixSum(_){return _<0?0:(_=(0,k.toUint32)(_),this._getPrefixSum(_))}_getPrefixSum(_){if(_<=this.prefixSumValidIndex[0])return this.prefixSum[_];let b=this.prefixSumValidIndex[0]+1;b===0&&(this.prefixSum[0]=this.values[0],b++),_>=this.values.length&&(_=this.values.length-1);for(let p=b;p<=_;p++)this.prefixSum[p]=this.prefixSum[p-1]+this.values[p];return this.prefixSumValidIndex[0]=Math.max(this.prefixSumValidIndex[0],_),this.prefixSum[_]}getIndexOf(_){_=Math.floor(_),this.getTotalSum();let b=0,p=this.values.length-1,n=0,o=0,t=0;for(;b<=p;)if(n=b+(p-b)/2|0,o=this.prefixSum[n],t=o-this.values[n],_=o)b=n+1;else break;return new y(n,_-t)}}e.PrefixSumComputer=I;class E{constructor(_){this._values=_,this._isValid=!1,this._validEndIndex=-1,this._prefixSum=[],this._indexBySum=[]}getTotalSum(){return this._ensureValid(),this._indexBySum.length}getPrefixSum(_){return this._ensureValid(),_===0?0:this._prefixSum[_-1]}getIndexOf(_){this._ensureValid();const b=this._indexBySum[_],p=b>0?this._prefixSum[b-1]:0;return new y(b,_-p)}removeValues(_,b){this._values.splice(_,b),this._invalidate(_)}insertValues(_,b){this._values=(0,d.arrayInsert)(this._values,_,b),this._invalidate(_)}_invalidate(_){this._isValid=!1,this._validEndIndex=Math.min(this._validEndIndex,_-1)}_ensureValid(){if(!this._isValid){for(let _=this._validEndIndex+1,b=this._values.length;_0?this._prefixSum[_-1]:0;this._prefixSum[_]=n+p;for(let o=0;o=0;let a=null;try{a=d.createRegExp(this.searchString,this.isRegex,{matchCase:this.matchCase,wholeWord:!1,multiline:l,global:!0,unicode:!0})}catch{return null}if(!a)return null;let r=!this.isRegex&&!l;return r&&this.searchString.toLowerCase()!==this.searchString.toUpperCase()&&(r=this.matchCase),new y.SearchData(a,this.wordSeparators?(0,k.getMapForWordSeparators)(this.wordSeparators,[]):null,r?this.searchString:null)}}e.SearchParams=_;function b(c){if(!c||c.length===0)return!1;for(let l=0,a=c.length;l=a)break;const u=c.charCodeAt(l);if(u===110||u===114||u===87)return!0}}return!1}function p(c,l,a){if(!a)return new y.FindMatch(c,null);const r=[];for(let u=0,C=l.length;u>0);a[C]>=l?u=C-1:a[C+1]>=l?(r=C,u=C):r=C+1}return r+1}}class o{static findMatches(l,a,r,u,C){const f=a.parseSearchRequest();return f?f.regex.multiline?this._doFindMatchesMultiline(l,r,new g(f.wordSeparators,f.regex),u,C):this._doFindMatchesLineByLine(l,r,f,u,C):[]}static _getMultilineMatchRange(l,a,r,u,C,f){let h,v=0;u?(v=u.findLineFeedCountBeforeOffset(C),h=a+C+v):h=a+C;let w;if(u){const T=u.findLineFeedCountBeforeOffset(C+f.length)-v;w=h+f.length+T}else w=h+f.length;const S=l.getPositionAt(h),L=l.getPositionAt(w);return new E.Range(S.lineNumber,S.column,L.lineNumber,L.column)}static _doFindMatchesMultiline(l,a,r,u,C){const f=l.getOffsetAt(a.getStartPosition()),h=l.getValueInRange(a,1),v=l.getEOL()===`\r `?new n(h):null,w=[];let S=0,L;for(r.reset(0);L=r.next(h);)if(w[S++]=p(this._getMultilineMatchRange(l,f,h,v,L.index,L[0]),L,u),S>=C)return w;return w}static _doFindMatchesLineByLine(l,a,r,u,C){const f=[];let h=0;if(a.startLineNumber===a.endLineNumber){const w=l.getLineContent(a.startLineNumber).substring(a.startColumn-1,a.endColumn-1);return h=this._findMatchesInLine(r,w,a.startLineNumber,a.startColumn-1,h,f,u,C),f}const v=l.getLineContent(a.startLineNumber).substring(a.startColumn-1);h=this._findMatchesInLine(r,v,a.startLineNumber,a.startColumn-1,h,f,u,C);for(let w=a.startLineNumber+1;w=v))return C;return C}const S=new g(l.wordSeparators,l.regex);let L;S.reset(0);do if(L=S.next(a),L&&(f[C++]=p(new E.Range(r,L.index+1+u,r,L.index+1+L[0].length+u),L,h),C>=v))return C;while(L);return C}static findNextMatch(l,a,r,u){const C=a.parseSearchRequest();if(!C)return null;const f=new g(C.wordSeparators,C.regex);return C.regex.multiline?this._doFindNextMatchMultiline(l,r,f,u):this._doFindNextMatchLineByLine(l,r,f,u)}static _doFindNextMatchMultiline(l,a,r,u){const C=new I.Position(a.lineNumber,1),f=l.getOffsetAt(C),h=l.getLineCount(),v=l.getValueInRange(new E.Range(C.lineNumber,C.column,h,l.getLineMaxColumn(h)),1),w=l.getEOL()===`\r `?new n(v):null;r.reset(a.column-1);const S=r.next(v);return S?p(this._getMultilineMatchRange(l,f,v,w,S.index,S[0]),S,u):a.lineNumber!==1||a.column!==1?this._doFindNextMatchMultiline(l,new I.Position(1,1),r,u):null}static _doFindNextMatchLineByLine(l,a,r,u){const C=l.getLineCount(),f=a.lineNumber,h=l.getLineContent(f),v=this._findFirstMatchInLine(r,h,f,a.column,u);if(v)return v;for(let w=1;w<=C;w++){const S=(f+w-1)%C,L=l.getLineContent(S+1),D=this._findFirstMatchInLine(r,L,S+1,1,u);if(D)return D}return null}static _findFirstMatchInLine(l,a,r,u,C){l.reset(u-1);const f=l.next(a);return f?p(new E.Range(r,f.index+1,r,f.index+1+f[0].length),f,C):null}static findPreviousMatch(l,a,r,u){const C=a.parseSearchRequest();if(!C)return null;const f=new g(C.wordSeparators,C.regex);return C.regex.multiline?this._doFindPreviousMatchMultiline(l,r,f,u):this._doFindPreviousMatchLineByLine(l,r,f,u)}static _doFindPreviousMatchMultiline(l,a,r,u){const C=this._doFindMatchesMultiline(l,new E.Range(1,1,a.lineNumber,a.column),r,u,10*m);if(C.length>0)return C[C.length-1];const f=l.getLineCount();return a.lineNumber!==f||a.column!==l.getLineMaxColumn(f)?this._doFindPreviousMatchMultiline(l,new I.Position(f,l.getLineMaxColumn(f)),r,u):null}static _doFindPreviousMatchLineByLine(l,a,r,u){const C=l.getLineCount(),f=a.lineNumber,h=l.getLineContent(f).substring(0,a.column-1),v=this._findLastMatchInLine(r,h,f,u);if(v)return v;for(let w=1;w<=C;w++){const S=(C+f-w-1)%C,L=l.getLineContent(S+1),D=this._findLastMatchInLine(r,L,S+1,u);if(D)return D}return null}static _findLastMatchInLine(l,a,r,u){let C=null,f;for(l.reset(0);f=l.next(a);)C=p(new E.Range(r,f.index+1,r,f.index+1+f[0].length),f,u);return C}}e.TextModelSearch=o;function t(c,l,a,r,u){if(r===0)return!0;const C=l.charCodeAt(r-1);if(c.get(C)!==0||C===13||C===10)return!0;if(u>0){const f=l.charCodeAt(r);if(c.get(f)!==0)return!0}return!1}function i(c,l,a,r,u){if(r+u===a)return!0;const C=l.charCodeAt(r+u);if(c.get(C)!==0||C===13||C===10)return!0;if(u>0){const f=l.charCodeAt(r+u-1);if(c.get(f)!==0)return!0}return!1}function s(c,l,a,r,u){return t(c,l,a,r,u)&&i(c,l,a,r,u)}class g{constructor(l,a){this._wordSeparators=l,this._searchRegex=a,this._prevMatchStartIndex=-1,this._prevMatchLength=0}reset(l){this._searchRegex.lastIndex=l,this._prevMatchStartIndex=-1,this._prevMatchLength=0}next(l){const a=l.length;let r;do{if(this._prevMatchStartIndex+this._prevMatchLength===a||(r=this._searchRegex.exec(l),!r))return null;const u=r.index,C=r[0].length;if(u===this._prevMatchStartIndex&&C===this._prevMatchLength){if(C===0){d.getNextCodePoint(l,a,this._searchRegex.lastIndex)>65535?this._searchRegex.lastIndex+=2:this._searchRegex.lastIndex+=1;continue}return null}if(this._prevMatchStartIndex=u,this._prevMatchLength=C,!this._wordSeparators||s(this._wordSeparators,l,a,u,C))return r}while(r);return null}}e.Searcher=g}),define(ne[324],se([1,0,9,4,40,579,202]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PieceTreeBase=e.StringBuffer=e.Piece=void 0,e.createLineStartsFast=p,e.createLineStarts=n;const m=65535;function _(c){let l;return c[c.length-1]<65536?l=new Uint16Array(c.length):l=new Uint32Array(c.length),l.set(c,0),l}class b{constructor(l,a,r,u,C){this.lineStarts=l,this.cr=a,this.lf=r,this.crlf=u,this.isBasicASCII=C}}function p(c,l=!0){const a=[0];let r=1;for(let u=0,C=c.length;u126)&&(f=!1)}const h=new b(_(c),r,u,C,f);return c.length=0,h}class o{constructor(l,a,r,u,C){this.bufferIndex=l,this.start=a,this.end=r,this.lineFeedCnt=u,this.length=C}}e.Piece=o;class t{constructor(l,a){this.buffer=l,this.lineStarts=a}}e.StringBuffer=t;class i{constructor(l,a){this._pieces=[],this._tree=l,this._BOM=a,this._index=0,l.root!==E.SENTINEL&&l.iterate(l.root,r=>(r!==E.SENTINEL&&this._pieces.push(r.piece),!0))}read(){return this._pieces.length===0?this._index===0?(this._index++,this._BOM):null:this._index>this._pieces.length-1?null:this._index===0?this._BOM+this._tree.getPieceContent(this._pieces[this._index++]):this._tree.getPieceContent(this._pieces[this._index++])}}class s{constructor(l){this._limit=l,this._cache=[]}get(l){for(let a=this._cache.length-1;a>=0;a--){const r=this._cache[a];if(r.nodeStartOffset<=l&&r.nodeStartOffset+r.node.piece.length>=l)return r}return null}get2(l){for(let a=this._cache.length-1;a>=0;a--){const r=this._cache[a];if(r.nodeStartLineNumber&&r.nodeStartLineNumber=l)return r}return null}set(l){this._cache.length>=this._limit&&this._cache.shift(),this._cache.push(l)}validate(l){let a=!1;const r=this._cache;for(let u=0;u=l){r[u]=null,a=!0;continue}}if(a){const u=[];for(const C of r)C!==null&&u.push(C);this._cache=u}}}class g{constructor(l,a,r){this.create(l,a,r)}create(l,a,r){this._buffers=[new t("",[0])],this._lastChangeBufferPos={line:0,column:0},this.root=E.SENTINEL,this._lineCnt=1,this._length=0,this._EOL=a,this._EOLLength=a.length,this._EOLNormalized=r;let u=null;for(let C=0,f=l.length;C0){l[C].lineStarts||(l[C].lineStarts=p(l[C].buffer));const h=new o(C+1,{line:0,column:0},{line:l[C].lineStarts.length-1,column:l[C].buffer.length-l[C].lineStarts[l[C].lineStarts.length-1]},l[C].lineStarts.length-1,l[C].buffer.length);this._buffers.push(l[C]),u=this.rbInsertRight(u,h)}this._searchCache=new s(1),this._lastVisitedLine={lineNumber:0,value:""},this.computeBufferMetadata()}normalizeEOL(l){const a=m,r=a-Math.floor(a/3),u=r*2;let C="",f=0;const h=[];if(this.iterate(this.root,v=>{const w=this.getNodeContent(v),S=w.length;if(f<=r||f+S0){const v=C.replace(/\r\n|\r|\n/g,l);h.push(new t(v,p(v)))}this.create(h,l,!0)}getEOL(){return this._EOL}setEOL(l){this._EOL=l,this._EOLLength=this._EOL.length,this.normalizeEOL(l)}createSnapshot(l){return new i(this,l)}getOffsetAt(l,a){let r=0,u=this.root;for(;u!==E.SENTINEL;)if(u.left!==E.SENTINEL&&u.lf_left+1>=l)u=u.left;else if(u.lf_left+u.piece.lineFeedCnt+1>=l){r+=u.size_left;const C=this.getAccumulatedValue(u,l-u.lf_left-2);return r+=C+a-1}else l-=u.lf_left+u.piece.lineFeedCnt,r+=u.size_left+u.piece.length,u=u.right;return r}getPositionAt(l){l=Math.floor(l),l=Math.max(0,l);let a=this.root,r=0;const u=l;for(;a!==E.SENTINEL;)if(a.size_left!==0&&a.size_left>=l)a=a.left;else if(a.size_left+a.piece.length>=l){const C=this.getIndexOf(a,l-a.size_left);if(r+=a.lf_left+C.index,C.index===0){const f=this.getOffsetAt(r+1,1),h=u-f;return new d.Position(r+1,h+1)}return new d.Position(r+1,C.remainder+1)}else if(l-=a.size_left+a.piece.length,r+=a.lf_left+a.piece.lineFeedCnt,a.right===E.SENTINEL){const C=this.getOffsetAt(r+1,1),f=u-l-C;return new d.Position(r+1,f+1)}else a=a.right;return new d.Position(1,1)}getValueInRange(l,a){if(l.startLineNumber===l.endLineNumber&&l.startColumn===l.endColumn)return"";const r=this.nodeAt2(l.startLineNumber,l.startColumn),u=this.nodeAt2(l.endLineNumber,l.endColumn),C=this.getValueInRange2(r,u);return a?a!==this._EOL||!this._EOLNormalized?C.replace(/\r\n|\r|\n/g,a):a===this.getEOL()&&this._EOLNormalized?C:C.replace(/\r\n|\r|\n/g,a):C}getValueInRange2(l,a){if(l.node===a.node){const h=l.node,v=this._buffers[h.piece.bufferIndex].buffer,w=this.offsetInBuffer(h.piece.bufferIndex,h.piece.start);return v.substring(w+l.remainder,w+a.remainder)}let r=l.node;const u=this._buffers[r.piece.bufferIndex].buffer,C=this.offsetInBuffer(r.piece.bufferIndex,r.piece.start);let f=u.substring(C+l.remainder,C+r.piece.length);for(r=r.next();r!==E.SENTINEL;){const h=this._buffers[r.piece.bufferIndex].buffer,v=this.offsetInBuffer(r.piece.bufferIndex,r.piece.start);if(r===a.node){f+=h.substring(v,v+a.remainder);break}else f+=h.substr(v,r.piece.length);r=r.next()}return f}getLinesContent(){const l=[];let a=0,r="",u=!1;return this.iterate(this.root,C=>{if(C===E.SENTINEL)return!0;const f=C.piece;let h=f.length;if(h===0)return!0;const v=this._buffers[f.bufferIndex].buffer,w=this._buffers[f.bufferIndex].lineStarts,S=f.start.line,L=f.end.line;let D=w[S]+f.start.column;if(u&&(v.charCodeAt(D)===10&&(D++,h--),l[a++]=r,r="",u=!1,h===0))return!0;if(S===L)return!this._EOLNormalized&&v.charCodeAt(D+h-1)===13?(u=!0,r+=v.substr(D,h-1)):r+=v.substr(D,h),!0;r+=this._EOLNormalized?v.substring(D,Math.max(D,w[S+1]-this._EOLLength)):v.substring(D,w[S+1]).replace(/(\r\n|\r|\n)$/,""),l[a++]=r;for(let T=S+1;Tx+M,a.reset(0)):(O=D.buffer,F=x=>x,a.reset(M));do if(P=a.next(O),P){if(F(P.index)>=A)return S;this.positionInBuffer(l,F(P.index)-T,N);const x=this.getLineFeedCnt(l.piece.bufferIndex,C,N),W=N.line===C.line?N.column-C.column+u:N.column+1,V=W+P[0].length;if(L[S++]=(0,y.createFindMatch)(new k.Range(r+x,W,r+x,V),P,v),F(P.index)+P[0].length>=A||S>=w)return S}while(P);return S}findMatchesLineByLine(l,a,r,u){const C=[];let f=0;const h=new y.Searcher(a.wordSeparators,a.regex);let v=this.nodeAt2(l.startLineNumber,l.startColumn);if(v===null)return[];const w=this.nodeAt2(l.endLineNumber,l.endColumn);if(w===null)return[];let S=this.positionInBuffer(v.node,v.remainder);const L=this.positionInBuffer(w.node,w.remainder);if(v.node===w.node)return this.findMatchesInNode(v.node,h,l.startLineNumber,l.startColumn,S,L,a,r,u,f,C),C;let D=l.startLineNumber,T=v.node;for(;T!==w.node;){const A=this.getLineFeedCnt(T.piece.bufferIndex,S,T.piece.end);if(A>=1){const N=this._buffers[T.piece.bufferIndex].lineStarts,O=this.offsetInBuffer(T.piece.bufferIndex,T.piece.start),F=N[S.line+A],x=D===l.startLineNumber?l.startColumn:1;if(f=this.findMatchesInNode(T,h,D,x,S,this.positionInBuffer(T,F-O),a,r,u,f,C),f>=u)return C;D+=A}const P=D===l.startLineNumber?l.startColumn-1:0;if(D===l.endLineNumber){const N=this.getLineContent(D).substring(P,l.endColumn-1);return f=this._findMatchesInLine(a,h,N,l.endLineNumber,P,f,C,r,u),C}if(f=this._findMatchesInLine(a,h,this.getLineContent(D).substr(P),D,P,f,C,r,u),f>=u)return C;D++,v=this.nodeAt2(D,1),T=v.node,S=this.positionInBuffer(v.node,v.remainder)}if(D===l.endLineNumber){const A=D===l.startLineNumber?l.startColumn-1:0,P=this.getLineContent(D).substring(A,l.endColumn-1);return f=this._findMatchesInLine(a,h,P,l.endLineNumber,A,f,C,r,u),C}const M=D===l.startLineNumber?l.startColumn:1;return f=this.findMatchesInNode(w.node,h,D,M,S,L,a,r,u,f,C),C}_findMatchesInLine(l,a,r,u,C,f,h,v,w){const S=l.wordSeparators;if(!v&&l.simpleSearch){const D=l.simpleSearch,T=D.length,M=r.length;let A=-T;for(;(A=r.indexOf(D,A+T))!==-1;)if((!S||(0,y.isValidMatch)(S,r,M,A,T))&&(h[f++]=new I.FindMatch(new k.Range(u,A+1+C,u,A+1+T+C),null),f>=w))return f;return f}let L;a.reset(0);do if(L=a.next(r),L&&(h[f++]=(0,y.createFindMatch)(new k.Range(u,L.index+1+C,u,L.index+1+L[0].length+C),L,v),f>=w))return f;while(L);return f}insert(l,a,r=!1){if(this._EOLNormalized=this._EOLNormalized&&r,this._lastVisitedLine.lineNumber=0,this._lastVisitedLine.value="",this.root!==E.SENTINEL){const{node:u,remainder:C,nodeStartOffset:f}=this.nodeAt(l),h=u.piece,v=h.bufferIndex,w=this.positionInBuffer(u,C);if(u.piece.bufferIndex===0&&h.end.line===this._lastChangeBufferPos.line&&h.end.column===this._lastChangeBufferPos.column&&f+h.length===l&&a.lengthl){const S=[];let L=new o(h.bufferIndex,w,h.end,this.getLineFeedCnt(h.bufferIndex,w,h.end),this.offsetInBuffer(v,h.end)-this.offsetInBuffer(v,w));if(this.shouldCheckCRLF()&&this.endWithCR(a)&&this.nodeCharCodeAt(u,C)===10){const A={line:L.start.line+1,column:0};L=new o(L.bufferIndex,A,L.end,this.getLineFeedCnt(L.bufferIndex,A,L.end),L.length-1),a+=` `}if(this.shouldCheckCRLF()&&this.startWithLF(a))if(this.nodeCharCodeAt(u,C-1)===13){const A=this.positionInBuffer(u,C-1);this.deleteNodeTail(u,A),a="\r"+a,u.piece.length===0&&S.push(u)}else this.deleteNodeTail(u,w);else this.deleteNodeTail(u,w);const D=this.createNewPieces(a);L.length>0&&this.rbInsertRight(u,L);let T=u;for(let M=0;M=0;f--)C=this.rbInsertLeft(C,u[f]);this.validateCRLFWithPrevNode(C),this.deleteNodes(r)}insertContentToNodeRight(l,a){this.adjustCarriageReturnFromNext(l,a)&&(l+=` `);const r=this.createNewPieces(l),u=this.rbInsertRight(a,r[0]);let C=u;for(let f=1;f=D)w=L+1;else break;return r?(r.line=L,r.column=v-T,null):{line:L,column:v-T}}getLineFeedCnt(l,a,r){if(r.column===0)return r.line-a.line;const u=this._buffers[l].lineStarts;if(r.line===u.length-1)return r.line-a.line;const C=u[r.line+1],f=u[r.line]+r.column;if(C>f+1)return r.line-a.line;const h=f-1;return this._buffers[l].buffer.charCodeAt(h)===13?r.line-a.line+1:r.line-a.line}offsetInBuffer(l,a){return this._buffers[l].lineStarts[a.line]+a.column}deleteNodes(l){for(let a=0;am){const S=[];for(;l.length>m;){const D=l.charCodeAt(m-1);let T;D===13||D>=55296&&D<=56319?(T=l.substring(0,m-1),l=l.substring(m-1)):(T=l.substring(0,m),l=l.substring(m));const M=p(T);S.push(new o(this._buffers.length,{line:0,column:0},{line:M.length-1,column:T.length-M[M.length-1]},M.length-1,T.length)),this._buffers.push(new t(T,M))}const L=p(l);return S.push(new o(this._buffers.length,{line:0,column:0},{line:L.length-1,column:l.length-L[L.length-1]},L.length-1,l.length)),this._buffers.push(new t(l,L)),S}let a=this._buffers[0].buffer.length;const r=p(l,!1);let u=this._lastChangeBufferPos;if(this._buffers[0].lineStarts[this._buffers[0].lineStarts.length-1]===a&&a!==0&&this.startWithLF(l)&&this.endWithCR(this._buffers[0].buffer)){this._lastChangeBufferPos={line:this._lastChangeBufferPos.line,column:this._lastChangeBufferPos.column+1},u=this._lastChangeBufferPos;for(let S=0;S=l-1)r=r.left;else if(r.lf_left+r.piece.lineFeedCnt>l-1){const v=this.getAccumulatedValue(r,l-r.lf_left-2),w=this.getAccumulatedValue(r,l-r.lf_left-1),S=this._buffers[r.piece.bufferIndex].buffer,L=this.offsetInBuffer(r.piece.bufferIndex,r.piece.start);return f+=r.size_left,this._searchCache.set({node:r,nodeStartOffset:f,nodeStartLineNumber:h-(l-1-r.lf_left)}),S.substring(L+v,L+w-a)}else if(r.lf_left+r.piece.lineFeedCnt===l-1){const v=this.getAccumulatedValue(r,l-r.lf_left-2),w=this._buffers[r.piece.bufferIndex].buffer,S=this.offsetInBuffer(r.piece.bufferIndex,r.piece.start);u=w.substring(S+v,S+r.piece.length);break}else l-=r.lf_left+r.piece.lineFeedCnt,f+=r.size_left+r.piece.length,r=r.right}for(r=r.next();r!==E.SENTINEL;){const f=this._buffers[r.piece.bufferIndex].buffer;if(r.piece.lineFeedCnt>0){const h=this.getAccumulatedValue(r,0),v=this.offsetInBuffer(r.piece.bufferIndex,r.piece.start);return u+=f.substring(v,v+h-a),u}else{const h=this.offsetInBuffer(r.piece.bufferIndex,r.piece.start);u+=f.substr(h,r.piece.length)}r=r.next()}return u}computeBufferMetadata(){let l=this.root,a=1,r=0;for(;l!==E.SENTINEL;)a+=l.lf_left+l.piece.lineFeedCnt,r+=l.size_left+l.piece.length,l=l.right;this._lineCnt=a,this._length=r,this._searchCache.validate(this._length)}getIndexOf(l,a){const r=l.piece,u=this.positionInBuffer(l,a),C=u.line-r.start.line;if(this.offsetInBuffer(r.bufferIndex,r.end)-this.offsetInBuffer(r.bufferIndex,r.start)===a){const f=this.getLineFeedCnt(l.piece.bufferIndex,r.start,u);if(f!==C)return{index:f,remainder:0}}return{index:C,remainder:u.column}}getAccumulatedValue(l,a){if(a<0)return 0;const r=l.piece,u=this._buffers[r.bufferIndex].lineStarts,C=r.start.line+a+1;return C>r.end.line?u[r.end.line]+r.end.column-u[r.start.line]-r.start.column:u[C]-u[r.start.line]-r.start.column}deleteNodeTail(l,a){const r=l.piece,u=r.lineFeedCnt,C=this.offsetInBuffer(r.bufferIndex,r.end),f=a,h=this.offsetInBuffer(r.bufferIndex,f),v=this.getLineFeedCnt(r.bufferIndex,r.start,f),w=v-u,S=h-C,L=r.length+S;l.piece=new o(r.bufferIndex,r.start,f,v,L),(0,E.updateTreeMetadata)(this,l,S,w)}deleteNodeHead(l,a){const r=l.piece,u=r.lineFeedCnt,C=this.offsetInBuffer(r.bufferIndex,r.start),f=a,h=this.getLineFeedCnt(r.bufferIndex,f,r.end),v=this.offsetInBuffer(r.bufferIndex,f),w=h-u,S=C-v,L=r.length+S;l.piece=new o(r.bufferIndex,f,r.end,h,L),(0,E.updateTreeMetadata)(this,l,S,w)}shrinkNode(l,a,r){const u=l.piece,C=u.start,f=u.end,h=u.length,v=u.lineFeedCnt,w=a,S=this.getLineFeedCnt(u.bufferIndex,u.start,w),L=this.offsetInBuffer(u.bufferIndex,a)-this.offsetInBuffer(u.bufferIndex,C);l.piece=new o(u.bufferIndex,u.start,w,S,L),(0,E.updateTreeMetadata)(this,l,L-h,S-v);const D=new o(u.bufferIndex,r,f,this.getLineFeedCnt(u.bufferIndex,r,f),this.offsetInBuffer(u.bufferIndex,f)-this.offsetInBuffer(u.bufferIndex,r)),T=this.rbInsertRight(l,D);this.validateCRLFWithPrevNode(T)}appendToNode(l,a){this.adjustCarriageReturnFromNext(a,l)&&(a+=` `);const r=this.shouldCheckCRLF()&&this.startWithLF(a)&&this.endWithCR(l),u=this._buffers[0].buffer.length;this._buffers[0].buffer+=a;const C=p(a,!1);for(let T=0;Tl)a=a.left;else if(a.size_left+a.piece.length>=l){u+=a.size_left;const C={node:a,remainder:l-a.size_left,nodeStartOffset:u};return this._searchCache.set(C),C}else l-=a.size_left+a.piece.length,u+=a.size_left+a.piece.length,a=a.right;return null}nodeAt2(l,a){let r=this.root,u=0;for(;r!==E.SENTINEL;)if(r.left!==E.SENTINEL&&r.lf_left>=l-1)r=r.left;else if(r.lf_left+r.piece.lineFeedCnt>l-1){const C=this.getAccumulatedValue(r,l-r.lf_left-2),f=this.getAccumulatedValue(r,l-r.lf_left-1);return u+=r.size_left,{node:r,remainder:Math.min(C+a-1,f),nodeStartOffset:u}}else if(r.lf_left+r.piece.lineFeedCnt===l-1){const C=this.getAccumulatedValue(r,l-r.lf_left-2);if(C+a-1<=r.piece.length)return{node:r,remainder:C+a-1,nodeStartOffset:u};a-=r.piece.length-C;break}else l-=r.lf_left+r.piece.lineFeedCnt,u+=r.size_left+r.piece.length,r=r.right;for(r=r.next();r!==E.SENTINEL;){if(r.piece.lineFeedCnt>0){const C=this.getAccumulatedValue(r,0),f=this.offsetOfNode(r);return{node:r,remainder:Math.min(a-1,C),nodeStartOffset:f}}else if(r.piece.length>=a-1){const C=this.offsetOfNode(r);return{node:r,remainder:a-1,nodeStartOffset:C}}else a-=r.piece.length;r=r.next()}return null}nodeCharCodeAt(l,a){if(l.piece.lineFeedCnt<1)return-1;const r=this._buffers[l.piece.bufferIndex],u=this.offsetInBuffer(l.piece.bufferIndex,l.piece.start)+a;return r.buffer.charCodeAt(u)}offsetOfNode(l){if(!l)return 0;let a=l.size_left;for(;l!==this.root;)l.parent.right===l&&(a+=l.parent.size_left+l.parent.piece.length),l=l.parent;return a}shouldCheckCRLF(){return!(this._EOLNormalized&&this._EOL===` `)}startWithLF(l){if(typeof l=="string")return l.charCodeAt(0)===10;if(l===E.SENTINEL||l.piece.lineFeedCnt===0)return!1;const a=l.piece,r=this._buffers[a.bufferIndex].lineStarts,u=a.start.line,C=r[u]+a.start.column;return u===r.length-1||r[u+1]>C+1?!1:this._buffers[a.bufferIndex].buffer.charCodeAt(C)===10}endWithCR(l){return typeof l=="string"?l.charCodeAt(l.length-1)===13:l===E.SENTINEL||l.piece.lineFeedCnt===0?!1:this.nodeCharCodeAt(l,l.piece.length-1)===13}validateCRLFWithPrevNode(l){if(this.shouldCheckCRLF()&&this.startWithLF(l)){const a=l.prev();this.endWithCR(a)&&this.fixCRLF(a,l)}}validateCRLFWithNextNode(l){if(this.shouldCheckCRLF()&&this.endWithCR(l)){const a=l.next();this.startWithLF(a)&&this.fixCRLF(l,a)}}fixCRLF(l,a){const r=[],u=this._buffers[l.piece.bufferIndex].lineStarts;let C;l.piece.end.column===0?C={line:l.piece.end.line-1,column:u[l.piece.end.line]-u[l.piece.end.line-1]-1}:C={line:l.piece.end.line,column:l.piece.end.column-1};const f=l.piece.length-1,h=l.piece.lineFeedCnt-1;l.piece=new o(l.piece.bufferIndex,l.piece.start,C,h,f),(0,E.updateTreeMetadata)(this,l,-1,-1),l.piece.length===0&&r.push(l);const v={line:a.piece.start.line+1,column:0},w=a.piece.length-1,S=this.getLineFeedCnt(a.piece.bufferIndex,v,a.piece.end);a.piece=new o(a.piece.bufferIndex,v,a.piece.end,S,w),(0,E.updateTreeMetadata)(this,a,-1,-1),a.piece.length===0&&r.push(a);const L=this.createNewPieces(`\r `);this.rbInsertRight(l,L[0]);for(let D=0;D0?this.wrappedTextIndentLength:0}getLineLength(n){const o=n>0?this.breakOffsets[n-1]:0;let i=this.breakOffsets[n]-o;return n>0&&(i+=this.wrappedTextIndentLength),i}getMaxOutputOffset(n){return this.getLineLength(n)}translateToInputOffset(n,o){n>0&&(o=Math.max(0,o-this.wrappedTextIndentLength));let i=n===0?o:this.breakOffsets[n-1]+o;if(this.injectionOffsets!==null)for(let s=0;sthis.injectionOffsets[s];s++)i0?this.breakOffsets[s-1]:0,o===0)if(n<=g)i=s-1;else if(n>l)t=s+1;else break;else if(n=l)t=s+1;else break}let c=n-g;return s>0&&(c+=this.wrappedTextIndentLength),new b(s,c)}normalizeOutputPosition(n,o,t){if(this.injectionOffsets!==null){const i=this.outputPositionToOffsetInInputWithInjections(n,o),s=this.normalizeOffsetInInputWithInjectionsAroundInjections(i,t);if(s!==i)return this.offsetInInputWithInjectionsToOutputPosition(s,t)}if(t===0){if(n>0&&o===this.getMinOutputOffset(n))return new b(n-1,this.getMaxOutputOffset(n-1))}else if(t===1){const i=this.getOutputLineCount()-1;if(n0&&(o=Math.max(0,o-this.wrappedTextIndentLength)),(n>0?this.breakOffsets[n-1]:0)+o}normalizeOffsetInInputWithInjectionsAroundInjections(n,o){const t=this.getInjectedTextAtOffset(n);if(!t)return n;if(o===2){if(n===t.offsetInInputWithInjections+t.length&&y(this.injectionOptions[t.injectedTextIndex].cursorStops))return t.offsetInInputWithInjections+t.length;{let i=t.offsetInInputWithInjections;if(m(this.injectionOptions[t.injectedTextIndex].cursorStops))return i;let s=t.injectedTextIndex-1;for(;s>=0&&this.injectionOffsets[s]===this.injectionOffsets[t.injectedTextIndex]&&!(y(this.injectionOptions[s].cursorStops)||(i-=this.injectionOptions[s].content.length,m(this.injectionOptions[s].cursorStops)));)s--;return i}}else if(o===1||o===4){let i=t.offsetInInputWithInjections+t.length,s=t.injectedTextIndex;for(;s+1=0&&this.injectionOffsets[s-1]===this.injectionOffsets[s];)i-=this.injectionOptions[s-1].content.length,s--;return i}(0,d.assertNever)(o)}getInjectedText(n,o){const t=this.outputPositionToOffsetInInputWithInjections(n,o),i=this.getInjectedTextAtOffset(t);return i?{options:this.injectionOptions[i.injectedTextIndex]}:null}getInjectedTextAtOffset(n){const o=this.injectionOffsets,t=this.injectionOptions;if(o!==null){let i=0;for(let s=0;sn)break;if(n<=l)return{injectedTextIndex:s,offsetInInputWithInjections:c,length:g};i+=g}}}}e.ModelLineProjectionData=E;function y(p){return p==null?!0:p===I.InjectedTextCursorStops.Right||p===I.InjectedTextCursorStops.Both}function m(p){return p==null?!0:p===I.InjectedTextCursorStops.Left||p===I.InjectedTextCursorStops.Both}class _{constructor(n){this.options=n}}e.InjectedText=_;class b{constructor(n,o){this.outputLineIndex=n,this.outputOffset=o}toString(){return`${this.outputLineIndex}:${this.outputOffset}`}toPosition(n){return new k.Position(n+this.outputLineIndex,this.outputOffset+1)}}e.OutputPosition=b}),define(ne[326],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorWorkerHost=void 0;class d{static{this.CHANNEL_NAME="editorWorkerHost"}static getChannel(I){return I.getChannel(d.CHANNEL_NAME)}static setChannel(I,E){I.setChannel(d.CHANNEL_NAME,E)}}e.EditorWorkerHost=d}),define(ne[582],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.findSectionHeaders=I;const d=new RegExp("\\bMARK:\\s*(.*)$","d"),k=/^-+|-+$/g;function I(b,p){let n=[];if(p.findRegionSectionHeaders&&p.foldingRules?.markers){const o=E(b,p);n=n.concat(o)}if(p.findMarkSectionHeaders){const o=y(b);n=n.concat(o)}return n}function E(b,p){const n=[],o=b.getLineCount();for(let t=1;t<=o;t++){const i=b.getLineContent(t),s=i.match(p.foldingRules.markers.start);if(s){const g={startLineNumber:t,startColumn:s[0].length+1,endLineNumber:t,endColumn:i.length+1};if(g.endColumn>g.startColumn){const c={range:g,..._(i.substring(s[0].length)),shouldBeInComments:!1};(c.text||c.hasSeparatorLine)&&n.push(c)}}}return n}function y(b){const p=[],n=b.getLineCount();for(let o=1;o<=n;o++){const t=b.getLineContent(o);m(t,o,p)}return p}function m(b,p,n){d.lastIndex=0;const o=d.exec(b);if(o){const t=o.indices[1][0]+1,i=o.indices[1][1]+1,s={startLineNumber:p,startColumn:t,endLineNumber:p,endColumn:i};if(s.endColumn>s.startColumn){const g={range:s,..._(o[1]),shouldBeInComments:!0};(g.text||g.hasSeparatorLine)&&n.push(g)}}}function _(b){b=b.trim();const p=b.startsWith("-");return b=b.replace(k,""),{text:b,hasSeparatorLine:p}}}),define(ne[327],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DraggedTreeItemsIdentifier=e.TreeViewsDnDService=void 0;class d{constructor(){this._dragOperations=new Map}removeDragOperationTransfer(E){if(E&&this._dragOperations.has(E)){const y=this._dragOperations.get(E);return this._dragOperations.delete(E),y}}}e.TreeViewsDnDService=d;class k{constructor(E){this.identifier=E}}e.DraggedTreeItemsIdentifier=k}),define(ne[328],se([1,0,4,202,11,90,147]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UnicodeTextModelHighlighter=void 0;class m{static computeUnicodeHighlights(o,t,i){const s=i?i.startLineNumber:1,g=i?i.endLineNumber:o.getLineCount(),c=new b(t),l=c.getCandidateCodePoints();let a;l==="allNonBasicAscii"?a=new RegExp("[^\\t\\n\\r\\x20-\\x7E]","g"):a=new RegExp(`${_(Array.from(l))}`,"g");const r=new k.Searcher(null,a),u=[];let C=!1,f,h=0,v=0,w=0;e:for(let S=s,L=g;S<=L;S++){const D=o.getLineContent(S),T=D.length;r.reset(0);do if(f=r.next(D),f){let M=f.index,A=f.index+f[0].length;if(M>0){const F=D.charCodeAt(M-1);I.isHighSurrogate(F)&&M--}if(A+1=1e3){C=!0;break e}u.push(new d.Range(S,M+1,S,A+1))}}while(f)}return{ranges:u,hasMore:C,ambiguousCharacterCount:h,invisibleCharacterCount:v,nonBasicAsciiCharacterCount:w}}static computeUnicodeHighlightReason(o,t){const i=new b(t);switch(i.shouldHighlightNonBasicASCII(o,null)){case 0:return null;case 2:return{kind:1};case 3:{const g=o.codePointAt(0),c=i.ambiguousCharacters.getPrimaryConfusable(g),l=I.AmbiguousCharacters.getLocales().filter(a=>!I.AmbiguousCharacters.getInstance(new Set([...t.allowedLocales,a])).isAmbiguous(g));return{kind:0,confusableWith:String.fromCodePoint(c),notAmbiguousInLocales:l}}case 1:return{kind:2}}}}e.UnicodeTextModelHighlighter=m;function _(n,o){return`[${I.escapeRegExpCharacters(n.map(i=>String.fromCodePoint(i)).join(""))}]`}class b{constructor(o){this.options=o,this.allowedCodePoints=new Set(o.allowedCodePoints),this.ambiguousCharacters=I.AmbiguousCharacters.getInstance(new Set(o.allowedLocales))}getCandidateCodePoints(){if(this.options.nonBasicASCII)return"allNonBasicAscii";const o=new Set;if(this.options.invisibleCharacters)for(const t of I.InvisibleCharacters.codePoints)p(String.fromCodePoint(t))||o.add(t);if(this.options.ambiguousCharacters)for(const t of this.ambiguousCharacters.getConfusableCodePoints())o.add(t);for(const t of this.allowedCodePoints)o.delete(t);return o}shouldHighlightNonBasicASCII(o,t){const i=o.codePointAt(0);if(this.allowedCodePoints.has(i))return 0;if(this.options.nonBasicASCII)return 1;let s=!1,g=!1;if(t)for(const c of t){const l=c.codePointAt(0),a=I.isBasicASCII(c);s=s||a,!a&&!this.ambiguousCharacters.isAmbiguous(l)&&!I.InvisibleCharacters.isInvisibleCharacter(l)&&(g=!0)}return!s&&g?0:this.options.invisibleCharacters&&!p(o)&&I.InvisibleCharacters.isInvisibleCharacter(i)?2:this.options.ambiguousCharacters&&this.ambiguousCharacters.isAmbiguous(i)?3:0}}function p(n){return n===" "||n===` `||n===" "}}),define(ne[238],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.WrappingIndent=e.TrackedRangeStickiness=e.TextEditorCursorStyle=e.TextEditorCursorBlinkingStyle=e.SymbolTag=e.SymbolKind=e.SignatureHelpTriggerKind=e.ShowLightbulbIconMode=e.SelectionDirection=e.ScrollbarVisibility=e.ScrollType=e.RenderMinimap=e.RenderLineNumbersType=e.PositionAffinity=e.PartialAcceptTriggerKind=e.OverviewRulerLane=e.OverlayWidgetPositionPreference=e.NewSymbolNameTriggerKind=e.NewSymbolNameTag=e.MouseTargetType=e.MinimapSectionHeaderStyle=e.MinimapPosition=e.MarkerTag=e.MarkerSeverity=e.KeyCode=e.InlineEditTriggerKind=e.InlineCompletionTriggerKind=e.InlayHintKind=e.InjectedTextCursorStops=e.IndentAction=e.HoverVerbosityAction=e.GlyphMarginLane=e.EndOfLineSequence=e.EndOfLinePreference=e.EditorOption=e.EditorAutoIndentStrategy=e.DocumentHighlightKind=e.DefaultEndOfLine=e.CursorChangeReason=e.ContentWidgetPositionPreference=e.CompletionTriggerKind=e.CompletionItemTag=e.CompletionItemKind=e.CompletionItemInsertTextRule=e.CodeActionTriggerType=e.AccessibilitySupport=void 0;var d;(function(R){R[R.Unknown=0]="Unknown",R[R.Disabled=1]="Disabled",R[R.Enabled=2]="Enabled"})(d||(e.AccessibilitySupport=d={}));var k;(function(R){R[R.Invoke=1]="Invoke",R[R.Auto=2]="Auto"})(k||(e.CodeActionTriggerType=k={}));var I;(function(R){R[R.None=0]="None",R[R.KeepWhitespace=1]="KeepWhitespace",R[R.InsertAsSnippet=4]="InsertAsSnippet"})(I||(e.CompletionItemInsertTextRule=I={}));var E;(function(R){R[R.Method=0]="Method",R[R.Function=1]="Function",R[R.Constructor=2]="Constructor",R[R.Field=3]="Field",R[R.Variable=4]="Variable",R[R.Class=5]="Class",R[R.Struct=6]="Struct",R[R.Interface=7]="Interface",R[R.Module=8]="Module",R[R.Property=9]="Property",R[R.Event=10]="Event",R[R.Operator=11]="Operator",R[R.Unit=12]="Unit",R[R.Value=13]="Value",R[R.Constant=14]="Constant",R[R.Enum=15]="Enum",R[R.EnumMember=16]="EnumMember",R[R.Keyword=17]="Keyword",R[R.Text=18]="Text",R[R.Color=19]="Color",R[R.File=20]="File",R[R.Reference=21]="Reference",R[R.Customcolor=22]="Customcolor",R[R.Folder=23]="Folder",R[R.TypeParameter=24]="TypeParameter",R[R.User=25]="User",R[R.Issue=26]="Issue",R[R.Snippet=27]="Snippet"})(E||(e.CompletionItemKind=E={}));var y;(function(R){R[R.Deprecated=1]="Deprecated"})(y||(e.CompletionItemTag=y={}));var m;(function(R){R[R.Invoke=0]="Invoke",R[R.TriggerCharacter=1]="TriggerCharacter",R[R.TriggerForIncompleteCompletions=2]="TriggerForIncompleteCompletions"})(m||(e.CompletionTriggerKind=m={}));var _;(function(R){R[R.EXACT=0]="EXACT",R[R.ABOVE=1]="ABOVE",R[R.BELOW=2]="BELOW"})(_||(e.ContentWidgetPositionPreference=_={}));var b;(function(R){R[R.NotSet=0]="NotSet",R[R.ContentFlush=1]="ContentFlush",R[R.RecoverFromMarkers=2]="RecoverFromMarkers",R[R.Explicit=3]="Explicit",R[R.Paste=4]="Paste",R[R.Undo=5]="Undo",R[R.Redo=6]="Redo"})(b||(e.CursorChangeReason=b={}));var p;(function(R){R[R.LF=1]="LF",R[R.CRLF=2]="CRLF"})(p||(e.DefaultEndOfLine=p={}));var n;(function(R){R[R.Text=0]="Text",R[R.Read=1]="Read",R[R.Write=2]="Write"})(n||(e.DocumentHighlightKind=n={}));var o;(function(R){R[R.None=0]="None",R[R.Keep=1]="Keep",R[R.Brackets=2]="Brackets",R[R.Advanced=3]="Advanced",R[R.Full=4]="Full"})(o||(e.EditorAutoIndentStrategy=o={}));var t;(function(R){R[R.acceptSuggestionOnCommitCharacter=0]="acceptSuggestionOnCommitCharacter",R[R.acceptSuggestionOnEnter=1]="acceptSuggestionOnEnter",R[R.accessibilitySupport=2]="accessibilitySupport",R[R.accessibilityPageSize=3]="accessibilityPageSize",R[R.ariaLabel=4]="ariaLabel",R[R.ariaRequired=5]="ariaRequired",R[R.autoClosingBrackets=6]="autoClosingBrackets",R[R.autoClosingComments=7]="autoClosingComments",R[R.screenReaderAnnounceInlineSuggestion=8]="screenReaderAnnounceInlineSuggestion",R[R.autoClosingDelete=9]="autoClosingDelete",R[R.autoClosingOvertype=10]="autoClosingOvertype",R[R.autoClosingQuotes=11]="autoClosingQuotes",R[R.autoIndent=12]="autoIndent",R[R.automaticLayout=13]="automaticLayout",R[R.autoSurround=14]="autoSurround",R[R.bracketPairColorization=15]="bracketPairColorization",R[R.guides=16]="guides",R[R.codeLens=17]="codeLens",R[R.codeLensFontFamily=18]="codeLensFontFamily",R[R.codeLensFontSize=19]="codeLensFontSize",R[R.colorDecorators=20]="colorDecorators",R[R.colorDecoratorsLimit=21]="colorDecoratorsLimit",R[R.columnSelection=22]="columnSelection",R[R.comments=23]="comments",R[R.contextmenu=24]="contextmenu",R[R.copyWithSyntaxHighlighting=25]="copyWithSyntaxHighlighting",R[R.cursorBlinking=26]="cursorBlinking",R[R.cursorSmoothCaretAnimation=27]="cursorSmoothCaretAnimation",R[R.cursorStyle=28]="cursorStyle",R[R.cursorSurroundingLines=29]="cursorSurroundingLines",R[R.cursorSurroundingLinesStyle=30]="cursorSurroundingLinesStyle",R[R.cursorWidth=31]="cursorWidth",R[R.disableLayerHinting=32]="disableLayerHinting",R[R.disableMonospaceOptimizations=33]="disableMonospaceOptimizations",R[R.domReadOnly=34]="domReadOnly",R[R.dragAndDrop=35]="dragAndDrop",R[R.dropIntoEditor=36]="dropIntoEditor",R[R.emptySelectionClipboard=37]="emptySelectionClipboard",R[R.experimentalWhitespaceRendering=38]="experimentalWhitespaceRendering",R[R.extraEditorClassName=39]="extraEditorClassName",R[R.fastScrollSensitivity=40]="fastScrollSensitivity",R[R.find=41]="find",R[R.fixedOverflowWidgets=42]="fixedOverflowWidgets",R[R.folding=43]="folding",R[R.foldingStrategy=44]="foldingStrategy",R[R.foldingHighlight=45]="foldingHighlight",R[R.foldingImportsByDefault=46]="foldingImportsByDefault",R[R.foldingMaximumRegions=47]="foldingMaximumRegions",R[R.unfoldOnClickAfterEndOfLine=48]="unfoldOnClickAfterEndOfLine",R[R.fontFamily=49]="fontFamily",R[R.fontInfo=50]="fontInfo",R[R.fontLigatures=51]="fontLigatures",R[R.fontSize=52]="fontSize",R[R.fontWeight=53]="fontWeight",R[R.fontVariations=54]="fontVariations",R[R.formatOnPaste=55]="formatOnPaste",R[R.formatOnType=56]="formatOnType",R[R.glyphMargin=57]="glyphMargin",R[R.gotoLocation=58]="gotoLocation",R[R.hideCursorInOverviewRuler=59]="hideCursorInOverviewRuler",R[R.hover=60]="hover",R[R.inDiffEditor=61]="inDiffEditor",R[R.inlineSuggest=62]="inlineSuggest",R[R.inlineEdit=63]="inlineEdit",R[R.letterSpacing=64]="letterSpacing",R[R.lightbulb=65]="lightbulb",R[R.lineDecorationsWidth=66]="lineDecorationsWidth",R[R.lineHeight=67]="lineHeight",R[R.lineNumbers=68]="lineNumbers",R[R.lineNumbersMinChars=69]="lineNumbersMinChars",R[R.linkedEditing=70]="linkedEditing",R[R.links=71]="links",R[R.matchBrackets=72]="matchBrackets",R[R.minimap=73]="minimap",R[R.mouseStyle=74]="mouseStyle",R[R.mouseWheelScrollSensitivity=75]="mouseWheelScrollSensitivity",R[R.mouseWheelZoom=76]="mouseWheelZoom",R[R.multiCursorMergeOverlapping=77]="multiCursorMergeOverlapping",R[R.multiCursorModifier=78]="multiCursorModifier",R[R.multiCursorPaste=79]="multiCursorPaste",R[R.multiCursorLimit=80]="multiCursorLimit",R[R.occurrencesHighlight=81]="occurrencesHighlight",R[R.overviewRulerBorder=82]="overviewRulerBorder",R[R.overviewRulerLanes=83]="overviewRulerLanes",R[R.padding=84]="padding",R[R.pasteAs=85]="pasteAs",R[R.parameterHints=86]="parameterHints",R[R.peekWidgetDefaultFocus=87]="peekWidgetDefaultFocus",R[R.placeholder=88]="placeholder",R[R.definitionLinkOpensInPeek=89]="definitionLinkOpensInPeek",R[R.quickSuggestions=90]="quickSuggestions",R[R.quickSuggestionsDelay=91]="quickSuggestionsDelay",R[R.readOnly=92]="readOnly",R[R.readOnlyMessage=93]="readOnlyMessage",R[R.renameOnType=94]="renameOnType",R[R.renderControlCharacters=95]="renderControlCharacters",R[R.renderFinalNewline=96]="renderFinalNewline",R[R.renderLineHighlight=97]="renderLineHighlight",R[R.renderLineHighlightOnlyWhenFocus=98]="renderLineHighlightOnlyWhenFocus",R[R.renderValidationDecorations=99]="renderValidationDecorations",R[R.renderWhitespace=100]="renderWhitespace",R[R.revealHorizontalRightPadding=101]="revealHorizontalRightPadding",R[R.roundedSelection=102]="roundedSelection",R[R.rulers=103]="rulers",R[R.scrollbar=104]="scrollbar",R[R.scrollBeyondLastColumn=105]="scrollBeyondLastColumn",R[R.scrollBeyondLastLine=106]="scrollBeyondLastLine",R[R.scrollPredominantAxis=107]="scrollPredominantAxis",R[R.selectionClipboard=108]="selectionClipboard",R[R.selectionHighlight=109]="selectionHighlight",R[R.selectOnLineNumbers=110]="selectOnLineNumbers",R[R.showFoldingControls=111]="showFoldingControls",R[R.showUnused=112]="showUnused",R[R.snippetSuggestions=113]="snippetSuggestions",R[R.smartSelect=114]="smartSelect",R[R.smoothScrolling=115]="smoothScrolling",R[R.stickyScroll=116]="stickyScroll",R[R.stickyTabStops=117]="stickyTabStops",R[R.stopRenderingLineAfter=118]="stopRenderingLineAfter",R[R.suggest=119]="suggest",R[R.suggestFontSize=120]="suggestFontSize",R[R.suggestLineHeight=121]="suggestLineHeight",R[R.suggestOnTriggerCharacters=122]="suggestOnTriggerCharacters",R[R.suggestSelection=123]="suggestSelection",R[R.tabCompletion=124]="tabCompletion",R[R.tabIndex=125]="tabIndex",R[R.unicodeHighlighting=126]="unicodeHighlighting",R[R.unusualLineTerminators=127]="unusualLineTerminators",R[R.useShadowDOM=128]="useShadowDOM",R[R.useTabStops=129]="useTabStops",R[R.wordBreak=130]="wordBreak",R[R.wordSegmenterLocales=131]="wordSegmenterLocales",R[R.wordSeparators=132]="wordSeparators",R[R.wordWrap=133]="wordWrap",R[R.wordWrapBreakAfterCharacters=134]="wordWrapBreakAfterCharacters",R[R.wordWrapBreakBeforeCharacters=135]="wordWrapBreakBeforeCharacters",R[R.wordWrapColumn=136]="wordWrapColumn",R[R.wordWrapOverride1=137]="wordWrapOverride1",R[R.wordWrapOverride2=138]="wordWrapOverride2",R[R.wrappingIndent=139]="wrappingIndent",R[R.wrappingStrategy=140]="wrappingStrategy",R[R.showDeprecated=141]="showDeprecated",R[R.inlayHints=142]="inlayHints",R[R.editorClassName=143]="editorClassName",R[R.pixelRatio=144]="pixelRatio",R[R.tabFocusMode=145]="tabFocusMode",R[R.layoutInfo=146]="layoutInfo",R[R.wrappingInfo=147]="wrappingInfo",R[R.defaultColorDecorators=148]="defaultColorDecorators",R[R.colorDecoratorsActivatedOn=149]="colorDecoratorsActivatedOn",R[R.inlineCompletionsAccessibilityVerbose=150]="inlineCompletionsAccessibilityVerbose"})(t||(e.EditorOption=t={}));var i;(function(R){R[R.TextDefined=0]="TextDefined",R[R.LF=1]="LF",R[R.CRLF=2]="CRLF"})(i||(e.EndOfLinePreference=i={}));var s;(function(R){R[R.LF=0]="LF",R[R.CRLF=1]="CRLF"})(s||(e.EndOfLineSequence=s={}));var g;(function(R){R[R.Left=1]="Left",R[R.Center=2]="Center",R[R.Right=3]="Right"})(g||(e.GlyphMarginLane=g={}));var c;(function(R){R[R.Increase=0]="Increase",R[R.Decrease=1]="Decrease"})(c||(e.HoverVerbosityAction=c={}));var l;(function(R){R[R.None=0]="None",R[R.Indent=1]="Indent",R[R.IndentOutdent=2]="IndentOutdent",R[R.Outdent=3]="Outdent"})(l||(e.IndentAction=l={}));var a;(function(R){R[R.Both=0]="Both",R[R.Right=1]="Right",R[R.Left=2]="Left",R[R.None=3]="None"})(a||(e.InjectedTextCursorStops=a={}));var r;(function(R){R[R.Type=1]="Type",R[R.Parameter=2]="Parameter"})(r||(e.InlayHintKind=r={}));var u;(function(R){R[R.Automatic=0]="Automatic",R[R.Explicit=1]="Explicit"})(u||(e.InlineCompletionTriggerKind=u={}));var C;(function(R){R[R.Invoke=0]="Invoke",R[R.Automatic=1]="Automatic"})(C||(e.InlineEditTriggerKind=C={}));var f;(function(R){R[R.DependsOnKbLayout=-1]="DependsOnKbLayout",R[R.Unknown=0]="Unknown",R[R.Backspace=1]="Backspace",R[R.Tab=2]="Tab",R[R.Enter=3]="Enter",R[R.Shift=4]="Shift",R[R.Ctrl=5]="Ctrl",R[R.Alt=6]="Alt",R[R.PauseBreak=7]="PauseBreak",R[R.CapsLock=8]="CapsLock",R[R.Escape=9]="Escape",R[R.Space=10]="Space",R[R.PageUp=11]="PageUp",R[R.PageDown=12]="PageDown",R[R.End=13]="End",R[R.Home=14]="Home",R[R.LeftArrow=15]="LeftArrow",R[R.UpArrow=16]="UpArrow",R[R.RightArrow=17]="RightArrow",R[R.DownArrow=18]="DownArrow",R[R.Insert=19]="Insert",R[R.Delete=20]="Delete",R[R.Digit0=21]="Digit0",R[R.Digit1=22]="Digit1",R[R.Digit2=23]="Digit2",R[R.Digit3=24]="Digit3",R[R.Digit4=25]="Digit4",R[R.Digit5=26]="Digit5",R[R.Digit6=27]="Digit6",R[R.Digit7=28]="Digit7",R[R.Digit8=29]="Digit8",R[R.Digit9=30]="Digit9",R[R.KeyA=31]="KeyA",R[R.KeyB=32]="KeyB",R[R.KeyC=33]="KeyC",R[R.KeyD=34]="KeyD",R[R.KeyE=35]="KeyE",R[R.KeyF=36]="KeyF",R[R.KeyG=37]="KeyG",R[R.KeyH=38]="KeyH",R[R.KeyI=39]="KeyI",R[R.KeyJ=40]="KeyJ",R[R.KeyK=41]="KeyK",R[R.KeyL=42]="KeyL",R[R.KeyM=43]="KeyM",R[R.KeyN=44]="KeyN",R[R.KeyO=45]="KeyO",R[R.KeyP=46]="KeyP",R[R.KeyQ=47]="KeyQ",R[R.KeyR=48]="KeyR",R[R.KeyS=49]="KeyS",R[R.KeyT=50]="KeyT",R[R.KeyU=51]="KeyU",R[R.KeyV=52]="KeyV",R[R.KeyW=53]="KeyW",R[R.KeyX=54]="KeyX",R[R.KeyY=55]="KeyY",R[R.KeyZ=56]="KeyZ",R[R.Meta=57]="Meta",R[R.ContextMenu=58]="ContextMenu",R[R.F1=59]="F1",R[R.F2=60]="F2",R[R.F3=61]="F3",R[R.F4=62]="F4",R[R.F5=63]="F5",R[R.F6=64]="F6",R[R.F7=65]="F7",R[R.F8=66]="F8",R[R.F9=67]="F9",R[R.F10=68]="F10",R[R.F11=69]="F11",R[R.F12=70]="F12",R[R.F13=71]="F13",R[R.F14=72]="F14",R[R.F15=73]="F15",R[R.F16=74]="F16",R[R.F17=75]="F17",R[R.F18=76]="F18",R[R.F19=77]="F19",R[R.F20=78]="F20",R[R.F21=79]="F21",R[R.F22=80]="F22",R[R.F23=81]="F23",R[R.F24=82]="F24",R[R.NumLock=83]="NumLock",R[R.ScrollLock=84]="ScrollLock",R[R.Semicolon=85]="Semicolon",R[R.Equal=86]="Equal",R[R.Comma=87]="Comma",R[R.Minus=88]="Minus",R[R.Period=89]="Period",R[R.Slash=90]="Slash",R[R.Backquote=91]="Backquote",R[R.BracketLeft=92]="BracketLeft",R[R.Backslash=93]="Backslash",R[R.BracketRight=94]="BracketRight",R[R.Quote=95]="Quote",R[R.OEM_8=96]="OEM_8",R[R.IntlBackslash=97]="IntlBackslash",R[R.Numpad0=98]="Numpad0",R[R.Numpad1=99]="Numpad1",R[R.Numpad2=100]="Numpad2",R[R.Numpad3=101]="Numpad3",R[R.Numpad4=102]="Numpad4",R[R.Numpad5=103]="Numpad5",R[R.Numpad6=104]="Numpad6",R[R.Numpad7=105]="Numpad7",R[R.Numpad8=106]="Numpad8",R[R.Numpad9=107]="Numpad9",R[R.NumpadMultiply=108]="NumpadMultiply",R[R.NumpadAdd=109]="NumpadAdd",R[R.NUMPAD_SEPARATOR=110]="NUMPAD_SEPARATOR",R[R.NumpadSubtract=111]="NumpadSubtract",R[R.NumpadDecimal=112]="NumpadDecimal",R[R.NumpadDivide=113]="NumpadDivide",R[R.KEY_IN_COMPOSITION=114]="KEY_IN_COMPOSITION",R[R.ABNT_C1=115]="ABNT_C1",R[R.ABNT_C2=116]="ABNT_C2",R[R.AudioVolumeMute=117]="AudioVolumeMute",R[R.AudioVolumeUp=118]="AudioVolumeUp",R[R.AudioVolumeDown=119]="AudioVolumeDown",R[R.BrowserSearch=120]="BrowserSearch",R[R.BrowserHome=121]="BrowserHome",R[R.BrowserBack=122]="BrowserBack",R[R.BrowserForward=123]="BrowserForward",R[R.MediaTrackNext=124]="MediaTrackNext",R[R.MediaTrackPrevious=125]="MediaTrackPrevious",R[R.MediaStop=126]="MediaStop",R[R.MediaPlayPause=127]="MediaPlayPause",R[R.LaunchMediaPlayer=128]="LaunchMediaPlayer",R[R.LaunchMail=129]="LaunchMail",R[R.LaunchApp2=130]="LaunchApp2",R[R.Clear=131]="Clear",R[R.MAX_VALUE=132]="MAX_VALUE"})(f||(e.KeyCode=f={}));var h;(function(R){R[R.Hint=1]="Hint",R[R.Info=2]="Info",R[R.Warning=4]="Warning",R[R.Error=8]="Error"})(h||(e.MarkerSeverity=h={}));var v;(function(R){R[R.Unnecessary=1]="Unnecessary",R[R.Deprecated=2]="Deprecated"})(v||(e.MarkerTag=v={}));var w;(function(R){R[R.Inline=1]="Inline",R[R.Gutter=2]="Gutter"})(w||(e.MinimapPosition=w={}));var S;(function(R){R[R.Normal=1]="Normal",R[R.Underlined=2]="Underlined"})(S||(e.MinimapSectionHeaderStyle=S={}));var L;(function(R){R[R.UNKNOWN=0]="UNKNOWN",R[R.TEXTAREA=1]="TEXTAREA",R[R.GUTTER_GLYPH_MARGIN=2]="GUTTER_GLYPH_MARGIN",R[R.GUTTER_LINE_NUMBERS=3]="GUTTER_LINE_NUMBERS",R[R.GUTTER_LINE_DECORATIONS=4]="GUTTER_LINE_DECORATIONS",R[R.GUTTER_VIEW_ZONE=5]="GUTTER_VIEW_ZONE",R[R.CONTENT_TEXT=6]="CONTENT_TEXT",R[R.CONTENT_EMPTY=7]="CONTENT_EMPTY",R[R.CONTENT_VIEW_ZONE=8]="CONTENT_VIEW_ZONE",R[R.CONTENT_WIDGET=9]="CONTENT_WIDGET",R[R.OVERVIEW_RULER=10]="OVERVIEW_RULER",R[R.SCROLLBAR=11]="SCROLLBAR",R[R.OVERLAY_WIDGET=12]="OVERLAY_WIDGET",R[R.OUTSIDE_EDITOR=13]="OUTSIDE_EDITOR"})(L||(e.MouseTargetType=L={}));var D;(function(R){R[R.AIGenerated=1]="AIGenerated"})(D||(e.NewSymbolNameTag=D={}));var T;(function(R){R[R.Invoke=0]="Invoke",R[R.Automatic=1]="Automatic"})(T||(e.NewSymbolNameTriggerKind=T={}));var M;(function(R){R[R.TOP_RIGHT_CORNER=0]="TOP_RIGHT_CORNER",R[R.BOTTOM_RIGHT_CORNER=1]="BOTTOM_RIGHT_CORNER",R[R.TOP_CENTER=2]="TOP_CENTER"})(M||(e.OverlayWidgetPositionPreference=M={}));var A;(function(R){R[R.Left=1]="Left",R[R.Center=2]="Center",R[R.Right=4]="Right",R[R.Full=7]="Full"})(A||(e.OverviewRulerLane=A={}));var P;(function(R){R[R.Word=0]="Word",R[R.Line=1]="Line",R[R.Suggest=2]="Suggest"})(P||(e.PartialAcceptTriggerKind=P={}));var N;(function(R){R[R.Left=0]="Left",R[R.Right=1]="Right",R[R.None=2]="None",R[R.LeftOfInjectedText=3]="LeftOfInjectedText",R[R.RightOfInjectedText=4]="RightOfInjectedText"})(N||(e.PositionAffinity=N={}));var O;(function(R){R[R.Off=0]="Off",R[R.On=1]="On",R[R.Relative=2]="Relative",R[R.Interval=3]="Interval",R[R.Custom=4]="Custom"})(O||(e.RenderLineNumbersType=O={}));var F;(function(R){R[R.None=0]="None",R[R.Text=1]="Text",R[R.Blocks=2]="Blocks"})(F||(e.RenderMinimap=F={}));var x;(function(R){R[R.Smooth=0]="Smooth",R[R.Immediate=1]="Immediate"})(x||(e.ScrollType=x={}));var W;(function(R){R[R.Auto=1]="Auto",R[R.Hidden=2]="Hidden",R[R.Visible=3]="Visible"})(W||(e.ScrollbarVisibility=W={}));var V;(function(R){R[R.LTR=0]="LTR",R[R.RTL=1]="RTL"})(V||(e.SelectionDirection=V={}));var q;(function(R){R.Off="off",R.OnCode="onCode",R.On="on"})(q||(e.ShowLightbulbIconMode=q={}));var H;(function(R){R[R.Invoke=1]="Invoke",R[R.TriggerCharacter=2]="TriggerCharacter",R[R.ContentChange=3]="ContentChange"})(H||(e.SignatureHelpTriggerKind=H={}));var z;(function(R){R[R.File=0]="File",R[R.Module=1]="Module",R[R.Namespace=2]="Namespace",R[R.Package=3]="Package",R[R.Class=4]="Class",R[R.Method=5]="Method",R[R.Property=6]="Property",R[R.Field=7]="Field",R[R.Constructor=8]="Constructor",R[R.Enum=9]="Enum",R[R.Interface=10]="Interface",R[R.Function=11]="Function",R[R.Variable=12]="Variable",R[R.Constant=13]="Constant",R[R.String=14]="String",R[R.Number=15]="Number",R[R.Boolean=16]="Boolean",R[R.Array=17]="Array",R[R.Object=18]="Object",R[R.Key=19]="Key",R[R.Null=20]="Null",R[R.EnumMember=21]="EnumMember",R[R.Struct=22]="Struct",R[R.Event=23]="Event",R[R.Operator=24]="Operator",R[R.TypeParameter=25]="TypeParameter"})(z||(e.SymbolKind=z={}));var U;(function(R){R[R.Deprecated=1]="Deprecated"})(U||(e.SymbolTag=U={}));var j;(function(R){R[R.Hidden=0]="Hidden",R[R.Blink=1]="Blink",R[R.Smooth=2]="Smooth",R[R.Phase=3]="Phase",R[R.Expand=4]="Expand",R[R.Solid=5]="Solid"})(j||(e.TextEditorCursorBlinkingStyle=j={}));var Y;(function(R){R[R.Line=1]="Line",R[R.Block=2]="Block",R[R.Underline=3]="Underline",R[R.LineThin=4]="LineThin",R[R.BlockOutline=5]="BlockOutline",R[R.UnderlineThin=6]="UnderlineThin"})(Y||(e.TextEditorCursorStyle=Y={}));var G;(function(R){R[R.AlwaysGrowsWhenTypingAtEdges=0]="AlwaysGrowsWhenTypingAtEdges",R[R.NeverGrowsWhenTypingAtEdges=1]="NeverGrowsWhenTypingAtEdges",R[R.GrowsOnlyWhenTypingBefore=2]="GrowsOnlyWhenTypingBefore",R[R.GrowsOnlyWhenTypingAfter=3]="GrowsOnlyWhenTypingAfter"})(G||(e.TrackedRangeStickiness=G={}));var K;(function(R){R[R.None=0]="None",R[R.Same=1]="Same",R[R.Indent=2]="Indent",R[R.DeepIndent=3]="DeepIndent"})(K||(e.WrappingIndent=K={}))}),define(ne[583],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BracketPairWithMinIndentationInfo=e.BracketPairInfo=e.BracketInfo=void 0;class d{constructor(y,m,_,b){this.range=y,this.nestingLevel=m,this.nestingLevelOfEqualBracketType=_,this.isInvalid=b}}e.BracketInfo=d;class k{constructor(y,m,_,b,p,n){this.range=y,this.openingBracketRange=m,this.closingBracketRange=_,this.nestingLevel=b,this.nestingLevelOfEqualBracketType=p,this.bracketPairNode=n}get openingBracketInfo(){return this.bracketPairNode.openingBracket.bracketInfo}}e.BracketPairInfo=k;class I extends k{constructor(y,m,_,b,p,n,o){super(y,m,_,b,p,n),this.minVisibleColumnIndentation=o}}e.BracketPairWithMinIndentationInfo=I}),define(ne[584],se([1,0,6,2,583,200,321,106,320,149,236,13,319]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BracketPairsTree=void 0;class t extends k.Disposable{didLanguageChange(r){return this.brackets.didLanguageChange(r)}constructor(r,u){if(super(),this.textModel=r,this.getLanguageConfiguration=u,this.didChangeEmitter=new d.Emitter,this.denseKeyProvider=new b.DenseKeyProvider,this.brackets=new y.LanguageAgnosticBracketTokens(this.denseKeyProvider,this.getLanguageConfiguration),this.onDidChange=this.didChangeEmitter.event,this.queuedTextEditsForInitialAstWithoutTokens=[],this.queuedTextEdits=[],r.tokenization.hasTokens)r.tokenization.backgroundTokenizationState===2?(this.initialAstWithoutTokens=void 0,this.astWithTokens=this.parseDocumentFromTextBuffer([],void 0,!1)):(this.initialAstWithoutTokens=this.parseDocumentFromTextBuffer([],void 0,!0),this.astWithTokens=this.initialAstWithoutTokens);else{const C=this.brackets.getSingleLanguageBracketTokens(this.textModel.getLanguageId()),f=new p.FastTokenizer(this.textModel.getValue(),C);this.initialAstWithoutTokens=(0,_.parseDocument)(f,[],void 0,!0),this.astWithTokens=this.initialAstWithoutTokens}}handleDidChangeBackgroundTokenizationState(){if(this.textModel.tokenization.backgroundTokenizationState===2){const r=this.initialAstWithoutTokens===void 0;this.initialAstWithoutTokens=void 0,r||this.didChangeEmitter.fire()}}handleDidChangeTokens({ranges:r}){const u=r.map(C=>new E.TextEditInfo((0,m.toLength)(C.fromLineNumber-1,0),(0,m.toLength)(C.toLineNumber,0),(0,m.toLength)(C.toLineNumber-C.fromLineNumber+1,0)));this.handleEdits(u,!0),this.initialAstWithoutTokens||this.didChangeEmitter.fire()}handleContentChanged(r){const u=E.TextEditInfo.fromModelContentChanges(r.changes);this.handleEdits(u,!1)}handleEdits(r,u){const C=(0,o.combineTextEditInfos)(this.queuedTextEdits,r);this.queuedTextEdits=C,this.initialAstWithoutTokens&&!u&&(this.queuedTextEditsForInitialAstWithoutTokens=(0,o.combineTextEditInfos)(this.queuedTextEditsForInitialAstWithoutTokens,r))}flushQueue(){this.queuedTextEdits.length>0&&(this.astWithTokens=this.parseDocumentFromTextBuffer(this.queuedTextEdits,this.astWithTokens,!1),this.queuedTextEdits=[]),this.queuedTextEditsForInitialAstWithoutTokens.length>0&&(this.initialAstWithoutTokens&&(this.initialAstWithoutTokens=this.parseDocumentFromTextBuffer(this.queuedTextEditsForInitialAstWithoutTokens,this.initialAstWithoutTokens,!1)),this.queuedTextEditsForInitialAstWithoutTokens=[])}parseDocumentFromTextBuffer(r,u,C){const h=u,v=new p.TextBufferTokenizer(this.textModel,this.brackets);return(0,_.parseDocument)(v,r,h,C)}getBracketsInRange(r,u){this.flushQueue();const C=(0,m.toLength)(r.startLineNumber-1,r.startColumn-1),f=(0,m.toLength)(r.endLineNumber-1,r.endColumn-1);return new n.CallbackIterable(h=>{const v=this.initialAstWithoutTokens||this.astWithTokens;g(v,m.lengthZero,v.length,C,f,h,0,0,new Map,u)})}getBracketPairsInRange(r,u){this.flushQueue();const C=(0,m.positionToLength)(r.getStartPosition()),f=(0,m.positionToLength)(r.getEndPosition());return new n.CallbackIterable(h=>{const v=this.initialAstWithoutTokens||this.astWithTokens,w=new c(h,u,this.textModel);l(v,m.lengthZero,v.length,C,f,w,0,new Map)})}getFirstBracketAfter(r){this.flushQueue();const u=this.initialAstWithoutTokens||this.astWithTokens;return s(u,m.lengthZero,u.length,(0,m.positionToLength)(r))}getFirstBracketBefore(r){this.flushQueue();const u=this.initialAstWithoutTokens||this.astWithTokens;return i(u,m.lengthZero,u.length,(0,m.positionToLength)(r))}}e.BracketPairsTree=t;function i(a,r,u,C){if(a.kind===4||a.kind===2){const f=[];for(const h of a.children)u=(0,m.lengthAdd)(r,h.length),f.push({nodeOffsetStart:r,nodeOffsetEnd:u}),r=u;for(let h=f.length-1;h>=0;h--){const{nodeOffsetStart:v,nodeOffsetEnd:w}=f[h];if((0,m.lengthLessThan)(v,C)){const S=i(a.children[h],v,w,C);if(S)return S}}return null}else{if(a.kind===3)return null;if(a.kind===1){const f=(0,m.lengthsToRange)(r,u);return{bracketInfo:a.bracketInfo,range:f}}}return null}function s(a,r,u,C){if(a.kind===4||a.kind===2){for(const f of a.children){if(u=(0,m.lengthAdd)(r,f.length),(0,m.lengthLessThan)(C,u)){const h=s(f,r,u,C);if(h)return h}r=u}return null}else{if(a.kind===3)return null;if(a.kind===1){const f=(0,m.lengthsToRange)(r,u);return{bracketInfo:a.bracketInfo,range:f}}}return null}function g(a,r,u,C,f,h,v,w,S,L,D=!1){if(v>200)return!0;e:for(;;)switch(a.kind){case 4:{const T=a.childrenLength;for(let M=0;M200)return!0;let S=!0;if(a.kind===2){let L=0;if(w){let M=w.get(a.openingBracket.text);M===void 0&&(M=0),L=M,M++,w.set(a.openingBracket.text,M)}const D=(0,m.lengthAdd)(r,a.openingBracket.length);let T=-1;if(h.includeMinIndentation&&(T=a.computeMinIndentation(r,h.textModel)),S=h.push(new I.BracketPairWithMinIndentationInfo((0,m.lengthsToRange)(r,u),(0,m.lengthsToRange)(r,D),a.closingBracket?(0,m.lengthsToRange)((0,m.lengthAdd)(D,a.child?.length||m.lengthZero),u):void 0,v,L,a,T)),r=D,S&&a.child){const M=a.child;if(u=(0,m.lengthAdd)(r,M.length),(0,m.lengthLessThanEqual)(r,f)&&(0,m.lengthGreaterThanEqual)(u,C)&&(S=l(M,r,u,C,f,h,v+1,w),!S))return!1}w?.set(a.openingBracket.text,L)}else{let L=r;for(const D of a.children){const T=L;if(L=(0,m.lengthAdd)(L,D.length),(0,m.lengthLessThanEqual)(T,f)&&(0,m.lengthLessThanEqual)(C,L)&&(S=l(D,T,L,C,f,h,v,w),!S))return!1}}return S}}),define(ne[132],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InternalModelContentChangeEvent=e.ModelInjectedTextChangedEvent=e.ModelRawContentChangedEvent=e.ModelRawEOLChanged=e.ModelRawLinesInserted=e.ModelRawLinesDeleted=e.ModelRawLineChanged=e.LineInjectedText=e.ModelRawFlush=void 0;class d{constructor(){this.changeType=1}}e.ModelRawFlush=d;class k{static applyInjectedText(o,t){if(!t||t.length===0)return o;let i="",s=0;for(const g of t)i+=o.substring(s,g.column-1),s=g.column-1,i+=g.options.content;return i+=o.substring(s),i}static fromDecorations(o){const t=[];for(const i of o)i.options.before&&i.options.before.content.length>0&&t.push(new k(i.ownerId,i.range.startLineNumber,i.range.startColumn,i.options.before,0)),i.options.after&&i.options.after.content.length>0&&t.push(new k(i.ownerId,i.range.endLineNumber,i.range.endColumn,i.options.after,1));return t.sort((i,s)=>i.lineNumber===s.lineNumber?i.column===s.column?i.order-s.order:i.column-s.column:i.lineNumber-s.lineNumber),t}constructor(o,t,i,s,g){this.ownerId=o,this.lineNumber=t,this.column=i,this.options=s,this.order=g}}e.LineInjectedText=k;class I{constructor(o,t,i){this.changeType=2,this.lineNumber=o,this.detail=t,this.injectedText=i}}e.ModelRawLineChanged=I;class E{constructor(o,t){this.changeType=3,this.fromLineNumber=o,this.toLineNumber=t}}e.ModelRawLinesDeleted=E;class y{constructor(o,t,i,s){this.changeType=4,this.injectedTexts=s,this.fromLineNumber=o,this.toLineNumber=t,this.detail=i}}e.ModelRawLinesInserted=y;class m{constructor(){this.changeType=5}}e.ModelRawEOLChanged=m;class _{constructor(o,t,i,s){this.changes=o,this.versionId=t,this.isUndoing=i,this.isRedoing=s,this.resultingSelection=null}containsEvent(o){for(let t=0,i=this.changes.length;tg)throw new b.BugIndicatingError("Illegal value for lineNumber");const c=this.getLanguageConfiguration(this.textModel.getLanguageId()).foldingRules,l=!!(c&&c.offSide);let a=-2,r=-1,u=-2,C=-1;const f=O=>{if(a!==-1&&(a===-2||a>O-1)){a=-1,r=-1;for(let F=O-2;F>=0;F--){const x=this._computeIndentLevel(F);if(x>=0){a=F,r=x;break}}}if(u===-2){u=-1,C=-1;for(let F=O;F=0){u=F,C=x;break}}}};let h=-2,v=-1,w=-2,S=-1;const L=O=>{if(h===-2){h=-1,v=-1;for(let F=O-2;F>=0;F--){const x=this._computeIndentLevel(F);if(x>=0){h=F,v=x;break}}}if(w!==-1&&(w===-2||w=0){w=F,S=x;break}}}};let D=0,T=!0,M=0,A=!0,P=0,N=0;for(let O=0;T||A;O++){const F=t-O,x=t+O;O>1&&(F<1||F1&&(x>g||x>s)&&(A=!1),O>5e4&&(T=!1,A=!1);let W=-1;if(T&&F>=1){const q=this._computeIndentLevel(F-1);q>=0?(u=F-1,C=q,W=Math.ceil(q/this.textModel.getOptions().indentSize)):(f(F),W=this._getIndentLevelForWhitespaceLine(l,r,C))}let V=-1;if(A&&x<=g){const q=this._computeIndentLevel(x-1);q>=0?(h=x-1,v=q,V=Math.ceil(q/this.textModel.getOptions().indentSize)):(L(x),V=this._getIndentLevelForWhitespaceLine(l,v,S))}if(O===0){N=W;continue}if(O===1){if(x<=g&&V>=0&&N+1===V){T=!1,D=x,M=x,P=V;continue}if(F>=1&&W>=0&&W-1===N){A=!1,D=F,M=F,P=W;continue}if(D=t,M=t,P=N,P===0)return{startLineNumber:D,endLineNumber:M,indent:P}}T&&(W>=P?D=F:T=!1),A&&(V>=P?M=x:A=!1)}return{startLineNumber:D,endLineNumber:M,indent:P}}getLinesBracketGuides(t,i,s,g){const c=[];for(let f=t;f<=i;f++)c.push([]);const l=!0,a=this.textModel.bracketPairs.getBracketPairsInRangeWithMinIndentation(new E.Range(t,1,i,this.textModel.getLineMaxColumn(i))).toArray();let r;if(s&&a.length>0){const f=(t<=s.lineNumber&&s.lineNumber<=i?a:this.textModel.bracketPairs.getBracketPairsInRange(E.Range.fromPositions(s)).toArray()).filter(h=>E.Range.strictContainsPosition(h.range,s));r=(0,d.findLast)(f,h=>l||h.range.startLineNumber!==h.range.endLineNumber)?.range}const u=this.textModel.getOptions().bracketPairColorizationOptions.independentColorPoolPerBracketType,C=new n;for(const f of a){if(!f.closingBracketRange)continue;const h=r&&f.range.equalsRange(r);if(!h&&!g.includeInactive)continue;const v=C.getInlineClassName(f.nestingLevel,f.nestingLevelOfEqualBracketType,u)+(g.highlightActive&&h?" "+C.activeClassName:""),w=f.openingBracketRange.getStartPosition(),S=f.closingBracketRange.getStartPosition(),L=g.horizontalGuides===_.HorizontalGuidesState.Enabled||g.horizontalGuides===_.HorizontalGuidesState.EnabledForActive&&h;if(f.range.startLineNumber===f.range.endLineNumber){l&&L&&c[f.range.startLineNumber-t].push(new _.IndentGuide(-1,f.openingBracketRange.getEndPosition().column,v,new _.IndentGuideHorizontalLine(!1,S.column),-1,-1));continue}const D=this.getVisibleColumnFromPosition(S),T=this.getVisibleColumnFromPosition(f.openingBracketRange.getStartPosition()),M=Math.min(T,D,f.minVisibleColumnIndentation+1);let A=!1;k.firstNonWhitespaceIndex(this.textModel.getLineContent(f.closingBracketRange.startLineNumber))=t&&T>M&&c[w.lineNumber-t].push(new _.IndentGuide(M,-1,v,new _.IndentGuideHorizontalLine(!1,w.column),-1,-1)),S.lineNumber<=i&&D>M&&c[S.lineNumber-t].push(new _.IndentGuide(M,-1,v,new _.IndentGuideHorizontalLine(!A,S.column),-1,-1)))}for(const f of c)f.sort((h,v)=>h.visibleColumn-v.visibleColumn);return c}getVisibleColumnFromPosition(t){return I.CursorColumns.visibleColumnFromColumn(this.textModel.getLineContent(t.lineNumber),t.column,this.textModel.getOptions().tabSize)+1}getLinesIndentGuides(t,i){this.assertNotDisposed();const s=this.textModel.getLineCount();if(t<1||t>s)throw new Error("Illegal value for startLineNumber");if(i<1||i>s)throw new Error("Illegal value for endLineNumber");const g=this.textModel.getOptions(),c=this.getLanguageConfiguration(this.textModel.getLanguageId()).foldingRules,l=!!(c&&c.offSide),a=new Array(i-t+1);let r=-2,u=-1,C=-2,f=-1;for(let h=t;h<=i;h++){const v=h-t,w=this._computeIndentLevel(h-1);if(w>=0){r=h-1,u=w,a[v]=Math.ceil(w/g.indentSize);continue}if(r===-2){r=-1,u=-1;for(let S=h-2;S>=0;S--){const L=this._computeIndentLevel(S);if(L>=0){r=S,u=L;break}}}if(C!==-1&&(C===-2||C=0){C=S,f=L;break}}}a[v]=this._getIndentLevelForWhitespaceLine(l,u,f)}return a}_getIndentLevelForWhitespaceLine(t,i,s){const g=this.textModel.getOptions();return i===-1||s===-1?0:i{this._tokenizationSupports.get(m)===_&&(this._tokenizationSupports.delete(m),this.handleChange([m]))})}get(m){return this._tokenizationSupports.get(m)||null}registerFactory(m,_){this._factories.get(m)?.dispose();const b=new E(this,m,_);return this._factories.set(m,b),(0,k.toDisposable)(()=>{const p=this._factories.get(m);!p||p!==b||(this._factories.delete(m),p.dispose())})}async getOrCreate(m){const _=this.get(m);if(_)return _;const b=this._factories.get(m);return!b||b.isResolved?null:(await b.resolve(),this.get(m))}isResolved(m){if(this.get(m))return!0;const b=this._factories.get(m);return!!(!b||b.isResolved)}setColorMap(m){this._colorMap=m,this._onDidChange.fire({changedLanguages:Array.from(this._tokenizationSupports.keys()),changedColorMap:!0})}getColorMap(){return this._colorMap}getDefaultBackground(){return this._colorMap&&this._colorMap.length>2?this._colorMap[2]:null}}e.TokenizationRegistry=I;class E extends k.Disposable{get isResolved(){return this._isResolved}constructor(m,_,b){super(),this._registry=m,this._languageId=_,this._factory=b,this._isDisposed=!1,this._resolvePromise=null,this._isResolved=!1}dispose(){this._isDisposed=!0,super.dispose()}async resolve(){return this._resolvePromise||(this._resolvePromise=this._create()),this._resolvePromise}async _create(){const m=await this._factory.tokenizationSupport;this._isResolved=!0,m&&!this._isDisposed&&this._register(this._registry.register(this._languageId,m))}}}),define(ne[586],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContiguousMultilineTokens=void 0;class d{get startLineNumber(){return this._startLineNumber}get endLineNumber(){return this._startLineNumber+this._tokens.length-1}constructor(I,E){this._startLineNumber=I,this._tokens=E}getLineTokens(I){return this._tokens[I-this._startLineNumber]}appendLineTokens(I){this._tokens.push(I)}}e.ContiguousMultilineTokens=d}),define(ne[330],se([1,0,586]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContiguousMultilineTokensBuilder=void 0;class k{constructor(){this._tokens=[]}add(E,y){if(this._tokens.length>0){const m=this._tokens[this._tokens.length-1];if(m.endLineNumber+1===E){m.appendLineTokens(y);return}}this._tokens.push(new d.ContiguousMultilineTokens(E,[y]))}finalize(){return this._tokens}}e.ContiguousMultilineTokensBuilder=k}),define(ne[83],se([1,0,148]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LineTokens=void 0,e.getStandardTokenTypeAtPosition=E;class k{static{this.defaultTokenMetadata=(32768|2<<24)>>>0}static createEmpty(m,_){const b=k.defaultTokenMetadata,p=new Uint32Array(2);return p[0]=m.length,p[1]=b,new k(p,m,_)}static createFromTextAndMetadata(m,_){let b=0,p="";const n=new Array;for(const{text:o,metadata:t}of m)n.push(b+o.length,t),b+=o.length,p+=o;return new k(new Uint32Array(n),p,_)}constructor(m,_,b){this._lineTokensBrand=void 0,this._tokens=m,this._tokensCount=this._tokens.length>>>1,this._text=_,this.languageIdCodec=b}equals(m){return m instanceof k?this.slicedEquals(m,0,this._tokensCount):!1}slicedEquals(m,_,b){if(this._text!==m._text||this._tokensCount!==m._tokensCount)return!1;const p=_<<1,n=p+(b<<1);for(let o=p;o0?this._tokens[m-1<<1]:0}getMetadata(m){return this._tokens[(m<<1)+1]}getLanguageId(m){const _=this._tokens[(m<<1)+1],b=d.TokenMetadata.getLanguageId(_);return this.languageIdCodec.decodeLanguageId(b)}getStandardTokenType(m){const _=this._tokens[(m<<1)+1];return d.TokenMetadata.getTokenType(_)}getForeground(m){const _=this._tokens[(m<<1)+1];return d.TokenMetadata.getForeground(_)}getClassName(m){const _=this._tokens[(m<<1)+1];return d.TokenMetadata.getClassNameFromMetadata(_)}getInlineStyle(m,_){const b=this._tokens[(m<<1)+1];return d.TokenMetadata.getInlineStyleFromMetadata(b,_)}getPresentation(m){const _=this._tokens[(m<<1)+1];return d.TokenMetadata.getPresentationFromMetadata(_)}getEndOffset(m){return this._tokens[m<<1]}findTokenIndexAtOffset(m){return k.findIndexInTokensArray(this._tokens,m)}inflate(){return this}sliceAndInflate(m,_,b){return new I(this,m,_,b)}static convertToEndOffset(m,_){const p=(m.length>>>1)-1;for(let n=0;n>>1)-1;for(;b_&&(p=n)}return b}withInserted(m){if(m.length===0)return this;let _=0,b=0,p="";const n=new Array;let o=0;for(;;){const t=_o){p+=this._text.substring(o,i.offset);const s=this._tokens[(_<<1)+1];n.push(p.length,s),o=i.offset}p+=i.text,n.push(p.length,i.tokenMetadata),b++}else break}return new k(new Uint32Array(n),p,this.languageIdCodec)}getTokenText(m){const _=this.getStartOffset(m),b=this.getEndOffset(m);return this._text.substring(_,b)}forEach(m){const _=this.getCount();for(let b=0;b<_;b++)m(b)}}e.LineTokens=k;class I{constructor(m,_,b,p){this._source=m,this._startOffset=_,this._endOffset=b,this._deltaOffset=p,this._firstTokenIndex=m.findTokenIndexAtOffset(_),this.languageIdCodec=m.languageIdCodec,this._tokensCount=0;for(let n=this._firstTokenIndex,o=m.getCount();n=b);n++)this._tokensCount++}getMetadata(m){return this._source.getMetadata(this._firstTokenIndex+m)}getLanguageId(m){return this._source.getLanguageId(this._firstTokenIndex+m)}getLineContent(){return this._source.getLineContent().substring(this._startOffset,this._endOffset)}equals(m){return m instanceof I?this._startOffset===m._startOffset&&this._endOffset===m._endOffset&&this._deltaOffset===m._deltaOffset&&this._source.slicedEquals(m._source,this._firstTokenIndex,this._tokensCount):!1}getCount(){return this._tokensCount}getStandardTokenType(m){return this._source.getStandardTokenType(this._firstTokenIndex+m)}getForeground(m){return this._source.getForeground(this._firstTokenIndex+m)}getEndOffset(m){const _=this._source.getEndOffset(this._firstTokenIndex+m);return Math.min(this._endOffset,_)-this._startOffset+this._deltaOffset}getClassName(m){return this._source.getClassName(this._firstTokenIndex+m)}getInlineStyle(m,_){return this._source.getInlineStyle(this._firstTokenIndex+m,_)}getPresentation(m){return this._source.getPresentation(this._firstTokenIndex+m)}findTokenIndexAtOffset(m){return this._source.findTokenIndexAtOffset(m+this._startOffset-this._deltaOffset)-this._firstTokenIndex}getTokenText(m){const _=this._firstTokenIndex+m,b=this._source.getStartOffset(_),p=this._source.getEndOffset(_);let n=this._source.getTokenText(_);return bthis._endOffset&&(n=n.substring(0,n.length-(p-this._endOffset))),n}forEach(m){for(let _=0;_{this.model.tokenization.forceTokenization(C);const f=this.model.tokenization.getLineTokens(C),h=this.model.getLineMaxColumn(C)-1;return(0,k.createScopedLineTokens)(f,h)};this.model.tokenization.forceTokenization(p.startLineNumber);const o=this.model.tokenization.getLineTokens(p.startLineNumber),t=(0,k.createScopedLineTokens)(o,p.startColumn-1),i=I.LineTokens.createEmpty("",t.languageIdCodec),s=p.startLineNumber-1;if(s===0||!(t.firstCharOffset===0))return i;const l=n(s);if(!(t.languageId===l.languageId))return i;const r=l.toIViewLineTokens();return this.indentationLineProcessor.getProcessedTokens(r)}}e.IndentationContextProcessor=y;class m{constructor(p,n){this.model=p,this.languageConfigurationService=n}getProcessedLine(p,n){const o=(s,g)=>{const c=d.getLeadingWhitespace(s);return g+s.substring(c.length)};this.model.tokenization.forceTokenization?.(p);const t=this.model.tokenization.getLineTokens(p);let i=this.getProcessedTokens(t).getLineContent();return n!==void 0&&(i=o(i,n)),i}getProcessedTokens(p){const n=c=>c===2||c===3||c===1,o=p.getLanguageId(0),i=this.languageConfigurationService.getLanguageConfiguration(o).bracketsNew.getBracketRegExp({global:!0}),s=[];return p.forEach(c=>{const l=p.getStandardTokenType(c);let a=p.getTokenText(c);n(l)&&(a=a.replace(i,""));const r=p.getMetadata(c);s.push({text:a,metadata:r})}),I.LineTokens.createFromTextAndMetadata(s,p.languageIdCodec)}}function _(b,p){b.tokenization.forceTokenization(p.lineNumber);const n=b.tokenization.getLineTokens(p.lineNumber),o=(0,k.createScopedLineTokens)(n,p.column-1),t=o.firstCharOffset===0,i=n.getLanguageId(0)===o.languageId;return!t&&!i}}),define(ne[241],se([1,0,11,131,240]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getInheritIndentForLine=y,e.getGoodIndentForLine=m,e.getIndentForEnter=_,e.getIndentActionForType=b,e.getIndentMetadata=p;function E(o,t,i){const s=o.tokenization.getLanguageIdAtPosition(t,0);if(t>1){let g,c=-1;for(g=t-1;g>=1;g--){if(o.tokenization.getLanguageIdAtPosition(g,0)!==s)return c;const l=o.getLineContent(g);if(i.shouldIgnore(g)||/^\s+$/.test(l)||l===""){c=g;continue}return g}}return-1}function y(o,t,i,s=!0,g){if(o<4)return null;const c=g.getLanguageConfiguration(t.tokenization.getLanguageId()).indentRulesSupport;if(!c)return null;const l=new I.ProcessedIndentRulesSupport(t,c,g);if(i<=1)return{indentation:"",action:null};for(let r=i-1;r>0&&t.getLineContent(r)==="";r--)if(r===1)return{indentation:"",action:null};const a=E(t,i,l);if(a<0)return null;if(a<1)return{indentation:"",action:null};if(l.shouldIncrease(a)||l.shouldIndentNextLine(a)){const r=t.getLineContent(a);return{indentation:d.getLeadingWhitespace(r),action:k.IndentAction.Indent,line:a}}else if(l.shouldDecrease(a)){const r=t.getLineContent(a);return{indentation:d.getLeadingWhitespace(r),action:null,line:a}}else{if(a===1)return{indentation:d.getLeadingWhitespace(t.getLineContent(a)),action:null,line:a};const r=a-1,u=c.getIndentMetadata(t.getLineContent(r));if(!(u&3)&&u&4){let C=0;for(let f=r-1;f>0;f--)if(!l.shouldIndentNextLine(f)){C=f;break}return{indentation:d.getLeadingWhitespace(t.getLineContent(C+1)),action:null,line:C+1}}if(s)return{indentation:d.getLeadingWhitespace(t.getLineContent(a)),action:null,line:a};for(let C=a;C>0;C--){if(l.shouldIncrease(C))return{indentation:d.getLeadingWhitespace(t.getLineContent(C)),action:k.IndentAction.Indent,line:C};if(l.shouldIndentNextLine(C)){let f=0;for(let h=C-1;h>0;h--)if(!l.shouldIndentNextLine(C)){f=h;break}return{indentation:d.getLeadingWhitespace(t.getLineContent(f+1)),action:null,line:f+1}}else if(l.shouldDecrease(C))return{indentation:d.getLeadingWhitespace(t.getLineContent(C)),action:null,line:C}}return{indentation:d.getLeadingWhitespace(t.getLineContent(1)),action:null,line:1}}}function m(o,t,i,s,g,c){if(o<4)return null;const l=c.getLanguageConfiguration(i);if(!l)return null;const a=c.getLanguageConfiguration(i).indentRulesSupport;if(!a)return null;const r=new I.ProcessedIndentRulesSupport(t,a,c),u=y(o,t,s,void 0,c);if(u){const C=u.line;if(C!==void 0){let f=!0;for(let h=C;h0){const D=t.getLineContent(L);if(u.shouldIndentNextLine(D)&&u.shouldIncrease(S)){const M=y(l,t,i.startLineNumber,!1,c)?.indentation;if(M!==void 0){const A=t.getLineContent(i.startLineNumber),P=d.getLeadingWhitespace(A),O=g.shiftIndent(M)===P,F=/^\s*$/.test(w),x=o.autoClosingPairs.autoClosingPairsOpenByEnd.get(s),V=x&&x.length>0&&F;if(O&&V)return M}}}return null}function p(o,t,i){const s=i.getLanguageConfiguration(o.getLanguageId()).indentRulesSupport;return!s||t<1||t>o.getLineCount()?null:s.getIndentMetadata(o.getLineContent(t))}function n(o,t,i){return{tokenization:{getLineTokens:g=>g===t?i:o.tokenization.getLineTokens(g),getLanguageId:()=>o.getLanguageId(),getLanguageIdAtPosition:(g,c)=>o.getLanguageIdAtPosition(g,c)},getLineContent:g=>g===t?i.getLineContent():o.getLineContent(g)}}}),define(ne[587],se([1,0,83]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContiguousTokensEditing=e.EMPTY_LINE_TOKENS=void 0,e.toUint32Array=I,e.EMPTY_LINE_TOKENS=new Uint32Array(0).buffer;class k{static deleteBeginning(y,m){return y===null||y===e.EMPTY_LINE_TOKENS?y:k.delete(y,0,m)}static deleteEnding(y,m){if(y===null||y===e.EMPTY_LINE_TOKENS)return y;const _=I(y),b=_[_.length-2];return k.delete(y,m,b)}static delete(y,m,_){if(y===null||y===e.EMPTY_LINE_TOKENS||m===_)return y;const b=I(y),p=b.length>>>1;if(m===0&&b[b.length-2]===_)return e.EMPTY_LINE_TOKENS;const n=d.LineTokens.findIndexInTokensArray(b,m),o=n>0?b[n-1<<1]:0,t=b[n<<1];if(_s&&(b[i++]=a,b[i++]=b[(l<<1)+1],s=a)}if(i===b.length)return y;const c=new Uint32Array(i);return c.set(b.subarray(0,i),0),c.buffer}static append(y,m){if(m===e.EMPTY_LINE_TOKENS)return y;if(y===e.EMPTY_LINE_TOKENS)return m;if(y===null)return y;if(m===null)return null;const _=I(y),b=I(m),p=b.length>>>1,n=new Uint32Array(_.length+b.length);n.set(_,0);let o=_.length;const t=_[_.length-2];for(let i=0;i>>1;let n=d.LineTokens.findIndexInTokensArray(b,m);n>0&&b[n-1<<1]===m&&n--;for(let o=n;o0}getTokens(p,n,o){let t=null;if(n1&&(i=y.TokenMetadata.getLanguageId(t[1])!==p),!i)return I.EMPTY_LINE_TOKENS}if(!t||t.length===0){const i=new Uint32Array(2);return i[0]=n,i[1]=_(p),i.buffer}return t[t.length-2]=n,t.byteOffset===0&&t.byteLength===t.buffer.byteLength?t.buffer:t}_ensureLine(p){for(;p>=this._len;)this._lineTokens[this._len]=null,this._len++}_deleteLines(p,n){n!==0&&(p+n>this._len&&(n=this._len-p),this._lineTokens.splice(p,n),this._len-=n)}_insertLines(p,n){if(n===0)return;const o=[];for(let t=0;t=this._len)return;if(p.startLineNumber===p.endLineNumber){if(p.startColumn===p.endColumn)return;this._lineTokens[n]=I.ContiguousTokensEditing.delete(this._lineTokens[n],p.startColumn-1,p.endColumn-1);return}this._lineTokens[n]=I.ContiguousTokensEditing.deleteEnding(this._lineTokens[n],p.startColumn-1);const o=p.endLineNumber-1;let t=null;o=this._len)){if(n===0){this._lineTokens[t]=I.ContiguousTokensEditing.insert(this._lineTokens[t],p.column-1,o);return}this._lineTokens[t]=I.ContiguousTokensEditing.deleteEnding(this._lineTokens[t],p.column-1),this._lineTokens[t]=I.ContiguousTokensEditing.insert(this._lineTokens[t],p.column-1,o),this._insertLines(p.lineNumber,n)}}setMultilineTokens(p,n){if(p.length===0)return{changes:[]};const o=[];for(let t=0,i=p.length;t>>0}}),define(ne[589],se([1,0,9,4,145]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SparseLineTokens=e.SparseMultilineTokens=void 0;class E{static create(b,p){return new E(b,new y(p))}get startLineNumber(){return this._startLineNumber}get endLineNumber(){return this._endLineNumber}constructor(b,p){this._startLineNumber=b,this._tokens=p,this._endLineNumber=this._startLineNumber+this._tokens.getMaxDeltaLine()}toString(){return this._tokens.toString(this._startLineNumber)}_updateEndLineNumber(){this._endLineNumber=this._startLineNumber+this._tokens.getMaxDeltaLine()}isEmpty(){return this._tokens.isEmpty()}getLineTokens(b){return this._startLineNumber<=b&&b<=this._endLineNumber?this._tokens.getLineTokens(b-this._startLineNumber):null}getRange(){const b=this._tokens.getRange();return b&&new k.Range(this._startLineNumber+b.startLineNumber,b.startColumn,this._startLineNumber+b.endLineNumber,b.endColumn)}removeTokens(b){const p=b.startLineNumber-this._startLineNumber,n=b.endLineNumber-this._startLineNumber;this._startLineNumber+=this._tokens.removeTokens(p,b.startColumn-1,n,b.endColumn-1),this._updateEndLineNumber()}split(b){const p=b.startLineNumber-this._startLineNumber,n=b.endLineNumber-this._startLineNumber,[o,t,i]=this._tokens.split(p,b.startColumn-1,n,b.endColumn-1);return[new E(this._startLineNumber,o),new E(this._startLineNumber+i,t)]}applyEdit(b,p){const[n,o,t]=(0,I.countEOL)(p);this.acceptEdit(b,n,o,t,p.length>0?p.charCodeAt(0):0)}acceptEdit(b,p,n,o,t){this._acceptDeleteRange(b),this._acceptInsertText(new d.Position(b.startLineNumber,b.startColumn),p,n,o,t),this._updateEndLineNumber()}_acceptDeleteRange(b){if(b.startLineNumber===b.endLineNumber&&b.startColumn===b.endColumn)return;const p=b.startLineNumber-this._startLineNumber,n=b.endLineNumber-this._startLineNumber;if(n<0){const t=n-p;this._startLineNumber-=t;return}const o=this._tokens.getMaxDeltaLine();if(!(p>=o+1)){if(p<0&&n>=o+1){this._startLineNumber=0,this._tokens.clear();return}if(p<0){const t=-p;this._startLineNumber-=t,this._tokens.acceptDeleteRange(b.startColumn-1,0,0,n,b.endColumn-1)}else this._tokens.acceptDeleteRange(0,p,b.startColumn-1,n,b.endColumn-1)}}_acceptInsertText(b,p,n,o,t){if(p===0&&n===0)return;const i=b.lineNumber-this._startLineNumber;if(i<0){this._startLineNumber+=p;return}const s=this._tokens.getMaxDeltaLine();i>=s+1||this._tokens.acceptInsertText(i,b.column-1,p,n,o,t)}}e.SparseMultilineTokens=E;class y{constructor(b){this._tokens=b,this._tokenCount=b.length/4}toString(b){const p=[];for(let n=0;nb)n=o-1;else{let i=o;for(;i>p&&this._getDeltaLine(i-1)===b;)i--;let s=o;for(;sb||r===b&&C>=p)&&(rb||C===b&&h>=p){if(Ct?f-=t-n:f=n;else if(u===p&&C===n)if(u===o&&f>t)f-=t-n;else{l=!0;continue}else if(ut)u=p,C=n,f=C+(f-t);else{l=!0;continue}else if(u>o){if(g===0&&!l){c=s;break}u-=g}else if(u===o&&C>=t)b&&u===0&&(C+=b,f+=b),u-=g,C-=t-n,f-=t-n;else throw new Error("Not possible!");const v=4*c;i[v]=u,i[v+1]=C,i[v+2]=f,i[v+3]=h,c++}this._tokenCount=c}acceptInsertText(b,p,n,o,t,i){const s=n===0&&o===1&&(i>=48&&i<=57||i>=65&&i<=90||i>=97&&i<=122),g=this._tokens,c=this._tokenCount;for(let l=0;l0){const p=m[0].getRange(),n=m[m.length-1].getRange();if(!p||!n)return y;_=y.plusRange(p).plusRange(n)}let b=null;for(let p=0,n=this._pieces.length;p_.endLineNumber){b=b||{index:p};break}if(o.removeTokens(_),o.isEmpty()){this._pieces.splice(p,1),p--,n--;continue}if(o.endLineNumber<_.startLineNumber)continue;if(o.startLineNumber>_.endLineNumber){b=b||{index:p};continue}const[t,i]=o.split(_);if(t.isEmpty()){b=b||{index:p};continue}i.isEmpty()||(this._pieces.splice(p,1,t,i),p++,n++,b=b||{index:p})}return b=b||{index:this._pieces.length},m.length>0&&(this._pieces=d.arrayInsert(this._pieces,b.index,m)),_}isComplete(){return this._isComplete}addSparseTokens(y,m){if(m.getLineContent().length===0)return m;const _=this._pieces;if(_.length===0)return m;const b=I._findFirstPieceWithLine(_,y),p=_[b].getLineTokens(y);if(!p)return m;const n=m.getCount(),o=p.getCount();let t=0;const i=[];let s=0,g=0;const c=(l,a)=>{l!==g&&(g=l,i[s++]=l,i[s++]=a)};for(let l=0;l>>0,f=~C>>>0;for(;tm)b=p-1;else{for(;p>_&&y[p-1].startLineNumber<=m&&m<=y[p-1].endLineNumber;)p--;return p}}return _}acceptEdit(y,m,_,b,p){for(const n of this._pieces)n.acceptEdit(y,m,_,b,p)}}e.SparseTokensStore=I}),define(ne[170],se([1,0,2]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewEventHandler=void 0;class k extends d.Disposable{constructor(){super(),this._shouldRender=!0}shouldRender(){return this._shouldRender}forceShouldRender(){this._shouldRender=!0}setShouldRender(){this._shouldRender=!0}onDidRender(){this._shouldRender=!1}onCompositionStart(E){return!1}onCompositionEnd(E){return!1}onConfigurationChanged(E){return!1}onCursorStateChanged(E){return!1}onDecorationsChanged(E){return!1}onFlushed(E){return!1}onFocusChanged(E){return!1}onLanguageConfigurationChanged(E){return!1}onLineMappingChanged(E){return!1}onLinesChanged(E){return!1}onLinesDeleted(E){return!1}onLinesInserted(E){return!1}onRevealRangeRequest(E){return!1}onScrollChanged(E){return!1}onThemeChanged(E){return!1}onTokensChanged(E){return!1}onTokensColorsChanged(E){return!1}onZonesChanged(E){return!1}handleEvents(E){let y=!1;for(let m=0,_=E.length;m<_;m++){const b=E[m];switch(b.type){case 0:this.onCompositionStart(b)&&(y=!0);break;case 1:this.onCompositionEnd(b)&&(y=!0);break;case 2:this.onConfigurationChanged(b)&&(y=!0);break;case 3:this.onCursorStateChanged(b)&&(y=!0);break;case 4:this.onDecorationsChanged(b)&&(y=!0);break;case 5:this.onFlushed(b)&&(y=!0);break;case 6:this.onFocusChanged(b)&&(y=!0);break;case 7:this.onLanguageConfigurationChanged(b)&&(y=!0);break;case 8:this.onLineMappingChanged(b)&&(y=!0);break;case 9:this.onLinesChanged(b)&&(y=!0);break;case 10:this.onLinesDeleted(b)&&(y=!0);break;case 11:this.onLinesInserted(b)&&(y=!0);break;case 12:this.onRevealRangeRequest(b)&&(y=!0);break;case 13:this.onScrollChanged(b)&&(y=!0);break;case 15:this.onTokensChanged(b)&&(y=!0);break;case 14:this.onThemeChanged(b)&&(y=!0);break;case 16:this.onTokensColorsChanged(b)&&(y=!0);break;case 17:this.onZonesChanged(b)&&(y=!0);break;default:console.info("View received unknown event: "),console.info(b)}}y&&(this._shouldRender=!0)}}e.ViewEventHandler=k}),define(ne[133],se([1,0,170]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DynamicViewOverlay=void 0;class k extends d.ViewEventHandler{}e.DynamicViewOverlay=k}),define(ne[56],se([1,0,170]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PartFingerprints=e.ViewPart=void 0;class k extends d.ViewEventHandler{constructor(y){super(),this._context=y,this._context.addEventHandler(this)}dispose(){this._context.removeEventHandler(this),super.dispose()}}e.ViewPart=k;class I{static write(y,m){y.setAttribute("data-mprt",String(m))}static read(y){const m=y.getAttribute("data-mprt");return m===null?0:parseInt(m,10)}static collect(y,m){const _=[];let b=0;for(;y&&y!==y.ownerDocument.body&&y!==m;)y.nodeType===y.ELEMENT_NODE&&(_[b++]=this.read(y)),y=y.parentElement;const p=new Uint8Array(b);for(let n=0;n{if(i.options.zIndexs.options.zIndex)return 1;const g=i.options.className,c=s.options.className;return gc?1:I.Range.compareRangesUsingStarts(i.range,s.range)});const n=m.visibleRange.startLineNumber,o=m.visibleRange.endLineNumber,t=[];for(let i=n;i<=o;i++){const s=i-n;t[s]=""}this._renderWholeLineDecorations(m,b,t),this._renderNormalDecorations(m,b,t),this._renderResult=t}_renderWholeLineDecorations(m,_,b){const p=m.visibleRange.startLineNumber,n=m.visibleRange.endLineNumber;for(let o=0,t=_.length;o',g=Math.max(i.range.startLineNumber,p),c=Math.min(i.range.endLineNumber,n);for(let l=g;l<=c;l++){const a=l-p;b[a]+=s}}}_renderNormalDecorations(m,_,b){const p=m.visibleRange.startLineNumber;let n=null,o=!1,t=null,i=!1;for(let s=0,g=_.length;s';t[l]+=f}}}render(m,_){if(!this._renderResult)return"";const b=_-m;return b<0||b>=this._renderResult.length?"":this._renderResult[b]}}e.DecorationsOverlay=E}),define(ne[242],se([1,0,39,13,133,56,9,4,40,484]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GlyphMarginWidgets=e.DedupOverlay=e.VisibleLineDecorationsToRender=e.LineDecorationToRender=e.DecorationToRender=void 0;class b{constructor(l,a,r,u,C){this.startLineNumber=l,this.endLineNumber=a,this.className=r,this.tooltip=u,this._decorationToRenderBrand=void 0,this.zIndex=C??0}}e.DecorationToRender=b;class p{constructor(l,a,r){this.className=l,this.zIndex=a,this.tooltip=r}}e.LineDecorationToRender=p;class n{constructor(){this.decorations=[]}add(l){this.decorations.push(l)}getDecorations(){return this.decorations}}e.VisibleLineDecorationsToRender=n;class o extends I.DynamicViewOverlay{_render(l,a,r){const u=[];for(let h=l;h<=a;h++){const v=h-l;u[v]=new n}if(r.length===0)return u;r.sort((h,v)=>h.className===v.className?h.startLineNumber===v.startLineNumber?h.endLineNumber-v.endLineNumber:h.startLineNumber-v.startLineNumber:h.classNameu)continue;const w=Math.max(h,r),S=this._context.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new y.Position(w,0)),L=this._context.viewModel.glyphLanes.getLanesAtLine(S.lineNumber).indexOf(C.preference.lane);a.push(new s(w,L,C.preference.zIndex,C))}}_collectSortedGlyphRenderRequests(l){const a=[];return this._collectDecorationBasedGlyphRenderRequest(l,a),this._collectWidgetBasedGlyphRenderRequest(l,a),a.sort((r,u)=>r.lineNumber===u.lineNumber?r.laneIndex===u.laneIndex?r.zIndex===u.zIndex?u.type===r.type?r.type===0&&u.type===0?r.className0;){const u=a.peek();if(!u)break;const C=a.takeWhile(h=>h.lineNumber===u.lineNumber&&h.laneIndex===u.laneIndex);if(!C||C.length===0)break;const f=C[0];if(f.type===0){const h=[];for(const v of C){if(v.zIndex!==f.zIndex||v.type!==f.type)break;(h.length===0||h[h.length-1]!==v.className)&&h.push(v.className)}r.push(f.accept(h.join(" ")))}else f.widget.renderInfo={lineNumber:f.lineNumber,laneIndex:f.laneIndex}}this._decorationGlyphsToRender=r}render(l){if(!this._glyphMargin){for(const r of Object.values(this._widgets))r.domNode.setDisplay("none");for(;this._managedDomNodes.length>0;)this._managedDomNodes.pop()?.domNode.remove();return}const a=Math.round(this._glyphMarginWidth/this._glyphMarginDecorationLaneCount);for(const r of Object.values(this._widgets))if(!r.renderInfo)r.domNode.setDisplay("none");else{const u=l.viewportData.relativeVerticalOffset[r.renderInfo.lineNumber-l.viewportData.startLineNumber],C=this._glyphMarginLeft+r.renderInfo.laneIndex*this._lineHeight;r.domNode.setDisplay("block"),r.domNode.setTop(u),r.domNode.setLeft(C),r.domNode.setWidth(a),r.domNode.setHeight(this._lineHeight)}for(let r=0;rthis._decorationGlyphsToRender.length;)this._managedDomNodes.pop()?.domNode.remove()}}e.GlyphMarginWidgets=t;class i{constructor(l,a,r,u){this.lineNumber=l,this.laneIndex=a,this.zIndex=r,this.className=u,this.type=0}accept(l){return new g(this.lineNumber,this.laneIndex,l)}}class s{constructor(l,a,r,u){this.lineNumber=l,this.laneIndex=a,this.zIndex=r,this.widget=u,this.type=1}}class g{constructor(l,a,r){this.lineNumber=l,this.laneIndex=a,this.combinedClassName=r}}}),define(ne[593],se([1,0,242,488]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LinesDecorationsOverlay=void 0;class k extends d.DedupOverlay{constructor(E){super(),this._context=E;const m=this._context.configuration.options.get(146);this._decorationsLeft=m.decorationsLeft,this._decorationsWidth=m.decorationsWidth,this._renderResult=null,this._context.addEventHandler(this)}dispose(){this._context.removeEventHandler(this),this._renderResult=null,super.dispose()}onConfigurationChanged(E){const m=this._context.configuration.options.get(146);return this._decorationsLeft=m.decorationsLeft,this._decorationsWidth=m.decorationsWidth,!0}onDecorationsChanged(E){return!0}onFlushed(E){return!0}onLinesChanged(E){return!0}onLinesDeleted(E){return!0}onLinesInserted(E){return!0}onScrollChanged(E){return E.scrollTopChanged}onZonesChanged(E){return!0}_getDecorations(E){const y=E.getDecorationsInViewport(),m=[];let _=0;for(let b=0,p=y.length;b',o=[];for(let t=y;t<=m;t++){const i=t-y,s=_[i].getDecorations();let g="";for(const c of s){let l='
      ';b[n]=t}this._renderResult=b}render(E,y){return this._renderResult?this._renderResult[y-E]:""}}e.MarginViewLineDecorationsOverlay=k}),define(ne[595],se([1,0,39,56,493]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Rulers=void 0;class I extends k.ViewPart{constructor(y){super(y),this.domNode=(0,d.createFastDomNode)(document.createElement("div")),this.domNode.setAttribute("role","presentation"),this.domNode.setAttribute("aria-hidden","true"),this.domNode.setClassName("view-rulers"),this._renderedRulers=[];const m=this._context.configuration.options;this._rulers=m.get(103),this._typicalHalfwidthCharacterWidth=m.get(50).typicalHalfwidthCharacterWidth}dispose(){super.dispose()}onConfigurationChanged(y){const m=this._context.configuration.options;return this._rulers=m.get(103),this._typicalHalfwidthCharacterWidth=m.get(50).typicalHalfwidthCharacterWidth,!0}onScrollChanged(y){return y.scrollHeightChanged}prepareRender(y){}_ensureRulersCount(){const y=this._renderedRulers.length,m=this._rulers.length;if(y===m)return;if(y0;){const o=(0,d.createFastDomNode)(document.createElement("div"));o.setClassName("view-ruler"),o.setWidth(p),this.domNode.appendChild(o),this._renderedRulers.push(o),n--}return}let _=y-m;for(;_>0;){const b=this._renderedRulers.pop();this.domNode.removeChild(b),_--}}render(y){this._ensureRulersCount();for(let m=0,_=this._rulers.length;m<_;m++){const b=this._renderedRulers[m],p=this._rulers[m];b.setBoxShadow(p.color?`1px 0 0 0 ${p.color} inset`:""),b.setHeight(Math.min(y.scrollHeight,1e6)),b.setLeft(p.column*this._typicalHalfwidthCharacterWidth)}}}e.Rulers=I}),define(ne[596],se([1,0,39,56,494]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ScrollDecorationViewPart=void 0;class I extends k.ViewPart{constructor(y){super(y),this._scrollTop=0,this._width=0,this._updateWidth(),this._shouldShow=!1;const _=this._context.configuration.options.get(104);this._useShadows=_.useShadows,this._domNode=(0,d.createFastDomNode)(document.createElement("div")),this._domNode.setAttribute("role","presentation"),this._domNode.setAttribute("aria-hidden","true")}dispose(){super.dispose()}_updateShouldShow(){const y=this._useShadows&&this._scrollTop>0;return this._shouldShow!==y?(this._shouldShow=y,!0):!1}getDomNode(){return this._domNode}_updateWidth(){const m=this._context.configuration.options.get(146);m.minimap.renderMinimap===0||m.minimap.minimapWidth>0&&m.minimap.minimapLeft===0?this._width=m.width:this._width=m.width-m.verticalScrollbarWidth}onConfigurationChanged(y){const _=this._context.configuration.options.get(104);return this._useShadows=_.useShadows,this._updateWidth(),this._updateShouldShow(),!0}onScrollChanged(y){return this._scrollTop=y.scrollTop,this._updateShouldShow()}prepareRender(y){}render(y){this._domNode.setWidth(this._width),this._domNode.setClassName(this._shouldShow?"scroll-decoration":"")}}e.ScrollDecorationViewPart=I}),define(ne[597],se([1,0,39,8,56,9]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewZones=void 0;const y=()=>{throw new Error("Invalid change accessor")};class m extends I.ViewPart{constructor(p){super(p);const n=this._context.configuration.options,o=n.get(146);this._lineHeight=n.get(67),this._contentWidth=o.contentWidth,this._contentLeft=o.contentLeft,this.domNode=(0,d.createFastDomNode)(document.createElement("div")),this.domNode.setClassName("view-zones"),this.domNode.setPosition("absolute"),this.domNode.setAttribute("role","presentation"),this.domNode.setAttribute("aria-hidden","true"),this.marginDomNode=(0,d.createFastDomNode)(document.createElement("div")),this.marginDomNode.setClassName("margin-view-zones"),this.marginDomNode.setPosition("absolute"),this.marginDomNode.setAttribute("role","presentation"),this.marginDomNode.setAttribute("aria-hidden","true"),this._zones={}}dispose(){super.dispose(),this._zones={}}_recomputeWhitespacesProps(){const p=this._context.viewLayout.getWhitespaces(),n=new Map;for(const t of p)n.set(t.id,t);let o=!1;return this._context.viewModel.changeWhitespace(t=>{const i=Object.keys(this._zones);for(let s=0,g=i.length;s{const t={addZone:i=>(n=!0,this._addZone(o,i)),removeZone:i=>{i&&(n=this._removeZone(o,i)||n)},layoutZone:i=>{i&&(n=this._layoutZone(o,i)||n)}};_(p,t),t.addZone=y,t.removeZone=y,t.layoutZone=y}),n}_addZone(p,n){const o=this._computeWhitespaceProps(n),i={whitespaceId:p.insertWhitespace(o.afterViewLineNumber,this._getZoneOrdinal(n),o.heightInPx,o.minWidthInPx),delegate:n,isInHiddenArea:o.isInHiddenArea,isVisible:!1,domNode:(0,d.createFastDomNode)(n.domNode),marginDomNode:n.marginDomNode?(0,d.createFastDomNode)(n.marginDomNode):null};return this._safeCallOnComputedHeight(i.delegate,o.heightInPx),i.domNode.setPosition("absolute"),i.domNode.domNode.style.width="100%",i.domNode.setDisplay("none"),i.domNode.setAttribute("monaco-view-zone",i.whitespaceId),this.domNode.appendChild(i.domNode),i.marginDomNode&&(i.marginDomNode.setPosition("absolute"),i.marginDomNode.domNode.style.width="100%",i.marginDomNode.setDisplay("none"),i.marginDomNode.setAttribute("monaco-view-zone",i.whitespaceId),this.marginDomNode.appendChild(i.marginDomNode)),this._zones[i.whitespaceId]=i,this.setShouldRender(),i.whitespaceId}_removeZone(p,n){if(this._zones.hasOwnProperty(n)){const o=this._zones[n];return delete this._zones[n],p.removeWhitespace(o.whitespaceId),o.domNode.removeAttribute("monaco-visible-view-zone"),o.domNode.removeAttribute("monaco-view-zone"),o.domNode.domNode.remove(),o.marginDomNode&&(o.marginDomNode.removeAttribute("monaco-visible-view-zone"),o.marginDomNode.removeAttribute("monaco-view-zone"),o.marginDomNode.domNode.remove()),this.setShouldRender(),!0}return!1}_layoutZone(p,n){if(this._zones.hasOwnProperty(n)){const o=this._zones[n],t=this._computeWhitespaceProps(o.delegate);return o.isInHiddenArea=t.isInHiddenArea,p.changeOneWhitespace(o.whitespaceId,t.afterViewLineNumber,t.heightInPx),this._safeCallOnComputedHeight(o.delegate,t.heightInPx),this.setShouldRender(),!0}return!1}shouldSuppressMouseDownOnViewZone(p){return this._zones.hasOwnProperty(p)?!!this._zones[p].delegate.suppressMouseDown:!1}_heightInPixels(p){return typeof p.heightInPx=="number"?p.heightInPx:typeof p.heightInLines=="number"?this._lineHeight*p.heightInLines:this._lineHeight}_minWidthInPixels(p){return typeof p.minWidthInPx=="number"?p.minWidthInPx:0}_safeCallOnComputedHeight(p,n){if(typeof p.onComputedHeight=="function")try{p.onComputedHeight(n)}catch(o){(0,k.onUnexpectedError)(o)}}_safeCallOnDomNodeTop(p,n){if(typeof p.onDomNodeTop=="function")try{p.onDomNodeTop(n)}catch(o){(0,k.onUnexpectedError)(o)}}prepareRender(p){}render(p){const n=p.viewportData.whitespaceViewportData,o={};let t=!1;for(const s of n)this._zones[s.id].isInHiddenArea||(o[s.id]=s,t=!0);const i=Object.keys(this._zones);for(let s=0,g=i.length;s=o||(i[s++]=new k(Math.max(1,g.startColumn-n+1),Math.min(t+1,g.endColumn-n+1),g.className,g.type));return i}static filter(_,b,p,n){if(_.length===0)return[];const o=[];let t=0;for(let i=0,s=_.length;ib||c.isEmpty()&&(g.type===0||g.type===3))continue;const l=c.startLineNumber===b?c.startColumn:p,a=c.endLineNumber===b?c.endColumn:n;o[t++]=new k(l,a,g.inlineClassName,g.type)}return o}static _typeCompare(_,b){const p=[2,0,1,3];return p[_]-p[b]}static compare(_,b){if(_.startColumn!==b.startColumn)return _.startColumn-b.startColumn;if(_.endColumn!==b.endColumn)return _.endColumn-b.endColumn;const p=k._typeCompare(_.type,b.type);return p!==0?p:_.className!==b.className?_.className0&&this.stopOffsets[0]<_;){let n=0;for(;n+10&&b<_&&(p.push(new I(b,_-1,this.classNames.join(" "),E._metadata(this.metadata))),b=_),b}insert(_,b,p){if(this.count===0||this.stopOffsets[this.count-1]<=_)this.stopOffsets.push(_),this.classNames.push(b),this.metadata.push(p);else for(let n=0;n=_){this.stopOffsets.splice(n,0,_),this.classNames.splice(n,0,b),this.metadata.splice(n,0,p);break}this.count++}}class y{static normalize(_,b){if(b.length===0)return[];const p=[],n=new E;let o=0;for(let t=0,i=b.length;t1){const C=_.charCodeAt(g-2);d.isHighSurrogate(C)&&g--}if(c>1){const C=_.charCodeAt(c-2);d.isHighSurrogate(C)&&c--}const r=g-1,u=c-2;o=n.consumeLowerThan(r,o,p),n.count===0&&(o=r),n.insert(u,l,a)}return n.consumeLowerThan(1073741824,o,p),p}}e.LineDecorationsNormalizer=y}),define(ne[598],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LinePart=void 0;class d{constructor(I,E,y,m){this.endIndex=I,this.type=E,this.metadata=y,this.containsRTL=m,this._linePartBrand=void 0}isWhitespace(){return!!(this.metadata&1)}isPseudoAfter(){return!!(this.metadata&4)}}e.LinePart=d}),define(ne[599],se([1,0,11]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LinesLayout=e.EditorWhitespace=void 0;class k{constructor(){this._hasPending=!1,this._inserts=[],this._changes=[],this._removes=[]}insert(m){this._hasPending=!0,this._inserts.push(m)}change(m){this._hasPending=!0,this._changes.push(m)}remove(m){this._hasPending=!0,this._removes.push(m)}mustCommit(){return this._hasPending}commit(m){if(!this._hasPending)return;const _=this._inserts,b=this._changes,p=this._removes;this._hasPending=!1,this._inserts=[],this._changes=[],this._removes=[],m._commitPendingChanges(_,b,p)}}class I{constructor(m,_,b,p,n){this.id=m,this.afterLineNumber=_,this.ordinal=b,this.height=p,this.minWidth=n,this.prefixSum=0}}e.EditorWhitespace=I;class E{static{this.INSTANCE_COUNT=0}constructor(m,_,b,p){this._instanceId=d.singleLetterHash(++E.INSTANCE_COUNT),this._pendingChanges=new k,this._lastWhitespaceId=0,this._arr=[],this._prefixSumValidIndex=-1,this._minWidth=-1,this._lineCount=m,this._lineHeight=_,this._paddingTop=b,this._paddingBottom=p}static findInsertionIndex(m,_,b){let p=0,n=m.length;for(;p>>1;_===m[o].afterLineNumber?b{_=!0,p=p|0,n=n|0,o=o|0,t=t|0;const i=this._instanceId+ ++this._lastWhitespaceId;return this._pendingChanges.insert(new I(i,p,n,o,t)),i},changeOneWhitespace:(p,n,o)=>{_=!0,n=n|0,o=o|0,this._pendingChanges.change({id:p,newAfterLineNumber:n,newHeight:o})},removeWhitespace:p=>{_=!0,this._pendingChanges.remove({id:p})}})}finally{this._pendingChanges.commit(this)}return _}_commitPendingChanges(m,_,b){if((m.length>0||b.length>0)&&(this._minWidth=-1),m.length+_.length+b.length<=1){for(const i of m)this._insertWhitespace(i);for(const i of _)this._changeOneWhitespace(i.id,i.newAfterLineNumber,i.newHeight);for(const i of b){const s=this._findWhitespaceIndex(i.id);s!==-1&&this._removeWhitespace(s)}return}const p=new Set;for(const i of b)p.add(i.id);const n=new Map;for(const i of _)n.set(i.id,i);const o=i=>{const s=[];for(const g of i)if(!p.has(g.id)){if(n.has(g.id)){const c=n.get(g.id);g.afterLineNumber=c.newAfterLineNumber,g.height=c.newHeight}s.push(g)}return s},t=o(this._arr).concat(o(m));t.sort((i,s)=>i.afterLineNumber===s.afterLineNumber?i.ordinal-s.ordinal:i.afterLineNumber-s.afterLineNumber),this._arr=t,this._prefixSumValidIndex=-1}_checkPendingChanges(){this._pendingChanges.mustCommit()&&this._pendingChanges.commit(this)}_insertWhitespace(m){const _=E.findInsertionIndex(this._arr,m.afterLineNumber,m.ordinal);this._arr.splice(_,0,m),this._prefixSumValidIndex=Math.min(this._prefixSumValidIndex,_-1)}_findWhitespaceIndex(m){const _=this._arr;for(let b=0,p=_.length;b_&&(this._arr[b].afterLineNumber-=_-m+1)}}onLinesInserted(m,_){this._checkPendingChanges(),m=m|0,_=_|0,this._lineCount+=_-m+1;for(let b=0,p=this._arr.length;b=_.length||_[t+1].afterLineNumber>=m)return t;b=t+1|0}else p=t-1|0}return-1}_findFirstWhitespaceAfterLineNumber(m){m=m|0;const b=this._findLastWhitespaceBeforeLineNumber(m)+1;return b1?b=this._lineHeight*(m-1):b=0;const p=this.getWhitespaceAccumulatedHeightBeforeLineNumber(m-(_?1:0));return b+p+this._paddingTop}getVerticalOffsetAfterLineNumber(m,_=!1){this._checkPendingChanges(),m=m|0;const b=this._lineHeight*m,p=this.getWhitespaceAccumulatedHeightBeforeLineNumber(m+(_?1:0));return b+p+this._paddingTop}getWhitespaceMinWidth(){if(this._checkPendingChanges(),this._minWidth===-1){let m=0;for(let _=0,b=this._arr.length;__}isInTopPadding(m){return this._paddingTop===0?!1:(this._checkPendingChanges(),m=_-this._paddingBottom}getLineNumberAtOrAfterVerticalOffset(m){if(this._checkPendingChanges(),m=m|0,m<0)return 1;const _=this._lineCount|0,b=this._lineHeight;let p=1,n=_;for(;p=t+b)p=o+1;else{if(m>=t)return o;n=o}}return p>_?_:p}getLinesViewportData(m,_){this._checkPendingChanges(),m=m|0,_=_|0;const b=this._lineHeight,p=this.getLineNumberAtOrAfterVerticalOffset(m)|0,n=this.getVerticalOffsetForLineNumber(p)|0;let o=this._lineCount|0,t=this.getFirstWhitespaceIndexAfterLineNumber(p)|0;const i=this.getWhitespacesCount()|0;let s,g;t===-1?(t=i,g=o+1,s=0):(g=this.getAfterLineNumberForWhitespaceIndex(t)|0,s=this.getHeightForWhitespaceIndex(t)|0);let c=n,l=c;const a=5e5;let r=0;n>=a&&(r=Math.floor(n/a)*a,r=Math.floor(r/b)*b,l-=r);const u=[],C=m+(_-m)/2;let f=-1;for(let S=p;S<=o;S++){if(f===-1){const L=c,D=c+b;(L<=C&&CC)&&(f=S)}for(c+=b,u[S-p]=l,l+=b;g===S;)l+=s,c+=s,t++,t>=i?g=o+1:(g=this.getAfterLineNumberForWhitespaceIndex(t)|0,s=this.getHeightForWhitespaceIndex(t)|0);if(c>=_){o=S;break}}f===-1&&(f=o);const h=this.getVerticalOffsetForLineNumber(o)|0;let v=p,w=o;return v_&&w--,{bigNumbersDelta:r,startLineNumber:p,endLineNumber:o,relativeVerticalOffset:u,centeredLineNumber:f,completelyVisibleStartLineNumber:v,completelyVisibleEndLineNumber:w,lineHeight:this._lineHeight}}getVerticalOffsetForWhitespaceIndex(m){this._checkPendingChanges(),m=m|0;const _=this.getAfterLineNumberForWhitespaceIndex(m);let b;_>=1?b=this._lineHeight*_:b=0;let p;return m>0?p=this.getWhitespacesAccumulatedHeight(m-1):p=0,b+p+this._paddingTop}getWhitespaceIndexAtOrAfterVerticallOffset(m){this._checkPendingChanges(),m=m|0;let _=0,b=this.getWhitespacesCount()-1;if(b<0)return-1;const p=this.getVerticalOffsetForWhitespaceIndex(b),n=this.getHeightForWhitespaceIndex(b);if(m>=p+n)return-1;for(;_=t+i)_=o+1;else{if(m>=t)return o;b=o}}return _}getWhitespaceAtVerticalOffset(m){this._checkPendingChanges(),m=m|0;const _=this.getWhitespaceIndexAtOrAfterVerticallOffset(m);if(_<0||_>=this.getWhitespacesCount())return null;const b=this.getVerticalOffsetForWhitespaceIndex(_);if(b>m)return null;const p=this.getHeightForWhitespaceIndex(_),n=this.getIdForWhitespaceIndex(_),o=this.getAfterLineNumberForWhitespaceIndex(_);return{id:n,afterLineNumber:o,verticalOffset:b,height:p}}getWhitespaceViewportData(m,_){this._checkPendingChanges(),m=m|0,_=_|0;const b=this.getWhitespaceIndexAtOrAfterVerticallOffset(m),p=this.getWhitespacesCount()-1;if(b<0)return[];const n=[];for(let o=b;o<=p;o++){const t=this.getVerticalOffsetForWhitespaceIndex(o),i=this.getHeightForWhitespaceIndex(o);if(t>=_)break;n.push({id:this.getIdForWhitespaceIndex(o),afterLineNumber:this.getAfterLineNumberForWhitespaceIndex(o),verticalOffset:t,height:i})}return n}getWhitespaces(){return this._checkPendingChanges(),this._arr.slice(0)}getWhitespacesCount(){return this._checkPendingChanges(),this._arr.length}getIdForWhitespaceIndex(m){return this._checkPendingChanges(),m=m|0,this._arr[m].id}getAfterLineNumberForWhitespaceIndex(m){return this._checkPendingChanges(),m=m|0,this._arr[m].afterLineNumber}getHeightForWhitespaceIndex(m){return this._checkPendingChanges(),m=m|0,this._arr[m].height}}e.LinesLayout=E}),define(ne[600],se([1,0,4]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewportData=void 0;class k{constructor(E,y,m,_){this.selections=E,this.startLineNumber=y.startLineNumber|0,this.endLineNumber=y.endLineNumber|0,this.relativeVerticalOffset=y.relativeVerticalOffset,this.bigNumbersDelta=y.bigNumbersDelta|0,this.lineHeight=y.lineHeight|0,this.whitespaceViewportData=m,this._model=_,this.visibleRange=new d.Range(y.startLineNumber,this._model.getLineMinColumn(y.startLineNumber),y.endLineNumber,this._model.getLineMaxColumn(y.endLineNumber))}getViewLineRenderingData(E){return this._model.getViewportViewLineRenderingData(this.visibleRange,E)}getDecorationsInViewport(){return this._model.getDecorationsInViewport(this.visibleRange)}}e.ViewportData=k}),define(ne[95],se([1,0,13,11,4]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OverviewRulerDecorationsGroup=e.ViewModelDecoration=e.SingleLineInlineDecoration=e.InlineDecoration=e.ViewLineRenderingData=e.ViewLineData=e.MinimapLinesRenderingData=e.Viewport=void 0;class E{constructor(i,s,g,c){this._viewportBrand=void 0,this.top=i|0,this.left=s|0,this.width=g|0,this.height=c|0}}e.Viewport=E;class y{constructor(i,s){this.tabSize=i,this.data=s}}e.MinimapLinesRenderingData=y;class m{constructor(i,s,g,c,l,a,r){this._viewLineDataBrand=void 0,this.content=i,this.continuesWithWrappedLine=s,this.minColumn=g,this.maxColumn=c,this.startVisibleColumn=l,this.tokens=a,this.inlineDecorations=r}}e.ViewLineData=m;class _{constructor(i,s,g,c,l,a,r,u,C,f){this.minColumn=i,this.maxColumn=s,this.content=g,this.continuesWithWrappedLine=c,this.isBasicASCII=_.isBasicASCII(g,a),this.containsRTL=_.containsRTL(g,this.isBasicASCII,l),this.tokens=r,this.inlineDecorations=u,this.tabSize=C,this.startVisibleColumn=f}static isBasicASCII(i,s){return s?k.isBasicASCII(i):!0}static containsRTL(i,s,g){return!s&&g?k.containsRTL(i):!1}}e.ViewLineRenderingData=_;class b{constructor(i,s,g){this.range=i,this.inlineClassName=s,this.type=g}}e.InlineDecoration=b;class p{constructor(i,s,g,c){this.startOffset=i,this.endOffset=s,this.inlineClassName=g,this.inlineClassNameAffectsLetterSpacing=c}toInlineDecoration(i){return new b(new I.Range(i,this.startOffset+1,i,this.endOffset+1),this.inlineClassName,this.inlineClassNameAffectsLetterSpacing?3:0)}}e.SingleLineInlineDecoration=p;class n{constructor(i,s){this._viewModelDecorationBrand=void 0,this.range=i,this.options=s}}e.ViewModelDecoration=n;class o{constructor(i,s,g){this.color=i,this.zIndex=s,this.data=g}static compareByRenderingProps(i,s){return i.zIndex===s.zIndex?i.colors.color?1:0:i.zIndex-s.zIndex}static equals(i,s){return i.color===s.color&&i.zIndex===s.zIndex&&d.equals(i.data,s.data)}static equalsArr(i,s){return d.equals(i,s,o.equals)}}e.OverviewRulerDecorationsGroup=o}),define(ne[601],se([1,0,40]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GlyphMarginLanesModel=void 0;const k=d.GlyphMarginLane.Right;class I{constructor(y){this.persist=0,this._requiredLanes=1,this.lanes=new Uint8Array(Math.ceil((y+1)*k/8))}reset(y){const m=Math.ceil((y+1)*k/8);this.lanes.length>>3]|=1<>>3]&1<<_%8)&&m.push(b+1),_++;return m.length?m:[d.GlyphMarginLane.Center]}countAtLine(y){let m=k*y,_=0;for(let b=0;b>>3]&1<0?this._projectionData.breakOffsets[g-1]:0,l=this._projectionData.breakOffsets[g];let a;if(this._projectionData.injectionOffsets!==null){const r=this._projectionData.injectionOffsets.map((C,f)=>new I.LineInjectedText(0,0,C+1,this._projectionData.injectionOptions[f],0));a=I.LineInjectedText.applyInjectedText(i.getLineContent(s),r).substring(c,l)}else a=i.getValueInRange({startLineNumber:s,startColumn:c+1,endLineNumber:s,endColumn:l+1});return g>0&&(a=n(this._projectionData.wrappedTextIndentLength)+a),a}getViewLineLength(i,s,g){return this._assertVisible(),this._projectionData.getLineLength(g)}getViewLineMinColumn(i,s,g){return this._assertVisible(),this._projectionData.getMinOutputOffset(g)+1}getViewLineMaxColumn(i,s,g){return this._assertVisible(),this._projectionData.getMaxOutputOffset(g)+1}getViewLineData(i,s,g){const c=new Array;return this.getViewLinesData(i,s,g,1,0,[!0],c),c[0]}getViewLinesData(i,s,g,c,l,a,r){this._assertVisible();const u=this._projectionData,C=u.injectionOffsets,f=u.injectionOptions;let h=null;if(C){h=[];let w=0,S=0;for(let L=0;L0?u.breakOffsets[L-1]:0,M=u.breakOffsets[L];for(;SM)break;if(T0?u.wrappedTextIndentLength:0,x=F+Math.max(P-T,0),W=F+Math.min(N-T,M-T);x!==W&&D.push(new E.SingleLineInlineDecoration(x,W,O.inlineClassName,O.inlineClassNameAffectsLetterSpacing))}}if(N<=M)w+=A,S++;else break}}}let v;C?v=i.tokenization.getLineTokens(s).withInserted(C.map((w,S)=>({offset:w,text:f[S].content,tokenMetadata:d.LineTokens.defaultTokenMetadata}))):v=i.tokenization.getLineTokens(s);for(let w=g;w0?c.wrappedTextIndentLength:0,a=g>0?c.breakOffsets[g-1]:0,r=c.breakOffsets[g],u=i.sliceAndInflate(a,r,l);let C=u.getLineContent();g>0&&(C=n(c.wrappedTextIndentLength)+C);const f=this._projectionData.getMinOutputOffset(g)+1,h=C.length+1,v=g+1=p.length)for(let i=1;i<=t;i++)p[i]=o(i);return p[t]}function o(t){return new Array(t+1).join(" ")}}),define(ne[603],se([1,0,11,144,132,325]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MonospaceLineBreaksComputerFactory=void 0;class y{static create(c){return new y(c.get(135),c.get(134))}constructor(c,l){this.classifier=new m(c,l)}createLineBreaksComputer(c,l,a,r,u){const C=[],f=[],h=[];return{addRequest:(v,w,S)=>{C.push(v),f.push(w),h.push(S)},finalize:()=>{const v=c.typicalFullwidthCharacterWidth/c.typicalHalfwidthCharacterWidth,w=[];for(let S=0,L=C.length;S=0&&c<256?this._asciiMap[c]:c>=12352&&c<=12543||c>=13312&&c<=19903||c>=19968&&c<=40959?3:this._map.get(c)||this._defaultValue}}let _=[],b=[];function p(g,c,l,a,r,u,C,f){if(r===-1)return null;const h=l.length;if(h<=1)return null;const v=f==="keepAll",w=c.breakOffsets,S=c.breakOffsetsVisibleColumn,L=s(l,a,r,u,C),D=r-L,T=_,M=b;let A=0,P=0,N=0,O=r;const F=w.length;let x=0;if(x>=0){let W=Math.abs(S[x]-O);for(;x+1=W)break;W=V,x++}}for(;xW&&(W=P,V=N);let q=0,H=0,z=0,U=0;if(V<=O){let Y=V,G=W===0?0:l.charCodeAt(W-1),K=W===0?0:g.get(G),R=!0;for(let J=W;JP&&i(G,K,ue,he,v)&&(q=ie,H=Y),Y+=pe,Y>O){ie>P?(z=ie,U=Y-pe):(z=J+1,U=Y),Y-H>D&&(q=0),R=!1;break}G=ue,K=he}if(R){A>0&&(T[A]=w[w.length-1],M[A]=S[w.length-1],A++);break}}if(q===0){let Y=V,G=l.charCodeAt(W),K=g.get(G),R=!1;for(let J=W-1;J>=P;J--){const ie=J+1,ue=l.charCodeAt(J);if(ue===9){R=!0;break}let he,pe;if(d.isLowSurrogate(ue)?(J--,he=0,pe=2):(he=g.get(ue),pe=d.isFullWidthCharacter(ue)?u:1),Y<=O){if(z===0&&(z=ie,U=Y),Y<=O-D)break;if(i(ue,he,G,K,v)){q=ie,H=Y;break}}Y-=pe,G=ue,K=he}if(q!==0){const J=D-(U-H);if(J<=a){const ie=l.charCodeAt(z);let ue;d.isHighSurrogate(ie)?ue=2:ue=o(ie,U,a,u),J-ue<0&&(q=0)}}if(R){x--;continue}}if(q===0&&(q=z,H=U),q<=P){const Y=l.charCodeAt(P);d.isHighSurrogate(Y)?(q=P+2,H=N+2):(q=P+1,H=N+o(Y,N,a,u))}for(P=q,T[A]=q,N=H,M[A]=H,A++,O=H+D;x<0||x=j)break;j=Y,x++}}return A===0?null:(T.length=A,M.length=A,_=c.breakOffsets,b=c.breakOffsetsVisibleColumn,c.breakOffsets=T,c.breakOffsetsVisibleColumn=M,c.wrappedTextIndentLength=L,c)}function n(g,c,l,a,r,u,C,f){const h=I.LineInjectedText.applyInjectedText(c,l);let v,w;if(l&&l.length>0?(v=l.map(H=>H.options),w=l.map(H=>H.column-1)):(v=null,w=null),r===-1)return v?new E.ModelLineProjectionData(w,v,[h.length],[],0):null;const S=h.length;if(S<=1)return v?new E.ModelLineProjectionData(w,v,[h.length],[],0):null;const L=f==="keepAll",D=s(h,a,r,u,C),T=r-D,M=[],A=[];let P=0,N=0,O=0,F=r,x=h.charCodeAt(0),W=g.get(x),V=o(x,0,a,u),q=1;d.isHighSurrogate(x)&&(V+=1,x=h.charCodeAt(1),W=g.get(x),q++);for(let H=q;HF&&((N===0||V-O>T)&&(N=z,O=V-Y),M[P]=N,A[P]=O,P++,F=O+T,N=0),x=U,W=j}return P===0&&(!l||l.length===0)?null:(M[P]=S,A[P]=V,new E.ModelLineProjectionData(w,v,M,A,D))}function o(g,c,l,a){return g===9?l-c%l:d.isFullWidthCharacter(g)||g<32?a:1}function t(g,c){return c-g%c}function i(g,c,l,a,r){return l!==32&&(c===2&&a!==2||c!==1&&a===1||!r&&c===3&&a!==2||!r&&a===3&&c!==1)}function s(g,c,l,a,r){let u=0;if(r!==0){const C=d.firstNonWhitespaceIndex(g);if(C!==-1){for(let h=0;hl&&(u=0)}}return u}}),define(ne[332],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OverviewZoneManager=e.OverviewRulerZone=e.ColorZone=void 0;class d{constructor(y,m,_){this._colorZoneBrand=void 0,this.from=y|0,this.to=m|0,this.colorId=_|0}static compare(y,m){return y.colorId===m.colorId?y.from===m.from?y.to-m.to:y.from-m.from:y.colorId-m.colorId}}e.ColorZone=d;class k{constructor(y,m,_,b){this._overviewRulerZoneBrand=void 0,this.startLineNumber=y,this.endLineNumber=m,this.heightInLines=_,this.color=b,this._colorZone=null}static compare(y,m){return y.color===m.color?y.startLineNumber===m.startLineNumber?y.heightInLines===m.heightInLines?y.endLineNumber-m.endLineNumber:y.heightInLines-m.heightInLines:y.startLineNumber-m.startLineNumber:y.color_&&(r=_-u);const C=s.color;let f=this._color2Id[C];f||(f=++this._lastAssignedId,this._color2Id[C]=f,this._id2Color[f]=C);const h=new d(r-u,r+u,f);s.setColorZone(h),o.push(h)}return this._colorZonesInvalid=!1,o.sort(d.compare),o}}e.OverviewZoneManager=I}),define(ne[604],se([1,0,39,332,170]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OverviewRuler=void 0;class E extends I.ViewEventHandler{constructor(m,_){super(),this._context=m;const b=this._context.configuration.options;this._domNode=(0,d.createFastDomNode)(document.createElement("canvas")),this._domNode.setClassName(_),this._domNode.setPosition("absolute"),this._domNode.setLayerHinting(!0),this._domNode.setContain("strict"),this._zoneManager=new k.OverviewZoneManager(p=>this._context.viewLayout.getVerticalOffsetForLineNumber(p)),this._zoneManager.setDOMWidth(0),this._zoneManager.setDOMHeight(0),this._zoneManager.setOuterHeight(this._context.viewLayout.getScrollHeight()),this._zoneManager.setLineHeight(b.get(67)),this._zoneManager.setPixelRatio(b.get(144)),this._context.addEventHandler(this)}dispose(){this._context.removeEventHandler(this),super.dispose()}onConfigurationChanged(m){const _=this._context.configuration.options;return m.hasChanged(67)&&(this._zoneManager.setLineHeight(_.get(67)),this._render()),m.hasChanged(144)&&(this._zoneManager.setPixelRatio(_.get(144)),this._domNode.setWidth(this._zoneManager.getDOMWidth()),this._domNode.setHeight(this._zoneManager.getDOMHeight()),this._domNode.domNode.width=this._zoneManager.getCanvasWidth(),this._domNode.domNode.height=this._zoneManager.getCanvasHeight(),this._render()),!0}onFlushed(m){return this._render(),!0}onScrollChanged(m){return m.scrollHeightChanged&&(this._zoneManager.setOuterHeight(m.scrollHeight),this._render()),!0}onZonesChanged(m){return this._render(),!0}getDomNode(){return this._domNode.domNode}setLayout(m){this._domNode.setTop(m.top),this._domNode.setRight(m.right);let _=!1;_=this._zoneManager.setDOMWidth(m.width)||_,_=this._zoneManager.setDOMHeight(m.height)||_,_&&(this._domNode.setWidth(this._zoneManager.getDOMWidth()),this._domNode.setHeight(this._zoneManager.getDOMHeight()),this._domNode.domNode.width=this._zoneManager.getCanvasWidth(),this._domNode.domNode.height=this._zoneManager.getCanvasHeight(),this._render())}setZones(m){this._zoneManager.setZones(m),this._render()}_render(){if(this._zoneManager.getOuterHeight()===0)return!1;const m=this._zoneManager.getCanvasWidth(),_=this._zoneManager.getCanvasHeight(),b=this._zoneManager.resolveColorZones(),p=this._zoneManager.getId2Color(),n=this._domNode.domNode.getContext("2d");return n.clearRect(0,0,m,_),b.length>0&&this._renderOneLane(n,b,p,m),!0}_renderOneLane(m,_,b,p){let n=0,o=0,t=0;for(const i of _){const s=i.colorId,g=i.from,c=i.to;s!==n?(m.fillRect(0,o,p,t-o),n=s,m.fillStyle=b[n],o=g,t=c):t>=g?t=Math.max(t,c):(m.fillRect(0,o,p,t-o),o=g,t=c)}m.fillRect(0,o,p,t-o)}}e.OverviewRuler=E}),define(ne[605],se([1,0,562]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewContext=void 0;class k{constructor(E,y,m){this.configuration=E,this.theme=new d.EditorTheme(y),this.viewModel=m,this.viewLayout=m.viewLayout}addEventHandler(E){this.viewModel.addViewEventHandler(E)}removeEventHandler(E){this.viewModel.removeViewEventHandler(E)}}e.ViewContext=k}),define(ne[244],se([1,0,6,2]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ModelTokensChangedEvent=e.ModelOptionsChangedEvent=e.ModelContentChangedEvent=e.ModelLanguageConfigurationChangedEvent=e.ModelLanguageChangedEvent=e.ModelDecorationsChangedEvent=e.ReadOnlyEditAttemptEvent=e.CursorStateChangedEvent=e.HiddenAreasChangedEvent=e.ViewZonesChangedEvent=e.ScrollChangedEvent=e.FocusChangedEvent=e.ContentSizeChangedEvent=e.ViewModelEventsCollector=e.ViewModelEventDispatcher=void 0;class I extends k.Disposable{constructor(){super(),this._onEvent=this._register(new d.Emitter),this.onEvent=this._onEvent.event,this._eventHandlers=[],this._viewEventQueue=null,this._isConsumingViewEventQueue=!1,this._collector=null,this._collectorCnt=0,this._outgoingEvents=[]}emitOutgoingEvent(r){this._addOutgoingEvent(r),this._emitOutgoingEvents()}_addOutgoingEvent(r){for(let u=0,C=this._outgoingEvents.length;u0;){if(this._collector||this._isConsumingViewEventQueue)return;const r=this._outgoingEvents.shift();r.isNoOp()||this._onEvent.fire(r)}}addViewEventHandler(r){for(let u=0,C=this._eventHandlers.length;u0&&this._emitMany(u)}this._emitOutgoingEvents()}emitSingleViewEvent(r){try{this.beginEmitViewEvents().emitViewEvent(r)}finally{this.endEmitViewEvents()}}_emitMany(r){this._viewEventQueue?this._viewEventQueue=this._viewEventQueue.concat(r):this._viewEventQueue=r,this._isConsumingViewEventQueue||this._consumeViewEventQueue()}_consumeViewEventQueue(){try{this._isConsumingViewEventQueue=!0,this._doConsumeQueue()}finally{this._isConsumingViewEventQueue=!1}}_doConsumeQueue(){for(;this._viewEventQueue;){const r=this._viewEventQueue;this._viewEventQueue=null;const u=this._eventHandlers.slice(0);for(const C of u)C.handleEvents(r)}}}e.ViewModelEventDispatcher=I;class E{constructor(){this.viewEvents=[],this.outgoingEvents=[]}emitViewEvent(r){this.viewEvents.push(r)}emitOutgoingEvent(r){this.outgoingEvents.push(r)}}e.ViewModelEventsCollector=E;class y{constructor(r,u,C,f){this.kind=0,this._oldContentWidth=r,this._oldContentHeight=u,this.contentWidth=C,this.contentHeight=f,this.contentWidthChanged=this._oldContentWidth!==this.contentWidth,this.contentHeightChanged=this._oldContentHeight!==this.contentHeight}isNoOp(){return!this.contentWidthChanged&&!this.contentHeightChanged}attemptToMerge(r){return r.kind!==this.kind?null:new y(this._oldContentWidth,this._oldContentHeight,r.contentWidth,r.contentHeight)}}e.ContentSizeChangedEvent=y;class m{constructor(r,u){this.kind=1,this.oldHasFocus=r,this.hasFocus=u}isNoOp(){return this.oldHasFocus===this.hasFocus}attemptToMerge(r){return r.kind!==this.kind?null:new m(this.oldHasFocus,r.hasFocus)}}e.FocusChangedEvent=m;class _{constructor(r,u,C,f,h,v,w,S){this.kind=2,this._oldScrollWidth=r,this._oldScrollLeft=u,this._oldScrollHeight=C,this._oldScrollTop=f,this.scrollWidth=h,this.scrollLeft=v,this.scrollHeight=w,this.scrollTop=S,this.scrollWidthChanged=this._oldScrollWidth!==this.scrollWidth,this.scrollLeftChanged=this._oldScrollLeft!==this.scrollLeft,this.scrollHeightChanged=this._oldScrollHeight!==this.scrollHeight,this.scrollTopChanged=this._oldScrollTop!==this.scrollTop}isNoOp(){return!this.scrollWidthChanged&&!this.scrollLeftChanged&&!this.scrollHeightChanged&&!this.scrollTopChanged}attemptToMerge(r){return r.kind!==this.kind?null:new _(this._oldScrollWidth,this._oldScrollLeft,this._oldScrollHeight,this._oldScrollTop,r.scrollWidth,r.scrollLeft,r.scrollHeight,r.scrollTop)}}e.ScrollChangedEvent=_;class b{constructor(){this.kind=3}isNoOp(){return!1}attemptToMerge(r){return r.kind!==this.kind?null:this}}e.ViewZonesChangedEvent=b;class p{constructor(){this.kind=4}isNoOp(){return!1}attemptToMerge(r){return r.kind!==this.kind?null:this}}e.HiddenAreasChangedEvent=p;class n{constructor(r,u,C,f,h,v,w){this.kind=6,this.oldSelections=r,this.selections=u,this.oldModelVersionId=C,this.modelVersionId=f,this.source=h,this.reason=v,this.reachedMaxCursorCount=w}static _selectionsAreEqual(r,u){if(!r&&!u)return!0;if(!r||!u)return!1;const C=r.length,f=u.length;if(C!==f)return!1;for(let h=0;h=i?0:g.horizontalScrollbarSize}_getContentHeight(t,i,s){const g=this._configuration.options;let c=this._linesLayout.getLinesTotalHeight();return g.get(106)?c+=Math.max(0,i-g.get(67)-g.get(84).bottom):g.get(104).ignoreHorizontalScrollbarInContentHeight||(c+=this._getHorizontalScrollbarHeight(t,s)),c}_updateHeight(){const t=this._scrollable.getScrollDimensions(),i=t.width,s=t.height,g=t.contentWidth;this._scrollable.setScrollDimensions(new b(i,t.contentWidth,s,this._getContentHeight(i,s,g)))}getCurrentViewport(){const t=this._scrollable.getScrollDimensions(),i=this._scrollable.getCurrentScrollPosition();return new y.Viewport(i.scrollTop,i.scrollLeft,t.width,t.height)}getFutureViewport(){const t=this._scrollable.getScrollDimensions(),i=this._scrollable.getFutureScrollPosition();return new y.Viewport(i.scrollTop,i.scrollLeft,t.width,t.height)}_computeContentWidth(){const t=this._configuration.options,i=this._maxLineWidth,s=t.get(147),g=t.get(50),c=t.get(146);if(s.isViewportWrapping){const l=t.get(73);return i>c.contentWidth+g.typicalHalfwidthCharacterWidth&&l.enabled&&l.side==="right"?i+c.verticalScrollbarWidth:i}else{const l=t.get(105)*g.typicalHalfwidthCharacterWidth,a=this._linesLayout.getWhitespaceMinWidth();return Math.max(i+l+c.verticalScrollbarWidth,a,this._overlayWidgetsMinWidth)}}setMaxLineWidth(t){this._maxLineWidth=t,this._updateContentWidth()}setOverlayWidgetsMinWidth(t){this._overlayWidgetsMinWidth=t,this._updateContentWidth()}_updateContentWidth(){const t=this._scrollable.getScrollDimensions();this._scrollable.setScrollDimensions(new b(t.width,this._computeContentWidth(),t.height,t.contentHeight)),this._updateHeight()}saveState(){const t=this._scrollable.getFutureScrollPosition(),i=t.scrollTop,s=this._linesLayout.getLineNumberAtOrAfterVerticalOffset(i),g=this._linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(s);return{scrollTop:i,scrollTopWithoutViewZones:i-g,scrollLeft:t.scrollLeft}}changeWhitespace(t){const i=this._linesLayout.changeWhitespace(t);return i&&this.onHeightMaybeChanged(),i}getVerticalOffsetForLineNumber(t,i=!1){return this._linesLayout.getVerticalOffsetForLineNumber(t,i)}getVerticalOffsetAfterLineNumber(t,i=!1){return this._linesLayout.getVerticalOffsetAfterLineNumber(t,i)}isAfterLines(t){return this._linesLayout.isAfterLines(t)}isInTopPadding(t){return this._linesLayout.isInTopPadding(t)}isInBottomPadding(t){return this._linesLayout.isInBottomPadding(t)}getLineNumberAtVerticalOffset(t){return this._linesLayout.getLineNumberAtOrAfterVerticalOffset(t)}getWhitespaceAtVerticalOffset(t){return this._linesLayout.getWhitespaceAtVerticalOffset(t)}getLinesViewportData(){const t=this.getCurrentViewport();return this._linesLayout.getLinesViewportData(t.top,t.top+t.height)}getLinesViewportDataAtScrollTop(t){const i=this._scrollable.getScrollDimensions();return t+i.height>i.scrollHeight&&(t=i.scrollHeight-i.height),t<0&&(t=0),this._linesLayout.getLinesViewportData(t,t+i.height)}getWhitespaceViewportData(){const t=this.getCurrentViewport();return this._linesLayout.getWhitespaceViewportData(t.top,t.top+t.height)}getWhitespaces(){return this._linesLayout.getWhitespaces()}getContentWidth(){return this._scrollable.getScrollDimensions().contentWidth}getScrollWidth(){return this._scrollable.getScrollDimensions().scrollWidth}getContentHeight(){return this._scrollable.getScrollDimensions().contentHeight}getScrollHeight(){return this._scrollable.getScrollDimensions().scrollHeight}getCurrentScrollLeft(){return this._scrollable.getCurrentScrollPosition().scrollLeft}getCurrentScrollTop(){return this._scrollable.getCurrentScrollPosition().scrollTop}validateScrollPosition(t){return this._scrollable.validateScrollPosition(t)}setScrollPosition(t,i){i===1?this._scrollable.setScrollPositionNow(t):this._scrollable.setScrollPositionSmooth(t)}hasPendingScrollAnimation(){return this._scrollable.hasPendingScrollAnimation()}deltaScrollNow(t,i){const s=this._scrollable.getCurrentScrollPosition();this._scrollable.setScrollPositionNow({scrollLeft:s.scrollLeft+t,scrollTop:s.scrollTop+i})}}e.ViewLayout=n}),define(ne[607],se([1,0,4,23]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MoveCaretCommand=void 0;class I{constructor(y,m){this._selection=y,this._isMovingLeft=m}getEditOperations(y,m){if(this._selection.startLineNumber!==this._selection.endLineNumber||this._selection.isEmpty())return;const _=this._selection.startLineNumber,b=this._selection.startColumn,p=this._selection.endColumn;if(!(this._isMovingLeft&&b===1)&&!(!this._isMovingLeft&&p===y.getLineMaxColumn(_)))if(this._isMovingLeft){const n=new d.Range(_,b-1,_,b),o=y.getValueInRange(n);m.addEditOperation(n,null),m.addEditOperation(new d.Range(_,p,_,p),o)}else{const n=new d.Range(_,p,_,p+1),o=y.getValueInRange(n);m.addEditOperation(n,null),m.addEditOperation(new d.Range(_,b,_,b),o)}}computeCursorState(y,m){return this._isMovingLeft?new k.Selection(this._selection.startLineNumber,this._selection.startColumn-1,this._selection.endLineNumber,this._selection.endColumn-1):new k.Selection(this._selection.startLineNumber,this._selection.startColumn+1,this._selection.endLineNumber,this._selection.endColumn+1)}}e.MoveCaretCommand=I}),define(ne[134],se([1,0,8,91]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CodeActionItem=e.CodeActionCommandArgs=e.CodeActionTriggerSource=e.CodeActionKind=void 0,e.mayIncludeActionsOfKind=E,e.filtersAction=y,e.CodeActionKind=new class{constructor(){this.QuickFix=new k.HierarchicalKind("quickfix"),this.Refactor=new k.HierarchicalKind("refactor"),this.RefactorExtract=this.Refactor.append("extract"),this.RefactorInline=this.Refactor.append("inline"),this.RefactorMove=this.Refactor.append("move"),this.RefactorRewrite=this.Refactor.append("rewrite"),this.Notebook=new k.HierarchicalKind("notebook"),this.Source=new k.HierarchicalKind("source"),this.SourceOrganizeImports=this.Source.append("organizeImports"),this.SourceFixAll=this.Source.append("fixAll"),this.SurroundWith=this.Refactor.append("surround")}};var I;(function(p){p.Refactor="refactor",p.RefactorPreview="refactor preview",p.Lightbulb="lightbulb",p.Default="other (default)",p.SourceAction="source action",p.QuickFix="quick fix action",p.FixAll="fix all",p.OrganizeImports="organize imports",p.AutoFix="auto fix",p.QuickFixHover="quick fix hover window",p.OnSave="save participants",p.ProblemsView="problems view"})(I||(e.CodeActionTriggerSource=I={}));function E(p,n){return!(p.include&&!p.include.intersects(n)||p.excludes&&p.excludes.some(o=>m(n,o,p.include))||!p.includeSourceActions&&e.CodeActionKind.Source.contains(n))}function y(p,n){const o=n.kind?new k.HierarchicalKind(n.kind):void 0;return!(p.include&&(!o||!p.include.contains(o))||p.excludes&&o&&p.excludes.some(t=>m(o,t,p.include))||!p.includeSourceActions&&o&&e.CodeActionKind.Source.contains(o)||p.onlyIncludePreferredActions&&!n.isPreferred)}function m(p,n,o){return!(!n.contains(p)||o&&n.contains(o))}class _{static fromUser(n,o){return!n||typeof n!="object"?new _(o.kind,o.apply,!1):new _(_.getKindFromUser(n,o.kind),_.getApplyFromUser(n,o.apply),_.getPreferredUser(n))}static getApplyFromUser(n,o){switch(typeof n.apply=="string"?n.apply.toLowerCase():""){case"first":return"first";case"never":return"never";case"ifsingle":return"ifSingle";default:return o}}static getKindFromUser(n,o){return typeof n.kind=="string"?new k.HierarchicalKind(n.kind):o}static getPreferredUser(n){return typeof n.preferred=="boolean"?n.preferred:!1}constructor(n,o,t){this.kind=n,this.apply=o,this.preferred=t}}e.CodeActionCommandArgs=_;class b{constructor(n,o,t){this.action=n,this.provider=o,this.highlightRange=t}async resolve(n){if(this.provider?.resolveCodeAction&&!this.action.edit){let o;try{o=await this.provider.resolveCodeAction(this.action,n)}catch(t){(0,d.onUnexpectedExternalError)(t)}o&&(this.action.edit=o.edit)}return this}}e.CodeActionItem=b}),define(ne[608],se([1,0,6]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ColorPickerModel=void 0;class k{get color(){return this._color}set color(E){this._color.equals(E)||(this._color=E,this._onDidChangeColor.fire(E))}get presentation(){return this.colorPresentations[this.presentationIndex]}get colorPresentations(){return this._colorPresentations}set colorPresentations(E){this._colorPresentations=E,this.presentationIndex>E.length-1&&(this.presentationIndex=0),this._onDidChangePresentation.fire(this.presentation)}constructor(E,y,m){this.presentationIndex=m,this._onColorFlushed=new d.Emitter,this.onColorFlushed=this._onColorFlushed.event,this._onDidChangeColor=new d.Emitter,this.onDidChangeColor=this._onDidChangeColor.event,this._onDidChangePresentation=new d.Emitter,this.onDidChangePresentation=this._onDidChangePresentation.event,this.originalColor=E,this._color=E,this._colorPresentations=y}selectNextColorPresentation(){this.presentationIndex=(this.presentationIndex+1)%this.colorPresentations.length,this.flushColor(),this._onDidChangePresentation.fire(this.presentation)}guessColorPresentation(E,y){let m=-1;for(let _=0;_o)return!1;for(let t=0;t=65&&i<=90&&i+32===s)&&!(s>=65&&s<=90&&s+32===i))return!1}return!0}_createOperationsForBlockComment(_,b,p,n,o,t){const i=_.startLineNumber,s=_.startColumn,g=_.endLineNumber,c=_.endColumn,l=o.getLineContent(i),a=o.getLineContent(g);let r=l.lastIndexOf(b,s-1+b.length),u=a.indexOf(p,c-1-p.length);if(r!==-1&&u!==-1)if(i===g)l.substring(r+b.length,u).indexOf(p)>=0&&(r=-1,u=-1);else{const f=l.substring(r+b.length),h=a.substring(0,u);(f.indexOf(p)>=0||h.indexOf(p)>=0)&&(r=-1,u=-1)}let C;r!==-1&&u!==-1?(n&&r+b.length0&&a.charCodeAt(u-1)===32&&(p=" "+p,u-=1),C=y._createRemoveBlockCommentOperations(new I.Range(i,r+b.length+1,g,u+1),b,p)):(C=y._createAddBlockCommentOperations(_,b,p,this._insertSpace),this._usedEndToken=C.length===1?p:null);for(const f of C)t.addTrackedEditOperation(f.range,f.text)}static _createRemoveBlockCommentOperations(_,b,p){const n=[];return I.Range.isEmpty(_)?n.push(d.EditOperation.delete(new I.Range(_.startLineNumber,_.startColumn-b.length,_.endLineNumber,_.endColumn+p.length))):(n.push(d.EditOperation.delete(new I.Range(_.startLineNumber,_.startColumn-b.length,_.startLineNumber,_.startColumn))),n.push(d.EditOperation.delete(new I.Range(_.endLineNumber,_.endColumn,_.endLineNumber,_.endColumn+p.length)))),n}static _createAddBlockCommentOperations(_,b,p,n){const o=[];return I.Range.isEmpty(_)?o.push(d.EditOperation.replace(new I.Range(_.startLineNumber,_.startColumn,_.endLineNumber,_.endColumn),b+" "+p)):(o.push(d.EditOperation.insert(new k.Position(_.startLineNumber,_.startColumn),b+(n?" ":""))),o.push(d.EditOperation.insert(new k.Position(_.endLineNumber,_.endColumn),(n?" ":"")+p))),o}getEditOperations(_,b){const p=this._selection.startLineNumber,n=this._selection.startColumn;_.tokenization.tokenizeIfCheap(p);const o=_.getLanguageIdAtPosition(p,n),t=this.languageConfigurationService.getLanguageConfiguration(o).comments;!t||!t.blockCommentStartToken||!t.blockCommentEndToken||this._createOperationsForBlockComment(this._selection,t.blockCommentStartToken,t.blockCommentEndToken,this._insertSpace,_,b)}computeCursorState(_,b){const p=b.getInverseEditOperations();if(p.length===2){const n=p[0],o=p[1];return new E.Selection(n.range.endLineNumber,n.range.endColumn,o.range.startLineNumber,o.range.startColumn)}else{const n=p[0].range,o=this._usedEndToken?-this._usedEndToken.length-1:0;return new E.Selection(n.endLineNumber,n.endColumn+o,n.endLineNumber,n.endColumn+o)}}}e.BlockCommentCommand=y}),define(ne[609],se([1,0,11,75,9,4,23,333]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LineCommentCommand=void 0;class _{constructor(p,n,o,t,i,s,g){this.languageConfigurationService=p,this._selection=n,this._indentSize=o,this._type=t,this._insertSpace=i,this._selectionId=null,this._deltaColumn=0,this._moveEndPositionDown=!1,this._ignoreEmptyLines=s,this._ignoreFirstLine=g||!1}static _gatherPreflightCommentStrings(p,n,o,t){p.tokenization.tokenizeIfCheap(n);const i=p.getLanguageIdAtPosition(n,1),s=t.getLanguageConfiguration(i).comments,g=s?s.lineCommentToken:null;if(!g)return null;const c=[];for(let l=0,a=o-n+1;li?n[c].commentStrOffset=s-1:n[c].commentStrOffset=s}}}e.LineCommentCommand=_}),define(ne[610],se([1,0,4,23]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DragAndDropCommand=void 0;class I{constructor(y,m,_){this.selection=y,this.targetPosition=m,this.copy=_,this.targetSelection=null}getEditOperations(y,m){const _=y.getValueInRange(this.selection);if(this.copy||m.addEditOperation(this.selection,null),m.addEditOperation(new d.Range(this.targetPosition.lineNumber,this.targetPosition.column,this.targetPosition.lineNumber,this.targetPosition.column),_),this.selection.containsPosition(this.targetPosition)&&!(this.copy&&(this.selection.getEndPosition().equals(this.targetPosition)||this.selection.getStartPosition().equals(this.targetPosition)))){this.targetSelection=this.selection;return}if(this.copy){this.targetSelection=new k.Selection(this.targetPosition.lineNumber,this.targetPosition.column,this.selection.endLineNumber-this.selection.startLineNumber+this.targetPosition.lineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column+this.selection.endColumn-this.selection.startColumn:this.selection.endColumn);return}if(this.targetPosition.lineNumber>this.selection.endLineNumber){this.targetSelection=new k.Selection(this.targetPosition.lineNumber-this.selection.endLineNumber+this.selection.startLineNumber,this.targetPosition.column,this.targetPosition.lineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column+this.selection.endColumn-this.selection.startColumn:this.selection.endColumn);return}if(this.targetPosition.lineNumber0){const m=[];for(let p=0;pd.Range.compareRangesUsingStarts(p.range,n.range));const _=[];let b=m[0];for(let p=1;p0){const c=[],l=s.caseOps.length;let a=0;for(let r=0,u=g.length;r=l){c.push(g.slice(r));break}switch(s.caseOps[a]){case"U":c.push(g[r].toUpperCase());break;case"u":c.push(g[r].toUpperCase()),a++;break;case"L":c.push(g[r].toLowerCase());break;case"l":c.push(g[r].toLowerCase()),a++;break;default:c.push(g[r])}}g=c.join("")}o+=g}return o}static _substitute(p,n){if(n===null)return"";if(p===0)return n[0];let o="";for(;p>0;){if(p=t)break;const s=b.charCodeAt(o);switch(s){case 92:n.emitUnchanged(o-1),n.emitStatic("\\",o+1);break;case 110:n.emitUnchanged(o-1),n.emitStatic(` `,o+1);break;case 116:n.emitUnchanged(o-1),n.emitStatic(" ",o+1);break;case 117:case 85:case 108:case 76:n.emitUnchanged(o-1),n.emitStatic("",o+1),p.push(String.fromCharCode(s));break}continue}if(i===36){if(o++,o>=t)break;const s=b.charCodeAt(o);if(s===36){n.emitUnchanged(o-1),n.emitStatic("$",o+1);continue}if(s===48||s===38){n.emitUnchanged(o-1),n.emitMatchIndex(0,o+1,p),p.length=0;continue}if(49<=s&&s<=57){let g=s-48;if(o+1e.MAX_FOLDING_REGIONS)throw new Error("invalid startIndexes or endIndexes size");this._startIndexes=m,this._endIndexes=_,this._collapseStates=new k(m.length),this._userDefinedStates=new k(m.length),this._recoveredStates=new k(m.length),this._types=b,this._parentsComputed=!1}ensureParentIndices(){if(!this._parentsComputed){this._parentsComputed=!0;const m=[],_=(b,p)=>{const n=m[m.length-1];return this.getStartLineNumber(n)<=b&&this.getEndLineNumber(n)>=p};for(let b=0,p=this._startIndexes.length;be.MAX_LINE_NUMBER||o>e.MAX_LINE_NUMBER)throw new Error("startLineNumber or endLineNumber must not exceed "+e.MAX_LINE_NUMBER);for(;m.length>0&&!_(n,o);)m.pop();const t=m.length>0?m[m.length-1]:-1;m.push(b),this._startIndexes[b]=n+((t&255)<<24),this._endIndexes[b]=o+((t&65280)<<16)}}}get length(){return this._startIndexes.length}getStartLineNumber(m){return this._startIndexes[m]&e.MAX_LINE_NUMBER}getEndLineNumber(m){return this._endIndexes[m]&e.MAX_LINE_NUMBER}getType(m){return this._types?this._types[m]:void 0}hasTypes(){return!!this._types}isCollapsed(m){return this._collapseStates.get(m)}setCollapsed(m,_){this._collapseStates.set(m,_)}isUserDefined(m){return this._userDefinedStates.get(m)}setUserDefined(m,_){return this._userDefinedStates.set(m,_)}isRecovered(m){return this._recoveredStates.get(m)}setRecovered(m,_){return this._recoveredStates.set(m,_)}getSource(m){return this.isUserDefined(m)?1:this.isRecovered(m)?2:0}setSource(m,_){_===1?(this.setUserDefined(m,!0),this.setRecovered(m,!1)):_===2?(this.setUserDefined(m,!1),this.setRecovered(m,!0)):(this.setUserDefined(m,!1),this.setRecovered(m,!1))}setCollapsedAllOfType(m,_){let b=!1;if(this._types)for(let p=0;p>>24)+((this._endIndexes[m]&d)>>>16);return _===e.MAX_FOLDING_REGIONS?-1:_}contains(m,_){return this.getStartLineNumber(m)<=_&&this.getEndLineNumber(m)>=_}findIndex(m){let _=0,b=this._startIndexes.length;if(b===0)return-1;for(;_=0){if(this.getEndLineNumber(_)>=m)return _;for(_=this.getParentIndex(_);_!==-1;){if(this.contains(_,m))return _;_=this.getParentIndex(_)}}return-1}toString(){const m=[];for(let _=0;_Array.isArray(C)?h=>hh=c.startLineNumber))g&&g.startLineNumber===c.startLineNumber?(c.source===1?C=c:(C=g,C.isCollapsed=c.isCollapsed&&(g.endLineNumber===c.endLineNumber||!p?.startsInside(g.startLineNumber+1,g.endLineNumber+1)),C.source=0),g=o(++i)):(C=c,c.isCollapsed&&c.source===0&&(C.source=2)),c=t(++s);else{let f=s,h=c;for(;;){if(!h||h.startLineNumber>g.endLineNumber){C=g;break}if(h.source===1&&h.endLineNumber>g.endLineNumber)break;h=t(++f)}g=o(++i)}if(C){for(;a&&a.endLineNumberC.startLineNumber&&C.startLineNumber>r&&C.endLineNumber<=b&&(!a||a.endLineNumber>=C.endLineNumber)&&(u.push(C),r=C.startLineNumber,a&&l.push(a),a=C)}}return u}}e.FoldingRegions=I;class E{constructor(m,_){this.ranges=m,this.index=_}get startLineNumber(){return this.ranges.getStartLineNumber(this.index)}get endLineNumber(){return this.ranges.getEndLineNumber(this.index)}get regionIndex(){return this.index}get parentIndex(){return this.ranges.getParentIndex(this.index)}get isCollapsed(){return this.ranges.isCollapsed(this.index)}containedBy(m){return m.startLineNumber<=this.startLineNumber&&m.endLineNumber>=this.endLineNumber}containsLine(m){return this.startLineNumber<=m&&m<=this.endLineNumber}}e.FoldingRegion=E}),define(ne[334],se([1,0,6,203,129]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FoldingModel=void 0,e.toggleCollapseState=y,e.setCollapseStateLevelsDown=m,e.setCollapseStateLevelsUp=_,e.setCollapseStateUp=b,e.setCollapseStateAtLevel=p,e.setCollapseStateForRest=n,e.setCollapseStateForMatchingLines=o,e.setCollapseStateForType=t,e.getParentFoldLine=i,e.getPreviousFoldLine=s,e.getNextFoldLine=g;class E{get regions(){return this._regions}get textModel(){return this._textModel}constructor(l,a){this._updateEventEmitter=new d.Emitter,this.onDidChange=this._updateEventEmitter.event,this._textModel=l,this._decorationProvider=a,this._regions=new k.FoldingRegions(new Uint32Array(0),new Uint32Array(0)),this._editorDecorationIds=[]}toggleCollapseState(l){if(!l.length)return;l=l.sort((r,u)=>r.regionIndex-u.regionIndex);const a={};this._decorationProvider.changeDecorations(r=>{let u=0,C=-1,f=-1;const h=v=>{for(;uf&&(f=w),u++}};for(const v of l){const w=v.regionIndex,S=this._editorDecorationIds[w];if(S&&!a[S]){a[S]=!0,h(w);const L=!this._regions.isCollapsed(w);this._regions.setCollapsed(w,L),C=Math.max(C,this._regions.getEndLineNumber(w))}}h(this._regions.length)}),this._updateEventEmitter.fire({model:this,collapseStateChanged:l})}removeManualRanges(l){const a=new Array,r=u=>{for(const C of l)if(!(C.startLineNumber>u.endLineNumber||u.startLineNumber>C.endLineNumber))return!0;return!1};for(let u=0;ur&&(r=h)}this._decorationProvider.changeDecorations(u=>this._editorDecorationIds=u.deltaDecorations(this._editorDecorationIds,a)),this._regions=l,this._updateEventEmitter.fire({model:this})}_currentFoldedOrManualRanges(l){const a=[];for(let r=0,u=this._regions.length;r=f.endLineNumber||f.startLineNumber<1||f.endLineNumber>r)continue;const h=this._getLinesChecksum(f.startLineNumber+1,f.endLineNumber);a.push({startLineNumber:f.startLineNumber,endLineNumber:f.endLineNumber,isCollapsed:f.isCollapsed,source:f.source,checksum:h})}return a.length>0?a:void 0}applyMemento(l){if(!Array.isArray(l))return;const a=[],r=this._textModel.getLineCount();for(const C of l){if(C.startLineNumber>=C.endLineNumber||C.startLineNumber<1||C.endLineNumber>r)continue;const f=this._getLinesChecksum(C.startLineNumber+1,C.endLineNumber);(!C.checksum||f===C.checksum)&&a.push({startLineNumber:C.startLineNumber,endLineNumber:C.endLineNumber,type:void 0,isCollapsed:C.isCollapsed??!0,source:C.source??0})}const u=k.FoldingRegions.sanitizeAndMerge(this._regions,a,r);this.updatePost(k.FoldingRegions.fromFoldRanges(u))}_getLinesChecksum(l,a){return(0,I.hash)(this._textModel.getLineContent(l)+this._textModel.getLineContent(a))%1e6}dispose(){this._decorationProvider.removeDecorations(this._editorDecorationIds)}getAllRegionsAtLine(l,a){const r=[];if(this._regions){let u=this._regions.findRange(l),C=1;for(;u>=0;){const f=this._regions.toRegion(u);(!a||a(f,C))&&r.push(f),C++,u=f.parentIndex}}return r}getRegionAtLine(l){if(this._regions){const a=this._regions.findRange(l);if(a>=0)return this._regions.toRegion(a)}return null}getRegionsInside(l,a){const r=[],u=l?l.regionIndex+1:0,C=l?l.endLineNumber:Number.MAX_VALUE;if(a&&a.length===2){const f=[];for(let h=u,v=this._regions.length;h0&&!w.containedBy(f[f.length-1]);)f.pop();f.push(w),a(w,f.length)&&r.push(w)}else break}}else for(let f=u,h=this._regions.length;f1){const h=c.getRegionsInside(C,(v,w)=>v.isCollapsed!==f&&w0)for(const C of r){const f=c.getRegionAtLine(C);if(f&&(f.isCollapsed!==l&&u.push(f),a>1)){const h=c.getRegionsInside(f,(v,w)=>v.isCollapsed!==l&&wf.isCollapsed!==l&&hh.isCollapsed!==l&&v<=a);u.push(...f)}c.toggleCollapseState(u)}function b(c,l,a){const r=[];for(const u of a){const C=c.getAllRegionsAtLine(u,f=>f.isCollapsed!==l);C.length>0&&r.push(C[0])}c.toggleCollapseState(r)}function p(c,l,a,r){const u=(f,h)=>h===l&&f.isCollapsed!==a&&!r.some(v=>f.containsLine(v)),C=c.getRegionsInside(null,u);c.toggleCollapseState(C)}function n(c,l,a){const r=[];for(const f of a){const h=c.getAllRegionsAtLine(f,void 0);h.length>0&&r.push(h[0])}const u=f=>r.every(h=>!h.containedBy(f)&&!f.containedBy(h))&&f.isCollapsed!==l,C=c.getRegionsInside(null,u);c.toggleCollapseState(C)}function o(c,l,a){const r=c.textModel,u=c.regions,C=[];for(let f=u.length-1;f>=0;f--)if(a!==u.isCollapsed(f)){const h=u.getStartLineNumber(f);l.test(r.getLineContent(h))&&C.push(u.toRegion(f))}c.toggleCollapseState(C)}function t(c,l,a){const r=c.regions,u=[];for(let C=r.length-1;C>=0;C--)a!==r.isCollapsed(C)&&l===r.getType(C)&&u.push(r.toRegion(C));c.toggleCollapseState(u)}function i(c,l){let a=null;const r=l.getRegionAtLine(c);if(r!==null&&(a=r.startLineNumber,c===a)){const u=r.parentIndex;u!==-1?a=l.regions.getStartLineNumber(u):a=null}return a}function s(c,l){let a=l.getRegionAtLine(c);if(a!==null&&a.startLineNumber===c){if(c!==a.startLineNumber)return a.startLineNumber;{const r=a.parentIndex;let u=0;for(r!==-1&&(u=l.regions.getStartLineNumber(a.parentIndex));a!==null;)if(a.regionIndex>0){if(a=l.regions.toRegion(a.regionIndex-1),a.startLineNumber<=u)return null;if(a.parentIndex===r)return a.startLineNumber}else return null}}else if(l.regions.length>0)for(a=l.regions.toRegion(l.regions.length-1);a!==null;){if(a.startLineNumber0?a=l.regions.toRegion(a.regionIndex-1):a=null}return null}function g(c,l){let a=l.getRegionAtLine(c);if(a!==null&&a.startLineNumber===c){const r=a.parentIndex;let u=0;if(r!==-1)u=l.regions.getEndLineNumber(a.parentIndex);else{if(l.regions.length===0)return null;u=l.regions.getEndLineNumber(l.regions.length-1)}for(;a!==null;)if(a.regionIndex=u)return null;if(a.parentIndex===r)return a.startLineNumber}else return null}else if(l.regions.length>0)for(a=l.regions.toRegion(0);a!==null;){if(a.startLineNumber>c)return a.startLineNumber;a.regionIndexthis.updateHiddenRanges()),this._hiddenRanges=[],p.regions.length&&this.updateHiddenRanges()}notifyChangeModelContent(p){this._hiddenRanges.length&&!this._hasLineChanges&&(this._hasLineChanges=p.changes.some(n=>n.range.endLineNumber!==n.range.startLineNumber||(0,E.countEOL)(n.text)[0]!==0))}updateHiddenRanges(){let p=!1;const n=[];let o=0,t=0,i=Number.MAX_VALUE,s=-1;const g=this._foldingModel.regions;for(;o0}isHidden(p){return _(this._hiddenRanges,p)!==null}adjustSelections(p){let n=!1;const o=this._foldingModel.textModel;let t=null;const i=s=>((!t||!m(s,t))&&(t=_(this._hiddenRanges,s)),t?t.startLineNumber-1:null);for(let s=0,g=p.length;s0&&(this._hiddenRanges=[],this._updateEventEmitter.fire(this._hiddenRanges)),this._foldingModelListener&&(this._foldingModelListener.dispose(),this._foldingModelListener=null)}}e.HiddenRangeModel=y;function m(b,p){return b>=p.startLineNumber&&b<=p.endLineNumber}function _(b,p){const n=(0,d.findFirstIdxMonotonousOrArrLen)(b,o=>p=0&&b[n].endLineNumber>=p?b[n]:null}}),define(ne[335],se([1,0,237,203]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RangesCollector=e.IndentRangeProvider=void 0,e.computeRanges=b;const I=5e3,E="indent";class y{constructor(n,o,t){this.editorModel=n,this.languageConfigurationService=o,this.foldingRangesLimit=t,this.id=E}dispose(){}compute(n){const o=this.languageConfigurationService.getLanguageConfiguration(this.editorModel.getLanguageId()).foldingRules,t=o&&!!o.offSide,i=o&&o.markers;return Promise.resolve(b(this.editorModel,t,i,this.foldingRangesLimit))}}e.IndentRangeProvider=y;class m{constructor(n){this._startIndexes=[],this._endIndexes=[],this._indentOccurrences=[],this._length=0,this._foldingRangesLimit=n}insertFirst(n,o,t){if(n>k.MAX_LINE_NUMBER||o>k.MAX_LINE_NUMBER)return;const i=this._length;this._startIndexes[i]=n,this._endIndexes[i]=o,this._length++,t<1e3&&(this._indentOccurrences[t]=(this._indentOccurrences[t]||0)+1)}toIndentRanges(n){const o=this._foldingRangesLimit.limit;if(this._length<=o){this._foldingRangesLimit.update(this._length,!1);const t=new Uint32Array(this._length),i=new Uint32Array(this._length);for(let s=this._length-1,g=0;s>=0;s--,g++)t[g]=this._startIndexes[s],i[g]=this._endIndexes[s];return new k.FoldingRegions(t,i)}else{this._foldingRangesLimit.update(this._length,o);let t=0,i=this._indentOccurrences.length;for(let l=0;lo){i=l;break}t+=a}}const s=n.getOptions().tabSize,g=new Uint32Array(o),c=new Uint32Array(o);for(let l=this._length-1,a=0;l>=0;l--){const r=this._startIndexes[l],u=n.getLineContent(r),C=(0,d.computeIndentLevel)(u,s);(C{}};function b(p,n,o,t=_){const i=p.getOptions().tabSize,s=new m(t);let g;o&&(g=new RegExp(`(${o.start.source})|(?:${o.end.source})`));const c=[],l=p.getLineCount()+1;c.push({indent:-1,endAbove:l,line:l});for(let a=p.getLineCount();a>0;a--){const r=p.getLineContent(a),u=(0,d.computeIndentLevel)(r,i);let C=c[c.length-1];if(u===-1){n&&(C.endAbove=a);continue}let f;if(g&&(f=r.match(g)))if(f[1]){let h=c.length-1;for(;h>0&&c[h].indent!==-2;)h--;if(h>0){c.length=h+1,C=c[h],s.insertFirst(a,C.line,u),C.line=a,C.indent=u,C.endAbove=a;continue}}else{c.push({indent:-2,endAbove:a,line:a});continue}if(C.indent>u){do c.pop(),C=c[c.length-1];while(C.indent>u);const h=C.endAbove-1;h-a>=1&&s.insertFirst(a,h,u)}C.indent===u?C.endAbove=a:c.push({indent:u,endAbove:a,line:a})}return s.toIndentRanges(p)}}),define(ne[336],se([1,0,8,2,203]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SyntaxRangeProvider=void 0,e.sanitizeRanges=p;const E={},y="syntax";class m{constructor(o,t,i,s,g){this.editorModel=o,this.providers=t,this.handleFoldingRangesChange=i,this.foldingRangesLimit=s,this.fallbackRangeProvider=g,this.id=y,this.disposables=new k.DisposableStore,g&&this.disposables.add(g);for(const c of t)typeof c.onDidChange=="function"&&this.disposables.add(c.onDidChange(i))}compute(o){return _(this.providers,this.editorModel,o).then(t=>t?p(t,this.foldingRangesLimit):this.fallbackRangeProvider?.compute(o)??null)}dispose(){this.disposables.dispose()}}e.SyntaxRangeProvider=m;function _(n,o,t){let i=null;const s=n.map((g,c)=>Promise.resolve(g.provideFoldingRanges(o,E,t)).then(l=>{if(!t.isCancellationRequested&&Array.isArray(l)){Array.isArray(i)||(i=[]);const a=o.getLineCount();for(const r of l)r.start>0&&r.end>r.start&&r.end<=a&&i.push({start:r.start,end:r.end,rank:c,kind:r.kind})}},d.onUnexpectedExternalError));return Promise.all(s).then(g=>i)}class b{constructor(o){this._startIndexes=[],this._endIndexes=[],this._nestingLevels=[],this._nestingLevelCounts=[],this._types=[],this._length=0,this._foldingRangesLimit=o}add(o,t,i,s){if(o>I.MAX_LINE_NUMBER||t>I.MAX_LINE_NUMBER)return;const g=this._length;this._startIndexes[g]=o,this._endIndexes[g]=t,this._nestingLevels[g]=s,this._types[g]=i,this._length++,s<30&&(this._nestingLevelCounts[s]=(this._nestingLevelCounts[s]||0)+1)}toIndentRanges(){const o=this._foldingRangesLimit.limit;if(this._length<=o){this._foldingRangesLimit.update(this._length,!1);const t=new Uint32Array(this._length),i=new Uint32Array(this._length);for(let s=0;so){i=l;break}t+=a}}const s=new Uint32Array(o),g=new Uint32Array(o),c=[];for(let l=0,a=0;l{let a=c.start-l.start;return a===0&&(a=c.rank-l.rank),a}),i=new b(o);let s;const g=[];for(const c of t)if(!s)s=c,i.add(c.start,c.end,c.kind&&c.kind.value,g.length);else if(c.start>s.start)if(c.end<=s.end)g.push(s),s=c,i.add(c.start,c.end,c.kind&&c.kind.value,g.length);else{if(c.start>s.end){do s=g.pop();while(s&&c.start>s.end);s&&g.push(s),s=c}i.add(c.start,c.end,c.kind&&c.kind.value,g.length)}return i.toIndentRanges()}}),define(ne[337],se([1,0,75,4,143]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FormattingEdit=void 0;class E{static _handleEolEdits(m,_){let b;const p=[];for(const n of _)typeof n.eol=="number"&&(b=n.eol),n.range&&typeof n.text=="string"&&p.push(n);return typeof b=="number"&&m.hasModel()&&m.getModel().pushEOL(b),p}static _isFullModelReplaceEdit(m,_){if(!m.hasModel())return!1;const b=m.getModel(),p=b.validateRange(_.range);return b.getFullModelRange().equalsRange(p)}static execute(m,_,b){b&&m.pushUndoStop();const p=I.StableEditorScrollState.capture(m),n=E._handleEolEdits(m,_);n.length===1&&E._isFullModelReplaceEdit(m,n[0])?m.executeEdits("formatEditsCommand",n.map(o=>d.EditOperation.replace(k.Range.lift(o.range),o.text))):m.executeEdits("formatEditsCommand",n.map(o=>d.EditOperation.replaceMove(k.Range.lift(o.range),o.text))),b&&m.pushUndoStop(),p.restoreRelativeVerticalPositionOfCursor(m)}}e.FormattingEdit=E}),define(ne[614],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FilteredHoverResult=e.HoverResult=void 0;class d{constructor(E,y,m){this.anchor=E,this.hoverParts=y,this.isComplete=m}filter(E){const y=this.hoverParts.filter(m=>m.isValidForHoverAnchor(E));return y.length===this.hoverParts.length?this:new k(this,this.anchor,y,this.isComplete)}}e.HoverResult=d;class k extends d{constructor(E,y,m,_){super(y,m,_),this.original=E}filter(E){return this.original.filter(E)}}e.FilteredHoverResult=k}),define(ne[615],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ExtHoverAccessibleView=e.HoverAccessibilityHelp=e.HoverAccessibleView=void 0;class d{}e.HoverAccessibleView=d;class k{}e.HoverAccessibilityHelp=k;class I{}e.ExtHoverAccessibleView=I}),define(ne[84],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HoverParticipantRegistry=e.RenderedHoverParts=e.HoverForeignElementAnchor=e.HoverRangeAnchor=void 0;class d{constructor(y,m,_,b){this.priority=y,this.range=m,this.initialMousePosX=_,this.initialMousePosY=b,this.type=1}equals(y){return y.type===1&&this.range.equalsRange(y.range)}canAdoptVisibleHover(y,m){return y.type===1&&m.lineNumber===this.range.startLineNumber}}e.HoverRangeAnchor=d;class k{constructor(y,m,_,b,p,n){this.priority=y,this.owner=m,this.range=_,this.initialMousePosX=b,this.initialMousePosY=p,this.supportsMarkerHover=n,this.type=2}equals(y){return y.type===2&&this.owner===y.owner}canAdoptVisibleHover(y,m){return y.type===2&&this.owner===y.owner}}e.HoverForeignElementAnchor=k;class I{constructor(y){this.renderedHoverParts=y}dispose(){for(const y of this.renderedHoverParts)y.dispose()}}e.RenderedHoverParts=I,e.HoverParticipantRegistry=new class{constructor(){this._participants=[]}register(y){this._participants.push(y)}getAll(){return this._participants}}}),define(ne[616],se([1,0,23]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InPlaceReplaceCommand=void 0;class k{constructor(E,y,m){this._editRange=E,this._originalSelection=y,this._text=m}getEditOperations(E,y){y.addTrackedEditOperation(this._editRange,this._text)}computeCursorState(E,y){const _=y.getInverseEditOperations()[0].range;return this._originalSelection.isEmpty()?new d.Selection(_.endLineNumber,Math.min(this._originalSelection.positionColumn,_.endColumn),_.endLineNumber,Math.min(this._originalSelection.positionColumn,_.endColumn)):new d.Selection(_.endLineNumber,_.endColumn-this._text.length,_.endLineNumber,_.endColumn)}}e.InPlaceReplaceCommand=k}),define(ne[338],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getSpaceCnt=d,e.generateIndent=k;function d(I,E){let y=0;for(let m=0;mi.equals(t.parts[s]))}renderForScreenReader(t){if(this.parts.length===0)return"";const i=this.parts[this.parts.length-1],s=t.substr(0,i.column-1);return new y.TextEdit([...this.parts.map(c=>new y.SingleTextEdit(E.Range.fromPositions(new I.Position(1,c.column)),c.lines.join(` `)))]).applyToString(s).substring(this.parts[0].column-1)}isEmpty(){return this.parts.every(t=>t.lines.length===0)}get lineCount(){return 1+this.parts.reduce((t,i)=>t+i.lines.length-1,0)}}e.GhostText=m;class _{constructor(t,i,s){this.column=t,this.text=i,this.preview=s,this.lines=(0,k.splitLines)(this.text)}equals(t){return this.column===t.column&&this.lines.length===t.lines.length&&this.lines.every((i,s)=>i===t.lines[s])}}e.GhostTextPart=_;class b{constructor(t,i,s,g=0){this.lineNumber=t,this.columnRange=i,this.text=s,this.additionalReservedLineCount=g,this.parts=[new _(this.columnRange.endColumnExclusive,this.text,!1)],this.newLines=(0,k.splitLines)(this.text)}renderForScreenReader(t){return this.newLines.join(` `)}get lineCount(){return this.newLines.length}isEmpty(){return this.parts.every(t=>t.lines.length===0)}equals(t){return this.lineNumber===t.lineNumber&&this.columnRange.equals(t.columnRange)&&this.newLines.length===t.newLines.length&&this.newLines.every((i,s)=>i===t.newLines[s])&&this.additionalReservedLineCount===t.additionalReservedLineCount}}e.GhostTextReplacement=b;function p(o,t){return(0,d.equals)(o,t,n)}function n(o,t){return o===t?!0:!o||!t?!1:o instanceof m&&t instanceof m||o instanceof b&&t instanceof b?o.equals(t):!1}}),define(ne[246],se([1,0,190,11,4,113,104,204]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.singleTextRemoveCommonPrefix=_,e.singleTextEditAugments=b,e.computeGhostText=p;function _(g,c,l){const a=l?g.range.intersectRanges(l):g.range;if(!a)return g;const r=c.getValueInRange(a,1),u=(0,k.commonPrefixLength)(r,g.text),C=E.TextLength.ofText(r.substring(0,u)).addToPosition(g.range.getStartPosition()),f=g.text.substring(u),h=I.Range.fromPositions(C,g.range.getEndPosition());return new y.SingleTextEdit(h,f)}function b(g,c){return g.text.startsWith(c.text)&&n(g.range,c.range)}function p(g,c,l,a,r=0){let u=_(g,c);if(u.range.endLineNumber!==u.range.startLineNumber)return;const C=c.getLineContent(u.range.startLineNumber),f=(0,k.getLeadingWhitespace)(C).length;if(u.range.startColumn-1<=f){const T=(0,k.getLeadingWhitespace)(u.text).length,M=C.substring(u.range.startColumn-1,f),[A,P]=[u.range.getStartPosition(),u.range.getEndPosition()],N=A.column+M.length<=P.column?A.delta(0,M.length):P,O=I.Range.fromPositions(N,P),F=u.text.startsWith(M)?u.text.substring(M.length):u.text.substring(T);u=new y.SingleTextEdit(O,F)}const v=c.getValueInRange(u.range),w=t(v,u.text);if(!w)return;const S=u.range.startLineNumber,L=new Array;if(l==="prefix"){const T=w.filter(M=>M.originalLength===0);if(T.length>1||T.length===1&&T[0].originalStart!==v.length)return}const D=u.text.length-r;for(const T of w){const M=u.range.startColumn+T.originalStart+T.originalLength;if(l==="subwordSmart"&&a&&a.lineNumber===u.range.startLineNumber&&M0)return;if(T.modifiedLength===0)continue;const A=T.modifiedStart+T.modifiedLength,P=Math.max(T.modifiedStart,Math.min(A,D)),N=u.text.substring(T.modifiedStart,P),O=u.text.substring(P,Math.max(T.modifiedStart,A));N.length>0&&L.push(new m.GhostTextPart(M,N,!1)),O.length>0&&L.push(new m.GhostTextPart(M,O,!0))}return new m.GhostText(S,L)}function n(g,c){return c.getStartPosition().equals(g.getStartPosition())&&c.getEndPosition().isBeforeOrEqual(g.getEndPosition())}let o;function t(g,c){if(o?.originalValue===g&&o?.newValue===c)return o?.changes;{let l=s(g,c,!0);if(l){const a=i(l);if(a>0){const r=s(g,c,!1);r&&i(r)5e3||c.length>5e3)return;function a(v){let w=0;for(let S=0,L=v.length;Sw&&(w=D)}return w}const r=Math.max(a(g),a(c));function u(v){if(v<0)throw new Error("unexpected");return r+v+1}function C(v){let w=0,S=0;const L=new Int32Array(v.length);for(let D=0,T=v.length;Df},{getElements:()=>h}).ComputeDiff(!1).changes}}),define(ne[205],se([1,0,8,2,21,9,4]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ColumnRange=void 0,e.getReadonlyEmptyArray=_,e.applyObservableDecorations=p,e.addPositions=n,e.subtractPositions=o;const m=[];function _(){return m}class b{constructor(i,s){if(this.startColumn=i,this.endColumnExclusive=s,i>s)throw new d.BugIndicatingError(`startColumn ${i} cannot be after endColumnExclusive ${s}`)}toRange(i){return new y.Range(i,this.startColumn,i,this.endColumnExclusive)}equals(i){return this.startColumn===i.startColumn&&this.endColumnExclusive===i.endColumnExclusive}}e.ColumnRange=b;function p(t,i){const s=new k.DisposableStore,g=t.createDecorationsCollection();return s.add((0,I.autorunOpts)({debugName:()=>`Apply decorations from ${i.debugName}`},c=>{const l=i.read(c);g.set(l)})),s.add({dispose:()=>{g.clear()}}),s}function n(t,i){return new E.Position(t.lineNumber+i.lineNumber-1,i.lineNumber===1?t.column+i.column-1:i.column)}function o(t,i){return new E.Position(t.lineNumber-i.lineNumber+1,t.lineNumber-i.lineNumber===0?t.column-i.column+1:t.column)}}),define(ne[618],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.inlineEditJumpBackId=e.inlineEditJumpToId=e.inlineEditRejectId=e.inlineEditAcceptId=void 0,e.inlineEditAcceptId="editor.action.inlineEdit.accept",e.inlineEditRejectId="editor.action.inlineEdit.reject",e.inlineEditJumpToId="editor.action.inlineEdit.jumpTo",e.inlineEditJumpBackId="editor.action.inlineEdit.jumpBack"}),define(ne[619],se([1,0,4,23]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CopyLinesCommand=void 0;class I{constructor(y,m,_){this._selection=y,this._isCopyingDown=m,this._noop=_||!1,this._selectionDirection=0,this._selectionId=null,this._startLineNumberDelta=0,this._endLineNumberDelta=0}getEditOperations(y,m){let _=this._selection;this._startLineNumberDelta=0,this._endLineNumberDelta=0,_.startLineNumber<_.endLineNumber&&_.endColumn===1&&(this._endLineNumberDelta=1,_=_.setEndPosition(_.endLineNumber-1,y.getLineMaxColumn(_.endLineNumber-1)));const b=[];for(let n=_.startLineNumber;n<=_.endLineNumber;n++)b.push(y.getLineContent(n));const p=b.join(` `);p===""&&this._isCopyingDown&&(this._startLineNumberDelta++,this._endLineNumberDelta++),this._noop?m.addEditOperation(new d.Range(_.endLineNumber,y.getLineMaxColumn(_.endLineNumber),_.endLineNumber+1,1),_.endLineNumber===y.getLineCount()?"":` `):this._isCopyingDown?m.addEditOperation(new d.Range(_.startLineNumber,1,_.startLineNumber,1),p+` `):m.addEditOperation(new d.Range(_.endLineNumber,y.getLineMaxColumn(_.endLineNumber),_.endLineNumber,y.getLineMaxColumn(_.endLineNumber)),` `+p),this._selectionId=m.trackSelection(_),this._selectionDirection=this._selection.getDirection()}computeCursorState(y,m){let _=m.getTrackedSelection(this._selectionId);if(this._startLineNumberDelta!==0||this._endLineNumberDelta!==0){let b=_.startLineNumber,p=_.startColumn,n=_.endLineNumber,o=_.endColumn;this._startLineNumberDelta!==0&&(b=b+this._startLineNumberDelta,p=1),this._endLineNumberDelta!==0&&(n=n+this._endLineNumberDelta,o=1),_=k.Selection.createWithDirection(b,p,n,o,this._selectionDirection)}return _}}e.CopyLinesCommand=I}),define(ne[620],se([1,0,75,4]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SortLinesCommand=void 0;class I{static{this._COLLATOR=null}static getCollator(){return I._COLLATOR||(I._COLLATOR=new Intl.Collator),I._COLLATOR}constructor(_,b){this.selection=_,this.descending=b,this.selectionId=null}getEditOperations(_,b){const p=y(_,this.selection,this.descending);p&&b.addEditOperation(p.range,p.text),this.selectionId=b.trackSelection(this.selection)}computeCursorState(_,b){return b.getTrackedSelection(this.selectionId)}static canRun(_,b,p){if(_===null)return!1;const n=E(_,b,p);if(!n)return!1;for(let o=0,t=n.before.length;o=n)return null;const o=[];for(let i=p;i<=n;i++)o.push(m.getLineContent(i));let t=o.slice(0);return t.sort(I.getCollator().compare),b===!0&&(t=t.reverse()),{startLineNumber:p,endLineNumber:n,before:o,after:t}}function y(m,_,b){const p=E(m,_,b);return p?d.EditOperation.replace(new k.Range(p.startLineNumber,1,p.endLineNumber,m.getLineMaxColumn(p.endLineNumber)),p.after.join(` `)):null}}),define(ne[339],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SEMANTIC_HIGHLIGHTING_SETTING_ID=void 0,e.isSemanticColoringEnabled=d,e.SEMANTIC_HIGHLIGHTING_SETTING_ID="editor.semanticHighlighting";function d(k,I,E){const y=E.getValue(e.SEMANTIC_HIGHLIGHTING_SETTING_ID,{overrideIdentifier:k.getLanguageId(),resource:k.uri})?.enabled;return typeof y=="boolean"?y:I.getColorTheme().semanticHighlighting}}),define(ne[340],se([1,0,73,9,4]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BracketSelectionRangeProvider=void 0;class E{async provideSelectionRanges(m,_){const b=[];for(const p of _){const n=[];b.push(n);const o=new Map;await new Promise(t=>E._bracketsRightYield(t,0,m,p,o)),await new Promise(t=>E._bracketsLeftYield(t,0,m,p,o,n))}return b}static{this._maxDuration=30}static{this._maxRounds=2}static _bracketsRightYield(m,_,b,p,n){const o=new Map,t=Date.now();for(;;){if(_>=E._maxRounds){m();break}if(!p){m();break}const i=b.bracketPairs.findNextBracket(p);if(!i){m();break}if(Date.now()-t>E._maxDuration){setTimeout(()=>E._bracketsRightYield(m,_+1,b,p,n));break}if(i.bracketInfo.isOpeningBracket){const g=i.bracketInfo.bracketText,c=o.has(g)?o.get(g):0;o.set(g,c+1)}else{const g=i.bracketInfo.getOpeningBrackets()[0].bracketText;let c=o.has(g)?o.get(g):0;if(c-=1,o.set(g,Math.max(0,c)),c<0){let l=n.get(g);l||(l=new d.LinkedList,n.set(g,l)),l.push(i.range)}}p=i.range.getEndPosition()}}static _bracketsLeftYield(m,_,b,p,n,o){const t=new Map,i=Date.now();for(;;){if(_>=E._maxRounds&&n.size===0){m();break}if(!p){m();break}const s=b.bracketPairs.findPrevBracket(p);if(!s){m();break}if(Date.now()-i>E._maxDuration){setTimeout(()=>E._bracketsLeftYield(m,_+1,b,p,n,o));break}if(s.bracketInfo.isOpeningBracket){const c=s.bracketInfo.bracketText;let l=t.has(c)?t.get(c):0;if(l-=1,t.set(c,Math.max(0,l)),l<0){const a=n.get(c);if(a){const r=a.shift();a.size===0&&n.delete(c);const u=I.Range.fromPositions(s.range.getEndPosition(),r.getStartPosition()),C=I.Range.fromPositions(s.range.getStartPosition(),r.getEndPosition());o.push({range:u}),o.push({range:C}),E._addBracketLeading(b,C,o)}}}else{const c=s.bracketInfo.getOpeningBrackets()[0].bracketText,l=t.has(c)?t.get(c):0;t.set(c,l+1)}p=s.range.getStartPosition()}}static _addBracketLeading(m,_,b){if(_.startLineNumber===_.endLineNumber)return;const p=_.startLineNumber,n=m.getLineFirstNonWhitespaceColumn(p);n!==0&&n!==_.startColumn&&(b.push({range:I.Range.fromPositions(new k.Position(p,n),_.getEndPosition())}),b.push({range:I.Range.fromPositions(new k.Position(p,1),_.getEndPosition())}));const o=p-1;if(o>0){const t=m.getLineFirstNonWhitespaceColumn(o);t===_.startColumn&&t!==m.getLineLastNonWhitespaceColumn(o)&&(b.push({range:I.Range.fromPositions(new k.Position(o,t),_.getEndPosition())}),b.push({range:I.Range.fromPositions(new k.Position(o,1),_.getEndPosition())}))}}}e.BracketSelectionRangeProvider=E}),define(ne[621],se([1,0,11,4]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.WordSelectionRangeProvider=void 0;class I{constructor(y=!0){this.selectSubwords=y}provideSelectionRanges(y,m){const _=[];for(const b of m){const p=[];_.push(p),this.selectSubwords&&this._addInWordRanges(p,y,b),this._addWordRanges(p,y,b),this._addWhitespaceLine(p,y,b),p.push({range:y.getFullModelRange()})}return _}_addInWordRanges(y,m,_){const b=m.getWordAtPosition(_);if(!b)return;const{word:p,startColumn:n}=b,o=_.column-n;let t=o,i=o,s=0;for(;t>=0;t--){const g=p.charCodeAt(t);if(t!==o&&(g===95||g===45))break;if((0,d.isLowerAsciiLetter)(g)&&(0,d.isUpperAsciiLetter)(s))break;s=g}for(t+=1;i0&&m.getLineFirstNonWhitespaceColumn(_.lineNumber)===0&&m.getLineLastNonWhitespaceColumn(_.lineNumber)===0&&y.push({range:new k.Range(_.lineNumber,1,_.lineNumber,m.getLineMaxColumn(_.lineNumber))})}}e.WordSelectionRangeProvider=I}),define(ne[135],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SnippetParser=e.TextmateSnippet=e.Variable=e.FormatString=e.Transform=e.Choice=e.Placeholder=e.TransformableMarker=e.Text=e.Marker=e.Scanner=void 0;class d{constructor(){this.value="",this.pos=0}static{this._table={36:0,58:1,44:2,123:3,125:4,92:5,47:6,124:7,43:11,45:12,63:13}}static isDigitCharacter(s){return s>=48&&s<=57}static isVariableCharacter(s){return s===95||s>=97&&s<=122||s>=65&&s<=90}text(s){this.value=s,this.pos=0}tokenText(s){return this.value.substr(s.pos,s.len)}next(){if(this.pos>=this.value.length)return{type:14,pos:this.pos,len:0};const s=this.pos;let g=0,c=this.value.charCodeAt(s),l;if(l=d._table[c],typeof l=="number")return this.pos+=1,{type:l,pos:s,len:1};if(d.isDigitCharacter(c)){l=8;do g+=1,c=this.value.charCodeAt(s+g);while(d.isDigitCharacter(c));return this.pos+=g,{type:l,pos:s,len:g}}if(d.isVariableCharacter(c)){l=9;do c=this.value.charCodeAt(s+ ++g);while(d.isVariableCharacter(c)||d.isDigitCharacter(c));return this.pos+=g,{type:l,pos:s,len:g}}l=10;do g+=1,c=this.value.charCodeAt(s+g);while(!isNaN(c)&&typeof d._table[c]>"u"&&!d.isDigitCharacter(c)&&!d.isVariableCharacter(c));return this.pos+=g,{type:l,pos:s,len:g}}}e.Scanner=d;class k{constructor(){this._children=[]}appendChild(s){return s instanceof I&&this._children[this._children.length-1]instanceof I?this._children[this._children.length-1].value+=s.value:(s.parent=this,this._children.push(s)),this}replace(s,g){const{parent:c}=s,l=c.children.indexOf(s),a=c.children.slice(0);a.splice(l,1,...g),c._children=a,function r(u,C){for(const f of u)f.parent=C,r(f.children,f)}(g,c)}get children(){return this._children}get rightMostDescendant(){return this._children.length>0?this._children[this._children.length-1].rightMostDescendant:this}get snippet(){let s=this;for(;;){if(!s)return;if(s instanceof o)return s;s=s.parent}}toString(){return this.children.reduce((s,g)=>s+g.toString(),"")}len(){return 0}}e.Marker=k;class I extends k{constructor(s){super(),this.value=s}toString(){return this.value}len(){return this.value.length}clone(){return new I(this.value)}}e.Text=I;class E extends k{}e.TransformableMarker=E;class y extends E{static compareByIndex(s,g){return s.index===g.index?0:s.isFinalTabstop?1:g.isFinalTabstop||s.indexg.index?1:0}constructor(s){super(),this.index=s}get isFinalTabstop(){return this.index===0}get choice(){return this._children.length===1&&this._children[0]instanceof m?this._children[0]:void 0}clone(){const s=new y(this.index);return this.transform&&(s.transform=this.transform.clone()),s._children=this.children.map(g=>g.clone()),s}}e.Placeholder=y;class m extends k{constructor(){super(...arguments),this.options=[]}appendChild(s){return s instanceof I&&(s.parent=this,this.options.push(s)),this}toString(){return this.options[0].value}len(){return this.options[0].len()}clone(){const s=new m;return this.options.forEach(s.appendChild,s),s}}e.Choice=m;class _ extends k{constructor(){super(...arguments),this.regexp=new RegExp("")}resolve(s){const g=this;let c=!1,l=s.replace(this.regexp,function(){return c=!0,g._replace(Array.prototype.slice.call(arguments,0,-2))});return!c&&this._children.some(a=>a instanceof b&&!!a.elseValue)&&(l=this._replace([])),l}_replace(s){let g="";for(const c of this._children)if(c instanceof b){let l=s[c.index]||"";l=c.resolve(l),g+=l}else g+=c.toString();return g}toString(){return""}clone(){const s=new _;return s.regexp=new RegExp(this.regexp.source,(this.regexp.ignoreCase?"i":"")+(this.regexp.global?"g":"")),s._children=this.children.map(g=>g.clone()),s}}e.Transform=_;class b extends k{constructor(s,g,c,l){super(),this.index=s,this.shorthandName=g,this.ifValue=c,this.elseValue=l}resolve(s){return this.shorthandName==="upcase"?s?s.toLocaleUpperCase():"":this.shorthandName==="downcase"?s?s.toLocaleLowerCase():"":this.shorthandName==="capitalize"?s?s[0].toLocaleUpperCase()+s.substr(1):"":this.shorthandName==="pascalcase"?s?this._toPascalCase(s):"":this.shorthandName==="camelcase"?s?this._toCamelCase(s):"":s&&typeof this.ifValue=="string"?this.ifValue:!s&&typeof this.elseValue=="string"?this.elseValue:s||""}_toPascalCase(s){const g=s.match(/[a-z0-9]+/gi);return g?g.map(c=>c.charAt(0).toUpperCase()+c.substr(1)).join(""):s}_toCamelCase(s){const g=s.match(/[a-z0-9]+/gi);return g?g.map((c,l)=>l===0?c.charAt(0).toLowerCase()+c.substr(1):c.charAt(0).toUpperCase()+c.substr(1)).join(""):s}clone(){return new b(this.index,this.shorthandName,this.ifValue,this.elseValue)}}e.FormatString=b;class p extends E{constructor(s){super(),this.name=s}resolve(s){let g=s.resolve(this);return this.transform&&(g=this.transform.resolve(g||"")),g!==void 0?(this._children=[new I(g)],!0):!1}clone(){const s=new p(this.name);return this.transform&&(s.transform=this.transform.clone()),s._children=this.children.map(g=>g.clone()),s}}e.Variable=p;function n(i,s){const g=[...i];for(;g.length>0;){const c=g.shift();if(!s(c))break;g.unshift(...c.children)}}class o extends k{get placeholderInfo(){if(!this._placeholders){const s=[];let g;this.walk(function(c){return c instanceof y&&(s.push(c),g=!g||g.indexl===s?(c=!0,!1):(g+=l.len(),!0)),c?g:-1}fullLen(s){let g=0;return n([s],c=>(g+=c.len(),!0)),g}enclosingPlaceholders(s){const g=[];let{parent:c}=s;for(;c;)c instanceof y&&g.push(c),c=c.parent;return g}resolveVariables(s){return this.walk(g=>(g instanceof p&&g.resolve(s)&&(this._placeholders=void 0),!0)),this}appendChild(s){return this._placeholders=void 0,super.appendChild(s)}replace(s,g){return this._placeholders=void 0,super.replace(s,g)}clone(){const s=new o;return this._children=this.children.map(g=>g.clone()),s}walk(s){n(this.children,s)}}e.TextmateSnippet=o;class t{constructor(){this._scanner=new d,this._token={type:14,pos:0,len:0}}static escape(s){return s.replace(/\$|}|\\/g,"\\$&")}static guessNeedsClipboard(s){return/\${?CLIPBOARD/.test(s)}parse(s,g,c){const l=new o;return this.parseFragment(s,l),this.ensureFinalTabstop(l,c??!1,g??!1),l}parseFragment(s,g){const c=g.children.length;for(this._scanner.text(s),this._token=this._scanner.next();this._parse(g););const l=new Map,a=[];g.walk(C=>(C instanceof y&&(C.isFinalTabstop?l.set(0,void 0):!l.has(C.index)&&C.children.length>0?l.set(C.index,C.children):a.push(C)),!0));const r=(C,f)=>{const h=l.get(C.index);if(!h)return;const v=new y(C.index);v.transform=C.transform;for(const w of h){const S=w.clone();v.appendChild(S),S instanceof y&&l.has(S.index)&&!f.has(S.index)&&(f.add(S.index),r(S,f),f.delete(S.index))}g.replace(C,[v])},u=new Set;for(const C of a)r(C,u);return g.children.slice(c)}ensureFinalTabstop(s,g,c){(g||c&&s.placeholders.length>0)&&(s.placeholders.find(a=>a.index===0)||s.appendChild(new y(0)))}_accept(s,g){if(s===void 0||this._token.type===s){const c=g?this._scanner.tokenText(this._token):!0;return this._token=this._scanner.next(),c}return!1}_backTo(s){return this._scanner.pos=s.pos+s.len,this._token=s,!1}_until(s){const g=this._token;for(;this._token.type!==s;){if(this._token.type===14)return!1;if(this._token.type===5){const l=this._scanner.next();if(l.type!==0&&l.type!==4&&l.type!==5)return!1}this._token=this._scanner.next()}const c=this._scanner.value.substring(g.pos,this._token.pos).replace(/\\(\$|}|\\)/g,"$1");return this._token=this._scanner.next(),c}_parse(s){return this._parseEscaped(s)||this._parseTabstopOrVariableName(s)||this._parseComplexPlaceholder(s)||this._parseComplexVariable(s)||this._parseAnything(s)}_parseEscaped(s){let g;return(g=this._accept(5,!0))?(g=this._accept(0,!0)||this._accept(4,!0)||this._accept(5,!0)||g,s.appendChild(new I(g)),!0):!1}_parseTabstopOrVariableName(s){let g;const c=this._token;return this._accept(0)&&(g=this._accept(9,!0)||this._accept(8,!0))?(s.appendChild(/^\d+$/.test(g)?new y(Number(g)):new p(g)),!0):this._backTo(c)}_parseComplexPlaceholder(s){let g;const c=this._token;if(!(this._accept(0)&&this._accept(3)&&(g=this._accept(8,!0))))return this._backTo(c);const a=new y(Number(g));if(this._accept(1))for(;;){if(this._accept(4))return s.appendChild(a),!0;if(!this._parse(a))return s.appendChild(new I("${"+g+":")),a.children.forEach(s.appendChild,s),!0}else if(a.index>0&&this._accept(7)){const r=new m;for(;;){if(this._parseChoiceElement(r)){if(this._accept(2))continue;if(this._accept(7)&&(a.appendChild(r),this._accept(4)))return s.appendChild(a),!0}return this._backTo(c),!1}}else return this._accept(6)?this._parseTransform(a)?(s.appendChild(a),!0):(this._backTo(c),!1):this._accept(4)?(s.appendChild(a),!0):this._backTo(c)}_parseChoiceElement(s){const g=this._token,c=[];for(;!(this._token.type===2||this._token.type===7);){let l;if((l=this._accept(5,!0))?l=this._accept(2,!0)||this._accept(7,!0)||this._accept(5,!0)||l:l=this._accept(void 0,!0),!l)return this._backTo(g),!1;c.push(l)}return c.length===0?(this._backTo(g),!1):(s.appendChild(new I(c.join(""))),!0)}_parseComplexVariable(s){let g;const c=this._token;if(!(this._accept(0)&&this._accept(3)&&(g=this._accept(9,!0))))return this._backTo(c);const a=new p(g);if(this._accept(1))for(;;){if(this._accept(4))return s.appendChild(a),!0;if(!this._parse(a))return s.appendChild(new I("${"+g+":")),a.children.forEach(s.appendChild,s),!0}else return this._accept(6)?this._parseTransform(a)?(s.appendChild(a),!0):(this._backTo(c),!1):this._accept(4)?(s.appendChild(a),!0):this._backTo(c)}_parseTransform(s){const g=new _;let c="",l="";for(;!this._accept(6);){let a;if(a=this._accept(5,!0)){a=this._accept(6,!0)||a,c+=a;continue}if(this._token.type!==14){c+=this._accept(void 0,!0);continue}return!1}for(;!this._accept(6);){let a;if(a=this._accept(5,!0)){a=this._accept(5,!0)||this._accept(6,!0)||a,g.appendChild(new I(a));continue}if(!(this._parseFormatString(g)||this._parseAnything(g)))return!1}for(;!this._accept(4);){if(this._token.type!==14){l+=this._accept(void 0,!0);continue}return!1}try{g.regexp=new RegExp(c,l)}catch{return!1}return s.transform=g,!0}_parseFormatString(s){const g=this._token;if(!this._accept(0))return!1;let c=!1;this._accept(3)&&(c=!0);const l=this._accept(8,!0);if(l)if(c){if(this._accept(4))return s.appendChild(new b(Number(l))),!0;if(!this._accept(1))return this._backTo(g),!1}else return s.appendChild(new b(Number(l))),!0;else return this._backTo(g),!1;if(this._accept(6)){const a=this._accept(9,!0);return!a||!this._accept(4)?(this._backTo(g),!1):(s.appendChild(new b(Number(l),a)),!0)}else if(this._accept(11)){const a=this._until(4);if(a)return s.appendChild(new b(Number(l),void 0,a,void 0)),!0}else if(this._accept(12)){const a=this._until(4);if(a)return s.appendChild(new b(Number(l),void 0,void 0,a)),!0}else if(this._accept(13)){const a=this._until(1);if(a){const r=this._until(4);if(r)return s.appendChild(new b(Number(l),void 0,a,r)),!0}}else{const a=this._until(4);if(a)return s.appendChild(new b(Number(l),void 0,void 0,a)),!0}return this._backTo(g),!1}_parseAnything(s){return this._token.type!==14?(s.appendChild(new I(this._scanner.tokenText(this._token))),this._accept(void 0),!0):!1}}e.SnippetParser=t}),define(ne[341],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StickyModel=e.StickyElement=e.StickyRange=void 0;class d{constructor(y,m){this.startLineNumber=y,this.endLineNumber=m}}e.StickyRange=d;class k{constructor(y,m,_){this.range=y,this.children=m,this.parent=_}}e.StickyElement=k;class I{constructor(y,m,_,b){this.uri=y,this.version=m,this.element=_,this.outlineProviderId=b}}e.StickyModel=I}),define(ne[342],se([1,0,13,82,11]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CompletionModel=e.LineContext=void 0;class E{constructor(_,b){this.leadingLineContent=_,this.characterCountDelta=b}}e.LineContext=E;class y{constructor(_,b,p,n,o,t,i=k.FuzzyScoreOptions.default,s=void 0){this.clipboardText=s,this._snippetCompareFn=y._compareCompletionItems,this._items=_,this._column=b,this._wordDistance=n,this._options=o,this._refilterKind=1,this._lineContext=p,this._fuzzyScoreOptions=i,t==="top"?this._snippetCompareFn=y._compareCompletionItemsSnippetsUp:t==="bottom"&&(this._snippetCompareFn=y._compareCompletionItemsSnippetsDown)}get lineContext(){return this._lineContext}set lineContext(_){(this._lineContext.leadingLineContent!==_.leadingLineContent||this._lineContext.characterCountDelta!==_.characterCountDelta)&&(this._refilterKind=this._lineContext.characterCountDelta<_.characterCountDelta&&this._filteredItems?2:1,this._lineContext=_)}get items(){return this._ensureCachedState(),this._filteredItems}getItemsByProvider(){return this._ensureCachedState(),this._itemsByProvider}getIncompleteProvider(){this._ensureCachedState();const _=new Set;for(const[b,p]of this.getItemsByProvider())p.length>0&&p[0].container.incomplete&&_.add(b);return _}get stats(){return this._ensureCachedState(),this._stats}_ensureCachedState(){this._refilterKind!==0&&this._createCachedState()}_createCachedState(){this._itemsByProvider=new Map;const _=[],{leadingLineContent:b,characterCountDelta:p}=this._lineContext;let n="",o="";const t=this._refilterKind===1?this._items:this._filteredItems,i=[],s=!this._options.filterGraceful||t.length>2e3?k.fuzzyScore:k.fuzzyScoreGracefulAggressive;for(let g=0;g=r)c.score=k.FuzzyScore.Default;else if(typeof c.completion.filterText=="string"){const C=s(n,o,u,c.completion.filterText,c.filterTextLow,0,this._fuzzyScoreOptions);if(!C)continue;(0,I.compareIgnoreCase)(c.completion.filterText,c.textLabel)===0?c.score=C:(c.score=(0,k.anyScore)(n,o,u,c.textLabel,c.labelLow,0),c.score[0]=C[0])}else{const C=s(n,o,u,c.textLabel,c.labelLow,0,this._fuzzyScoreOptions);if(!C)continue;c.score=C}}c.idx=g,c.distance=this._wordDistance.distance(c.position,c.completion),i.push(c),_.push(c.textLabel.length)}this._filteredItems=i.sort(this._snippetCompareFn),this._refilterKind=0,this._stats={pLabelLen:_.length?(0,d.quickSelect)(_.length-.85,_,(g,c)=>g-c):0}}static _compareCompletionItems(_,b){return _.score[0]>b.score[0]?-1:_.score[0]b.distance?1:_.idxb.idx?1:0}static _compareCompletionItemsSnippetsDown(_,b){if(_.completion.kind!==b.completion.kind){if(_.completion.kind===27)return 1;if(b.completion.kind===27)return-1}return y._compareCompletionItems(_,b)}static _compareCompletionItemsSnippetsUp(_,b){if(_.completion.kind!==b.completion.kind){if(_.completion.kind===27)return-1;if(b.completion.kind===27)return 1}return y._compareCompletionItems(_,b)}}e.CompletionModel=y}),define(ne[622],se([1,0,13,2,144]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CommitCharacterController=void 0;class E{constructor(m,_,b,p){this._disposables=new k.DisposableStore,this._disposables.add(b.onDidSuggest(n=>{n.completionModel.items.length===0&&this.reset()})),this._disposables.add(b.onDidCancel(n=>{this.reset()})),this._disposables.add(_.onDidShow(()=>this._onItem(_.getFocusedItem()))),this._disposables.add(_.onDidFocus(this._onItem,this)),this._disposables.add(_.onDidHide(this.reset,this)),this._disposables.add(m.onWillType(n=>{if(this._active&&!_.isFrozen()&&b.state!==0){const o=n.charCodeAt(n.length-1);this._active.acceptCharacters.has(o)&&m.getOption(0)&&p(this._active.item)}}))}_onItem(m){if(!m||!(0,d.isNonEmptyArray)(m.item.completion.commitCharacters)){this.reset();return}if(this._active&&this._active.item.item===m.item)return;const _=new I.CharacterSet;for(const b of m.item.completion.commitCharacters)b.length>0&&_.add(b.charCodeAt(0));this._active={acceptCharacters:_,item:m}}reset(){this._active=void 0}dispose(){this._disposables.dispose()}}e.CommitCharacterController=E}),define(ne[623],se([1,0,2]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OvertypingCapturer=void 0;class k{static{this._maxSelectionLength=51200}constructor(E,y){this._disposables=new d.DisposableStore,this._lastOvertyped=[],this._locked=!1,this._disposables.add(E.onWillType(()=>{if(this._locked||!E.hasModel())return;const m=E.getSelections(),_=m.length;let b=!1;for(let n=0;n<_;n++)if(!m[n].isEmpty()){b=!0;break}if(!b){this._lastOvertyped.length!==0&&(this._lastOvertyped.length=0);return}this._lastOvertyped=[];const p=E.getModel();for(let n=0;n<_;n++){const o=m[n];if(p.getValueLengthInRange(o)>k._maxSelectionLength)return;this._lastOvertyped[n]={value:p.getValueInRange(o),multiline:o.startLineNumber!==o.endLineNumber}}})),this._disposables.add(y.onDidTrigger(m=>{this._locked=!0})),this._disposables.add(y.onDidCancel(m=>{this._locked=!1}))}getLastOvertypedInfo(E){if(E>=0&&E=0?c[l]:c[Math.max(0,~l-1)];let r=n.length;for(const u of n){if(!k.Range.containsRange(u.range,a))break;r-=1}return r}}}}e.WordDistance=E}),define(ne[624],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneTreeSitterParserService=void 0;class d{getParseResult(I){}}e.StandaloneTreeSitterParserService=d}),define(ne[344],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isFuzzyActionArr=d,e.isFuzzyAction=k,e.isString=I,e.isIAction=E,e.empty=y,e.fixCase=m,e.sanitize=_,e.log=b,e.createError=p,e.substituteMatches=n,e.substituteMatchesRe=o,e.findRules=t,e.stateExists=i;function d(s){return Array.isArray(s)}function k(s){return!d(s)}function I(s){return typeof s=="string"}function E(s){return!I(s)}function y(s){return!s}function m(s,g){return s.ignoreCase&&g?g.toLowerCase():g}function _(s){return s.replace(/[&<>'"_]/g,"-")}function b(s,g){console.log(`${s.languageId}: ${g}`)}function p(s,g){return new Error(`${s.languageId}: ${g}`)}function n(s,g,c,l,a){const r=/\$((\$)|(#)|(\d\d?)|[sS](\d\d?)|@(\w+))/g;let u=null;return g.replace(r,function(C,f,h,v,w,S,L,D,T){return y(h)?y(v)?!y(w)&&w0;){const l=s.tokenizer[c];if(l)return l;const a=c.lastIndexOf(".");a<0?c=null:c=c.substr(0,a)}return null}function i(s,g){let c=g;for(;c&&c.length>0;){if(s.stateNames[c])return!0;const a=c.lastIndexOf(".");a<0?c=null:c=c.substr(0,a)}return!1}}),define(ne[625],se([1,0,344]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.compile=t;function k(i,s){if(!s||!Array.isArray(s))return!1;for(const g of s)if(!i(g))return!1;return!0}function I(i,s){return typeof i=="boolean"?i:s}function E(i,s){return typeof i=="string"?i:s}function y(i){const s={};for(const g of i)s[g]=!0;return s}function m(i,s=!1){s&&(i=i.map(function(c){return c.toLowerCase()}));const g=y(i);return s?function(c){return g[c.toLowerCase()]!==void 0&&g.hasOwnProperty(c.toLowerCase())}:function(c){return g[c]!==void 0&&g.hasOwnProperty(c)}}function _(i,s,g){s=s.replace(/@@/g,"");let c=0,l;do l=!1,s=s.replace(/@(\w+)/g,function(r,u){l=!0;let C="";if(typeof i[u]=="string")C=i[u];else if(i[u]&&i[u]instanceof RegExp)C=i[u].source;else throw i[u]===void 0?d.createError(i,"language definition does not contain attribute '"+u+"', used at: "+s):d.createError(i,"attribute reference '"+u+"' must be a string, used at: "+s);return d.empty(C)?"":"(?:"+C+")"}),c++;while(l&&c<5);s=s.replace(/\x01/g,"@");const a=(i.ignoreCase?"i":"")+(i.unicode?"u":"");if(g&&s.match(/\$[sS](\d\d?)/g)){let u=null,C=null;return f=>(C&&u===f||(u=f,C=new RegExp(d.substituteMatchesRe(i,s,f),a)),C)}return new RegExp(s,a)}function b(i,s,g,c){if(c<0)return i;if(c=100){c=c-100;const l=g.split(".");if(l.unshift(g),c=0&&(c.tokenSubst=!0),typeof g.bracket=="string")if(g.bracket==="@open")c.bracket=1;else if(g.bracket==="@close")c.bracket=-1;else throw d.createError(i,"a 'bracket' attribute must be either '@open' or '@close', in rule: "+s);if(g.next){if(typeof g.next!="string")throw d.createError(i,"the next state must be a string value in rule: "+s);{let l=g.next;if(!/^(@pop|@push|@popall)$/.test(l)&&(l[0]==="@"&&(l=l.substr(1)),l.indexOf("$")<0&&!d.stateExists(i,d.substituteMatches(i,l,"",[],""))))throw d.createError(i,"the next state '"+g.next+"' is not defined in rule: "+s);c.next=l}}return typeof g.goBack=="number"&&(c.goBack=g.goBack),typeof g.switchTo=="string"&&(c.switchTo=g.switchTo),typeof g.log=="string"&&(c.log=g.log),typeof g.nextEmbedded=="string"&&(c.nextEmbedded=g.nextEmbedded,i.usesEmbedded=!0),c}}else if(Array.isArray(g)){const c=[];for(let l=0,a=g.length;l0&&c[0]==="^",this.name=this.name+": "+c,this.regex=_(s,"^(?:"+(this.matchOnlyAtLineStart?c.substr(1):c)+")",!0)}setAction(s,g){this.action=n(s,this.name,g)}resolveRegex(s){return this.regex instanceof RegExp?this.regex:this.regex(s)}}function t(i,s){if(!s||typeof s!="object")throw new Error("Monarch: expecting a language definition object");const g={languageId:i,includeLF:I(s.includeLF,!1),noThrow:!1,maxStack:100,start:typeof s.start=="string"?s.start:null,ignoreCase:I(s.ignoreCase,!1),unicode:I(s.unicode,!1),tokenPostfix:E(s.tokenPostfix,"."+i),defaultToken:E(s.defaultToken,"source"),usesEmbedded:!1,stateNames:{},tokenizer:{},brackets:[]},c=s;c.languageId=i,c.includeLF=g.includeLF,c.ignoreCase=g.ignoreCase,c.unicode=g.unicode,c.noThrow=g.noThrow,c.usesEmbedded=g.usesEmbedded,c.stateNames=s.tokenizer,c.defaultToken=g.defaultToken;function l(r,u,C){for(const f of C){let h=f.include;if(h){if(typeof h!="string")throw d.createError(g,"an 'include' attribute must be a string at: "+r);if(h[0]==="@"&&(h=h.substr(1)),!s.tokenizer[h])throw d.createError(g,"include target '"+h+"' is not defined at: "+r);l(r+"."+h,u,s.tokenizer[h])}else{const v=new o(r);if(Array.isArray(f)&&f.length>=1&&f.length<=3)if(v.setRegex(c,f[0]),f.length>=3)if(typeof f[1]=="string")v.setAction(c,{token:f[1],next:f[2]});else if(typeof f[1]=="object"){const w=f[1];w.next=f[2],v.setAction(c,w)}else throw d.createError(g,"a next state as the last element of a rule can only be given if the action is either an object or a string, at: "+r);else v.setAction(c,f[1]);else{if(!f.regex)throw d.createError(g,"a rule must either be an array, or an object with a 'regex' or 'include' field at: "+r);f.name&&typeof f.name=="string"&&(v.name=f.name),f.matchOnlyAtStart&&(v.matchOnlyAtLineStart=I(f.matchOnlyAtLineStart,!1)),v.setRegex(c,f.regex),v.setAction(c,f.action)}u.push(v)}}}if(!s.tokenizer||typeof s.tokenizer!="object")throw d.createError(g,"a language definition must define the 'tokenizer' attribute as an object");g.tokenizer=[];for(const r in s.tokenizer)if(s.tokenizer.hasOwnProperty(r)){g.start||(g.start=r);const u=s.tokenizer[r];g.tokenizer[r]=new Array,l("tokenizer."+r,g.tokenizer[r],u)}if(g.usesEmbedded=c.usesEmbedded,s.brackets){if(!Array.isArray(s.brackets))throw d.createError(g,"the 'brackets' attribute must be defined as an array")}else s.brackets=[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}];const a=[];for(const r of s.brackets){let u=r;if(u&&Array.isArray(u)&&u.length===3&&(u={token:u[2],open:u[0],close:u[1]}),u.open===u.close)throw d.createError(g,"open and close brackets in a 'brackets' attribute must be different: "+u.open+` hint: use the 'bracket' attribute if matching on equal brackets is required.`);if(typeof u.open=="string"&&typeof u.token=="string"&&typeof u.close=="string")a.push({token:u.token+g.tokenPostfix,open:d.fixCase(g,u.open),close:d.fixCase(g,u.close)});else throw d.createError(g,"every element in the 'brackets' array must be a '{open,close,token}' object or array")}return g.brackets=a,g.noThrow=!0,g}}),define(ne[345],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getNLSMessages=d,e.getNLSLanguage=k;function d(){return globalThis._VSCODE_NLS_MESSAGES}function k(){return globalThis._VSCODE_NLS_LANGUAGE}}),define(ne[3],se([1,0,345,345]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getNLSMessages=e.getNLSLanguage=void 0,e.localize=y,e.localize2=_,Object.defineProperty(e,"getNLSLanguage",{enumerable:!0,get:function(){return k.getNLSLanguage}}),Object.defineProperty(e,"getNLSMessages",{enumerable:!0,get:function(){return k.getNLSMessages}});const I=(0,d.getNLSLanguage)()==="pseudo"||typeof document<"u"&&document.location&&document.location.hash.indexOf("pseudo=true")>=0;function E(b,p){let n;return p.length===0?n=b:n=b.replace(/\{(\d+)\}/g,(o,t)=>{const i=t[0],s=p[i];let g=o;return typeof s=="string"?g=s:(typeof s=="number"||typeof s=="boolean"||s===void 0||s===null)&&(g=String(s)),g}),I&&(n="\uFF3B"+n.replace(/[aouei]/g,"$&$&")+"\uFF3D"),n}function y(b,p,...n){return E(typeof b=="number"?m(b,p):p,n)}function m(b,p){const n=(0,d.getNLSMessages)()?.[b];if(typeof n!="string"){if(typeof p=="string")return p;throw new Error(`!!! NLS MISSING: ${b} !!!`)}return n}function _(b,p,...n){let o;typeof b=="number"?o=m(b,p):o=p;const t=E(o,n);return{value:t,original:p===o?t:E(p,n)}}}),define(ne[41],se([1,0,6,2,3]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EmptySubmenuAction=e.SubmenuAction=e.Separator=e.ActionRunner=e.Action=void 0,e.toAction=p;class E extends k.Disposable{constructor(o,t="",i="",s=!0,g){super(),this._onDidChange=this._register(new d.Emitter),this.onDidChange=this._onDidChange.event,this._enabled=!0,this._id=o,this._label=t,this._cssClass=i,this._enabled=s,this._actionCallback=g}get id(){return this._id}get label(){return this._label}set label(o){this._setLabel(o)}_setLabel(o){this._label!==o&&(this._label=o,this._onDidChange.fire({label:o}))}get tooltip(){return this._tooltip||""}set tooltip(o){this._setTooltip(o)}_setTooltip(o){this._tooltip!==o&&(this._tooltip=o,this._onDidChange.fire({tooltip:o}))}get class(){return this._cssClass}set class(o){this._setClass(o)}_setClass(o){this._cssClass!==o&&(this._cssClass=o,this._onDidChange.fire({class:o}))}get enabled(){return this._enabled}set enabled(o){this._setEnabled(o)}_setEnabled(o){this._enabled!==o&&(this._enabled=o,this._onDidChange.fire({enabled:o}))}get checked(){return this._checked}set checked(o){this._setChecked(o)}_setChecked(o){this._checked!==o&&(this._checked=o,this._onDidChange.fire({checked:o}))}async run(o,t){this._actionCallback&&await this._actionCallback(o)}}e.Action=E;class y extends k.Disposable{constructor(){super(...arguments),this._onWillRun=this._register(new d.Emitter),this.onWillRun=this._onWillRun.event,this._onDidRun=this._register(new d.Emitter),this.onDidRun=this._onDidRun.event}async run(o,t){if(!o.enabled)return;this._onWillRun.fire({action:o});let i;try{await this.runAction(o,t)}catch(s){i=s}this._onDidRun.fire({action:o,error:i})}async runAction(o,t){await o.run(t)}}e.ActionRunner=y;class m{constructor(){this.id=m.ID,this.label="",this.tooltip="",this.class="separator",this.enabled=!1,this.checked=!1}static join(...o){let t=[];for(const i of o)i.length&&(t.length?t=[...t,new m,...i]:t=i);return t}static{this.ID="vs.actions.separator"}async run(){}}e.Separator=m;class _{get actions(){return this._actions}constructor(o,t,i,s){this.tooltip="",this.enabled=!0,this.checked=void 0,this.id=o,this.label=t,this.class=s,this._actions=i}async run(){}}e.SubmenuAction=_;class b extends E{static{this.ID="vs.actions.empty"}constructor(){super(b.ID,I.localize(27,"(empty)"),void 0,!1)}}e.EmptySubmenuAction=b;function p(n){return{id:n.id,label:n.label,tooltip:n.tooltip??n.label,class:n.class,enabled:n.enabled??!0,checked:n.checked,run:async(...o)=>n.run(...o)}}}),define(ne[346],se([1,0,13,19,3]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.toErrorMessage=_;function E(b,p){return p&&(b.stack||b.stacktrace)?I.localize(28,"{0}: {1}",m(b),y(b.stack)||y(b.stacktrace)):m(b)}function y(b){return Array.isArray(b)?b.join(` `):b}function m(b){return b.code==="ERR_UNC_HOST_NOT_ALLOWED"?`${b.message}. Please update the 'security.allowedUNCHosts' setting if you want to allow this host.`:typeof b.code=="string"&&typeof b.errno=="number"&&typeof b.syscall=="string"?I.localize(29,"A system error occurred ({0})",b.message):b.message||I.localize(30,"An unknown error occurred. Please consult the log for more details.")}function _(b=null,p=!1){if(!b)return I.localize(31,"An unknown error occurred. Please consult the log for more details.");if(Array.isArray(b)){const n=d.coalesce(b),o=_(n[0],p);return n.length>1?I.localize(32,"{0} ({1} errors in total)",o,n.length):o}if(k.isString(b))return b;if(b.detail){const n=b.detail;if(n.error)return E(n.error,p);if(n.exception)return E(n.exception,p)}return b.stack?E(b,p):b.message?b.message:I.localize(33,"An unknown error occurred. Please consult the log for more details.")}}),define(ne[247],se([1,0,3]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UserSettingsLabelProvider=e.ElectronAcceleratorLabelProvider=e.AriaLabelProvider=e.UILabelProvider=e.ModifierLabelProvider=void 0;class k{constructor(y,m,_=m){this.modifierLabels=[null],this.modifierLabels[2]=y,this.modifierLabels[1]=m,this.modifierLabels[3]=_}toLabel(y,m,_){if(m.length===0)return null;const b=[];for(let p=0,n=m.length;p=0,I=c.indexOf("Macintosh")>=0,p=(c.indexOf("Macintosh")>=0||c.indexOf("iPad")>=0||c.indexOf("iPhone")>=0)&&!!navigator.maxTouchPoints&&navigator.maxTouchPoints>0,E=c.indexOf("Linux")>=0,o=c?.indexOf("Mobi")>=0,_=!0,i=d.getNLSLanguage()||e.LANGUAGE_DEFAULT,t=navigator.language.toLowerCase(),s=t):console.error("Unable to resolve platform.");let C=0;I?C=1:k?C=3:E&&(C=2),e.isWindows=k,e.isMacintosh=I,e.isLinux=E,e.isNative=m,e.isWeb=_,e.isWebWorker=_&&typeof l.importScripts=="function",e.webWorkerOrigin=e.isWebWorker?l.origin:void 0,e.isIOS=p,e.isMobile=o,e.userAgent=c,e.language=i,e.setTimeout0IsFaster=typeof l.postMessage=="function"&&!l.importScripts,e.setTimeout0=(()=>{if(e.setTimeout0IsFaster){const w=[];l.addEventListener("message",L=>{if(L.data&&L.data.vscodeScheduleAsyncWork)for(let D=0,T=w.length;D{const D=++S;w.push({id:D,callback:L}),l.postMessage({vscodeScheduleAsyncWork:D},"*")}}return w=>setTimeout(w)})(),e.OS=I||p?2:k?1:3;let f=!0,h=!1;function v(){if(!h){h=!0;const w=new Uint8Array(2);w[0]=1,w[1]=2,f=new Uint16Array(w.buffer)[0]===513}return f}e.isChrome=!!(e.userAgent&&e.userAgent.indexOf("Chrome")>=0),e.isFirefox=!!(e.userAgent&&e.userAgent.indexOf("Firefox")>=0),e.isSafari=!!(!e.isChrome&&e.userAgent&&e.userAgent.indexOf("Safari")>=0),e.isEdge=!!(e.userAgent&&e.userAgent.indexOf("Edg/")>=0),e.isAndroid=!!(e.userAgent&&e.userAgent.indexOf("Android")>=0)}),define(ne[248],se([1,0,64,52,16]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BrowserFeatures=void 0,e.BrowserFeatures={clipboard:{writeText:I.isNative||document.queryCommandSupported&&document.queryCommandSupported("copy")||!!(navigator&&navigator.clipboard&&navigator.clipboard.writeText),readText:I.isNative||!!(navigator&&navigator.clipboard&&navigator.clipboard.readText)},keyboard:I.isNative||d.isStandalone()?0:navigator.keyboard||d.isSafari?1:2,touch:"ontouchstart"in k.mainWindow||navigator.maxTouchPoints>0,pointerEvents:k.mainWindow.PointerEvent&&("ontouchstart"in k.mainWindow||navigator.maxTouchPoints>0)}}),define(ne[347],se([1,0,16]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DEFAULT_FONT_FAMILY=void 0,e.DEFAULT_FONT_FAMILY=d.isWindows?'"Segoe WPC", "Segoe UI", sans-serif':d.isMacintosh?"-apple-system, BlinkMacSystemFont, sans-serif":'system-ui, "Ubuntu", "Droid Sans", sans-serif'}),define(ne[47],se([1,0,64,72,140,16]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandardKeyboardEvent=void 0;function y(o){if(o.charCode){const i=String.fromCharCode(o.charCode).toUpperCase();return k.KeyCodeUtils.fromString(i)}const t=o.keyCode;if(t===3)return 7;if(d.isFirefox)switch(t){case 59:return 85;case 60:if(E.isLinux)return 97;break;case 61:return 86;case 107:return 109;case 109:return 111;case 173:return 88;case 224:if(E.isMacintosh)return 57;break}else if(d.isWebKit){if(E.isMacintosh&&t===93)return 57;if(!E.isMacintosh&&t===92)return 57}return k.EVENT_KEY_CODE_MAP[t]||0}const m=E.isMacintosh?256:2048,_=512,b=1024,p=E.isMacintosh?2048:256;class n{constructor(t){this._standardKeyboardEventBrand=!0;const i=t;this.browserEvent=i,this.target=i.target,this.ctrlKey=i.ctrlKey,this.shiftKey=i.shiftKey,this.altKey=i.altKey,this.metaKey=i.metaKey,this.altGraphKey=i.getModifierState?.("AltGraph"),this.keyCode=y(i),this.code=i.code,this.ctrlKey=this.ctrlKey||this.keyCode===5,this.altKey=this.altKey||this.keyCode===6,this.shiftKey=this.shiftKey||this.keyCode===4,this.metaKey=this.metaKey||this.keyCode===57,this._asKeybinding=this._computeKeybinding(),this._asKeyCodeChord=this._computeKeyCodeChord()}preventDefault(){this.browserEvent&&this.browserEvent.preventDefault&&this.browserEvent.preventDefault()}stopPropagation(){this.browserEvent&&this.browserEvent.stopPropagation&&this.browserEvent.stopPropagation()}toKeyCodeChord(){return this._asKeyCodeChord}equals(t){return this._asKeybinding===t}_computeKeybinding(){let t=0;this.keyCode!==5&&this.keyCode!==4&&this.keyCode!==6&&this.keyCode!==57&&(t=this.keyCode);let i=0;return this.ctrlKey&&(i|=m),this.altKey&&(i|=_),this.shiftKey&&(i|=b),this.metaKey&&(i|=p),i|=t,i}_computeKeyCodeChord(){let t=0;return this.keyCode!==5&&this.keyCode!==4&&this.keyCode!==6&&this.keyCode!==57&&(t=this.keyCode),new I.KeyCodeChord(this.ctrlKey,this.shiftKey,this.altKey,this.metaKey,t)}}e.StandardKeyboardEvent=n}),define(ne[77],se([1,0,64,441,16]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandardWheelEvent=e.StandardMouseEvent=void 0;class E{constructor(_,b){this.timestamp=Date.now(),this.browserEvent=b,this.leftButton=b.button===0,this.middleButton=b.button===1,this.rightButton=b.button===2,this.buttons=b.buttons,this.target=b.target,this.detail=b.detail||1,b.type==="dblclick"&&(this.detail=2),this.ctrlKey=b.ctrlKey,this.shiftKey=b.shiftKey,this.altKey=b.altKey,this.metaKey=b.metaKey,typeof b.pageX=="number"?(this.posx=b.pageX,this.posy=b.pageY):(this.posx=b.clientX+this.target.ownerDocument.body.scrollLeft+this.target.ownerDocument.documentElement.scrollLeft,this.posy=b.clientY+this.target.ownerDocument.body.scrollTop+this.target.ownerDocument.documentElement.scrollTop);const p=k.IframeUtils.getPositionOfChildWindowRelativeToAncestorWindow(_,b.view);this.posx-=p.left,this.posy-=p.top}preventDefault(){this.browserEvent.preventDefault()}stopPropagation(){this.browserEvent.stopPropagation()}}e.StandardMouseEvent=E;class y{constructor(_,b=0,p=0){this.browserEvent=_||null,this.target=_?_.target||_.targetNode||_.srcElement:null,this.deltaY=p,this.deltaX=b;let n=!1;if(d.isChrome){const o=navigator.userAgent.match(/Chrome\/(\d+)/);n=(o?parseInt(o[1]):123)<=122}if(_){const o=_,t=_,i=_.view?.devicePixelRatio||1;if(typeof o.wheelDeltaY<"u")n?this.deltaY=o.wheelDeltaY/(120*i):this.deltaY=o.wheelDeltaY/120;else if(typeof t.VERTICAL_AXIS<"u"&&t.axis===t.VERTICAL_AXIS)this.deltaY=-t.detail/3;else if(_.type==="wheel"){const s=_;s.deltaMode===s.DOM_DELTA_LINE?d.isFirefox&&!I.isMacintosh?this.deltaY=-_.deltaY/3:this.deltaY=-_.deltaY:this.deltaY=-_.deltaY/40}if(typeof o.wheelDeltaX<"u")d.isSafari&&I.isWindows?this.deltaX=-(o.wheelDeltaX/120):n?this.deltaX=o.wheelDeltaX/(120*i):this.deltaX=o.wheelDeltaX/120;else if(typeof t.HORIZONTAL_AXIS<"u"&&t.axis===t.HORIZONTAL_AXIS)this.deltaX=-_.detail/3;else if(_.type==="wheel"){const s=_;s.deltaMode===s.DOM_DELTA_LINE?d.isFirefox&&!I.isMacintosh?this.deltaX=-_.deltaX/3:this.deltaX=-_.deltaX:this.deltaX=-_.deltaX/40}this.deltaY===0&&this.deltaX===0&&_.wheelDelta&&(n?this.deltaY=_.wheelDelta/(120*i):this.deltaY=_.wheelDelta/120)}}preventDefault(){this.browserEvent?.preventDefault()}stopPropagation(){this.browserEvent?.stopPropagation()}}e.StandardWheelEvent=y}),define(ne[14],se([1,0,18,8,6,2,16,301]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CancelableAsyncIterableObject=e.AsyncIterableObject=e.Promises=e.DeferredPromise=e.GlobalIdleValue=e.AbstractIdleValue=e._runWhenIdle=e.runWhenGlobalIdle=e.RunOnceScheduler=e.IntervalTimer=e.TimeoutTimer=e.ThrottledDelayer=e.Delayer=e.Throttler=void 0,e.isThenable=_,e.createCancelablePromise=b,e.raceCancellation=p,e.timeout=g,e.disposableTimeout=c,e.first=l,e.createCancelableAsyncIterable=L;function _(D){return!!D&&typeof D.then=="function"}function b(D){const T=new d.CancellationTokenSource,M=D(T.token),A=new Promise((P,N)=>{const O=T.token.onCancellationRequested(()=>{O.dispose(),N(new k.CancellationError)});Promise.resolve(M).then(F=>{O.dispose(),T.dispose(),P(F)},F=>{O.dispose(),T.dispose(),N(F)})});return new class{cancel(){T.cancel(),T.dispose()}then(P,N){return A.then(P,N)}catch(P){return this.then(void 0,P)}finally(P){return A.finally(P)}}}function p(D,T,M){return new Promise((A,P)=>{const N=T.onCancellationRequested(()=>{N.dispose(),A(M)});D.then(A,P).finally(()=>N.dispose())})}class n{constructor(){this.isDisposed=!1,this.activePromise=null,this.queuedPromise=null,this.queuedPromiseFactory=null}queue(T){if(this.isDisposed)return Promise.reject(new Error("Throttler is disposed"));if(this.activePromise){if(this.queuedPromiseFactory=T,!this.queuedPromise){const M=()=>{if(this.queuedPromise=null,this.isDisposed)return;const A=this.queue(this.queuedPromiseFactory);return this.queuedPromiseFactory=null,A};this.queuedPromise=new Promise(A=>{this.activePromise.then(M,M).then(A)})}return new Promise((M,A)=>{this.queuedPromise.then(M,A)})}return this.activePromise=T(),new Promise((M,A)=>{this.activePromise.then(P=>{this.activePromise=null,M(P)},P=>{this.activePromise=null,A(P)})})}dispose(){this.isDisposed=!0}}e.Throttler=n;const o=(D,T)=>{let M=!0;const A=setTimeout(()=>{M=!1,T()},D);return{isTriggered:()=>M,dispose:()=>{clearTimeout(A),M=!1}}},t=D=>{let T=!0;return queueMicrotask(()=>{T&&(T=!1,D())}),{isTriggered:()=>T,dispose:()=>{T=!1}}};class i{constructor(T){this.defaultDelay=T,this.deferred=null,this.completionPromise=null,this.doResolve=null,this.doReject=null,this.task=null}trigger(T,M=this.defaultDelay){this.task=T,this.cancelTimeout(),this.completionPromise||(this.completionPromise=new Promise((P,N)=>{this.doResolve=P,this.doReject=N}).then(()=>{if(this.completionPromise=null,this.doResolve=null,this.task){const P=this.task;return this.task=null,P()}}));const A=()=>{this.deferred=null,this.doResolve?.(null)};return this.deferred=M===m.MicrotaskDelay?t(A):o(M,A),this.completionPromise}isTriggered(){return!!this.deferred?.isTriggered()}cancel(){this.cancelTimeout(),this.completionPromise&&(this.doReject?.(new k.CancellationError),this.completionPromise=null)}cancelTimeout(){this.deferred?.dispose(),this.deferred=null}dispose(){this.cancel()}}e.Delayer=i;class s{constructor(T){this.delayer=new i(T),this.throttler=new n}trigger(T,M){return this.delayer.trigger(()=>this.throttler.queue(T),M)}cancel(){this.delayer.cancel()}dispose(){this.delayer.dispose(),this.throttler.dispose()}}e.ThrottledDelayer=s;function g(D,T){return T?new Promise((M,A)=>{const P=setTimeout(()=>{N.dispose(),M()},D),N=T.onCancellationRequested(()=>{clearTimeout(P),N.dispose(),A(new k.CancellationError)})}):b(M=>g(D,M))}function c(D,T=0,M){const A=setTimeout(()=>{D(),M&&P.dispose()},T),P=(0,E.toDisposable)(()=>{clearTimeout(A),M?.deleteAndLeak(P)});return M?.add(P),P}function l(D,T=A=>!!A,M=null){let A=0;const P=D.length,N=()=>{if(A>=P)return Promise.resolve(M);const O=D[A++];return Promise.resolve(O()).then(x=>T(x)?Promise.resolve(x):N())};return N()}class a{constructor(T,M){this._isDisposed=!1,this._token=-1,typeof T=="function"&&typeof M=="number"&&this.setIfNotSet(T,M)}dispose(){this.cancel(),this._isDisposed=!0}cancel(){this._token!==-1&&(clearTimeout(this._token),this._token=-1)}cancelAndSet(T,M){if(this._isDisposed)throw new k.BugIndicatingError("Calling 'cancelAndSet' on a disposed TimeoutTimer");this.cancel(),this._token=setTimeout(()=>{this._token=-1,T()},M)}setIfNotSet(T,M){if(this._isDisposed)throw new k.BugIndicatingError("Calling 'setIfNotSet' on a disposed TimeoutTimer");this._token===-1&&(this._token=setTimeout(()=>{this._token=-1,T()},M))}}e.TimeoutTimer=a;class r{constructor(){this.disposable=void 0,this.isDisposed=!1}cancel(){this.disposable?.dispose(),this.disposable=void 0}cancelAndSet(T,M,A=globalThis){if(this.isDisposed)throw new k.BugIndicatingError("Calling 'cancelAndSet' on a disposed IntervalTimer");this.cancel();const P=A.setInterval(()=>{T()},M);this.disposable=(0,E.toDisposable)(()=>{A.clearInterval(P),this.disposable=void 0})}dispose(){this.cancel(),this.isDisposed=!0}}e.IntervalTimer=r;class u{constructor(T,M){this.timeoutToken=-1,this.runner=T,this.timeout=M,this.timeoutHandler=this.onTimeout.bind(this)}dispose(){this.cancel(),this.runner=null}cancel(){this.isScheduled()&&(clearTimeout(this.timeoutToken),this.timeoutToken=-1)}schedule(T=this.timeout){this.cancel(),this.timeoutToken=setTimeout(this.timeoutHandler,T)}get delay(){return this.timeout}set delay(T){this.timeout=T}isScheduled(){return this.timeoutToken!==-1}onTimeout(){this.timeoutToken=-1,this.runner&&this.doRun()}doRun(){this.runner?.()}}e.RunOnceScheduler=u,function(){typeof globalThis.requestIdleCallback!="function"||typeof globalThis.cancelIdleCallback!="function"?e._runWhenIdle=(D,T)=>{(0,y.setTimeout0)(()=>{if(M)return;const A=Date.now()+15;T(Object.freeze({didTimeout:!0,timeRemaining(){return Math.max(0,A-Date.now())}}))});let M=!1;return{dispose(){M||(M=!0)}}}:e._runWhenIdle=(D,T,M)=>{const A=D.requestIdleCallback(T,typeof M=="number"?{timeout:M}:void 0);let P=!1;return{dispose(){P||(P=!0,D.cancelIdleCallback(A))}}},e.runWhenGlobalIdle=D=>(0,e._runWhenIdle)(globalThis,D)}();class C{constructor(T,M){this._didRun=!1,this._executor=()=>{try{this._value=M()}catch(A){this._error=A}finally{this._didRun=!0}},this._handle=(0,e._runWhenIdle)(T,()=>this._executor())}dispose(){this._handle.dispose()}get value(){if(this._didRun||(this._handle.dispose(),this._executor()),this._error)throw this._error;return this._value}get isInitialized(){return this._didRun}}e.AbstractIdleValue=C;class f extends C{constructor(T){super(globalThis,T)}}e.GlobalIdleValue=f;class h{get isRejected(){return this.outcome?.outcome===1}get isSettled(){return!!this.outcome}constructor(){this.p=new Promise((T,M)=>{this.completeCallback=T,this.errorCallback=M})}complete(T){return new Promise(M=>{this.completeCallback(T),this.outcome={outcome:0,value:T},M()})}error(T){return new Promise(M=>{this.errorCallback(T),this.outcome={outcome:1,value:T},M()})}cancel(){return this.error(new k.CancellationError)}}e.DeferredPromise=h;var v;(function(D){async function T(A){let P;const N=await Promise.all(A.map(O=>O.then(F=>F,F=>{P||(P=F)})));if(typeof P<"u")throw P;return N}D.settled=T;function M(A){return new Promise(async(P,N)=>{try{await A(P,N)}catch(O){N(O)}})}D.withAsyncBody=M})(v||(e.Promises=v={}));class w{static fromArray(T){return new w(M=>{M.emitMany(T)})}static fromPromise(T){return new w(async M=>{M.emitMany(await T)})}static fromPromises(T){return new w(async M=>{await Promise.all(T.map(async A=>M.emitOne(await A)))})}static merge(T){return new w(async M=>{await Promise.all(T.map(async A=>{for await(const P of A)M.emitOne(P)}))})}static{this.EMPTY=w.fromArray([])}constructor(T,M){this._state=0,this._results=[],this._error=null,this._onReturn=M,this._onStateChanged=new I.Emitter,queueMicrotask(async()=>{const A={emitOne:P=>this.emitOne(P),emitMany:P=>this.emitMany(P),reject:P=>this.reject(P)};try{await Promise.resolve(T(A)),this.resolve()}catch(P){this.reject(P)}finally{A.emitOne=void 0,A.emitMany=void 0,A.reject=void 0}})}[Symbol.asyncIterator](){let T=0;return{next:async()=>{do{if(this._state===2)throw this._error;if(T(this._onReturn?.(),{done:!0,value:void 0})}}static map(T,M){return new w(async A=>{for await(const P of T)A.emitOne(M(P))})}map(T){return w.map(this,T)}static filter(T,M){return new w(async A=>{for await(const P of T)M(P)&&A.emitOne(P)})}filter(T){return w.filter(this,T)}static coalesce(T){return w.filter(T,M=>!!M)}coalesce(){return w.coalesce(this)}static async toPromise(T){const M=[];for await(const A of T)M.push(A);return M}toPromise(){return w.toPromise(this)}emitOne(T){this._state===0&&(this._results.push(T),this._onStateChanged.fire())}emitMany(T){this._state===0&&(this._results=this._results.concat(T),this._onStateChanged.fire())}resolve(){this._state===0&&(this._state=1,this._onStateChanged.fire())}reject(T){this._state===0&&(this._state=2,this._error=T,this._onStateChanged.fire())}}e.AsyncIterableObject=w;class S extends w{constructor(T,M){super(M),this._source=T}cancel(){this._source.cancel()}}e.CancelableAsyncIterableObject=S;function L(D){const T=new d.CancellationTokenSource,M=D(T.token);return new S(T,async A=>{const P=T.token.onCancellationRequested(()=>{P.dispose(),T.dispose(),A.reject(new k.CancellationError)});try{for await(const N of M){if(T.token.isCancellationRequested)return;A.emitOne(N)}P.dispose(),T.dispose()}catch(N){P.dispose(),T.dispose(),A.reject(N)}})}}),define(ne[626],se([1,0,14,2]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ScrollbarVisibilityController=void 0;class I extends k.Disposable{constructor(y,m,_){super(),this._visibility=y,this._visibleClassName=m,this._invisibleClassName=_,this._domNode=null,this._isVisible=!1,this._isNeeded=!1,this._rawShouldBeVisible=!1,this._shouldBeVisible=!1,this._revealTimer=this._register(new d.TimeoutTimer)}setVisibility(y){this._visibility!==y&&(this._visibility=y,this._updateShouldBeVisible())}setShouldBeVisible(y){this._rawShouldBeVisible=y,this._updateShouldBeVisible()}_applyVisibilitySetting(){return this._visibility===2?!1:this._visibility===3?!0:this._rawShouldBeVisible}_updateShouldBeVisible(){const y=this._applyVisibilitySetting();this._shouldBeVisible!==y&&(this._shouldBeVisible=y,this.ensureVisibility())}setIsNeeded(y){this._isNeeded!==y&&(this._isNeeded=y,this.ensureVisibility())}setDomNode(y){this._domNode=y,this._domNode.setClassName(this._invisibleClassName),this.setShouldBeVisible(!1)}ensureVisibility(){if(!this._isNeeded){this._hide(!1);return}this._shouldBeVisible?this._reveal():this._hide(!0)}_reveal(){this._isVisible||(this._isVisible=!0,this._revealTimer.setIfNotSet(()=>{this._domNode?.setClassName(this._visibleClassName)},0))}_hide(y){this._revealTimer.cancel(),this._isVisible&&(this._isVisible=!1,this._domNode?.setClassName(this._invisibleClassName+(y?" fade":"")))}}e.ScrollbarVisibilityController=I}),define(ne[249],se([1,0,159,13,14,301,190,6,53]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IndexTreeModel=void 0,e.isFilterResult=b,e.getVisibleState=p;function b(t){return typeof t=="object"&&"visibility"in t&&"data"in t}function p(t){switch(t){case!0:return 1;case!1:return 0;default:return t}}function n(t){return typeof t.collapsible=="boolean"}class o{constructor(i,s,g,c={}){this.user=i,this.list=s,this.rootRef=[],this.eventBufferer=new m.EventBufferer,this._onDidChangeCollapseState=new m.Emitter,this.onDidChangeCollapseState=this.eventBufferer.wrapEvent(this._onDidChangeCollapseState.event),this._onDidChangeRenderNodeCount=new m.Emitter,this.onDidChangeRenderNodeCount=this.eventBufferer.wrapEvent(this._onDidChangeRenderNodeCount.event),this._onDidSplice=new m.Emitter,this.onDidSplice=this._onDidSplice.event,this.refilterDelayer=new I.Delayer(E.MicrotaskDelay),this.collapseByDefault=typeof c.collapseByDefault>"u"?!1:c.collapseByDefault,this.allowNonCollapsibleParents=c.allowNonCollapsibleParents??!1,this.filter=c.filter,this.autoExpandSingleChildren=typeof c.autoExpandSingleChildren>"u"?!1:c.autoExpandSingleChildren,this.root={parent:void 0,element:g,children:[],depth:0,visibleChildrenCount:0,visibleChildIndex:-1,collapsible:!1,collapsed:!1,renderNodeCount:0,visibility:1,visible:!0,filterData:void 0}}splice(i,s,g=_.Iterable.empty(),c={}){if(i.length===0)throw new d.TreeError(this.user,"Invalid tree location");c.diffIdentityProvider?this.spliceSmart(c.diffIdentityProvider,i,s,g,c):this.spliceSimple(i,s,g,c)}spliceSmart(i,s,g,c=_.Iterable.empty(),l,a=l.diffDepth??0){const{parentNode:r}=this.getParentNodeWithListIndex(s);if(!r.lastDiffIds)return this.spliceSimple(s,g,c,l);const u=[...c],C=s[s.length-1],f=new y.LcsDiff({getElements:()=>r.lastDiffIds},{getElements:()=>[...r.children.slice(0,C),...u,...r.children.slice(C+g)].map(L=>i.getId(L.element).toString())}).ComputeDiff(!1);if(f.quitEarly)return r.lastDiffIds=void 0,this.spliceSimple(s,g,u,l);const h=s.slice(0,-1),v=(L,D,T)=>{if(a>0)for(let M=0;MT.originalStart-D.originalStart))v(w,S,w-(L.originalStart+L.originalLength)),w=L.originalStart,S=L.modifiedStart-C,this.spliceSimple([...h,w],L.originalLength,_.Iterable.slice(u,S,S+L.modifiedLength),l);v(w,S,w)}spliceSimple(i,s,g=_.Iterable.empty(),{onDidCreateNode:c,onDidDeleteNode:l,diffIdentityProvider:a}){const{parentNode:r,listIndex:u,revealed:C,visible:f}=this.getParentNodeWithListIndex(i),h=[],v=_.Iterable.map(g,N=>this.createTreeNode(N,r,r.visible?1:0,C,h,c)),w=i[i.length-1];let S=0;for(let N=w;N>=0&&Na.getId(N.element).toString())):r.lastDiffIds=r.children.map(N=>a.getId(N.element).toString()):r.lastDiffIds=void 0;let A=0;for(const N of M)N.visible&&A++;if(A!==0)for(let N=w+L.length;NO+(F.visible?F.renderNodeCount:0),0);this._updateAncestorsRenderNodeCount(r,T-N),this.list.splice(u,N,h)}if(M.length>0&&l){const N=O=>{l(O),O.children.forEach(N)};M.forEach(N)}this._onDidSplice.fire({insertedNodes:L,deletedNodes:M});let P=r;for(;P;){if(P.visibility===2){this.refilterDelayer.trigger(()=>this.refilter());break}P=P.parent}}rerender(i){if(i.length===0)throw new d.TreeError(this.user,"Invalid tree location");const{node:s,listIndex:g,revealed:c}=this.getTreeNodeWithListIndex(i);s.visible&&c&&this.list.splice(g,1,[s])}has(i){return this.hasTreeNode(i)}getListIndex(i){const{listIndex:s,visible:g,revealed:c}=this.getTreeNodeWithListIndex(i);return g&&c?s:-1}getListRenderCount(i){return this.getTreeNode(i).renderNodeCount}isCollapsible(i){return this.getTreeNode(i).collapsible}setCollapsible(i,s){const g=this.getTreeNode(i);typeof s>"u"&&(s=!g.collapsible);const c={collapsible:s};return this.eventBufferer.bufferEvents(()=>this._setCollapseState(i,c))}isCollapsed(i){return this.getTreeNode(i).collapsed}setCollapsed(i,s,g){const c=this.getTreeNode(i);typeof s>"u"&&(s=!c.collapsed);const l={collapsed:s,recursive:g||!1};return this.eventBufferer.bufferEvents(()=>this._setCollapseState(i,l))}_setCollapseState(i,s){const{node:g,listIndex:c,revealed:l}=this.getTreeNodeWithListIndex(i),a=this._setListNodeCollapseState(g,c,l,s);if(g!==this.root&&this.autoExpandSingleChildren&&a&&!n(s)&&g.collapsible&&!g.collapsed&&!s.recursive){let r=-1;for(let u=0;u-1){r=-1;break}else r=u;r>-1&&this._setCollapseState([...i,r],s)}return a}_setListNodeCollapseState(i,s,g,c){const l=this._setNodeCollapseState(i,c,!1);if(!g||!i.visible||!l)return l;const a=i.renderNodeCount,r=this.updateNodeAfterCollapseChange(i),u=a-(s===-1?0:1);return this.list.splice(s+1,u,r.slice(1)),l}_setNodeCollapseState(i,s,g){let c;if(i===this.root?c=!1:(n(s)?(c=i.collapsible!==s.collapsible,i.collapsible=s.collapsible):i.collapsible?(c=i.collapsed!==s.collapsed,i.collapsed=s.collapsed):c=!1,c&&this._onDidChangeCollapseState.fire({node:i,deep:g})),!n(s)&&s.recursive)for(const l of i.children)c=this._setNodeCollapseState(l,s,!0)||c;return c}expandTo(i){this.eventBufferer.bufferEvents(()=>{let s=this.getTreeNode(i);for(;s.parent;)s=s.parent,i=i.slice(0,i.length-1),s.collapsed&&this._setCollapseState(i,{collapsed:!1,recursive:!1})})}refilter(){const i=this.root.renderNodeCount,s=this.updateNodeAfterFilterChange(this.root);this.list.splice(0,i,s),this.refilterDelayer.cancel()}createTreeNode(i,s,g,c,l,a){const r={parent:s,element:i.element,children:[],depth:s.depth+1,visibleChildrenCount:0,visibleChildIndex:-1,collapsible:typeof i.collapsible=="boolean"?i.collapsible:typeof i.collapsed<"u",collapsed:typeof i.collapsed>"u"?this.collapseByDefault:i.collapsed,renderNodeCount:1,visibility:1,visible:!0,filterData:void 0},u=this._filterNode(r,g);r.visibility=u,c&&l.push(r);const C=i.children||_.Iterable.empty(),f=c&&u!==0&&!r.collapsed;let h=0,v=1;for(const w of C){const S=this.createTreeNode(w,r,u,f,l,a);r.children.push(S),v+=S.renderNodeCount,S.visible&&(S.visibleChildIndex=h++)}return this.allowNonCollapsibleParents||(r.collapsible=r.collapsible||r.children.length>0),r.visibleChildrenCount=h,r.visible=u===2?h>0:u===1,r.visible?r.collapsed||(r.renderNodeCount=v):(r.renderNodeCount=0,c&&l.pop()),a?.(r),r}updateNodeAfterCollapseChange(i){const s=i.renderNodeCount,g=[];return this._updateNodeAfterCollapseChange(i,g),this._updateAncestorsRenderNodeCount(i.parent,g.length-s),g}_updateNodeAfterCollapseChange(i,s){if(i.visible===!1)return 0;if(s.push(i),i.renderNodeCount=1,!i.collapsed)for(const g of i.children)i.renderNodeCount+=this._updateNodeAfterCollapseChange(g,s);return this._onDidChangeRenderNodeCount.fire(i),i.renderNodeCount}updateNodeAfterFilterChange(i){const s=i.renderNodeCount,g=[];return this._updateNodeAfterFilterChange(i,i.visible?1:0,g),this._updateAncestorsRenderNodeCount(i.parent,g.length-s),g}_updateNodeAfterFilterChange(i,s,g,c=!0){let l;if(i!==this.root){if(l=this._filterNode(i,s),l===0)return i.visible=!1,i.renderNodeCount=0,!1;c&&g.push(i)}const a=g.length;i.renderNodeCount=i===this.root?0:1;let r=!1;if(!i.collapsed||l!==0){let u=0;for(const C of i.children)r=this._updateNodeAfterFilterChange(C,l,g,c&&!i.collapsed)||r,C.visible&&(C.visibleChildIndex=u++);i.visibleChildrenCount=u}else i.visibleChildrenCount=0;return i!==this.root&&(i.visible=l===2?r:l===1,i.visibility=l),i.visible?i.collapsed||(i.renderNodeCount+=g.length-a):(i.renderNodeCount=0,c&&g.pop()),this._onDidChangeRenderNodeCount.fire(i),i.visible}_updateAncestorsRenderNodeCount(i,s){if(s!==0)for(;i;)i.renderNodeCount+=s,this._onDidChangeRenderNodeCount.fire(i),i=i.parent}_filterNode(i,s){const g=this.filter?this.filter.filter(i.element,s):1;return typeof g=="boolean"?(i.filterData=void 0,g?1:0):b(g)?(i.filterData=g.data,p(g.visibility)):(i.filterData=void 0,p(g))}hasTreeNode(i,s=this.root){if(!i||i.length===0)return!0;const[g,...c]=i;return g<0||g>s.children.length?!1:this.hasTreeNode(c,s.children[g])}getTreeNode(i,s=this.root){if(!i||i.length===0)return s;const[g,...c]=i;if(g<0||g>s.children.length)throw new d.TreeError(this.user,"Invalid tree location");return this.getTreeNode(c,s.children[g])}getTreeNodeWithListIndex(i){if(i.length===0)return{node:this.root,listIndex:-1,revealed:!0,visible:!1};const{parentNode:s,listIndex:g,revealed:c,visible:l}=this.getParentNodeWithListIndex(i),a=i[i.length-1];if(a<0||a>s.children.length)throw new d.TreeError(this.user,"Invalid tree location");const r=s.children[a];return{node:r,listIndex:g,revealed:c,visible:l&&r.visible}}getParentNodeWithListIndex(i,s=this.root,g=0,c=!0,l=!0){const[a,...r]=i;if(a<0||a>s.children.length)throw new d.TreeError(this.user,"Invalid tree location");for(let u=0;u{if(i.element===null)return;const s=i;if(p.add(s.element),this.nodes.set(s.element,s),this.identityProvider){const g=this.identityProvider.getId(s.element).toString();n.add(g),this.nodesByIdentity.set(g,s)}b.onDidCreateNode?.(s)},t=i=>{if(i.element===null)return;const s=i;if(p.has(s.element)||this.nodes.delete(s.element),this.identityProvider){const g=this.identityProvider.getId(s.element).toString();n.has(g)||this.nodesByIdentity.delete(g)}b.onDidDeleteNode?.(s)};this.model.splice([...m,0],Number.MAX_VALUE,_,{...b,onDidCreateNode:o,onDidDeleteNode:t})}preserveCollapseState(m=I.Iterable.empty()){return this.sorter&&(m=[...m].sort(this.sorter.compare.bind(this.sorter))),I.Iterable.map(m,_=>{let b=this.nodes.get(_.element);if(!b&&this.identityProvider){const o=this.identityProvider.getId(_.element).toString();b=this.nodesByIdentity.get(o)}if(!b){let o;return typeof _.collapsed>"u"?o=void 0:_.collapsed===k.ObjectTreeElementCollapseState.Collapsed||_.collapsed===k.ObjectTreeElementCollapseState.PreserveOrCollapsed?o=!0:_.collapsed===k.ObjectTreeElementCollapseState.Expanded||_.collapsed===k.ObjectTreeElementCollapseState.PreserveOrExpanded?o=!1:o=!!_.collapsed,{..._,children:this.preserveCollapseState(_.children),collapsed:o}}const p=typeof _.collapsible=="boolean"?_.collapsible:b.collapsible;let n;return typeof _.collapsed>"u"||_.collapsed===k.ObjectTreeElementCollapseState.PreserveOrCollapsed||_.collapsed===k.ObjectTreeElementCollapseState.PreserveOrExpanded?n=b.collapsed:_.collapsed===k.ObjectTreeElementCollapseState.Collapsed?n=!0:_.collapsed===k.ObjectTreeElementCollapseState.Expanded?n=!1:n=!!_.collapsed,{..._,collapsible:p,collapsed:n,children:this.preserveCollapseState(_.children)}})}rerender(m){const _=this.getElementLocation(m);this.model.rerender(_)}getFirstElementChild(m=null){const _=this.getElementLocation(m);return this.model.getFirstElementChild(_)}has(m){return this.nodes.has(m)}getListIndex(m){const _=this.getElementLocation(m);return this.model.getListIndex(_)}getListRenderCount(m){const _=this.getElementLocation(m);return this.model.getListRenderCount(_)}isCollapsible(m){const _=this.getElementLocation(m);return this.model.isCollapsible(_)}setCollapsible(m,_){const b=this.getElementLocation(m);return this.model.setCollapsible(b,_)}isCollapsed(m){const _=this.getElementLocation(m);return this.model.isCollapsed(_)}setCollapsed(m,_,b){const p=this.getElementLocation(m);return this.model.setCollapsed(p,_,b)}expandTo(m){const _=this.getElementLocation(m);this.model.expandTo(_)}refilter(){this.model.refilter()}getNode(m=null){if(m===null)return this.model.getNode(this.model.rootRef);const _=this.nodes.get(m);if(!_)throw new k.TreeError(this.user,`Tree element not found: ${m}`);return _}getNodeLocation(m){return m.element}getParentNodeLocation(m){if(m===null)throw new k.TreeError(this.user,"Invalid getParentNodeLocation call");const _=this.nodes.get(m);if(!_)throw new k.TreeError(this.user,`Tree element not found: ${m}`);const b=this.model.getNodeLocation(_),p=this.model.getParentNodeLocation(b);return this.model.getNode(p).element}getElementLocation(m){if(m===null)return[];const _=this.nodes.get(m);if(!_)throw new k.TreeError(this.user,`Tree element not found: ${m}`);return this.model.getNodeLocation(_)}}e.ObjectTreeModel=E}),define(ne[627],se([1,0,250,159,13,6,53]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CompressibleObjectTreeModel=e.DefaultElementMapper=e.CompressedObjectTreeModel=void 0,e.compress=_,e.decompress=p;function m(a){const r=[a.element],u=a.incompressible||!1;return{element:{elements:r,incompressible:u},children:y.Iterable.map(y.Iterable.from(a.children),m),collapsible:a.collapsible,collapsed:a.collapsed}}function _(a){const r=[a.element],u=a.incompressible||!1;let C,f;for(;[f,C]=y.Iterable.consume(y.Iterable.from(a.children),2),!(f.length!==1||f[0].incompressible);)a=f[0],r.push(a.element);return{element:{elements:r,incompressible:u},children:y.Iterable.map(y.Iterable.concat(f,C),_),collapsible:a.collapsible,collapsed:a.collapsed}}function b(a,r=0){let u;return rb(C,0)),r===0&&a.element.incompressible?{element:a.element.elements[r],children:u,incompressible:!0,collapsible:a.collapsible,collapsed:a.collapsed}:{element:a.element.elements[r],children:u,collapsible:a.collapsible,collapsed:a.collapsed}}function p(a){return b(a,0)}function n(a,r,u){return a.element===r?{...a,children:u}:{...a,children:y.Iterable.map(y.Iterable.from(a.children),C=>n(C,r,u))}}const o=a=>({getId(r){return r.elements.map(u=>a.getId(u).toString()).join("\0")}});class t{get onDidSplice(){return this.model.onDidSplice}get onDidChangeCollapseState(){return this.model.onDidChangeCollapseState}get onDidChangeRenderNodeCount(){return this.model.onDidChangeRenderNodeCount}constructor(r,u,C={}){this.user=r,this.rootRef=null,this.nodes=new Map,this.model=new d.ObjectTreeModel(r,u,C),this.enabled=typeof C.compressionEnabled>"u"?!0:C.compressionEnabled,this.identityProvider=C.identityProvider}setChildren(r,u=y.Iterable.empty(),C){const f=C.diffIdentityProvider&&o(C.diffIdentityProvider);if(r===null){const P=y.Iterable.map(u,this.enabled?_:m);this._setChildren(null,P,{diffIdentityProvider:f,diffDepth:1/0});return}const h=this.nodes.get(r);if(!h)throw new k.TreeError(this.user,"Unknown compressed tree node");const v=this.model.getNode(h),w=this.model.getParentNodeLocation(h),S=this.model.getNode(w),L=p(v),D=n(L,r,u),T=(this.enabled?_:m)(D),M=C.diffIdentityProvider?(P,N)=>C.diffIdentityProvider.getId(P)===C.diffIdentityProvider.getId(N):void 0;if((0,I.equals)(T.element.elements,v.element.elements,M)){this._setChildren(h,T.children||y.Iterable.empty(),{diffIdentityProvider:f,diffDepth:1});return}const A=S.children.map(P=>P===v?T:P);this._setChildren(S.element,A,{diffIdentityProvider:f,diffDepth:v.depth-S.depth})}isCompressionEnabled(){return this.enabled}setCompressionEnabled(r){if(r===this.enabled)return;this.enabled=r;const C=this.model.getNode().children,f=y.Iterable.map(C,p),h=y.Iterable.map(f,r?_:m);this._setChildren(null,h,{diffIdentityProvider:this.identityProvider,diffDepth:1/0})}_setChildren(r,u,C){const f=new Set,h=w=>{for(const S of w.element.elements)f.add(S),this.nodes.set(S,w.element)},v=w=>{for(const S of w.element.elements)f.has(S)||this.nodes.delete(S)};this.model.setChildren(r,u,{...C,onDidCreateNode:h,onDidDeleteNode:v})}has(r){return this.nodes.has(r)}getListIndex(r){const u=this.getCompressedNode(r);return this.model.getListIndex(u)}getListRenderCount(r){const u=this.getCompressedNode(r);return this.model.getListRenderCount(u)}getNode(r){if(typeof r>"u")return this.model.getNode();const u=this.getCompressedNode(r);return this.model.getNode(u)}getNodeLocation(r){const u=this.model.getNodeLocation(r);return u===null?null:u.elements[u.elements.length-1]}getParentNodeLocation(r){const u=this.getCompressedNode(r),C=this.model.getParentNodeLocation(u);return C===null?null:C.elements[C.elements.length-1]}getFirstElementChild(r){const u=this.getCompressedNode(r);return this.model.getFirstElementChild(u)}isCollapsible(r){const u=this.getCompressedNode(r);return this.model.isCollapsible(u)}setCollapsible(r,u){const C=this.getCompressedNode(r);return this.model.setCollapsible(C,u)}isCollapsed(r){const u=this.getCompressedNode(r);return this.model.isCollapsed(u)}setCollapsed(r,u,C){const f=this.getCompressedNode(r);return this.model.setCollapsed(f,u,C)}expandTo(r){const u=this.getCompressedNode(r);this.model.expandTo(u)}rerender(r){const u=this.getCompressedNode(r);this.model.rerender(u)}refilter(){this.model.refilter()}getCompressedNode(r){if(r===null)return null;const u=this.nodes.get(r);if(!u)throw new k.TreeError(this.user,`Tree element not found: ${r}`);return u}}e.CompressedObjectTreeModel=t;const i=a=>a[a.length-1];e.DefaultElementMapper=i;class s{get element(){return this.node.element===null?null:this.unwrapper(this.node.element)}get children(){return this.node.children.map(r=>new s(this.unwrapper,r))}get depth(){return this.node.depth}get visibleChildrenCount(){return this.node.visibleChildrenCount}get visibleChildIndex(){return this.node.visibleChildIndex}get collapsible(){return this.node.collapsible}get collapsed(){return this.node.collapsed}get visible(){return this.node.visible}get filterData(){return this.node.filterData}constructor(r,u){this.unwrapper=r,this.node=u}}function g(a,r){return{splice(u,C,f){r.splice(u,C,f.map(h=>a.map(h)))},updateElementHeight(u,C){r.updateElementHeight(u,C)}}}function c(a,r){return{...r,identityProvider:r.identityProvider&&{getId(u){return r.identityProvider.getId(a(u))}},sorter:r.sorter&&{compare(u,C){return r.sorter.compare(u.elements[0],C.elements[0])}},filter:r.filter&&{filter(u,C){return r.filter.filter(a(u),C)}}}}class l{get onDidSplice(){return E.Event.map(this.model.onDidSplice,({insertedNodes:r,deletedNodes:u})=>({insertedNodes:r.map(C=>this.nodeMapper.map(C)),deletedNodes:u.map(C=>this.nodeMapper.map(C))}))}get onDidChangeCollapseState(){return E.Event.map(this.model.onDidChangeCollapseState,({node:r,deep:u})=>({node:this.nodeMapper.map(r),deep:u}))}get onDidChangeRenderNodeCount(){return E.Event.map(this.model.onDidChangeRenderNodeCount,r=>this.nodeMapper.map(r))}constructor(r,u,C={}){this.rootRef=null,this.elementMapper=C.elementMapper||e.DefaultElementMapper;const f=h=>this.elementMapper(h.elements);this.nodeMapper=new k.WeakMapper(h=>new s(f,h)),this.model=new t(r,g(this.nodeMapper,u),c(f,C))}setChildren(r,u=y.Iterable.empty(),C={}){this.model.setChildren(r,u,C)}isCompressionEnabled(){return this.model.isCompressionEnabled()}setCompressionEnabled(r){this.model.setCompressionEnabled(r)}has(r){return this.model.has(r)}getListIndex(r){return this.model.getListIndex(r)}getListRenderCount(r){return this.model.getListRenderCount(r)}getNode(r){return this.nodeMapper.map(this.model.getNode(r))}getNodeLocation(r){return r.element}getParentNodeLocation(r){return this.model.getParentNodeLocation(r)}getFirstElementChild(r){const u=this.model.getFirstElementChild(r);return u===null||typeof u>"u"?u:this.elementMapper(u.elements)}isCollapsible(r){return this.model.isCollapsible(r)}setCollapsible(r,u){return this.model.setCollapsible(r,u)}isCollapsed(r){return this.model.isCollapsed(r)}setCollapsed(r,u,C){return this.model.setCollapsed(r,u,C)}expandTo(r){return this.model.expandTo(r)}rerender(r){return this.model.rerender(r)}refilter(){return this.model.refilter()}getCompressedTreeNode(r=null){return this.model.getNode(r)}}e.CompressibleObjectTreeModel=l}),define(ne[348],se([1,0,16]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.platform=e.env=e.cwd=void 0;let k;const I=globalThis.vscode;if(typeof I<"u"&&typeof I.process<"u"){const E=I.process;k={get platform(){return E.platform},get arch(){return E.arch},get env(){return E.env},cwd(){return E.cwd()}}}else typeof process<"u"&&typeof process?.versions?.node=="string"?k={get platform(){return process.platform},get arch(){return process.arch},get env(){return process.env},cwd(){return process.env.VSCODE_CWD||process.cwd()}}:k={get platform(){return d.isWindows?"win32":d.isMacintosh?"darwin":"linux"},get arch(){},get env(){return{}},cwd(){return"/"}};e.cwd=k.cwd,e.env=k.env,e.platform=k.platform}),define(ne[349],se([1,0,348]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isHotReloadEnabled=k,e.registerHotReloadHandler=I;function k(){return d.env&&!!d.env.VSCODE_DEV}function I(m){if(k()){const _=E();return _.add(m),{dispose(){_.delete(m)}}}else return{dispose(){}}}function E(){y||(y=new Set);const m=globalThis;return m.$hotReload_applyNewExports||(m.$hotReload_applyNewExports=_=>{const b={config:{mode:void 0},..._},p=[];for(const n of y){const o=n(b);o&&p.push(o)}if(p.length>0)return n=>{let o=!1;for(const t of p)t(n)&&(o=!0);return o}}),y}let y;k()&&I(({oldExports:m,newSrc:_,config:b})=>{if(b.mode==="patch-prototype")return p=>{for(const n in p){const o=p[n];if(console.log(`[hot-reload] Patching prototype methods of '${n}'`,{exportedItem:o}),typeof o=="function"&&o.prototype){const t=m[n];if(t){for(const i of Object.getOwnPropertyNames(o.prototype)){const s=Object.getOwnPropertyDescriptor(o.prototype,i),g=Object.getOwnPropertyDescriptor(t.prototype,i);s?.value?.toString()!==g?.value?.toString()&&console.log(`[hot-reload] Patching prototype method '${n}.${i}'`),Object.defineProperty(t.prototype,i,s)}p[n]=t}}}return!0}})}),define(ne[171],se([1,0,349,21]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.readHotReloadableExport=I,e.observeHotReloadableExports=E;function I(y,m){return E([y],m),y}function E(y,m){(0,d.isHotReloadEnabled)()&&(0,k.observableSignalFromEvent)("reload",b=>(0,d.registerHotReloadHandler)(({oldExports:p})=>{if([...Object.values(p)].some(n=>y.includes(n)))return n=>(b(void 0),!0)})).read(m)}}),define(ne[99],se([1,0,348]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.sep=e.extname=e.basename=e.dirname=e.relative=e.resolve=e.join=e.normalize=e.posix=e.win32=void 0;const k=65,I=97,E=90,y=122,m=46,_=47,b=92,p=58,n=63;class o extends Error{constructor(h,v,w){let S;typeof v=="string"&&v.indexOf("not ")===0?(S="must not be",v=v.replace(/^not /,"")):S="must be";const L=h.indexOf(".")!==-1?"property":"argument";let D=`The "${h}" ${L} ${S} of type ${v}`;D+=`. Received type ${typeof w}`,super(D),this.code="ERR_INVALID_ARG_TYPE"}}function t(f,h){if(f===null||typeof f!="object")throw new o(h,"Object",f)}function i(f,h){if(typeof f!="string")throw new o(h,"string",f)}const s=d.platform==="win32";function g(f){return f===_||f===b}function c(f){return f===_}function l(f){return f>=k&&f<=E||f>=I&&f<=y}function a(f,h,v,w){let S="",L=0,D=-1,T=0,M=0;for(let A=0;A<=f.length;++A){if(A2){const P=S.lastIndexOf(v);P===-1?(S="",L=0):(S=S.slice(0,P),L=S.length-1-S.lastIndexOf(v)),D=A,T=0;continue}else if(S.length!==0){S="",L=0,D=A,T=0;continue}}h&&(S+=S.length>0?`${v}..`:"..",L=2)}else S.length>0?S+=`${v}${f.slice(D+1,A)}`:S=f.slice(D+1,A),L=A-D-1;D=A,T=0}else M===m&&T!==-1?++T:T=-1}return S}function r(f){return f?`${f[0]==="."?"":"."}${f}`:""}function u(f,h){t(h,"pathObject");const v=h.dir||h.root,w=h.base||`${h.name||""}${r(h.ext)}`;return v?v===h.root?`${v}${w}`:`${v}${f}${w}`:w}e.win32={resolve(...f){let h="",v="",w=!1;for(let S=f.length-1;S>=-1;S--){let L;if(S>=0){if(L=f[S],i(L,`paths[${S}]`),L.length===0)continue}else h.length===0?L=d.cwd():(L=d.env[`=${h}`]||d.cwd(),(L===void 0||L.slice(0,2).toLowerCase()!==h.toLowerCase()&&L.charCodeAt(2)===b)&&(L=`${h}\\`));const D=L.length;let T=0,M="",A=!1;const P=L.charCodeAt(0);if(D===1)g(P)&&(T=1,A=!0);else if(g(P))if(A=!0,g(L.charCodeAt(1))){let N=2,O=N;for(;N2&&g(L.charCodeAt(2))&&(A=!0,T=3));if(M.length>0)if(h.length>0){if(M.toLowerCase()!==h.toLowerCase())continue}else h=M;if(w){if(h.length>0)break}else if(v=`${L.slice(T)}\\${v}`,w=A,A&&h.length>0)break}return v=a(v,!w,"\\",g),w?`${h}\\${v}`:`${h}${v}`||"."},normalize(f){i(f,"path");const h=f.length;if(h===0)return".";let v=0,w,S=!1;const L=f.charCodeAt(0);if(h===1)return c(L)?"\\":f;if(g(L))if(S=!0,g(f.charCodeAt(1))){let T=2,M=T;for(;T2&&g(f.charCodeAt(2))&&(S=!0,v=3));let D=v0&&g(f.charCodeAt(h-1))&&(D+="\\"),w===void 0?S?`\\${D}`:D:S?`${w}\\${D}`:`${w}${D}`},isAbsolute(f){i(f,"path");const h=f.length;if(h===0)return!1;const v=f.charCodeAt(0);return g(v)||h>2&&l(v)&&f.charCodeAt(1)===p&&g(f.charCodeAt(2))},join(...f){if(f.length===0)return".";let h,v;for(let L=0;L0&&(h===void 0?h=v=D:h+=`\\${D}`)}if(h===void 0)return".";let w=!0,S=0;if(typeof v=="string"&&g(v.charCodeAt(0))){++S;const L=v.length;L>1&&g(v.charCodeAt(1))&&(++S,L>2&&(g(v.charCodeAt(2))?++S:w=!1))}if(w){for(;S=2&&(h=`\\${h.slice(S)}`)}return e.win32.normalize(h)},relative(f,h){if(i(f,"from"),i(h,"to"),f===h)return"";const v=e.win32.resolve(f),w=e.win32.resolve(h);if(v===w||(f=v.toLowerCase(),h=w.toLowerCase(),f===h))return"";let S=0;for(;SS&&f.charCodeAt(L-1)===b;)L--;const D=L-S;let T=0;for(;TT&&h.charCodeAt(M-1)===b;)M--;const A=M-T,P=DP){if(h.charCodeAt(T+O)===b)return w.slice(T+O+1);if(O===2)return w.slice(T+O)}D>P&&(f.charCodeAt(S+O)===b?N=O:O===2&&(N=3)),N===-1&&(N=0)}let F="";for(O=S+N+1;O<=L;++O)(O===L||f.charCodeAt(O)===b)&&(F+=F.length===0?"..":"\\..");return T+=N,F.length>0?`${F}${w.slice(T,M)}`:(w.charCodeAt(T)===b&&++T,w.slice(T,M))},toNamespacedPath(f){if(typeof f!="string"||f.length===0)return f;const h=e.win32.resolve(f);if(h.length<=2)return f;if(h.charCodeAt(0)===b){if(h.charCodeAt(1)===b){const v=h.charCodeAt(2);if(v!==n&&v!==m)return`\\\\?\\UNC\\${h.slice(2)}`}}else if(l(h.charCodeAt(0))&&h.charCodeAt(1)===p&&h.charCodeAt(2)===b)return`\\\\?\\${h}`;return f},dirname(f){i(f,"path");const h=f.length;if(h===0)return".";let v=-1,w=0;const S=f.charCodeAt(0);if(h===1)return g(S)?f:".";if(g(S)){if(v=w=1,g(f.charCodeAt(1))){let T=2,M=T;for(;T2&&g(f.charCodeAt(2))?3:2,w=v);let L=-1,D=!0;for(let T=h-1;T>=w;--T)if(g(f.charCodeAt(T))){if(!D){L=T;break}}else D=!1;if(L===-1){if(v===-1)return".";L=v}return f.slice(0,L)},basename(f,h){h!==void 0&&i(h,"suffix"),i(f,"path");let v=0,w=-1,S=!0,L;if(f.length>=2&&l(f.charCodeAt(0))&&f.charCodeAt(1)===p&&(v=2),h!==void 0&&h.length>0&&h.length<=f.length){if(h===f)return"";let D=h.length-1,T=-1;for(L=f.length-1;L>=v;--L){const M=f.charCodeAt(L);if(g(M)){if(!S){v=L+1;break}}else T===-1&&(S=!1,T=L+1),D>=0&&(M===h.charCodeAt(D)?--D===-1&&(w=L):(D=-1,w=T))}return v===w?w=T:w===-1&&(w=f.length),f.slice(v,w)}for(L=f.length-1;L>=v;--L)if(g(f.charCodeAt(L))){if(!S){v=L+1;break}}else w===-1&&(S=!1,w=L+1);return w===-1?"":f.slice(v,w)},extname(f){i(f,"path");let h=0,v=-1,w=0,S=-1,L=!0,D=0;f.length>=2&&f.charCodeAt(1)===p&&l(f.charCodeAt(0))&&(h=w=2);for(let T=f.length-1;T>=h;--T){const M=f.charCodeAt(T);if(g(M)){if(!L){w=T+1;break}continue}S===-1&&(L=!1,S=T+1),M===m?v===-1?v=T:D!==1&&(D=1):v!==-1&&(D=-1)}return v===-1||S===-1||D===0||D===1&&v===S-1&&v===w+1?"":f.slice(v,S)},format:u.bind(null,"\\"),parse(f){i(f,"path");const h={root:"",dir:"",base:"",ext:"",name:""};if(f.length===0)return h;const v=f.length;let w=0,S=f.charCodeAt(0);if(v===1)return g(S)?(h.root=h.dir=f,h):(h.base=h.name=f,h);if(g(S)){if(w=1,g(f.charCodeAt(1))){let N=2,O=N;for(;N0&&(h.root=f.slice(0,w));let L=-1,D=w,T=-1,M=!0,A=f.length-1,P=0;for(;A>=w;--A){if(S=f.charCodeAt(A),g(S)){if(!M){D=A+1;break}continue}T===-1&&(M=!1,T=A+1),S===m?L===-1?L=A:P!==1&&(P=1):L!==-1&&(P=-1)}return T!==-1&&(L===-1||P===0||P===1&&L===T-1&&L===D+1?h.base=h.name=f.slice(D,T):(h.name=f.slice(D,L),h.base=f.slice(D,T),h.ext=f.slice(L,T))),D>0&&D!==w?h.dir=f.slice(0,D-1):h.dir=h.root,h},sep:"\\",delimiter:";",win32:null,posix:null};const C=(()=>{if(s){const f=/\\/g;return()=>{const h=d.cwd().replace(f,"/");return h.slice(h.indexOf("/"))}}return()=>d.cwd()})();e.posix={resolve(...f){let h="",v=!1;for(let w=f.length-1;w>=-1&&!v;w--){const S=w>=0?f[w]:C();i(S,`paths[${w}]`),S.length!==0&&(h=`${S}/${h}`,v=S.charCodeAt(0)===_)}return h=a(h,!v,"/",c),v?`/${h}`:h.length>0?h:"."},normalize(f){if(i(f,"path"),f.length===0)return".";const h=f.charCodeAt(0)===_,v=f.charCodeAt(f.length-1)===_;return f=a(f,!h,"/",c),f.length===0?h?"/":v?"./":".":(v&&(f+="/"),h?`/${f}`:f)},isAbsolute(f){return i(f,"path"),f.length>0&&f.charCodeAt(0)===_},join(...f){if(f.length===0)return".";let h;for(let v=0;v0&&(h===void 0?h=w:h+=`/${w}`)}return h===void 0?".":e.posix.normalize(h)},relative(f,h){if(i(f,"from"),i(h,"to"),f===h||(f=e.posix.resolve(f),h=e.posix.resolve(h),f===h))return"";const v=1,w=f.length,S=w-v,L=1,D=h.length-L,T=ST){if(h.charCodeAt(L+A)===_)return h.slice(L+A+1);if(A===0)return h.slice(L+A)}else S>T&&(f.charCodeAt(v+A)===_?M=A:A===0&&(M=0));let P="";for(A=v+M+1;A<=w;++A)(A===w||f.charCodeAt(A)===_)&&(P+=P.length===0?"..":"/..");return`${P}${h.slice(L+M)}`},toNamespacedPath(f){return f},dirname(f){if(i(f,"path"),f.length===0)return".";const h=f.charCodeAt(0)===_;let v=-1,w=!0;for(let S=f.length-1;S>=1;--S)if(f.charCodeAt(S)===_){if(!w){v=S;break}}else w=!1;return v===-1?h?"/":".":h&&v===1?"//":f.slice(0,v)},basename(f,h){h!==void 0&&i(h,"ext"),i(f,"path");let v=0,w=-1,S=!0,L;if(h!==void 0&&h.length>0&&h.length<=f.length){if(h===f)return"";let D=h.length-1,T=-1;for(L=f.length-1;L>=0;--L){const M=f.charCodeAt(L);if(M===_){if(!S){v=L+1;break}}else T===-1&&(S=!1,T=L+1),D>=0&&(M===h.charCodeAt(D)?--D===-1&&(w=L):(D=-1,w=T))}return v===w?w=T:w===-1&&(w=f.length),f.slice(v,w)}for(L=f.length-1;L>=0;--L)if(f.charCodeAt(L)===_){if(!S){v=L+1;break}}else w===-1&&(S=!1,w=L+1);return w===-1?"":f.slice(v,w)},extname(f){i(f,"path");let h=-1,v=0,w=-1,S=!0,L=0;for(let D=f.length-1;D>=0;--D){const T=f.charCodeAt(D);if(T===_){if(!S){v=D+1;break}continue}w===-1&&(S=!1,w=D+1),T===m?h===-1?h=D:L!==1&&(L=1):h!==-1&&(L=-1)}return h===-1||w===-1||L===0||L===1&&h===w-1&&h===v+1?"":f.slice(h,w)},format:u.bind(null,"/"),parse(f){i(f,"path");const h={root:"",dir:"",base:"",ext:"",name:""};if(f.length===0)return h;const v=f.charCodeAt(0)===_;let w;v?(h.root="/",w=1):w=0;let S=-1,L=0,D=-1,T=!0,M=f.length-1,A=0;for(;M>=w;--M){const P=f.charCodeAt(M);if(P===_){if(!T){L=M+1;break}continue}D===-1&&(T=!1,D=M+1),P===m?S===-1?S=M:A!==1&&(A=1):S!==-1&&(A=-1)}if(D!==-1){const P=L===0&&v?1:L;S===-1||A===0||A===1&&S===D-1&&S===L+1?h.base=h.name=f.slice(P,D):(h.name=f.slice(P,S),h.base=f.slice(P,D),h.ext=f.slice(S,D))}return L>0?h.dir=f.slice(0,L-1):v&&(h.dir="/"),h},sep:"/",delimiter:":",win32:null,posix:null},e.posix.win32=e.win32.win32=e.win32,e.posix.posix=e.win32.posix=e.posix,e.normalize=s?e.win32.normalize:e.posix.normalize,e.join=s?e.win32.join:e.posix.join,e.resolve=s?e.win32.resolve:e.posix.resolve,e.relative=s?e.win32.relative:e.posix.relative,e.dirname=s?e.win32.dirname:e.posix.dirname,e.basename=s?e.win32.basename:e.posix.basename,e.extname=s?e.win32.extname:e.posix.extname,e.sep=s?e.win32.sep:e.posix.sep}),define(ne[251],se([1,0,99,16,11]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isPathSeparator=E,e.toSlashes=y,e.toPosixPath=m,e.getRoot=_,e.isEqualOrParent=b,e.isWindowsDriveLetter=p,e.hasDriveLetter=n;function E(o){return o===47||o===92}function y(o){return o.replace(/[\\/]/g,d.posix.sep)}function m(o){return o.indexOf("/")===-1&&(o=y(o)),/^[a-zA-Z]:(\/|$)/.test(o)&&(o="/"+o),o}function _(o,t=d.posix.sep){if(!o)return"";const i=o.length,s=o.charCodeAt(0);if(E(s)){if(E(o.charCodeAt(1))&&!E(o.charCodeAt(2))){let c=3;const l=c;for(;co.length)return!1;if(i){if(!(0,I.startsWithIgnoreCase)(o,t))return!1;if(t.length===o.length)return!0;let c=t.length;return t.charAt(t.length-1)===s&&c--,o.charAt(c)===s}return t.charAt(t.length-1)!==s&&(t+=s),o.indexOf(t)===0}function p(o){return o>=65&&o<=90||o>=97&&o<=122}function n(o,t=k.isWindows){return t?p(o.charCodeAt(0))&&o.charCodeAt(1)===58:!1}}),define(ne[628],se([1,0,82,99,16,11]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.scoreFuzzy2=m,e.prepareQuery=s,e.pieceToQuery=c;const y=[void 0,[]];function m(l,a,r=0,u=0){const C=a;return C.values&&C.values.length>1?_(l,C.values,r,u):b(l,a,r,u)}function _(l,a,r,u){let C=0;const f=[];for(const h of a){const[v,w]=b(l,h,r,u);if(typeof v!="number")return y;C+=v,f.push(...w)}return[C,n(f)]}function b(l,a,r,u){const C=(0,d.fuzzyScore)(a.original,a.originalLowercase,r,l,l.toLowerCase(),u,{firstMatchCanBeWeak:!0,boostFullMatch:!0});return C?[C[0],(0,d.createMatches)(C)]:y}const p=Object.freeze({score:0});function n(l){const a=l.sort((C,f)=>C.start-f.start),r=[];let u;for(const C of a)!u||!o(u,C)?(u=C,r.push(C)):(u.start=Math.min(u.start,C.start),u.end=Math.max(u.end,C.end));return r}function o(l,a){return!(l.end=0,h=t(l);let v;const w=l.split(i);if(w.length>1)for(const S of w){const L=t(S),{pathNormalized:D,normalized:T,normalizedLowercase:M}=g(S);T&&(v||(v=[]),v.push({original:S,originalLowercase:S.toLowerCase(),pathNormalized:D,normalized:T,normalizedLowercase:M,expectContiguousMatch:L}))}return{original:l,originalLowercase:a,pathNormalized:r,normalized:u,normalizedLowercase:C,values:v,containsPathSeparator:f,expectContiguousMatch:h}}function g(l){let a;I.isWindows?a=l.replace(/\//g,k.sep):a=l.replace(/\\/g,k.sep);const r=(0,E.stripWildcards)(a).replace(/\s|"/g,"");return{pathNormalized:a,normalized:r,normalizedLowercase:r.toLowerCase()}}function c(l){return Array.isArray(l)?s(l.map(a=>a.original).join(i)):s(l.original)}}),define(ne[350],se([1,0,14,251,45,99,16,11]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GLOB_SPLIT=e.GLOBSTAR=void 0,e.splitGlobAware=o,e.match=M,e.parse=A,e.isRelativePattern=P,e.GLOBSTAR="**",e.GLOB_SPLIT="/";const _="[/\\\\]",b="[^/\\\\]",p=/\//g;function n(x,W){switch(x){case 0:return"";case 1:return`${b}*?`;default:return`(?:${_}|${b}+${_}${W?`|${_}${b}+`:""})*?`}}function o(x,W){if(!x)return[];const V=[];let q=!1,H=!1,z="";for(const U of x){switch(U){case W:if(!q&&!H){V.push(z),z="";continue}break;case"{":q=!0;break;case"}":q=!1;break;case"[":H=!0;break;case"]":H=!1;break}z+=U}return z&&V.push(z),V}function t(x){if(!x)return"";let W="";const V=o(x,e.GLOB_SPLIT);if(V.every(q=>q===e.GLOBSTAR))W=".*";else{let q=!1;V.forEach((H,z)=>{if(H===e.GLOBSTAR){if(q)return;W+=n(2,z===V.length-1)}else{let U=!1,j="",Y=!1,G="";for(const K of H){if(K!=="}"&&U){j+=K;continue}if(Y&&(K!=="]"||!G)){let R;K==="-"?R=K:(K==="^"||K==="!")&&!G?R="^":K===e.GLOB_SPLIT?R="":R=(0,m.escapeRegExpCharacters)(K),G+=R;continue}switch(K){case"{":U=!0;continue;case"[":Y=!0;continue;case"}":{const J=`(?:${o(j,",").map(ie=>t(ie)).join("|")})`;W+=J,U=!1,j="";break}case"]":{W+="["+G+"]",Y=!1,G="";break}case"?":W+=b;continue;case"*":W+=n(1);continue;default:W+=(0,m.escapeRegExpCharacters)(K)}}zf(j,W)).filter(j=>j!==C),x),q=V.length;if(!q)return C;if(q===1)return V[0];const H=function(j,Y){for(let G=0,K=V.length;G!!j.allBasenames);z&&(H.allBasenames=z.allBasenames);const U=V.reduce((j,Y)=>Y.allPaths?j.concat(Y.allPaths):j,[]);return U.length&&(H.allPaths=U),H}function D(x,W,V){const q=E.sep===E.posix.sep,H=q?x:x.replace(p,E.sep),z=E.sep+H,U=E.posix.sep+x;let j;return V?j=function(Y,G){return typeof Y=="string"&&(Y===H||Y.endsWith(z)||!q&&(Y===x||Y.endsWith(U)))?W:null}:j=function(Y,G){return typeof Y=="string"&&(Y===H||!q&&Y===x)?W:null},j.allPaths=[(V?"*/":"./")+x],j}function T(x){try{const W=new RegExp(`^${t(x)}$`);return function(V){return W.lastIndex=0,typeof V=="string"&&W.test(V)?x:null}}catch{return C}}function M(x,W,V){return!x||typeof W!="string"?!1:A(x)(W,void 0,V)}function A(x,W={}){if(!x)return u;if(typeof x=="string"||P(x)){const V=f(x,W);if(V===C)return u;const q=function(H,z){return!!V(H,z)};return V.allBasenames&&(q.allBasenames=V.allBasenames),V.allPaths&&(q.allPaths=V.allPaths),q}return N(x,W)}function P(x){const W=x;return W?typeof W.base=="string"&&typeof W.pattern=="string":!1}function N(x,W){const V=F(Object.getOwnPropertyNames(x).map(j=>O(j,x[j],W)).filter(j=>j!==C)),q=V.length;if(!q)return C;if(!V.some(j=>!!j.requiresSiblings)){if(q===1)return V[0];const j=function(K,R){let J;for(let ie=0,ue=V.length;ie{for(const ie of J){const ue=await ie;if(typeof ue=="string")return ue}return null})():null},Y=V.find(K=>!!K.allBasenames);Y&&(j.allBasenames=Y.allBasenames);const G=V.reduce((K,R)=>R.allPaths?K.concat(R.allPaths):K,[]);return G.length&&(j.allPaths=G),j}const H=function(j,Y,G){let K,R;for(let J=0,ie=V.length;J{for(const J of R){const ie=await J;if(typeof ie=="string")return ie}return null})():null},z=V.find(j=>!!j.allBasenames);z&&(H.allBasenames=z.allBasenames);const U=V.reduce((j,Y)=>Y.allPaths?j.concat(Y.allPaths):j,[]);return U.length&&(H.allPaths=U),H}function O(x,W,V){if(W===!1)return C;const q=f(x,V);if(q===C)return C;if(typeof W=="boolean")return q;if(W){const H=W.when;if(typeof H=="string"){const z=(U,j,Y,G)=>{if(!G||!q(U,j))return null;const K=H.replace("$(basename)",()=>Y),R=G(K);return(0,d.isThenable)(R)?R.then(J=>J?x:null):R?x:null};return z.requiresSiblings=!0,z}}return q}function F(x,W){const V=x.filter(j=>!!j.basenames);if(V.length<2)return x;const q=V.reduce((j,Y)=>{const G=Y.basenames;return G?j.concat(G):j},[]);let H;if(W){H=[];for(let j=0,Y=q.length;j{const G=Y.patterns;return G?j.concat(G):j},[]);const z=function(j,Y){if(typeof j!="string")return null;if(!Y){let K;for(K=j.length;K>0;K--){const R=j.charCodeAt(K-1);if(R===47||R===92)break}Y=j.substr(K)}const G=q.indexOf(Y);return G!==-1?H[G]:null};z.basenames=q,z.patterns=H,z.allBasenames=q;const U=x.filter(j=>!j.basenames);return U.push(z),U}}),define(ne[629],se([1,0,251,16]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.normalizeDriveLetter=I;function I(y,m=k.isWindows){return(0,d.hasDriveLetter)(y,m)?y.charAt(0).toUpperCase()+y.slice(1):y}let E=Object.create(null)}),define(ne[22],se([1,0,99,16]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.URI=void 0,e.uriToFsPath=a;const I=/^\w[\w\d+.-]*$/,E=/^\//,y=/^\/\//;function m(h,v){if(!h.scheme&&v)throw new Error(`[UriError]: Scheme is missing: {scheme: "", authority: "${h.authority}", path: "${h.path}", query: "${h.query}", fragment: "${h.fragment}"}`);if(h.scheme&&!I.test(h.scheme))throw new Error("[UriError]: Scheme contains illegal characters.");if(h.path){if(h.authority){if(!E.test(h.path))throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character')}else if(y.test(h.path))throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")')}}function _(h,v){return!h&&!v?"file":h}function b(h,v){switch(h){case"https":case"http":case"file":v?v[0]!==n&&(v=n+v):v=n;break}return v}const p="",n="/",o=/^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;class t{static isUri(v){return v instanceof t?!0:v?typeof v.authority=="string"&&typeof v.fragment=="string"&&typeof v.path=="string"&&typeof v.query=="string"&&typeof v.scheme=="string"&&typeof v.fsPath=="string"&&typeof v.with=="function"&&typeof v.toString=="function":!1}constructor(v,w,S,L,D,T=!1){typeof v=="object"?(this.scheme=v.scheme||p,this.authority=v.authority||p,this.path=v.path||p,this.query=v.query||p,this.fragment=v.fragment||p):(this.scheme=_(v,T),this.authority=w||p,this.path=b(this.scheme,S||p),this.query=L||p,this.fragment=D||p,m(this,T))}get fsPath(){return a(this,!1)}with(v){if(!v)return this;let{scheme:w,authority:S,path:L,query:D,fragment:T}=v;return w===void 0?w=this.scheme:w===null&&(w=p),S===void 0?S=this.authority:S===null&&(S=p),L===void 0?L=this.path:L===null&&(L=p),D===void 0?D=this.query:D===null&&(D=p),T===void 0?T=this.fragment:T===null&&(T=p),w===this.scheme&&S===this.authority&&L===this.path&&D===this.query&&T===this.fragment?this:new s(w,S,L,D,T)}static parse(v,w=!1){const S=o.exec(v);return S?new s(S[2]||p,f(S[4]||p),f(S[5]||p),f(S[7]||p),f(S[9]||p),w):new s(p,p,p,p,p)}static file(v){let w=p;if(k.isWindows&&(v=v.replace(/\\/g,n)),v[0]===n&&v[1]===n){const S=v.indexOf(n,2);S===-1?(w=v.substring(2),v=n):(w=v.substring(2,S),v=v.substring(S)||n)}return new s("file",w,v,p,p)}static from(v,w){return new s(v.scheme,v.authority,v.path,v.query,v.fragment,w)}static joinPath(v,...w){if(!v.path)throw new Error("[UriError]: cannot call joinPath on URI without path");let S;return k.isWindows&&v.scheme==="file"?S=t.file(d.win32.join(a(v,!0),...w)).path:S=d.posix.join(v.path,...w),v.with({path:S})}toString(v=!1){return r(this,v)}toJSON(){return this}static revive(v){if(v){if(v instanceof t)return v;{const w=new s(v);return w._formatted=v.external??null,w._fsPath=v._sep===i?v.fsPath??null:null,w}}else return v}}e.URI=t;const i=k.isWindows?1:void 0;class s extends t{constructor(){super(...arguments),this._formatted=null,this._fsPath=null}get fsPath(){return this._fsPath||(this._fsPath=a(this,!1)),this._fsPath}toString(v=!1){return v?r(this,!0):(this._formatted||(this._formatted=r(this,!1)),this._formatted)}toJSON(){const v={$mid:1};return this._fsPath&&(v.fsPath=this._fsPath,v._sep=i),this._formatted&&(v.external=this._formatted),this.path&&(v.path=this.path),this.scheme&&(v.scheme=this.scheme),this.authority&&(v.authority=this.authority),this.query&&(v.query=this.query),this.fragment&&(v.fragment=this.fragment),v}}const g={58:"%3A",47:"%2F",63:"%3F",35:"%23",91:"%5B",93:"%5D",64:"%40",33:"%21",36:"%24",38:"%26",39:"%27",40:"%28",41:"%29",42:"%2A",43:"%2B",44:"%2C",59:"%3B",61:"%3D",32:"%20"};function c(h,v,w){let S,L=-1;for(let D=0;D=97&&T<=122||T>=65&&T<=90||T>=48&&T<=57||T===45||T===46||T===95||T===126||v&&T===47||w&&T===91||w&&T===93||w&&T===58)L!==-1&&(S+=encodeURIComponent(h.substring(L,D)),L=-1),S!==void 0&&(S+=h.charAt(D));else{S===void 0&&(S=h.substr(0,D));const M=g[T];M!==void 0?(L!==-1&&(S+=encodeURIComponent(h.substring(L,D)),L=-1),S+=M):L===-1&&(L=D)}}return L!==-1&&(S+=encodeURIComponent(h.substring(L))),S!==void 0?S:h}function l(h){let v;for(let w=0;w1&&h.scheme==="file"?w=`//${h.authority}${h.path}`:h.path.charCodeAt(0)===47&&(h.path.charCodeAt(1)>=65&&h.path.charCodeAt(1)<=90||h.path.charCodeAt(1)>=97&&h.path.charCodeAt(1)<=122)&&h.path.charCodeAt(2)===58?v?w=h.path.substr(1):w=h.path[1].toLowerCase()+h.path.substr(2):w=h.path,k.isWindows&&(w=w.replace(/\//g,"\\")),w}function r(h,v){const w=v?l:c;let S="",{scheme:L,authority:D,path:T,query:M,fragment:A}=h;if(L&&(S+=L,S+=":"),(D||L==="file")&&(S+=n,S+=n),D){let P=D.indexOf("@");if(P!==-1){const N=D.substr(0,P);D=D.substr(P+1),P=N.lastIndexOf(":"),P===-1?S+=w(N,!1,!1):(S+=w(N.substr(0,P),!1,!1),S+=":",S+=w(N.substr(P+1),!1,!0)),S+="@"}D=D.toLowerCase(),P=D.lastIndexOf(":"),P===-1?S+=w(D,!1,!0):(S+=w(D.substr(0,P),!1,!0),S+=D.substr(P))}if(T){if(T.length>=3&&T.charCodeAt(0)===47&&T.charCodeAt(2)===58){const P=T.charCodeAt(1);P>=65&&P<=90&&(T=`/${String.fromCharCode(P+32)}:${T.substr(3)}`)}else if(T.length>=2&&T.charCodeAt(1)===58){const P=T.charCodeAt(0);P>=65&&P<=90&&(T=`${String.fromCharCode(P+32)}:${T.substr(2)}`)}S+=w(T,!0,!1)}return M&&(S+="?",S+=w(M,!1,!1)),A&&(S+="#",S+=v?A:c(A,!1,!1)),S}function u(h){try{return decodeURIComponent(h)}catch{return h.length>3?h.substr(0,3)+u(h.substr(3)):h}}const C=/(%[0-9A-Za-z][0-9A-Za-z])+/g;function f(h){return h.match(C)?h.replace(C,v=>u(v)):h}}),define(ne[252],se([1,0,160,22]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.stringify=I,e.parse=E,e.revive=m;function I(_){return JSON.stringify(_,y)}function E(_){let b=JSON.parse(_);return b=m(b),b}function y(_,b){return b instanceof RegExp?{$mid:2,source:b.source,flags:b.flags}:b}function m(_,b=0){if(!_||b>200)return _;if(typeof _=="object"){switch(_.$mid){case 1:return k.URI.revive(_);case 2:return new RegExp(_.source,_.flags);case 17:return new Date(_.source)}if(_ instanceof d.VSBuffer||_ instanceof Uint8Array)return _;if(Array.isArray(_))for(let p=0;p<_.length;++p)_[p]=m(_[p],b+1);else for(const p in _)Object.hasOwnProperty.call(_,p)&&(_[p]=m(_[p],b+1))}return _}}),define(ne[42],se([1,0,8,16,11,22,99]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.COI=e.FileAccess=e.VSCODE_AUTHORITY=e.RemoteAuthorities=e.connectionTokenQueryName=e.Schemas=void 0,e.matchesScheme=_,e.matchesSomeScheme=b;var m;(function(t){t.inMemory="inmemory",t.vscode="vscode",t.internal="private",t.walkThrough="walkThrough",t.walkThroughSnippet="walkThroughSnippet",t.http="http",t.https="https",t.file="file",t.mailto="mailto",t.untitled="untitled",t.data="data",t.command="command",t.vscodeRemote="vscode-remote",t.vscodeRemoteResource="vscode-remote-resource",t.vscodeManagedRemoteResource="vscode-managed-remote-resource",t.vscodeUserData="vscode-userdata",t.vscodeCustomEditor="vscode-custom-editor",t.vscodeNotebookCell="vscode-notebook-cell",t.vscodeNotebookCellMetadata="vscode-notebook-cell-metadata",t.vscodeNotebookCellMetadataDiff="vscode-notebook-cell-metadata-diff",t.vscodeNotebookCellOutput="vscode-notebook-cell-output",t.vscodeNotebookCellOutputDiff="vscode-notebook-cell-output-diff",t.vscodeNotebookMetadata="vscode-notebook-metadata",t.vscodeInteractiveInput="vscode-interactive-input",t.vscodeSettings="vscode-settings",t.vscodeWorkspaceTrust="vscode-workspace-trust",t.vscodeTerminal="vscode-terminal",t.vscodeChatCodeBlock="vscode-chat-code-block",t.vscodeChatCodeCompareBlock="vscode-chat-code-compare-block",t.vscodeChatSesssion="vscode-chat-editor",t.webviewPanel="webview-panel",t.vscodeWebview="vscode-webview",t.extension="extension",t.vscodeFileResource="vscode-file",t.tmp="tmp",t.vsls="vsls",t.vscodeSourceControl="vscode-scm",t.commentsInput="comment",t.codeSetting="code-setting",t.outputChannel="output"})(m||(e.Schemas=m={}));function _(t,i){return E.URI.isUri(t)?(0,I.equalsIgnoreCase)(t.scheme,i):(0,I.startsWithIgnoreCase)(t,i+":")}function b(t,...i){return i.some(s=>_(t,s))}e.connectionTokenQueryName="tkn";class p{constructor(){this._hosts=Object.create(null),this._ports=Object.create(null),this._connectionTokens=Object.create(null),this._preferredWebSchema="http",this._delegate=null,this._serverRootPath="/"}setPreferredWebSchema(i){this._preferredWebSchema=i}get _remoteResourcesPath(){return y.posix.join(this._serverRootPath,m.vscodeRemoteResource)}rewrite(i){if(this._delegate)try{return this._delegate(i)}catch(r){return d.onUnexpectedError(r),i}const s=i.authority;let g=this._hosts[s];g&&g.indexOf(":")!==-1&&g.indexOf("[")===-1&&(g=`[${g}]`);const c=this._ports[s],l=this._connectionTokens[s];let a=`path=${encodeURIComponent(i.path)}`;return typeof l=="string"&&(a+=`&${e.connectionTokenQueryName}=${encodeURIComponent(l)}`),E.URI.from({scheme:k.isWeb?this._preferredWebSchema:m.vscodeRemoteResource,authority:`${g}:${c}`,path:this._remoteResourcesPath,query:a})}}e.RemoteAuthorities=new p,e.VSCODE_AUTHORITY="vscode-app";class n{static{this.FALLBACK_AUTHORITY=e.VSCODE_AUTHORITY}asBrowserUri(i){const s=this.toUri(i,oe);return this.uriToBrowserUri(s)}uriToBrowserUri(i){return i.scheme===m.vscodeRemote?e.RemoteAuthorities.rewrite(i):i.scheme===m.file&&(k.isNative||k.webWorkerOrigin===`${m.vscodeFileResource}://${n.FALLBACK_AUTHORITY}`)?i.with({scheme:m.vscodeFileResource,authority:i.authority||n.FALLBACK_AUTHORITY,query:null,fragment:null}):i}toUri(i,s){if(E.URI.isUri(i))return i;if(globalThis._VSCODE_FILE_ROOT){const g=globalThis._VSCODE_FILE_ROOT;if(/^\w[\w\d+.-]*:\/\//.test(g))return E.URI.joinPath(E.URI.parse(g,!0),i);const c=y.join(g,i);return E.URI.file(c)}return E.URI.parse(s.toUrl(i))}}e.FileAccess=new n;var o;(function(t){const i=new Map([["1",{"Cross-Origin-Opener-Policy":"same-origin"}],["2",{"Cross-Origin-Embedder-Policy":"require-corp"}],["3",{"Cross-Origin-Opener-Policy":"same-origin","Cross-Origin-Embedder-Policy":"require-corp"}]]);t.CoopAndCoep=Object.freeze(i.get("3"));const s="vscode-coi";function g(l){let a;typeof l=="string"?a=new URL(l).searchParams:l instanceof URL?a=l.searchParams:E.URI.isUri(l)&&(a=new URL(l.toString(!0)).searchParams);const r=a?.get(s);if(r)return i.get(r)}t.getHeadersFromQuery=g;function c(l,a,r){if(!globalThis.crossOriginIsolated)return;const u=a&&r?"3":r?"2":"1";l instanceof URLSearchParams?l.set(s,u):l[s]=u}t.addSearchParam=c})(o||(e.COI=o={}))}),define(ne[5],se([1,0,64,248,47,77,14,8,6,351,2,42,16,129,52]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.DragAndDropObserver=e.ModifierKeyEmitter=e.basicMarkupHtmlTags=e.Namespace=e.EventHelper=e.EventType=e.sharedMutationObserver=e.Dimension=e.WindowIntervalTimer=e.scheduleAtNextAnimationFrame=e.runAtThisOrScheduleAtNextAnimationFrame=e.WindowIdleValue=e.addStandardDisposableGenericMouseUpListener=e.addStandardDisposableGenericMouseDownListener=e.addStandardDisposableListener=e.onDidUnregisterWindow=e.onWillUnregisterWindow=e.onDidRegisterWindow=e.hasWindow=e.getWindowById=e.getWindowId=e.getWindowsCount=e.getWindows=e.getDocument=e.getWindow=e.registerWindow=void 0,e.clearNode=g,e.addDisposableListener=l,e.addDisposableGenericMouseDownListener=h,e.addDisposableGenericMouseUpListener=v,e.runWhenWindowIdle=w,e.getComputedStyle=T,e.getClientArea=M,e.getTopLeftOffset=N,e.size=O,e.getDomNodePagePosition=F,e.getDomNodeZoomLevel=x,e.getTotalWidth=W,e.getContentWidth=V,e.getContentHeight=q,e.getTotalHeight=H,e.isAncestor=z,e.findParentWithClass=U,e.hasParentWithClass=j,e.isShadowRoot=Y,e.isInShadowDOM=G,e.getShadowRoot=K,e.getActiveElement=R,e.isActiveElement=J,e.isAncestorOfActiveElement=ie,e.getActiveDocument=ue,e.getActiveWindow=he,e.createStyleSheet2=ae,e.createStyleSheet=de,e.createCSSRule=Q,e.removeCSSRulesContainingSelector=Z,e.isHTMLElement=re,e.isHTMLAnchorElement=le,e.isSVGElement=me,e.isMouseEvent=Ce,e.isKeyboardEvent=ye,e.isEventLike=Le,e.saveParentsScrollTop=Ee,e.restoreParentsScrollTop=Me,e.trackFocus=Ne,e.after=Ke,e.append=ze,e.prepend=Ge,e.reset=it,e.$=_e,e.setVisibility=xe,e.show=be,e.hide=ve,e.computeScreenAwareSize=we,e.windowOpenNoOpener=Te,e.animate=Pe,e.asCSSUrl=Be,e.asCSSPropertyValue=He,e.asCssValueWithDefault=$e,e.hookDomPurifyHrefAndSrcSanitizer=je,e.h=st,e.svgElem=pt,s=function(){const De=new Map;(0,i.ensureCodeWindow)(i.mainWindow,1);const Ie={window:i.mainWindow,disposables:new p.DisposableStore};De.set(i.mainWindow.vscodeWindowId,Ie);const Re=new _.Emitter,Se=new _.Emitter,We=new _.Emitter;function qe(Ue,Je){return(typeof Ue=="number"?De.get(Ue):void 0)??(Je?Ie:void 0)}return{onDidRegisterWindow:Re.event,onWillUnregisterWindow:We.event,onDidUnregisterWindow:Se.event,registerWindow(Ue){if(De.has(Ue.vscodeWindowId))return p.Disposable.None;const Je=new p.DisposableStore,tt={window:Ue,disposables:Je.add(new p.DisposableStore)};return De.set(Ue.vscodeWindowId,tt),Je.add((0,p.toDisposable)(()=>{De.delete(Ue.vscodeWindowId),Se.fire(Ue)})),Je.add(l(Ue,e.EventType.BEFORE_UNLOAD,()=>{We.fire(Ue)})),Re.fire(tt),Je},getWindows(){return De.values()},getWindowsCount(){return De.size},getWindowId(Ue){return Ue.vscodeWindowId},hasWindow(Ue){return De.has(Ue)},getWindowById:qe,getWindow(Ue){const Je=Ue;if(Je?.ownerDocument?.defaultView)return Je.ownerDocument.defaultView.window;const tt=Ue;return tt?.view?tt.view.window:i.mainWindow},getDocument(Ue){const Je=Ue;return(0,e.getWindow)(Je).document}}}(),e.registerWindow=s.registerWindow,e.getWindow=s.getWindow,e.getDocument=s.getDocument,e.getWindows=s.getWindows,e.getWindowsCount=s.getWindowsCount,e.getWindowId=s.getWindowId,e.getWindowById=s.getWindowById,e.hasWindow=s.hasWindow,e.onDidRegisterWindow=s.onDidRegisterWindow,e.onWillUnregisterWindow=s.onWillUnregisterWindow,e.onDidUnregisterWindow=s.onDidUnregisterWindow;function g(De){for(;De.firstChild;)De.firstChild.remove()}class c{constructor(Ie,Re,Se,We){this._node=Ie,this._type=Re,this._handler=Se,this._options=We||!1,this._node.addEventListener(this._type,this._handler,this._options)}dispose(){this._handler&&(this._node.removeEventListener(this._type,this._handler,this._options),this._node=null,this._handler=null)}}function l(De,Ie,Re,Se){return new c(De,Ie,Re,Se)}function a(De,Ie){return function(Re){return Ie(new E.StandardMouseEvent(De,Re))}}function r(De){return function(Ie){return De(new I.StandardKeyboardEvent(Ie))}}const u=function(Ie,Re,Se,We){let qe=Se;return Re==="click"||Re==="mousedown"||Re==="contextmenu"?qe=a((0,e.getWindow)(Ie),Se):(Re==="keydown"||Re==="keypress"||Re==="keyup")&&(qe=r(Se)),l(Ie,Re,qe,We)};e.addStandardDisposableListener=u;const C=function(Ie,Re,Se){const We=a((0,e.getWindow)(Ie),Re);return h(Ie,We,Se)};e.addStandardDisposableGenericMouseDownListener=C;const f=function(Ie,Re,Se){const We=a((0,e.getWindow)(Ie),Re);return v(Ie,We,Se)};e.addStandardDisposableGenericMouseUpListener=f;function h(De,Ie,Re){return l(De,o.isIOS&&k.BrowserFeatures.pointerEvents?e.EventType.POINTER_DOWN:e.EventType.MOUSE_DOWN,Ie,Re)}function v(De,Ie,Re){return l(De,o.isIOS&&k.BrowserFeatures.pointerEvents?e.EventType.POINTER_UP:e.EventType.MOUSE_UP,Ie,Re)}function w(De,Ie,Re){return(0,y._runWhenIdle)(De,Ie,Re)}class S extends y.AbstractIdleValue{constructor(Ie,Re){super(Ie,Re)}}e.WindowIdleValue=S;class L extends y.IntervalTimer{constructor(Ie){super(),this.defaultTarget=Ie&&(0,e.getWindow)(Ie)}cancelAndSet(Ie,Re,Se){return super.cancelAndSet(Ie,Re,Se??this.defaultTarget)}}e.WindowIntervalTimer=L;class D{constructor(Ie,Re=0){this._runner=Ie,this.priority=Re,this._canceled=!1}dispose(){this._canceled=!0}execute(){if(!this._canceled)try{this._runner()}catch(Ie){(0,m.onUnexpectedError)(Ie)}}static sort(Ie,Re){return Re.priority-Ie.priority}}(function(){const De=new Map,Ie=new Map,Re=new Map,Se=new Map,We=qe=>{Re.set(qe,!1);const Ue=De.get(qe)??[];for(Ie.set(qe,Ue),De.set(qe,[]),Se.set(qe,!0);Ue.length>0;)Ue.sort(D.sort),Ue.shift().execute();Se.set(qe,!1)};e.scheduleAtNextAnimationFrame=(qe,Ue,Je=0)=>{const tt=(0,e.getWindowId)(qe),Qe=new D(Ue,Je);let rt=De.get(tt);return rt||(rt=[],De.set(tt,rt)),rt.push(Qe),Re.get(tt)||(Re.set(tt,!0),qe.requestAnimationFrame(()=>We(tt))),Qe},e.runAtThisOrScheduleAtNextAnimationFrame=(qe,Ue,Je)=>{const tt=(0,e.getWindowId)(qe);if(Se.get(tt)){const Qe=new D(Ue,Je);let rt=Ie.get(tt);return rt||(rt=[],Ie.set(tt,rt)),rt.push(Qe),Qe}else return(0,e.scheduleAtNextAnimationFrame)(qe,Ue,Je)}})();function T(De){return(0,e.getWindow)(De).getComputedStyle(De,null)}function M(De,Ie){const Re=(0,e.getWindow)(De),Se=Re.document;if(De!==Se.body)return new P(De.clientWidth,De.clientHeight);if(o.isIOS&&Re?.visualViewport)return new P(Re.visualViewport.width,Re.visualViewport.height);if(Re?.innerWidth&&Re.innerHeight)return new P(Re.innerWidth,Re.innerHeight);if(Se.body&&Se.body.clientWidth&&Se.body.clientHeight)return new P(Se.body.clientWidth,Se.body.clientHeight);if(Se.documentElement&&Se.documentElement.clientWidth&&Se.documentElement.clientHeight)return new P(Se.documentElement.clientWidth,Se.documentElement.clientHeight);if(Ie)return M(Ie);throw new Error("Unable to figure out browser width and height")}class A{static convertToPixels(Ie,Re){return parseFloat(Re)||0}static getDimension(Ie,Re,Se){const We=T(Ie),qe=We?We.getPropertyValue(Re):"0";return A.convertToPixels(Ie,qe)}static getBorderLeftWidth(Ie){return A.getDimension(Ie,"border-left-width","borderLeftWidth")}static getBorderRightWidth(Ie){return A.getDimension(Ie,"border-right-width","borderRightWidth")}static getBorderTopWidth(Ie){return A.getDimension(Ie,"border-top-width","borderTopWidth")}static getBorderBottomWidth(Ie){return A.getDimension(Ie,"border-bottom-width","borderBottomWidth")}static getPaddingLeft(Ie){return A.getDimension(Ie,"padding-left","paddingLeft")}static getPaddingRight(Ie){return A.getDimension(Ie,"padding-right","paddingRight")}static getPaddingTop(Ie){return A.getDimension(Ie,"padding-top","paddingTop")}static getPaddingBottom(Ie){return A.getDimension(Ie,"padding-bottom","paddingBottom")}static getMarginLeft(Ie){return A.getDimension(Ie,"margin-left","marginLeft")}static getMarginTop(Ie){return A.getDimension(Ie,"margin-top","marginTop")}static getMarginRight(Ie){return A.getDimension(Ie,"margin-right","marginRight")}static getMarginBottom(Ie){return A.getDimension(Ie,"margin-bottom","marginBottom")}}class P{static{this.None=new P(0,0)}constructor(Ie,Re){this.width=Ie,this.height=Re}with(Ie=this.width,Re=this.height){return Ie!==this.width||Re!==this.height?new P(Ie,Re):this}static is(Ie){return typeof Ie=="object"&&typeof Ie.height=="number"&&typeof Ie.width=="number"}static lift(Ie){return Ie instanceof P?Ie:new P(Ie.width,Ie.height)}static equals(Ie,Re){return Ie===Re?!0:!Ie||!Re?!1:Ie.width===Re.width&&Ie.height===Re.height}}e.Dimension=P;function N(De){let Ie=De.offsetParent,Re=De.offsetTop,Se=De.offsetLeft;for(;(De=De.parentNode)!==null&&De!==De.ownerDocument.body&&De!==De.ownerDocument.documentElement;){Re-=De.scrollTop;const We=Y(De)?null:T(De);We&&(Se-=We.direction!=="rtl"?De.scrollLeft:-De.scrollLeft),De===Ie&&(Se+=A.getBorderLeftWidth(De),Re+=A.getBorderTopWidth(De),Re+=De.offsetTop,Se+=De.offsetLeft,Ie=De.offsetParent)}return{left:Se,top:Re}}function O(De,Ie,Re){typeof Ie=="number"&&(De.style.width=`${Ie}px`),typeof Re=="number"&&(De.style.height=`${Re}px`)}function F(De){const Ie=De.getBoundingClientRect(),Re=(0,e.getWindow)(De);return{left:Ie.left+Re.scrollX,top:Ie.top+Re.scrollY,width:Ie.width,height:Ie.height}}function x(De){let Ie=De,Re=1;do{const Se=T(Ie).zoom;Se!=null&&Se!=="1"&&(Re*=Se),Ie=Ie.parentElement}while(Ie!==null&&Ie!==Ie.ownerDocument.documentElement);return Re}function W(De){const Ie=A.getMarginLeft(De)+A.getMarginRight(De);return De.offsetWidth+Ie}function V(De){const Ie=A.getBorderLeftWidth(De)+A.getBorderRightWidth(De),Re=A.getPaddingLeft(De)+A.getPaddingRight(De);return De.offsetWidth-Ie-Re}function q(De){const Ie=A.getBorderTopWidth(De)+A.getBorderBottomWidth(De),Re=A.getPaddingTop(De)+A.getPaddingBottom(De);return De.offsetHeight-Ie-Re}function H(De){const Ie=A.getMarginTop(De)+A.getMarginBottom(De);return De.offsetHeight+Ie}function z(De,Ie){return!!Ie?.contains(De)}function U(De,Ie,Re){for(;De&&De.nodeType===De.ELEMENT_NODE;){if(De.classList.contains(Ie))return De;if(Re){if(typeof Re=="string"){if(De.classList.contains(Re))return null}else if(De===Re)return null}De=De.parentNode}return null}function j(De,Ie,Re){return!!U(De,Ie,Re)}function Y(De){return De&&!!De.host&&!!De.mode}function G(De){return!!K(De)}function K(De){for(;De.parentNode;){if(De===De.ownerDocument?.body)return null;De=De.parentNode}return Y(De)?De:null}function R(){let De=ue().activeElement;for(;De?.shadowRoot;)De=De.shadowRoot.activeElement;return De}function J(De){return R()===De}function ie(De){return z(R(),De)}function ue(){return(0,e.getWindowsCount)()<=1?i.mainWindow.document:Array.from((0,e.getWindows)()).map(({window:Ie})=>Ie.document).find(Ie=>Ie.hasFocus())??i.mainWindow.document}function he(){return ue().defaultView?.window??i.mainWindow}const pe=new Map;function ae(){return new ee}class ee{constructor(){this._currentCssStyle="",this._styleSheet=void 0}setStyle(Ie){Ie!==this._currentCssStyle&&(this._currentCssStyle=Ie,this._styleSheet?this._styleSheet.innerText=Ie:this._styleSheet=de(i.mainWindow.document.head,Re=>Re.innerText=Ie))}dispose(){this._styleSheet&&(this._styleSheet.remove(),this._styleSheet=void 0)}}function de(De=i.mainWindow.document.head,Ie,Re){const Se=document.createElement("style");if(Se.type="text/css",Se.media="screen",Ie?.(Se),De.appendChild(Se),Re&&Re.add((0,p.toDisposable)(()=>Se.remove())),De===i.mainWindow.document.head){const We=new Set;pe.set(Se,We);for(const{window:qe,disposables:Ue}of(0,e.getWindows)()){if(qe===i.mainWindow)continue;const Je=Ue.add(ge(Se,We,qe));Re?.add(Je)}}return Se}function ge(De,Ie,Re){const Se=new p.DisposableStore,We=De.cloneNode(!0);Re.document.head.appendChild(We),Se.add((0,p.toDisposable)(()=>We.remove()));for(const qe of $(De))We.sheet?.insertRule(qe.cssText,We.sheet?.cssRules.length);return Se.add(e.sharedMutationObserver.observe(De,Se,{childList:!0})(()=>{We.textContent=De.textContent})),Ie.add(We),Se.add((0,p.toDisposable)(()=>Ie.delete(We))),Se}e.sharedMutationObserver=new class{constructor(){this.mutationObservers=new Map}observe(De,Ie,Re){let Se=this.mutationObservers.get(De);Se||(Se=new Map,this.mutationObservers.set(De,Se));const We=(0,t.hash)(Re);let qe=Se.get(We);if(qe)qe.users+=1;else{const Ue=new _.Emitter,Je=new MutationObserver(Qe=>Ue.fire(Qe));Je.observe(De,Re);const tt=qe={users:1,observer:Je,onDidMutate:Ue.event};Ie.add((0,p.toDisposable)(()=>{tt.users-=1,tt.users===0&&(Ue.dispose(),Je.disconnect(),Se?.delete(We),Se?.size===0&&this.mutationObservers.delete(De))})),Se.set(We,qe)}return qe.onDidMutate}};let X=null;function B(){return X||(X=de()),X}function $(De){return De?.sheet?.rules?De.sheet.rules:De?.sheet?.cssRules?De.sheet.cssRules:[]}function Q(De,Ie,Re=B()){if(!(!Re||!Ie)){Re.sheet?.insertRule(`${De} {${Ie}}`,0);for(const Se of pe.get(Re)??[])Q(De,Ie,Se)}}function Z(De,Ie=B()){if(!Ie)return;const Re=$(Ie),Se=[];for(let We=0;We=0;We--)Ie.sheet?.deleteRule(Se[We]);for(const We of pe.get(Ie)??[])Z(De,We)}function te(De){return typeof De.selectorText=="string"}function re(De){return De instanceof HTMLElement||De instanceof(0,e.getWindow)(De).HTMLElement}function le(De){return De instanceof HTMLAnchorElement||De instanceof(0,e.getWindow)(De).HTMLAnchorElement}function me(De){return De instanceof SVGElement||De instanceof(0,e.getWindow)(De).SVGElement}function Ce(De){return De instanceof MouseEvent||De instanceof(0,e.getWindow)(De).MouseEvent}function ye(De){return De instanceof KeyboardEvent||De instanceof(0,e.getWindow)(De).KeyboardEvent}e.EventType={CLICK:"click",AUXCLICK:"auxclick",DBLCLICK:"dblclick",MOUSE_UP:"mouseup",MOUSE_DOWN:"mousedown",MOUSE_OVER:"mouseover",MOUSE_MOVE:"mousemove",MOUSE_OUT:"mouseout",MOUSE_ENTER:"mouseenter",MOUSE_LEAVE:"mouseleave",MOUSE_WHEEL:"wheel",POINTER_UP:"pointerup",POINTER_DOWN:"pointerdown",POINTER_MOVE:"pointermove",POINTER_LEAVE:"pointerleave",CONTEXT_MENU:"contextmenu",WHEEL:"wheel",KEY_DOWN:"keydown",KEY_PRESS:"keypress",KEY_UP:"keyup",LOAD:"load",BEFORE_UNLOAD:"beforeunload",UNLOAD:"unload",PAGE_SHOW:"pageshow",PAGE_HIDE:"pagehide",PASTE:"paste",ABORT:"abort",ERROR:"error",RESIZE:"resize",SCROLL:"scroll",FULLSCREEN_CHANGE:"fullscreenchange",WK_FULLSCREEN_CHANGE:"webkitfullscreenchange",SELECT:"select",CHANGE:"change",SUBMIT:"submit",RESET:"reset",FOCUS:"focus",FOCUS_IN:"focusin",FOCUS_OUT:"focusout",BLUR:"blur",INPUT:"input",STORAGE:"storage",DRAG_START:"dragstart",DRAG:"drag",DRAG_ENTER:"dragenter",DRAG_LEAVE:"dragleave",DRAG_OVER:"dragover",DROP:"drop",DRAG_END:"dragend",ANIMATION_START:d.isWebKit?"webkitAnimationStart":"animationstart",ANIMATION_END:d.isWebKit?"webkitAnimationEnd":"animationend",ANIMATION_ITERATION:d.isWebKit?"webkitAnimationIteration":"animationiteration"};function Le(De){const Ie=De;return!!(Ie&&typeof Ie.preventDefault=="function"&&typeof Ie.stopPropagation=="function")}e.EventHelper={stop:(De,Ie)=>(De.preventDefault(),Ie&&De.stopPropagation(),De)};function Ee(De){const Ie=[];for(let Re=0;De&&De.nodeType===De.ELEMENT_NODE;Re++)Ie[Re]=De.scrollTop,De=De.parentNode;return Ie}function Me(De,Ie){for(let Re=0;De&&De.nodeType===De.ELEMENT_NODE;Re++)De.scrollTop!==Ie[Re]&&(De.scrollTop=Ie[Re]),De=De.parentNode}class Ae extends p.Disposable{static hasFocusWithin(Ie){if(re(Ie)){const Re=K(Ie),Se=Re?Re.activeElement:Ie.ownerDocument.activeElement;return z(Se,Ie)}else{const Re=Ie;return z(Re.document.activeElement,Re.document)}}constructor(Ie){super(),this._onDidFocus=this._register(new _.Emitter),this.onDidFocus=this._onDidFocus.event,this._onDidBlur=this._register(new _.Emitter),this.onDidBlur=this._onDidBlur.event;let Re=Ae.hasFocusWithin(Ie),Se=!1;const We=()=>{Se=!1,Re||(Re=!0,this._onDidFocus.fire())},qe=()=>{Re&&(Se=!0,(re(Ie)?(0,e.getWindow)(Ie):Ie).setTimeout(()=>{Se&&(Se=!1,Re=!1,this._onDidBlur.fire())},0))};this._refreshStateHandler=()=>{Ae.hasFocusWithin(Ie)!==Re&&(Re?qe():We())},this._register(l(Ie,e.EventType.FOCUS,We,!0)),this._register(l(Ie,e.EventType.BLUR,qe,!0)),re(Ie)&&(this._register(l(Ie,e.EventType.FOCUS_IN,()=>this._refreshStateHandler())),this._register(l(Ie,e.EventType.FOCUS_OUT,()=>this._refreshStateHandler())))}}function Ne(De){return new Ae(De)}function Ke(De,Ie){return De.after(Ie),Ie}function ze(De,...Ie){if(De.append(...Ie),Ie.length===1&&typeof Ie[0]!="string")return Ie[0]}function Ge(De,Ie){return De.insertBefore(Ie,De.firstChild),Ie}function it(De,...Ie){De.innerText="",ze(De,...Ie)}const Oe=/([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/;var Fe;(function(De){De.HTML="http://www.w3.org/1999/xhtml",De.SVG="http://www.w3.org/2000/svg"})(Fe||(e.Namespace=Fe={}));function fe(De,Ie,Re,...Se){const We=Oe.exec(Ie);if(!We)throw new Error("Bad use of emmet");const qe=We[1]||"div";let Ue;return De!==Fe.HTML?Ue=document.createElementNS(De,qe):Ue=document.createElement(qe),We[3]&&(Ue.id=We[3]),We[4]&&(Ue.className=We[4].replace(/\./g," ").trim()),Re&&Object.entries(Re).forEach(([Je,tt])=>{typeof tt>"u"||(/^on\w+$/.test(Je)?Ue[Je]=tt:Je==="selected"?tt&&Ue.setAttribute(Je,"true"):Ue.setAttribute(Je,tt))}),Ue.append(...Se),Ue}function _e(De,Ie,...Re){return fe(Fe.HTML,De,Ie,...Re)}_e.SVG=function(De,Ie,...Re){return fe(Fe.SVG,De,Ie,...Re)};function xe(De,...Ie){De?be(...Ie):ve(...Ie)}function be(...De){for(const Ie of De)Ie.style.display="",Ie.removeAttribute("aria-hidden")}function ve(...De){for(const Ie of De)Ie.style.display="none",Ie.setAttribute("aria-hidden","true")}function we(De,Ie){const Re=De.devicePixelRatio*Ie;return Math.max(1,Math.floor(Re))/De.devicePixelRatio}function Te(De){i.mainWindow.open(De,"_blank","noopener")}function Pe(De,Ie){const Re=()=>{Ie(),Se=(0,e.scheduleAtNextAnimationFrame)(De,Re)};let Se=(0,e.scheduleAtNextAnimationFrame)(De,Re);return(0,p.toDisposable)(()=>Se.dispose())}n.RemoteAuthorities.setPreferredWebSchema(/^https:/.test(i.mainWindow.location.href)?"https":"http");function Be(De){return De?`url('${n.FileAccess.uriToBrowserUri(De).toString(!0).replace(/'/g,"%27")}')`:"url('')"}function He(De){return`'${De.replace(/'/g,"%27")}'`}function $e(De,Ie){if(De!==void 0){const Re=De.match(/^\s*var\((.+)\)$/);if(Re){const Se=Re[1].split(",",2);return Se.length===2&&(Ie=$e(Se[1].trim(),Ie)),`var(${Se[0]}, ${Ie})`}return De}return Ie}function je(De,Ie=!1){const Re=document.createElement("a");return b.addHook("afterSanitizeAttributes",Se=>{for(const We of["href","src"])if(Se.hasAttribute(We)){const qe=Se.getAttribute(We);if(We==="href"&&qe.startsWith("#"))continue;if(Re.href=qe,!De.includes(Re.protocol.replace(/:$/,""))){if(Ie&&We==="src"&&Re.href.startsWith("data:"))continue;Se.removeAttribute(We)}}}),(0,p.toDisposable)(()=>{b.removeHook("afterSanitizeAttributes")})}e.basicMarkupHtmlTags=Object.freeze(["a","abbr","b","bdo","blockquote","br","caption","cite","code","col","colgroup","dd","del","details","dfn","div","dl","dt","em","figcaption","figure","h1","h2","h3","h4","h5","h6","hr","i","img","input","ins","kbd","label","li","mark","ol","p","pre","q","rp","rt","ruby","samp","small","small","source","span","strike","strong","sub","summary","sup","table","tbody","td","tfoot","th","thead","time","tr","tt","u","ul","var","video","wbr"]);const Xe=Object.freeze({ALLOWED_TAGS:["a","button","blockquote","code","div","h1","h2","h3","h4","h5","h6","hr","input","label","li","p","pre","select","small","span","strong","textarea","ul","ol"],ALLOWED_ATTR:["href","data-href","data-command","target","title","name","src","alt","class","id","role","tabindex","style","data-code","width","height","align","x-dispatch","required","checked","placeholder","type","start"],RETURN_DOM:!1,RETURN_DOM_FRAGMENT:!1,RETURN_TRUSTED_TYPE:!0});class et extends _.Emitter{constructor(){super(),this._subscriptions=new p.DisposableStore,this._keyStatus={altKey:!1,shiftKey:!1,ctrlKey:!1,metaKey:!1},this._subscriptions.add(_.Event.runAndSubscribe(e.onDidRegisterWindow,({window:Ie,disposables:Re})=>this.registerListeners(Ie,Re),{window:i.mainWindow,disposables:this._subscriptions}))}registerListeners(Ie,Re){Re.add(l(Ie,"keydown",Se=>{if(Se.defaultPrevented)return;const We=new I.StandardKeyboardEvent(Se);if(!(We.keyCode===6&&Se.repeat)){if(Se.altKey&&!this._keyStatus.altKey)this._keyStatus.lastKeyPressed="alt";else if(Se.ctrlKey&&!this._keyStatus.ctrlKey)this._keyStatus.lastKeyPressed="ctrl";else if(Se.metaKey&&!this._keyStatus.metaKey)this._keyStatus.lastKeyPressed="meta";else if(Se.shiftKey&&!this._keyStatus.shiftKey)this._keyStatus.lastKeyPressed="shift";else if(We.keyCode!==6)this._keyStatus.lastKeyPressed=void 0;else return;this._keyStatus.altKey=Se.altKey,this._keyStatus.ctrlKey=Se.ctrlKey,this._keyStatus.metaKey=Se.metaKey,this._keyStatus.shiftKey=Se.shiftKey,this._keyStatus.lastKeyPressed&&(this._keyStatus.event=Se,this.fire(this._keyStatus))}},!0)),Re.add(l(Ie,"keyup",Se=>{Se.defaultPrevented||(!Se.altKey&&this._keyStatus.altKey?this._keyStatus.lastKeyReleased="alt":!Se.ctrlKey&&this._keyStatus.ctrlKey?this._keyStatus.lastKeyReleased="ctrl":!Se.metaKey&&this._keyStatus.metaKey?this._keyStatus.lastKeyReleased="meta":!Se.shiftKey&&this._keyStatus.shiftKey?this._keyStatus.lastKeyReleased="shift":this._keyStatus.lastKeyReleased=void 0,this._keyStatus.lastKeyPressed!==this._keyStatus.lastKeyReleased&&(this._keyStatus.lastKeyPressed=void 0),this._keyStatus.altKey=Se.altKey,this._keyStatus.ctrlKey=Se.ctrlKey,this._keyStatus.metaKey=Se.metaKey,this._keyStatus.shiftKey=Se.shiftKey,this._keyStatus.lastKeyReleased&&(this._keyStatus.event=Se,this.fire(this._keyStatus)))},!0)),Re.add(l(Ie.document.body,"mousedown",()=>{this._keyStatus.lastKeyPressed=void 0},!0)),Re.add(l(Ie.document.body,"mouseup",()=>{this._keyStatus.lastKeyPressed=void 0},!0)),Re.add(l(Ie.document.body,"mousemove",Se=>{Se.buttons&&(this._keyStatus.lastKeyPressed=void 0)},!0)),Re.add(l(Ie,"blur",()=>{this.resetKeyStatus()}))}get keyStatus(){return this._keyStatus}resetKeyStatus(){this.doResetKeyStatus(),this.fire(this._keyStatus)}doResetKeyStatus(){this._keyStatus={altKey:!1,shiftKey:!1,ctrlKey:!1,metaKey:!1}}static getInstance(){return et.instance||(et.instance=new et),et.instance}dispose(){super.dispose(),this._subscriptions.dispose()}}e.ModifierKeyEmitter=et;class dt extends p.Disposable{constructor(Ie,Re){super(),this.element=Ie,this.callbacks=Re,this.counter=0,this.dragStartTime=0,this.registerListeners()}registerListeners(){this.callbacks.onDragStart&&this._register(l(this.element,e.EventType.DRAG_START,Ie=>{this.callbacks.onDragStart?.(Ie)})),this.callbacks.onDrag&&this._register(l(this.element,e.EventType.DRAG,Ie=>{this.callbacks.onDrag?.(Ie)})),this._register(l(this.element,e.EventType.DRAG_ENTER,Ie=>{this.counter++,this.dragStartTime=Ie.timeStamp,this.callbacks.onDragEnter?.(Ie)})),this._register(l(this.element,e.EventType.DRAG_OVER,Ie=>{Ie.preventDefault(),this.callbacks.onDragOver?.(Ie,Ie.timeStamp-this.dragStartTime)})),this._register(l(this.element,e.EventType.DRAG_LEAVE,Ie=>{this.counter--,this.counter===0&&(this.dragStartTime=0,this.callbacks.onDragLeave?.(Ie))})),this._register(l(this.element,e.EventType.DRAG_END,Ie=>{this.counter=0,this.dragStartTime=0,this.callbacks.onDragEnd?.(Ie)})),this._register(l(this.element,e.EventType.DROP,Ie=>{this.counter=0,this.dragStartTime=0,this.callbacks.onDrop?.(Ie)}))}}e.DragAndDropObserver=dt;const at=/(?[\w\-]+)?(?:#(?[\w\-]+))?(?(?:\.(?:[\w\-]+))*)(?:@(?(?:[\w\_])+))?/;function st(De,...Ie){let Re,Se;Array.isArray(Ie[0])?(Re={},Se=Ie[0]):(Re=Ie[0]||{},Se=Ie[1]);const We=at.exec(De);if(!We||!We.groups)throw new Error("Bad use of h");const qe=We.groups.tag||"div",Ue=document.createElement(qe);We.groups.id&&(Ue.id=We.groups.id);const Je=[];if(We.groups.class)for(const Qe of We.groups.class.split("."))Qe!==""&&Je.push(Qe);if(Re.className!==void 0)for(const Qe of Re.className.split("."))Qe!==""&&Je.push(Qe);Je.length>0&&(Ue.className=Je.join(" "));const tt={};if(We.groups.name&&(tt[We.groups.name]=Ue),Se)for(const Qe of Se)re(Qe)?Ue.appendChild(Qe):typeof Qe=="string"?Ue.append(Qe):"root"in Qe&&(Object.assign(tt,Qe),Ue.appendChild(Qe.root));for(const[Qe,rt]of Object.entries(Re))if(Qe!=="className")if(Qe==="style")for(const[Ct,ut]of Object.entries(rt))Ue.style.setProperty(bt(Ct),typeof ut=="number"?ut+"px":""+ut);else Qe==="tabIndex"?Ue.tabIndex=rt:Ue.setAttribute(bt(Qe),rt.toString());return tt.root=Ue,tt}function pt(De,...Ie){let Re,Se;Array.isArray(Ie[0])?(Re={},Se=Ie[0]):(Re=Ie[0]||{},Se=Ie[1]);const We=at.exec(De);if(!We||!We.groups)throw new Error("Bad use of h");const qe=We.groups.tag||"div",Ue=document.createElementNS("http://www.w3.org/2000/svg",qe);We.groups.id&&(Ue.id=We.groups.id);const Je=[];if(We.groups.class)for(const Qe of We.groups.class.split("."))Qe!==""&&Je.push(Qe);if(Re.className!==void 0)for(const Qe of Re.className.split("."))Qe!==""&&Je.push(Qe);Je.length>0&&(Ue.className=Je.join(" "));const tt={};if(We.groups.name&&(tt[We.groups.name]=Ue),Se)for(const Qe of Se)re(Qe)?Ue.appendChild(Qe):typeof Qe=="string"?Ue.append(Qe):"root"in Qe&&(Object.assign(tt,Qe),Ue.appendChild(Qe.root));for(const[Qe,rt]of Object.entries(Re))if(Qe!=="className")if(Qe==="style")for(const[Ct,ut]of Object.entries(rt))Ue.style.setProperty(bt(Ct),typeof ut=="number"?ut+"px":""+ut);else Qe==="tabIndex"?Ue.tabIndex=rt:Ue.setAttribute(bt(Qe),rt.toString());return tt.root=Ue,tt}function bt(De){return De.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}}),define(ne[630],se([1,0,5,2,21]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.createStyleSheetFromObservable=E;function E(y){const m=new k.DisposableStore,_=m.add((0,d.createStyleSheet2)());return m.add((0,I.autorun)(b=>{_.setStyle(y.read(b))})),m}}),define(ne[352],se([1,0,5]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.renderText=k,e.renderFormattedText=I,e.createElement=E;function k(n,o={}){const t=E(o);return t.textContent=n,t}function I(n,o={}){const t=E(o);return m(t,_(n,!!o.renderCodeSegments),o.actionHandler,o.renderCodeSegments),t}function E(n){const o=n.inline?"span":"div",t=document.createElement(o);return n.className&&(t.className=n.className),t}class y{constructor(o){this.source=o,this.index=0}eos(){return this.index>=this.source.length}next(){const o=this.peek();return this.advance(),o}peek(){return this.source[this.index]}advance(){this.index++}}function m(n,o,t,i){let s;if(o.type===2)s=document.createTextNode(o.content||"");else if(o.type===3)s=document.createElement("b");else if(o.type===4)s=document.createElement("i");else if(o.type===7&&i)s=document.createElement("code");else if(o.type===5&&t){const g=document.createElement("a");t.disposables.add(d.addStandardDisposableListener(g,"click",c=>{t.callback(String(o.index),c)})),s=g}else o.type===8?s=document.createElement("br"):o.type===1&&(s=n);s&&n!==s&&n.appendChild(s),s&&Array.isArray(o.children)&&o.children.forEach(g=>{m(s,g,t,i)})}function _(n,o){const t={type:1,children:[]};let i=0,s=t;const g=[],c=new y(n);for(;!c.eos();){let l=c.next();const a=l==="\\"&&p(c.peek(),o)!==0;if(a&&(l=c.next()),!a&&b(l,o)&&l===c.peek()){c.advance(),s.type===2&&(s=g.pop());const r=p(l,o);if(s.type===r||s.type===5&&r===6)s=g.pop();else{const u={type:r,children:[]};r===5&&(u.index=i,i++),s.children.push(u),g.push(s),s=u}}else if(l===` `)s.type===2&&(s=g.pop()),s.children.push({type:8});else if(s.type!==2){const r={type:2,content:l};s.children.push(r),g.push(s),s=r}else s.content+=l}return s.type===2&&(s=g.pop()),g.length,t}function b(n,o){return p(n,o)!==0}function p(n,o){switch(n){case"*":return 3;case"_":return 4;case"[":return 5;case"]":return 6;case"`":return o?7:0;default:return 0}}}),define(ne[172],se([1,0,5,2]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GlobalPointerMoveMonitor=void 0;class I{constructor(){this._hooks=new k.DisposableStore,this._pointerMoveCallback=null,this._onStopCallback=null}dispose(){this.stopMonitoring(!1),this._hooks.dispose()}stopMonitoring(y,m){if(!this.isMonitoring())return;this._hooks.clear(),this._pointerMoveCallback=null;const _=this._onStopCallback;this._onStopCallback=null,y&&_&&_(m)}isMonitoring(){return!!this._pointerMoveCallback}startMonitoring(y,m,_,b,p){this.isMonitoring()&&this.stopMonitoring(!1),this._pointerMoveCallback=b,this._onStopCallback=p;let n=y;try{y.setPointerCapture(m),this._hooks.add((0,k.toDisposable)(()=>{try{y.releasePointerCapture(m)}catch{}}))}catch{n=d.getWindow(y)}this._hooks.add(d.addDisposableListener(n,d.EventType.POINTER_MOVE,o=>{if(o.buttons!==_){this.stopMonitoring(!0);return}o.preventDefault(),this._pointerMoveCallback(o)})),this._hooks.add(d.addDisposableListener(n,d.EventType.POINTER_UP,o=>this.stopMonitoring(!0)))}}e.GlobalPointerMoveMonitor=I}),define(ne[253],se([1,0,5,6,2]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PixelRatio=void 0;class E extends I.Disposable{constructor(b){super(),this._onDidChange=this._register(new k.Emitter),this.onDidChange=this._onDidChange.event,this._listener=()=>this._handleChange(b,!0),this._mediaQueryList=null,this._handleChange(b,!1)}_handleChange(b,p){this._mediaQueryList?.removeEventListener("change",this._listener),this._mediaQueryList=b.matchMedia(`(resolution: ${b.devicePixelRatio}dppx)`),this._mediaQueryList.addEventListener("change",this._listener),p&&this._onDidChange.fire()}}class y extends I.Disposable{get value(){return this._value}constructor(b){super(),this._onDidChange=this._register(new k.Emitter),this.onDidChange=this._onDidChange.event,this._value=this._getPixelRatio(b);const p=this._register(new E(b));this._register(p.onDidChange(()=>{this._value=this._getPixelRatio(b),this._onDidChange.fire(this._value)}))}_getPixelRatio(b){const p=document.createElement("canvas").getContext("2d"),n=b.devicePixelRatio||1,o=p.webkitBackingStorePixelRatio||p.mozBackingStorePixelRatio||p.msBackingStorePixelRatio||p.oBackingStorePixelRatio||p.backingStorePixelRatio||1;return n/o}}class m{constructor(){this.mapWindowIdToPixelRatioMonitor=new Map}_getOrCreatePixelRatioMonitor(b){const p=(0,d.getWindowId)(b);let n=this.mapWindowIdToPixelRatioMonitor.get(p);return n||(n=(0,I.markAsSingleton)(new y(b)),this.mapWindowIdToPixelRatioMonitor.set(p,n),(0,I.markAsSingleton)(k.Event.once(d.onDidUnregisterWindow)(({vscodeWindowId:o})=>{o===p&&(n?.dispose(),this.mapWindowIdToPixelRatioMonitor.delete(p))}))),n}getInstance(b){return this._getOrCreatePixelRatioMonitor(b)}}e.PixelRatio=new m}),define(ne[69],se([1,0,5,52,13,126,6,2,73]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Gesture=e.EventType=void 0;var b;(function(n){n.Tap="-monaco-gesturetap",n.Change="-monaco-gesturechange",n.Start="-monaco-gesturestart",n.End="-monaco-gesturesend",n.Contextmenu="-monaco-gesturecontextmenu"})(b||(e.EventType=b={}));class p extends m.Disposable{static{this.SCROLL_FRICTION=-.005}static{this.HOLD_DELAY=700}static{this.CLEAR_TAP_COUNT_TIME=400}constructor(){super(),this.dispatched=!1,this.targets=new _.LinkedList,this.ignoreTargets=new _.LinkedList,this.activeTouches={},this.handle=null,this._lastSetTapCountTime=0,this._register(y.Event.runAndSubscribe(d.onDidRegisterWindow,({window:o,disposables:t})=>{t.add(d.addDisposableListener(o.document,"touchstart",i=>this.onTouchStart(i),{passive:!1})),t.add(d.addDisposableListener(o.document,"touchend",i=>this.onTouchEnd(o,i))),t.add(d.addDisposableListener(o.document,"touchmove",i=>this.onTouchMove(i),{passive:!1}))},{window:k.mainWindow,disposables:this._store}))}static addTarget(o){if(!p.isTouchDevice())return m.Disposable.None;p.INSTANCE||(p.INSTANCE=(0,m.markAsSingleton)(new p));const t=p.INSTANCE.targets.push(o);return(0,m.toDisposable)(t)}static ignoreTarget(o){if(!p.isTouchDevice())return m.Disposable.None;p.INSTANCE||(p.INSTANCE=(0,m.markAsSingleton)(new p));const t=p.INSTANCE.ignoreTargets.push(o);return(0,m.toDisposable)(t)}static isTouchDevice(){return"ontouchstart"in k.mainWindow||navigator.maxTouchPoints>0}dispose(){this.handle&&(this.handle.dispose(),this.handle=null),super.dispose()}onTouchStart(o){const t=Date.now();this.handle&&(this.handle.dispose(),this.handle=null);for(let i=0,s=o.targetTouches.length;i=p.HOLD_DELAY&&Math.abs(a.initialPageX-I.tail(a.rollingPageX))<30&&Math.abs(a.initialPageY-I.tail(a.rollingPageY))<30){const u=this.newGestureEvent(b.Contextmenu,a.initialTarget);u.pageX=I.tail(a.rollingPageX),u.pageY=I.tail(a.rollingPageY),this.dispatchEvent(u)}else if(s===1){const u=I.tail(a.rollingPageX),C=I.tail(a.rollingPageY),f=I.tail(a.rollingTimestamps)-a.rollingTimestamps[0],h=u-a.rollingPageX[0],v=C-a.rollingPageY[0],w=[...this.targets].filter(S=>a.initialTarget instanceof Node&&S.contains(a.initialTarget));this.inertia(o,w,i,Math.abs(h)/f,h>0?1:-1,u,Math.abs(v)/f,v>0?1:-1,C)}this.dispatchEvent(this.newGestureEvent(b.End,a.initialTarget)),delete this.activeTouches[l.identifier]}this.dispatched&&(t.preventDefault(),t.stopPropagation(),this.dispatched=!1)}newGestureEvent(o,t){const i=document.createEvent("CustomEvent");return i.initEvent(o,!1,!0),i.initialTarget=t,i.tapCount=0,i}dispatchEvent(o){if(o.type===b.Tap){const t=new Date().getTime();let i=0;t-this._lastSetTapCountTime>p.CLEAR_TAP_COUNT_TIME?i=1:i=2,this._lastSetTapCountTime=t,o.tapCount=i}else(o.type===b.Change||o.type===b.Contextmenu)&&(this._lastSetTapCountTime=0);if(o.initialTarget instanceof Node){for(const i of this.ignoreTargets)if(i.contains(o.initialTarget))return;const t=[];for(const i of this.targets)if(i.contains(o.initialTarget)){let s=0,g=o.initialTarget;for(;g&&g!==i;)s++,g=g.parentElement;t.push([s,i])}t.sort((i,s)=>i[0]-s[0]);for(const[i,s]of t)s.dispatchEvent(o),this.dispatched=!0}}inertia(o,t,i,s,g,c,l,a,r){this.handle=d.scheduleAtNextAnimationFrame(o,()=>{const u=Date.now(),C=u-i;let f=0,h=0,v=!0;s+=p.SCROLL_FRICTION*C,l+=p.SCROLL_FRICTION*C,s>0&&(v=!1,f=g*s*C),l>0&&(v=!1,h=a*l*C);const w=this.newGestureEvent(b.Change);w.translationX=f,w.translationY=h,t.forEach(S=>S.dispatchEvent(w)),v||this.inertia(o,t,u,s,g,c+f,l,a,r+h)})}onTouchMove(o){const t=Date.now();for(let i=0,s=o.changedTouches.length;i3&&(c.rollingPageX.shift(),c.rollingPageY.shift(),c.rollingTimestamps.shift()),c.rollingPageX.push(g.pageX),c.rollingPageY.push(g.pageY),c.rollingTimestamps.push(t)}this.dispatched&&(o.preventDefault(),o.stopPropagation(),this.dispatched=!1)}}e.Gesture=p,ke([E.memoize],p,"isTouchDevice",null)}),define(ne[46],se([1,0,5,458]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setARIAContainer=b,e.alert=p,e.status=n;const k=2e4;let I,E,y,m,_;function b(t){I=document.createElement("div"),I.className="monaco-aria-container";const i=()=>{const g=document.createElement("div");return g.className="monaco-alert",g.setAttribute("role","alert"),g.setAttribute("aria-atomic","true"),I.appendChild(g),g};E=i(),y=i();const s=()=>{const g=document.createElement("div");return g.className="monaco-status",g.setAttribute("aria-live","polite"),g.setAttribute("aria-atomic","true"),I.appendChild(g),g};m=s(),_=s(),t.appendChild(I)}function p(t){I&&(E.textContent!==t?(d.clearNode(y),o(E,t)):(d.clearNode(E),o(y,t)))}function n(t){I&&(m.textContent!==t?(d.clearNode(_),o(m,t)):(d.clearNode(m),o(_,t)))}function o(t,i){d.clearNode(t),i.length>k&&(i=i.substr(0,k)),t.textContent=i,t.style.visibility="hidden",t.style.visibility="visible"}}),define(ne[353],se([1,0,248,5,2,16,188,462]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContextView=e.LayoutAnchorMode=void 0,e.isAnchor=m,e.layout=b;function m(o){const t=o;return!!t&&typeof t.x=="number"&&typeof t.y=="number"}var _;(function(o){o[o.AVOID=0]="AVOID",o[o.ALIGN=1]="ALIGN"})(_||(e.LayoutAnchorMode=_={}));function b(o,t,i){const s=i.mode===_.ALIGN?i.offset:i.offset+i.size,g=i.mode===_.ALIGN?i.offset+i.size:i.offset;return i.position===0?t<=o-s?s:t<=g?g-t:Math.max(o-t,0):t<=g?g-t:t<=o-s?s:0}class p extends I.Disposable{static{this.BUBBLE_UP_EVENTS=["click","keydown","focus","blur"]}static{this.BUBBLE_DOWN_EVENTS=["click"]}constructor(t,i){super(),this.container=null,this.useFixedPosition=!1,this.useShadowDOM=!1,this.delegate=null,this.toDisposeOnClean=I.Disposable.None,this.toDisposeOnSetContainer=I.Disposable.None,this.shadowRoot=null,this.shadowRootHostElement=null,this.view=k.$(".context-view"),k.hide(this.view),this.setContainer(t,i),this._register((0,I.toDisposable)(()=>this.setContainer(null,1)))}setContainer(t,i){this.useFixedPosition=i!==1;const s=this.useShadowDOM;if(this.useShadowDOM=i===3,!(t===this.container&&s===this.useShadowDOM)&&(this.container&&(this.toDisposeOnSetContainer.dispose(),this.view.remove(),this.shadowRoot&&(this.shadowRoot=null,this.shadowRootHostElement?.remove(),this.shadowRootHostElement=null),this.container=null),t)){if(this.container=t,this.useShadowDOM){this.shadowRootHostElement=k.$(".shadow-root-host"),this.container.appendChild(this.shadowRootHostElement),this.shadowRoot=this.shadowRootHostElement.attachShadow({mode:"open"});const c=document.createElement("style");c.textContent=n,this.shadowRoot.appendChild(c),this.shadowRoot.appendChild(this.view),this.shadowRoot.appendChild(k.$("slot"))}else this.container.appendChild(this.view);const g=new I.DisposableStore;p.BUBBLE_UP_EVENTS.forEach(c=>{g.add(k.addStandardDisposableListener(this.container,c,l=>{this.onDOMEvent(l,!1)}))}),p.BUBBLE_DOWN_EVENTS.forEach(c=>{g.add(k.addStandardDisposableListener(this.container,c,l=>{this.onDOMEvent(l,!0)},!0))}),this.toDisposeOnSetContainer=g}}show(t){this.isVisible()&&this.hide(),k.clearNode(this.view),this.view.className="context-view monaco-component",this.view.style.top="0px",this.view.style.left="0px",this.view.style.zIndex=`${2575+(t.layer??0)}`,this.view.style.position=this.useFixedPosition?"fixed":"absolute",k.show(this.view),this.toDisposeOnClean=t.render(this.view)||I.Disposable.None,this.delegate=t,this.doLayout(),this.delegate.focus?.()}getViewElement(){return this.view}layout(){if(this.isVisible()){if(this.delegate.canRelayout===!1&&!(E.isIOS&&d.BrowserFeatures.pointerEvents)){this.hide();return}this.delegate?.layout?.(),this.doLayout()}}doLayout(){if(!this.isVisible())return;const t=this.delegate.getAnchor();let i;if(k.isHTMLElement(t)){const h=k.getDomNodePagePosition(t),v=k.getDomNodeZoomLevel(t);i={top:h.top*v,left:h.left*v,width:h.width*v,height:h.height*v}}else m(t)?i={top:t.y,left:t.x,width:t.width||1,height:t.height||2}:i={top:t.posy,left:t.posx,width:2,height:2};const s=k.getTotalWidth(this.view),g=k.getTotalHeight(this.view),c=this.delegate.anchorPosition||0,l=this.delegate.anchorAlignment||0,a=this.delegate.anchorAxisAlignment||0;let r,u;const C=k.getActiveWindow();if(a===0){const h={offset:i.top-C.pageYOffset,size:i.height,position:c===0?0:1},v={offset:i.left,size:i.width,position:l===0?0:1,mode:_.ALIGN};r=b(C.innerHeight,g,h)+C.pageYOffset,y.Range.intersects({start:r,end:r+g},{start:h.offset,end:h.offset+h.size})&&(v.mode=_.AVOID),u=b(C.innerWidth,s,v)}else{const h={offset:i.left,size:i.width,position:l===0?0:1},v={offset:i.top,size:i.height,position:c===0?0:1,mode:_.ALIGN};u=b(C.innerWidth,s,h),y.Range.intersects({start:u,end:u+s},{start:h.offset,end:h.offset+h.size})&&(v.mode=_.AVOID),r=b(C.innerHeight,g,v)+C.pageYOffset}this.view.classList.remove("top","bottom","left","right"),this.view.classList.add(c===0?"bottom":"top"),this.view.classList.add(l===0?"left":"right"),this.view.classList.toggle("fixed",this.useFixedPosition);const f=k.getDomNodePagePosition(this.container);this.view.style.top=`${r-(this.useFixedPosition?k.getDomNodePagePosition(this.view).top:f.top)}px`,this.view.style.left=`${u-(this.useFixedPosition?k.getDomNodePagePosition(this.view).left:f.left)}px`,this.view.style.width="initial"}hide(t){const i=this.delegate;this.delegate=null,i?.onHide&&i.onHide(t),this.toDisposeOnClean.dispose(),k.hide(this.view)}isVisible(){return!!this.delegate}onDOMEvent(t,i){this.delegate&&(this.delegate.onDOMEvent?this.delegate.onDOMEvent(t,k.getWindow(t).document.activeElement):i&&!k.isAncestor(t.target,this.container)&&this.hide())}dispose(){this.hide(),super.dispose()}}e.ContextView=p;const n=` :host { all: initial; /* 1st rule so subsequent properties are reset. */ } .codicon[class*='codicon-'] { font: normal normal normal 16px/1 codicon; display: inline-block; text-decoration: none; text-rendering: auto; text-align: center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; user-select: none; -webkit-user-select: none; -ms-user-select: none; } :host { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", system-ui, "Ubuntu", "Droid Sans", sans-serif; } :host-context(.mac) { font-family: -apple-system, BlinkMacSystemFont, sans-serif; } :host-context(.mac:lang(zh-Hans)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; } :host-context(.mac:lang(zh-Hant)) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; } :host-context(.mac:lang(ja)) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; } :host-context(.mac:lang(ko)) { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; } :host-context(.windows) { font-family: "Segoe WPC", "Segoe UI", sans-serif; } :host-context(.windows:lang(zh-Hans)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; } :host-context(.windows:lang(zh-Hant)) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; } :host-context(.windows:lang(ja)) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; } :host-context(.windows:lang(ko)) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; } :host-context(.linux) { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; } :host-context(.linux:lang(zh-Hans)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; } :host-context(.linux:lang(zh-Hant)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; } :host-context(.linux:lang(ja)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; } :host-context(.linux:lang(ko)) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; } `}),define(ne[354],se([1,0,5,11,463]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CountBadge=void 0;class I{constructor(y,m,_){this.options=m,this.styles=_,this.count=0,this.element=(0,d.append)(y,(0,d.$)(".monaco-count-badge")),this.countFormat=this.options.countFormat||"{0}",this.titleFormat=this.options.titleFormat||"",this.setCount(this.options.count||0)}setCount(y){this.count=y,this.render()}setTitleFormat(y){this.titleFormat=y,this.render()}render(){this.element.textContent=(0,k.format)(this.countFormat,this.count),this.element.title=(0,k.format)(this.titleFormat,this.count),this.element.style.backgroundColor=this.styles.badgeBackground??"",this.element.style.color=this.styles.badgeForeground??"",this.styles.badgeBorder&&(this.element.style.border=`1px solid ${this.styles.badgeBorder}`)}}e.CountBadge=I}),define(ne[631],se([1,0,5,47,69,41,6,303]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DropdownMenu=void 0;class m extends E.ActionRunner{constructor(p,n){super(),this._onDidChangeVisibility=this._register(new y.Emitter),this.onDidChangeVisibility=this._onDidChangeVisibility.event,this._element=(0,d.append)(p,(0,d.$)(".monaco-dropdown")),this._label=(0,d.append)(this._element,(0,d.$)(".dropdown-label"));let o=n.labelRenderer;o||(o=i=>(i.textContent=n.label||"",null));for(const i of[d.EventType.CLICK,d.EventType.MOUSE_DOWN,I.EventType.Tap])this._register((0,d.addDisposableListener)(this.element,i,s=>d.EventHelper.stop(s,!0)));for(const i of[d.EventType.MOUSE_DOWN,I.EventType.Tap])this._register((0,d.addDisposableListener)(this._label,i,s=>{(0,d.isMouseEvent)(s)&&(s.detail>1||s.button!==0)||(this.visible?this.hide():this.show())}));this._register((0,d.addDisposableListener)(this._label,d.EventType.KEY_UP,i=>{const s=new k.StandardKeyboardEvent(i);(s.equals(3)||s.equals(10))&&(d.EventHelper.stop(i,!0),this.visible?this.hide():this.show())}));const t=o(this._label);t&&this._register(t),this._register(I.Gesture.addTarget(this._label))}get element(){return this._element}show(){this.visible||(this.visible=!0,this._onDidChangeVisibility.fire(!0))}hide(){this.visible&&(this.visible=!1,this._onDidChangeVisibility.fire(!1))}dispose(){super.dispose(),this.hide(),this.boxContainer&&(this.boxContainer.remove(),this.boxContainer=void 0),this.contents&&(this.contents.remove(),this.contents=void 0),this._label&&(this._label.remove(),this._label=void 0)}}class _ extends m{constructor(p,n){super(p,n),this._options=n,this._actions=[],this.actions=n.actions||[]}set menuOptions(p){this._menuOptions=p}get menuOptions(){return this._menuOptions}get actions(){return this._options.actionProvider?this._options.actionProvider.getActions():this._actions}set actions(p){this._actions=p}show(){super.show(),this.element.classList.add("active"),this._options.contextMenuProvider.showContextMenu({getAnchor:()=>this.element,getActions:()=>this.actions,getActionsContext:()=>this.menuOptions?this.menuOptions.context:null,getActionViewItem:(p,n)=>this.menuOptions&&this.menuOptions.actionViewItemProvider?this.menuOptions.actionViewItemProvider(p,n):void 0,getKeyBinding:p=>this.menuOptions&&this.menuOptions.getKeyBinding?this.menuOptions.getKeyBinding(p):void 0,getMenuClassName:()=>this._options.menuClassName||"",onHide:()=>this.onHide(),actionRunner:this.menuOptions?this.menuOptions.actionRunner:void 0,anchorAlignment:this.menuOptions?this.menuOptions.anchorAlignment:0,domForShadowRoot:this._options.menuAsChild?this.element:void 0,skipTelemetry:this._options.skipTelemetry})}hide(){super.hide()}onHide(){this.hide(),this.element.classList.remove("active")}}e.DropdownMenu=_}),define(ne[114],se([1,0,5,30]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.renderLabelWithIcons=E,e.renderIcon=y;const I=new RegExp(`(\\\\)?\\$\\((${k.ThemeIcon.iconNameExpression}(?:${k.ThemeIcon.iconModifierExpression})?)\\)`,"g");function E(m){const _=new Array;let b,p=0,n=0;for(;(b=I.exec(m))!==null;){n=b.index||0,p{t=i===`\r `?-1:0,s+=o;for(const g of n)g.end<=s||(g.start>=s&&(g.start+=t),g.end>=s&&(g.end+=t));return o+=t,"\u23CE"})}}e.HighlightedLabel=_}),define(ne[254],se([1,0,5,355,2,60,188,44,81,19,142,465]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IconLabel=void 0;class n{constructor(c){this._element=c}get element(){return this._element}set textContent(c){this.disposed||c===this._textContent||(this._textContent=c,this._element.textContent=c)}set classNames(c){this.disposed||(0,E.equals)(c,this._classNames)||(this._classNames=c,this._element.classList.value="",this._element.classList.add(...c))}set empty(c){this.disposed||c===this._empty||(this._empty=c,this._element.style.marginLeft=c?"0":"")}dispose(){this.disposed=!0}}class o extends I.Disposable{constructor(c,l){super(),this.customHovers=new Map,this.creationOptions=l,this.domNode=this._register(new n(d.append(c,d.$(".monaco-icon-label")))),this.labelContainer=d.append(this.domNode.element,d.$(".monaco-icon-label-container")),this.nameContainer=d.append(this.labelContainer,d.$("span.monaco-icon-name-container")),l?.supportHighlights||l?.supportIcons?this.nameNode=this._register(new s(this.nameContainer,!!l.supportIcons)):this.nameNode=new t(this.nameContainer),this.hoverDelegate=l?.hoverDelegate??(0,m.getDefaultHoverDelegate)("mouse")}get element(){return this.domNode.element}setLabel(c,l,a){const r=["monaco-icon-label"],u=["monaco-icon-label-container"];let C="";a&&(a.extraClasses&&r.push(...a.extraClasses),a.italic&&r.push("italic"),a.strikethrough&&r.push("strikethrough"),a.disabledCommand&&u.push("disabled"),a.title&&(typeof a.title=="string"?C+=a.title:C+=c));const f=this.domNode.element.querySelector(".monaco-icon-label-iconpath");if(a?.iconPath){let h;!f||!d.isHTMLElement(f)?(h=d.$(".monaco-icon-label-iconpath"),this.domNode.element.prepend(h)):h=f,h.style.backgroundImage=d.asCSSUrl(a?.iconPath)}else f&&f.remove();if(this.domNode.classNames=r,this.domNode.element.setAttribute("aria-label",C),this.labelContainer.classList.value="",this.labelContainer.classList.add(...u),this.setupHover(a?.descriptionTitle?this.labelContainer:this.element,a?.title),this.nameNode.setLabel(c,a),l||this.descriptionNode){const h=this.getOrCreateDescriptionNode();h instanceof k.HighlightedLabel?(h.set(l||"",a?a.descriptionMatches:void 0,void 0,a?.labelEscapeNewLines),this.setupHover(h.element,a?.descriptionTitle)):(h.textContent=l&&a?.labelEscapeNewLines?k.HighlightedLabel.escapeNewLines(l,[]):l||"",this.setupHover(h.element,a?.descriptionTitle||""),h.empty=!l)}if(a?.suffix||this.suffixNode){const h=this.getOrCreateSuffixNode();h.textContent=a?.suffix??""}}setupHover(c,l){const a=this.customHovers.get(c);if(a&&(a.dispose(),this.customHovers.delete(c)),!l){c.removeAttribute("title");return}if(this.hoverDelegate.showNativeHover)(function(u,C){(0,b.isString)(C)?u.title=(0,p.stripIcons)(C):C?.markdownNotSupportedFallback?u.title=C.markdownNotSupportedFallback:u.removeAttribute("title")})(c,l);else{const r=(0,_.getBaseLayerHoverDelegate)().setupManagedHover(this.hoverDelegate,c,l);r&&this.customHovers.set(c,r)}}dispose(){super.dispose();for(const c of this.customHovers.values())c.dispose();this.customHovers.clear()}getOrCreateSuffixNode(){if(!this.suffixNode){const c=this._register(new n(d.after(this.nameContainer,d.$("span.monaco-icon-suffix-container"))));this.suffixNode=this._register(new n(d.append(c.element,d.$("span.label-suffix"))))}return this.suffixNode}getOrCreateDescriptionNode(){if(!this.descriptionNode){const c=this._register(new n(d.append(this.labelContainer,d.$("span.monaco-icon-description-container"))));this.creationOptions?.supportDescriptionHighlights?this.descriptionNode=this._register(new k.HighlightedLabel(d.append(c.element,d.$("span.label-description")),{supportIcons:!!this.creationOptions.supportIcons})):this.descriptionNode=this._register(new n(d.append(c.element,d.$("span.label-description"))))}return this.descriptionNode}}e.IconLabel=o;class t{constructor(c){this.container=c,this.label=void 0,this.singleLabel=void 0}setLabel(c,l){if(!(this.label===c&&(0,E.equals)(this.options,l)))if(this.label=c,this.options=l,typeof c=="string")this.singleLabel||(this.container.innerText="",this.container.classList.remove("multiple"),this.singleLabel=d.append(this.container,d.$("a.label-name",{id:l?.domId}))),this.singleLabel.textContent=c;else{this.container.innerText="",this.container.classList.add("multiple"),this.singleLabel=void 0;for(let a=0;a{const u={start:a,end:a+r.length},C=l.map(f=>y.Range.intersect(u,f)).filter(f=>!y.Range.isEmpty(f)).map(({start:f,end:h})=>({start:f-a,end:h-a}));return a=u.end+c.length,C})}class s extends I.Disposable{constructor(c,l){super(),this.container=c,this.supportIcons=l,this.label=void 0,this.singleLabel=void 0}setLabel(c,l){if(!(this.label===c&&(0,E.equals)(this.options,l)))if(this.label=c,this.options=l,typeof c=="string")this.singleLabel||(this.container.innerText="",this.container.classList.remove("multiple"),this.singleLabel=this._register(new k.HighlightedLabel(d.append(this.container,d.$("a.label-name",{id:l?.domId})),{supportIcons:this.supportIcons}))),this.singleLabel.set(c,l?.matches,void 0,l?.labelEscapeNewLines);else{this.container.innerText="",this.container.classList.add("multiple"),this.singleLabel=void 0;const a=l?.separator||"/",r=i(c,a,l?.matches);for(let u=0;u{for(const m of E)this.getRenderer(y).disposeTemplate(m.templateData),m.templateData=null}),this.cache.clear(),this.transactionNodesPendingRemoval.clear()}getRenderer(E){const y=this.renderers.get(E);if(!y)throw new Error(`No renderer found for ${E}`);return y}}e.RowCache=k}),define(ne[633],se([1,0,5,14,2,469]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ProgressBar=void 0;const E="done",y="active",m="infinite",_="infinite-long-running",b="discrete";class p extends I.Disposable{static{this.LONG_RUNNING_INFINITE_THRESHOLD=1e4}constructor(o,t){super(),this.progressSignal=this._register(new I.MutableDisposable),this.workedVal=0,this.showDelayedScheduler=this._register(new k.RunOnceScheduler(()=>(0,d.show)(this.element),0)),this.longRunningScheduler=this._register(new k.RunOnceScheduler(()=>this.infiniteLongRunning(),p.LONG_RUNNING_INFINITE_THRESHOLD)),this.create(o,t)}create(o,t){this.element=document.createElement("div"),this.element.classList.add("monaco-progress-container"),this.element.setAttribute("role","progressbar"),this.element.setAttribute("aria-valuemin","0"),o.appendChild(this.element),this.bit=document.createElement("div"),this.bit.classList.add("progress-bit"),this.bit.style.backgroundColor=t?.progressBarBackground||"#0E70C0",this.element.appendChild(this.bit)}off(){this.bit.style.width="inherit",this.bit.style.opacity="1",this.element.classList.remove(y,m,_,b),this.workedVal=0,this.totalWork=void 0,this.longRunningScheduler.cancel(),this.progressSignal.clear()}stop(){return this.doDone(!1)}doDone(o){return this.element.classList.add(E),this.element.classList.contains(m)?(this.bit.style.opacity="0",o?setTimeout(()=>this.off(),200):this.off()):(this.bit.style.width="inherit",o?setTimeout(()=>this.off(),200):this.off()),this}infinite(){return this.bit.style.width="2%",this.bit.style.opacity="1",this.element.classList.remove(b,E,_),this.element.classList.add(y,m),this.longRunningScheduler.schedule(),this}infiniteLongRunning(){this.element.classList.add(_)}getContainer(){return this.element}}e.ProgressBar=p}),define(ne[173],se([1,0,5,93,69,14,126,6,2,16,470]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Sash=e.OrthogonalEdge=void 0;const p=!1;var n;(function(u){u.North="north",u.South="south",u.East="east",u.West="west"})(n||(e.OrthogonalEdge=n={}));let o=4;const t=new m.Emitter;let i=300;const s=new m.Emitter;class g{constructor(C){this.el=C,this.disposables=new _.DisposableStore}get onPointerMove(){return this.disposables.add(new k.DomEmitter((0,d.getWindow)(this.el),"mousemove")).event}get onPointerUp(){return this.disposables.add(new k.DomEmitter((0,d.getWindow)(this.el),"mouseup")).event}dispose(){this.disposables.dispose()}}ke([y.memoize],g.prototype,"onPointerMove",null),ke([y.memoize],g.prototype,"onPointerUp",null);class c{get onPointerMove(){return this.disposables.add(new k.DomEmitter(this.el,I.EventType.Change)).event}get onPointerUp(){return this.disposables.add(new k.DomEmitter(this.el,I.EventType.End)).event}constructor(C){this.el=C,this.disposables=new _.DisposableStore}dispose(){this.disposables.dispose()}}ke([y.memoize],c.prototype,"onPointerMove",null),ke([y.memoize],c.prototype,"onPointerUp",null);class l{get onPointerMove(){return this.factory.onPointerMove}get onPointerUp(){return this.factory.onPointerUp}constructor(C){this.factory=C}dispose(){}}ke([y.memoize],l.prototype,"onPointerMove",null),ke([y.memoize],l.prototype,"onPointerUp",null);const a="pointer-events-disabled";class r extends _.Disposable{get state(){return this._state}get orthogonalStartSash(){return this._orthogonalStartSash}get orthogonalEndSash(){return this._orthogonalEndSash}set state(C){this._state!==C&&(this.el.classList.toggle("disabled",C===0),this.el.classList.toggle("minimum",C===1),this.el.classList.toggle("maximum",C===2),this._state=C,this.onDidEnablementChange.fire(C))}set orthogonalStartSash(C){if(this._orthogonalStartSash!==C){if(this.orthogonalStartDragHandleDisposables.clear(),this.orthogonalStartSashDisposables.clear(),C){const f=h=>{this.orthogonalStartDragHandleDisposables.clear(),h!==0&&(this._orthogonalStartDragHandle=(0,d.append)(this.el,(0,d.$)(".orthogonal-drag-handle.start")),this.orthogonalStartDragHandleDisposables.add((0,_.toDisposable)(()=>this._orthogonalStartDragHandle.remove())),this.orthogonalStartDragHandleDisposables.add(new k.DomEmitter(this._orthogonalStartDragHandle,"mouseenter")).event(()=>r.onMouseEnter(C),void 0,this.orthogonalStartDragHandleDisposables),this.orthogonalStartDragHandleDisposables.add(new k.DomEmitter(this._orthogonalStartDragHandle,"mouseleave")).event(()=>r.onMouseLeave(C),void 0,this.orthogonalStartDragHandleDisposables))};this.orthogonalStartSashDisposables.add(C.onDidEnablementChange.event(f,this)),f(C.state)}this._orthogonalStartSash=C}}set orthogonalEndSash(C){if(this._orthogonalEndSash!==C){if(this.orthogonalEndDragHandleDisposables.clear(),this.orthogonalEndSashDisposables.clear(),C){const f=h=>{this.orthogonalEndDragHandleDisposables.clear(),h!==0&&(this._orthogonalEndDragHandle=(0,d.append)(this.el,(0,d.$)(".orthogonal-drag-handle.end")),this.orthogonalEndDragHandleDisposables.add((0,_.toDisposable)(()=>this._orthogonalEndDragHandle.remove())),this.orthogonalEndDragHandleDisposables.add(new k.DomEmitter(this._orthogonalEndDragHandle,"mouseenter")).event(()=>r.onMouseEnter(C),void 0,this.orthogonalEndDragHandleDisposables),this.orthogonalEndDragHandleDisposables.add(new k.DomEmitter(this._orthogonalEndDragHandle,"mouseleave")).event(()=>r.onMouseLeave(C),void 0,this.orthogonalEndDragHandleDisposables))};this.orthogonalEndSashDisposables.add(C.onDidEnablementChange.event(f,this)),f(C.state)}this._orthogonalEndSash=C}}constructor(C,f,h){super(),this.hoverDelay=i,this.hoverDelayer=this._register(new E.Delayer(this.hoverDelay)),this._state=3,this.onDidEnablementChange=this._register(new m.Emitter),this._onDidStart=this._register(new m.Emitter),this._onDidChange=this._register(new m.Emitter),this._onDidReset=this._register(new m.Emitter),this._onDidEnd=this._register(new m.Emitter),this.orthogonalStartSashDisposables=this._register(new _.DisposableStore),this.orthogonalStartDragHandleDisposables=this._register(new _.DisposableStore),this.orthogonalEndSashDisposables=this._register(new _.DisposableStore),this.orthogonalEndDragHandleDisposables=this._register(new _.DisposableStore),this.onDidStart=this._onDidStart.event,this.onDidChange=this._onDidChange.event,this.onDidReset=this._onDidReset.event,this.onDidEnd=this._onDidEnd.event,this.linkedSash=void 0,this.el=(0,d.append)(C,(0,d.$)(".monaco-sash")),h.orthogonalEdge&&this.el.classList.add(`orthogonal-edge-${h.orthogonalEdge}`),b.isMacintosh&&this.el.classList.add("mac");const v=this._register(new k.DomEmitter(this.el,"mousedown")).event;this._register(v(A=>this.onPointerStart(A,new g(C)),this));const w=this._register(new k.DomEmitter(this.el,"dblclick")).event;this._register(w(this.onPointerDoublePress,this));const S=this._register(new k.DomEmitter(this.el,"mouseenter")).event;this._register(S(()=>r.onMouseEnter(this)));const L=this._register(new k.DomEmitter(this.el,"mouseleave")).event;this._register(L(()=>r.onMouseLeave(this))),this._register(I.Gesture.addTarget(this.el));const D=this._register(new k.DomEmitter(this.el,I.EventType.Start)).event;this._register(D(A=>this.onPointerStart(A,new c(this.el)),this));const T=this._register(new k.DomEmitter(this.el,I.EventType.Tap)).event;let M;this._register(T(A=>{if(M){clearTimeout(M),M=void 0,this.onPointerDoublePress(A);return}clearTimeout(M),M=setTimeout(()=>M=void 0,250)},this)),typeof h.size=="number"?(this.size=h.size,h.orientation===0?this.el.style.width=`${this.size}px`:this.el.style.height=`${this.size}px`):(this.size=o,this._register(t.event(A=>{this.size=A,this.layout()}))),this._register(s.event(A=>this.hoverDelay=A)),this.layoutProvider=f,this.orthogonalStartSash=h.orthogonalStartSash,this.orthogonalEndSash=h.orthogonalEndSash,this.orientation=h.orientation||0,this.orientation===1?(this.el.classList.add("horizontal"),this.el.classList.remove("vertical")):(this.el.classList.remove("horizontal"),this.el.classList.add("vertical")),this.el.classList.toggle("debug",p),this.layout()}onPointerStart(C,f){d.EventHelper.stop(C);let h=!1;if(!C.__orthogonalSashEvent){const O=this.getOrthogonalSash(C);O&&(h=!0,C.__orthogonalSashEvent=!0,O.onPointerStart(C,new l(f)))}if(this.linkedSash&&!C.__linkedSashEvent&&(C.__linkedSashEvent=!0,this.linkedSash.onPointerStart(C,new l(f))),!this.state)return;const v=this.el.ownerDocument.getElementsByTagName("iframe");for(const O of v)O.classList.add(a);const w=C.pageX,S=C.pageY,L=C.altKey,D={startX:w,currentX:w,startY:S,currentY:S,altKey:L};this.el.classList.add("active"),this._onDidStart.fire(D);const T=(0,d.createStyleSheet)(this.el),M=()=>{let O="";h?O="all-scroll":this.orientation===1?this.state===1?O="s-resize":this.state===2?O="n-resize":O=b.isMacintosh?"row-resize":"ns-resize":this.state===1?O="e-resize":this.state===2?O="w-resize":O=b.isMacintosh?"col-resize":"ew-resize",T.textContent=`* { cursor: ${O} !important; }`},A=new _.DisposableStore;M(),h||this.onDidEnablementChange.event(M,null,A);const P=O=>{d.EventHelper.stop(O,!1);const F={startX:w,currentX:O.pageX,startY:S,currentY:O.pageY,altKey:L};this._onDidChange.fire(F)},N=O=>{d.EventHelper.stop(O,!1),T.remove(),this.el.classList.remove("active"),this._onDidEnd.fire(),A.dispose();for(const F of v)F.classList.remove(a)};f.onPointerMove(P,null,A),f.onPointerUp(N,null,A),A.add(f)}onPointerDoublePress(C){const f=this.getOrthogonalSash(C);f&&f._onDidReset.fire(),this.linkedSash&&this.linkedSash._onDidReset.fire(),this._onDidReset.fire()}static onMouseEnter(C,f=!1){C.el.classList.contains("active")?(C.hoverDelayer.cancel(),C.el.classList.add("hover")):C.hoverDelayer.trigger(()=>C.el.classList.add("hover"),C.hoverDelay).then(void 0,()=>{}),!f&&C.linkedSash&&r.onMouseEnter(C.linkedSash,!0)}static onMouseLeave(C,f=!1){C.hoverDelayer.cancel(),C.el.classList.remove("hover"),!f&&C.linkedSash&&r.onMouseLeave(C.linkedSash,!0)}clearSashHoverState(){r.onMouseLeave(this)}layout(){if(this.orientation===0){const C=this.layoutProvider;this.el.style.left=C.getVerticalSashLeft(this)-this.size/2+"px",C.getVerticalSashTop&&(this.el.style.top=C.getVerticalSashTop(this)+"px"),C.getVerticalSashHeight&&(this.el.style.height=C.getVerticalSashHeight(this)+"px")}else{const C=this.layoutProvider;this.el.style.top=C.getHorizontalSashTop(this)-this.size/2+"px",C.getHorizontalSashLeft&&(this.el.style.left=C.getHorizontalSashLeft(this)+"px"),C.getHorizontalSashWidth&&(this.el.style.width=C.getHorizontalSashWidth(this)+"px")}}getOrthogonalSash(C){const f=C.initialTarget??C.target;if(!(!f||!(0,d.isHTMLElement)(f))&&f.classList.contains("orthogonal-drag-handle"))return f.classList.contains("start")?this.orthogonalStartSash:this.orthogonalEndSash}dispose(){super.dispose(),this.el.remove()}}e.Sash=r}),define(ne[255],se([1,0,5,173,6,2]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ResizableHTMLElement=void 0;class y{constructor(){this._onDidWillResize=new I.Emitter,this.onDidWillResize=this._onDidWillResize.event,this._onDidResize=new I.Emitter,this.onDidResize=this._onDidResize.event,this._sashListener=new E.DisposableStore,this._size=new d.Dimension(0,0),this._minSize=new d.Dimension(0,0),this._maxSize=new d.Dimension(Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER),this.domNode=document.createElement("div"),this._eastSash=new k.Sash(this.domNode,{getVerticalSashLeft:()=>this._size.width},{orientation:0}),this._westSash=new k.Sash(this.domNode,{getVerticalSashLeft:()=>0},{orientation:0}),this._northSash=new k.Sash(this.domNode,{getHorizontalSashTop:()=>0},{orientation:1,orthogonalEdge:k.OrthogonalEdge.North}),this._southSash=new k.Sash(this.domNode,{getHorizontalSashTop:()=>this._size.height},{orientation:1,orthogonalEdge:k.OrthogonalEdge.South}),this._northSash.orthogonalStartSash=this._westSash,this._northSash.orthogonalEndSash=this._eastSash,this._southSash.orthogonalStartSash=this._westSash,this._southSash.orthogonalEndSash=this._eastSash;let _,b=0,p=0;this._sashListener.add(I.Event.any(this._northSash.onDidStart,this._eastSash.onDidStart,this._southSash.onDidStart,this._westSash.onDidStart)(()=>{_===void 0&&(this._onDidWillResize.fire(),_=this._size,b=0,p=0)})),this._sashListener.add(I.Event.any(this._northSash.onDidEnd,this._eastSash.onDidEnd,this._southSash.onDidEnd,this._westSash.onDidEnd)(()=>{_!==void 0&&(_=void 0,b=0,p=0,this._onDidResize.fire({dimension:this._size,done:!0}))})),this._sashListener.add(this._eastSash.onDidChange(n=>{_&&(p=n.currentX-n.startX,this.layout(_.height+b,_.width+p),this._onDidResize.fire({dimension:this._size,done:!1,east:!0}))})),this._sashListener.add(this._westSash.onDidChange(n=>{_&&(p=-(n.currentX-n.startX),this.layout(_.height+b,_.width+p),this._onDidResize.fire({dimension:this._size,done:!1,west:!0}))})),this._sashListener.add(this._northSash.onDidChange(n=>{_&&(b=-(n.currentY-n.startY),this.layout(_.height+b,_.width+p),this._onDidResize.fire({dimension:this._size,done:!1,north:!0}))})),this._sashListener.add(this._southSash.onDidChange(n=>{_&&(b=n.currentY-n.startY,this.layout(_.height+b,_.width+p),this._onDidResize.fire({dimension:this._size,done:!1,south:!0}))})),this._sashListener.add(I.Event.any(this._eastSash.onDidReset,this._westSash.onDidReset)(n=>{this._preferredSize&&(this.layout(this._size.height,this._preferredSize.width),this._onDidResize.fire({dimension:this._size,done:!0}))})),this._sashListener.add(I.Event.any(this._northSash.onDidReset,this._southSash.onDidReset)(n=>{this._preferredSize&&(this.layout(this._preferredSize.height,this._size.width),this._onDidResize.fire({dimension:this._size,done:!0}))}))}dispose(){this._northSash.dispose(),this._southSash.dispose(),this._eastSash.dispose(),this._westSash.dispose(),this._sashListener.dispose(),this._onDidResize.dispose(),this._onDidWillResize.dispose(),this.domNode.remove()}enableSashes(_,b,p,n){this._northSash.state=_?3:0,this._eastSash.state=b?3:0,this._southSash.state=p?3:0,this._westSash.state=n?3:0}layout(_=this.size.height,b=this.size.width){const{height:p,width:n}=this._minSize,{height:o,width:t}=this._maxSize;_=Math.max(p,Math.min(o,_)),b=Math.max(n,Math.min(t,b));const i=new d.Dimension(b,_);d.Dimension.equals(i,this._size)||(this.domNode.style.height=_+"px",this.domNode.style.width=b+"px",this._size=i,this._northSash.layout(),this._eastSash.layout(),this._southSash.layout(),this._westSash.layout())}clearSashHoverState(){this._eastSash.clearSashHoverState(),this._westSash.clearSashHoverState(),this._northSash.clearSashHoverState(),this._southSash.clearSashHoverState()}get size(){return this._size}set maxSize(_){this._maxSize=_}get maxSize(){return this._maxSize}set minSize(_){this._minSize=_}get minSize(){return this._minSize}set preferredSize(_){this._preferredSize=_}get preferredSize(){return this._preferredSize}}e.ResizableHTMLElement=y}),define(ne[634],se([1,0,5,69,13,6,2,16]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SelectBoxNative=void 0;class _ extends y.Disposable{constructor(p,n,o,t){super(),this.selected=0,this.selectBoxOptions=t||Object.create(null),this.options=[],this.selectElement=document.createElement("select"),this.selectElement.className="monaco-select-box",typeof this.selectBoxOptions.ariaLabel=="string"&&this.selectElement.setAttribute("aria-label",this.selectBoxOptions.ariaLabel),typeof this.selectBoxOptions.ariaDescription=="string"&&this.selectElement.setAttribute("aria-description",this.selectBoxOptions.ariaDescription),this._onDidSelect=this._register(new E.Emitter),this.styles=o,this.registerListeners(),this.setOptions(p,n)}registerListeners(){this._register(k.Gesture.addTarget(this.selectElement)),[k.EventType.Tap].forEach(p=>{this._register(d.addDisposableListener(this.selectElement,p,n=>{this.selectElement.focus()}))}),this._register(d.addStandardDisposableListener(this.selectElement,"click",p=>{d.EventHelper.stop(p,!0)})),this._register(d.addStandardDisposableListener(this.selectElement,"change",p=>{this.selectElement.title=p.target.value,this._onDidSelect.fire({index:p.target.selectedIndex,selected:p.target.value})})),this._register(d.addStandardDisposableListener(this.selectElement,"keydown",p=>{let n=!1;m.isMacintosh?(p.keyCode===18||p.keyCode===16||p.keyCode===10)&&(n=!0):(p.keyCode===18&&p.altKey||p.keyCode===10||p.keyCode===3)&&(n=!0),n&&p.stopPropagation()}))}get onDidSelect(){return this._onDidSelect.event}setOptions(p,n){(!this.options||!I.equals(this.options,p))&&(this.options=p,this.selectElement.options.length=0,this.options.forEach((o,t)=>{this.selectElement.add(this.createOption(o.text,t,o.isDisabled))})),n!==void 0&&this.select(n)}select(p){this.options.length===0?this.selected=0:p>=0&&pthis.options.length-1?this.select(this.options.length-1):this.selected<0&&(this.selected=0),this.selectElement.selectedIndex=this.selected,this.selectedp(new I.StandardMouseEvent(d.getWindow(b),n))))}onmousedown(b,p){this._register(d.addDisposableListener(b,d.EventType.MOUSE_DOWN,n=>p(new I.StandardMouseEvent(d.getWindow(b),n))))}onmouseover(b,p){this._register(d.addDisposableListener(b,d.EventType.MOUSE_OVER,n=>p(new I.StandardMouseEvent(d.getWindow(b),n))))}onmouseleave(b,p){this._register(d.addDisposableListener(b,d.EventType.MOUSE_LEAVE,n=>p(new I.StandardMouseEvent(d.getWindow(b),n))))}onkeydown(b,p){this._register(d.addDisposableListener(b,d.EventType.KEY_DOWN,n=>p(new k.StandardKeyboardEvent(n))))}onkeyup(b,p){this._register(d.addDisposableListener(b,d.EventType.KEY_UP,n=>p(new k.StandardKeyboardEvent(n))))}oninput(b,p){this._register(d.addDisposableListener(b,d.EventType.INPUT,p))}onblur(b,p){this._register(d.addDisposableListener(b,d.EventType.BLUR,p))}onfocus(b,p){this._register(d.addDisposableListener(b,d.EventType.FOCUS,p))}ignoreGesture(b){return E.Gesture.ignoreTarget(b)}}e.Widget=m}),define(ne[256],se([1,0,172,85,14,30,5]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ScrollbarArrow=e.ARROW_IMG_SIZE=void 0,e.ARROW_IMG_SIZE=11;class m extends k.Widget{constructor(b){super(),this._onActivate=b.onActivate,this.bgDomNode=document.createElement("div"),this.bgDomNode.className="arrow-background",this.bgDomNode.style.position="absolute",this.bgDomNode.style.width=b.bgWidth+"px",this.bgDomNode.style.height=b.bgHeight+"px",typeof b.top<"u"&&(this.bgDomNode.style.top="0px"),typeof b.left<"u"&&(this.bgDomNode.style.left="0px"),typeof b.bottom<"u"&&(this.bgDomNode.style.bottom="0px"),typeof b.right<"u"&&(this.bgDomNode.style.right="0px"),this.domNode=document.createElement("div"),this.domNode.className=b.className,this.domNode.classList.add(...E.ThemeIcon.asClassNameArray(b.icon)),this.domNode.style.position="absolute",this.domNode.style.width=e.ARROW_IMG_SIZE+"px",this.domNode.style.height=e.ARROW_IMG_SIZE+"px",typeof b.top<"u"&&(this.domNode.style.top=b.top+"px"),typeof b.left<"u"&&(this.domNode.style.left=b.left+"px"),typeof b.bottom<"u"&&(this.domNode.style.bottom=b.bottom+"px"),typeof b.right<"u"&&(this.domNode.style.right=b.right+"px"),this._pointerMoveMonitor=this._register(new d.GlobalPointerMoveMonitor),this._register(y.addStandardDisposableListener(this.bgDomNode,y.EventType.POINTER_DOWN,p=>this._arrowPointerDown(p))),this._register(y.addStandardDisposableListener(this.domNode,y.EventType.POINTER_DOWN,p=>this._arrowPointerDown(p))),this._pointerdownRepeatTimer=this._register(new y.WindowIntervalTimer),this._pointerdownScheduleRepeatTimer=this._register(new I.TimeoutTimer)}_arrowPointerDown(b){if(!b.target||!(b.target instanceof Element))return;const p=()=>{this._pointerdownRepeatTimer.cancelAndSet(()=>this._onActivate(),1e3/24,y.getWindow(b))};this._onActivate(),this._pointerdownRepeatTimer.cancel(),this._pointerdownScheduleRepeatTimer.cancelAndSet(p,200),this._pointerMoveMonitor.startMonitoring(b.target,b.pointerId,b.buttons,n=>{},()=>{this._pointerdownRepeatTimer.cancel(),this._pointerdownScheduleRepeatTimer.cancel()}),b.preventDefault()}}e.ScrollbarArrow=m}),define(ne[356],se([1,0,5,39,172,256,626,85,16]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractScrollbar=void 0;const b=140;class p extends m.Widget{constructor(o){super(),this._lazyRender=o.lazyRender,this._host=o.host,this._scrollable=o.scrollable,this._scrollByPage=o.scrollByPage,this._scrollbarState=o.scrollbarState,this._visibilityController=this._register(new y.ScrollbarVisibilityController(o.visibility,"visible scrollbar "+o.extraScrollbarClassName,"invisible scrollbar "+o.extraScrollbarClassName)),this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()),this._pointerMoveMonitor=this._register(new I.GlobalPointerMoveMonitor),this._shouldRender=!0,this.domNode=(0,k.createFastDomNode)(document.createElement("div")),this.domNode.setAttribute("role","presentation"),this.domNode.setAttribute("aria-hidden","true"),this._visibilityController.setDomNode(this.domNode),this.domNode.setPosition("absolute"),this._register(d.addDisposableListener(this.domNode.domNode,d.EventType.POINTER_DOWN,t=>this._domNodePointerDown(t)))}_createArrow(o){const t=this._register(new E.ScrollbarArrow(o));this.domNode.domNode.appendChild(t.bgDomNode),this.domNode.domNode.appendChild(t.domNode)}_createSlider(o,t,i,s){this.slider=(0,k.createFastDomNode)(document.createElement("div")),this.slider.setClassName("slider"),this.slider.setPosition("absolute"),this.slider.setTop(o),this.slider.setLeft(t),typeof i=="number"&&this.slider.setWidth(i),typeof s=="number"&&this.slider.setHeight(s),this.slider.setLayerHinting(!0),this.slider.setContain("strict"),this.domNode.domNode.appendChild(this.slider.domNode),this._register(d.addDisposableListener(this.slider.domNode,d.EventType.POINTER_DOWN,g=>{g.button===0&&(g.preventDefault(),this._sliderPointerDown(g))})),this.onclick(this.slider.domNode,g=>{g.leftButton&&g.stopPropagation()})}_onElementSize(o){return this._scrollbarState.setVisibleSize(o)&&(this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()),this._shouldRender=!0,this._lazyRender||this.render()),this._shouldRender}_onElementScrollSize(o){return this._scrollbarState.setScrollSize(o)&&(this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()),this._shouldRender=!0,this._lazyRender||this.render()),this._shouldRender}_onElementScrollPosition(o){return this._scrollbarState.setScrollPosition(o)&&(this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()),this._shouldRender=!0,this._lazyRender||this.render()),this._shouldRender}beginReveal(){this._visibilityController.setShouldBeVisible(!0)}beginHide(){this._visibilityController.setShouldBeVisible(!1)}render(){this._shouldRender&&(this._shouldRender=!1,this._renderDomNode(this._scrollbarState.getRectangleLargeSize(),this._scrollbarState.getRectangleSmallSize()),this._updateSlider(this._scrollbarState.getSliderSize(),this._scrollbarState.getArrowSize()+this._scrollbarState.getSliderPosition()))}_domNodePointerDown(o){o.target===this.domNode.domNode&&this._onPointerDown(o)}delegatePointerDown(o){const t=this.domNode.domNode.getClientRects()[0].top,i=t+this._scrollbarState.getSliderPosition(),s=t+this._scrollbarState.getSliderPosition()+this._scrollbarState.getSliderSize(),g=this._sliderPointerPosition(o);i<=g&&g<=s?o.button===0&&(o.preventDefault(),this._sliderPointerDown(o)):this._onPointerDown(o)}_onPointerDown(o){let t,i;if(o.target===this.domNode.domNode&&typeof o.offsetX=="number"&&typeof o.offsetY=="number")t=o.offsetX,i=o.offsetY;else{const g=d.getDomNodePagePosition(this.domNode.domNode);t=o.pageX-g.left,i=o.pageY-g.top}const s=this._pointerDownRelativePosition(t,i);this._setDesiredScrollPositionNow(this._scrollByPage?this._scrollbarState.getDesiredScrollPositionFromOffsetPaged(s):this._scrollbarState.getDesiredScrollPositionFromOffset(s)),o.button===0&&(o.preventDefault(),this._sliderPointerDown(o))}_sliderPointerDown(o){if(!o.target||!(o.target instanceof Element))return;const t=this._sliderPointerPosition(o),i=this._sliderOrthogonalPointerPosition(o),s=this._scrollbarState.clone();this.slider.toggleClassName("active",!0),this._pointerMoveMonitor.startMonitoring(o.target,o.pointerId,o.buttons,g=>{const c=this._sliderOrthogonalPointerPosition(g),l=Math.abs(c-i);if(_.isWindows&&l>b){this._setDesiredScrollPositionNow(s.getScrollPosition());return}const r=this._sliderPointerPosition(g)-t;this._setDesiredScrollPositionNow(s.getDesiredScrollPositionFromDelta(r))},()=>{this.slider.toggleClassName("active",!1),this._host.onDragEnd()}),this._host.onDragStart()}_setDesiredScrollPositionNow(o){const t={};this.writeScrollPosition(t,o),this._scrollable.setScrollPositionNow(t)}updateScrollbarSize(o){this._updateScrollbarSize(o),this._scrollbarState.setScrollbarSize(o),this._shouldRender=!0,this._lazyRender||this.render()}isNeeded(){return this._scrollbarState.isNeeded()}}e.AbstractScrollbar=p}),define(ne[635],se([1,0,77,356,256,223,26]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HorizontalScrollbar=void 0;class m extends k.AbstractScrollbar{constructor(b,p,n){const o=b.getScrollDimensions(),t=b.getCurrentScrollPosition();if(super({lazyRender:p.lazyRender,host:n,scrollbarState:new E.ScrollbarState(p.horizontalHasArrows?p.arrowSize:0,p.horizontal===2?0:p.horizontalScrollbarSize,p.vertical===2?0:p.verticalScrollbarSize,o.width,o.scrollWidth,t.scrollLeft),visibility:p.horizontal,extraScrollbarClassName:"horizontal",scrollable:b,scrollByPage:p.scrollByPage}),p.horizontalHasArrows){const i=(p.arrowSize-I.ARROW_IMG_SIZE)/2,s=(p.horizontalScrollbarSize-I.ARROW_IMG_SIZE)/2;this._createArrow({className:"scra",icon:y.Codicon.scrollbarButtonLeft,top:s,left:i,bottom:void 0,right:void 0,bgWidth:p.arrowSize,bgHeight:p.horizontalScrollbarSize,onActivate:()=>this._host.onMouseWheel(new d.StandardWheelEvent(null,1,0))}),this._createArrow({className:"scra",icon:y.Codicon.scrollbarButtonRight,top:s,left:void 0,bottom:void 0,right:i,bgWidth:p.arrowSize,bgHeight:p.horizontalScrollbarSize,onActivate:()=>this._host.onMouseWheel(new d.StandardWheelEvent(null,-1,0))})}this._createSlider(Math.floor((p.horizontalScrollbarSize-p.horizontalSliderSize)/2),0,void 0,p.horizontalSliderSize)}_updateSlider(b,p){this.slider.setWidth(b),this.slider.setLeft(p)}_renderDomNode(b,p){this.domNode.setWidth(b),this.domNode.setHeight(p),this.domNode.setLeft(0),this.domNode.setBottom(0)}onDidScroll(b){return this._shouldRender=this._onElementScrollSize(b.scrollWidth)||this._shouldRender,this._shouldRender=this._onElementScrollPosition(b.scrollLeft)||this._shouldRender,this._shouldRender=this._onElementSize(b.width)||this._shouldRender,this._shouldRender}_pointerDownRelativePosition(b,p){return b}_sliderPointerPosition(b){return b.pageX}_sliderOrthogonalPointerPosition(b){return b.pageY}_updateScrollbarSize(b){this.slider.setHeight(b)}writeScrollPosition(b,p){b.scrollLeft=p}updateOptions(b){this.updateScrollbarSize(b.horizontal===2?0:b.horizontalScrollbarSize),this._scrollbarState.setOppositeScrollbarSize(b.vertical===2?0:b.verticalScrollbarSize),this._visibilityController.setVisibility(b.horizontal),this._scrollByPage=b.scrollByPage}}e.HorizontalScrollbar=m}),define(ne[636],se([1,0,77,356,256,223,26]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.VerticalScrollbar=void 0;class m extends k.AbstractScrollbar{constructor(b,p,n){const o=b.getScrollDimensions(),t=b.getCurrentScrollPosition();if(super({lazyRender:p.lazyRender,host:n,scrollbarState:new E.ScrollbarState(p.verticalHasArrows?p.arrowSize:0,p.vertical===2?0:p.verticalScrollbarSize,0,o.height,o.scrollHeight,t.scrollTop),visibility:p.vertical,extraScrollbarClassName:"vertical",scrollable:b,scrollByPage:p.scrollByPage}),p.verticalHasArrows){const i=(p.arrowSize-I.ARROW_IMG_SIZE)/2,s=(p.verticalScrollbarSize-I.ARROW_IMG_SIZE)/2;this._createArrow({className:"scra",icon:y.Codicon.scrollbarButtonUp,top:i,left:s,bottom:void 0,right:void 0,bgWidth:p.verticalScrollbarSize,bgHeight:p.arrowSize,onActivate:()=>this._host.onMouseWheel(new d.StandardWheelEvent(null,0,1))}),this._createArrow({className:"scra",icon:y.Codicon.scrollbarButtonDown,top:void 0,left:s,bottom:i,right:void 0,bgWidth:p.verticalScrollbarSize,bgHeight:p.arrowSize,onActivate:()=>this._host.onMouseWheel(new d.StandardWheelEvent(null,0,-1))})}this._createSlider(0,Math.floor((p.verticalScrollbarSize-p.verticalSliderSize)/2),p.verticalSliderSize,void 0)}_updateSlider(b,p){this.slider.setHeight(b),this.slider.setTop(p)}_renderDomNode(b,p){this.domNode.setWidth(p),this.domNode.setHeight(b),this.domNode.setRight(0),this.domNode.setTop(0)}onDidScroll(b){return this._shouldRender=this._onElementScrollSize(b.scrollHeight)||this._shouldRender,this._shouldRender=this._onElementScrollPosition(b.scrollTop)||this._shouldRender,this._shouldRender=this._onElementSize(b.height)||this._shouldRender,this._shouldRender}_pointerDownRelativePosition(b,p){return p}_sliderPointerPosition(b){return b.pageY}_sliderOrthogonalPointerPosition(b){return b.pageX}_updateScrollbarSize(b){this.slider.setWidth(b)}writeScrollPosition(b,p){b.scrollTop=p}updateOptions(b){this.updateScrollbarSize(b.vertical===2?0:b.verticalScrollbarSize),this._scrollbarState.setOppositeScrollbarSize(0),this._visibilityController.setVisibility(b.vertical),this._scrollByPage=b.scrollByPage}}e.VerticalScrollbar=m}),define(ne[86],se([1,0,64,5,39,77,635,636,85,14,6,2,16,163,471]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DomScrollableElement=e.SmoothScrollableElement=e.ScrollableElement=e.AbstractScrollableElement=e.MouseWheelClassifier=void 0;const i=500,s=50,g=!0;class c{constructor(v,w,S){this.timestamp=v,this.deltaX=w,this.deltaY=S,this.score=0}}class l{static{this.INSTANCE=new l}constructor(){this._capacity=5,this._memory=[],this._front=-1,this._rear=-1}isPhysicalMouseWheel(){if(this._front===-1&&this._rear===-1)return!1;let v=1,w=0,S=1,L=this._rear;do{const D=L===this._front?v:Math.pow(2,-S);if(v-=D,w+=this._memory[L].score*D,L===this._front)break;L=(this._capacity+L-1)%this._capacity,S++}while(!0);return w<=.5}acceptStandardWheelEvent(v){if(d.isChrome){const w=k.getWindow(v.browserEvent),S=(0,d.getZoomFactor)(w);this.accept(Date.now(),v.deltaX*S,v.deltaY*S)}else this.accept(Date.now(),v.deltaX,v.deltaY)}accept(v,w,S){let L=null;const D=new c(v,w,S);this._front===-1&&this._rear===-1?(this._memory[0]=D,this._front=0,this._rear=0):(L=this._memory[this._rear],this._rear=(this._rear+1)%this._capacity,this._rear===this._front&&(this._front=(this._front+1)%this._capacity),this._memory[this._rear]=D),D.score=this._computeScore(D,L)}_computeScore(v,w){if(Math.abs(v.deltaX)>0&&Math.abs(v.deltaY)>0)return 1;let S=.5;if((!this._isAlmostInt(v.deltaX)||!this._isAlmostInt(v.deltaY))&&(S+=.25),w){const L=Math.abs(v.deltaX),D=Math.abs(v.deltaY),T=Math.abs(w.deltaX),M=Math.abs(w.deltaY),A=Math.max(Math.min(L,T),1),P=Math.max(Math.min(D,M),1),N=Math.max(L,T),O=Math.max(D,M);N%A===0&&O%P===0&&(S-=.5)}return Math.min(Math.max(S,0),1)}_isAlmostInt(v){return Math.abs(Math.round(v)-v)<.01}}e.MouseWheelClassifier=l;class a extends _.Widget{get options(){return this._options}constructor(v,w,S){super(),this._onScroll=this._register(new p.Emitter),this.onScroll=this._onScroll.event,this._onWillScroll=this._register(new p.Emitter),v.style.overflow="hidden",this._options=f(w),this._scrollable=S,this._register(this._scrollable.onScroll(D=>{this._onWillScroll.fire(D),this._onDidScroll(D),this._onScroll.fire(D)}));const L={onMouseWheel:D=>this._onMouseWheel(D),onDragStart:()=>this._onDragStart(),onDragEnd:()=>this._onDragEnd()};this._verticalScrollbar=this._register(new m.VerticalScrollbar(this._scrollable,this._options,L)),this._horizontalScrollbar=this._register(new y.HorizontalScrollbar(this._scrollable,this._options,L)),this._domNode=document.createElement("div"),this._domNode.className="monaco-scrollable-element "+this._options.className,this._domNode.setAttribute("role","presentation"),this._domNode.style.position="relative",this._domNode.style.overflow="hidden",this._domNode.appendChild(v),this._domNode.appendChild(this._horizontalScrollbar.domNode.domNode),this._domNode.appendChild(this._verticalScrollbar.domNode.domNode),this._options.useShadows?(this._leftShadowDomNode=(0,I.createFastDomNode)(document.createElement("div")),this._leftShadowDomNode.setClassName("shadow"),this._domNode.appendChild(this._leftShadowDomNode.domNode),this._topShadowDomNode=(0,I.createFastDomNode)(document.createElement("div")),this._topShadowDomNode.setClassName("shadow"),this._domNode.appendChild(this._topShadowDomNode.domNode),this._topLeftShadowDomNode=(0,I.createFastDomNode)(document.createElement("div")),this._topLeftShadowDomNode.setClassName("shadow"),this._domNode.appendChild(this._topLeftShadowDomNode.domNode)):(this._leftShadowDomNode=null,this._topShadowDomNode=null,this._topLeftShadowDomNode=null),this._listenOnDomNode=this._options.listenOnDomNode||this._domNode,this._mouseWheelToDispose=[],this._setListeningToMouseWheel(this._options.handleMouseWheel),this.onmouseover(this._listenOnDomNode,D=>this._onMouseOver(D)),this.onmouseleave(this._listenOnDomNode,D=>this._onMouseLeave(D)),this._hideTimeout=this._register(new b.TimeoutTimer),this._isDragging=!1,this._mouseIsOver=!1,this._shouldRender=!0,this._revealOnScroll=!0}dispose(){this._mouseWheelToDispose=(0,n.dispose)(this._mouseWheelToDispose),super.dispose()}getDomNode(){return this._domNode}getOverviewRulerLayoutInfo(){return{parent:this._domNode,insertBefore:this._verticalScrollbar.domNode.domNode}}delegateVerticalScrollbarPointerDown(v){this._verticalScrollbar.delegatePointerDown(v)}getScrollDimensions(){return this._scrollable.getScrollDimensions()}setScrollDimensions(v){this._scrollable.setScrollDimensions(v,!1)}updateClassName(v){this._options.className=v,o.isMacintosh&&(this._options.className+=" mac"),this._domNode.className="monaco-scrollable-element "+this._options.className}updateOptions(v){typeof v.handleMouseWheel<"u"&&(this._options.handleMouseWheel=v.handleMouseWheel,this._setListeningToMouseWheel(this._options.handleMouseWheel)),typeof v.mouseWheelScrollSensitivity<"u"&&(this._options.mouseWheelScrollSensitivity=v.mouseWheelScrollSensitivity),typeof v.fastScrollSensitivity<"u"&&(this._options.fastScrollSensitivity=v.fastScrollSensitivity),typeof v.scrollPredominantAxis<"u"&&(this._options.scrollPredominantAxis=v.scrollPredominantAxis),typeof v.horizontal<"u"&&(this._options.horizontal=v.horizontal),typeof v.vertical<"u"&&(this._options.vertical=v.vertical),typeof v.horizontalScrollbarSize<"u"&&(this._options.horizontalScrollbarSize=v.horizontalScrollbarSize),typeof v.verticalScrollbarSize<"u"&&(this._options.verticalScrollbarSize=v.verticalScrollbarSize),typeof v.scrollByPage<"u"&&(this._options.scrollByPage=v.scrollByPage),this._horizontalScrollbar.updateOptions(this._options),this._verticalScrollbar.updateOptions(this._options),this._options.lazyRender||this._render()}delegateScrollFromMouseWheelEvent(v){this._onMouseWheel(new E.StandardWheelEvent(v))}_setListeningToMouseWheel(v){if(this._mouseWheelToDispose.length>0!==v&&(this._mouseWheelToDispose=(0,n.dispose)(this._mouseWheelToDispose),v)){const S=L=>{this._onMouseWheel(new E.StandardWheelEvent(L))};this._mouseWheelToDispose.push(k.addDisposableListener(this._listenOnDomNode,k.EventType.MOUSE_WHEEL,S,{passive:!1}))}}_onMouseWheel(v){if(v.browserEvent?.defaultPrevented)return;const w=l.INSTANCE;g&&w.acceptStandardWheelEvent(v);let S=!1;if(v.deltaY||v.deltaX){let D=v.deltaY*this._options.mouseWheelScrollSensitivity,T=v.deltaX*this._options.mouseWheelScrollSensitivity;this._options.scrollPredominantAxis&&(this._options.scrollYToX&&T+D===0?T=D=0:Math.abs(D)>=Math.abs(T)?T=0:D=0),this._options.flipAxes&&([D,T]=[T,D]);const M=!o.isMacintosh&&v.browserEvent&&v.browserEvent.shiftKey;(this._options.scrollYToX||M)&&!T&&(T=D,D=0),v.browserEvent&&v.browserEvent.altKey&&(T=T*this._options.fastScrollSensitivity,D=D*this._options.fastScrollSensitivity);const A=this._scrollable.getFutureScrollPosition();let P={};if(D){const N=s*D,O=A.scrollTop-(N<0?Math.floor(N):Math.ceil(N));this._verticalScrollbar.writeScrollPosition(P,O)}if(T){const N=s*T,O=A.scrollLeft-(N<0?Math.floor(N):Math.ceil(N));this._horizontalScrollbar.writeScrollPosition(P,O)}P=this._scrollable.validateScrollPosition(P),(A.scrollLeft!==P.scrollLeft||A.scrollTop!==P.scrollTop)&&(g&&this._options.mouseWheelSmoothScroll&&w.isPhysicalMouseWheel()?this._scrollable.setScrollPositionSmooth(P):this._scrollable.setScrollPositionNow(P),S=!0)}let L=S;!L&&this._options.alwaysConsumeMouseWheel&&(L=!0),!L&&this._options.consumeMouseWheelIfScrollbarIsNeeded&&(this._verticalScrollbar.isNeeded()||this._horizontalScrollbar.isNeeded())&&(L=!0),L&&(v.preventDefault(),v.stopPropagation())}_onDidScroll(v){this._shouldRender=this._horizontalScrollbar.onDidScroll(v)||this._shouldRender,this._shouldRender=this._verticalScrollbar.onDidScroll(v)||this._shouldRender,this._options.useShadows&&(this._shouldRender=!0),this._revealOnScroll&&this._reveal(),this._options.lazyRender||this._render()}renderNow(){if(!this._options.lazyRender)throw new Error("Please use `lazyRender` together with `renderNow`!");this._render()}_render(){if(this._shouldRender&&(this._shouldRender=!1,this._horizontalScrollbar.render(),this._verticalScrollbar.render(),this._options.useShadows)){const v=this._scrollable.getCurrentScrollPosition(),w=v.scrollTop>0,S=v.scrollLeft>0,L=S?" left":"",D=w?" top":"",T=S||w?" top-left-corner":"";this._leftShadowDomNode.setClassName(`shadow${L}`),this._topShadowDomNode.setClassName(`shadow${D}`),this._topLeftShadowDomNode.setClassName(`shadow${T}${D}${L}`)}}_onDragStart(){this._isDragging=!0,this._reveal()}_onDragEnd(){this._isDragging=!1,this._hide()}_onMouseLeave(v){this._mouseIsOver=!1,this._hide()}_onMouseOver(v){this._mouseIsOver=!0,this._reveal()}_reveal(){this._verticalScrollbar.beginReveal(),this._horizontalScrollbar.beginReveal(),this._scheduleHide()}_hide(){!this._mouseIsOver&&!this._isDragging&&(this._verticalScrollbar.beginHide(),this._horizontalScrollbar.beginHide())}_scheduleHide(){!this._mouseIsOver&&!this._isDragging&&this._hideTimeout.cancelAndSet(()=>this._hide(),i)}}e.AbstractScrollableElement=a;class r extends a{constructor(v,w){w=w||{},w.mouseWheelSmoothScroll=!1;const S=new t.Scrollable({forceIntegerValues:!0,smoothScrollDuration:0,scheduleAtNextAnimationFrame:L=>k.scheduleAtNextAnimationFrame(k.getWindow(v),L)});super(v,w,S),this._register(S)}setScrollPosition(v){this._scrollable.setScrollPositionNow(v)}}e.ScrollableElement=r;class u extends a{constructor(v,w,S){super(v,w,S)}setScrollPosition(v){v.reuseAnimation?this._scrollable.setScrollPositionSmooth(v,v.reuseAnimation):this._scrollable.setScrollPositionNow(v)}getScrollPosition(){return this._scrollable.getCurrentScrollPosition()}}e.SmoothScrollableElement=u;class C extends a{constructor(v,w){w=w||{},w.mouseWheelSmoothScroll=!1;const S=new t.Scrollable({forceIntegerValues:!1,smoothScrollDuration:0,scheduleAtNextAnimationFrame:L=>k.scheduleAtNextAnimationFrame(k.getWindow(v),L)});super(v,w,S),this._register(S),this._element=v,this._register(this.onScroll(L=>{L.scrollTopChanged&&(this._element.scrollTop=L.scrollTop),L.scrollLeftChanged&&(this._element.scrollLeft=L.scrollLeft)})),this.scanDomNode()}setScrollPosition(v){this._scrollable.setScrollPositionNow(v)}getScrollPosition(){return this._scrollable.getCurrentScrollPosition()}scanDomNode(){this.setScrollDimensions({width:this._element.clientWidth,scrollWidth:this._element.scrollWidth,height:this._element.clientHeight,scrollHeight:this._element.scrollHeight}),this.setScrollPosition({scrollLeft:this._element.scrollLeft,scrollTop:this._element.scrollTop})}}e.DomScrollableElement=C;function f(h){const v={lazyRender:typeof h.lazyRender<"u"?h.lazyRender:!1,className:typeof h.className<"u"?h.className:"",useShadows:typeof h.useShadows<"u"?h.useShadows:!0,handleMouseWheel:typeof h.handleMouseWheel<"u"?h.handleMouseWheel:!0,flipAxes:typeof h.flipAxes<"u"?h.flipAxes:!1,consumeMouseWheelIfScrollbarIsNeeded:typeof h.consumeMouseWheelIfScrollbarIsNeeded<"u"?h.consumeMouseWheelIfScrollbarIsNeeded:!1,alwaysConsumeMouseWheel:typeof h.alwaysConsumeMouseWheel<"u"?h.alwaysConsumeMouseWheel:!1,scrollYToX:typeof h.scrollYToX<"u"?h.scrollYToX:!1,mouseWheelScrollSensitivity:typeof h.mouseWheelScrollSensitivity<"u"?h.mouseWheelScrollSensitivity:1,fastScrollSensitivity:typeof h.fastScrollSensitivity<"u"?h.fastScrollSensitivity:5,scrollPredominantAxis:typeof h.scrollPredominantAxis<"u"?h.scrollPredominantAxis:!0,mouseWheelSmoothScroll:typeof h.mouseWheelSmoothScroll<"u"?h.mouseWheelSmoothScroll:!0,arrowSize:typeof h.arrowSize<"u"?h.arrowSize:11,listenOnDomNode:typeof h.listenOnDomNode<"u"?h.listenOnDomNode:null,horizontal:typeof h.horizontal<"u"?h.horizontal:1,horizontalScrollbarSize:typeof h.horizontalScrollbarSize<"u"?h.horizontalScrollbarSize:10,horizontalSliderSize:typeof h.horizontalSliderSize<"u"?h.horizontalSliderSize:0,horizontalHasArrows:typeof h.horizontalHasArrows<"u"?h.horizontalHasArrows:!1,vertical:typeof h.vertical<"u"?h.vertical:1,verticalScrollbarSize:typeof h.verticalScrollbarSize<"u"?h.verticalScrollbarSize:10,verticalHasArrows:typeof h.verticalHasArrows<"u"?h.verticalHasArrows:!1,verticalSliderSize:typeof h.verticalSliderSize<"u"?h.verticalSliderSize:0,scrollByPage:typeof h.scrollByPage<"u"?h.scrollByPage:!1};return v.horizontalSliderSize=typeof h.horizontalSliderSize<"u"?h.horizontalSliderSize:v.horizontalScrollbarSize,v.verticalSliderSize=typeof h.verticalSliderSize<"u"?h.verticalSliderSize:v.verticalScrollbarSize,o.isMacintosh&&(v.className+=" mac"),v}}),define(ne[174],se([1,0,5,47,86,2,3,464]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.KeyDownAction=e.ClickAction=e.HoverAction=e.HoverWidget=void 0,e.getHoverAccessibleViewHint=p;const m=d.$;class _ extends E.Disposable{constructor(){super(),this.containerDomNode=document.createElement("div"),this.containerDomNode.className="monaco-hover",this.containerDomNode.tabIndex=0,this.containerDomNode.setAttribute("role","tooltip"),this.contentsDomNode=document.createElement("div"),this.contentsDomNode.className="monaco-hover-content",this.scrollbar=this._register(new I.DomScrollableElement(this.contentsDomNode,{consumeMouseWheelIfScrollbarIsNeeded:!0})),this.containerDomNode.appendChild(this.scrollbar.getDomNode())}onContentsChanged(){this.scrollbar.scanDomNode()}}e.HoverWidget=_;class b extends E.Disposable{static render(i,s,g){return new b(i,s,g)}constructor(i,s,g){super(),this.actionLabel=s.label,this.actionKeybindingLabel=g,this.actionContainer=d.append(i,m("div.action-container")),this.actionContainer.setAttribute("tabindex","0"),this.action=d.append(this.actionContainer,m("a.action")),this.action.setAttribute("role","button"),s.iconClass&&d.append(this.action,m(`span.icon.${s.iconClass}`));const c=d.append(this.action,m("span"));c.textContent=g?`${s.label} (${g})`:s.label,this._store.add(new n(this.actionContainer,s.run)),this._store.add(new o(this.actionContainer,s.run,[3,10])),this.setEnabled(!0)}setEnabled(i){i?(this.actionContainer.classList.remove("disabled"),this.actionContainer.removeAttribute("aria-disabled")):(this.actionContainer.classList.add("disabled"),this.actionContainer.setAttribute("aria-disabled","true"))}}e.HoverAction=b;function p(t,i){return t&&i?(0,y.localize)(7,"Inspect this in the accessible view with {0}.",i):t?(0,y.localize)(8,"Inspect this in the accessible view via the command Open Accessible View which is currently not triggerable via keybinding."):""}class n extends E.Disposable{constructor(i,s){super(),this._register(d.addDisposableListener(i,d.EventType.CLICK,g=>{g.stopPropagation(),g.preventDefault(),s(i)}))}}e.ClickAction=n;class o extends E.Disposable{constructor(i,s,g){super(),this._register(d.addDisposableListener(i,d.EventType.KEY_DOWN,c=>{const l=new k.StandardKeyboardEvent(c);g.some(a=>l.equals(a))&&(c.stopPropagation(),c.preventDefault(),s(i))}))}}e.KeyDownAction=o}),define(ne[257],se([1,0,224,5,93,69,86,13,14,126,6,2,188,163,454,632,8,141]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ListView=e.NativeDragAndDropData=e.ExternalElementsDragAndDropData=e.ElementsDragAndDropData=void 0;const l={CurrentDragAndDropData:void 0},a={useShadows:!0,verticalScrollMode:1,setRowLineHeight:!0,setRowHeight:!0,supportDynamicHeights:!1,dnd:{getDragElements(w){return[w]},getDragURI(){return null},onDragStart(){},onDragOver(){return!1},drop(){},dispose(){}},horizontalScrolling:!1,transformOptimization:!0,alwaysConsumeMouseWheel:!0};class r{constructor(S){this.elements=S}update(){}getData(){return this.elements}}e.ElementsDragAndDropData=r;class u{constructor(S){this.elements=S}update(){}getData(){return this.elements}}e.ExternalElementsDragAndDropData=u;class C{constructor(){this.types=[],this.files=[]}update(S){if(S.types&&this.types.splice(0,this.types.length,...S.types),S.files){this.files.splice(0,this.files.length);for(let L=0;LT,S?.getPosInSet?this.getPosInSet=S.getPosInSet.bind(S):this.getPosInSet=(L,D)=>D+1,S?.getRole?this.getRole=S.getRole.bind(S):this.getRole=L=>"listitem",S?.isChecked?this.isChecked=S.isChecked.bind(S):this.isChecked=L=>{}}}class v{static{this.InstanceCount=0}get contentHeight(){return this.rangeMap.size}get onDidScroll(){return this.scrollableElement.onScroll}get scrollableElementDomNode(){return this.scrollableElement.getDomNode()}get horizontalScrolling(){return this._horizontalScrolling}set horizontalScrolling(S){if(S!==this._horizontalScrolling){if(S&&this.supportDynamicHeights)throw new Error("Horizontal scrolling and dynamic heights not supported simultaneously");if(this._horizontalScrolling=S,this.domNode.classList.toggle("horizontal-scrolling",this._horizontalScrolling),this._horizontalScrolling){for(const L of this.items)this.measureItemWidth(L);this.updateScrollWidth(),this.scrollableElement.setScrollDimensions({width:(0,k.getContentWidth)(this.domNode)}),this.rowsContainer.style.width=`${Math.max(this.scrollWidth||0,this.renderWidth)}px`}else this.scrollableElementWidthDelayer.cancel(),this.scrollableElement.setScrollDimensions({width:this.renderWidth,scrollWidth:this.renderWidth}),this.rowsContainer.style.width=""}}constructor(S,L,D,T=a){if(this.virtualDelegate=L,this.domId=`list_id_${++v.InstanceCount}`,this.renderers=new Map,this.renderWidth=0,this._scrollHeight=0,this.scrollableElementUpdateDisposable=null,this.scrollableElementWidthDelayer=new _.Delayer(50),this.splicing=!1,this.dragOverAnimationStopDisposable=n.Disposable.None,this.dragOverMouseY=0,this.canDrop=!1,this.currentDragFeedbackDisposable=n.Disposable.None,this.onDragLeaveTimeout=n.Disposable.None,this.disposables=new n.DisposableStore,this._onDidChangeContentHeight=new p.Emitter,this._onDidChangeContentWidth=new p.Emitter,this.onDidChangeContentHeight=p.Event.latch(this._onDidChangeContentHeight.event,void 0,this.disposables),this._horizontalScrolling=!1,T.horizontalScrolling&&T.supportDynamicHeights)throw new Error("Horizontal scrolling and dynamic heights not supported simultaneously");this.items=[],this.itemId=0,this.rangeMap=this.createRangeMap(T.paddingTop??0);for(const A of D)this.renderers.set(A.templateId,A);this.cache=this.disposables.add(new s.RowCache(this.renderers)),this.lastRenderTop=0,this.lastRenderHeight=0,this.domNode=document.createElement("div"),this.domNode.className="monaco-list",this.domNode.classList.add(this.domId),this.domNode.tabIndex=0,this.domNode.classList.toggle("mouse-support",typeof T.mouseSupport=="boolean"?T.mouseSupport:!0),this._horizontalScrolling=T.horizontalScrolling??a.horizontalScrolling,this.domNode.classList.toggle("horizontal-scrolling",this._horizontalScrolling),this.paddingBottom=typeof T.paddingBottom>"u"?0:T.paddingBottom,this.accessibilityProvider=new h(T.accessibilityProvider),this.rowsContainer=document.createElement("div"),this.rowsContainer.className="monaco-list-rows",(T.transformOptimization??a.transformOptimization)&&(this.rowsContainer.style.transform="translate3d(0px, 0px, 0px)",this.rowsContainer.style.overflow="hidden",this.rowsContainer.style.contain="strict"),this.disposables.add(E.Gesture.addTarget(this.rowsContainer)),this.scrollable=this.disposables.add(new t.Scrollable({forceIntegerValues:!0,smoothScrollDuration:T.smoothScrolling??!1?125:0,scheduleAtNextAnimationFrame:A=>(0,k.scheduleAtNextAnimationFrame)((0,k.getWindow)(this.domNode),A)})),this.scrollableElement=this.disposables.add(new y.SmoothScrollableElement(this.rowsContainer,{alwaysConsumeMouseWheel:T.alwaysConsumeMouseWheel??a.alwaysConsumeMouseWheel,horizontal:1,vertical:T.verticalScrollMode??a.verticalScrollMode,useShadows:T.useShadows??a.useShadows,mouseWheelScrollSensitivity:T.mouseWheelScrollSensitivity,fastScrollSensitivity:T.fastScrollSensitivity,scrollByPage:T.scrollByPage},this.scrollable)),this.domNode.appendChild(this.scrollableElement.getDomNode()),S.appendChild(this.domNode),this.scrollableElement.onScroll(this.onScroll,this,this.disposables),this.disposables.add((0,k.addDisposableListener)(this.rowsContainer,E.EventType.Change,A=>this.onTouchChange(A))),this.disposables.add((0,k.addDisposableListener)(this.scrollableElement.getDomNode(),"scroll",A=>A.target.scrollTop=0)),this.disposables.add((0,k.addDisposableListener)(this.domNode,"dragover",A=>this.onDragOver(this.toDragEvent(A)))),this.disposables.add((0,k.addDisposableListener)(this.domNode,"drop",A=>this.onDrop(this.toDragEvent(A)))),this.disposables.add((0,k.addDisposableListener)(this.domNode,"dragleave",A=>this.onDragLeave(this.toDragEvent(A)))),this.disposables.add((0,k.addDisposableListener)(this.domNode,"dragend",A=>this.onDragEnd(A))),this.setRowLineHeight=T.setRowLineHeight??a.setRowLineHeight,this.setRowHeight=T.setRowHeight??a.setRowHeight,this.supportDynamicHeights=T.supportDynamicHeights??a.supportDynamicHeights,this.dnd=T.dnd??this.disposables.add(a.dnd),this.layout(T.initialSize?.height,T.initialSize?.width)}updateOptions(S){S.paddingBottom!==void 0&&(this.paddingBottom=S.paddingBottom,this.scrollableElement.setScrollDimensions({scrollHeight:this.scrollHeight})),S.smoothScrolling!==void 0&&this.scrollable.setSmoothScrollDuration(S.smoothScrolling?125:0),S.horizontalScrolling!==void 0&&(this.horizontalScrolling=S.horizontalScrolling);let L;if(S.scrollByPage!==void 0&&(L={...L??{},scrollByPage:S.scrollByPage}),S.mouseWheelScrollSensitivity!==void 0&&(L={...L??{},mouseWheelScrollSensitivity:S.mouseWheelScrollSensitivity}),S.fastScrollSensitivity!==void 0&&(L={...L??{},fastScrollSensitivity:S.fastScrollSensitivity}),L&&this.scrollableElement.updateOptions(L),S.paddingTop!==void 0&&S.paddingTop!==this.rangeMap.paddingTop){const D=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight),T=S.paddingTop-this.rangeMap.paddingTop;this.rangeMap.paddingTop=S.paddingTop,this.render(D,Math.max(0,this.lastRenderTop+T),this.lastRenderHeight,void 0,void 0,!0),this.setScrollTop(this.lastRenderTop),this.eventuallyUpdateScrollDimensions(),this.supportDynamicHeights&&this._rerender(this.lastRenderTop,this.lastRenderHeight)}}createRangeMap(S){return new i.RangeMap(S)}splice(S,L,D=[]){if(this.splicing)throw new Error("Can't run recursive splices.");this.splicing=!0;try{return this._splice(S,L,D)}finally{this.splicing=!1,this._onDidChangeContentHeight.fire(this.contentHeight)}}_splice(S,L,D=[]){const T=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight),M={start:S,end:S+L},A=o.Range.intersect(T,M),P=new Map;for(let K=A.end-1;K>=A.start;K--){const R=this.items[K];if(R.dragStartDisposable.dispose(),R.checkedDisposable.dispose(),R.row){let J=P.get(R.templateId);J||(J=[],P.set(R.templateId,J));const ie=this.renderers.get(R.templateId);ie&&ie.disposeElement&&ie.disposeElement(R.element,K,R.row.templateData,R.size),J.unshift(R.row)}R.row=null,R.stale=!0}const N={start:S+L,end:this.items.length},O=o.Range.intersect(N,T),F=o.Range.relativeComplement(N,T),x=D.map(K=>({id:String(this.itemId++),element:K,templateId:this.virtualDelegate.getTemplateId(K),size:this.virtualDelegate.getHeight(K),width:void 0,hasDynamicHeight:!!this.virtualDelegate.hasDynamicHeight&&this.virtualDelegate.hasDynamicHeight(K),lastDynamicHeightWidth:void 0,row:null,uri:void 0,dropTarget:!1,dragStartDisposable:n.Disposable.None,checkedDisposable:n.Disposable.None,stale:!1}));let W;S===0&&L>=this.items.length?(this.rangeMap=this.createRangeMap(this.rangeMap.paddingTop),this.rangeMap.splice(0,0,x),W=this.items,this.items=x):(this.rangeMap.splice(S,L,x),W=this.items.splice(S,L,...x));const V=D.length-L,q=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight),H=(0,i.shift)(O,V),z=o.Range.intersect(q,H);for(let K=z.start;K(0,i.shift)(K,V)),G=[{start:S,end:S+D.length},...j].map(K=>o.Range.intersect(q,K)).reverse();for(const K of G)for(let R=K.end-1;R>=K.start;R--){const J=this.items[R],ue=P.get(J.templateId)?.pop();this.insertItemInDOM(R,ue)}for(const K of P.values())for(const R of K)this.cache.release(R);return this.eventuallyUpdateScrollDimensions(),this.supportDynamicHeights&&this._rerender(this.scrollTop,this.renderHeight),W.map(K=>K.element)}eventuallyUpdateScrollDimensions(){this._scrollHeight=this.contentHeight,this.rowsContainer.style.height=`${this._scrollHeight}px`,this.scrollableElementUpdateDisposable||(this.scrollableElementUpdateDisposable=(0,k.scheduleAtNextAnimationFrame)((0,k.getWindow)(this.domNode),()=>{this.scrollableElement.setScrollDimensions({scrollHeight:this.scrollHeight}),this.updateScrollWidth(),this.scrollableElementUpdateDisposable=null}))}eventuallyUpdateScrollWidth(){if(!this.horizontalScrolling){this.scrollableElementWidthDelayer.cancel();return}this.scrollableElementWidthDelayer.trigger(()=>this.updateScrollWidth())}updateScrollWidth(){if(!this.horizontalScrolling)return;let S=0;for(const L of this.items)typeof L.width<"u"&&(S=Math.max(S,L.width));this.scrollWidth=S,this.scrollableElement.setScrollDimensions({scrollWidth:S===0?0:S+10}),this._onDidChangeContentWidth.fire(this.scrollWidth)}rerender(){if(this.supportDynamicHeights){for(const S of this.items)S.lastDynamicHeightWidth=void 0;this._rerender(this.lastRenderTop,this.lastRenderHeight)}}get length(){return this.items.length}get renderHeight(){return this.scrollableElement.getScrollDimensions().height}get firstVisibleIndex(){return this.getRenderRange(this.lastRenderTop,this.lastRenderHeight).start}element(S){return this.items[S].element}indexOf(S){return this.items.findIndex(L=>L.element===S)}domElement(S){const L=this.items[S].row;return L&&L.domNode}elementHeight(S){return this.items[S].size}elementTop(S){return this.rangeMap.positionAt(S)}indexAt(S){return this.rangeMap.indexAt(S)}indexAfter(S){return this.rangeMap.indexAfter(S)}layout(S,L){const D={height:typeof S=="number"?S:(0,k.getContentHeight)(this.domNode)};this.scrollableElementUpdateDisposable&&(this.scrollableElementUpdateDisposable.dispose(),this.scrollableElementUpdateDisposable=null,D.scrollHeight=this.scrollHeight),this.scrollableElement.setScrollDimensions(D),typeof L<"u"&&(this.renderWidth=L,this.supportDynamicHeights&&this._rerender(this.scrollTop,this.renderHeight)),this.horizontalScrolling&&this.scrollableElement.setScrollDimensions({width:typeof L=="number"?L:(0,k.getContentWidth)(this.domNode)})}render(S,L,D,T,M,A=!1){const P=this.getRenderRange(L,D),N=o.Range.relativeComplement(P,S).reverse(),O=o.Range.relativeComplement(S,P);if(A){const F=o.Range.intersect(S,P);for(let x=F.start;x{for(const F of O)for(let x=F.start;x=F.start;x--)this.insertItemInDOM(x)}),T!==void 0&&(this.rowsContainer.style.left=`-${T}px`),this.rowsContainer.style.top=`-${L}px`,this.horizontalScrolling&&M!==void 0&&(this.rowsContainer.style.width=`${Math.max(M,this.renderWidth)}px`),this.lastRenderTop=L,this.lastRenderHeight=D}insertItemInDOM(S,L){const D=this.items[S];if(!D.row)if(L)D.row=L,D.stale=!0;else{const N=this.cache.alloc(D.templateId);D.row=N.row,D.stale||=N.isReusingConnectedDomNode}const T=this.accessibilityProvider.getRole(D.element)||"listitem";D.row.domNode.setAttribute("role",T);const M=this.accessibilityProvider.isChecked(D.element);if(typeof M=="boolean")D.row.domNode.setAttribute("aria-checked",String(!!M));else if(M){const N=O=>D.row.domNode.setAttribute("aria-checked",String(!!O));N(M.value),D.checkedDisposable=M.onDidChange(()=>N(M.value))}if(D.stale||!D.row.domNode.parentElement){const N=this.items.at(S+1)?.row?.domNode??null;(D.row.domNode.parentElement!==this.rowsContainer||D.row.domNode.nextElementSibling!==N)&&this.rowsContainer.insertBefore(D.row.domNode,N),D.stale=!1}this.updateItemInDOM(D,S);const A=this.renderers.get(D.templateId);if(!A)throw new Error(`No renderer found for template id ${D.templateId}`);A?.renderElement(D.element,S,D.row.templateData,D.size);const P=this.dnd.getDragURI(D.element);D.dragStartDisposable.dispose(),D.row.domNode.draggable=!!P,P&&(D.dragStartDisposable=(0,k.addDisposableListener)(D.row.domNode,"dragstart",N=>this.onDragStart(D.element,P,N))),this.horizontalScrolling&&(this.measureItemWidth(D),this.eventuallyUpdateScrollWidth())}measureItemWidth(S){if(!S.row||!S.row.domNode)return;S.row.domNode.style.width="fit-content",S.width=(0,k.getContentWidth)(S.row.domNode);const L=(0,k.getWindow)(S.row.domNode).getComputedStyle(S.row.domNode);L.paddingLeft&&(S.width+=parseFloat(L.paddingLeft)),L.paddingRight&&(S.width+=parseFloat(L.paddingRight)),S.row.domNode.style.width=""}updateItemInDOM(S,L){S.row.domNode.style.top=`${this.elementTop(L)}px`,this.setRowHeight&&(S.row.domNode.style.height=`${S.size}px`),this.setRowLineHeight&&(S.row.domNode.style.lineHeight=`${S.size}px`),S.row.domNode.setAttribute("data-index",`${L}`),S.row.domNode.setAttribute("data-last-element",L===this.length-1?"true":"false"),S.row.domNode.setAttribute("data-parity",L%2===0?"even":"odd"),S.row.domNode.setAttribute("aria-setsize",String(this.accessibilityProvider.getSetSize(S.element,L,this.length))),S.row.domNode.setAttribute("aria-posinset",String(this.accessibilityProvider.getPosInSet(S.element,L))),S.row.domNode.setAttribute("id",this.getElementDomId(L)),S.row.domNode.classList.toggle("drop-target",S.dropTarget)}removeItemFromDOM(S){const L=this.items[S];if(L.dragStartDisposable.dispose(),L.checkedDisposable.dispose(),L.row){const D=this.renderers.get(L.templateId);D&&D.disposeElement&&D.disposeElement(L.element,S,L.row.templateData,L.size),this.cache.release(L.row),L.row=null}this.horizontalScrolling&&this.eventuallyUpdateScrollWidth()}getScrollTop(){return this.scrollableElement.getScrollPosition().scrollTop}setScrollTop(S,L){this.scrollableElementUpdateDisposable&&(this.scrollableElementUpdateDisposable.dispose(),this.scrollableElementUpdateDisposable=null,this.scrollableElement.setScrollDimensions({scrollHeight:this.scrollHeight})),this.scrollableElement.setScrollPosition({scrollTop:S,reuseAnimation:L})}get scrollTop(){return this.getScrollTop()}set scrollTop(S){this.setScrollTop(S)}get scrollHeight(){return this._scrollHeight+(this.horizontalScrolling?10:0)+this.paddingBottom}get onMouseClick(){return p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"click")).event,S=>this.toMouseEvent(S),this.disposables)}get onMouseDblClick(){return p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"dblclick")).event,S=>this.toMouseEvent(S),this.disposables)}get onMouseMiddleClick(){return p.Event.filter(p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"auxclick")).event,S=>this.toMouseEvent(S),this.disposables),S=>S.browserEvent.button===1,this.disposables)}get onMouseDown(){return p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"mousedown")).event,S=>this.toMouseEvent(S),this.disposables)}get onMouseOver(){return p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"mouseover")).event,S=>this.toMouseEvent(S),this.disposables)}get onMouseOut(){return p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"mouseout")).event,S=>this.toMouseEvent(S),this.disposables)}get onContextMenu(){return p.Event.any(p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"contextmenu")).event,S=>this.toMouseEvent(S),this.disposables),p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,E.EventType.Contextmenu)).event,S=>this.toGestureEvent(S),this.disposables))}get onTouchStart(){return p.Event.map(this.disposables.add(new I.DomEmitter(this.domNode,"touchstart")).event,S=>this.toTouchEvent(S),this.disposables)}get onTap(){return p.Event.map(this.disposables.add(new I.DomEmitter(this.rowsContainer,E.EventType.Tap)).event,S=>this.toGestureEvent(S),this.disposables)}toMouseEvent(S){const L=this.getItemIndexFromEventTarget(S.target||null),D=typeof L>"u"?void 0:this.items[L],T=D&&D.element;return{browserEvent:S,index:L,element:T}}toTouchEvent(S){const L=this.getItemIndexFromEventTarget(S.target||null),D=typeof L>"u"?void 0:this.items[L],T=D&&D.element;return{browserEvent:S,index:L,element:T}}toGestureEvent(S){const L=this.getItemIndexFromEventTarget(S.initialTarget||null),D=typeof L>"u"?void 0:this.items[L],T=D&&D.element;return{browserEvent:S,index:L,element:T}}toDragEvent(S){const L=this.getItemIndexFromEventTarget(S.target||null),D=typeof L>"u"?void 0:this.items[L],T=D&&D.element,M=this.getTargetSector(S,L);return{browserEvent:S,index:L,element:T,sector:M}}onScroll(S){try{const L=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight);this.render(L,S.scrollTop,S.height,S.scrollLeft,S.scrollWidth),this.supportDynamicHeights&&this._rerender(S.scrollTop,S.height,S.inSmoothScrolling)}catch(L){throw console.error("Got bad scroll event:",S),L}}onTouchChange(S){S.preventDefault(),S.stopPropagation(),this.scrollTop-=S.translationY}onDragStart(S,L,D){if(!D.dataTransfer)return;const T=this.dnd.getDragElements(S);if(D.dataTransfer.effectAllowed="copyMove",D.dataTransfer.setData(d.DataTransfers.TEXT,L),D.dataTransfer.setDragImage){let M;this.dnd.getDragLabel&&(M=this.dnd.getDragLabel(T,D)),typeof M>"u"&&(M=String(T.length));const A=(0,k.$)(".monaco-drag-image");A.textContent=M,(O=>{for(;O&&!O.classList.contains("monaco-workbench");)O=O.parentElement;return O||this.domNode.ownerDocument})(this.domNode).appendChild(A),D.dataTransfer.setDragImage(A,-10,-10),setTimeout(()=>A.remove(),0)}this.domNode.classList.add("dragging"),this.currentDragData=new r(T),l.CurrentDragAndDropData=new u(T),this.dnd.onDragStart?.(this.currentDragData,D)}onDragOver(S){if(S.browserEvent.preventDefault(),this.onDragLeaveTimeout.dispose(),l.CurrentDragAndDropData&&l.CurrentDragAndDropData.getData()==="vscode-ui"||(this.setupDragAndDropScrollTopAnimation(S.browserEvent),!S.browserEvent.dataTransfer))return!1;if(!this.currentDragData)if(l.CurrentDragAndDropData)this.currentDragData=l.CurrentDragAndDropData;else{if(!S.browserEvent.dataTransfer.types)return!1;this.currentDragData=new C}const L=this.dnd.onDragOver(this.currentDragData,S.element,S.index,S.sector,S.browserEvent);if(this.canDrop=typeof L=="boolean"?L:L.accept,!this.canDrop)return this.currentDragFeedback=void 0,this.currentDragFeedbackDisposable.dispose(),!1;S.browserEvent.dataTransfer.dropEffect=typeof L!="boolean"&&L.effect?.type===0?"copy":"move";let D;typeof L!="boolean"&&L.feedback?D=L.feedback:typeof S.index>"u"?D=[-1]:D=[S.index],D=(0,m.distinct)(D).filter(M=>M>=-1&&MM-A),D=D[0]===-1?[-1]:D;let T=typeof L!="boolean"&&L.effect&&L.effect.position?L.effect.position:"drop-target";if(f(this.currentDragFeedback,D)&&this.currentDragFeedbackPosition===T)return!0;if(this.currentDragFeedback=D,this.currentDragFeedbackPosition=T,this.currentDragFeedbackDisposable.dispose(),D[0]===-1)this.domNode.classList.add(T),this.rowsContainer.classList.add(T),this.currentDragFeedbackDisposable=(0,n.toDisposable)(()=>{this.domNode.classList.remove(T),this.rowsContainer.classList.remove(T)});else{if(D.length>1&&T!=="drop-target")throw new Error("Can't use multiple feedbacks with position different than 'over'");T==="drop-target-after"&&D[0]{for(const M of D){const A=this.items[M];A.dropTarget=!1,A.row?.domNode.classList.remove(T)}})}return!0}onDragLeave(S){this.onDragLeaveTimeout.dispose(),this.onDragLeaveTimeout=(0,_.disposableTimeout)(()=>this.clearDragOverFeedback(),100,this.disposables),this.currentDragData&&this.dnd.onDragLeave?.(this.currentDragData,S.element,S.index,S.browserEvent)}onDrop(S){if(!this.canDrop)return;const L=this.currentDragData;this.teardownDragAndDropScrollTopAnimation(),this.clearDragOverFeedback(),this.domNode.classList.remove("dragging"),this.currentDragData=void 0,l.CurrentDragAndDropData=void 0,!(!L||!S.browserEvent.dataTransfer)&&(S.browserEvent.preventDefault(),L.update(S.browserEvent.dataTransfer),this.dnd.drop(L,S.element,S.index,S.sector,S.browserEvent))}onDragEnd(S){this.canDrop=!1,this.teardownDragAndDropScrollTopAnimation(),this.clearDragOverFeedback(),this.domNode.classList.remove("dragging"),this.currentDragData=void 0,l.CurrentDragAndDropData=void 0,this.dnd.onDragEnd?.(S)}clearDragOverFeedback(){this.currentDragFeedback=void 0,this.currentDragFeedbackPosition=void 0,this.currentDragFeedbackDisposable.dispose(),this.currentDragFeedbackDisposable=n.Disposable.None}setupDragAndDropScrollTopAnimation(S){if(!this.dragOverAnimationDisposable){const L=(0,k.getTopLeftOffset)(this.domNode).top;this.dragOverAnimationDisposable=(0,k.animate)((0,k.getWindow)(this.domNode),this.animateDragAndDropScrollTop.bind(this,L))}this.dragOverAnimationStopDisposable.dispose(),this.dragOverAnimationStopDisposable=(0,_.disposableTimeout)(()=>{this.dragOverAnimationDisposable&&(this.dragOverAnimationDisposable.dispose(),this.dragOverAnimationDisposable=void 0)},1e3,this.disposables),this.dragOverMouseY=S.pageY}animateDragAndDropScrollTop(S){if(this.dragOverMouseY===void 0)return;const L=this.dragOverMouseY-S,D=this.renderHeight-35;L<35?this.scrollTop+=Math.max(-14,Math.floor(.3*(L-35))):L>D&&(this.scrollTop+=Math.min(14,Math.floor(.3*(L-D))))}teardownDragAndDropScrollTopAnimation(){this.dragOverAnimationStopDisposable.dispose(),this.dragOverAnimationDisposable&&(this.dragOverAnimationDisposable.dispose(),this.dragOverAnimationDisposable=void 0)}getTargetSector(S,L){if(L===void 0)return;const D=S.offsetY/this.items[L].size,T=Math.floor(D/.25);return(0,c.clamp)(T,0,3)}getItemIndexFromEventTarget(S){const L=this.scrollableElement.getDomNode();let D=S;for(;((0,k.isHTMLElement)(D)||(0,k.isSVGElement)(D))&&D!==this.rowsContainer&&L.contains(D);){const T=D.getAttribute("data-index");if(T){const M=Number(T);if(!isNaN(M))return M}D=D.parentElement}}getRenderRange(S,L){return{start:this.rangeMap.indexAt(S),end:this.rangeMap.indexAfter(S+L-1)}}_rerender(S,L,D){const T=this.getRenderRange(S,L);let M,A;S===this.elementTop(T.start)?(M=T.start,A=0):T.end-T.start>1&&(M=T.start+1,A=this.elementTop(M)-S);let P=0;for(;;){const N=this.getRenderRange(S,L);let O=!1;for(let F=N.start;F=W.start;V--)this.insertItemInDOM(V);for(let W=N.start;WB.templateData===ge);if(X>=0){const B=this.renderedElements[X];this.trait.unrender(ge),B.index=de}else{const B={index:de,templateData:ge};this.renderedElements.push(B)}this.trait.renderIndex(de,ge)}splice(ee,de,ge){const X=[];for(const B of this.renderedElements)B.index=ee+de&&X.push({index:B.index+ge-de,templateData:B.templateData});this.renderedElements=X}renderIndexes(ee){for(const{index:de,templateData:ge}of this.renderedElements)ee.indexOf(de)>-1&&this.trait.renderIndex(de,ge)}disposeTemplate(ee){const de=this.renderedElements.findIndex(ge=>ge.templateData===ee);de<0||this.renderedElements.splice(de,1)}}class f{get name(){return this._trait}get renderer(){return new C(this)}constructor(ee){this._trait=ee,this.indexes=[],this.sortedIndexes=[],this._onChange=new o.Emitter,this.onChange=this._onChange.event}splice(ee,de,ge){const X=ge.length-de,B=ee+de,$=[];let Q=0;for(;Q=B;)$.push(this.sortedIndexes[Q++]+X);this.renderer.splice(ee,de,ge.length),this._set($,$)}renderIndex(ee,de){de.classList.toggle(this._trait,this.contains(ee))}unrender(ee){ee.classList.remove(this._trait)}set(ee,de){return this._set(ee,[...ee].sort(J),de)}_set(ee,de,ge){const X=this.indexes,B=this.sortedIndexes;this.indexes=ee,this.sortedIndexes=de;const $=K(B,ee);return this.renderer.renderIndexes($),this._onChange.fire({indexes:ee,browserEvent:ge}),X}get(){return this.indexes}contains(ee){return(0,_.binarySearch)(this.sortedIndexes,ee,J)>=0}dispose(){(0,i.dispose)(this._onChange)}}ke([n.memoize],f.prototype,"renderer",null);class h extends f{constructor(ee){super("selected"),this.setAriaSelected=ee}renderIndex(ee,de){super.renderIndex(ee,de),this.setAriaSelected&&(this.contains(ee)?de.setAttribute("aria-selected","true"):de.setAttribute("aria-selected","false"))}}class v{constructor(ee,de,ge){this.trait=ee,this.view=de,this.identityProvider=ge}splice(ee,de,ge){if(!this.identityProvider)return this.trait.splice(ee,de,new Array(ge.length).fill(!1));const X=this.trait.get().map(Q=>this.identityProvider.getId(this.view.element(Q)).toString());if(X.length===0)return this.trait.splice(ee,de,new Array(ge.length).fill(!1));const B=new Set(X),$=ge.map(Q=>B.has(this.identityProvider.getId(Q).toString()));this.trait.splice(ee,de,$)}}function w(ae){return ae.tagName==="INPUT"||ae.tagName==="TEXTAREA"}function S(ae,ee){return ae.classList.contains(ee)?!0:ae.classList.contains("monaco-list")||!ae.parentElement?!1:S(ae.parentElement,ee)}function L(ae){return S(ae,"monaco-editor")}function D(ae){return S(ae,"monaco-custom-toggle")}function T(ae){return S(ae,"action-item")}function M(ae){return S(ae,"monaco-tree-sticky-row")}function A(ae){return ae.classList.contains("monaco-tree-sticky-container")}function P(ae){return ae.tagName==="A"&&ae.classList.contains("monaco-button")||ae.tagName==="DIV"&&ae.classList.contains("monaco-button-dropdown")?!0:ae.classList.contains("monaco-list")||!ae.parentElement?!1:P(ae.parentElement)}class N{get onKeyDown(){return o.Event.chain(this.disposables.add(new k.DomEmitter(this.view.domNode,"keydown")).event,ee=>ee.filter(de=>!w(de.target)).map(de=>new I.StandardKeyboardEvent(de)))}constructor(ee,de,ge){this.list=ee,this.view=de,this.disposables=new i.DisposableStore,this.multipleSelectionDisposables=new i.DisposableStore,this.multipleSelectionSupport=ge.multipleSelectionSupport,this.disposables.add(this.onKeyDown(X=>{switch(X.keyCode){case 3:return this.onEnter(X);case 16:return this.onUpArrow(X);case 18:return this.onDownArrow(X);case 11:return this.onPageUpArrow(X);case 12:return this.onPageDownArrow(X);case 9:return this.onEscape(X);case 31:this.multipleSelectionSupport&&(g.isMacintosh?X.metaKey:X.ctrlKey)&&this.onCtrlA(X)}}))}updateOptions(ee){ee.multipleSelectionSupport!==void 0&&(this.multipleSelectionSupport=ee.multipleSelectionSupport)}onEnter(ee){ee.preventDefault(),ee.stopPropagation(),this.list.setSelection(this.list.getFocus(),ee.browserEvent)}onUpArrow(ee){ee.preventDefault(),ee.stopPropagation(),this.list.focusPrevious(1,!1,ee.browserEvent);const de=this.list.getFocus()[0];this.list.setAnchor(de),this.list.reveal(de),this.view.domNode.focus()}onDownArrow(ee){ee.preventDefault(),ee.stopPropagation(),this.list.focusNext(1,!1,ee.browserEvent);const de=this.list.getFocus()[0];this.list.setAnchor(de),this.list.reveal(de),this.view.domNode.focus()}onPageUpArrow(ee){ee.preventDefault(),ee.stopPropagation(),this.list.focusPreviousPage(ee.browserEvent);const de=this.list.getFocus()[0];this.list.setAnchor(de),this.list.reveal(de),this.view.domNode.focus()}onPageDownArrow(ee){ee.preventDefault(),ee.stopPropagation(),this.list.focusNextPage(ee.browserEvent);const de=this.list.getFocus()[0];this.list.setAnchor(de),this.list.reveal(de),this.view.domNode.focus()}onCtrlA(ee){ee.preventDefault(),ee.stopPropagation(),this.list.setSelection((0,_.range)(this.list.length),ee.browserEvent),this.list.setAnchor(void 0),this.view.domNode.focus()}onEscape(ee){this.list.getSelection().length&&(ee.preventDefault(),ee.stopPropagation(),this.list.setSelection([],ee.browserEvent),this.list.setAnchor(void 0),this.view.domNode.focus())}dispose(){this.disposables.dispose(),this.multipleSelectionDisposables.dispose()}}ke([n.memoize],N.prototype,"onKeyDown",null);var O;(function(ae){ae[ae.Automatic=0]="Automatic",ae[ae.Trigger=1]="Trigger"})(O||(e.TypeNavigationMode=O={}));var F;(function(ae){ae[ae.Idle=0]="Idle",ae[ae.Typing=1]="Typing"})(F||(F={})),e.DefaultKeyboardNavigationDelegate=new class{mightProducePrintableCharacter(ae){return ae.ctrlKey||ae.metaKey||ae.altKey?!1:ae.keyCode>=31&&ae.keyCode<=56||ae.keyCode>=21&&ae.keyCode<=30||ae.keyCode>=98&&ae.keyCode<=107||ae.keyCode>=85&&ae.keyCode<=95}};class x{constructor(ee,de,ge,X,B){this.list=ee,this.view=de,this.keyboardNavigationLabelProvider=ge,this.keyboardNavigationEventFilter=X,this.delegate=B,this.enabled=!1,this.state=F.Idle,this.mode=O.Automatic,this.triggered=!1,this.previouslyFocused=-1,this.enabledDisposables=new i.DisposableStore,this.disposables=new i.DisposableStore,this.updateOptions(ee.options)}updateOptions(ee){ee.typeNavigationEnabled??!0?this.enable():this.disable(),this.mode=ee.typeNavigationMode??O.Automatic}enable(){if(this.enabled)return;let ee=!1;const de=o.Event.chain(this.enabledDisposables.add(new k.DomEmitter(this.view.domNode,"keydown")).event,B=>B.filter($=>!w($.target)).filter(()=>this.mode===O.Automatic||this.triggered).map($=>new I.StandardKeyboardEvent($)).filter($=>ee||this.keyboardNavigationEventFilter($)).filter($=>this.delegate.mightProducePrintableCharacter($)).forEach($=>d.EventHelper.stop($,!0)).map($=>$.browserEvent.key)),ge=o.Event.debounce(de,()=>null,800,void 0,void 0,void 0,this.enabledDisposables);o.Event.reduce(o.Event.any(de,ge),(B,$)=>$===null?null:(B||"")+$,void 0,this.enabledDisposables)(this.onInput,this,this.enabledDisposables),ge(this.onClear,this,this.enabledDisposables),de(()=>ee=!0,void 0,this.enabledDisposables),ge(()=>ee=!1,void 0,this.enabledDisposables),this.enabled=!0,this.triggered=!1}disable(){this.enabled&&(this.enabledDisposables.clear(),this.enabled=!1,this.triggered=!1)}onClear(){const ee=this.list.getFocus();if(ee.length>0&&ee[0]===this.previouslyFocused){const de=this.list.options.accessibilityProvider?.getAriaLabel(this.list.element(ee[0]));typeof de=="string"?(0,y.alert)(de):de&&(0,y.alert)(de.get())}this.previouslyFocused=-1}onInput(ee){if(!ee){this.state=F.Idle,this.triggered=!1;return}const de=this.list.getFocus(),ge=de.length>0?de[0]:0,X=this.state===F.Idle?1:0;this.state=F.Typing;for(let B=0;B1&&te.length===1){this.previouslyFocused=ge,this.list.setFocus([$]),this.list.reveal($);return}}}else if(typeof Z>"u"||(0,t.matchesPrefix)(ee,Z)){this.previouslyFocused=ge,this.list.setFocus([$]),this.list.reveal($);return}}}dispose(){this.disable(),this.enabledDisposables.dispose(),this.disposables.dispose()}}class W{constructor(ee,de){this.list=ee,this.view=de,this.disposables=new i.DisposableStore;const ge=o.Event.chain(this.disposables.add(new k.DomEmitter(de.domNode,"keydown")).event,B=>B.filter($=>!w($.target)).map($=>new I.StandardKeyboardEvent($)));o.Event.chain(ge,B=>B.filter($=>$.keyCode===2&&!$.ctrlKey&&!$.metaKey&&!$.shiftKey&&!$.altKey))(this.onTab,this,this.disposables)}onTab(ee){if(ee.target!==this.view.domNode)return;const de=this.list.getFocus();if(de.length===0)return;const ge=this.view.domElement(de[0]);if(!ge)return;const X=ge.querySelector("[tabIndex]");if(!X||!(0,d.isHTMLElement)(X)||X.tabIndex===-1)return;const B=(0,d.getWindow)(X).getComputedStyle(X);B.visibility==="hidden"||B.display==="none"||(ee.preventDefault(),ee.stopPropagation(),X.focus())}dispose(){this.disposables.dispose()}}function V(ae){return g.isMacintosh?ae.browserEvent.metaKey:ae.browserEvent.ctrlKey}function q(ae){return ae.browserEvent.shiftKey}function H(ae){return(0,d.isMouseEvent)(ae)&&ae.button===2}const z={isSelectionSingleChangeEvent:V,isSelectionRangeChangeEvent:q};class U{constructor(ee){this.list=ee,this.disposables=new i.DisposableStore,this._onPointer=new o.Emitter,this.onPointer=this._onPointer.event,ee.options.multipleSelectionSupport!==!1&&(this.multipleSelectionController=this.list.options.multipleSelectionController||z),this.mouseSupport=typeof ee.options.mouseSupport>"u"||!!ee.options.mouseSupport,this.mouseSupport&&(ee.onMouseDown(this.onMouseDown,this,this.disposables),ee.onContextMenu(this.onContextMenu,this,this.disposables),ee.onMouseDblClick(this.onDoubleClick,this,this.disposables),ee.onTouchStart(this.onMouseDown,this,this.disposables),this.disposables.add(E.Gesture.addTarget(ee.getHTMLElement()))),o.Event.any(ee.onMouseClick,ee.onMouseMiddleClick,ee.onTap)(this.onViewPointer,this,this.disposables)}updateOptions(ee){ee.multipleSelectionSupport!==void 0&&(this.multipleSelectionController=void 0,ee.multipleSelectionSupport&&(this.multipleSelectionController=this.list.options.multipleSelectionController||z))}isSelectionSingleChangeEvent(ee){return this.multipleSelectionController?this.multipleSelectionController.isSelectionSingleChangeEvent(ee):!1}isSelectionRangeChangeEvent(ee){return this.multipleSelectionController?this.multipleSelectionController.isSelectionRangeChangeEvent(ee):!1}isSelectionChangeEvent(ee){return this.isSelectionSingleChangeEvent(ee)||this.isSelectionRangeChangeEvent(ee)}onMouseDown(ee){L(ee.browserEvent.target)||(0,d.getActiveElement)()!==ee.browserEvent.target&&this.list.domFocus()}onContextMenu(ee){if(w(ee.browserEvent.target)||L(ee.browserEvent.target))return;const de=typeof ee.index>"u"?[]:[ee.index];this.list.setFocus(de,ee.browserEvent)}onViewPointer(ee){if(!this.mouseSupport||w(ee.browserEvent.target)||L(ee.browserEvent.target)||ee.browserEvent.isHandledByList)return;ee.browserEvent.isHandledByList=!0;const de=ee.index;if(typeof de>"u"){this.list.setFocus([],ee.browserEvent),this.list.setSelection([],ee.browserEvent),this.list.setAnchor(void 0);return}if(this.isSelectionChangeEvent(ee))return this.changeSelection(ee);this.list.setFocus([de],ee.browserEvent),this.list.setAnchor(de),H(ee.browserEvent)||this.list.setSelection([de],ee.browserEvent),this._onPointer.fire(ee)}onDoubleClick(ee){if(w(ee.browserEvent.target)||L(ee.browserEvent.target)||this.isSelectionChangeEvent(ee)||ee.browserEvent.isHandledByList)return;ee.browserEvent.isHandledByList=!0;const de=this.list.getFocus();this.list.setSelection(de,ee.browserEvent)}changeSelection(ee){const de=ee.index;let ge=this.list.getAnchor();if(this.isSelectionRangeChangeEvent(ee)){typeof ge>"u"&&(ge=this.list.getFocus()[0]??de,this.list.setAnchor(ge));const X=Math.min(ge,de),B=Math.max(ge,de),$=(0,_.range)(X,B+1),Q=this.list.getSelection(),Z=G(K(Q,[ge]),ge);if(Z.length===0)return;const te=K($,R(Q,Z));this.list.setSelection(te,ee.browserEvent),this.list.setFocus([de],ee.browserEvent)}else if(this.isSelectionSingleChangeEvent(ee)){const X=this.list.getSelection(),B=X.filter($=>$!==de);this.list.setFocus([de]),this.list.setAnchor(de),X.length===B.length?this.list.setSelection([...B,de],ee.browserEvent):this.list.setSelection(B,ee.browserEvent)}}dispose(){this.disposables.dispose()}}e.MouseController=U;class j{constructor(ee,de){this.styleElement=ee,this.selectorSuffix=de}style(ee){const de=this.selectorSuffix&&`.${this.selectorSuffix}`,ge=[];ee.listBackground&&ge.push(`.monaco-list${de} .monaco-list-rows { background: ${ee.listBackground}; }`),ee.listFocusBackground&&(ge.push(`.monaco-list${de}:focus .monaco-list-row.focused { background-color: ${ee.listFocusBackground}; }`),ge.push(`.monaco-list${de}:focus .monaco-list-row.focused:hover { background-color: ${ee.listFocusBackground}; }`)),ee.listFocusForeground&&ge.push(`.monaco-list${de}:focus .monaco-list-row.focused { color: ${ee.listFocusForeground}; }`),ee.listActiveSelectionBackground&&(ge.push(`.monaco-list${de}:focus .monaco-list-row.selected { background-color: ${ee.listActiveSelectionBackground}; }`),ge.push(`.monaco-list${de}:focus .monaco-list-row.selected:hover { background-color: ${ee.listActiveSelectionBackground}; }`)),ee.listActiveSelectionForeground&&ge.push(`.monaco-list${de}:focus .monaco-list-row.selected { color: ${ee.listActiveSelectionForeground}; }`),ee.listActiveSelectionIconForeground&&ge.push(`.monaco-list${de}:focus .monaco-list-row.selected .codicon { color: ${ee.listActiveSelectionIconForeground}; }`),ee.listFocusAndSelectionBackground&&ge.push(` .monaco-drag-image, .monaco-list${de}:focus .monaco-list-row.selected.focused { background-color: ${ee.listFocusAndSelectionBackground}; } `),ee.listFocusAndSelectionForeground&&ge.push(` .monaco-drag-image, .monaco-list${de}:focus .monaco-list-row.selected.focused { color: ${ee.listFocusAndSelectionForeground}; } `),ee.listInactiveFocusForeground&&(ge.push(`.monaco-list${de} .monaco-list-row.focused { color: ${ee.listInactiveFocusForeground}; }`),ge.push(`.monaco-list${de} .monaco-list-row.focused:hover { color: ${ee.listInactiveFocusForeground}; }`)),ee.listInactiveSelectionIconForeground&&ge.push(`.monaco-list${de} .monaco-list-row.focused .codicon { color: ${ee.listInactiveSelectionIconForeground}; }`),ee.listInactiveFocusBackground&&(ge.push(`.monaco-list${de} .monaco-list-row.focused { background-color: ${ee.listInactiveFocusBackground}; }`),ge.push(`.monaco-list${de} .monaco-list-row.focused:hover { background-color: ${ee.listInactiveFocusBackground}; }`)),ee.listInactiveSelectionBackground&&(ge.push(`.monaco-list${de} .monaco-list-row.selected { background-color: ${ee.listInactiveSelectionBackground}; }`),ge.push(`.monaco-list${de} .monaco-list-row.selected:hover { background-color: ${ee.listInactiveSelectionBackground}; }`)),ee.listInactiveSelectionForeground&&ge.push(`.monaco-list${de} .monaco-list-row.selected { color: ${ee.listInactiveSelectionForeground}; }`),ee.listHoverBackground&&ge.push(`.monaco-list${de}:not(.drop-target):not(.dragging) .monaco-list-row:hover:not(.selected):not(.focused) { background-color: ${ee.listHoverBackground}; }`),ee.listHoverForeground&&ge.push(`.monaco-list${de}:not(.drop-target):not(.dragging) .monaco-list-row:hover:not(.selected):not(.focused) { color: ${ee.listHoverForeground}; }`);const X=(0,d.asCssValueWithDefault)(ee.listFocusAndSelectionOutline,(0,d.asCssValueWithDefault)(ee.listSelectionOutline,ee.listFocusOutline??""));X&&ge.push(`.monaco-list${de}:focus .monaco-list-row.focused.selected { outline: 1px solid ${X}; outline-offset: -1px;}`),ee.listFocusOutline&&ge.push(` .monaco-drag-image, .monaco-list${de}:focus .monaco-list-row.focused { outline: 1px solid ${ee.listFocusOutline}; outline-offset: -1px; } .monaco-workbench.context-menu-visible .monaco-list${de}.last-focused .monaco-list-row.focused { outline: 1px solid ${ee.listFocusOutline}; outline-offset: -1px; } `);const B=(0,d.asCssValueWithDefault)(ee.listSelectionOutline,ee.listInactiveFocusOutline??"");B&&ge.push(`.monaco-list${de} .monaco-list-row.focused.selected { outline: 1px dotted ${B}; outline-offset: -1px; }`),ee.listSelectionOutline&&ge.push(`.monaco-list${de} .monaco-list-row.selected { outline: 1px dotted ${ee.listSelectionOutline}; outline-offset: -1px; }`),ee.listInactiveFocusOutline&&ge.push(`.monaco-list${de} .monaco-list-row.focused { outline: 1px dotted ${ee.listInactiveFocusOutline}; outline-offset: -1px; }`),ee.listHoverOutline&&ge.push(`.monaco-list${de} .monaco-list-row:hover { outline: 1px dashed ${ee.listHoverOutline}; outline-offset: -1px; }`),ee.listDropOverBackground&&ge.push(` .monaco-list${de}.drop-target, .monaco-list${de} .monaco-list-rows.drop-target, .monaco-list${de} .monaco-list-row.drop-target { background-color: ${ee.listDropOverBackground} !important; color: inherit !important; } `),ee.listDropBetweenBackground&&(ge.push(` .monaco-list${de} .monaco-list-rows.drop-target-before .monaco-list-row:first-child::before, .monaco-list${de} .monaco-list-row.drop-target-before::before { content: ""; position: absolute; top: 0px; left: 0px; width: 100%; height: 1px; background-color: ${ee.listDropBetweenBackground}; }`),ge.push(` .monaco-list${de} .monaco-list-rows.drop-target-after .monaco-list-row:last-child::after, .monaco-list${de} .monaco-list-row.drop-target-after::after { content: ""; position: absolute; bottom: 0px; left: 0px; width: 100%; height: 1px; background-color: ${ee.listDropBetweenBackground}; }`)),ee.tableColumnsBorder&&ge.push(` .monaco-table > .monaco-split-view2, .monaco-table > .monaco-split-view2 .monaco-sash.vertical::before, .monaco-workbench:not(.reduce-motion) .monaco-table:hover > .monaco-split-view2, .monaco-workbench:not(.reduce-motion) .monaco-table:hover > .monaco-split-view2 .monaco-sash.vertical::before { border-color: ${ee.tableColumnsBorder}; } .monaco-workbench:not(.reduce-motion) .monaco-table > .monaco-split-view2, .monaco-workbench:not(.reduce-motion) .monaco-table > .monaco-split-view2 .monaco-sash.vertical::before { border-color: transparent; } `),ee.tableOddRowsBackgroundColor&&ge.push(` .monaco-table .monaco-list-row[data-parity=odd]:not(.focused):not(.selected):not(:hover) .monaco-table-tr, .monaco-table .monaco-list:not(:focus) .monaco-list-row[data-parity=odd].focused:not(.selected):not(:hover) .monaco-table-tr, .monaco-table .monaco-list:not(.focused) .monaco-list-row[data-parity=odd].focused:not(.selected):not(:hover) .monaco-table-tr { background-color: ${ee.tableOddRowsBackgroundColor}; } `),this.styleElement.textContent=ge.join(` `)}}e.DefaultStyleController=j,e.unthemedListStyles={listFocusBackground:"#7FB0D0",listActiveSelectionBackground:"#0E639C",listActiveSelectionForeground:"#FFFFFF",listActiveSelectionIconForeground:"#FFFFFF",listFocusAndSelectionOutline:"#90C2F9",listFocusAndSelectionBackground:"#094771",listFocusAndSelectionForeground:"#FFFFFF",listInactiveSelectionBackground:"#3F3F46",listInactiveSelectionIconForeground:"#FFFFFF",listHoverBackground:"#2A2D2E",listDropOverBackground:"#383B3D",listDropBetweenBackground:"#EEEEEE",treeIndentGuidesStroke:"#a9a9a9",treeInactiveIndentGuidesStroke:p.Color.fromHex("#a9a9a9").transparent(.4).toString(),tableColumnsBorder:p.Color.fromHex("#cccccc").transparent(.2).toString(),tableOddRowsBackgroundColor:p.Color.fromHex("#cccccc").transparent(.04).toString(),listBackground:void 0,listFocusForeground:void 0,listInactiveSelectionForeground:void 0,listInactiveFocusForeground:void 0,listInactiveFocusBackground:void 0,listHoverForeground:void 0,listFocusOutline:void 0,listInactiveFocusOutline:void 0,listSelectionOutline:void 0,listHoverOutline:void 0,treeStickyScrollBackground:void 0,treeStickyScrollBorder:void 0,treeStickyScrollShadow:void 0};const Y={keyboardSupport:!0,mouseSupport:!0,multipleSelectionSupport:!0,dnd:{getDragURI(){return null},onDragStart(){},onDragOver(){return!1},drop(){},dispose(){}}};function G(ae,ee){const de=ae.indexOf(ee);if(de===-1)return[];const ge=[];let X=de-1;for(;X>=0&&ae[X]===ee-(de-X);)ge.push(ae[X--]);for(ge.reverse(),X=de;X=ae.length)de.push(ee[X++]);else if(X>=ee.length)de.push(ae[ge++]);else if(ae[ge]===ee[X]){de.push(ae[ge]),ge++,X++;continue}else ae[ge]=ae.length)de.push(ee[X++]);else if(X>=ee.length)de.push(ae[ge++]);else if(ae[ge]===ee[X]){ge++,X++;continue}else ae[ge]ae-ee;class ie{constructor(ee,de){this._templateId=ee,this.renderers=de}get templateId(){return this._templateId}renderTemplate(ee){return this.renderers.map(de=>de.renderTemplate(ee))}renderElement(ee,de,ge,X){let B=0;for(const $ of this.renderers)$.renderElement(ee,de,ge[B++],X)}disposeElement(ee,de,ge,X){let B=0;for(const $ of this.renderers)$.disposeElement?.(ee,de,ge[B],X),B+=1}disposeTemplate(ee){let de=0;for(const ge of this.renderers)ge.disposeTemplate(ee[de++])}}class ue{constructor(ee){this.accessibilityProvider=ee,this.templateId="a18n"}renderTemplate(ee){return{container:ee,disposables:new i.DisposableStore}}renderElement(ee,de,ge){const X=this.accessibilityProvider.getAriaLabel(ee),B=X&&typeof X!="string"?X:(0,u.constObservable)(X);ge.disposables.add((0,u.autorun)(Q=>{this.setAriaLabel(Q.readObservable(B),ge.container)}));const $=this.accessibilityProvider.getAriaLevel&&this.accessibilityProvider.getAriaLevel(ee);typeof $=="number"?ge.container.setAttribute("aria-level",`${$}`):ge.container.removeAttribute("aria-level")}setAriaLabel(ee,de){ee?de.setAttribute("aria-label",ee):de.removeAttribute("aria-label")}disposeElement(ee,de,ge,X){ge.disposables.clear()}disposeTemplate(ee){ee.disposables.dispose()}}class he{constructor(ee,de){this.list=ee,this.dnd=de}getDragElements(ee){const de=this.list.getSelectedElements();return de.indexOf(ee)>-1?de:[ee]}getDragURI(ee){return this.dnd.getDragURI(ee)}getDragLabel(ee,de){if(this.dnd.getDragLabel)return this.dnd.getDragLabel(ee,de)}onDragStart(ee,de){this.dnd.onDragStart?.(ee,de)}onDragOver(ee,de,ge,X,B){return this.dnd.onDragOver(ee,de,ge,X,B)}onDragLeave(ee,de,ge,X){this.dnd.onDragLeave?.(ee,de,ge,X)}onDragEnd(ee){this.dnd.onDragEnd?.(ee)}drop(ee,de,ge,X,B){this.dnd.drop(ee,de,ge,X,B)}dispose(){this.dnd.dispose()}}class pe{get onDidChangeFocus(){return o.Event.map(this.eventBufferer.wrapEvent(this.focus.onChange),ee=>this.toListEvent(ee),this.disposables)}get onDidChangeSelection(){return o.Event.map(this.eventBufferer.wrapEvent(this.selection.onChange),ee=>this.toListEvent(ee),this.disposables)}get domId(){return this.view.domId}get onDidScroll(){return this.view.onDidScroll}get onMouseClick(){return this.view.onMouseClick}get onMouseDblClick(){return this.view.onMouseDblClick}get onMouseMiddleClick(){return this.view.onMouseMiddleClick}get onPointer(){return this.mouseController.onPointer}get onMouseDown(){return this.view.onMouseDown}get onMouseOver(){return this.view.onMouseOver}get onMouseOut(){return this.view.onMouseOut}get onTouchStart(){return this.view.onTouchStart}get onTap(){return this.view.onTap}get onContextMenu(){let ee=!1;const de=o.Event.chain(this.disposables.add(new k.DomEmitter(this.view.domNode,"keydown")).event,B=>B.map($=>new I.StandardKeyboardEvent($)).filter($=>ee=$.keyCode===58||$.shiftKey&&$.keyCode===68).map($=>d.EventHelper.stop($,!0)).filter(()=>!1)),ge=o.Event.chain(this.disposables.add(new k.DomEmitter(this.view.domNode,"keyup")).event,B=>B.forEach(()=>ee=!1).map($=>new I.StandardKeyboardEvent($)).filter($=>$.keyCode===58||$.shiftKey&&$.keyCode===68).map($=>d.EventHelper.stop($,!0)).map(({browserEvent:$})=>{const Q=this.getFocus(),Z=Q.length?Q[0]:void 0,te=typeof Z<"u"?this.view.element(Z):void 0,re=typeof Z<"u"?this.view.domElement(Z):this.view.domNode;return{index:Z,element:te,anchor:re,browserEvent:$}})),X=o.Event.chain(this.view.onContextMenu,B=>B.filter($=>!ee).map(({element:$,index:Q,browserEvent:Z})=>({element:$,index:Q,anchor:new r.StandardMouseEvent((0,d.getWindow)(this.view.domNode),Z),browserEvent:Z})));return o.Event.any(de,ge,X)}get onKeyDown(){return this.disposables.add(new k.DomEmitter(this.view.domNode,"keydown")).event}get onDidFocus(){return o.Event.signal(this.disposables.add(new k.DomEmitter(this.view.domNode,"focus",!0)).event)}get onDidBlur(){return o.Event.signal(this.disposables.add(new k.DomEmitter(this.view.domNode,"blur",!0)).event)}constructor(ee,de,ge,X,B=Y){this.user=ee,this._options=B,this.focus=new f("focused"),this.anchor=new f("anchor"),this.eventBufferer=new o.EventBufferer,this._ariaLabel="",this.disposables=new i.DisposableStore,this._onDidDispose=new o.Emitter,this.onDidDispose=this._onDidDispose.event;const $=this._options.accessibilityProvider&&this._options.accessibilityProvider.getWidgetRole?this._options.accessibilityProvider?.getWidgetRole():"list";this.selection=new h($!=="listbox");const Q=[this.focus.renderer,this.selection.renderer];this.accessibilityProvider=B.accessibilityProvider,this.accessibilityProvider&&(Q.push(new ue(this.accessibilityProvider)),this.accessibilityProvider.onDidChangeActiveDescendant?.(this.onDidChangeActiveDescendant,this,this.disposables)),X=X.map(te=>new ie(te.templateId,[...Q,te]));const Z={...B,dnd:B.dnd&&new he(this,B.dnd)};if(this.view=this.createListView(de,ge,X,Z),this.view.domNode.setAttribute("role",$),B.styleController)this.styleController=B.styleController(this.view.domId);else{const te=(0,d.createStyleSheet)(this.view.domNode);this.styleController=new j(te,this.view.domId)}if(this.spliceable=new m.CombinedSpliceable([new v(this.focus,this.view,B.identityProvider),new v(this.selection,this.view,B.identityProvider),new v(this.anchor,this.view,B.identityProvider),this.view]),this.disposables.add(this.focus),this.disposables.add(this.selection),this.disposables.add(this.anchor),this.disposables.add(this.view),this.disposables.add(this._onDidDispose),this.disposables.add(new W(this,this.view)),(typeof B.keyboardSupport!="boolean"||B.keyboardSupport)&&(this.keyboardController=new N(this,this.view,B),this.disposables.add(this.keyboardController)),B.keyboardNavigationLabelProvider){const te=B.keyboardNavigationDelegate||e.DefaultKeyboardNavigationDelegate;this.typeNavigationController=new x(this,this.view,B.keyboardNavigationLabelProvider,B.keyboardNavigationEventFilter??(()=>!0),te),this.disposables.add(this.typeNavigationController)}this.mouseController=this.createMouseController(B),this.disposables.add(this.mouseController),this.onDidChangeFocus(this._onFocusChange,this,this.disposables),this.onDidChangeSelection(this._onSelectionChange,this,this.disposables),this.accessibilityProvider&&(this.ariaLabel=this.accessibilityProvider.getWidgetAriaLabel()),this._options.multipleSelectionSupport!==!1&&this.view.domNode.setAttribute("aria-multiselectable","true")}createListView(ee,de,ge,X){return new a.ListView(ee,de,ge,X)}createMouseController(ee){return new U(this)}updateOptions(ee={}){this._options={...this._options,...ee},this.typeNavigationController?.updateOptions(this._options),this._options.multipleSelectionController!==void 0&&(this._options.multipleSelectionSupport?this.view.domNode.setAttribute("aria-multiselectable","true"):this.view.domNode.removeAttribute("aria-multiselectable")),this.mouseController.updateOptions(ee),this.keyboardController?.updateOptions(ee),this.view.updateOptions(ee)}get options(){return this._options}splice(ee,de,ge=[]){if(ee<0||ee>this.view.length)throw new l.ListError(this.user,`Invalid start index: ${ee}`);if(de<0)throw new l.ListError(this.user,`Invalid delete count: ${de}`);de===0&&ge.length===0||this.eventBufferer.bufferEvents(()=>this.spliceable.splice(ee,de,ge))}rerender(){this.view.rerender()}element(ee){return this.view.element(ee)}indexOf(ee){return this.view.indexOf(ee)}indexAt(ee){return this.view.indexAt(ee)}get length(){return this.view.length}get contentHeight(){return this.view.contentHeight}get onDidChangeContentHeight(){return this.view.onDidChangeContentHeight}get scrollTop(){return this.view.getScrollTop()}set scrollTop(ee){this.view.setScrollTop(ee)}get scrollHeight(){return this.view.scrollHeight}get renderHeight(){return this.view.renderHeight}get firstVisibleIndex(){return this.view.firstVisibleIndex}get ariaLabel(){return this._ariaLabel}set ariaLabel(ee){this._ariaLabel=ee,this.view.domNode.setAttribute("aria-label",ee)}domFocus(){this.view.domNode.focus({preventScroll:!0})}layout(ee,de){this.view.layout(ee,de)}setSelection(ee,de){for(const ge of ee)if(ge<0||ge>=this.length)throw new l.ListError(this.user,`Invalid index ${ge}`);this.selection.set(ee,de)}getSelection(){return this.selection.get()}getSelectedElements(){return this.getSelection().map(ee=>this.view.element(ee))}setAnchor(ee){if(typeof ee>"u"){this.anchor.set([]);return}if(ee<0||ee>=this.length)throw new l.ListError(this.user,`Invalid index ${ee}`);this.anchor.set([ee])}getAnchor(){return(0,_.firstOrDefault)(this.anchor.get(),void 0)}getAnchorElement(){const ee=this.getAnchor();return typeof ee>"u"?void 0:this.element(ee)}setFocus(ee,de){for(const ge of ee)if(ge<0||ge>=this.length)throw new l.ListError(this.user,`Invalid index ${ge}`);this.focus.set(ee,de)}focusNext(ee=1,de=!1,ge,X){if(this.length===0)return;const B=this.focus.get(),$=this.findNextIndex(B.length>0?B[0]+ee:0,de,X);$>-1&&this.setFocus([$],ge)}focusPrevious(ee=1,de=!1,ge,X){if(this.length===0)return;const B=this.focus.get(),$=this.findPreviousIndex(B.length>0?B[0]-ee:0,de,X);$>-1&&this.setFocus([$],ge)}async focusNextPage(ee,de){let ge=this.view.indexAt(this.view.getScrollTop()+this.view.renderHeight);ge=ge===0?0:ge-1;const X=this.getFocus()[0];if(X!==ge&&(X===void 0||ge>X)){const B=this.findPreviousIndex(ge,!1,de);B>-1&&X!==B?this.setFocus([B],ee):this.setFocus([ge],ee)}else{const B=this.view.getScrollTop();let $=B+this.view.renderHeight;ge>X&&($-=this.view.elementHeight(ge)),this.view.setScrollTop($),this.view.getScrollTop()!==B&&(this.setFocus([]),await(0,b.timeout)(0),await this.focusNextPage(ee,de))}}async focusPreviousPage(ee,de,ge=()=>0){let X;const B=ge(),$=this.view.getScrollTop()+B;$===0?X=this.view.indexAt($):X=this.view.indexAfter($-1);const Q=this.getFocus()[0];if(Q!==X&&(Q===void 0||Q>=X)){const Z=this.findNextIndex(X,!1,de);Z>-1&&Q!==Z?this.setFocus([Z],ee):this.setFocus([X],ee)}else{const Z=$;this.view.setScrollTop($-this.view.renderHeight-B),this.view.getScrollTop()+ge()!==Z&&(this.setFocus([]),await(0,b.timeout)(0),await this.focusPreviousPage(ee,de,ge))}}focusLast(ee,de){if(this.length===0)return;const ge=this.findPreviousIndex(this.length-1,!1,de);ge>-1&&this.setFocus([ge],ee)}focusFirst(ee,de){this.focusNth(0,ee,de)}focusNth(ee,de,ge){if(this.length===0)return;const X=this.findNextIndex(ee,!1,ge);X>-1&&this.setFocus([X],de)}findNextIndex(ee,de=!1,ge){for(let X=0;X=this.length&&!de)return-1;if(ee=ee%this.length,!ge||ge(this.element(ee)))return ee;ee++}return-1}findPreviousIndex(ee,de=!1,ge){for(let X=0;Xthis.view.element(ee))}reveal(ee,de,ge=0){if(ee<0||ee>=this.length)throw new l.ListError(this.user,`Invalid index ${ee}`);const X=this.view.getScrollTop(),B=this.view.elementTop(ee),$=this.view.elementHeight(ee);if((0,c.isNumber)(de)){const Q=$-this.view.renderHeight+ge;this.view.setScrollTop(Q*(0,s.clamp)(de,0,1)+B-ge)}else{const Q=B+$,Z=X+this.view.renderHeight;B=Z||(B=Z&&$>=this.view.renderHeight?this.view.setScrollTop(B-ge):Q>=Z&&this.view.setScrollTop(Q-this.view.renderHeight))}}getRelativeTop(ee,de=0){if(ee<0||ee>=this.length)throw new l.ListError(this.user,`Invalid index ${ee}`);const ge=this.view.getScrollTop(),X=this.view.elementTop(ee),B=this.view.elementHeight(ee);if(Xge+this.view.renderHeight)return null;const $=B-this.view.renderHeight+de;return Math.abs((ge+de-X)/$)}getHTMLElement(){return this.view.domNode}getScrollableElement(){return this.view.scrollableElementDomNode}getElementID(ee){return this.view.getElementDomId(ee)}getElementTop(ee){return this.view.elementTop(ee)}style(ee){this.styleController.style(ee)}toListEvent({indexes:ee,browserEvent:de}){return{indexes:ee,elements:ee.map(ge=>this.view.element(ge)),browserEvent:de}}_onFocusChange(){const ee=this.focus.get();this.view.domNode.classList.toggle("element-focused",ee.length>0),this.onDidChangeActiveDescendant()}onDidChangeActiveDescendant(){const ee=this.focus.get();if(ee.length>0){let de;this.accessibilityProvider?.getActiveDescendantId&&(de=this.accessibilityProvider.getActiveDescendantId(this.view.element(ee[0]))),this.view.domNode.setAttribute("aria-activedescendant",de||this.view.getElementDomId(ee[0]))}else this.view.domNode.removeAttribute("aria-activedescendant")}_onSelectionChange(){const ee=this.selection.get();this.view.domNode.classList.toggle("selection-none",ee.length===0),this.view.domNode.classList.toggle("selection-single",ee.length===1),this.view.domNode.classList.toggle("selection-multiple",ee.length>1)}dispose(){this._onDidDispose.fire(),this.disposables.dispose(),this._onDidDispose.dispose()}}e.List=pe,ke([n.memoize],pe.prototype,"onDidChangeFocus",null),ke([n.memoize],pe.prototype,"onDidChangeSelection",null),ke([n.memoize],pe.prototype,"onContextMenu",null),ke([n.memoize],pe.prototype,"onKeyDown",null),ke([n.memoize],pe.prototype,"onDidFocus",null),ke([n.memoize],pe.prototype,"onDidBlur",null)}),define(ne[637],se([1,0,13,18,6,2,115,305]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PagedList=void 0;class m{get templateId(){return this.renderer.templateId}constructor(o,t){this.renderer=o,this.modelProvider=t}renderTemplate(o){return{data:this.renderer.renderTemplate(o),disposable:E.Disposable.None}}renderElement(o,t,i,s){if(i.disposable?.dispose(),!i.data)return;const g=this.modelProvider();if(g.isResolved(o))return this.renderer.renderElement(g.get(o),o,i.data,s);const c=new k.CancellationTokenSource,l=g.resolve(o,c.token);i.disposable={dispose:()=>c.cancel()},this.renderer.renderPlaceholder(o,i.data),l.then(a=>this.renderer.renderElement(a,o,i.data,s))}disposeTemplate(o){o.disposable&&(o.disposable.dispose(),o.disposable=void 0),o.data&&(this.renderer.disposeTemplate(o.data),o.data=void 0)}}class _{constructor(o,t){this.modelProvider=o,this.accessibilityProvider=t}getWidgetAriaLabel(){return this.accessibilityProvider.getWidgetAriaLabel()}getAriaLabel(o){const t=this.modelProvider();return t.isResolved(o)?this.accessibilityProvider.getAriaLabel(t.get(o)):null}}function b(n,o){return{...o,accessibilityProvider:o.accessibilityProvider&&new _(n,o.accessibilityProvider)}}class p{constructor(o,t,i,s,g={}){const c=()=>this.model,l=s.map(a=>new m(a,c));this.list=new y.List(o,t,i,l,b(c,g))}updateOptions(o){this.list.updateOptions(o)}getHTMLElement(){return this.list.getHTMLElement()}get onDidFocus(){return this.list.onDidFocus}get widget(){return this.list}get onDidDispose(){return this.list.onDidDispose}get onMouseDblClick(){return I.Event.map(this.list.onMouseDblClick,({element:o,index:t,browserEvent:i})=>({element:o===void 0?void 0:this._model.get(o),index:t,browserEvent:i}))}get onPointer(){return I.Event.map(this.list.onPointer,({element:o,index:t,browserEvent:i})=>({element:o===void 0?void 0:this._model.get(o),index:t,browserEvent:i}))}get onDidChangeSelection(){return I.Event.map(this.list.onDidChangeSelection,({elements:o,indexes:t,browserEvent:i})=>({elements:o.map(s=>this._model.get(s)),indexes:t,browserEvent:i}))}get model(){return this._model}set model(o){this._model=o,this.list.splice(0,this.list.length,(0,d.range)(o.length))}getFocus(){return this.list.getFocus()}getSelection(){return this.list.getSelection()}getSelectedElements(){return this.getSelection().map(o=>this.model.get(o))}style(o){this.list.style(o)}dispose(){this.list.dispose()}}e.PagedList=p}),define(ne[357],se([1,0,5,93,173,86,13,33,6,2,141,163,19,474]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SplitView=e.Sizing=void 0;const t={separatorBorder:m.Color.transparent};class i{set size(u){this._size=u}get size(){return this._size}get visible(){return typeof this._cachedVisibleSize>"u"}setVisible(u,C){if(u!==this.visible){u?(this.size=(0,p.clamp)(this._cachedVisibleSize,this.viewMinimumSize,this.viewMaximumSize),this._cachedVisibleSize=void 0):(this._cachedVisibleSize=typeof C=="number"?C:this.size,this.size=0),this.container.classList.toggle("visible",u);try{this.view.setVisible?.(u)}catch(f){console.error("Splitview: Failed to set visible view"),console.error(f)}}}get minimumSize(){return this.visible?this.view.minimumSize:0}get viewMinimumSize(){return this.view.minimumSize}get maximumSize(){return this.visible?this.view.maximumSize:0}get viewMaximumSize(){return this.view.maximumSize}get priority(){return this.view.priority}get proportionalLayout(){return this.view.proportionalLayout??!0}get snap(){return!!this.view.snap}set enabled(u){this.container.style.pointerEvents=u?"":"none"}constructor(u,C,f,h){this.container=u,this.view=C,this.disposable=h,this._cachedVisibleSize=void 0,typeof f=="number"?(this._size=f,this._cachedVisibleSize=void 0,u.classList.add("visible")):(this._size=0,this._cachedVisibleSize=f.cachedVisibleSize)}layout(u,C){this.layoutContainer(u);try{this.view.layout(this.size,u,C)}catch(f){console.error("Splitview: Failed to layout view"),console.error(f)}}dispose(){this.disposable.dispose()}}class s extends i{layoutContainer(u){this.container.style.top=`${u}px`,this.container.style.height=`${this.size}px`}}class g extends i{layoutContainer(u){this.container.style.left=`${u}px`,this.container.style.width=`${this.size}px`}}var c;(function(r){r[r.Idle=0]="Idle",r[r.Busy=1]="Busy"})(c||(c={}));var l;(function(r){r.Distribute={type:"distribute"};function u(h){return{type:"split",index:h}}r.Split=u;function C(h){return{type:"auto",index:h}}r.Auto=C;function f(h){return{type:"invisible",cachedVisibleSize:h}}r.Invisible=f})(l||(e.Sizing=l={}));class a extends b.Disposable{get orthogonalStartSash(){return this._orthogonalStartSash}get orthogonalEndSash(){return this._orthogonalEndSash}get startSnappingEnabled(){return this._startSnappingEnabled}get endSnappingEnabled(){return this._endSnappingEnabled}set orthogonalStartSash(u){for(const C of this.sashItems)C.sash.orthogonalStartSash=u;this._orthogonalStartSash=u}set orthogonalEndSash(u){for(const C of this.sashItems)C.sash.orthogonalEndSash=u;this._orthogonalEndSash=u}set startSnappingEnabled(u){this._startSnappingEnabled!==u&&(this._startSnappingEnabled=u,this.updateSashEnablement())}set endSnappingEnabled(u){this._endSnappingEnabled!==u&&(this._endSnappingEnabled=u,this.updateSashEnablement())}constructor(u,C={}){super(),this.size=0,this._contentSize=0,this.proportions=void 0,this.viewItems=[],this.sashItems=[],this.state=c.Idle,this._onDidSashChange=this._register(new _.Emitter),this._onDidSashReset=this._register(new _.Emitter),this._startSnappingEnabled=!0,this._endSnappingEnabled=!0,this.onDidSashChange=this._onDidSashChange.event,this.onDidSashReset=this._onDidSashReset.event,this.orientation=C.orientation??0,this.inverseAltBehavior=C.inverseAltBehavior??!1,this.proportionalLayout=C.proportionalLayout??!0,this.getSashOrthogonalSize=C.getSashOrthogonalSize,this.el=document.createElement("div"),this.el.classList.add("monaco-split-view2"),this.el.classList.add(this.orientation===0?"vertical":"horizontal"),u.appendChild(this.el),this.sashContainer=(0,d.append)(this.el,(0,d.$)(".sash-container")),this.viewContainer=(0,d.$)(".split-view-container"),this.scrollable=this._register(new n.Scrollable({forceIntegerValues:!0,smoothScrollDuration:125,scheduleAtNextAnimationFrame:h=>(0,d.scheduleAtNextAnimationFrame)((0,d.getWindow)(this.el),h)})),this.scrollableElement=this._register(new E.SmoothScrollableElement(this.viewContainer,{vertical:this.orientation===0?C.scrollbarVisibility??1:2,horizontal:this.orientation===1?C.scrollbarVisibility??1:2},this.scrollable));const f=this._register(new k.DomEmitter(this.viewContainer,"scroll")).event;this._register(f(h=>{const v=this.scrollableElement.getScrollPosition(),w=Math.abs(this.viewContainer.scrollLeft-v.scrollLeft)<=1?void 0:this.viewContainer.scrollLeft,S=Math.abs(this.viewContainer.scrollTop-v.scrollTop)<=1?void 0:this.viewContainer.scrollTop;(w!==void 0||S!==void 0)&&this.scrollableElement.setScrollPosition({scrollLeft:w,scrollTop:S})})),this.onDidScroll=this.scrollableElement.onScroll,this._register(this.onDidScroll(h=>{h.scrollTopChanged&&(this.viewContainer.scrollTop=h.scrollTop),h.scrollLeftChanged&&(this.viewContainer.scrollLeft=h.scrollLeft)})),(0,d.append)(this.el,this.scrollableElement.getDomNode()),this.style(C.styles||t),C.descriptor&&(this.size=C.descriptor.size,C.descriptor.views.forEach((h,v)=>{const w=o.isUndefined(h.visible)||h.visible?h.size:{type:"invisible",cachedVisibleSize:h.size},S=h.view;this.doAddView(S,w,v,!0)}),this._contentSize=this.viewItems.reduce((h,v)=>h+v.size,0),this.saveProportions())}style(u){u.separatorBorder.isTransparent()?(this.el.classList.remove("separator-border"),this.el.style.removeProperty("--separator-border")):(this.el.classList.add("separator-border"),this.el.style.setProperty("--separator-border",u.separatorBorder.toString()))}addView(u,C,f=this.viewItems.length,h){this.doAddView(u,C,f,h)}layout(u,C){const f=Math.max(this.size,this._contentSize);if(this.size=u,this.layoutContext=C,this.proportions){let h=0;for(let v=0;v0&&(w.size=(0,p.clamp)(Math.round(S*u/h),w.minimumSize,w.maximumSize))}}else{const h=(0,y.range)(this.viewItems.length),v=h.filter(S=>this.viewItems[S].priority===1),w=h.filter(S=>this.viewItems[S].priority===2);this.resize(this.viewItems.length-1,u-f,void 0,v,w)}this.distributeEmptySpace(),this.layoutViews()}saveProportions(){this.proportionalLayout&&this._contentSize>0&&(this.proportions=this.viewItems.map(u=>u.proportionalLayout&&u.visible?u.size/this._contentSize:void 0))}onSashStart({sash:u,start:C,alt:f}){for(const S of this.viewItems)S.enabled=!1;const h=this.sashItems.findIndex(S=>S.sash===u),v=(0,b.combinedDisposable)((0,d.addDisposableListener)(this.el.ownerDocument.body,"keydown",S=>w(this.sashDragState.current,S.altKey)),(0,d.addDisposableListener)(this.el.ownerDocument.body,"keyup",()=>w(this.sashDragState.current,!1))),w=(S,L)=>{const D=this.viewItems.map(N=>N.size);let T=Number.NEGATIVE_INFINITY,M=Number.POSITIVE_INFINITY;if(this.inverseAltBehavior&&(L=!L),L)if(h===this.sashItems.length-1){const O=this.viewItems[h];T=(O.minimumSize-O.size)/2,M=(O.maximumSize-O.size)/2}else{const O=this.viewItems[h+1];T=(O.size-O.maximumSize)/2,M=(O.size-O.minimumSize)/2}let A,P;if(!L){const N=(0,y.range)(h,-1),O=(0,y.range)(h+1,this.viewItems.length),F=N.reduce((j,Y)=>j+(this.viewItems[Y].minimumSize-D[Y]),0),x=N.reduce((j,Y)=>j+(this.viewItems[Y].viewMaximumSize-D[Y]),0),W=O.length===0?Number.POSITIVE_INFINITY:O.reduce((j,Y)=>j+(D[Y]-this.viewItems[Y].minimumSize),0),V=O.length===0?Number.NEGATIVE_INFINITY:O.reduce((j,Y)=>j+(D[Y]-this.viewItems[Y].viewMaximumSize),0),q=Math.max(F,V),H=Math.min(W,x),z=this.findFirstSnapIndex(N),U=this.findFirstSnapIndex(O);if(typeof z=="number"){const j=this.viewItems[z],Y=Math.floor(j.viewMinimumSize/2);A={index:z,limitDelta:j.visible?q-Y:q+Y,size:j.size}}if(typeof U=="number"){const j=this.viewItems[U],Y=Math.floor(j.viewMinimumSize/2);P={index:U,limitDelta:j.visible?H+Y:H-Y,size:j.size}}}this.sashDragState={start:S,current:S,index:h,sizes:D,minDelta:T,maxDelta:M,alt:L,snapBefore:A,snapAfter:P,disposable:v}};w(C,f)}onSashChange({current:u}){const{index:C,start:f,sizes:h,alt:v,minDelta:w,maxDelta:S,snapBefore:L,snapAfter:D}=this.sashDragState;this.sashDragState.current=u;const T=u-f,M=this.resize(C,T,h,void 0,void 0,w,S,L,D);if(v){const A=C===this.sashItems.length-1,P=this.viewItems.map(V=>V.size),N=A?C:C+1,O=this.viewItems[N],F=O.size-O.maximumSize,x=O.size-O.minimumSize,W=A?C-1:C+1;this.resize(W,-M,P,void 0,void 0,F,x)}this.distributeEmptySpace(),this.layoutViews()}onSashEnd(u){this._onDidSashChange.fire(u),this.sashDragState.disposable.dispose(),this.saveProportions();for(const C of this.viewItems)C.enabled=!0}onViewChange(u,C){const f=this.viewItems.indexOf(u);f<0||f>=this.viewItems.length||(C=typeof C=="number"?C:u.size,C=(0,p.clamp)(C,u.minimumSize,u.maximumSize),this.inverseAltBehavior&&f>0?(this.resize(f-1,Math.floor((u.size-C)/2)),this.distributeEmptySpace(),this.layoutViews()):(u.size=C,this.relayout([f],void 0)))}resizeView(u,C){if(!(u<0||u>=this.viewItems.length)){if(this.state!==c.Idle)throw new Error("Cant modify splitview");this.state=c.Busy;try{const f=(0,y.range)(this.viewItems.length).filter(S=>S!==u),h=[...f.filter(S=>this.viewItems[S].priority===1),u],v=f.filter(S=>this.viewItems[S].priority===2),w=this.viewItems[u];C=Math.round(C),C=(0,p.clamp)(C,w.minimumSize,Math.min(w.maximumSize,this.size)),w.size=C,this.relayout(h,v)}finally{this.state=c.Idle}}}distributeViewSizes(){const u=[];let C=0;for(const S of this.viewItems)S.maximumSize-S.minimumSize>0&&(u.push(S),C+=S.size);const f=Math.floor(C/u.length);for(const S of u)S.size=(0,p.clamp)(f,S.minimumSize,S.maximumSize);const h=(0,y.range)(this.viewItems.length),v=h.filter(S=>this.viewItems[S].priority===1),w=h.filter(S=>this.viewItems[S].priority===2);this.relayout(v,w)}getViewSize(u){return u<0||u>=this.viewItems.length?-1:this.viewItems[u].size}doAddView(u,C,f=this.viewItems.length,h){if(this.state!==c.Idle)throw new Error("Cant modify splitview");this.state=c.Busy;try{const v=(0,d.$)(".split-view-view");f===this.viewItems.length?this.viewContainer.appendChild(v):this.viewContainer.insertBefore(v,this.viewContainer.children.item(f));const w=u.onDidChange(A=>this.onViewChange(T,A)),S=(0,b.toDisposable)(()=>v.remove()),L=(0,b.combinedDisposable)(w,S);let D;typeof C=="number"?D=C:(C.type==="auto"&&(this.areViewsDistributed()?C={type:"distribute"}:C={type:"split",index:C.index}),C.type==="split"?D=this.getViewSize(C.index)/2:C.type==="invisible"?D={cachedVisibleSize:C.cachedVisibleSize}:D=u.minimumSize);const T=this.orientation===0?new s(v,u,D,L):new g(v,u,D,L);if(this.viewItems.splice(f,0,T),this.viewItems.length>1){const A={orthogonalStartSash:this.orthogonalStartSash,orthogonalEndSash:this.orthogonalEndSash},P=this.orientation===0?new I.Sash(this.sashContainer,{getHorizontalSashTop:j=>this.getSashPosition(j),getHorizontalSashWidth:this.getSashOrthogonalSize},{...A,orientation:1}):new I.Sash(this.sashContainer,{getVerticalSashLeft:j=>this.getSashPosition(j),getVerticalSashHeight:this.getSashOrthogonalSize},{...A,orientation:0}),N=this.orientation===0?j=>({sash:P,start:j.startY,current:j.currentY,alt:j.altKey}):j=>({sash:P,start:j.startX,current:j.currentX,alt:j.altKey}),F=_.Event.map(P.onDidStart,N)(this.onSashStart,this),W=_.Event.map(P.onDidChange,N)(this.onSashChange,this),q=_.Event.map(P.onDidEnd,()=>this.sashItems.findIndex(j=>j.sash===P))(this.onSashEnd,this),H=P.onDidReset(()=>{const j=this.sashItems.findIndex(J=>J.sash===P),Y=(0,y.range)(j,-1),G=(0,y.range)(j+1,this.viewItems.length),K=this.findFirstSnapIndex(Y),R=this.findFirstSnapIndex(G);typeof K=="number"&&!this.viewItems[K].visible||typeof R=="number"&&!this.viewItems[R].visible||this._onDidSashReset.fire(j)}),z=(0,b.combinedDisposable)(F,W,q,H,P),U={sash:P,disposable:z};this.sashItems.splice(f-1,0,U)}v.appendChild(u.element);let M;typeof C!="number"&&C.type==="split"&&(M=[C.index]),h||this.relayout([f],M),!h&&typeof C!="number"&&C.type==="distribute"&&this.distributeViewSizes()}finally{this.state=c.Idle}}relayout(u,C){const f=this.viewItems.reduce((h,v)=>h+v.size,0);this.resize(this.viewItems.length-1,this.size-f,void 0,u,C),this.distributeEmptySpace(),this.layoutViews(),this.saveProportions()}resize(u,C,f=this.viewItems.map(T=>T.size),h,v,w=Number.NEGATIVE_INFINITY,S=Number.POSITIVE_INFINITY,L,D){if(u<0||u>=this.viewItems.length)return 0;const T=(0,y.range)(u,-1),M=(0,y.range)(u+1,this.viewItems.length);if(v)for(const U of v)(0,y.pushToStart)(T,U),(0,y.pushToStart)(M,U);if(h)for(const U of h)(0,y.pushToEnd)(T,U),(0,y.pushToEnd)(M,U);const A=T.map(U=>this.viewItems[U]),P=T.map(U=>f[U]),N=M.map(U=>this.viewItems[U]),O=M.map(U=>f[U]),F=T.reduce((U,j)=>U+(this.viewItems[j].minimumSize-f[j]),0),x=T.reduce((U,j)=>U+(this.viewItems[j].maximumSize-f[j]),0),W=M.length===0?Number.POSITIVE_INFINITY:M.reduce((U,j)=>U+(f[j]-this.viewItems[j].minimumSize),0),V=M.length===0?Number.NEGATIVE_INFINITY:M.reduce((U,j)=>U+(f[j]-this.viewItems[j].maximumSize),0),q=Math.max(F,V,w),H=Math.min(W,x,S);let z=!1;if(L){const U=this.viewItems[L.index],j=C>=L.limitDelta;z=j!==U.visible,U.setVisible(j,L.size)}if(!z&&D){const U=this.viewItems[D.index],j=CS+L.size,0);let f=this.size-C;const h=(0,y.range)(this.viewItems.length-1,-1),v=h.filter(S=>this.viewItems[S].priority===1),w=h.filter(S=>this.viewItems[S].priority===2);for(const S of w)(0,y.pushToStart)(h,S);for(const S of v)(0,y.pushToEnd)(h,S);typeof u=="number"&&(0,y.pushToEnd)(h,u);for(let S=0;f!==0&&SC+f.size,0);let u=0;for(const C of this.viewItems)C.layout(u,this.layoutContext),u+=C.size;this.sashItems.forEach(C=>C.sash.layout()),this.updateSashEnablement(),this.updateScrollableElement()}updateScrollableElement(){this.orientation===0?this.scrollableElement.setScrollDimensions({height:this.size,scrollHeight:this._contentSize}):this.scrollableElement.setScrollDimensions({width:this.size,scrollWidth:this._contentSize})}updateSashEnablement(){let u=!1;const C=this.viewItems.map(L=>u=L.size-L.minimumSize>0||u);u=!1;const f=this.viewItems.map(L=>u=L.maximumSize-L.size>0||u),h=[...this.viewItems].reverse();u=!1;const v=h.map(L=>u=L.size-L.minimumSize>0||u).reverse();u=!1;const w=h.map(L=>u=L.maximumSize-L.size>0||u).reverse();let S=0;for(let L=0;L0||this.startSnappingEnabled)?D.state=1:W&&C[L]&&(S0)return;if(!f.visible&&f.snap)return C}}areViewsDistributed(){let u,C;for(const f of this.viewItems)if(u=u===void 0?f.size:Math.min(u,f.size),C=C===void 0?f.size:Math.max(C,f.size),C-u>2)return!1;return!0}dispose(){this.sashDragState?.disposable.dispose(),(0,b.dispose)(this.viewItems),this.viewItems=[],this.sashItems.forEach(u=>u.disposable.dispose()),this.sashItems=[],super.dispose()}}e.SplitView=a}),define(ne[638],se([1,0,5,81,44,115,357,6,2,475]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Table=void 0;class b{static{this.TemplateId="row"}constructor(i,s,g){this.columns=i,this.getColumnSize=g,this.templateId=b.TemplateId,this.renderedTemplates=new Set;const c=new Map(s.map(l=>[l.templateId,l]));this.renderers=[];for(const l of i){const a=c.get(l.templateId);if(!a)throw new Error(`Table cell renderer for template id ${l.templateId} not found.`);this.renderers.push(a)}}renderTemplate(i){const s=(0,d.append)(i,(0,d.$)(".monaco-table-tr")),g=[],c=[];for(let a=0;athis.disposables.add(new n(f,h))),u={size:r.reduce((f,h)=>f+h.column.weight,0),views:r.map(f=>({size:f.column.weight,view:f}))};this.splitview=this.disposables.add(new y.SplitView(this.domNode,{orientation:1,scrollbarVisibility:2,getSashOrthogonalSize:()=>this.cachedHeight,descriptor:u})),this.splitview.el.style.height=`${g.headerRowHeight}px`,this.splitview.el.style.lineHeight=`${g.headerRowHeight}px`;const C=new b(c,l,f=>this.splitview.getViewSize(f));this.list=this.disposables.add(new E.List(i,this.domNode,p(g),[C],a)),m.Event.any(...r.map(f=>f.onDidLayout))(([f,h])=>C.layoutColumn(f,h),null,this.disposables),this.splitview.onDidSashReset(f=>{const h=c.reduce((w,S)=>w+S.weight,0),v=c[f].weight/h*this.cachedWidth;this.splitview.resizeView(f,v)},null,this.disposables),this.styleElement=(0,d.createStyleSheet)(this.domNode),this.style(E.unthemedListStyles)}updateOptions(i){this.list.updateOptions(i)}splice(i,s,g=[]){this.list.splice(i,s,g)}getHTMLElement(){return this.domNode}style(i){const s=[];s.push(`.monaco-table.${this.domId} > .monaco-split-view2 .monaco-sash.vertical::before { top: ${this.virtualDelegate.headerRowHeight+1}px; height: calc(100% - ${this.virtualDelegate.headerRowHeight}px); }`),this.styleElement.textContent=s.join(` `),this.list.style(i)}getSelectedElements(){return this.list.getSelectedElements()}getSelection(){return this.list.getSelection()}getFocus(){return this.list.getFocus()}dispose(){this.disposables.dispose()}}e.Table=o}),define(ne[175],se([1,0,85,30,6,44,81,476]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Toggle=e.unthemedToggleStyles=void 0,e.unthemedToggleStyles={inputActiveOptionBorder:"#007ACC00",inputActiveOptionForeground:"#FFFFFF",inputActiveOptionBackground:"#0E639C50"};class m extends d.Widget{constructor(b){super(),this._onChange=this._register(new I.Emitter),this.onChange=this._onChange.event,this._onKeyDown=this._register(new I.Emitter),this.onKeyDown=this._onKeyDown.event,this._opts=b,this._checked=this._opts.isChecked;const p=["monaco-custom-toggle"];this._opts.icon&&(this._icon=this._opts.icon,p.push(...k.ThemeIcon.asClassNameArray(this._icon))),this._opts.actionClassName&&p.push(...this._opts.actionClassName.split(" ")),this._checked&&p.push("checked"),this.domNode=document.createElement("div"),this._hover=this._register((0,y.getBaseLayerHoverDelegate)().setupManagedHover(b.hoverDelegate??(0,E.getDefaultHoverDelegate)("mouse"),this.domNode,this._opts.title)),this.domNode.classList.add(...p),this._opts.notFocusable||(this.domNode.tabIndex=0),this.domNode.setAttribute("role","checkbox"),this.domNode.setAttribute("aria-checked",String(this._checked)),this.domNode.setAttribute("aria-label",this._opts.title),this.applyStyles(),this.onclick(this.domNode,n=>{this.enabled&&(this.checked=!this._checked,this._onChange.fire(!1),n.preventDefault())}),this._register(this.ignoreGesture(this.domNode)),this.onkeydown(this.domNode,n=>{if(n.keyCode===10||n.keyCode===3){this.checked=!this._checked,this._onChange.fire(!0),n.preventDefault(),n.stopPropagation();return}this._onKeyDown.fire(n)})}get enabled(){return this.domNode.getAttribute("aria-disabled")!=="true"}focus(){this.domNode.focus()}get checked(){return this._checked}set checked(b){this._checked=b,this.domNode.setAttribute("aria-checked",String(this._checked)),this.domNode.classList.toggle("checked",this._checked),this.applyStyles()}width(){return 22}applyStyles(){this.domNode&&(this.domNode.style.borderColor=this._checked&&this._opts.inputActiveOptionBorder||"",this.domNode.style.color=this._checked&&this._opts.inputActiveOptionForeground||"inherit",this.domNode.style.backgroundColor=this._checked&&this._opts.inputActiveOptionBackground||"")}enable(){this.domNode.setAttribute("aria-disabled",String(!1))}disable(){this.domNode.setAttribute("aria-disabled",String(!0))}}e.Toggle=m}),define(ne[358],se([1,0,44,175,26,3]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RegexToggle=e.WholeWordsToggle=e.CaseSensitiveToggle=void 0;const y=E.localize(2,"Match Case"),m=E.localize(3,"Match Whole Word"),_=E.localize(4,"Use Regular Expression");class b extends k.Toggle{constructor(t){super({icon:I.Codicon.caseSensitive,title:y+t.appendTitle,isChecked:t.isChecked,hoverDelegate:t.hoverDelegate??(0,d.getDefaultHoverDelegate)("element"),inputActiveOptionBorder:t.inputActiveOptionBorder,inputActiveOptionForeground:t.inputActiveOptionForeground,inputActiveOptionBackground:t.inputActiveOptionBackground})}}e.CaseSensitiveToggle=b;class p extends k.Toggle{constructor(t){super({icon:I.Codicon.wholeWord,title:m+t.appendTitle,isChecked:t.isChecked,hoverDelegate:t.hoverDelegate??(0,d.getDefaultHoverDelegate)("element"),inputActiveOptionBorder:t.inputActiveOptionBorder,inputActiveOptionForeground:t.inputActiveOptionForeground,inputActiveOptionBackground:t.inputActiveOptionBackground})}}e.WholeWordsToggle=p;class n extends k.Toggle{constructor(t){super({icon:I.Codicon.regex,title:_+t.appendTitle,isChecked:t.isChecked,hoverDelegate:t.hoverDelegate??(0,d.getDefaultHoverDelegate)("element"),inputActiveOptionBorder:t.inputActiveOptionBorder,inputActiveOptionForeground:t.inputActiveOptionForeground,inputActiveOptionBackground:t.inputActiveOptionBackground})}}e.RegexToggle=n}),define(ne[48],se([1,0,251,42,99,16,11,22]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DataUri=e.addTrailingPathSeparator=e.removeTrailingPathSeparator=e.hasTrailingPathSeparator=e.isEqualAuthority=e.isAbsolutePath=e.resolvePath=e.relativePath=e.normalizePath=e.joinPath=e.dirname=e.extname=e.basename=e.basenameOrAuthority=e.getComparisonKey=e.isEqualOrParent=e.isEqual=e.extUriIgnorePathCase=e.extUriBiasedIgnorePathCase=e.extUri=e.ExtUri=void 0,e.originalFSPath=_;function _(n){return(0,m.uriToFsPath)(n,!0)}class b{constructor(o){this._ignorePathCasing=o}compare(o,t,i=!1){return o===t?0:(0,y.compare)(this.getComparisonKey(o,i),this.getComparisonKey(t,i))}isEqual(o,t,i=!1){return o===t?!0:!o||!t?!1:this.getComparisonKey(o,i)===this.getComparisonKey(t,i)}getComparisonKey(o,t=!1){return o.with({path:this._ignorePathCasing(o)?o.path.toLowerCase():void 0,fragment:t?null:void 0}).toString()}isEqualOrParent(o,t,i=!1){if(o.scheme===t.scheme){if(o.scheme===k.Schemas.file)return d.isEqualOrParent(_(o),_(t),this._ignorePathCasing(o))&&o.query===t.query&&(i||o.fragment===t.fragment);if((0,e.isEqualAuthority)(o.authority,t.authority))return d.isEqualOrParent(o.path,t.path,this._ignorePathCasing(o),"/")&&o.query===t.query&&(i||o.fragment===t.fragment)}return!1}joinPath(o,...t){return m.URI.joinPath(o,...t)}basenameOrAuthority(o){return(0,e.basename)(o)||o.authority}basename(o){return I.posix.basename(o.path)}extname(o){return I.posix.extname(o.path)}dirname(o){if(o.path.length===0)return o;let t;return o.scheme===k.Schemas.file?t=m.URI.file(I.dirname(_(o))).path:(t=I.posix.dirname(o.path),o.authority&&t.length&&t.charCodeAt(0)!==47&&(console.error(`dirname("${o.toString})) resulted in a relative path`),t="/")),o.with({path:t})}normalizePath(o){if(!o.path.length)return o;let t;return o.scheme===k.Schemas.file?t=m.URI.file(I.normalize(_(o))).path:t=I.posix.normalize(o.path),o.with({path:t})}relativePath(o,t){if(o.scheme!==t.scheme||!(0,e.isEqualAuthority)(o.authority,t.authority))return;if(o.scheme===k.Schemas.file){const g=I.relative(_(o),_(t));return E.isWindows?d.toSlashes(g):g}let i=o.path||"/";const s=t.path||"/";if(this._ignorePathCasing(o)){let g=0;for(const c=Math.min(i.length,s.length);gd.getRoot(i).length&&i[i.length-1]===t}else{const i=o.path;return i.length>1&&i.charCodeAt(i.length-1)===47&&!/^[a-zA-Z]:(\/$|\\$)/.test(o.fsPath)}}removeTrailingPathSeparator(o,t=I.sep){return(0,e.hasTrailingPathSeparator)(o,t)?o.with({path:o.path.substr(0,o.path.length-1)}):o}addTrailingPathSeparator(o,t=I.sep){let i=!1;if(o.scheme===k.Schemas.file){const s=_(o);i=s!==void 0&&s.length===d.getRoot(s).length&&s[s.length-1]===t}else{t="/";const s=o.path;i=s.length===1&&s.charCodeAt(s.length-1)===47}return!i&&!(0,e.hasTrailingPathSeparator)(o,t)?o.with({path:o.path+"/"}):o}}e.ExtUri=b,e.extUri=new b(()=>!1),e.extUriBiasedIgnorePathCase=new b(n=>n.scheme===k.Schemas.file?!E.isLinux:!0),e.extUriIgnorePathCase=new b(n=>!0),e.isEqual=e.extUri.isEqual.bind(e.extUri),e.isEqualOrParent=e.extUri.isEqualOrParent.bind(e.extUri),e.getComparisonKey=e.extUri.getComparisonKey.bind(e.extUri),e.basenameOrAuthority=e.extUri.basenameOrAuthority.bind(e.extUri),e.basename=e.extUri.basename.bind(e.extUri),e.extname=e.extUri.extname.bind(e.extUri),e.dirname=e.extUri.dirname.bind(e.extUri),e.joinPath=e.extUri.joinPath.bind(e.extUri),e.normalizePath=e.extUri.normalizePath.bind(e.extUri),e.relativePath=e.extUri.relativePath.bind(e.extUri),e.resolvePath=e.extUri.resolvePath.bind(e.extUri),e.isAbsolutePath=e.extUri.isAbsolutePath.bind(e.extUri),e.isEqualAuthority=e.extUri.isEqualAuthority.bind(e.extUri),e.hasTrailingPathSeparator=e.extUri.hasTrailingPathSeparator.bind(e.extUri),e.removeTrailingPathSeparator=e.extUri.removeTrailingPathSeparator.bind(e.extUri),e.addTrailingPathSeparator=e.extUri.addTrailingPathSeparator.bind(e.extUri);var p;(function(n){n.META_DATA_LABEL="label",n.META_DATA_DESCRIPTION="description",n.META_DATA_SIZE="size",n.META_DATA_MIME="mime";function o(t){const i=new Map;t.path.substring(t.path.indexOf(";")+1,t.path.lastIndexOf(";")).split(";").forEach(c=>{const[l,a]=c.split(":");l&&a&&i.set(l,a)});const g=t.path.substring(0,t.path.indexOf(";"));return g&&i.set(n.META_DATA_MIME,g),i}n.parseMetaData=o})(p||(e.DataUri=p={}))}),define(ne[57],se([1,0,8,142,48,11,22]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MarkdownString=void 0,e.isEmptyMarkdownString=_,e.isMarkdownString=b,e.markdownStringEqual=p,e.escapeMarkdownSyntaxTokens=n,e.appendEscapedMarkdownCodeBlockFence=o,e.escapeDoubleQuotes=t,e.removeMarkdownEscapes=i,e.parseHrefAndDimensions=s;class m{constructor(c="",l=!1){if(this.value=c,typeof this.value!="string")throw(0,d.illegalArgument)("value");typeof l=="boolean"?(this.isTrusted=l,this.supportThemeIcons=!1,this.supportHtml=!1):(this.isTrusted=l.isTrusted??void 0,this.supportThemeIcons=l.supportThemeIcons??!1,this.supportHtml=l.supportHtml??!1)}appendText(c,l=0){return this.value+=n(this.supportThemeIcons?(0,k.escapeIcons)(c):c).replace(/([ \t]+)/g,(a,r)=>" ".repeat(r.length)).replace(/\>/gm,"\\>").replace(/\n/g,l===1?`\\ `:` `),this}appendMarkdown(c){return this.value+=c,this}appendCodeblock(c,l){return this.value+=` ${o(l,c)} `,this}appendLink(c,l,a){return this.value+="[",this.value+=this._escape(l,"]"),this.value+="](",this.value+=this._escape(String(c),")"),a&&(this.value+=` "${this._escape(this._escape(a,'"'),")")}"`),this.value+=")",this}_escape(c,l){const a=new RegExp((0,E.escapeRegExpCharacters)(l),"g");return c.replace(a,(r,u)=>c.charAt(u-1)!=="\\"?`\\${r}`:r)}}e.MarkdownString=m;function _(g){return b(g)?!g.value:Array.isArray(g)?g.every(_):!0}function b(g){return g instanceof m?!0:g&&typeof g=="object"?typeof g.value=="string"&&(typeof g.isTrusted=="boolean"||typeof g.isTrusted=="object"||g.isTrusted===void 0)&&(typeof g.supportThemeIcons=="boolean"||g.supportThemeIcons===void 0):!1}function p(g,c){return g===c?!0:!g||!c?!1:g.value===c.value&&g.isTrusted===c.isTrusted&&g.supportThemeIcons===c.supportThemeIcons&&g.supportHtml===c.supportHtml&&(g.baseUri===c.baseUri||!!g.baseUri&&!!c.baseUri&&(0,I.isEqual)(y.URI.from(g.baseUri),y.URI.from(c.baseUri)))}function n(g){return g.replace(/[\\`*_{}[\]()#+\-!~]/g,"\\$&")}function o(g,c){const l=g.match(/^`+/gm)?.reduce((r,u)=>r.length>u.length?r:u).length??0,a=l>=3?l+1:3;return[`${"`".repeat(a)}${c}`,g,`${"`".repeat(a)}`].join(` `)}function t(g){return g.replace(/"/g,""")}function i(g){return g&&g.replace(/\\([\\`*_{}[\]()#+\-.!~])/g,"$1")}function s(g){const c=[],l=g.split("|").map(r=>r.trim());g=l[0];const a=l[1];if(a){const r=/height=(\d+)/.exec(a),u=/width=(\d+)/.exec(a),C=r?r[1]:"",f=u?u[1]:"",h=isFinite(parseInt(f)),v=isFinite(parseInt(C));h&&c.push(`width="${f}"`),v&&c.push(`height="${C}"`)}return{href:g,dimensions:c}}}),define(ne[207],se([1,0,5,351,93,352,47,77,114,8,6,57,142,187,98,2,447,252,42,60,48,11,22]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.allowedMarkdownAttr=void 0,e.renderMarkdown=h,e.renderStringAsPlaintext=T,e.renderMarkdownAsPlaintext=M,e.fillInIncompleteTokens=z;const f=Object.freeze({image:({href:ee,title:de,text:ge})=>{let X=[],B=[];return ee&&({href:ee,dimensions:X}=(0,n.parseHrefAndDimensions)(ee),B.push(`src="${(0,n.escapeDoubleQuotes)(ee)}"`)),ge&&B.push(`alt="${(0,n.escapeDoubleQuotes)(ge)}"`),de&&B.push(`title="${(0,n.escapeDoubleQuotes)(de)}"`),X.length&&(B=B.concat(X)),""},paragraph({tokens:ee}){return`

      ${this.parser.parseInline(ee)}

      `},link({href:ee,title:de,tokens:ge}){let X=this.parser.parseInline(ge);return typeof ee!="string"?"":(ee===X&&(X=(0,n.removeMarkdownEscapes)(X)),de=typeof de=="string"?(0,n.escapeDoubleQuotes)((0,n.removeMarkdownEscapes)(de)):"",ee=(0,n.removeMarkdownEscapes)(ee),ee=ee.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'"),`
      ${X}`)}});function h(ee,de={},ge={}){const X=new s.DisposableStore;let B=!1;const $=(0,E.createElement)(de),Q=function(Ee){let Me;try{Me=(0,c.parse)(decodeURIComponent(Ee))}catch{}return Me?(Me=(0,a.cloneAndChange)(Me,Ae=>{if(ee.uris&&ee.uris[Ae])return C.URI.revive(ee.uris[Ae])}),encodeURIComponent(JSON.stringify(Me))):Ee},Z=function(Ee,Me){const Ae=ee.uris&&ee.uris[Ee];let Ne=C.URI.revive(Ae);return Me?Ee.startsWith(l.Schemas.data+":")?Ee:(Ne||(Ne=C.URI.parse(Ee)),l.FileAccess.uriToBrowserUri(Ne).toString(!0)):!Ne||C.URI.parse(Ee).toString()===Ne.toString()?Ee:(Ne.query&&(Ne=Ne.with({query:Q(Ne.query)})),Ne.toString())},te=new g.Renderer;te.image=f.image,te.link=f.link,te.paragraph=f.paragraph;const re=[],le=[];if(de.codeBlockRendererSync?te.code=({text:Ee,lang:Me})=>{const Ae=t.defaultGenerator.nextId(),Ne=de.codeBlockRendererSync(v(Me),Ee);return le.push([Ae,Ne]),`
      ${(0,u.escape)(Ee)}
      `}:de.codeBlockRenderer&&(te.code=({text:Ee,lang:Me})=>{const Ae=t.defaultGenerator.nextId(),Ne=de.codeBlockRenderer(v(Me),Ee);return re.push(Ne.then(Ke=>[Ae,Ke])),`
      ${(0,u.escape)(Ee)}
      `}),de.actionHandler){const Ee=function(Ne){let Ke=Ne.target;if(!(Ke.tagName!=="A"&&(Ke=Ke.parentElement,!Ke||Ke.tagName!=="A")))try{let ze=Ke.dataset.href;ze&&(ee.baseUri&&(ze=w(C.URI.from(ee.baseUri),ze)),de.actionHandler.callback(ze,Ne))}catch(ze){(0,b.onUnexpectedError)(ze)}finally{Ne.preventDefault()}},Me=de.actionHandler.disposables.add(new I.DomEmitter($,"click")),Ae=de.actionHandler.disposables.add(new I.DomEmitter($,"auxclick"));de.actionHandler.disposables.add(p.Event.any(Me.event,Ae.event)(Ne=>{const Ke=new m.StandardMouseEvent(d.getWindow($),Ne);!Ke.leftButton&&!Ke.middleButton||Ee(Ke)})),de.actionHandler.disposables.add(d.addDisposableListener($,"keydown",Ne=>{const Ke=new y.StandardKeyboardEvent(Ne);!Ke.equals(10)&&!Ke.equals(3)||Ee(Ke)}))}ee.supportHtml||(te.html=({text:Ee})=>de.sanitizerOptions?.replaceWithPlaintext?(0,u.escape)(Ee):(ee.isTrusted?Ee.match(/^(]+>)|(<\/\s*span>)$/):void 0)?Ee:""),ge.renderer=te;let me=ee.value??"";me.length>1e5&&(me=`${me.substr(0,1e5)}\u2026`),ee.supportThemeIcons&&(me=(0,o.markdownEscapeEscapedIcons)(me));let Ce;if(de.fillInIncompleteTokens){const Ee={...g.defaults,...ge},Me=g.lexer(me,Ee),Ae=z(Me);Ce=g.parser(Ae,Ee)}else Ce=g.parse(me,{...ge,async:!1});ee.supportThemeIcons&&(Ce=(0,_.renderLabelWithIcons)(Ce).map(Me=>typeof Me=="string"?Me:Me.outerHTML).join(""));const Le=new DOMParser().parseFromString(L({isTrusted:ee.isTrusted,...de.sanitizerOptions},Ce),"text/html");if(Le.body.querySelectorAll("img, audio, video, source").forEach(Ee=>{const Me=Ee.getAttribute("src");if(Me){let Ae=Me;try{ee.baseUri&&(Ae=w(C.URI.from(ee.baseUri),Ae))}catch{}if(Ee.setAttribute("src",Z(Ae,!0)),de.remoteImageIsAllowed){const Ne=C.URI.parse(Ae);Ne.scheme!==l.Schemas.file&&Ne.scheme!==l.Schemas.data&&!de.remoteImageIsAllowed(Ne)&&Ee.replaceWith(d.$("",void 0,Ee.outerHTML))}}}),Le.body.querySelectorAll("a").forEach(Ee=>{const Me=Ee.getAttribute("href");if(Ee.setAttribute("href",""),!Me||/^data:|javascript:/i.test(Me)||/^command:/i.test(Me)&&!ee.isTrusted||/^command:(\/\/\/)?_workbench\.downloadResource/i.test(Me))Ee.replaceWith(...Ee.childNodes);else{let Ae=Z(Me,!1);ee.baseUri&&(Ae=w(C.URI.from(ee.baseUri),Me)),Ee.dataset.href=Ae}}),$.innerHTML=L({isTrusted:ee.isTrusted,...de.sanitizerOptions},Le.body.innerHTML),re.length>0)Promise.all(re).then(Ee=>{if(B)return;const Me=new Map(Ee),Ae=$.querySelectorAll("div[data-code]");for(const Ne of Ae){const Ke=Me.get(Ne.dataset.code??"");Ke&&d.reset(Ne,Ke)}de.asyncRenderCallback?.()});else if(le.length>0){const Ee=new Map(le),Me=$.querySelectorAll("div[data-code]");for(const Ae of Me){const Ne=Ee.get(Ae.dataset.code??"");Ne&&d.reset(Ae,Ne)}}if(de.asyncRenderCallback)for(const Ee of $.getElementsByTagName("img")){const Me=X.add(d.addDisposableListener(Ee,"load",()=>{Me.dispose(),de.asyncRenderCallback()}))}return{element:$,dispose:()=>{B=!0,X.dispose()}}}function v(ee){if(!ee)return"";const de=ee.split(/[\s+|:|,|\{|\?]/,1);return de.length?de[0]:ee}function w(ee,de){return/^\w[\w\d+.-]*:/.test(de)?de:ee.path.endsWith("/")?(0,r.resolvePath)(ee,de).toString():(0,r.resolvePath)((0,r.dirname)(ee),de).toString()}const S=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"];function L(ee,de){const{config:ge,allowedSchemes:X}=D(ee),B=new s.DisposableStore;B.add(ae("uponSanitizeAttribute",($,Q)=>{if(Q.attrName==="style"||Q.attrName==="class"){if($.tagName==="SPAN"){if(Q.attrName==="style"){Q.keepAttr=/^(color\:(#[0-9a-fA-F]+|var\(--vscode(-[a-zA-Z]+)+\));)?(background-color\:(#[0-9a-fA-F]+|var\(--vscode(-[a-zA-Z]+)+\));)?(border-radius:[0-9]+px;)?$/.test(Q.attrValue);return}else if(Q.attrName==="class"){Q.keepAttr=/^codicon codicon-[a-z\-]+( codicon-modifier-[a-z\-]+)?$/.test(Q.attrValue);return}}Q.keepAttr=!1;return}else if($.tagName==="INPUT"&&$.attributes.getNamedItem("type")?.value==="checkbox"){if(Q.attrName==="type"&&Q.attrValue==="checkbox"||Q.attrName==="disabled"||Q.attrName==="checked"){Q.keepAttr=!0;return}Q.keepAttr=!1}})),B.add(ae("uponSanitizeElement",($,Q)=>{if(Q.tagName==="input"&&($.attributes.getNamedItem("type")?.value==="checkbox"?$.setAttribute("disabled",""):ee.replaceWithPlaintext||$.remove()),ee.replaceWithPlaintext&&!Q.allowedTags[Q.tagName]&&Q.tagName!=="body"&&$.parentElement){let Z,te;if(Q.tagName==="#comment")Z=``;else{const Ce=S.includes(Q.tagName),ye=$.attributes.length?" "+Array.from($.attributes).map(Le=>`${Le.name}="${Le.value}"`).join(" "):"";Z=`<${Q.tagName}${ye}>`,Ce||(te=``)}const re=document.createDocumentFragment(),le=$.parentElement.ownerDocument.createTextNode(Z);re.appendChild(le);const me=te?$.parentElement.ownerDocument.createTextNode(te):void 0;for(;$.firstChild;)re.appendChild($.firstChild);me&&re.appendChild(me),$.nodeType===Node.COMMENT_NODE?$.parentElement.insertBefore(re,$):$.parentElement.replaceChild(re,$)}})),B.add(d.hookDomPurifyHrefAndSrcSanitizer(X));try{return k.sanitize(de,{...ge,RETURN_TRUSTED_TYPE:!0})}finally{B.dispose()}}e.allowedMarkdownAttr=["align","autoplay","alt","checked","class","colspan","controls","data-code","data-href","disabled","draggable","height","href","loop","muted","playsinline","poster","rowspan","src","style","target","title","type","width","start"];function D(ee){const de=[l.Schemas.http,l.Schemas.https,l.Schemas.mailto,l.Schemas.data,l.Schemas.file,l.Schemas.vscodeFileResource,l.Schemas.vscodeRemote,l.Schemas.vscodeRemoteResource];return ee.isTrusted&&de.push(l.Schemas.command),{config:{ALLOWED_TAGS:ee.allowedTags??[...d.basicMarkupHtmlTags],ALLOWED_ATTR:e.allowedMarkdownAttr,ALLOW_UNKNOWN_PROTOCOLS:!0},allowedSchemes:de}}function T(ee){return typeof ee=="string"?ee:M(ee)}function M(ee,de){let ge=ee.value??"";ge.length>1e5&&(ge=`${ge.substr(0,1e5)}\u2026`);const X=g.parse(ge,{async:!1,renderer:de?O.value:N.value}).replace(/&(#\d+|[a-zA-Z]+);/g,B=>A.get(B)??B);return L({isTrusted:!1},X).toString()}const A=new Map([[""",'"'],[" "," "],["&","&"],["'","'"],["<","<"],[">",">"]]);function P(){const ee=new g.Renderer;return ee.code=({text:de})=>de,ee.blockquote=({text:de})=>de+` `,ee.html=de=>"",ee.heading=function({tokens:de}){return this.parser.parseInline(de)+` `},ee.hr=()=>"",ee.list=function({items:de}){return de.map(ge=>this.listitem(ge)).join(` `)+` `},ee.listitem=({text:de})=>de+` `,ee.paragraph=function({tokens:de}){return this.parser.parseInline(de)+` `},ee.table=function({header:de,rows:ge}){return de.map(X=>this.tablecell(X)).join(" ")+` `+ge.map(X=>X.map(B=>this.tablecell(B)).join(" ")).join(` `)+` `},ee.tablerow=({text:de})=>de,ee.tablecell=function({tokens:de}){return this.parser.parseInline(de)},ee.strong=({text:de})=>de,ee.em=({text:de})=>de,ee.codespan=({text:de})=>de,ee.br=de=>` `,ee.del=({text:de})=>de,ee.image=de=>"",ee.text=({text:de})=>de,ee.link=({text:de})=>de,ee}const N=new i.Lazy(ee=>P()),O=new i.Lazy(()=>{const ee=P();return ee.code=({text:de})=>` \`\`\` ${de} \`\`\` `,ee});function F(ee){let de="";return ee.forEach(ge=>{de+=ge.raw}),de}function x(ee){if(ee.tokens)for(let de=ee.tokens.length-1;de>=0;de--){const ge=ee.tokens[de];if(ge.type==="text"){const X=ge.raw.split(` `),B=X[X.length-1];if(B.includes("`"))return j(ee);if(B.includes("**"))return ie(ee);if(B.match(/\*\w/))return Y(ee);if(B.match(/(^|\s)__\w/))return ue(ee);if(B.match(/(^|\s)_\w/))return G(ee);if(W(B)||V(B)&&ee.tokens.slice(0,de).some($=>$.type==="text"&&$.raw.match(/\[[^\]]*$/))){const $=ee.tokens.slice(de+1);return $[0]?.type==="link"&&$[1]?.type==="text"&&$[1].raw.match(/^ *"[^"]*$/)||B.match(/^[^"]* +"[^"]*$/)?R(ee):K(ee)}else if(B.match(/(^|\s)\[\w*/))return J(ee)}}}function W(ee){return!!ee.match(/(^|\s)\[.*\]\(\w*/)}function V(ee){return!!ee.match(/^[^\[]*\]\([^\)]*$/)}function q(ee){const de=ee.items[ee.items.length-1],ge=de.tokens?de.tokens[de.tokens.length-1]:void 0;let X;if(ge?.type==="text"&&!("inRawBlock"in de)&&(X=x(ge)),!X||X.type!=="paragraph")return;const B=F(ee.items.slice(0,-1)),$=de.raw.match(/^(\s*(-|\d+\.|\*) +)/)?.[0];if(!$)return;const Q=$+F(de.tokens.slice(0,-1))+X.raw,Z=g.lexer(B+Q)[0];if(Z.type==="list")return Z}const H=3;function z(ee){for(let de=0;de"u"&&Q.match(/^\s*\|/)){const Z=Q.match(/(\|[^\|]+)(?=\||$)/g);Z&&(X=Z.length)}else if(typeof X=="number")if(Q.match(/^\s*\|/)){if($!==ge.length-1)return;B=!0}else return}if(typeof X=="number"&&X>0){const $=B?ge.slice(0,-1).join(` `):de,Q=!!$.match(/\|\s*$/),Z=$+(Q?"":"|")+` |${" --- |".repeat(X)}`;return g.lexer(Z)}}function ae(ee,de){return k.addHook(ee,de),(0,s.toDisposable)(()=>k.removeHook(ee))}}),define(ne[258],se([1,0,5,351,47,207,69,44,114,33,6,57,2,30,81,459]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Button=e.unthemedButtonStyles=void 0,e.unthemedButtonStyles={buttonBackground:"#0E639C",buttonHoverBackground:"#006BB3",buttonSeparator:b.Color.white.toString(),buttonForeground:b.Color.white.toString(),buttonBorder:void 0,buttonSecondaryBackground:void 0,buttonSecondaryForeground:void 0,buttonSecondaryHoverBackground:void 0};class s extends o.Disposable{get onDidClick(){return this._onDidClick.event}constructor(c,l){super(),this._label="",this._onDidClick=this._register(new p.Emitter),this._onDidEscape=this._register(new p.Emitter),this.options=l,this._element=document.createElement("a"),this._element.classList.add("monaco-button"),this._element.tabIndex=0,this._element.setAttribute("role","button"),this._element.classList.toggle("secondary",!!l.secondary);const a=l.secondary?l.buttonSecondaryBackground:l.buttonBackground,r=l.secondary?l.buttonSecondaryForeground:l.buttonForeground;this._element.style.color=r||"",this._element.style.backgroundColor=a||"",l.supportShortLabel&&(this._labelShortElement=document.createElement("div"),this._labelShortElement.classList.add("monaco-button-label-short"),this._element.appendChild(this._labelShortElement),this._labelElement=document.createElement("div"),this._labelElement.classList.add("monaco-button-label"),this._element.appendChild(this._labelElement),this._element.classList.add("monaco-text-button-with-short-label")),typeof l.title=="string"&&this.setTitle(l.title),typeof l.ariaLabel=="string"&&this._element.setAttribute("aria-label",l.ariaLabel),c.appendChild(this._element),this._register(y.Gesture.addTarget(this._element)),[d.EventType.CLICK,y.EventType.Tap].forEach(u=>{this._register((0,d.addDisposableListener)(this._element,u,C=>{if(!this.enabled){d.EventHelper.stop(C);return}this._onDidClick.fire(C)}))}),this._register((0,d.addDisposableListener)(this._element,d.EventType.KEY_DOWN,u=>{const C=new I.StandardKeyboardEvent(u);let f=!1;this.enabled&&(C.equals(3)||C.equals(10))?(this._onDidClick.fire(u),f=!0):C.equals(9)&&(this._onDidEscape.fire(u),this._element.blur(),f=!0),f&&d.EventHelper.stop(C,!0)})),this._register((0,d.addDisposableListener)(this._element,d.EventType.MOUSE_OVER,u=>{this._element.classList.contains("disabled")||this.updateBackground(!0)})),this._register((0,d.addDisposableListener)(this._element,d.EventType.MOUSE_OUT,u=>{this.updateBackground(!1)})),this.focusTracker=this._register((0,d.trackFocus)(this._element)),this._register(this.focusTracker.onDidFocus(()=>{this.enabled&&this.updateBackground(!0)})),this._register(this.focusTracker.onDidBlur(()=>{this.enabled&&this.updateBackground(!1)}))}dispose(){super.dispose(),this._element.remove()}getContentElements(c){const l=[];for(let a of(0,_.renderLabelWithIcons)(c))if(typeof a=="string"){if(a=a.trim(),a==="")continue;const r=document.createElement("span");r.textContent=a,l.push(r)}else l.push(a);return l}updateBackground(c){let l;this.options.secondary?l=c?this.options.buttonSecondaryHoverBackground:this.options.buttonSecondaryBackground:l=c?this.options.buttonHoverBackground:this.options.buttonBackground,l&&(this._element.style.backgroundColor=l)}get element(){return this._element}set label(c){if(this._label===c||(0,n.isMarkdownString)(this._label)&&(0,n.isMarkdownString)(c)&&(0,n.markdownStringEqual)(this._label,c))return;this._element.classList.add("monaco-text-button");const l=this.options.supportShortLabel?this._labelElement:this._element;if((0,n.isMarkdownString)(c)){const r=(0,E.renderMarkdown)(c,{inline:!0});r.dispose();const u=r.element.querySelector("p")?.innerHTML;if(u){const C=(0,k.sanitize)(u,{ADD_TAGS:["b","i","u","code","span"],ALLOWED_ATTR:["class"],RETURN_TRUSTED_TYPE:!0});l.innerHTML=C}else(0,d.reset)(l)}else this.options.supportIcons?(0,d.reset)(l,...this.getContentElements(c)):l.textContent=c;let a="";typeof this.options.title=="string"?a=this.options.title:this.options.title&&(a=(0,E.renderStringAsPlaintext)(c)),this.setTitle(a),typeof this.options.ariaLabel=="string"?this._element.setAttribute("aria-label",this.options.ariaLabel):this.options.ariaLabel&&this._element.setAttribute("aria-label",a),this._label=c}get label(){return this._label}set icon(c){this._element.classList.add(...t.ThemeIcon.asClassNameArray(c))}set enabled(c){c?(this._element.classList.remove("disabled"),this._element.setAttribute("aria-disabled",String(!1)),this._element.tabIndex=0):(this._element.classList.add("disabled"),this._element.setAttribute("aria-disabled",String(!0)))}get enabled(){return!this._element.classList.contains("disabled")}setTitle(c){!this._hover&&c!==""?this._hover=this._register((0,i.getBaseLayerHoverDelegate)().setupManagedHover(this.options.hoverDelegate??(0,m.getDefaultHoverDelegate)("mouse"),this._element,c)):this._hover&&this._hover.update(c)}}e.Button=s}),define(ne[639],se([1,0,5,93,47,207,81,44,115,13,6,72,2,16,3,473]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SelectBoxList=void 0;const s=d.$,g="selectOption.entry.template";class c{get templateId(){return g}renderTemplate(r){const u=Object.create(null);return u.root=r,u.text=d.append(r,s(".option-text")),u.detail=d.append(r,s(".option-detail")),u.decoratorRight=d.append(r,s(".option-decorator-right")),u}renderElement(r,u,C){const f=C,h=r.text,v=r.detail,w=r.decoratorRight,S=r.isDisabled;f.text.textContent=h,f.detail.textContent=v||"",f.decoratorRight.innerText=w||"",S?f.root.classList.add("option-disabled"):f.root.classList.remove("option-disabled")}disposeTemplate(r){}}class l extends o.Disposable{static{this.DEFAULT_DROPDOWN_MINIMUM_BOTTOM_MARGIN=32}static{this.DEFAULT_DROPDOWN_MINIMUM_TOP_MARGIN=2}static{this.DEFAULT_MINIMUM_VISIBLE_OPTIONS=3}constructor(r,u,C,f,h){super(),this.options=[],this._currentSelection=0,this._hasDetails=!1,this._skipLayout=!1,this._sticky=!1,this._isVisible=!1,this.styles=f,this.selectBoxOptions=h||Object.create(null),typeof this.selectBoxOptions.minBottomMargin!="number"?this.selectBoxOptions.minBottomMargin=l.DEFAULT_DROPDOWN_MINIMUM_BOTTOM_MARGIN:this.selectBoxOptions.minBottomMargin<0&&(this.selectBoxOptions.minBottomMargin=0),this.selectElement=document.createElement("select"),this.selectElement.className="monaco-select-box monaco-select-box-dropdown-padding",typeof this.selectBoxOptions.ariaLabel=="string"&&this.selectElement.setAttribute("aria-label",this.selectBoxOptions.ariaLabel),typeof this.selectBoxOptions.ariaDescription=="string"&&this.selectElement.setAttribute("aria-description",this.selectBoxOptions.ariaDescription),this._onDidSelect=new p.Emitter,this._register(this._onDidSelect),this.registerListeners(),this.constructSelectDropDown(C),this.selected=u||0,r&&this.setOptions(r,u),this.initStyleSheet()}setTitle(r){!this._hover&&r?this._hover=this._register((0,y.getBaseLayerHoverDelegate)().setupManagedHover((0,m.getDefaultHoverDelegate)("mouse"),this.selectElement,r)):this._hover&&this._hover.update(r)}getHeight(){return 22}getTemplateId(){return g}constructSelectDropDown(r){this.contextViewProvider=r,this.selectDropDownContainer=d.$(".monaco-select-box-dropdown-container"),this.selectDropDownContainer.classList.add("monaco-select-box-dropdown-padding"),this.selectionDetailsPane=d.append(this.selectDropDownContainer,s(".select-box-details-pane"));const u=d.append(this.selectDropDownContainer,s(".select-box-dropdown-container-width-control")),C=d.append(u,s(".width-control-div"));this.widthControlElement=document.createElement("span"),this.widthControlElement.className="option-text-width-control",d.append(C,this.widthControlElement),this._dropDownPosition=0,this.styleElement=d.createStyleSheet(this.selectDropDownContainer),this.selectDropDownContainer.setAttribute("draggable","true"),this._register(d.addDisposableListener(this.selectDropDownContainer,d.EventType.DRAG_START,f=>{d.EventHelper.stop(f,!0)}))}registerListeners(){this._register(d.addStandardDisposableListener(this.selectElement,"change",u=>{this.selected=u.target.selectedIndex,this._onDidSelect.fire({index:u.target.selectedIndex,selected:u.target.value}),this.options[this.selected]&&this.options[this.selected].text&&this.setTitle(this.options[this.selected].text)})),this._register(d.addDisposableListener(this.selectElement,d.EventType.CLICK,u=>{d.EventHelper.stop(u),this._isVisible?this.hideSelectDropDown(!0):this.showSelectDropDown()})),this._register(d.addDisposableListener(this.selectElement,d.EventType.MOUSE_DOWN,u=>{d.EventHelper.stop(u)}));let r;this._register(d.addDisposableListener(this.selectElement,"touchstart",u=>{r=this._isVisible})),this._register(d.addDisposableListener(this.selectElement,"touchend",u=>{d.EventHelper.stop(u),r?this.hideSelectDropDown(!0):this.showSelectDropDown()})),this._register(d.addDisposableListener(this.selectElement,d.EventType.KEY_DOWN,u=>{const C=new I.StandardKeyboardEvent(u);let f=!1;t.isMacintosh?(C.keyCode===18||C.keyCode===16||C.keyCode===10||C.keyCode===3)&&(f=!0):(C.keyCode===18&&C.altKey||C.keyCode===16&&C.altKey||C.keyCode===10||C.keyCode===3)&&(f=!0),f&&(this.showSelectDropDown(),d.EventHelper.stop(u,!0))}))}get onDidSelect(){return this._onDidSelect.event}setOptions(r,u){b.equals(this.options,r)||(this.options=r,this.selectElement.options.length=0,this._hasDetails=!1,this._cachedMaxDetailsHeight=void 0,this.options.forEach((C,f)=>{this.selectElement.add(this.createOption(C.text,f,C.isDisabled)),typeof C.description=="string"&&(this._hasDetails=!0)})),u!==void 0&&(this.select(u),this._currentSelection=this.selected)}setOptionsList(){this.selectList?.splice(0,this.selectList.length,this.options)}select(r){r>=0&&rthis.options.length-1?this.select(this.options.length-1):this.selected<0&&(this.selected=0),this.selectElement.selectedIndex=this.selected,this.options[this.selected]&&this.options[this.selected].text&&this.setTitle(this.options[this.selected].text)}focus(){this.selectElement&&(this.selectElement.tabIndex=0,this.selectElement.focus())}blur(){this.selectElement&&(this.selectElement.tabIndex=-1,this.selectElement.blur())}setFocusable(r){this.selectElement.tabIndex=r?0:-1}render(r){this.container=r,r.classList.add("select-container"),r.appendChild(this.selectElement),this.styleSelectElement()}initStyleSheet(){const r=[];this.styles.listFocusBackground&&r.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { background-color: ${this.styles.listFocusBackground} !important; }`),this.styles.listFocusForeground&&r.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { color: ${this.styles.listFocusForeground} !important; }`),this.styles.decoratorRightForeground&&r.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.focused) .option-decorator-right { color: ${this.styles.decoratorRightForeground}; }`),this.styles.selectBackground&&this.styles.selectBorder&&this.styles.selectBorder!==this.styles.selectBackground?(r.push(`.monaco-select-box-dropdown-container { border: 1px solid ${this.styles.selectBorder} } `),r.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-top { border-top: 1px solid ${this.styles.selectBorder} } `),r.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-bottom { border-bottom: 1px solid ${this.styles.selectBorder} } `)):this.styles.selectListBorder&&(r.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-top { border-top: 1px solid ${this.styles.selectListBorder} } `),r.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-bottom { border-bottom: 1px solid ${this.styles.selectListBorder} } `)),this.styles.listHoverForeground&&r.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.option-disabled):not(.focused):hover { color: ${this.styles.listHoverForeground} !important; }`),this.styles.listHoverBackground&&r.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.option-disabled):not(.focused):hover { background-color: ${this.styles.listHoverBackground} !important; }`),this.styles.listFocusOutline&&r.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { outline: 1.6px dotted ${this.styles.listFocusOutline} !important; outline-offset: -1.6px !important; }`),this.styles.listHoverOutline&&r.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.option-disabled):not(.focused):hover { outline: 1.6px dashed ${this.styles.listHoverOutline} !important; outline-offset: -1.6px !important; }`),r.push(".monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled.focused { background-color: transparent !important; color: inherit !important; outline: none !important; }"),r.push(".monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: transparent !important; color: inherit !important; outline: none !important; }"),this.styleElement.textContent=r.join(` `)}styleSelectElement(){const r=this.styles.selectBackground??"",u=this.styles.selectForeground??"",C=this.styles.selectBorder??"";this.selectElement.style.backgroundColor=r,this.selectElement.style.color=u,this.selectElement.style.borderColor=C}styleList(){const r=this.styles.selectBackground??"",u=d.asCssValueWithDefault(this.styles.selectListBackground,r);this.selectDropDownListContainer.style.backgroundColor=u,this.selectionDetailsPane.style.backgroundColor=u;const C=this.styles.focusBorder??"";this.selectDropDownContainer.style.outlineColor=C,this.selectDropDownContainer.style.outlineOffset="-1px",this.selectList.style(this.styles)}createOption(r,u,C){const f=document.createElement("option");return f.value=r,f.text=r,f.disabled=!!C,f}showSelectDropDown(){this.selectionDetailsPane.innerText="",!(!this.contextViewProvider||this._isVisible)&&(this.createSelectList(this.selectDropDownContainer),this.setOptionsList(),this.contextViewProvider.showContextView({getAnchor:()=>this.selectElement,render:r=>this.renderSelectDropDown(r,!0),layout:()=>{this.layoutSelectDropDown()},onHide:()=>{this.selectDropDownContainer.classList.remove("visible"),this.selectElement.classList.remove("synthetic-focus")},anchorPosition:this._dropDownPosition},this.selectBoxOptions.optionsAsChildren?this.container:void 0),this._isVisible=!0,this.hideSelectDropDown(!1),this.contextViewProvider.showContextView({getAnchor:()=>this.selectElement,render:r=>this.renderSelectDropDown(r),layout:()=>this.layoutSelectDropDown(),onHide:()=>{this.selectDropDownContainer.classList.remove("visible"),this.selectElement.classList.remove("synthetic-focus")},anchorPosition:this._dropDownPosition},this.selectBoxOptions.optionsAsChildren?this.container:void 0),this._currentSelection=this.selected,this._isVisible=!0,this.selectElement.setAttribute("aria-expanded","true"))}hideSelectDropDown(r){!this.contextViewProvider||!this._isVisible||(this._isVisible=!1,this.selectElement.setAttribute("aria-expanded","false"),r&&this.selectElement.focus(),this.contextViewProvider.hideContextView())}renderSelectDropDown(r,u){return r.appendChild(this.selectDropDownContainer),this.layoutSelectDropDown(u),{dispose:()=>{this.selectDropDownContainer.remove()}}}measureMaxDetailsHeight(){let r=0;return this.options.forEach((u,C)=>{this.updateDetail(C),this.selectionDetailsPane.offsetHeight>r&&(r=this.selectionDetailsPane.offsetHeight)}),r}layoutSelectDropDown(r){if(this._skipLayout)return!1;if(this.selectList){this.selectDropDownContainer.classList.add("visible");const u=d.getWindow(this.selectElement),C=d.getDomNodePagePosition(this.selectElement),f=d.getWindow(this.selectElement).getComputedStyle(this.selectElement),h=parseFloat(f.getPropertyValue("--dropdown-padding-top"))+parseFloat(f.getPropertyValue("--dropdown-padding-bottom")),v=u.innerHeight-C.top-C.height-(this.selectBoxOptions.minBottomMargin||0),w=C.top-l.DEFAULT_DROPDOWN_MINIMUM_TOP_MARGIN,S=this.selectElement.offsetWidth,L=this.setWidthControlElement(this.widthControlElement),D=Math.max(L,Math.round(S)).toString()+"px";this.selectDropDownContainer.style.width=D,this.selectList.getHTMLElement().style.height="",this.selectList.layout();let T=this.selectList.contentHeight;this._hasDetails&&this._cachedMaxDetailsHeight===void 0&&(this._cachedMaxDetailsHeight=this.measureMaxDetailsHeight());const M=this._hasDetails?this._cachedMaxDetailsHeight:0,A=T+h+M,P=Math.floor((v-h-M)/this.getHeight()),N=Math.floor((w-h-M)/this.getHeight());if(r)return C.top+C.height>u.innerHeight-22||C.topP&&this.options.length>P?(this._dropDownPosition=1,this.selectDropDownListContainer.remove(),this.selectionDetailsPane.remove(),this.selectDropDownContainer.appendChild(this.selectionDetailsPane),this.selectDropDownContainer.appendChild(this.selectDropDownListContainer),this.selectionDetailsPane.classList.remove("border-top"),this.selectionDetailsPane.classList.add("border-bottom")):(this._dropDownPosition=0,this.selectDropDownListContainer.remove(),this.selectionDetailsPane.remove(),this.selectDropDownContainer.appendChild(this.selectDropDownListContainer),this.selectDropDownContainer.appendChild(this.selectionDetailsPane),this.selectionDetailsPane.classList.remove("border-bottom"),this.selectionDetailsPane.classList.add("border-top")),!0);if(C.top+C.height>u.innerHeight-22||C.topv&&(T=P*this.getHeight())}else A>w&&(T=N*this.getHeight());return this.selectList.layout(T),this.selectList.domFocus(),this.selectList.length>0&&(this.selectList.setFocus([this.selected||0]),this.selectList.reveal(this.selectList.getFocus()[0]||0)),this._hasDetails?(this.selectList.getHTMLElement().style.height=T+h+"px",this.selectDropDownContainer.style.height=""):this.selectDropDownContainer.style.height=T+h+"px",this.updateDetail(this.selected),this.selectDropDownContainer.style.width=D,this.selectDropDownListContainer.setAttribute("tabindex","0"),this.selectElement.classList.add("synthetic-focus"),this.selectDropDownContainer.classList.add("synthetic-focus"),!0}else return!1}setWidthControlElement(r){let u=0;if(r){let C=0,f=0;this.options.forEach((h,v)=>{const w=h.detail?h.detail.length:0,S=h.decoratorRight?h.decoratorRight.length:0,L=h.text.length+w+S;L>f&&(C=v,f=L)}),r.textContent=this.options[C].text+(this.options[C].decoratorRight?this.options[C].decoratorRight+" ":""),u=d.getTotalWidth(r)}return u}createSelectList(r){if(this.selectList)return;this.selectDropDownListContainer=d.append(r,s(".select-box-dropdown-list-container")),this.listRenderer=new c,this.selectList=this._register(new _.List("SelectBoxCustom",this.selectDropDownListContainer,this,[this.listRenderer],{useShadows:!1,verticalScrollMode:3,keyboardSupport:!1,mouseSupport:!1,accessibilityProvider:{getAriaLabel:f=>{let h=f.text;return f.detail&&(h+=`. ${f.detail}`),f.decoratorRight&&(h+=`. ${f.decoratorRight}`),f.description&&(h+=`. ${f.description}`),h},getWidgetAriaLabel:()=>(0,i.localize)(16,"Select Box"),getRole:()=>t.isMacintosh?"":"option",getWidgetRole:()=>"listbox"}})),this.selectBoxOptions.ariaLabel&&(this.selectList.ariaLabel=this.selectBoxOptions.ariaLabel);const u=this._register(new k.DomEmitter(this.selectDropDownListContainer,"keydown")),C=p.Event.chain(u.event,f=>f.filter(()=>this.selectList.length>0).map(h=>new I.StandardKeyboardEvent(h)));this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===3))(this.onEnter,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===2))(this.onEnter,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===9))(this.onEscape,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===16))(this.onUpArrow,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===18))(this.onDownArrow,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===12))(this.onPageDown,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===11))(this.onPageUp,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===14))(this.onHome,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode===13))(this.onEnd,this)),this._register(p.Event.chain(C,f=>f.filter(h=>h.keyCode>=21&&h.keyCode<=56||h.keyCode>=85&&h.keyCode<=113))(this.onCharacter,this)),this._register(d.addDisposableListener(this.selectList.getHTMLElement(),d.EventType.POINTER_UP,f=>this.onPointerUp(f))),this._register(this.selectList.onMouseOver(f=>typeof f.index<"u"&&this.selectList.setFocus([f.index]))),this._register(this.selectList.onDidChangeFocus(f=>this.onListFocus(f))),this._register(d.addDisposableListener(this.selectDropDownContainer,d.EventType.FOCUS_OUT,f=>{!this._isVisible||d.isAncestor(f.relatedTarget,this.selectDropDownContainer)||this.onListBlur()})),this.selectList.getHTMLElement().setAttribute("aria-label",this.selectBoxOptions.ariaLabel||""),this.selectList.getHTMLElement().setAttribute("aria-expanded","true"),this.styleList()}onPointerUp(r){if(!this.selectList.length)return;d.EventHelper.stop(r);const u=r.target;if(!u||u.classList.contains("slider"))return;const C=u.closest(".monaco-list-row");if(!C)return;const f=Number(C.getAttribute("data-index")),h=C.classList.contains("option-disabled");f>=0&&f{for(let v=0;vthis.selected+2)this.selected+=2;else{if(u)return;this.selected++}this.select(this.selected),this.selectList.setFocus([this.selected]),this.selectList.reveal(this.selectList.getFocus()[0])}}onUpArrow(r){this.selected>0&&(d.EventHelper.stop(r,!0),this.options[this.selected-1].isDisabled&&this.selected>1?this.selected-=2:this.selected--,this.select(this.selected),this.selectList.setFocus([this.selected]),this.selectList.reveal(this.selectList.getFocus()[0]))}onPageUp(r){d.EventHelper.stop(r),this.selectList.focusPreviousPage(),setTimeout(()=>{this.selected=this.selectList.getFocus()[0],this.options[this.selected].isDisabled&&this.selected{this.selected=this.selectList.getFocus()[0],this.options[this.selected].isDisabled&&this.selected>0&&(this.selected--,this.selectList.setFocus([this.selected])),this.selectList.reveal(this.selected),this.select(this.selected)},1)}onHome(r){d.EventHelper.stop(r),!(this.options.length<2)&&(this.selected=0,this.options[this.selected].isDisabled&&this.selected>1&&this.selected++,this.selectList.setFocus([this.selected]),this.selectList.reveal(this.selected),this.select(this.selected))}onEnd(r){d.EventHelper.stop(r),!(this.options.length<2)&&(this.selected=this.options.length-1,this.options[this.selected].isDisabled&&this.selected>1&&this.selected--,this.selectList.setFocus([this.selected]),this.selectList.reveal(this.selected),this.select(this.selected))}onCharacter(r){const u=n.KeyCodeUtils.toString(r.keyCode);let C=-1;for(let f=0;f{this.element&&this.handleActionChangeEvent(u)}))}handleActionChangeEvent(l){l.enabled!==void 0&&this.updateEnabled(),l.checked!==void 0&&this.updateChecked(),l.class!==void 0&&this.updateClass(),l.label!==void 0&&(this.updateLabel(),this.updateTooltip()),l.tooltip!==void 0&&this.updateTooltip()}get actionRunner(){return this._actionRunner||(this._actionRunner=this._register(new _.ActionRunner)),this._actionRunner}set actionRunner(l){this._actionRunner=l}isEnabled(){return this._action.enabled}setActionContext(l){this._context=l}render(l){const a=this.element=l;this._register(E.Gesture.addTarget(l));const r=this.options&&this.options.draggable;r&&(l.draggable=!0,d.isFirefox&&this._register((0,I.addDisposableListener)(l,I.EventType.DRAG_START,u=>u.dataTransfer?.setData(k.DataTransfers.TEXT,this._action.label)))),this._register((0,I.addDisposableListener)(a,E.EventType.Tap,u=>this.onClick(u,!0))),this._register((0,I.addDisposableListener)(a,I.EventType.MOUSE_DOWN,u=>{r||I.EventHelper.stop(u,!0),this._action.enabled&&u.button===0&&a.classList.add("active")})),p.isMacintosh&&this._register((0,I.addDisposableListener)(a,I.EventType.CONTEXT_MENU,u=>{u.button===0&&u.ctrlKey===!0&&this.onClick(u)})),this._register((0,I.addDisposableListener)(a,I.EventType.CLICK,u=>{I.EventHelper.stop(u,!0),this.options&&this.options.isMenu||this.onClick(u)})),this._register((0,I.addDisposableListener)(a,I.EventType.DBLCLICK,u=>{I.EventHelper.stop(u,!0)})),[I.EventType.MOUSE_UP,I.EventType.MOUSE_OUT].forEach(u=>{this._register((0,I.addDisposableListener)(a,u,C=>{I.EventHelper.stop(C),a.classList.remove("active")}))})}onClick(l,a=!1){I.EventHelper.stop(l,!0);const r=n.isUndefinedOrNull(this._context)?this.options?.useEventAsContext?l:{preserveFocus:a}:this._context;this.actionRunner.run(this._action,r)}focus(){this.element&&(this.element.tabIndex=0,this.element.focus(),this.element.classList.add("focused"))}blur(){this.element&&(this.element.blur(),this.element.tabIndex=-1,this.element.classList.remove("focused"))}setFocusable(l){this.element&&(this.element.tabIndex=l?0:-1)}get trapsArrowNavigation(){return!1}updateEnabled(){}updateLabel(){}getClass(){return this.action.class}getTooltip(){return this.action.tooltip}updateTooltip(){if(!this.element)return;const l=this.getTooltip()??"";if(this.updateAriaLabel(),this.options.hoverDelegate?.showNativeHover)this.element.title=l;else if(!this.customHover&&l!==""){const a=this.options.hoverDelegate??(0,y.getDefaultHoverDelegate)("element");this.customHover=this._store.add((0,t.getBaseLayerHoverDelegate)().setupManagedHover(a,this.element,l))}else this.customHover&&this.customHover.update(l)}updateAriaLabel(){if(this.element){const l=this.getTooltip()??"";this.element.setAttribute("aria-label",l)}}updateClass(){}updateChecked(){}dispose(){this.element&&(this.element.remove(),this.element=void 0),this._context=void 0,super.dispose()}}e.BaseActionViewItem=i;class s extends i{constructor(l,a,r){super(l,a,r),this.options=r,this.options.icon=r.icon!==void 0?r.icon:!1,this.options.label=r.label!==void 0?r.label:!0,this.cssClass=""}render(l){super.render(l),n.assertType(this.element);const a=document.createElement("a");if(a.classList.add("action-label"),a.setAttribute("role",this.getDefaultAriaRole()),this.label=a,this.element.appendChild(a),this.options.label&&this.options.keybinding){const r=document.createElement("span");r.classList.add("keybinding"),r.textContent=this.options.keybinding,this.element.appendChild(r)}this.updateClass(),this.updateLabel(),this.updateTooltip(),this.updateEnabled(),this.updateChecked()}getDefaultAriaRole(){return this._action.id===_.Separator.ID?"presentation":this.options.isMenu?"menuitem":this.options.isTabList?"tab":"button"}focus(){this.label&&(this.label.tabIndex=0,this.label.focus())}blur(){this.label&&(this.label.tabIndex=-1)}setFocusable(l){this.label&&(this.label.tabIndex=l?0:-1)}updateLabel(){this.options.label&&this.label&&(this.label.textContent=this.action.label)}getTooltip(){let l=null;return this.action.tooltip?l=this.action.tooltip:!this.options.label&&this.action.label&&this.options.icon&&(l=this.action.label,this.options.keybinding&&(l=o.localize(0,"{0} ({1})",l,this.options.keybinding))),l??void 0}updateClass(){this.cssClass&&this.label&&this.label.classList.remove(...this.cssClass.split(" ")),this.options.icon?(this.cssClass=this.getClass(),this.label&&(this.label.classList.add("codicon"),this.cssClass&&this.label.classList.add(...this.cssClass.split(" "))),this.updateEnabled()):this.label?.classList.remove("codicon")}updateEnabled(){this.action.enabled?(this.label&&(this.label.removeAttribute("aria-disabled"),this.label.classList.remove("disabled")),this.element?.classList.remove("disabled")):(this.label&&(this.label.setAttribute("aria-disabled","true"),this.label.classList.add("disabled")),this.element?.classList.add("disabled"))}updateAriaLabel(){if(this.label){const l=this.getTooltip()??"";this.label.setAttribute("aria-label",l)}}updateChecked(){this.label&&(this.action.checked!==void 0?(this.label.classList.toggle("checked",this.action.checked),this.options.isTabList?this.label.setAttribute("aria-selected",this.action.checked?"true":"false"):(this.label.setAttribute("aria-checked",this.action.checked?"true":"false"),this.label.setAttribute("role","checkbox"))):(this.label.classList.remove("checked"),this.label.removeAttribute(this.options.isTabList?"aria-selected":"aria-checked"),this.label.setAttribute("role",this.getDefaultAriaRole())))}}e.ActionViewItem=s;class g extends i{constructor(l,a,r,u,C,f,h){super(l,a),this.selectBox=new m.SelectBox(r,u,C,f,h),this.selectBox.setFocusable(!1),this._register(this.selectBox),this.registerListeners()}select(l){this.selectBox.select(l)}registerListeners(){this._register(this.selectBox.onDidSelect(l=>this.runAction(l.selected,l.index)))}runAction(l,a){this.actionRunner.run(this._action,this.getActionContext(l,a))}getActionContext(l,a){return l}setFocusable(l){this.selectBox.setFocusable(l)}focus(){this.selectBox?.focus()}blur(){this.selectBox?.blur()}render(l){this.selectBox.render(l)}}e.SelectActionViewItem=g}),define(ne[87],se([1,0,5,47,151,44,41,6,2,19,302]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ActionBar=void 0;class p extends _.Disposable{constructor(o,t={}){super(),this._actionRunnerDisposables=this._register(new _.DisposableStore),this.viewItemDisposables=this._register(new _.DisposableMap),this.triggerKeyDown=!1,this.focusable=!0,this._onDidBlur=this._register(new m.Emitter),this.onDidBlur=this._onDidBlur.event,this._onDidCancel=this._register(new m.Emitter({onWillAddFirstListener:()=>this.cancelHasListener=!0})),this.onDidCancel=this._onDidCancel.event,this.cancelHasListener=!1,this._onDidRun=this._register(new m.Emitter),this.onDidRun=this._onDidRun.event,this._onWillRun=this._register(new m.Emitter),this.onWillRun=this._onWillRun.event,this.options=t,this._context=t.context??null,this._orientation=this.options.orientation??0,this._triggerKeys={keyDown:this.options.triggerKeys?.keyDown??!1,keys:this.options.triggerKeys?.keys??[3,10]},this._hoverDelegate=t.hoverDelegate??this._register((0,E.createInstantHoverDelegate)()),this.options.actionRunner?this._actionRunner=this.options.actionRunner:(this._actionRunner=new y.ActionRunner,this._actionRunnerDisposables.add(this._actionRunner)),this._actionRunnerDisposables.add(this._actionRunner.onDidRun(g=>this._onDidRun.fire(g))),this._actionRunnerDisposables.add(this._actionRunner.onWillRun(g=>this._onWillRun.fire(g))),this.viewItems=[],this.focusedItem=void 0,this.domNode=document.createElement("div"),this.domNode.className="monaco-action-bar";let i,s;switch(this._orientation){case 0:i=[15],s=[17];break;case 1:i=[16],s=[18],this.domNode.className+=" vertical";break}this._register(d.addDisposableListener(this.domNode,d.EventType.KEY_DOWN,g=>{const c=new k.StandardKeyboardEvent(g);let l=!0;const a=typeof this.focusedItem=="number"?this.viewItems[this.focusedItem]:void 0;i&&(c.equals(i[0])||c.equals(i[1]))?l=this.focusPrevious():s&&(c.equals(s[0])||c.equals(s[1]))?l=this.focusNext():c.equals(9)&&this.cancelHasListener?this._onDidCancel.fire():c.equals(14)?l=this.focusFirst():c.equals(13)?l=this.focusLast():c.equals(2)&&a instanceof I.BaseActionViewItem&&a.trapsArrowNavigation?l=this.focusNext(void 0,!0):this.isTriggerKeyEvent(c)?this._triggerKeys.keyDown?this.doTrigger(c):this.triggerKeyDown=!0:l=!1,l&&(c.preventDefault(),c.stopPropagation())})),this._register(d.addDisposableListener(this.domNode,d.EventType.KEY_UP,g=>{const c=new k.StandardKeyboardEvent(g);this.isTriggerKeyEvent(c)?(!this._triggerKeys.keyDown&&this.triggerKeyDown&&(this.triggerKeyDown=!1,this.doTrigger(c)),c.preventDefault(),c.stopPropagation()):(c.equals(2)||c.equals(1026)||c.equals(16)||c.equals(18)||c.equals(15)||c.equals(17))&&this.updateFocusedItem()})),this.focusTracker=this._register(d.trackFocus(this.domNode)),this._register(this.focusTracker.onDidBlur(()=>{(d.getActiveElement()===this.domNode||!d.isAncestor(d.getActiveElement(),this.domNode))&&(this._onDidBlur.fire(),this.previouslyFocusedItem=this.focusedItem,this.focusedItem=void 0,this.triggerKeyDown=!1)})),this._register(this.focusTracker.onDidFocus(()=>this.updateFocusedItem())),this.actionsList=document.createElement("ul"),this.actionsList.className="actions-container",this.options.highlightToggledItems&&this.actionsList.classList.add("highlight-toggled"),this.actionsList.setAttribute("role",this.options.ariaRole||"toolbar"),this.options.ariaLabel&&this.actionsList.setAttribute("aria-label",this.options.ariaLabel),this.domNode.appendChild(this.actionsList),o.appendChild(this.domNode)}refreshRole(){this.length()>=1?this.actionsList.setAttribute("role",this.options.ariaRole||"toolbar"):this.actionsList.setAttribute("role","presentation")}setFocusable(o){if(this.focusable=o,this.focusable){const t=this.viewItems.find(i=>i instanceof I.BaseActionViewItem&&i.isEnabled());t instanceof I.BaseActionViewItem&&t.setFocusable(!0)}else this.viewItems.forEach(t=>{t instanceof I.BaseActionViewItem&&t.setFocusable(!1)})}isTriggerKeyEvent(o){let t=!1;return this._triggerKeys.keys.forEach(i=>{t=t||o.equals(i)}),t}updateFocusedItem(){for(let o=0;ot.setActionContext(o))}get actionRunner(){return this._actionRunner}set actionRunner(o){this._actionRunner=o,this._actionRunnerDisposables.clear(),this._actionRunnerDisposables.add(this._actionRunner.onDidRun(t=>this._onDidRun.fire(t))),this._actionRunnerDisposables.add(this._actionRunner.onWillRun(t=>this._onWillRun.fire(t))),this.viewItems.forEach(t=>t.actionRunner=o)}getContainer(){return this.domNode}getAction(o){if(typeof o=="number")return this.viewItems[o]?.action;if(d.isHTMLElement(o)){for(;o.parentElement!==this.actionsList;){if(!o.parentElement)return;o=o.parentElement}for(let t=0;t{const c=document.createElement("li");c.className="action-item",c.setAttribute("role","presentation");let l;const a={hoverDelegate:this._hoverDelegate,...t,isTabList:this.options.ariaRole==="tablist"};this.options.actionViewItemProvider&&(l=this.options.actionViewItemProvider(g,a)),l||(l=new I.ActionViewItem(this.context,g,a)),this.options.allowContextMenu||this.viewItemDisposables.set(l,d.addDisposableListener(c,d.EventType.CONTEXT_MENU,r=>{d.EventHelper.stop(r,!0)})),l.actionRunner=this._actionRunner,l.setActionContext(this.context),l.render(c),this.focusable&&l instanceof I.BaseActionViewItem&&this.viewItems.length===0&&l.setFocusable(!0),s===null||s<0||s>=this.actionsList.children.length?(this.actionsList.appendChild(c),this.viewItems.push(l)):(this.actionsList.insertBefore(c,this.actionsList.children[s]),this.viewItems.splice(s,0,l),s++)}),typeof this.focusedItem=="number"&&this.focus(this.focusedItem),this.refreshRole()}clear(){this.isEmpty()||(this.viewItems=(0,_.dispose)(this.viewItems),this.viewItemDisposables.clearAndDisposeAll(),d.clearNode(this.actionsList),this.refreshRole())}length(){return this.viewItems.length}isEmpty(){return this.viewItems.length===0}focus(o){let t=!1,i;if(o===void 0?t=!0:typeof o=="number"?i=o:typeof o=="boolean"&&(t=o),t&&typeof this.focusedItem>"u"){const s=this.viewItems.findIndex(g=>g.isEnabled());this.focusedItem=s===-1?void 0:s,this.updateFocus(void 0,void 0,!0)}else i!==void 0&&(this.focusedItem=i),this.updateFocus(void 0,void 0,!0)}focusFirst(){return this.focusedItem=this.length()-1,this.focusNext(!0)}focusLast(){return this.focusedItem=0,this.focusPrevious(!0)}focusNext(o,t){if(typeof this.focusedItem>"u")this.focusedItem=this.viewItems.length-1;else if(this.viewItems.length<=1)return!1;const i=this.focusedItem;let s;do{if(!o&&this.options.preventLoopNavigation&&this.focusedItem+1>=this.viewItems.length)return this.focusedItem=i,!1;this.focusedItem=(this.focusedItem+1)%this.viewItems.length,s=this.viewItems[this.focusedItem]}while(this.focusedItem!==i&&(this.options.focusOnlyEnabledItems&&!s.isEnabled()||s.action.id===y.Separator.ID));return this.updateFocus(void 0,void 0,t),!0}focusPrevious(o){if(typeof this.focusedItem>"u")this.focusedItem=0;else if(this.viewItems.length<=1)return!1;const t=this.focusedItem;let i;do{if(this.focusedItem=this.focusedItem-1,this.focusedItem<0){if(!o&&this.options.preventLoopNavigation)return this.focusedItem=t,!1;this.focusedItem=this.viewItems.length-1}i=this.viewItems[this.focusedItem]}while(this.focusedItem!==t&&(this.options.focusOnlyEnabledItems&&!i.isEnabled()||i.action.id===y.Separator.ID));return this.updateFocus(!0),!0}updateFocus(o,t,i=!1){typeof this.focusedItem>"u"&&this.actionsList.focus({preventScroll:t}),this.previouslyFocusedItem!==void 0&&this.previouslyFocusedItem!==this.focusedItem&&this.viewItems[this.previouslyFocusedItem]?.blur();const s=this.focusedItem!==void 0?this.viewItems[this.focusedItem]:void 0;if(s){let g=!0;b.isFunction(s.focus)||(g=!1),this.options.focusOnlyEnabledItems&&b.isFunction(s.isEnabled)&&!s.isEnabled()&&(g=!1),s.action.id===y.Separator.ID&&(g=!1),g?(i||this.previouslyFocusedItem!==this.focusedItem)&&(s.focus(o),this.previouslyFocusedItem=this.focusedItem):(this.actionsList.focus({preventScroll:t}),this.previouslyFocusedItem=void 0),g&&s.showHover?.()}}doTrigger(o){if(typeof this.focusedItem>"u")return;const t=this.viewItems[this.focusedItem];if(t instanceof I.BaseActionViewItem){const i=t._context===null||t._context===void 0?o:t._context;this.run(t._action,i)}}async run(o,t){await this._actionRunner.run(o,t)}dispose(){this._context=void 0,this.viewItems=(0,_.dispose)(this.viewItems),this.getContainer().remove(),super.dispose()}}e.ActionBar=p}),define(ne[359],se([1,0,5,151,631,6,44,81,303]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DropdownMenuActionViewItem=void 0;class _ extends k.BaseActionViewItem{constructor(p,n,o,t=Object.create(null)){super(null,p,t),this.actionItem=null,this._onDidChangeVisibility=this._register(new E.Emitter),this.onDidChangeVisibility=this._onDidChangeVisibility.event,this.menuActionsOrProvider=n,this.contextMenuProvider=o,this.options=t,this.options.actionRunner&&(this.actionRunner=this.options.actionRunner)}render(p){this.actionItem=p;const n=i=>{this.element=(0,d.append)(i,(0,d.$)("a.action-label"));let s=[];return typeof this.options.classNames=="string"?s=this.options.classNames.split(/\s+/g).filter(g=>!!g):this.options.classNames&&(s=this.options.classNames),s.find(g=>g==="icon")||s.push("codicon"),this.element.classList.add(...s),this.element.setAttribute("role","button"),this.element.setAttribute("aria-haspopup","true"),this.element.setAttribute("aria-expanded","false"),this._action.label&&this._register((0,m.getBaseLayerHoverDelegate)().setupManagedHover(this.options.hoverDelegate??(0,y.getDefaultHoverDelegate)("mouse"),this.element,this._action.label)),this.element.ariaLabel=this._action.label||"",null},o=Array.isArray(this.menuActionsOrProvider),t={contextMenuProvider:this.contextMenuProvider,labelRenderer:n,menuAsChild:this.options.menuAsChild,actions:o?this.menuActionsOrProvider:void 0,actionProvider:o?void 0:this.menuActionsOrProvider,skipTelemetry:this.options.skipTelemetry};if(this.dropdownMenu=this._register(new I.DropdownMenu(p,t)),this._register(this.dropdownMenu.onDidChangeVisibility(i=>{this.element?.setAttribute("aria-expanded",`${i}`),this._onDidChangeVisibility.fire(i)})),this.dropdownMenu.menuOptions={actionViewItemProvider:this.options.actionViewItemProvider,actionRunner:this.actionRunner,getKeyBinding:this.options.keybindingProvider,context:this._context},this.options.anchorAlignmentProvider){const i=this;this.dropdownMenu.menuOptions={...this.dropdownMenu.menuOptions,get anchorAlignment(){return i.options.anchorAlignmentProvider()}}}this.updateTooltip(),this.updateEnabled()}getTooltip(){let p=null;return this.action.tooltip?p=this.action.tooltip:this.action.label&&(p=this.action.label),p??void 0}setActionContext(p){super.setActionContext(p),this.dropdownMenu&&(this.dropdownMenu.menuOptions?this.dropdownMenu.menuOptions.context=p:this.dropdownMenu.menuOptions={context:p})}show(){this.dropdownMenu?.show()}updateEnabled(){const p=!this.action.enabled;this.actionItem?.classList.toggle("disabled",p),this.element?.classList.toggle("disabled",p)}}e.DropdownMenuActionViewItem=_}),define(ne[259],se([1,0,5,93,352,87,46,81,44,86,85,6,450,60,3,466]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HistoryInputBox=e.InputBox=e.unthemedInboxStyles=void 0;const s=d.$;e.unthemedInboxStyles={inputBackground:"#3C3C3C",inputForeground:"#CCCCCC",inputValidationInfoBorder:"#55AAFF",inputValidationInfoBackground:"#063B49",inputValidationWarningBorder:"#B89500",inputValidationWarningBackground:"#352A05",inputValidationErrorBorder:"#BE1100",inputValidationErrorBackground:"#5A1D1D",inputBorder:void 0,inputValidationErrorForeground:void 0,inputValidationInfoForeground:void 0,inputValidationWarningForeground:void 0};class g extends p.Widget{constructor(a,r,u){super(),this.state="idle",this.maxHeight=Number.POSITIVE_INFINITY,this._onDidChange=this._register(new n.Emitter),this.onDidChange=this._onDidChange.event,this._onDidHeightChange=this._register(new n.Emitter),this.onDidHeightChange=this._onDidHeightChange.event,this.contextViewProvider=r,this.options=u,this.message=null,this.placeholder=this.options.placeholder||"",this.tooltip=this.options.tooltip??(this.placeholder||""),this.ariaLabel=this.options.ariaLabel||"",this.options.validationOptions&&(this.validation=this.options.validationOptions.validation),this.element=d.append(a,s(".monaco-inputbox.idle"));const C=this.options.flexibleHeight?"textarea":"input",f=d.append(this.element,s(".ibwrapper"));if(this.input=d.append(f,s(C+".input.empty")),this.input.setAttribute("autocorrect","off"),this.input.setAttribute("autocapitalize","off"),this.input.setAttribute("spellcheck","false"),this.onfocus(this.input,()=>this.element.classList.add("synthetic-focus")),this.onblur(this.input,()=>this.element.classList.remove("synthetic-focus")),this.options.flexibleHeight){this.maxHeight=typeof this.options.flexibleMaxHeight=="number"?this.options.flexibleMaxHeight:Number.POSITIVE_INFINITY,this.mirror=d.append(f,s("div.mirror")),this.mirror.innerText="\xA0",this.scrollableElement=new b.ScrollableElement(this.element,{vertical:1}),this.options.flexibleWidth&&(this.input.setAttribute("wrap","off"),this.mirror.style.whiteSpace="pre",this.mirror.style.wordWrap="initial"),d.append(a,this.scrollableElement.getDomNode()),this._register(this.scrollableElement),this._register(this.scrollableElement.onScroll(w=>this.input.scrollTop=w.scrollTop));const h=this._register(new k.DomEmitter(a.ownerDocument,"selectionchange")),v=n.Event.filter(h.event,()=>a.ownerDocument.getSelection()?.anchorNode===f);this._register(v(this.updateScrollDimensions,this)),this._register(this.onDidHeightChange(this.updateScrollDimensions,this))}else this.input.type=this.options.type||"text",this.input.setAttribute("wrap","off");this.ariaLabel&&this.input.setAttribute("aria-label",this.ariaLabel),this.placeholder&&!this.options.showPlaceholderOnFocus&&this.setPlaceHolder(this.placeholder),this.tooltip&&this.setTooltip(this.tooltip),this.oninput(this.input,()=>this.onValueChange()),this.onblur(this.input,()=>this.onBlur()),this.onfocus(this.input,()=>this.onFocus()),this._register(this.ignoreGesture(this.input)),setTimeout(()=>this.updateMirror(),0),this.options.actions&&(this.actionbar=this._register(new E.ActionBar(this.element)),this.actionbar.push(this.options.actions,{icon:!0,label:!1})),this.applyStyles()}onBlur(){this._hideMessage(),this.options.showPlaceholderOnFocus&&this.input.setAttribute("placeholder","")}onFocus(){this._showMessage(),this.options.showPlaceholderOnFocus&&this.input.setAttribute("placeholder",this.placeholder||"")}setPlaceHolder(a){this.placeholder=a,this.input.setAttribute("placeholder",a)}setTooltip(a){this.tooltip=a,this.hover?this.hover.update(a):this.hover=this._register((0,m.getBaseLayerHoverDelegate)().setupManagedHover((0,_.getDefaultHoverDelegate)("mouse"),this.input,a))}get inputElement(){return this.input}get value(){return this.input.value}set value(a){this.input.value!==a&&(this.input.value=a,this.onValueChange())}get height(){return typeof this.cachedHeight=="number"?this.cachedHeight:d.getTotalHeight(this.element)}focus(){this.input.focus()}blur(){this.input.blur()}hasFocus(){return d.isActiveElement(this.input)}select(a=null){this.input.select(),a&&(this.input.setSelectionRange(a.start,a.end),a.end===this.input.value.length&&(this.input.scrollLeft=this.input.scrollWidth))}isSelectionAtEnd(){return this.input.selectionEnd===this.input.value.length&&this.input.selectionStart===this.input.selectionEnd}getSelection(){const a=this.input.selectionStart;if(a===null)return null;const r=this.input.selectionEnd??a;return{start:a,end:r}}enable(){this.input.removeAttribute("disabled")}disable(){this.blur(),this.input.disabled=!0,this._hideMessage()}set paddingRight(a){this.input.style.width=`calc(100% - ${a}px)`,this.mirror&&(this.mirror.style.paddingRight=a+"px")}updateScrollDimensions(){if(typeof this.cachedContentHeight!="number"||typeof this.cachedHeight!="number"||!this.scrollableElement)return;const a=this.cachedContentHeight,r=this.cachedHeight,u=this.input.scrollTop;this.scrollableElement.setScrollDimensions({scrollHeight:a,height:r}),this.scrollableElement.setScrollPosition({scrollTop:u})}showMessage(a,r){if(this.state==="open"&&(0,t.equals)(this.message,a))return;this.message=a,this.element.classList.remove("idle"),this.element.classList.remove("info"),this.element.classList.remove("warning"),this.element.classList.remove("error"),this.element.classList.add(this.classForType(a.type));const u=this.stylesForType(this.message.type);this.element.style.border=`1px solid ${d.asCssValueWithDefault(u.border,"transparent")}`,this.message.content&&(this.hasFocus()||r)&&this._showMessage()}hideMessage(){this.message=null,this.element.classList.remove("info"),this.element.classList.remove("warning"),this.element.classList.remove("error"),this.element.classList.add("idle"),this._hideMessage(),this.applyStyles()}validate(){let a=null;return this.validation&&(a=this.validation(this.value),a?(this.inputElement.setAttribute("aria-invalid","true"),this.showMessage(a)):this.inputElement.hasAttribute("aria-invalid")&&(this.inputElement.removeAttribute("aria-invalid"),this.hideMessage())),a?.type}stylesForType(a){const r=this.options.inputBoxStyles;switch(a){case 1:return{border:r.inputValidationInfoBorder,background:r.inputValidationInfoBackground,foreground:r.inputValidationInfoForeground};case 2:return{border:r.inputValidationWarningBorder,background:r.inputValidationWarningBackground,foreground:r.inputValidationWarningForeground};default:return{border:r.inputValidationErrorBorder,background:r.inputValidationErrorBackground,foreground:r.inputValidationErrorForeground}}}classForType(a){switch(a){case 1:return"info";case 2:return"warning";default:return"error"}}_showMessage(){if(!this.contextViewProvider||!this.message)return;let a;const r=()=>a.style.width=d.getTotalWidth(this.element)+"px";this.contextViewProvider.showContextView({getAnchor:()=>this.element,anchorAlignment:1,render:C=>{if(!this.message)return null;a=d.append(C,s(".monaco-inputbox-container")),r();const f={inline:!0,className:"monaco-inputbox-message"},h=this.message.formatContent?(0,I.renderFormattedText)(this.message.content,f):(0,I.renderText)(this.message.content,f);h.classList.add(this.classForType(this.message.type));const v=this.stylesForType(this.message.type);return h.style.backgroundColor=v.background??"",h.style.color=v.foreground??"",h.style.border=v.border?`1px solid ${v.border}`:"",d.append(a,h),null},onHide:()=>{this.state="closed"},layout:r});let u;this.message.type===3?u=i.localize(9,"Error: {0}",this.message.content):this.message.type===2?u=i.localize(10,"Warning: {0}",this.message.content):u=i.localize(11,"Info: {0}",this.message.content),y.alert(u),this.state="open"}_hideMessage(){this.contextViewProvider&&(this.state==="open"&&this.contextViewProvider.hideContextView(),this.state="idle")}onValueChange(){this._onDidChange.fire(this.value),this.validate(),this.updateMirror(),this.input.classList.toggle("empty",!this.value),this.state==="open"&&this.contextViewProvider&&this.contextViewProvider.layout()}updateMirror(){if(!this.mirror)return;const a=this.value,u=a.charCodeAt(a.length-1)===10?" ":"";(a+u).replace(/\u000c/g,"")?this.mirror.textContent=a+u:this.mirror.innerText="\xA0",this.layout()}applyStyles(){const a=this.options.inputBoxStyles,r=a.inputBackground??"",u=a.inputForeground??"",C=a.inputBorder??"";this.element.style.backgroundColor=r,this.element.style.color=u,this.input.style.backgroundColor="inherit",this.input.style.color=u,this.element.style.border=`1px solid ${d.asCssValueWithDefault(C,"transparent")}`}layout(){if(!this.mirror)return;const a=this.cachedContentHeight;this.cachedContentHeight=d.getTotalHeight(this.mirror),a!==this.cachedContentHeight&&(this.cachedHeight=Math.min(this.cachedContentHeight,this.maxHeight),this.input.style.height=this.cachedHeight+"px",this._onDidHeightChange.fire(this.cachedContentHeight))}insertAtCursor(a){const r=this.inputElement,u=r.selectionStart,C=r.selectionEnd,f=r.value;u!==null&&C!==null&&(this.value=f.substr(0,u)+a+f.substr(C),r.setSelectionRange(u+1,u+1),this.layout())}dispose(){this._hideMessage(),this.message=null,this.actionbar?.dispose(),super.dispose()}}e.InputBox=g;class c extends g{constructor(a,r,u){const C=i.localize(12," or {0} for history","\u21C5"),f=i.localize(13," ({0} for history)","\u21C5");super(a,r,u),this._onDidFocus=this._register(new n.Emitter),this.onDidFocus=this._onDidFocus.event,this._onDidBlur=this._register(new n.Emitter),this.onDidBlur=this._onDidBlur.event,this.history=new o.HistoryNavigator(u.history,100);const h=()=>{if(u.showHistoryHint&&u.showHistoryHint()&&!this.placeholder.endsWith(C)&&!this.placeholder.endsWith(f)&&this.history.getHistory().length){const v=this.placeholder.endsWith(")")?C:f,w=this.placeholder+v;u.showPlaceholderOnFocus&&!d.isActiveElement(this.input)?this.placeholder=w:this.setPlaceHolder(w)}};this.observer=new MutationObserver((v,w)=>{v.forEach(S=>{S.target.textContent||h()})}),this.observer.observe(this.input,{attributeFilter:["class"]}),this.onfocus(this.input,()=>h()),this.onblur(this.input,()=>{const v=w=>{if(this.placeholder.endsWith(w)){const S=this.placeholder.slice(0,this.placeholder.length-w.length);return u.showPlaceholderOnFocus?this.placeholder=S:this.setPlaceHolder(S),!0}else return!1};v(f)||v(C)})}dispose(){super.dispose(),this.observer&&(this.observer.disconnect(),this.observer=void 0)}addToHistory(a){this.value&&(a||this.value!==this.getCurrentValue())&&this.history.add(this.value)}isAtLastInHistory(){return this.history.isLast()}isNowhereInHistory(){return this.history.isNowhere()}showNextValue(){this.history.has(this.value)||this.addToHistory();let a=this.getNextValue();a&&(a=a===this.value?this.getNextValue():a),this.value=a??"",y.status(this.value?this.value:i.localize(14,"Cleared Input"))}showPreviousValue(){this.history.has(this.value)||this.addToHistory();let a=this.getPreviousValue();a&&(a=a===this.value?this.getPreviousValue():a),a&&(this.value=a,y.status(this.value))}setPlaceHolder(a){super.setPlaceHolder(a),this.setTooltip(a)}onBlur(){super.onBlur(),this._onDidBlur.fire()}onFocus(){super.onFocus(),this._onDidFocus.fire()}getCurrentValue(){let a=this.history.current();return a||(a=this.history.last(),this.history.next()),a}getPreviousValue(){return this.history.previous()||this.history.first()}getNextValue(){return this.history.next()}}e.HistoryInputBox=c}),define(ne[260],se([1,0,5,358,259,85,6,3,2,44,304]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FindInput=void 0;const p=m.localize(1,"input");class n extends E.Widget{constructor(t,i,s){super(),this.fixFocusOnOptionClickEnabled=!0,this.imeSessionInProgress=!1,this.additionalTogglesDisposables=this._register(new _.MutableDisposable),this.additionalToggles=[],this._onDidOptionChange=this._register(new y.Emitter),this.onDidOptionChange=this._onDidOptionChange.event,this._onKeyDown=this._register(new y.Emitter),this.onKeyDown=this._onKeyDown.event,this._onMouseDown=this._register(new y.Emitter),this.onMouseDown=this._onMouseDown.event,this._onInput=this._register(new y.Emitter),this._onKeyUp=this._register(new y.Emitter),this._onCaseSensitiveKeyDown=this._register(new y.Emitter),this.onCaseSensitiveKeyDown=this._onCaseSensitiveKeyDown.event,this._onRegexKeyDown=this._register(new y.Emitter),this.onRegexKeyDown=this._onRegexKeyDown.event,this._lastHighlightFindOptions=0,this.placeholder=s.placeholder||"",this.validation=s.validation,this.label=s.label||p,this.showCommonFindToggles=!!s.showCommonFindToggles;const g=s.appendCaseSensitiveLabel||"",c=s.appendWholeWordsLabel||"",l=s.appendRegexLabel||"",a=s.history||[],r=!!s.flexibleHeight,u=!!s.flexibleWidth,C=s.flexibleMaxHeight;this.domNode=document.createElement("div"),this.domNode.classList.add("monaco-findInput"),this.inputBox=this._register(new I.HistoryInputBox(this.domNode,i,{placeholder:this.placeholder||"",ariaLabel:this.label||"",validationOptions:{validation:this.validation},history:a,showHistoryHint:s.showHistoryHint,flexibleHeight:r,flexibleWidth:u,flexibleMaxHeight:C,inputBoxStyles:s.inputBoxStyles}));const f=this._register((0,b.createInstantHoverDelegate)());if(this.showCommonFindToggles){this.regex=this._register(new k.RegexToggle({appendTitle:l,isChecked:!1,hoverDelegate:f,...s.toggleStyles})),this._register(this.regex.onChange(v=>{this._onDidOptionChange.fire(v),!v&&this.fixFocusOnOptionClickEnabled&&this.inputBox.focus(),this.validate()})),this._register(this.regex.onKeyDown(v=>{this._onRegexKeyDown.fire(v)})),this.wholeWords=this._register(new k.WholeWordsToggle({appendTitle:c,isChecked:!1,hoverDelegate:f,...s.toggleStyles})),this._register(this.wholeWords.onChange(v=>{this._onDidOptionChange.fire(v),!v&&this.fixFocusOnOptionClickEnabled&&this.inputBox.focus(),this.validate()})),this.caseSensitive=this._register(new k.CaseSensitiveToggle({appendTitle:g,isChecked:!1,hoverDelegate:f,...s.toggleStyles})),this._register(this.caseSensitive.onChange(v=>{this._onDidOptionChange.fire(v),!v&&this.fixFocusOnOptionClickEnabled&&this.inputBox.focus(),this.validate()})),this._register(this.caseSensitive.onKeyDown(v=>{this._onCaseSensitiveKeyDown.fire(v)}));const h=[this.caseSensitive.domNode,this.wholeWords.domNode,this.regex.domNode];this.onkeydown(this.domNode,v=>{if(v.equals(15)||v.equals(17)||v.equals(9)){const w=h.indexOf(this.domNode.ownerDocument.activeElement);if(w>=0){let S=-1;v.equals(17)?S=(w+1)%h.length:v.equals(15)&&(w===0?S=h.length-1:S=w-1),v.equals(9)?(h[w].blur(),this.inputBox.focus()):S>=0&&h[S].focus(),d.EventHelper.stop(v,!0)}}})}this.controls=document.createElement("div"),this.controls.className="controls",this.controls.style.display=this.showCommonFindToggles?"":"none",this.caseSensitive&&this.controls.append(this.caseSensitive.domNode),this.wholeWords&&this.controls.appendChild(this.wholeWords.domNode),this.regex&&this.controls.appendChild(this.regex.domNode),this.setAdditionalToggles(s?.additionalToggles),this.controls&&this.domNode.appendChild(this.controls),t?.appendChild(this.domNode),this._register(d.addDisposableListener(this.inputBox.inputElement,"compositionstart",h=>{this.imeSessionInProgress=!0})),this._register(d.addDisposableListener(this.inputBox.inputElement,"compositionend",h=>{this.imeSessionInProgress=!1,this._onInput.fire()})),this.onkeydown(this.inputBox.inputElement,h=>this._onKeyDown.fire(h)),this.onkeyup(this.inputBox.inputElement,h=>this._onKeyUp.fire(h)),this.oninput(this.inputBox.inputElement,h=>this._onInput.fire()),this.onmousedown(this.inputBox.inputElement,h=>this._onMouseDown.fire(h))}get onDidChange(){return this.inputBox.onDidChange}layout(t){this.inputBox.layout(),this.updateInputBoxPadding(t.collapsedFindWidget)}enable(){this.domNode.classList.remove("disabled"),this.inputBox.enable(),this.regex?.enable(),this.wholeWords?.enable(),this.caseSensitive?.enable();for(const t of this.additionalToggles)t.enable()}disable(){this.domNode.classList.add("disabled"),this.inputBox.disable(),this.regex?.disable(),this.wholeWords?.disable(),this.caseSensitive?.disable();for(const t of this.additionalToggles)t.disable()}setFocusInputOnOptionClick(t){this.fixFocusOnOptionClickEnabled=t}setEnabled(t){t?this.enable():this.disable()}setAdditionalToggles(t){for(const i of this.additionalToggles)i.domNode.remove();this.additionalToggles=[],this.additionalTogglesDisposables.value=new _.DisposableStore;for(const i of t??[])this.additionalTogglesDisposables.value.add(i),this.controls.appendChild(i.domNode),this.additionalTogglesDisposables.value.add(i.onChange(s=>{this._onDidOptionChange.fire(s),!s&&this.fixFocusOnOptionClickEnabled&&this.inputBox.focus()})),this.additionalToggles.push(i);this.additionalToggles.length>0&&(this.controls.style.display=""),this.updateInputBoxPadding()}updateInputBoxPadding(t=!1){t?this.inputBox.paddingRight=0:this.inputBox.paddingRight=(this.caseSensitive?.width()??0)+(this.wholeWords?.width()??0)+(this.regex?.width()??0)+this.additionalToggles.reduce((i,s)=>i+s.width(),0)}getValue(){return this.inputBox.value}setValue(t){this.inputBox.value!==t&&(this.inputBox.value=t)}select(){this.inputBox.select()}focus(){this.inputBox.focus()}getCaseSensitive(){return this.caseSensitive?.checked??!1}setCaseSensitive(t){this.caseSensitive&&(this.caseSensitive.checked=t)}getWholeWords(){return this.wholeWords?.checked??!1}setWholeWords(t){this.wholeWords&&(this.wholeWords.checked=t)}getRegex(){return this.regex?.checked??!1}setRegex(t){this.regex&&(this.regex.checked=t,this.validate())}focusOnCaseSensitive(){this.caseSensitive?.focus()}highlightFindOptions(){this.domNode.classList.remove("highlight-"+this._lastHighlightFindOptions),this._lastHighlightFindOptions=1-this._lastHighlightFindOptions,this.domNode.classList.add("highlight-"+this._lastHighlightFindOptions)}validate(){this.inputBox.validate()}showMessage(t){this.inputBox.showMessage(t)}clearMessage(){this.inputBox.hideMessage()}}e.FindInput=n}),define(ne[641],se([1,0,5,175,259,85,26,6,3,44,304]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ReplaceInput=void 0;const p=_.localize(5,"input"),n=_.localize(6,"Preserve Case");class o extends k.Toggle{constructor(s){super({icon:y.Codicon.preserveCase,title:n+s.appendTitle,isChecked:s.isChecked,hoverDelegate:s.hoverDelegate??(0,b.getDefaultHoverDelegate)("element"),inputActiveOptionBorder:s.inputActiveOptionBorder,inputActiveOptionForeground:s.inputActiveOptionForeground,inputActiveOptionBackground:s.inputActiveOptionBackground})}}class t extends E.Widget{constructor(s,g,c,l){super(),this._showOptionButtons=c,this.fixFocusOnOptionClickEnabled=!0,this.cachedOptionsWidth=0,this._onDidOptionChange=this._register(new m.Emitter),this.onDidOptionChange=this._onDidOptionChange.event,this._onKeyDown=this._register(new m.Emitter),this.onKeyDown=this._onKeyDown.event,this._onMouseDown=this._register(new m.Emitter),this._onInput=this._register(new m.Emitter),this._onKeyUp=this._register(new m.Emitter),this._onPreserveCaseKeyDown=this._register(new m.Emitter),this.onPreserveCaseKeyDown=this._onPreserveCaseKeyDown.event,this.contextViewProvider=g,this.placeholder=l.placeholder||"",this.validation=l.validation,this.label=l.label||p;const a=l.appendPreserveCaseLabel||"",r=l.history||[],u=!!l.flexibleHeight,C=!!l.flexibleWidth,f=l.flexibleMaxHeight;this.domNode=document.createElement("div"),this.domNode.classList.add("monaco-findInput"),this.inputBox=this._register(new I.HistoryInputBox(this.domNode,this.contextViewProvider,{ariaLabel:this.label||"",placeholder:this.placeholder||"",validationOptions:{validation:this.validation},history:r,showHistoryHint:l.showHistoryHint,flexibleHeight:u,flexibleWidth:C,flexibleMaxHeight:f,inputBoxStyles:l.inputBoxStyles})),this.preserveCase=this._register(new o({appendTitle:a,isChecked:!1,...l.toggleStyles})),this._register(this.preserveCase.onChange(w=>{this._onDidOptionChange.fire(w),!w&&this.fixFocusOnOptionClickEnabled&&this.inputBox.focus(),this.validate()})),this._register(this.preserveCase.onKeyDown(w=>{this._onPreserveCaseKeyDown.fire(w)})),this._showOptionButtons?this.cachedOptionsWidth=this.preserveCase.width():this.cachedOptionsWidth=0;const h=[this.preserveCase.domNode];this.onkeydown(this.domNode,w=>{if(w.equals(15)||w.equals(17)||w.equals(9)){const S=h.indexOf(this.domNode.ownerDocument.activeElement);if(S>=0){let L=-1;w.equals(17)?L=(S+1)%h.length:w.equals(15)&&(S===0?L=h.length-1:L=S-1),w.equals(9)?(h[S].blur(),this.inputBox.focus()):L>=0&&h[L].focus(),d.EventHelper.stop(w,!0)}}});const v=document.createElement("div");v.className="controls",v.style.display=this._showOptionButtons?"block":"none",v.appendChild(this.preserveCase.domNode),this.domNode.appendChild(v),s?.appendChild(this.domNode),this.onkeydown(this.inputBox.inputElement,w=>this._onKeyDown.fire(w)),this.onkeyup(this.inputBox.inputElement,w=>this._onKeyUp.fire(w)),this.oninput(this.inputBox.inputElement,w=>this._onInput.fire()),this.onmousedown(this.inputBox.inputElement,w=>this._onMouseDown.fire(w))}enable(){this.domNode.classList.remove("disabled"),this.inputBox.enable(),this.preserveCase.enable()}disable(){this.domNode.classList.add("disabled"),this.inputBox.disable(),this.preserveCase.disable()}setEnabled(s){s?this.enable():this.disable()}select(){this.inputBox.select()}focus(){this.inputBox.focus()}getPreserveCase(){return this.preserveCase.checked}setPreserveCase(s){this.preserveCase.checked=s}focusOnPreserve(){this.preserveCase.focus()}validate(){this.inputBox?.validate()}set width(s){this.inputBox.paddingRight=this.cachedOptionsWidth,this.domNode.style.width=s+"px"}dispose(){super.dispose()}}e.ReplaceInput=t}),define(ne[642],se([1,0,64,69,5,47,77,87,151,353,86,41,14,26,191,30,142,2,16,11]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Menu=e.VerticalDirection=e.HorizontalDirection=e.MENU_ESCAPED_MNEMONIC_REGEX=e.MENU_MNEMONIC_REGEX=void 0,e.cleanMnemonic=w,e.formatRule=S,e.MENU_MNEMONIC_REGEX=/\(&([^\s&])\)|(^|[^&])&([^\s&])/,e.MENU_ESCAPED_MNEMONIC_REGEX=/(&)?(&)([^\s&])/g;var r;(function(D){D[D.Right=0]="Right",D[D.Left=1]="Left"})(r||(e.HorizontalDirection=r={}));var u;(function(D){D[D.Above=0]="Above",D[D.Below=1]="Below"})(u||(e.VerticalDirection=u={}));class C extends m.ActionBar{constructor(T,M,A,P){T.classList.add("monaco-menu-container"),T.setAttribute("role","presentation");const N=document.createElement("div");N.classList.add("monaco-menu"),N.setAttribute("role","presentation"),super(N,{orientation:1,actionViewItemProvider:W=>this.doGetActionViewItem(W,A,O),context:A.context,actionRunner:A.actionRunner,ariaLabel:A.ariaLabel,ariaRole:"menu",focusOnlyEnabledItems:!0,triggerKeys:{keys:[3,...l.isMacintosh||l.isLinux?[10]:[]],keyDown:!0}}),this.menuStyles=P,this.menuElement=N,this.actionsList.tabIndex=0,this.initializeOrUpdateStyleSheet(T,P),this._register(k.Gesture.addTarget(N)),this._register((0,I.addDisposableListener)(N,I.EventType.KEY_DOWN,W=>{new E.StandardKeyboardEvent(W).equals(2)&&W.preventDefault()})),A.enableMnemonics&&this._register((0,I.addDisposableListener)(N,I.EventType.KEY_DOWN,W=>{const V=W.key.toLocaleLowerCase();if(this.mnemonics.has(V)){I.EventHelper.stop(W,!0);const q=this.mnemonics.get(V);if(q.length===1&&(q[0]instanceof h&&q[0].container&&this.focusItemByElement(q[0].container),q[0].onClick(W)),q.length>1){const H=q.shift();H&&H.container&&(this.focusItemByElement(H.container),q.push(H)),this.mnemonics.set(V,q)}}})),l.isLinux&&this._register((0,I.addDisposableListener)(N,I.EventType.KEY_DOWN,W=>{const V=new E.StandardKeyboardEvent(W);V.equals(14)||V.equals(11)?(this.focusedItem=this.viewItems.length-1,this.focusNext(),I.EventHelper.stop(W,!0)):(V.equals(13)||V.equals(12))&&(this.focusedItem=0,this.focusPrevious(),I.EventHelper.stop(W,!0))})),this._register((0,I.addDisposableListener)(this.domNode,I.EventType.MOUSE_OUT,W=>{const V=W.relatedTarget;(0,I.isAncestor)(V,this.domNode)||(this.focusedItem=void 0,this.updateFocus(),W.stopPropagation())})),this._register((0,I.addDisposableListener)(this.actionsList,I.EventType.MOUSE_OVER,W=>{let V=W.target;if(!(!V||!(0,I.isAncestor)(V,this.actionsList)||V===this.actionsList)){for(;V.parentElement!==this.actionsList&&V.parentElement!==null;)V=V.parentElement;if(V.classList.contains("action-item")){const q=this.focusedItem;this.setFocusedItem(V),q!==this.focusedItem&&this.updateFocus()}}})),this._register(k.Gesture.addTarget(this.actionsList)),this._register((0,I.addDisposableListener)(this.actionsList,k.EventType.Tap,W=>{let V=W.initialTarget;if(!(!V||!(0,I.isAncestor)(V,this.actionsList)||V===this.actionsList)){for(;V.parentElement!==this.actionsList&&V.parentElement!==null;)V=V.parentElement;if(V.classList.contains("action-item")){const q=this.focusedItem;this.setFocusedItem(V),q!==this.focusedItem&&this.updateFocus()}}}));const O={parent:this};this.mnemonics=new Map,this.scrollableElement=this._register(new p.DomScrollableElement(N,{alwaysConsumeMouseWheel:!0,horizontal:2,vertical:3,verticalScrollbarSize:7,handleMouseWheel:!0,useShadows:!0}));const F=this.scrollableElement.getDomNode();F.style.position="",this.styleScrollElement(F,P),this._register((0,I.addDisposableListener)(N,k.EventType.Change,W=>{I.EventHelper.stop(W,!0);const V=this.scrollableElement.getScrollPosition().scrollTop;this.scrollableElement.setScrollPosition({scrollTop:V-W.translationY})})),this._register((0,I.addDisposableListener)(F,I.EventType.MOUSE_UP,W=>{W.preventDefault()}));const x=(0,I.getWindow)(T);N.style.maxHeight=`${Math.max(10,x.innerHeight-T.getBoundingClientRect().top-35)}px`,M=M.filter((W,V)=>A.submenuIds?.has(W.id)?(console.warn(`Found submenu cycle: ${W.id}`),!1):!(W instanceof n.Separator&&(V===M.length-1||V===0||M[V-1]instanceof n.Separator))),this.push(M,{icon:!0,label:!0,isMenu:!0}),T.appendChild(this.scrollableElement.getDomNode()),this.scrollableElement.scanDomNode(),this.viewItems.filter(W=>!(W instanceof v)).forEach((W,V,q)=>{W.updatePositionInSet(V+1,q.length)})}initializeOrUpdateStyleSheet(T,M){this.styleSheet||((0,I.isInShadowDOM)(T)?this.styleSheet=(0,I.createStyleSheet)(T):(C.globalStyleSheet||(C.globalStyleSheet=(0,I.createStyleSheet)()),this.styleSheet=C.globalStyleSheet)),this.styleSheet.textContent=L(M,(0,I.isInShadowDOM)(T))}styleScrollElement(T,M){const A=M.foregroundColor??"",P=M.backgroundColor??"",N=M.borderColor?`1px solid ${M.borderColor}`:"",O="5px",F=M.shadowColor?`0 2px 8px ${M.shadowColor}`:"";T.style.outline=N,T.style.borderRadius=O,T.style.color=A,T.style.backgroundColor=P,T.style.boxShadow=F}getContainer(){return this.scrollableElement.getDomNode()}get onScroll(){return this.scrollableElement.onScroll}focusItemByElement(T){const M=this.focusedItem;this.setFocusedItem(T),M!==this.focusedItem&&this.updateFocus()}setFocusedItem(T){for(let M=0;M{this.element&&(this._register((0,I.addDisposableListener)(this.element,I.EventType.MOUSE_UP,N=>{if(I.EventHelper.stop(N,!0),d.isFirefox){if(new y.StandardMouseEvent((0,I.getWindow)(this.element),N).rightButton)return;this.onClick(N)}else setTimeout(()=>{this.onClick(N)},0)})),this._register((0,I.addDisposableListener)(this.element,I.EventType.CONTEXT_MENU,N=>{I.EventHelper.stop(N,!0)})))},100),this._register(this.runOnceToEnableMouseUp)}render(T){super.render(T),this.element&&(this.container=T,this.item=(0,I.append)(this.element,(0,I.$)("a.action-menu-item")),this._action.id===n.Separator.ID?this.item.setAttribute("role","presentation"):(this.item.setAttribute("role","menuitem"),this.mnemonic&&this.item.setAttribute("aria-keyshortcuts",`${this.mnemonic}`)),this.check=(0,I.append)(this.item,(0,I.$)("span.menu-item-check"+s.ThemeIcon.asCSSSelector(t.Codicon.menuSelection))),this.check.setAttribute("role","none"),this.label=(0,I.append)(this.item,(0,I.$)("span.action-label")),this.options.label&&this.options.keybinding&&((0,I.append)(this.item,(0,I.$)("span.keybinding")).textContent=this.options.keybinding),this.runOnceToEnableMouseUp.schedule(),this.updateClass(),this.updateLabel(),this.updateTooltip(),this.updateEnabled(),this.updateChecked(),this.applyStyle())}blur(){super.blur(),this.applyStyle()}focus(){super.focus(),this.item?.focus(),this.applyStyle()}updatePositionInSet(T,M){this.item&&(this.item.setAttribute("aria-posinset",`${T}`),this.item.setAttribute("aria-setsize",`${M}`))}updateLabel(){if(this.label&&this.options.label){(0,I.clearNode)(this.label);let T=(0,g.stripIcons)(this.action.label);if(T){const M=w(T);this.options.enableMnemonics||(T=M),this.label.setAttribute("aria-label",M.replace(/&&/g,"&"));const A=e.MENU_MNEMONIC_REGEX.exec(T);if(A){T=a.escape(T),e.MENU_ESCAPED_MNEMONIC_REGEX.lastIndex=0;let P=e.MENU_ESCAPED_MNEMONIC_REGEX.exec(T);for(;P&&P[1];)P=e.MENU_ESCAPED_MNEMONIC_REGEX.exec(T);const N=O=>O.replace(/&&/g,"&");P?this.label.append(a.ltrim(N(T.substr(0,P.index))," "),(0,I.$)("u",{"aria-hidden":"true"},P[3]),a.rtrim(N(T.substr(P.index+P[0].length))," ")):this.label.innerText=N(T).trim(),this.item?.setAttribute("aria-keyshortcuts",(A[1]?A[1]:A[3]).toLocaleLowerCase())}else this.label.innerText=T.replace(/&&/g,"&").trim()}}}updateTooltip(){}updateClass(){this.cssClass&&this.item&&this.item.classList.remove(...this.cssClass.split(" ")),this.options.icon&&this.label?(this.cssClass=this.action.class||"",this.label.classList.add("icon"),this.cssClass&&this.label.classList.add(...this.cssClass.split(" ")),this.updateEnabled()):this.label&&this.label.classList.remove("icon")}updateEnabled(){this.action.enabled?(this.element&&(this.element.classList.remove("disabled"),this.element.removeAttribute("aria-disabled")),this.item&&(this.item.classList.remove("disabled"),this.item.removeAttribute("aria-disabled"),this.item.tabIndex=0)):(this.element&&(this.element.classList.add("disabled"),this.element.setAttribute("aria-disabled","true")),this.item&&(this.item.classList.add("disabled"),this.item.setAttribute("aria-disabled","true")))}updateChecked(){if(!this.item)return;const T=this.action.checked;this.item.classList.toggle("checked",!!T),T!==void 0?(this.item.setAttribute("role","menuitemcheckbox"),this.item.setAttribute("aria-checked",T?"true":"false")):(this.item.setAttribute("role","menuitem"),this.item.setAttribute("aria-checked",""))}getMnemonic(){return this.mnemonic}applyStyle(){const T=this.element&&this.element.classList.contains("focused"),M=T&&this.menuStyle.selectionForegroundColor?this.menuStyle.selectionForegroundColor:this.menuStyle.foregroundColor,A=T&&this.menuStyle.selectionBackgroundColor?this.menuStyle.selectionBackgroundColor:void 0,P=T&&this.menuStyle.selectionBorderColor?`1px solid ${this.menuStyle.selectionBorderColor}`:"",N=T&&this.menuStyle.selectionBorderColor?"-1px":"";this.item&&(this.item.style.color=M??"",this.item.style.backgroundColor=A??"",this.item.style.outline=P,this.item.style.outlineOffset=N),this.check&&(this.check.style.color=M??"")}}class h extends f{constructor(T,M,A,P,N){super(T,T,P,N),this.submenuActions=M,this.parentData=A,this.submenuOptions=P,this.mysubmenu=null,this.submenuDisposables=this._register(new c.DisposableStore),this.mouseOver=!1,this.expandDirection=P&&P.expandDirection!==void 0?P.expandDirection:{horizontal:r.Right,vertical:u.Below},this.showScheduler=new o.RunOnceScheduler(()=>{this.mouseOver&&(this.cleanupExistingSubmenu(!1),this.createSubmenu(!1))},250),this.hideScheduler=new o.RunOnceScheduler(()=>{this.element&&!(0,I.isAncestor)((0,I.getActiveElement)(),this.element)&&this.parentData.submenu===this.mysubmenu&&(this.parentData.parent.focus(!1),this.cleanupExistingSubmenu(!0))},750)}render(T){super.render(T),this.element&&(this.item&&(this.item.classList.add("monaco-submenu-item"),this.item.tabIndex=0,this.item.setAttribute("aria-haspopup","true"),this.updateAriaExpanded("false"),this.submenuIndicator=(0,I.append)(this.item,(0,I.$)("span.submenu-indicator"+s.ThemeIcon.asCSSSelector(t.Codicon.menuSubmenu))),this.submenuIndicator.setAttribute("aria-hidden","true")),this._register((0,I.addDisposableListener)(this.element,I.EventType.KEY_UP,M=>{const A=new E.StandardKeyboardEvent(M);(A.equals(17)||A.equals(3))&&(I.EventHelper.stop(M,!0),this.createSubmenu(!0))})),this._register((0,I.addDisposableListener)(this.element,I.EventType.KEY_DOWN,M=>{const A=new E.StandardKeyboardEvent(M);(0,I.getActiveElement)()===this.item&&(A.equals(17)||A.equals(3))&&I.EventHelper.stop(M,!0)})),this._register((0,I.addDisposableListener)(this.element,I.EventType.MOUSE_OVER,M=>{this.mouseOver||(this.mouseOver=!0,this.showScheduler.schedule())})),this._register((0,I.addDisposableListener)(this.element,I.EventType.MOUSE_LEAVE,M=>{this.mouseOver=!1})),this._register((0,I.addDisposableListener)(this.element,I.EventType.FOCUS_OUT,M=>{this.element&&!(0,I.isAncestor)((0,I.getActiveElement)(),this.element)&&this.hideScheduler.schedule()})),this._register(this.parentData.parent.onScroll(()=>{this.parentData.submenu===this.mysubmenu&&(this.parentData.parent.focus(!1),this.cleanupExistingSubmenu(!0))})))}updateEnabled(){}onClick(T){I.EventHelper.stop(T,!0),this.cleanupExistingSubmenu(!1),this.createSubmenu(!0)}cleanupExistingSubmenu(T){if(this.parentData.submenu&&(T||this.parentData.submenu!==this.mysubmenu)){try{this.parentData.submenu.dispose()}catch{}this.parentData.submenu=void 0,this.updateAriaExpanded("false"),this.submenuContainer&&(this.submenuDisposables.clear(),this.submenuContainer=void 0)}}calculateSubmenuMenuLayout(T,M,A,P){const N={top:0,left:0};return N.left=(0,b.layout)(T.width,M.width,{position:P.horizontal===r.Right?0:1,offset:A.left,size:A.width}),N.left>=A.left&&N.left{new E.StandardKeyboardEvent(V).equals(15)&&(I.EventHelper.stop(V,!0),this.parentData.parent.focus(),this.cleanupExistingSubmenu(!0))})),this.submenuDisposables.add((0,I.addDisposableListener)(this.submenuContainer,I.EventType.KEY_DOWN,V=>{new E.StandardKeyboardEvent(V).equals(15)&&I.EventHelper.stop(V,!0)})),this.submenuDisposables.add(this.parentData.submenu.onDidCancel(()=>{this.parentData.parent.focus(),this.cleanupExistingSubmenu(!0)})),this.parentData.submenu.focus(T),this.mysubmenu=this.parentData.submenu}}updateAriaExpanded(T){this.item&&this.item?.setAttribute("aria-expanded",T)}applyStyle(){super.applyStyle();const M=this.element&&this.element.classList.contains("focused")&&this.menuStyle.selectionForegroundColor?this.menuStyle.selectionForegroundColor:this.menuStyle.foregroundColor;this.submenuIndicator&&(this.submenuIndicator.style.color=M??"")}dispose(){super.dispose(),this.hideScheduler.dispose(),this.mysubmenu&&(this.mysubmenu.dispose(),this.mysubmenu=null),this.submenuContainer&&(this.submenuContainer=void 0)}}class v extends _.ActionViewItem{constructor(T,M,A,P){super(T,M,A),this.menuStyles=P}render(T){super.render(T),this.label&&(this.label.style.borderBottomColor=this.menuStyles.separatorColor?`${this.menuStyles.separatorColor}`:"")}}function w(D){const T=e.MENU_MNEMONIC_REGEX,M=T.exec(D);if(!M)return D;const A=!M[1];return D.replace(T,A?"$2$3":"").trim()}function S(D){const T=(0,i.getCodiconFontCharacters)()[D.id];return`.codicon-${D.id}:before { content: '\\${T.toString(16)}'; }`}function L(D,T){let M=` .monaco-menu { font-size: 13px; border-radius: 5px; min-width: 160px; } ${S(t.Codicon.menuSelection)} ${S(t.Codicon.menuSubmenu)} .monaco-menu .monaco-action-bar { text-align: right; overflow: hidden; white-space: nowrap; } .monaco-menu .monaco-action-bar .actions-container { display: flex; margin: 0 auto; padding: 0; width: 100%; justify-content: flex-end; } .monaco-menu .monaco-action-bar.vertical .actions-container { display: inline-block; } .monaco-menu .monaco-action-bar.reverse .actions-container { flex-direction: row-reverse; } .monaco-menu .monaco-action-bar .action-item { cursor: pointer; display: inline-block; transition: transform 50ms ease; position: relative; /* DO NOT REMOVE - this is the key to preventing the ghosting icon bug in Chrome 42 */ } .monaco-menu .monaco-action-bar .action-item.disabled { cursor: default; } .monaco-menu .monaco-action-bar .action-item .icon, .monaco-menu .monaco-action-bar .action-item .codicon { display: inline-block; } .monaco-menu .monaco-action-bar .action-item .codicon { display: flex; align-items: center; } .monaco-menu .monaco-action-bar .action-label { font-size: 11px; margin-right: 4px; } .monaco-menu .monaco-action-bar .action-item.disabled .action-label, .monaco-menu .monaco-action-bar .action-item.disabled .action-label:hover { color: var(--vscode-disabledForeground); } /* Vertical actions */ .monaco-menu .monaco-action-bar.vertical { text-align: left; } .monaco-menu .monaco-action-bar.vertical .action-item { display: block; } .monaco-menu .monaco-action-bar.vertical .action-label.separator { display: block; border-bottom: 1px solid var(--vscode-menu-separatorBackground); padding-top: 1px; padding: 30px; } .monaco-menu .secondary-actions .monaco-action-bar .action-label { margin-left: 6px; } /* Action Items */ .monaco-menu .monaco-action-bar .action-item.select-container { overflow: hidden; /* somehow the dropdown overflows its container, we prevent it here to not push */ flex: 1; max-width: 170px; min-width: 60px; display: flex; align-items: center; justify-content: center; margin-right: 10px; } .monaco-menu .monaco-action-bar.vertical { margin-left: 0; overflow: visible; } .monaco-menu .monaco-action-bar.vertical .actions-container { display: block; } .monaco-menu .monaco-action-bar.vertical .action-item { padding: 0; transform: none; display: flex; } .monaco-menu .monaco-action-bar.vertical .action-item.active { transform: none; } .monaco-menu .monaco-action-bar.vertical .action-menu-item { flex: 1 1 auto; display: flex; height: 2em; align-items: center; position: relative; margin: 0 4px; border-radius: 4px; } .monaco-menu .monaco-action-bar.vertical .action-menu-item:hover .keybinding, .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .keybinding { opacity: unset; } .monaco-menu .monaco-action-bar.vertical .action-label { flex: 1 1 auto; text-decoration: none; padding: 0 1em; background: none; font-size: 12px; line-height: 1; } .monaco-menu .monaco-action-bar.vertical .keybinding, .monaco-menu .monaco-action-bar.vertical .submenu-indicator { display: inline-block; flex: 2 1 auto; padding: 0 1em; text-align: right; font-size: 12px; line-height: 1; } .monaco-menu .monaco-action-bar.vertical .submenu-indicator { height: 100%; } .monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon { font-size: 16px !important; display: flex; align-items: center; } .monaco-menu .monaco-action-bar.vertical .submenu-indicator.codicon::before { margin-left: auto; margin-right: -20px; } .monaco-menu .monaco-action-bar.vertical .action-item.disabled .keybinding, .monaco-menu .monaco-action-bar.vertical .action-item.disabled .submenu-indicator { opacity: 0.4; } .monaco-menu .monaco-action-bar.vertical .action-label:not(.separator) { display: inline-block; box-sizing: border-box; margin: 0; } .monaco-menu .monaco-action-bar.vertical .action-item { position: static; overflow: visible; } .monaco-menu .monaco-action-bar.vertical .action-item .monaco-submenu { position: absolute; } .monaco-menu .monaco-action-bar.vertical .action-label.separator { width: 100%; height: 0px !important; opacity: 1; } .monaco-menu .monaco-action-bar.vertical .action-label.separator.text { padding: 0.7em 1em 0.1em 1em; font-weight: bold; opacity: 1; } .monaco-menu .monaco-action-bar.vertical .action-label:hover { color: inherit; } .monaco-menu .monaco-action-bar.vertical .menu-item-check { position: absolute; visibility: hidden; width: 1em; height: 100%; } .monaco-menu .monaco-action-bar.vertical .action-menu-item.checked .menu-item-check { visibility: visible; display: flex; align-items: center; justify-content: center; } /* Context Menu */ .context-view.monaco-menu-container { outline: 0; border: none; animation: fadeIn 0.083s linear; -webkit-app-region: no-drag; } .context-view.monaco-menu-container :focus, .context-view.monaco-menu-container .monaco-action-bar.vertical:focus, .context-view.monaco-menu-container .monaco-action-bar.vertical :focus { outline: 0; } .hc-black .context-view.monaco-menu-container, .hc-light .context-view.monaco-menu-container, :host-context(.hc-black) .context-view.monaco-menu-container, :host-context(.hc-light) .context-view.monaco-menu-container { box-shadow: none; } .hc-black .monaco-menu .monaco-action-bar.vertical .action-item.focused, .hc-light .monaco-menu .monaco-action-bar.vertical .action-item.focused, :host-context(.hc-black) .monaco-menu .monaco-action-bar.vertical .action-item.focused, :host-context(.hc-light) .monaco-menu .monaco-action-bar.vertical .action-item.focused { background: none; } /* Vertical Action Bar Styles */ .monaco-menu .monaco-action-bar.vertical { padding: 4px 0; } .monaco-menu .monaco-action-bar.vertical .action-menu-item { height: 2em; } .monaco-menu .monaco-action-bar.vertical .action-label:not(.separator), .monaco-menu .monaco-action-bar.vertical .keybinding { font-size: inherit; padding: 0 2em; max-height: 100%; } .monaco-menu .monaco-action-bar.vertical .menu-item-check { font-size: inherit; width: 2em; } .monaco-menu .monaco-action-bar.vertical .action-label.separator { font-size: inherit; margin: 5px 0 !important; padding: 0; border-radius: 0; } .linux .monaco-menu .monaco-action-bar.vertical .action-label.separator, :host-context(.linux) .monaco-menu .monaco-action-bar.vertical .action-label.separator { margin-left: 0; margin-right: 0; } .monaco-menu .monaco-action-bar.vertical .submenu-indicator { font-size: 60%; padding: 0 1.8em; } .linux .monaco-menu .monaco-action-bar.vertical .submenu-indicator, :host-context(.linux) .monaco-menu .monaco-action-bar.vertical .submenu-indicator { height: 100%; mask-size: 10px 10px; -webkit-mask-size: 10px 10px; } .monaco-menu .action-item { cursor: default; }`;if(T){M+=` /* Arrows */ .monaco-scrollable-element > .scrollbar > .scra { cursor: pointer; font-size: 11px !important; } .monaco-scrollable-element > .visible { opacity: 1; /* Background rule added for IE9 - to allow clicks on dom node */ background:rgba(0,0,0,0); transition: opacity 100ms linear; } .monaco-scrollable-element > .invisible { opacity: 0; pointer-events: none; } .monaco-scrollable-element > .invisible.fade { transition: opacity 800ms linear; } /* Scrollable Content Inset Shadow */ .monaco-scrollable-element > .shadow { position: absolute; display: none; } .monaco-scrollable-element > .shadow.top { display: block; top: 0; left: 3px; height: 3px; width: 100%; } .monaco-scrollable-element > .shadow.left { display: block; top: 3px; left: 0; height: 100%; width: 3px; } .monaco-scrollable-element > .shadow.top-left-corner { display: block; top: 0; left: 0; height: 3px; width: 3px; } `;const A=D.scrollbarShadow;A&&(M+=` .monaco-scrollable-element > .shadow.top { box-shadow: ${A} 0 6px 6px -6px inset; } .monaco-scrollable-element > .shadow.left { box-shadow: ${A} 6px 0 6px -6px inset; } .monaco-scrollable-element > .shadow.top.left { box-shadow: ${A} 6px 6px 6px -6px inset; } `);const P=D.scrollbarSliderBackground;P&&(M+=` .monaco-scrollable-element > .scrollbar > .slider { background: ${P}; } `);const N=D.scrollbarSliderHoverBackground;N&&(M+=` .monaco-scrollable-element > .scrollbar > .slider:hover { background: ${N}; } `);const O=D.scrollbarSliderActiveBackground;O&&(M+=` .monaco-scrollable-element > .scrollbar > .slider.active { background: ${O}; } `)}return M}}),define(ne[643],se([1,0,87,359,41,26,30,6,2,3,44,477]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ToggleMenuAction=e.ToolBar=void 0;class n extends _.Disposable{constructor(i,s,g={orientation:0}){super(),this.submenuActionViewItems=[],this.hasSecondaryActions=!1,this._onDidChangeDropdownVisibility=this._register(new m.EventMultiplexer),this.onDidChangeDropdownVisibility=this._onDidChangeDropdownVisibility.event,this.disposables=this._register(new _.DisposableStore),g.hoverDelegate=g.hoverDelegate??this._register((0,p.createInstantHoverDelegate)()),this.options=g,this.toggleMenuAction=this._register(new o(()=>this.toggleMenuActionViewItem?.show(),g.toggleMenuTitle)),this.element=document.createElement("div"),this.element.className="monaco-toolbar",i.appendChild(this.element),this.actionBar=this._register(new d.ActionBar(this.element,{orientation:g.orientation,ariaLabel:g.ariaLabel,actionRunner:g.actionRunner,allowContextMenu:g.allowContextMenu,highlightToggledItems:g.highlightToggledItems,hoverDelegate:g.hoverDelegate,actionViewItemProvider:(c,l)=>{if(c.id===o.ID)return this.toggleMenuActionViewItem=new k.DropdownMenuActionViewItem(c,c.menuActions,s,{actionViewItemProvider:this.options.actionViewItemProvider,actionRunner:this.actionRunner,keybindingProvider:this.options.getKeyBinding,classNames:y.ThemeIcon.asClassNameArray(g.moreIcon??E.Codicon.toolBarMore),anchorAlignmentProvider:this.options.anchorAlignmentProvider,menuAsChild:!!this.options.renderDropdownAsChildElement,skipTelemetry:this.options.skipTelemetry,isMenu:!0,hoverDelegate:this.options.hoverDelegate}),this.toggleMenuActionViewItem.setActionContext(this.actionBar.context),this.disposables.add(this._onDidChangeDropdownVisibility.add(this.toggleMenuActionViewItem.onDidChangeVisibility)),this.toggleMenuActionViewItem;if(g.actionViewItemProvider){const a=g.actionViewItemProvider(c,l);if(a)return a}if(c instanceof I.SubmenuAction){const a=new k.DropdownMenuActionViewItem(c,c.actions,s,{actionViewItemProvider:this.options.actionViewItemProvider,actionRunner:this.actionRunner,keybindingProvider:this.options.getKeyBinding,classNames:c.class,anchorAlignmentProvider:this.options.anchorAlignmentProvider,menuAsChild:!!this.options.renderDropdownAsChildElement,skipTelemetry:this.options.skipTelemetry,hoverDelegate:this.options.hoverDelegate});return a.setActionContext(this.actionBar.context),this.submenuActionViewItems.push(a),this.disposables.add(this._onDidChangeDropdownVisibility.add(a.onDidChangeVisibility)),a}}}))}set actionRunner(i){this.actionBar.actionRunner=i}get actionRunner(){return this.actionBar.actionRunner}getElement(){return this.element}getItemAction(i){return this.actionBar.getAction(i)}setActions(i,s){this.clear();const g=i?i.slice(0):[];this.hasSecondaryActions=!!(s&&s.length>0),this.hasSecondaryActions&&s&&(this.toggleMenuAction.menuActions=s.slice(0),g.push(this.toggleMenuAction)),g.forEach(c=>{this.actionBar.push(c,{icon:this.options.icon??!0,label:this.options.label??!1,keybinding:this.getKeybindingLabel(c)})})}getKeybindingLabel(i){return this.options.getKeyBinding?.(i)?.getLabel()??void 0}clear(){this.submenuActionViewItems=[],this.disposables.clear(),this.actionBar.clear()}dispose(){this.clear(),this.disposables.dispose(),super.dispose()}}e.ToolBar=n;class o extends I.Action{static{this.ID="toolbar.toggle.more"}constructor(i,s){s=s||b.localize(17,"More Actions..."),super(o.ID,s,void 0,!0),this._menuActions=[],this.toggleDropdownMenu=i}async run(){this.toggleDropdownMenu()}get menuActions(){return this._menuActions}set menuActions(i){this._menuActions=i}}e.ToggleMenuAction=o}),define(ne[176],se([1,0,5,93,47,87,260,259,257,115,175,249,159,41,13,14,26,30,45,6,82,2,141,19,3,44,21,46,478]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractTree=e.TreeFindMatchType=e.TreeFindMode=e.FuzzyToggle=e.ModeToggle=e.TreeRenderer=e.RenderIndentGuides=e.ComposedTreeDelegate=void 0;class L extends _.ElementsDragAndDropData{constructor(B){super(B.elements.map($=>$.element)),this.data=B}}function D(X){return X instanceof _.ElementsDragAndDropData?new L(X):X}class T{constructor(B,$){this.modelProvider=B,this.dnd=$,this.autoExpandDisposable=u.Disposable.None,this.disposables=new u.DisposableStore}getDragURI(B){return this.dnd.getDragURI(B.element)}getDragLabel(B,$){if(this.dnd.getDragLabel)return this.dnd.getDragLabel(B.map(Q=>Q.element),$)}onDragStart(B,$){this.dnd.onDragStart?.(D(B),$)}onDragOver(B,$,Q,Z,te,re=!0){const le=this.dnd.onDragOver(D(B),$&&$.element,Q,Z,te),me=this.autoExpandNode!==$;if(me&&(this.autoExpandDisposable.dispose(),this.autoExpandNode=$),typeof $>"u")return le;if(me&&typeof le!="boolean"&&le.autoExpand&&(this.autoExpandDisposable=(0,s.disposableTimeout)(()=>{const Me=this.modelProvider(),Ae=Me.getNodeLocation($);Me.isCollapsed(Ae)&&Me.setCollapsed(Ae,!1),this.autoExpandNode=void 0},500,this.disposables)),typeof le=="boolean"||!le.accept||typeof le.bubble>"u"||le.feedback){if(!re){const Me=typeof le=="boolean"?le:le.accept,Ae=typeof le=="boolean"?void 0:le.effect;return{accept:Me,effect:Ae,feedback:[Q]}}return le}if(le.bubble===1){const Me=this.modelProvider(),Ae=Me.getNodeLocation($),Ne=Me.getParentNodeLocation(Ae),Ke=Me.getNode(Ne),ze=Ne&&Me.getListIndex(Ne);return this.onDragOver(B,Ke,ze,Z,te,!1)}const Ce=this.modelProvider(),ye=Ce.getNodeLocation($),Le=Ce.getListIndex(ye),Ee=Ce.getListRenderCount(ye);return{...le,feedback:(0,i.range)(Le,Le+Ee)}}drop(B,$,Q,Z,te){this.autoExpandDisposable.dispose(),this.autoExpandNode=void 0,this.dnd.drop(D(B),$&&$.element,Q,Z,te)}onDragEnd(B){this.dnd.onDragEnd?.(B)}dispose(){this.disposables.dispose(),this.dnd.dispose()}}function M(X,B){return B&&{...B,identityProvider:B.identityProvider&&{getId($){return B.identityProvider.getId($.element)}},dnd:B.dnd&&new T(X,B.dnd),multipleSelectionController:B.multipleSelectionController&&{isSelectionSingleChangeEvent($){return B.multipleSelectionController.isSelectionSingleChangeEvent({...$,element:$.element})},isSelectionRangeChangeEvent($){return B.multipleSelectionController.isSelectionRangeChangeEvent({...$,element:$.element})}},accessibilityProvider:B.accessibilityProvider&&{...B.accessibilityProvider,getSetSize($){const Q=X(),Z=Q.getNodeLocation($),te=Q.getParentNodeLocation(Z);return Q.getNode(te).visibleChildrenCount},getPosInSet($){return $.visibleChildIndex+1},isChecked:B.accessibilityProvider&&B.accessibilityProvider.isChecked?$=>B.accessibilityProvider.isChecked($.element):void 0,getRole:B.accessibilityProvider&&B.accessibilityProvider.getRole?$=>B.accessibilityProvider.getRole($.element):()=>"treeitem",getAriaLabel($){return B.accessibilityProvider.getAriaLabel($.element)},getWidgetAriaLabel(){return B.accessibilityProvider.getWidgetAriaLabel()},getWidgetRole:B.accessibilityProvider&&B.accessibilityProvider.getWidgetRole?()=>B.accessibilityProvider.getWidgetRole():()=>"tree",getAriaLevel:B.accessibilityProvider&&B.accessibilityProvider.getAriaLevel?$=>B.accessibilityProvider.getAriaLevel($.element):$=>$.depth,getActiveDescendantId:B.accessibilityProvider.getActiveDescendantId&&($=>B.accessibilityProvider.getActiveDescendantId($.element))},keyboardNavigationLabelProvider:B.keyboardNavigationLabelProvider&&{...B.keyboardNavigationLabelProvider,getKeyboardNavigationLabel($){return B.keyboardNavigationLabelProvider.getKeyboardNavigationLabel($.element)}}}}class A{constructor(B){this.delegate=B}getHeight(B){return this.delegate.getHeight(B.element)}getTemplateId(B){return this.delegate.getTemplateId(B.element)}hasDynamicHeight(B){return!!this.delegate.hasDynamicHeight&&this.delegate.hasDynamicHeight(B.element)}setDynamicHeight(B,$){this.delegate.setDynamicHeight?.(B.element,$)}}e.ComposedTreeDelegate=A;var P;(function(X){X.None="none",X.OnHover="onHover",X.Always="always"})(P||(e.RenderIndentGuides=P={}));class N{get elements(){return this._elements}constructor(B,$=[]){this._elements=$,this.disposables=new u.DisposableStore,this.onDidChange=a.Event.forEach(B,Q=>this._elements=Q,this.disposables)}dispose(){this.disposables.dispose()}}class O{static{this.DefaultIndent=8}constructor(B,$,Q,Z,te,re={}){this.renderer=B,this.modelProvider=$,this.activeNodes=Z,this.renderedIndentGuides=te,this.renderedElements=new Map,this.renderedNodes=new Map,this.indent=O.DefaultIndent,this.hideTwistiesOfChildlessElements=!1,this.shouldRenderIndentGuides=!1,this.activeIndentNodes=new Set,this.indentGuidesDisposable=u.Disposable.None,this.disposables=new u.DisposableStore,this.templateId=B.templateId,this.updateOptions(re),a.Event.map(Q,le=>le.node)(this.onDidChangeNodeTwistieState,this,this.disposables),B.onDidChangeTwistieState?.(this.onDidChangeTwistieState,this,this.disposables)}updateOptions(B={}){if(typeof B.indent<"u"){const $=(0,C.clamp)(B.indent,0,40);if($!==this.indent){this.indent=$;for(const[Q,Z]of this.renderedNodes)this.renderTreeElement(Q,Z)}}if(typeof B.renderIndentGuides<"u"){const $=B.renderIndentGuides!==P.None;if($!==this.shouldRenderIndentGuides){this.shouldRenderIndentGuides=$;for(const[Q,Z]of this.renderedNodes)this._renderIndentGuides(Q,Z);if(this.indentGuidesDisposable.dispose(),$){const Q=new u.DisposableStore;this.activeNodes.onDidChange(this._onDidChangeActiveNodes,this,Q),this.indentGuidesDisposable=Q,this._onDidChangeActiveNodes(this.activeNodes.elements)}}}typeof B.hideTwistiesOfChildlessElements<"u"&&(this.hideTwistiesOfChildlessElements=B.hideTwistiesOfChildlessElements)}renderTemplate(B){const $=(0,d.append)(B,(0,d.$)(".monaco-tl-row")),Q=(0,d.append)($,(0,d.$)(".monaco-tl-indent")),Z=(0,d.append)($,(0,d.$)(".monaco-tl-twistie")),te=(0,d.append)($,(0,d.$)(".monaco-tl-contents")),re=this.renderer.renderTemplate(te);return{container:B,indent:Q,twistie:Z,indentGuidesDisposable:u.Disposable.None,templateData:re}}renderElement(B,$,Q,Z){this.renderedNodes.set(B,Q),this.renderedElements.set(B.element,B),this.renderTreeElement(B,Q),this.renderer.renderElement(B,$,Q.templateData,Z)}disposeElement(B,$,Q,Z){Q.indentGuidesDisposable.dispose(),this.renderer.disposeElement?.(B,$,Q.templateData,Z),typeof Z=="number"&&(this.renderedNodes.delete(B),this.renderedElements.delete(B.element))}disposeTemplate(B){this.renderer.disposeTemplate(B.templateData)}onDidChangeTwistieState(B){const $=this.renderedElements.get(B);$&&this.onDidChangeNodeTwistieState($)}onDidChangeNodeTwistieState(B){const $=this.renderedNodes.get(B);$&&(this._onDidChangeActiveNodes(this.activeNodes.elements),this.renderTreeElement(B,$))}renderTreeElement(B,$){const Q=O.DefaultIndent+(B.depth-1)*this.indent;$.twistie.style.paddingLeft=`${Q}px`,$.indent.style.width=`${Q+this.indent-16}px`,B.collapsible?$.container.setAttribute("aria-expanded",String(!B.collapsed)):$.container.removeAttribute("aria-expanded"),$.twistie.classList.remove(...c.ThemeIcon.asClassNameArray(g.Codicon.treeItemExpanded));let Z=!1;this.renderer.renderTwistie&&(Z=this.renderer.renderTwistie(B.element,$.twistie)),B.collapsible&&(!this.hideTwistiesOfChildlessElements||B.visibleChildrenCount>0)?(Z||$.twistie.classList.add(...c.ThemeIcon.asClassNameArray(g.Codicon.treeItemExpanded)),$.twistie.classList.add("collapsible"),$.twistie.classList.toggle("collapsed",B.collapsed)):$.twistie.classList.remove("collapsible","collapsed"),this._renderIndentGuides(B,$)}_renderIndentGuides(B,$){if((0,d.clearNode)($.indent),$.indentGuidesDisposable.dispose(),!this.shouldRenderIndentGuides)return;const Q=new u.DisposableStore,Z=this.modelProvider();for(;;){const te=Z.getNodeLocation(B),re=Z.getParentNodeLocation(te);if(!re)break;const le=Z.getNode(re),me=(0,d.$)(".indent-guide",{style:`width: ${this.indent}px`});this.activeIndentNodes.has(le)&&me.classList.add("active"),$.indent.childElementCount===0?$.indent.appendChild(me):$.indent.insertBefore(me,$.indent.firstElementChild),this.renderedIndentGuides.add(le,me),Q.add((0,u.toDisposable)(()=>this.renderedIndentGuides.delete(le,me))),B=le}$.indentGuidesDisposable=Q}_onDidChangeActiveNodes(B){if(!this.shouldRenderIndentGuides)return;const $=new Set,Q=this.modelProvider();B.forEach(Z=>{const te=Q.getNodeLocation(Z);try{const re=Q.getParentNodeLocation(te);Z.collapsible&&Z.children.length>0&&!Z.collapsed?$.add(Z):re&&$.add(Q.getNode(re))}catch{}}),this.activeIndentNodes.forEach(Z=>{$.has(Z)||this.renderedIndentGuides.forEach(Z,te=>te.classList.remove("active"))}),$.forEach(Z=>{this.activeIndentNodes.has(Z)||this.renderedIndentGuides.forEach(Z,te=>te.classList.add("active"))}),this.activeIndentNodes=$}dispose(){this.renderedNodes.clear(),this.renderedElements.clear(),this.indentGuidesDisposable.dispose(),(0,u.dispose)(this.disposables)}}e.TreeRenderer=O;class F{get totalCount(){return this._totalCount}get matchCount(){return this._matchCount}constructor(B,$,Q){this.tree=B,this.keyboardNavigationLabelProvider=$,this._filter=Q,this._totalCount=0,this._matchCount=0,this._pattern="",this._lowercasePattern="",this.disposables=new u.DisposableStore,B.onWillRefilter(this.reset,this,this.disposables)}filter(B,$){let Q=1;if(this._filter){const re=this._filter.filter(B,$);if(typeof re=="boolean"?Q=re?1:0:(0,n.isFilterResult)(re)?Q=(0,n.getVisibleState)(re.visibility):Q=re,Q===0)return!1}if(this._totalCount++,!this._pattern)return this._matchCount++,{data:r.FuzzyScore.Default,visibility:Q};const Z=this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(B),te=Array.isArray(Z)?Z:[Z];for(const re of te){const le=re&&re.toString();if(typeof le>"u")return{data:r.FuzzyScore.Default,visibility:Q};let me;if(this.tree.findMatchType===H.Contiguous){const Ce=le.toLowerCase().indexOf(this._lowercasePattern);if(Ce>-1){me=[Number.MAX_SAFE_INTEGER,0];for(let ye=this._lowercasePattern.length;ye>0;ye--)me.push(Ce+ye-1)}}else me=(0,r.fuzzyScore)(this._pattern,this._lowercasePattern,0,le,le.toLowerCase(),0,{firstMatchCanBeWeak:!0,boostFullMatch:!0});if(me)return this._matchCount++,te.length===1?{data:me,visibility:Q}:{data:{label:le,score:me},visibility:Q}}return this.tree.findMode===q.Filter?typeof this.tree.options.defaultFindVisibility=="number"?this.tree.options.defaultFindVisibility:this.tree.options.defaultFindVisibility?this.tree.options.defaultFindVisibility(B):2:{data:r.FuzzyScore.Default,visibility:Q}}reset(){this._totalCount=0,this._matchCount=0}dispose(){(0,u.dispose)(this.disposables)}}class x extends p.Toggle{constructor(B){super({icon:g.Codicon.listFilter,title:(0,h.localize)(18,"Filter"),isChecked:B.isChecked??!1,hoverDelegate:B.hoverDelegate??(0,v.getDefaultHoverDelegate)("element"),inputActiveOptionBorder:B.inputActiveOptionBorder,inputActiveOptionForeground:B.inputActiveOptionForeground,inputActiveOptionBackground:B.inputActiveOptionBackground})}}e.ModeToggle=x;class W extends p.Toggle{constructor(B){super({icon:g.Codicon.searchFuzzy,title:(0,h.localize)(19,"Fuzzy Match"),isChecked:B.isChecked??!1,hoverDelegate:B.hoverDelegate??(0,v.getDefaultHoverDelegate)("element"),inputActiveOptionBorder:B.inputActiveOptionBorder,inputActiveOptionForeground:B.inputActiveOptionForeground,inputActiveOptionBackground:B.inputActiveOptionBackground})}}e.FuzzyToggle=W;const V={inputBoxStyles:m.unthemedInboxStyles,toggleStyles:p.unthemedToggleStyles,listFilterWidgetBackground:void 0,listFilterWidgetNoMatchesOutline:void 0,listFilterWidgetOutline:void 0,listFilterWidgetShadow:void 0};var q;(function(X){X[X.Highlight=0]="Highlight",X[X.Filter=1]="Filter"})(q||(e.TreeFindMode=q={}));var H;(function(X){X[X.Fuzzy=0]="Fuzzy",X[X.Contiguous=1]="Contiguous"})(H||(e.TreeFindMatchType=H={}));class z extends u.Disposable{set mode(B){this.modeToggle.checked=B===q.Filter,this.findInput.inputBox.setPlaceHolder(B===q.Filter?(0,h.localize)(20,"Type to filter"):(0,h.localize)(21,"Type to search"))}set matchType(B){this.matchTypeToggle.checked=B===H.Fuzzy}constructor(B,$,Q,Z,te,re){super(),this.tree=$,this.elements=(0,d.h)(".monaco-tree-type-filter",[(0,d.h)(".monaco-tree-type-filter-grab.codicon.codicon-debug-gripper@grab",{tabIndex:0}),(0,d.h)(".monaco-tree-type-filter-input@findInput"),(0,d.h)(".monaco-tree-type-filter-actionbar@actionbar")]),this.width=0,this.right=0,this.top=0,this._onDidDisable=new a.Emitter,B.appendChild(this.elements.root),this._register((0,u.toDisposable)(()=>this.elements.root.remove()));const le=re?.styles??V;le.listFilterWidgetBackground&&(this.elements.root.style.backgroundColor=le.listFilterWidgetBackground),le.listFilterWidgetShadow&&(this.elements.root.style.boxShadow=`0 0 8px 2px ${le.listFilterWidgetShadow}`);const me=this._register((0,v.createInstantHoverDelegate)());this.modeToggle=this._register(new x({...le.toggleStyles,isChecked:Z===q.Filter,hoverDelegate:me})),this.matchTypeToggle=this._register(new W({...le.toggleStyles,isChecked:te===H.Fuzzy,hoverDelegate:me})),this.onDidChangeMode=a.Event.map(this.modeToggle.onChange,()=>this.modeToggle.checked?q.Filter:q.Highlight,this._store),this.onDidChangeMatchType=a.Event.map(this.matchTypeToggle.onChange,()=>this.matchTypeToggle.checked?H.Fuzzy:H.Contiguous,this._store),this.findInput=this._register(new y.FindInput(this.elements.findInput,Q,{label:(0,h.localize)(22,"Type to search"),additionalToggles:[this.modeToggle,this.matchTypeToggle],showCommonFindToggles:!1,inputBoxStyles:le.inputBoxStyles,toggleStyles:le.toggleStyles,history:re?.history})),this.actionbar=this._register(new E.ActionBar(this.elements.actionbar)),this.mode=Z;const Ce=this._register(new k.DomEmitter(this.findInput.inputBox.inputElement,"keydown")),ye=a.Event.chain(Ce.event,Ae=>Ae.map(Ne=>new I.StandardKeyboardEvent(Ne)));this._register(ye(Ae=>{if(Ae.equals(3)){Ae.preventDefault(),Ae.stopPropagation(),this.findInput.inputBox.addToHistory(),this.tree.domFocus();return}if(Ae.equals(18)){Ae.preventDefault(),Ae.stopPropagation(),this.findInput.inputBox.isAtLastInHistory()||this.findInput.inputBox.isNowhereInHistory()?(this.findInput.inputBox.addToHistory(),this.tree.domFocus()):this.findInput.inputBox.showNextValue();return}if(Ae.equals(16)){Ae.preventDefault(),Ae.stopPropagation(),this.findInput.inputBox.showPreviousValue();return}}));const Le=this._register(new t.Action("close",(0,h.localize)(23,"Close"),"codicon codicon-close",!0,()=>this.dispose()));this.actionbar.push(Le,{icon:!0,label:!1});const Ee=this._register(new k.DomEmitter(this.elements.grab,"mousedown"));this._register(Ee.event(Ae=>{const Ne=new u.DisposableStore,Ke=Ne.add(new k.DomEmitter((0,d.getWindow)(Ae),"mousemove")),ze=Ne.add(new k.DomEmitter((0,d.getWindow)(Ae),"mouseup")),Ge=this.right,it=Ae.pageX,Oe=this.top,Fe=Ae.pageY;this.elements.grab.classList.add("grabbing");const fe=this.elements.root.style.transition;this.elements.root.style.transition="unset";const _e=xe=>{const be=xe.pageX-it;this.right=Ge-be;const ve=xe.pageY-Fe;this.top=Oe+ve,this.layout()};Ne.add(Ke.event(_e)),Ne.add(ze.event(xe=>{_e(xe),this.elements.grab.classList.remove("grabbing"),this.elements.root.style.transition=fe,Ne.dispose()}))}));const Me=a.Event.chain(this._register(new k.DomEmitter(this.elements.grab,"keydown")).event,Ae=>Ae.map(Ne=>new I.StandardKeyboardEvent(Ne)));this._register(Me(Ae=>{let Ne,Ke;if(Ae.keyCode===15?Ne=Number.POSITIVE_INFINITY:Ae.keyCode===17?Ne=0:Ae.keyCode===10&&(Ne=this.right===0?Number.POSITIVE_INFINITY:0),Ae.keyCode===16?Ke=0:Ae.keyCode===18&&(Ke=Number.POSITIVE_INFINITY),Ne!==void 0&&(Ae.preventDefault(),Ae.stopPropagation(),this.right=Ne,this.layout()),Ke!==void 0){Ae.preventDefault(),Ae.stopPropagation(),this.top=Ke;const ze=this.elements.root.style.transition;this.elements.root.style.transition="unset",this.layout(),setTimeout(()=>{this.elements.root.style.transition=ze},0)}})),this.onDidChangeValue=this.findInput.onDidChange}layout(B=this.width){this.width=B,this.right=(0,C.clamp)(this.right,0,Math.max(0,B-212)),this.elements.root.style.right=`${this.right}px`,this.top=(0,C.clamp)(this.top,0,24),this.elements.root.style.top=`${this.top}px`}showMessage(B){this.findInput.showMessage(B)}clearMessage(){this.findInput.clearMessage()}async dispose(){this._onDidDisable.fire(),this.elements.root.classList.add("disabled"),await(0,s.timeout)(300),super.dispose()}}class U{get pattern(){return this._pattern}get mode(){return this._mode}set mode(B){B!==this._mode&&(this._mode=B,this.widget&&(this.widget.mode=this._mode),this.tree.refilter(),this.render(),this._onDidChangeMode.fire(B))}get matchType(){return this._matchType}set matchType(B){B!==this._matchType&&(this._matchType=B,this.widget&&(this.widget.matchType=this._matchType),this.tree.refilter(),this.render(),this._onDidChangeMatchType.fire(B))}constructor(B,$,Q,Z,te,re={}){this.tree=B,this.view=Q,this.filter=Z,this.contextViewProvider=te,this.options=re,this._pattern="",this.width=0,this._onDidChangeMode=new a.Emitter,this.onDidChangeMode=this._onDidChangeMode.event,this._onDidChangeMatchType=new a.Emitter,this.onDidChangeMatchType=this._onDidChangeMatchType.event,this._onDidChangePattern=new a.Emitter,this._onDidChangeOpenState=new a.Emitter,this.onDidChangeOpenState=this._onDidChangeOpenState.event,this.enabledDisposables=new u.DisposableStore,this.disposables=new u.DisposableStore,this._mode=B.options.defaultFindMode??q.Highlight,this._matchType=B.options.defaultFindMatchType??H.Fuzzy,$.onDidSplice(this.onDidSpliceModel,this,this.disposables)}updateOptions(B={}){B.defaultFindMode!==void 0&&(this.mode=B.defaultFindMode),B.defaultFindMatchType!==void 0&&(this.matchType=B.defaultFindMatchType)}onDidSpliceModel(){!this.widget||this.pattern.length===0||(this.tree.refilter(),this.render())}render(){const B=this.filter.totalCount>0&&this.filter.matchCount===0;this.pattern&&B?((0,S.alert)((0,h.localize)(24,"No results")),this.tree.options.showNotFoundMessage??!0?this.widget?.showMessage({type:2,content:(0,h.localize)(25,"No elements found.")}):this.widget?.showMessage({type:2})):(this.widget?.clearMessage(),this.pattern&&(0,S.alert)((0,h.localize)(26,"{0} results",this.filter.matchCount)))}shouldAllowFocus(B){return!this.widget||!this.pattern||this.filter.totalCount>0&&this.filter.matchCount<=1?!0:!r.FuzzyScore.isDefault(B.filterData)}layout(B){this.width=B,this.widget?.layout(B)}dispose(){this._history=void 0,this._onDidChangePattern.dispose(),this.enabledDisposables.dispose(),this.disposables.dispose()}}function j(X,B){return X.position===B.position&&Y(X,B)}function Y(X,B){return X.node.element===B.node.element&&X.startIndex===B.startIndex&&X.height===B.height&&X.endIndex===B.endIndex}class G{constructor(B=[]){this.stickyNodes=B}get count(){return this.stickyNodes.length}equal(B){return(0,i.equals)(this.stickyNodes,B.stickyNodes,j)}lastNodePartiallyVisible(){if(this.count===0)return!1;const B=this.stickyNodes[this.count-1];if(this.count===1)return B.position!==0;const $=this.stickyNodes[this.count-2];return $.position+$.height!==B.position}animationStateChanged(B){if(!(0,i.equals)(this.stickyNodes,B.stickyNodes,Y)||this.count===0)return!1;const $=this.stickyNodes[this.count-1],Q=B.stickyNodes[B.count-1];return $.position!==Q.position}}class K{constrainStickyScrollNodes(B,$,Q){for(let Z=0;ZQ||Z>=$)return B.slice(0,Z)}return B}}class R extends u.Disposable{constructor(B,$,Q,Z,te,re={}){super(),this.tree=B,this.model=$,this.view=Q,this.treeDelegate=te,this.maxWidgetViewRatio=.4;const le=this.validateStickySettings(re);this.stickyScrollMaxItemCount=le.stickyScrollMaxItemCount,this.stickyScrollDelegate=re.stickyScrollDelegate??new K,this._widget=this._register(new J(Q.getScrollableElement(),Q,B,Z,te,re.accessibilityProvider)),this.onDidChangeHasFocus=this._widget.onDidChangeHasFocus,this.onContextMenu=this._widget.onContextMenu,this._register(Q.onDidScroll(()=>this.update())),this._register(Q.onDidChangeContentHeight(()=>this.update())),this._register(B.onDidChangeCollapseState(()=>this.update())),this.update()}get height(){return this._widget.height}getNodeAtHeight(B){let $;if(B===0?$=this.view.firstVisibleIndex:$=this.view.indexAt(B+this.view.scrollTop),!($<0||$>=this.view.length))return this.view.element($)}update(){const B=this.getNodeAtHeight(0);if(!B||this.tree.scrollTop===0){this._widget.setState(void 0);return}const $=this.findStickyState(B);this._widget.setState($)}findStickyState(B){const $=[];let Q=B,Z=0,te=this.getNextStickyNode(Q,void 0,Z);for(;te&&($.push(te),Z+=te.height,!($.length<=this.stickyScrollMaxItemCount&&(Q=this.getNextVisibleNode(te),!Q)));)te=this.getNextStickyNode(Q,te.node,Z);const re=this.constrainStickyNodes($);return re.length?new G(re):void 0}getNextVisibleNode(B){return this.getNodeAtHeight(B.position+B.height)}getNextStickyNode(B,$,Q){const Z=this.getAncestorUnderPrevious(B,$);if(Z&&!(Z===B&&(!this.nodeIsUncollapsedParent(B)||this.nodeTopAlignsWithStickyNodesBottom(B,Q))))return this.createStickyScrollNode(Z,Q)}nodeTopAlignsWithStickyNodesBottom(B,$){const Q=this.getNodeIndex(B),Z=this.view.getElementTop(Q),te=$;return this.view.scrollTop===Z-te}createStickyScrollNode(B,$){const Q=this.treeDelegate.getHeight(B),{startIndex:Z,endIndex:te}=this.getNodeRange(B),re=this.calculateStickyNodePosition(te,$,Q);return{node:B,position:re,height:Q,startIndex:Z,endIndex:te}}getAncestorUnderPrevious(B,$=void 0){let Q=B,Z=this.getParentNode(Q);for(;Z;){if(Z===$)return Q;Q=Z,Z=this.getParentNode(Q)}if($===void 0)return Q}calculateStickyNodePosition(B,$,Q){let Z=this.view.getRelativeTop(B);if(Z===null&&this.view.firstVisibleIndex===B&&B+1me&&$<=me?me-Q:$}constrainStickyNodes(B){if(B.length===0)return[];const $=this.view.renderHeight*this.maxWidgetViewRatio,Q=B[B.length-1];if(B.length<=this.stickyScrollMaxItemCount&&Q.position+Q.height<=$)return B;const Z=this.stickyScrollDelegate.constrainStickyScrollNodes(B,this.stickyScrollMaxItemCount,$);if(!Z.length)return[];const te=Z[Z.length-1];if(Z.length>this.stickyScrollMaxItemCount||te.position+te.height>$)throw new Error("stickyScrollDelegate violates constraints");return Z}getParentNode(B){const $=this.model.getNodeLocation(B),Q=this.model.getParentNodeLocation($);return Q?this.model.getNode(Q):void 0}nodeIsUncollapsedParent(B){const $=this.model.getNodeLocation(B);return this.model.getListRenderCount($)>1}getNodeIndex(B){const $=this.model.getNodeLocation(B);return this.model.getListIndex($)}getNodeRange(B){const $=this.model.getNodeLocation(B),Q=this.model.getListIndex($);if(Q<0)throw new Error("Node not found in tree");const Z=this.model.getListRenderCount($),te=Q+Z-1;return{startIndex:Q,endIndex:te}}nodePositionTopBelowWidget(B){const $=[];let Q=this.getParentNode(B);for(;Q;)$.push(Q),Q=this.getParentNode(Q);let Z=0;for(let te=0;te<$.length&&te0,Q=!!B&&B.count>0;if(!$&&!Q||$&&Q&&this._previousState.equal(B))return;if($!==Q&&this.setVisible(Q),!Q){this._previousState=void 0,this._previousElements=[],this._previousStateDisposables.clear();return}const Z=B.stickyNodes[B.count-1];if(this._previousState&&B.animationStateChanged(this._previousState))this._previousElements[this._previousState.count-1].style.top=`${Z.position}px`;else{this._previousStateDisposables.clear();const te=Array(B.count);for(let re=B.count-1;re>=0;re--){const le=B.stickyNodes[re],{element:me,disposable:Ce}=this.createElement(le,re,B.count);te[re]=me,this._rootDomNode.appendChild(me),this._previousStateDisposables.add(Ce)}this.stickyScrollFocus.updateElements(te,B),this._previousElements=te}this._previousState=B,this._rootDomNode.style.height=`${Z.position+Z.height}px`}createElement(B,$,Q){const Z=B.startIndex,te=document.createElement("div");te.style.top=`${B.position}px`,this.tree.options.setRowHeight!==!1&&(te.style.height=`${B.height}px`),this.tree.options.setRowLineHeight!==!1&&(te.style.lineHeight=`${B.height}px`),te.classList.add("monaco-tree-sticky-row"),te.classList.add("monaco-list-row"),te.setAttribute("data-index",`${Z}`),te.setAttribute("data-parity",Z%2===0?"even":"odd"),te.setAttribute("id",this.view.getElementID(Z));const re=this.setAccessibilityAttributes(te,B.node.element,$,Q),le=this.treeDelegate.getTemplateId(B.node),me=this.treeRenderers.find(Ee=>Ee.templateId===le);if(!me)throw new Error(`No renderer found for template id ${le}`);let Ce=B.node;Ce===this.tree.getNode(this.tree.getNodeLocation(B.node))&&(Ce=new Proxy(B.node,{}));const ye=me.renderTemplate(te);me.renderElement(Ce,B.startIndex,ye,B.height);const Le=(0,u.toDisposable)(()=>{re.dispose(),me.disposeElement(Ce,B.startIndex,ye,B.height),me.disposeTemplate(ye),te.remove()});return{element:te,disposable:Le}}setAccessibilityAttributes(B,$,Q,Z){if(!this.accessibilityProvider)return u.Disposable.None;this.accessibilityProvider.getSetSize&&B.setAttribute("aria-setsize",String(this.accessibilityProvider.getSetSize($,Q,Z))),this.accessibilityProvider.getPosInSet&&B.setAttribute("aria-posinset",String(this.accessibilityProvider.getPosInSet($,Q))),this.accessibilityProvider.getRole&&B.setAttribute("role",this.accessibilityProvider.getRole($)??"treeitem");const te=this.accessibilityProvider.getAriaLabel($),re=te&&typeof te!="string"?te:(0,w.constObservable)(te),le=(0,w.autorun)(Ce=>{const ye=Ce.readObservable(re);ye?B.setAttribute("aria-label",ye):B.removeAttribute("aria-label")});typeof te=="string"||te&&B.setAttribute("aria-label",te.get());const me=this.accessibilityProvider.getAriaLevel&&this.accessibilityProvider.getAriaLevel($);return typeof me=="number"&&B.setAttribute("aria-level",`${me}`),B.setAttribute("aria-selected",String(!1)),le}setVisible(B){this._rootDomNode.classList.toggle("empty",!B),B||this.stickyScrollFocus.updateElements([],void 0)}domFocus(){this.stickyScrollFocus.domFocus()}focusedLast(){return this.stickyScrollFocus.focusedLast()}dispose(){this.stickyScrollFocus.dispose(),this._previousStateDisposables.dispose(),this._rootDomNode.remove()}}class ie extends u.Disposable{get domHasFocus(){return this._domHasFocus}set domHasFocus(B){B!==this._domHasFocus&&(this._onDidChangeHasFocus.fire(B),this._domHasFocus=B)}constructor(B,$){super(),this.container=B,this.view=$,this.focusedIndex=-1,this.elements=[],this._onDidChangeHasFocus=new a.Emitter,this.onDidChangeHasFocus=this._onDidChangeHasFocus.event,this._onContextMenu=new a.Emitter,this.onContextMenu=this._onContextMenu.event,this._domHasFocus=!1,this._register((0,d.addDisposableListener)(this.container,"focus",()=>this.onFocus())),this._register((0,d.addDisposableListener)(this.container,"blur",()=>this.onBlur())),this._register(this.view.onDidFocus(()=>this.toggleStickyScrollFocused(!1))),this._register(this.view.onKeyDown(Q=>this.onKeyDown(Q))),this._register(this.view.onMouseDown(Q=>this.onMouseDown(Q))),this._register(this.view.onContextMenu(Q=>this.handleContextMenu(Q)))}handleContextMenu(B){const $=B.browserEvent.target;if(!(0,b.isStickyScrollContainer)($)&&!(0,b.isStickyScrollElement)($)){this.focusedLast()&&this.view.domFocus();return}if(!(0,d.isKeyboardEvent)(B.browserEvent)){if(!this.state)throw new Error("Context menu should not be triggered when state is undefined");const re=this.state.stickyNodes.findIndex(le=>le.node.element===B.element?.element);if(re===-1)throw new Error("Context menu should not be triggered when element is not in sticky scroll widget");this.container.focus(),this.setFocus(re);return}if(!this.state||this.focusedIndex<0)throw new Error("Context menu key should not be triggered when focus is not in sticky scroll widget");const Z=this.state.stickyNodes[this.focusedIndex].node.element,te=this.elements[this.focusedIndex];this._onContextMenu.fire({element:Z,anchor:te,browserEvent:B.browserEvent,isStickyScroll:!0})}onKeyDown(B){if(this.domHasFocus&&this.state){if(B.key==="ArrowUp")this.setFocusedElement(Math.max(0,this.focusedIndex-1)),B.preventDefault(),B.stopPropagation();else if(B.key==="ArrowDown"||B.key==="ArrowRight"){if(this.focusedIndex>=this.state.count-1){const $=this.state.stickyNodes[this.state.count-1].startIndex+1;this.view.domFocus(),this.view.setFocus([$]),this.scrollNodeUnderWidget($,this.state)}else this.setFocusedElement(this.focusedIndex+1);B.preventDefault(),B.stopPropagation()}}}onMouseDown(B){const $=B.browserEvent.target;!(0,b.isStickyScrollContainer)($)&&!(0,b.isStickyScrollElement)($)||(B.browserEvent.preventDefault(),B.browserEvent.stopPropagation())}updateElements(B,$){if($&&$.count===0)throw new Error("Sticky scroll state must be undefined when there are no sticky nodes");if($&&$.count!==B.length)throw new Error("Sticky scroll focus received illigel state");const Q=this.focusedIndex;if(this.removeFocus(),this.elements=B,this.state=$,$){const Z=(0,C.clamp)(Q,0,$.count-1);this.setFocus(Z)}else this.domHasFocus&&this.view.domFocus();this.container.tabIndex=$?0:-1}setFocusedElement(B){const $=this.state;if(!$)throw new Error("Cannot set focus when state is undefined");if(this.setFocus(B),!(B<$.count-1)&&$.lastNodePartiallyVisible()){const Q=$.stickyNodes[B];this.scrollNodeUnderWidget(Q.endIndex+1,$)}}scrollNodeUnderWidget(B,$){const Q=$.stickyNodes[$.count-1],Z=$.count>1?$.stickyNodes[$.count-2]:void 0,te=this.view.getElementTop(B),re=Z?Z.position+Z.height+Q.height:Q.height;this.view.scrollTop=te-re}domFocus(){if(!this.state)throw new Error("Cannot focus when state is undefined");this.container.focus()}focusedLast(){return this.state?this.view.getHTMLElement().classList.contains("sticky-scroll-focused"):!1}removeFocus(){this.focusedIndex!==-1&&(this.toggleElementFocus(this.elements[this.focusedIndex],!1),this.focusedIndex=-1)}setFocus(B){if(0>B)throw new Error("addFocus() can not remove focus");if(!this.state&&B>=0)throw new Error("Cannot set focus index when state is undefined");if(this.state&&B>=this.state.count)throw new Error("Cannot set focus index to an index that does not exist");const $=this.focusedIndex;$>=0&&this.toggleElementFocus(this.elements[$],!1),B>=0&&this.toggleElementFocus(this.elements[B],!0),this.focusedIndex=B}toggleElementFocus(B,$){this.toggleElementActiveFocus(B,$&&this.domHasFocus),this.toggleElementPassiveFocus(B,$)}toggleCurrentElementActiveFocus(B){this.focusedIndex!==-1&&this.toggleElementActiveFocus(this.elements[this.focusedIndex],B)}toggleElementActiveFocus(B,$){B.classList.toggle("focused",$)}toggleElementPassiveFocus(B,$){B.classList.toggle("passive-focused",$)}toggleStickyScrollFocused(B){this.view.getHTMLElement().classList.toggle("sticky-scroll-focused",B)}onFocus(){if(!this.state||this.elements.length===0)throw new Error("Cannot focus when state is undefined or elements are empty");this.domHasFocus=!0,this.toggleStickyScrollFocused(!0),this.toggleCurrentElementActiveFocus(!0),this.focusedIndex===-1&&this.setFocus(0)}onBlur(){this.domHasFocus=!1,this.toggleCurrentElementActiveFocus(!1)}dispose(){this.toggleStickyScrollFocused(!1),this._onDidChangeHasFocus.fire(!1),super.dispose()}}function ue(X){let B=o.TreeMouseEventTarget.Unknown;return(0,d.hasParentWithClass)(X.browserEvent.target,"monaco-tl-twistie","monaco-tl-row")?B=o.TreeMouseEventTarget.Twistie:(0,d.hasParentWithClass)(X.browserEvent.target,"monaco-tl-contents","monaco-tl-row")?B=o.TreeMouseEventTarget.Element:(0,d.hasParentWithClass)(X.browserEvent.target,"monaco-tree-type-filter","monaco-list")&&(B=o.TreeMouseEventTarget.Filter),{browserEvent:X.browserEvent,element:X.element?X.element.element:null,target:B}}function he(X){const B=(0,b.isStickyScrollContainer)(X.browserEvent.target);return{element:X.element?X.element.element:null,browserEvent:X.browserEvent,anchor:X.anchor,isStickyScroll:B}}function pe(X,B){B(X),X.children.forEach($=>pe($,B))}class ae{get nodeSet(){return this._nodeSet||(this._nodeSet=this.createNodeSet()),this._nodeSet}constructor(B,$){this.getFirstViewElementWithTrait=B,this.identityProvider=$,this.nodes=[],this._onDidChange=new a.Emitter,this.onDidChange=this._onDidChange.event}set(B,$){!$?.__forceEvent&&(0,i.equals)(this.nodes,B)||this._set(B,!1,$)}_set(B,$,Q){if(this.nodes=[...B],this.elements=void 0,this._nodeSet=void 0,!$){const Z=this;this._onDidChange.fire({get elements(){return Z.get()},browserEvent:Q})}}get(){return this.elements||(this.elements=this.nodes.map(B=>B.element)),[...this.elements]}getNodes(){return this.nodes}has(B){return this.nodeSet.has(B)}onDidModelSplice({insertedNodes:B,deletedNodes:$}){if(!this.identityProvider){const me=this.createNodeSet(),Ce=ye=>me.delete(ye);$.forEach(ye=>pe(ye,Ce)),this.set([...me.values()]);return}const Q=new Set,Z=me=>Q.add(this.identityProvider.getId(me.element).toString());$.forEach(me=>pe(me,Z));const te=new Map,re=me=>te.set(this.identityProvider.getId(me.element).toString(),me);B.forEach(me=>pe(me,re));const le=[];for(const me of this.nodes){const Ce=this.identityProvider.getId(me.element).toString();if(!Q.has(Ce))le.push(me);else{const Le=te.get(Ce);Le&&Le.visible&&le.push(Le)}}if(this.nodes.length>0&&le.length===0){const me=this.getFirstViewElementWithTrait();me&&le.push(me)}this._set(le,!0)}createNodeSet(){const B=new Set;for(const $ of this.nodes)B.add($);return B}}class ee extends b.MouseController{constructor(B,$,Q){super(B),this.tree=$,this.stickyScrollProvider=Q}onViewPointer(B){if((0,b.isButton)(B.browserEvent.target)||(0,b.isInputElement)(B.browserEvent.target)||(0,b.isMonacoEditor)(B.browserEvent.target)||B.browserEvent.isHandledByList)return;const $=B.element;if(!$)return super.onViewPointer(B);if(this.isSelectionRangeChangeEvent(B)||this.isSelectionSingleChangeEvent(B))return super.onViewPointer(B);const Q=B.browserEvent.target,Z=Q.classList.contains("monaco-tl-twistie")||Q.classList.contains("monaco-icon-label")&&Q.classList.contains("folder-icon")&&B.browserEvent.offsetX<16,te=(0,b.isStickyScrollElement)(B.browserEvent.target);let re=!1;if(te?re=!0:typeof this.tree.expandOnlyOnTwistieClick=="function"?re=this.tree.expandOnlyOnTwistieClick($.element):re=!!this.tree.expandOnlyOnTwistieClick,te)this.handleStickyScrollMouseEvent(B,$);else{if(re&&!Z&&B.browserEvent.detail!==2)return super.onViewPointer(B);if(!this.tree.expandOnDoubleClick&&B.browserEvent.detail===2)return super.onViewPointer(B)}if($.collapsible&&(!te||Z)){const le=this.tree.getNodeLocation($),me=B.browserEvent.altKey;if(this.tree.setFocus([le]),this.tree.toggleCollapsed(le,me),Z){B.browserEvent.isHandledByList=!0;return}}te||super.onViewPointer(B)}handleStickyScrollMouseEvent(B,$){if((0,b.isMonacoCustomToggle)(B.browserEvent.target)||(0,b.isActionItem)(B.browserEvent.target))return;const Q=this.stickyScrollProvider();if(!Q)throw new Error("Sticky scroll controller not found");const Z=this.list.indexOf($),te=this.list.getElementTop(Z),re=Q.nodePositionTopBelowWidget($);this.tree.scrollTop=te-re,this.list.domFocus(),this.list.setFocus([Z]),this.list.setSelection([Z])}onDoubleClick(B){B.browserEvent.target.classList.contains("monaco-tl-twistie")||!this.tree.expandOnDoubleClick||B.browserEvent.isHandledByList||super.onDoubleClick(B)}onMouseDown(B){const $=B.browserEvent.target;if(!(0,b.isStickyScrollContainer)($)&&!(0,b.isStickyScrollElement)($)){super.onMouseDown(B);return}}onContextMenu(B){const $=B.browserEvent.target;if(!(0,b.isStickyScrollContainer)($)&&!(0,b.isStickyScrollElement)($)){super.onContextMenu(B);return}}}class de extends b.List{constructor(B,$,Q,Z,te,re,le,me){super(B,$,Q,Z,me),this.focusTrait=te,this.selectionTrait=re,this.anchorTrait=le}createMouseController(B){return new ee(this,B.tree,B.stickyScrollProvider)}splice(B,$,Q=[]){if(super.splice(B,$,Q),Q.length===0)return;const Z=[],te=[];let re;Q.forEach((le,me)=>{this.focusTrait.has(le)&&Z.push(B+me),this.selectionTrait.has(le)&&te.push(B+me),this.anchorTrait.has(le)&&(re=B+me)}),Z.length>0&&super.setFocus((0,i.distinct)([...super.getFocus(),...Z])),te.length>0&&super.setSelection((0,i.distinct)([...super.getSelection(),...te])),typeof re=="number"&&super.setAnchor(re)}setFocus(B,$,Q=!1){super.setFocus(B,$),Q||this.focusTrait.set(B.map(Z=>this.element(Z)),$)}setSelection(B,$,Q=!1){super.setSelection(B,$),Q||this.selectionTrait.set(B.map(Z=>this.element(Z)),$)}setAnchor(B,$=!1){super.setAnchor(B),$||(typeof B>"u"?this.anchorTrait.set([]):this.anchorTrait.set([this.element(B)]))}}class ge{get onDidScroll(){return this.view.onDidScroll}get onDidChangeFocus(){return this.eventBufferer.wrapEvent(this.focus.onDidChange)}get onDidChangeSelection(){return this.eventBufferer.wrapEvent(this.selection.onDidChange)}get onMouseDblClick(){return a.Event.filter(a.Event.map(this.view.onMouseDblClick,ue),B=>B.target!==o.TreeMouseEventTarget.Filter)}get onMouseOver(){return a.Event.map(this.view.onMouseOver,ue)}get onMouseOut(){return a.Event.map(this.view.onMouseOut,ue)}get onContextMenu(){return a.Event.any(a.Event.filter(a.Event.map(this.view.onContextMenu,he),B=>!B.isStickyScroll),this.stickyScrollController?.onContextMenu??a.Event.None)}get onPointer(){return a.Event.map(this.view.onPointer,ue)}get onKeyDown(){return this.view.onKeyDown}get onDidFocus(){return this.view.onDidFocus}get onDidChangeModel(){return a.Event.signal(this.model.onDidSplice)}get onDidChangeCollapseState(){return this.model.onDidChangeCollapseState}get findMode(){return this.findController?.mode??q.Highlight}set findMode(B){this.findController&&(this.findController.mode=B)}get findMatchType(){return this.findController?.matchType??H.Fuzzy}set findMatchType(B){this.findController&&(this.findController.matchType=B)}get expandOnDoubleClick(){return typeof this._options.expandOnDoubleClick>"u"?!0:this._options.expandOnDoubleClick}get expandOnlyOnTwistieClick(){return typeof this._options.expandOnlyOnTwistieClick>"u"?!0:this._options.expandOnlyOnTwistieClick}get onDidDispose(){return this.view.onDidDispose}constructor(B,$,Q,Z,te={}){this._user=B,this._options=te,this.eventBufferer=new a.EventBufferer,this.onDidChangeFindOpenState=a.Event.None,this.onDidChangeStickyScrollFocused=a.Event.None,this.disposables=new u.DisposableStore,this._onWillRefilter=new a.Emitter,this.onWillRefilter=this._onWillRefilter.event,this._onDidUpdateOptions=new a.Emitter,this.treeDelegate=new A(Q);const re=new a.Relay,le=new a.Relay,me=this.disposables.add(new N(le.event)),Ce=new l.SetMap;this.renderers=Z.map(Ae=>new O(Ae,()=>this.model,re.event,me,Ce,te));for(const Ae of this.renderers)this.disposables.add(Ae);let ye;te.keyboardNavigationLabelProvider&&(ye=new F(this,te.keyboardNavigationLabelProvider,te.filter),te={...te,filter:ye},this.disposables.add(ye)),this.focus=new ae(()=>this.view.getFocusedElements()[0],te.identityProvider),this.selection=new ae(()=>this.view.getSelectedElements()[0],te.identityProvider),this.anchor=new ae(()=>this.view.getAnchorElement(),te.identityProvider),this.view=new de(B,$,this.treeDelegate,this.renderers,this.focus,this.selection,this.anchor,{...M(()=>this.model,te),tree:this,stickyScrollProvider:()=>this.stickyScrollController}),this.model=this.createModel(B,this.view,te),re.input=this.model.onDidChangeCollapseState;const Le=a.Event.forEach(this.model.onDidSplice,Ae=>{this.eventBufferer.bufferEvents(()=>{this.focus.onDidModelSplice(Ae),this.selection.onDidModelSplice(Ae)})},this.disposables);Le(()=>null,null,this.disposables);const Ee=this.disposables.add(new a.Emitter),Me=this.disposables.add(new s.Delayer(0));if(this.disposables.add(a.Event.any(Le,this.focus.onDidChange,this.selection.onDidChange)(()=>{Me.trigger(()=>{const Ae=new Set;for(const Ne of this.focus.getNodes())Ae.add(Ne);for(const Ne of this.selection.getNodes())Ae.add(Ne);Ee.fire([...Ae.values()])})})),le.input=Ee.event,te.keyboardSupport!==!1){const Ae=a.Event.chain(this.view.onKeyDown,Ne=>Ne.filter(Ke=>!(0,b.isInputElement)(Ke.target)).map(Ke=>new I.StandardKeyboardEvent(Ke)));a.Event.chain(Ae,Ne=>Ne.filter(Ke=>Ke.keyCode===15))(this.onLeftArrow,this,this.disposables),a.Event.chain(Ae,Ne=>Ne.filter(Ke=>Ke.keyCode===17))(this.onRightArrow,this,this.disposables),a.Event.chain(Ae,Ne=>Ne.filter(Ke=>Ke.keyCode===10))(this.onSpace,this,this.disposables)}if((te.findWidgetEnabled??!0)&&te.keyboardNavigationLabelProvider&&te.contextViewProvider){const Ae=this.options.findWidgetStyles?{styles:this.options.findWidgetStyles}:void 0;this.findController=new U(this,this.model,this.view,ye,te.contextViewProvider,Ae),this.focusNavigationFilter=Ne=>this.findController.shouldAllowFocus(Ne),this.onDidChangeFindOpenState=this.findController.onDidChangeOpenState,this.disposables.add(this.findController),this.onDidChangeFindMode=this.findController.onDidChangeMode,this.onDidChangeFindMatchType=this.findController.onDidChangeMatchType}else this.onDidChangeFindMode=a.Event.None,this.onDidChangeFindMatchType=a.Event.None;te.enableStickyScroll&&(this.stickyScrollController=new R(this,this.model,this.view,this.renderers,this.treeDelegate,te),this.onDidChangeStickyScrollFocused=this.stickyScrollController.onDidChangeHasFocus),this.styleElement=(0,d.createStyleSheet)(this.view.getHTMLElement()),this.getHTMLElement().classList.toggle("always",this._options.renderIndentGuides===P.Always)}updateOptions(B={}){this._options={...this._options,...B};for(const $ of this.renderers)$.updateOptions(B);this.view.updateOptions(this._options),this.findController?.updateOptions(B),this.updateStickyScroll(B),this._onDidUpdateOptions.fire(this._options),this.getHTMLElement().classList.toggle("always",this._options.renderIndentGuides===P.Always)}get options(){return this._options}updateStickyScroll(B){!this.stickyScrollController&&this._options.enableStickyScroll?(this.stickyScrollController=new R(this,this.model,this.view,this.renderers,this.treeDelegate,this._options),this.onDidChangeStickyScrollFocused=this.stickyScrollController.onDidChangeHasFocus):this.stickyScrollController&&!this._options.enableStickyScroll&&(this.onDidChangeStickyScrollFocused=a.Event.None,this.stickyScrollController.dispose(),this.stickyScrollController=void 0),this.stickyScrollController?.updateOptions(B)}getHTMLElement(){return this.view.getHTMLElement()}get scrollTop(){return this.view.scrollTop}set scrollTop(B){this.view.scrollTop=B}get scrollHeight(){return this.view.scrollHeight}get renderHeight(){return this.view.renderHeight}get ariaLabel(){return this.view.ariaLabel}set ariaLabel(B){this.view.ariaLabel=B}domFocus(){this.stickyScrollController?.focusedLast()?this.stickyScrollController.domFocus():this.view.domFocus()}layout(B,$){this.view.layout(B,$),(0,f.isNumber)($)&&this.findController?.layout($)}style(B){const $=`.${this.view.domId}`,Q=[];B.treeIndentGuidesStroke&&(Q.push(`.monaco-list${$}:hover .monaco-tl-indent > .indent-guide, .monaco-list${$}.always .monaco-tl-indent > .indent-guide { border-color: ${B.treeInactiveIndentGuidesStroke}; }`),Q.push(`.monaco-list${$} .monaco-tl-indent > .indent-guide.active { border-color: ${B.treeIndentGuidesStroke}; }`));const Z=B.treeStickyScrollBackground??B.listBackground;Z&&(Q.push(`.monaco-list${$} .monaco-scrollable-element .monaco-tree-sticky-container { background-color: ${Z}; }`),Q.push(`.monaco-list${$} .monaco-scrollable-element .monaco-tree-sticky-container .monaco-tree-sticky-row { background-color: ${Z}; }`)),B.treeStickyScrollBorder&&Q.push(`.monaco-list${$} .monaco-scrollable-element .monaco-tree-sticky-container { border-bottom: 1px solid ${B.treeStickyScrollBorder}; }`),B.treeStickyScrollShadow&&Q.push(`.monaco-list${$} .monaco-scrollable-element .monaco-tree-sticky-container .monaco-tree-sticky-container-shadow { box-shadow: ${B.treeStickyScrollShadow} 0 6px 6px -6px inset; height: 3px; }`),B.listFocusForeground&&(Q.push(`.monaco-list${$}.sticky-scroll-focused .monaco-scrollable-element .monaco-tree-sticky-container:focus .monaco-list-row.focused { color: ${B.listFocusForeground}; }`),Q.push(`.monaco-list${$}:not(.sticky-scroll-focused) .monaco-scrollable-element .monaco-tree-sticky-container .monaco-list-row.focused { color: inherit; }`));const te=(0,d.asCssValueWithDefault)(B.listFocusAndSelectionOutline,(0,d.asCssValueWithDefault)(B.listSelectionOutline,B.listFocusOutline??""));te&&(Q.push(`.monaco-list${$}.sticky-scroll-focused .monaco-scrollable-element .monaco-tree-sticky-container:focus .monaco-list-row.focused.selected { outline: 1px solid ${te}; outline-offset: -1px;}`),Q.push(`.monaco-list${$}:not(.sticky-scroll-focused) .monaco-scrollable-element .monaco-tree-sticky-container .monaco-list-row.focused.selected { outline: inherit;}`)),B.listFocusOutline&&(Q.push(`.monaco-list${$}.sticky-scroll-focused .monaco-scrollable-element .monaco-tree-sticky-container:focus .monaco-list-row.focused { outline: 1px solid ${B.listFocusOutline}; outline-offset: -1px; }`),Q.push(`.monaco-list${$}:not(.sticky-scroll-focused) .monaco-scrollable-element .monaco-tree-sticky-container .monaco-list-row.focused { outline: inherit; }`),Q.push(`.monaco-workbench.context-menu-visible .monaco-list${$}.last-focused.sticky-scroll-focused .monaco-scrollable-element .monaco-tree-sticky-container .monaco-list-row.passive-focused { outline: 1px solid ${B.listFocusOutline}; outline-offset: -1px; }`),Q.push(`.monaco-workbench.context-menu-visible .monaco-list${$}.last-focused.sticky-scroll-focused .monaco-list-rows .monaco-list-row.focused { outline: inherit; }`),Q.push(`.monaco-workbench.context-menu-visible .monaco-list${$}.last-focused:not(.sticky-scroll-focused) .monaco-tree-sticky-container .monaco-list-rows .monaco-list-row.focused { outline: inherit; }`)),this.styleElement.textContent=Q.join(` `),this.view.style(B)}getParentElement(B){const $=this.model.getParentNodeLocation(B);return this.model.getNode($).element}getFirstElementChild(B){return this.model.getFirstElementChild(B)}getNode(B){return this.model.getNode(B)}getNodeLocation(B){return this.model.getNodeLocation(B)}collapse(B,$=!1){return this.model.setCollapsed(B,!0,$)}expand(B,$=!1){return this.model.setCollapsed(B,!1,$)}toggleCollapsed(B,$=!1){return this.model.setCollapsed(B,void 0,$)}isCollapsible(B){return this.model.isCollapsible(B)}setCollapsible(B,$){return this.model.setCollapsible(B,$)}isCollapsed(B){return this.model.isCollapsed(B)}refilter(){this._onWillRefilter.fire(void 0),this.model.refilter()}setSelection(B,$){this.eventBufferer.bufferEvents(()=>{const Q=B.map(te=>this.model.getNode(te));this.selection.set(Q,$);const Z=B.map(te=>this.model.getListIndex(te)).filter(te=>te>-1);this.view.setSelection(Z,$,!0)})}getSelection(){return this.selection.get()}setFocus(B,$){this.eventBufferer.bufferEvents(()=>{const Q=B.map(te=>this.model.getNode(te));this.focus.set(Q,$);const Z=B.map(te=>this.model.getListIndex(te)).filter(te=>te>-1);this.view.setFocus(Z,$,!0)})}focusNext(B=1,$=!1,Q,Z=(0,d.isKeyboardEvent)(Q)&&Q.altKey?void 0:this.focusNavigationFilter){this.view.focusNext(B,$,Q,Z)}focusPrevious(B=1,$=!1,Q,Z=(0,d.isKeyboardEvent)(Q)&&Q.altKey?void 0:this.focusNavigationFilter){this.view.focusPrevious(B,$,Q,Z)}focusNextPage(B,$=(0,d.isKeyboardEvent)(B)&&B.altKey?void 0:this.focusNavigationFilter){return this.view.focusNextPage(B,$)}focusPreviousPage(B,$=(0,d.isKeyboardEvent)(B)&&B.altKey?void 0:this.focusNavigationFilter){return this.view.focusPreviousPage(B,$,()=>this.stickyScrollController?.height??0)}focusLast(B,$=(0,d.isKeyboardEvent)(B)&&B.altKey?void 0:this.focusNavigationFilter){this.view.focusLast(B,$)}focusFirst(B,$=(0,d.isKeyboardEvent)(B)&&B.altKey?void 0:this.focusNavigationFilter){this.view.focusFirst(B,$)}getFocus(){return this.focus.get()}reveal(B,$){this.model.expandTo(B);const Q=this.model.getListIndex(B);if(Q!==-1)if(!this.stickyScrollController)this.view.reveal(Q,$);else{const Z=this.stickyScrollController.nodePositionTopBelowWidget(this.getNode(B));this.view.reveal(Q,$,Z)}}onLeftArrow(B){B.preventDefault(),B.stopPropagation();const $=this.view.getFocusedElements();if($.length===0)return;const Q=$[0],Z=this.model.getNodeLocation(Q);if(!this.model.setCollapsed(Z,!0)){const re=this.model.getParentNodeLocation(Z);if(!re)return;const le=this.model.getListIndex(re);this.view.reveal(le),this.view.setFocus([le])}}onRightArrow(B){B.preventDefault(),B.stopPropagation();const $=this.view.getFocusedElements();if($.length===0)return;const Q=$[0],Z=this.model.getNodeLocation(Q);if(!this.model.setCollapsed(Z,!1)){if(!Q.children.some(me=>me.visible))return;const[re]=this.view.getFocus(),le=re+1;this.view.reveal(le),this.view.setFocus([le])}}onSpace(B){B.preventDefault(),B.stopPropagation();const $=this.view.getFocusedElements();if($.length===0)return;const Q=$[0],Z=this.model.getNodeLocation(Q),te=B.browserEvent.altKey;this.model.setCollapsed(Z,void 0,te)}dispose(){(0,u.dispose)(this.disposables),this.stickyScrollController?.dispose(),this.view.dispose()}}e.AbstractTree=ge}),define(ne[644],se([1,0,176,250]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DataTree=void 0;class I extends d.AbstractTree{constructor(y,m,_,b,p,n={}){super(y,m,_,b,n),this.user=y,this.dataSource=p,this.identityProvider=n.identityProvider}createModel(y,m,_){return new k.ObjectTreeModel(y,m,_)}}e.DataTree=I}),define(ne[360],se([1,0,176,627,250,126,53]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CompressibleObjectTree=e.ObjectTree=void 0;class m extends d.AbstractTree{get onDidChangeCollapseState(){return this.model.onDidChangeCollapseState}constructor(t,i,s,g,c={}){super(t,i,s,g,c),this.user=t}setChildren(t,i=y.Iterable.empty(),s){this.model.setChildren(t,i,s)}rerender(t){if(t===void 0){this.view.rerender();return}this.model.rerender(t)}hasElement(t){return this.model.has(t)}createModel(t,i,s){return new I.ObjectTreeModel(t,i,s)}}e.ObjectTree=m;class _{get compressedTreeNodeProvider(){return this._compressedTreeNodeProvider()}constructor(t,i,s){this._compressedTreeNodeProvider=t,this.stickyScrollDelegate=i,this.renderer=s,this.templateId=s.templateId,s.onDidChangeTwistieState&&(this.onDidChangeTwistieState=s.onDidChangeTwistieState)}renderTemplate(t){return{compressedTreeNode:void 0,data:this.renderer.renderTemplate(t)}}renderElement(t,i,s,g){let c=this.stickyScrollDelegate.getCompressedNode(t);c||(c=this.compressedTreeNodeProvider.getCompressedTreeNode(t.element)),c.element.elements.length===1?(s.compressedTreeNode=void 0,this.renderer.renderElement(t,i,s.data,g)):(s.compressedTreeNode=c,this.renderer.renderCompressedElements(c,i,s.data,g))}disposeElement(t,i,s,g){s.compressedTreeNode?this.renderer.disposeCompressedElements?.(s.compressedTreeNode,i,s.data,g):this.renderer.disposeElement?.(t,i,s.data,g)}disposeTemplate(t){this.renderer.disposeTemplate(t.data)}renderTwistie(t,i){return this.renderer.renderTwistie?this.renderer.renderTwistie(t,i):!1}}ke([E.memoize],_.prototype,"compressedTreeNodeProvider",null);class b{constructor(t){this.modelProvider=t,this.compressedStickyNodes=new Map}getCompressedNode(t){return this.compressedStickyNodes.get(t)}constrainStickyScrollNodes(t,i,s){if(this.compressedStickyNodes.clear(),t.length===0)return[];for(let g=0;gs||g>=i-1&&ithis,a=new b(()=>this.model),r=g.map(u=>new _(l,a,u));super(t,i,s,r,{...p(l,c),stickyScrollDelegate:a})}setChildren(t,i=y.Iterable.empty(),s){this.model.setChildren(t,i,s)}createModel(t,i,s){return new k.CompressibleObjectTreeModel(t,i,s)}updateOptions(t={}){super.updateOptions(t),typeof t.compressionEnabled<"u"&&this.model.setCompressionEnabled(t.compressionEnabled)}getCompressedTreeNode(t=null){return this.model.getCompressedTreeNode(t)}}e.CompressibleObjectTree=n}),define(ne[645],se([1,0,257,176,249,360,159,14,26,30,8,6,53,2,19]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CompressibleAsyncDataTree=e.AsyncDataTree=void 0;function s(P){return{...P,children:[],refreshPromise:void 0,stale:!0,slow:!1,forceExpanded:!1}}function g(P,N){return N.parent?N.parent===P?!0:g(P,N.parent):!1}function c(P,N){return P===N||g(P,N)||g(N,P)}class l{get element(){return this.node.element.element}get children(){return this.node.children.map(N=>new l(N))}get depth(){return this.node.depth}get visibleChildrenCount(){return this.node.visibleChildrenCount}get visibleChildIndex(){return this.node.visibleChildIndex}get collapsible(){return this.node.collapsible}get collapsed(){return this.node.collapsed}get visible(){return this.node.visible}get filterData(){return this.node.filterData}constructor(N){this.node=N}}class a{constructor(N,O,F){this.renderer=N,this.nodeMapper=O,this.onDidChangeTwistieState=F,this.renderedNodes=new Map,this.templateId=N.templateId}renderTemplate(N){return{templateData:this.renderer.renderTemplate(N)}}renderElement(N,O,F,x){this.renderer.renderElement(this.nodeMapper.map(N),O,F.templateData,x)}renderTwistie(N,O){return N.slow?(O.classList.add(...b.ThemeIcon.asClassNameArray(_.Codicon.treeItemLoading)),!0):(O.classList.remove(...b.ThemeIcon.asClassNameArray(_.Codicon.treeItemLoading)),!1)}disposeElement(N,O,F,x){this.renderer.disposeElement?.(this.nodeMapper.map(N),O,F.templateData,x)}disposeTemplate(N){this.renderer.disposeTemplate(N.templateData)}dispose(){this.renderedNodes.clear()}}function r(P){return{browserEvent:P.browserEvent,elements:P.elements.map(N=>N.element)}}function u(P){return{browserEvent:P.browserEvent,element:P.element&&P.element.element,target:P.target}}class C extends d.ElementsDragAndDropData{constructor(N){super(N.elements.map(O=>O.element)),this.data=N}}function f(P){return P instanceof d.ElementsDragAndDropData?new C(P):P}class h{constructor(N){this.dnd=N}getDragURI(N){return this.dnd.getDragURI(N.element)}getDragLabel(N,O){if(this.dnd.getDragLabel)return this.dnd.getDragLabel(N.map(F=>F.element),O)}onDragStart(N,O){this.dnd.onDragStart?.(f(N),O)}onDragOver(N,O,F,x,W,V=!0){return this.dnd.onDragOver(f(N),O&&O.element,F,x,W)}drop(N,O,F,x,W){this.dnd.drop(f(N),O&&O.element,F,x,W)}onDragEnd(N){this.dnd.onDragEnd?.(N)}dispose(){this.dnd.dispose()}}function v(P){return P&&{...P,collapseByDefault:!0,identityProvider:P.identityProvider&&{getId(N){return P.identityProvider.getId(N.element)}},dnd:P.dnd&&new h(P.dnd),multipleSelectionController:P.multipleSelectionController&&{isSelectionSingleChangeEvent(N){return P.multipleSelectionController.isSelectionSingleChangeEvent({...N,element:N.element})},isSelectionRangeChangeEvent(N){return P.multipleSelectionController.isSelectionRangeChangeEvent({...N,element:N.element})}},accessibilityProvider:P.accessibilityProvider&&{...P.accessibilityProvider,getPosInSet:void 0,getSetSize:void 0,getRole:P.accessibilityProvider.getRole?N=>P.accessibilityProvider.getRole(N.element):()=>"treeitem",isChecked:P.accessibilityProvider.isChecked?N=>!!P.accessibilityProvider?.isChecked(N.element):void 0,getAriaLabel(N){return P.accessibilityProvider.getAriaLabel(N.element)},getWidgetAriaLabel(){return P.accessibilityProvider.getWidgetAriaLabel()},getWidgetRole:P.accessibilityProvider.getWidgetRole?()=>P.accessibilityProvider.getWidgetRole():()=>"tree",getAriaLevel:P.accessibilityProvider.getAriaLevel&&(N=>P.accessibilityProvider.getAriaLevel(N.element)),getActiveDescendantId:P.accessibilityProvider.getActiveDescendantId&&(N=>P.accessibilityProvider.getActiveDescendantId(N.element))},filter:P.filter&&{filter(N,O){return P.filter.filter(N.element,O)}},keyboardNavigationLabelProvider:P.keyboardNavigationLabelProvider&&{...P.keyboardNavigationLabelProvider,getKeyboardNavigationLabel(N){return P.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(N.element)}},sorter:void 0,expandOnlyOnTwistieClick:typeof P.expandOnlyOnTwistieClick>"u"?void 0:typeof P.expandOnlyOnTwistieClick!="function"?P.expandOnlyOnTwistieClick:N=>P.expandOnlyOnTwistieClick(N.element),defaultFindVisibility:N=>N.hasChildren&&N.stale?1:typeof P.defaultFindVisibility=="number"?P.defaultFindVisibility:typeof P.defaultFindVisibility>"u"?2:P.defaultFindVisibility(N.element)}}function w(P,N){N(P),P.children.forEach(O=>w(O,N))}class S{get onDidScroll(){return this.tree.onDidScroll}get onDidChangeFocus(){return n.Event.map(this.tree.onDidChangeFocus,r)}get onDidChangeSelection(){return n.Event.map(this.tree.onDidChangeSelection,r)}get onMouseDblClick(){return n.Event.map(this.tree.onMouseDblClick,u)}get onPointer(){return n.Event.map(this.tree.onPointer,u)}get onDidFocus(){return this.tree.onDidFocus}get onDidChangeModel(){return this.tree.onDidChangeModel}get onDidChangeCollapseState(){return this.tree.onDidChangeCollapseState}get onDidChangeFindOpenState(){return this.tree.onDidChangeFindOpenState}get onDidChangeStickyScrollFocused(){return this.tree.onDidChangeStickyScrollFocused}get onDidDispose(){return this.tree.onDidDispose}constructor(N,O,F,x,W,V={}){this.user=N,this.dataSource=W,this.nodes=new Map,this.subTreeRefreshPromises=new Map,this.refreshPromises=new Map,this._onDidRender=new n.Emitter,this._onDidChangeNodeSlowState=new n.Emitter,this.nodeMapper=new y.WeakMapper(q=>new l(q)),this.disposables=new t.DisposableStore,this.identityProvider=V.identityProvider,this.autoExpandSingleChildren=typeof V.autoExpandSingleChildren>"u"?!1:V.autoExpandSingleChildren,this.sorter=V.sorter,this.getDefaultCollapseState=q=>V.collapseByDefault?V.collapseByDefault(q)?y.ObjectTreeElementCollapseState.PreserveOrCollapsed:y.ObjectTreeElementCollapseState.PreserveOrExpanded:void 0,this.tree=this.createTree(N,O,F,x,V),this.onDidChangeFindMode=this.tree.onDidChangeFindMode,this.onDidChangeFindMatchType=this.tree.onDidChangeFindMatchType,this.root=s({element:void 0,parent:null,hasChildren:!0,defaultCollapseState:void 0}),this.identityProvider&&(this.root={...this.root,id:null}),this.nodes.set(null,this.root),this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState,this,this.disposables)}createTree(N,O,F,x,W){const V=new k.ComposedTreeDelegate(F),q=x.map(z=>new a(z,this.nodeMapper,this._onDidChangeNodeSlowState.event)),H=v(W)||{};return new E.ObjectTree(N,O,V,q,H)}updateOptions(N={}){this.tree.updateOptions(N)}getHTMLElement(){return this.tree.getHTMLElement()}get scrollTop(){return this.tree.scrollTop}set scrollTop(N){this.tree.scrollTop=N}get scrollHeight(){return this.tree.scrollHeight}get renderHeight(){return this.tree.renderHeight}domFocus(){this.tree.domFocus()}layout(N,O){this.tree.layout(N,O)}style(N){this.tree.style(N)}getInput(){return this.root.element}async setInput(N,O){this.refreshPromises.forEach(x=>x.cancel()),this.refreshPromises.clear(),this.root.element=N;const F=O&&{viewState:O,focus:[],selection:[]};await this._updateChildren(N,!0,!1,F),F&&(this.tree.setFocus(F.focus),this.tree.setSelection(F.selection)),O&&typeof O.scrollTop=="number"&&(this.scrollTop=O.scrollTop)}async _updateChildren(N=this.root.element,O=!0,F=!1,x,W){if(typeof this.root.element>"u")throw new y.TreeError(this.user,"Tree input not set");this.root.refreshPromise&&(await this.root.refreshPromise,await n.Event.toPromise(this._onDidRender.event));const V=this.getDataNode(N);if(await this.refreshAndRenderNode(V,O,x,W),F)try{this.tree.rerender(V)}catch{}}rerender(N){if(N===void 0||N===this.root.element){this.tree.rerender();return}const O=this.getDataNode(N);this.tree.rerender(O)}getNode(N=this.root.element){const O=this.getDataNode(N),F=this.tree.getNode(O===this.root?null:O);return this.nodeMapper.map(F)}collapse(N,O=!1){const F=this.getDataNode(N);return this.tree.collapse(F===this.root?null:F,O)}async expand(N,O=!1){if(typeof this.root.element>"u")throw new y.TreeError(this.user,"Tree input not set");this.root.refreshPromise&&(await this.root.refreshPromise,await n.Event.toPromise(this._onDidRender.event));const F=this.getDataNode(N);if(this.tree.hasElement(F)&&!this.tree.isCollapsible(F)||(F.refreshPromise&&(await this.root.refreshPromise,await n.Event.toPromise(this._onDidRender.event)),F!==this.root&&!F.refreshPromise&&!this.tree.isCollapsed(F)))return!1;const x=this.tree.expand(F===this.root?null:F,O);return F.refreshPromise&&(await this.root.refreshPromise,await n.Event.toPromise(this._onDidRender.event)),x}setSelection(N,O){const F=N.map(x=>this.getDataNode(x));this.tree.setSelection(F,O)}getSelection(){return this.tree.getSelection().map(O=>O.element)}setFocus(N,O){const F=N.map(x=>this.getDataNode(x));this.tree.setFocus(F,O)}getFocus(){return this.tree.getFocus().map(O=>O.element)}reveal(N,O){this.tree.reveal(this.getDataNode(N),O)}getParentElement(N){const O=this.tree.getParentElement(this.getDataNode(N));return O&&O.element}getFirstElementChild(N=this.root.element){const O=this.getDataNode(N),F=this.tree.getFirstElementChild(O===this.root?null:O);return F&&F.element}getDataNode(N){const O=this.nodes.get(N===this.root.element?null:N);if(!O)throw new y.TreeError(this.user,`Data tree node not found: ${N}`);return O}async refreshAndRenderNode(N,O,F,x){await this.refreshNode(N,O,F),!this.disposables.isDisposed&&this.render(N,F,x)}async refreshNode(N,O,F){let x;if(this.subTreeRefreshPromises.forEach((W,V)=>{!x&&c(V,N)&&(x=W.then(()=>this.refreshNode(N,O,F)))}),x)return x;if(N!==this.root&&this.tree.getNode(N).collapsed){N.hasChildren=!!this.dataSource.hasChildren(N.element),N.stale=!0,this.setChildren(N,[],O,F);return}return this.doRefreshSubTree(N,O,F)}async doRefreshSubTree(N,O,F){let x;N.refreshPromise=new Promise(W=>x=W),this.subTreeRefreshPromises.set(N,N.refreshPromise),N.refreshPromise.finally(()=>{N.refreshPromise=void 0,this.subTreeRefreshPromises.delete(N)});try{const W=await this.doRefreshNode(N,O,F);N.stale=!1,await m.Promises.settled(W.map(V=>this.doRefreshSubTree(V,O,F)))}finally{x()}}async doRefreshNode(N,O,F){N.hasChildren=!!this.dataSource.hasChildren(N.element);let x;if(!N.hasChildren)x=Promise.resolve(o.Iterable.empty());else{const W=this.doGetChildren(N);if((0,i.isIterable)(W))x=Promise.resolve(W);else{const V=(0,m.timeout)(800);V.then(()=>{N.slow=!0,this._onDidChangeNodeSlowState.fire(N)},q=>null),x=W.finally(()=>V.cancel())}}try{const W=await x;return this.setChildren(N,W,O,F)}catch(W){if(N!==this.root&&this.tree.hasElement(N)&&this.tree.collapse(N),(0,p.isCancellationError)(W))return[];throw W}finally{N.slow&&(N.slow=!1,this._onDidChangeNodeSlowState.fire(N))}}doGetChildren(N){let O=this.refreshPromises.get(N);if(O)return O;const F=this.dataSource.getChildren(N.element);return(0,i.isIterable)(F)?this.processChildren(F):(O=(0,m.createCancelablePromise)(async()=>this.processChildren(await F)),this.refreshPromises.set(N,O),O.finally(()=>{this.refreshPromises.delete(N)}))}_onDidChangeCollapseState({node:N,deep:O}){N.element!==null&&!N.collapsed&&N.element.stale&&(O?this.collapse(N.element.element):this.refreshAndRenderNode(N.element,!1).catch(p.onUnexpectedError))}setChildren(N,O,F,x){const W=[...O];if(N.children.length===0&&W.length===0)return[];const V=new Map,q=new Map;for(const U of N.children)V.set(U.element,U),this.identityProvider&&q.set(U.id,{node:U,collapsed:this.tree.hasElement(U)&&this.tree.isCollapsed(U)});const H=[],z=W.map(U=>{const j=!!this.dataSource.hasChildren(U);if(!this.identityProvider){const R=s({element:U,parent:N,hasChildren:j,defaultCollapseState:this.getDefaultCollapseState(U)});return j&&R.defaultCollapseState===y.ObjectTreeElementCollapseState.PreserveOrExpanded&&H.push(R),R}const Y=this.identityProvider.getId(U).toString(),G=q.get(Y);if(G){const R=G.node;return V.delete(R.element),this.nodes.delete(R.element),this.nodes.set(U,R),R.element=U,R.hasChildren=j,F?G.collapsed?(R.children.forEach(J=>w(J,ie=>this.nodes.delete(ie.element))),R.children.splice(0,R.children.length),R.stale=!0):H.push(R):j&&!G.collapsed&&H.push(R),R}const K=s({element:U,parent:N,id:Y,hasChildren:j,defaultCollapseState:this.getDefaultCollapseState(U)});return x&&x.viewState.focus&&x.viewState.focus.indexOf(Y)>-1&&x.focus.push(K),x&&x.viewState.selection&&x.viewState.selection.indexOf(Y)>-1&&x.selection.push(K),(x&&x.viewState.expanded&&x.viewState.expanded.indexOf(Y)>-1||j&&K.defaultCollapseState===y.ObjectTreeElementCollapseState.PreserveOrExpanded)&&H.push(K),K});for(const U of V.values())w(U,j=>this.nodes.delete(j.element));for(const U of z)this.nodes.set(U.element,U);return N.children.splice(0,N.children.length,...z),N!==this.root&&this.autoExpandSingleChildren&&z.length===1&&H.length===0&&(z[0].forceExpanded=!0,H.push(z[0])),H}render(N,O,F){const x=N.children.map(V=>this.asTreeElement(V,O)),W=F&&{...F,diffIdentityProvider:F.diffIdentityProvider&&{getId(V){return F.diffIdentityProvider.getId(V.element)}}};this.tree.setChildren(N===this.root?null:N,x,W),N!==this.root&&this.tree.setCollapsible(N,N.hasChildren),this._onDidRender.fire()}asTreeElement(N,O){if(N.stale)return{element:N,collapsible:N.hasChildren,collapsed:!0};let F;return O&&O.viewState.expanded&&N.id&&O.viewState.expanded.indexOf(N.id)>-1?F=!1:N.forceExpanded?(F=!1,N.forceExpanded=!1):F=N.defaultCollapseState,{element:N,children:N.hasChildren?o.Iterable.map(N.children,x=>this.asTreeElement(x,O)):[],collapsible:N.hasChildren,collapsed:F}}processChildren(N){return this.sorter&&(N=[...N].sort(this.sorter.compare.bind(this.sorter))),N}dispose(){this.disposables.dispose(),this.tree.dispose()}}e.AsyncDataTree=S;class L{get element(){return{elements:this.node.element.elements.map(N=>N.element),incompressible:this.node.element.incompressible}}get children(){return this.node.children.map(N=>new L(N))}get depth(){return this.node.depth}get visibleChildrenCount(){return this.node.visibleChildrenCount}get visibleChildIndex(){return this.node.visibleChildIndex}get collapsible(){return this.node.collapsible}get collapsed(){return this.node.collapsed}get visible(){return this.node.visible}get filterData(){return this.node.filterData}constructor(N){this.node=N}}class D{constructor(N,O,F,x){this.renderer=N,this.nodeMapper=O,this.compressibleNodeMapperProvider=F,this.onDidChangeTwistieState=x,this.renderedNodes=new Map,this.disposables=[],this.templateId=N.templateId}renderTemplate(N){return{templateData:this.renderer.renderTemplate(N)}}renderElement(N,O,F,x){this.renderer.renderElement(this.nodeMapper.map(N),O,F.templateData,x)}renderCompressedElements(N,O,F,x){this.renderer.renderCompressedElements(this.compressibleNodeMapperProvider().map(N),O,F.templateData,x)}renderTwistie(N,O){return N.slow?(O.classList.add(...b.ThemeIcon.asClassNameArray(_.Codicon.treeItemLoading)),!0):(O.classList.remove(...b.ThemeIcon.asClassNameArray(_.Codicon.treeItemLoading)),!1)}disposeElement(N,O,F,x){this.renderer.disposeElement?.(this.nodeMapper.map(N),O,F.templateData,x)}disposeCompressedElements(N,O,F,x){this.renderer.disposeCompressedElements?.(this.compressibleNodeMapperProvider().map(N),O,F.templateData,x)}disposeTemplate(N){this.renderer.disposeTemplate(N.templateData)}dispose(){this.renderedNodes.clear(),this.disposables=(0,t.dispose)(this.disposables)}}function T(P){const N=P&&v(P);return N&&{...N,keyboardNavigationLabelProvider:N.keyboardNavigationLabelProvider&&{...N.keyboardNavigationLabelProvider,getCompressedNodeKeyboardNavigationLabel(O){return P.keyboardNavigationLabelProvider.getCompressedNodeKeyboardNavigationLabel(O.map(F=>F.element))}}}}class M extends S{constructor(N,O,F,x,W,V,q={}){super(N,O,F,W,V,q),this.compressionDelegate=x,this.compressibleNodeMapper=new y.WeakMapper(H=>new L(H)),this.filter=q.filter}createTree(N,O,F,x,W){const V=new k.ComposedTreeDelegate(F),q=x.map(z=>new D(z,this.nodeMapper,()=>this.compressibleNodeMapper,this._onDidChangeNodeSlowState.event)),H=T(W)||{};return new E.CompressibleObjectTree(N,O,V,q,H)}asTreeElement(N,O){return{incompressible:this.compressionDelegate.isIncompressible(N.element),...super.asTreeElement(N,O)}}updateOptions(N={}){this.tree.updateOptions(N)}render(N,O,F){if(!this.identityProvider)return super.render(N,O);const x=G=>this.identityProvider.getId(G).toString(),W=G=>{const K=new Set;for(const R of G){const J=this.tree.getCompressedTreeNode(R===this.root?null:R);if(J.element)for(const ie of J.element.elements)K.add(x(ie.element))}return K},V=W(this.tree.getSelection()),q=W(this.tree.getFocus());super.render(N,O,F);const H=this.getSelection();let z=!1;const U=this.getFocus();let j=!1;const Y=G=>{const K=G.element;if(K)for(let R=0;R{const F=this.filter.filter(O,1),x=A(F);if(x===2)throw new Error("Recursive tree visibility not supported in async data compressed trees");return x===1})),super.processChildren(N)}}e.CompressibleAsyncDataTree=M;function A(P){return typeof P=="boolean"?P?1:0:(0,I.isFilterResult)(P)?(0,I.getVisibleState)(P.visibility):(0,I.getVisibleState)(P)}}),define(ne[361],se([1,0,8,6,2,42,16,11]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SimpleWorkerServer=e.SimpleWorkerClient=void 0,e.logOnceWebWorkerWarning=o,e.create=f;const _=!1,b="default",p="$initialize";let n=!1;function o(h){y.isWeb&&(n||(n=!0,console.warn("Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq")),console.warn(h.message))}class t{constructor(v,w,S,L,D){this.vsWorker=v,this.req=w,this.channel=S,this.method=L,this.args=D,this.type=0}}class i{constructor(v,w,S,L){this.vsWorker=v,this.seq=w,this.res=S,this.err=L,this.type=1}}class s{constructor(v,w,S,L,D){this.vsWorker=v,this.req=w,this.channel=S,this.eventName=L,this.arg=D,this.type=2}}class g{constructor(v,w,S){this.vsWorker=v,this.req=w,this.event=S,this.type=3}}class c{constructor(v,w){this.vsWorker=v,this.req=w,this.type=4}}class l{constructor(v){this._workerId=-1,this._handler=v,this._lastSentReq=0,this._pendingReplies=Object.create(null),this._pendingEmitters=new Map,this._pendingEvents=new Map}setWorkerId(v){this._workerId=v}sendMessage(v,w,S){const L=String(++this._lastSentReq);return new Promise((D,T)=>{this._pendingReplies[L]={resolve:D,reject:T},this._send(new t(this._workerId,L,v,w,S))})}listen(v,w,S){let L=null;const D=new k.Emitter({onWillAddFirstListener:()=>{L=String(++this._lastSentReq),this._pendingEmitters.set(L,D),this._send(new s(this._workerId,L,v,w,S))},onDidRemoveLastListener:()=>{this._pendingEmitters.delete(L),this._send(new c(this._workerId,L)),L=null}});return D.event}handleMessage(v){!v||!v.vsWorker||this._workerId!==-1&&v.vsWorker!==this._workerId||this._handleMessage(v)}createProxyToRemoteChannel(v,w){const S={get:(L,D)=>(typeof D=="string"&&!L[D]&&(u(D)?L[D]=T=>this.listen(v,D,T):r(D)?L[D]=this.listen(v,D,void 0):D.charCodeAt(0)===36&&(L[D]=async(...T)=>(await w?.(),this.sendMessage(v,D,T)))),L[D])};return new Proxy(Object.create(null),S)}_handleMessage(v){switch(v.type){case 1:return this._handleReplyMessage(v);case 0:return this._handleRequestMessage(v);case 2:return this._handleSubscribeEventMessage(v);case 3:return this._handleEventMessage(v);case 4:return this._handleUnsubscribeEventMessage(v)}}_handleReplyMessage(v){if(!this._pendingReplies[v.seq]){console.warn("Got reply to unknown seq");return}const w=this._pendingReplies[v.seq];if(delete this._pendingReplies[v.seq],v.err){let S=v.err;v.err.$isError&&(S=new Error,S.name=v.err.name,S.message=v.err.message,S.stack=v.err.stack),w.reject(S);return}w.resolve(v.res)}_handleRequestMessage(v){const w=v.req;this._handler.handleMessage(v.channel,v.method,v.args).then(L=>{this._send(new i(this._workerId,w,L,void 0))},L=>{L.detail instanceof Error&&(L.detail=(0,d.transformErrorForSerialization)(L.detail)),this._send(new i(this._workerId,w,void 0,(0,d.transformErrorForSerialization)(L)))})}_handleSubscribeEventMessage(v){const w=v.req,S=this._handler.handleEvent(v.channel,v.eventName,v.arg)(L=>{this._send(new g(this._workerId,w,L))});this._pendingEvents.set(w,S)}_handleEventMessage(v){if(!this._pendingEmitters.has(v.req)){console.warn("Got event for unknown req");return}this._pendingEmitters.get(v.req).fire(v.event)}_handleUnsubscribeEventMessage(v){if(!this._pendingEvents.has(v.req)){console.warn("Got unsubscribe for unknown req");return}this._pendingEvents.get(v.req).dispose(),this._pendingEvents.delete(v.req)}_send(v){const w=[];if(v.type===0)for(let S=0;S{this._protocol.handleMessage(D)},D=>{(0,d.onUnexpectedError)(D)})),this._protocol=new l({sendMessage:(D,T)=>{this._worker.postMessage(D,T)},handleMessage:(D,T,M)=>this._handleMessage(D,T,M),handleEvent:(D,T,M)=>this._handleEvent(D,T,M)}),this._protocol.setWorkerId(this._worker.getId());let S=null;const L=globalThis.require;typeof L<"u"&&typeof L.getConfig=="function"?S=L.getConfig():typeof globalThis.requirejs<"u"&&(S=globalThis.requirejs.s.contexts._.config),this._onModuleLoaded=this._protocol.sendMessage(b,p,[this._worker.getId(),JSON.parse(JSON.stringify(S)),w.amdModuleId]),this.proxy=this._protocol.createProxyToRemoteChannel(b,async()=>{await this._onModuleLoaded}),this._onModuleLoaded.catch(D=>{this._onError("Worker failed to load "+w.amdModuleId,D)})}_handleMessage(v,w,S){const L=this._localChannels.get(v);if(!L)return Promise.reject(new Error(`Missing channel ${v} on main thread`));if(typeof L[w]!="function")return Promise.reject(new Error(`Missing method ${w} on main thread channel ${v}`));try{return Promise.resolve(L[w].apply(L,S))}catch(D){return Promise.reject(D)}}_handleEvent(v,w,S){const L=this._localChannels.get(v);if(!L)throw new Error(`Missing channel ${v} on main thread`);if(u(w)){const D=L[w].call(L,S);if(typeof D!="function")throw new Error(`Missing dynamic event ${w} on main thread channel ${v}.`);return D}if(r(w)){const D=L[w];if(typeof D!="function")throw new Error(`Missing event ${w} on main thread channel ${v}.`);return D}throw new Error(`Malformed event name ${w}`)}setChannel(v,w){this._localChannels.set(v,w)}_onError(v,w){console.error(v),console.info(w)}}e.SimpleWorkerClient=a;function r(h){return h[0]==="o"&&h[1]==="n"&&m.isUpperAsciiLetter(h.charCodeAt(2))}function u(h){return/^onDynamic/.test(h)&&m.isUpperAsciiLetter(h.charCodeAt(9))}class C{constructor(v,w){this._localChannels=new Map,this._remoteChannels=new Map,this._requestHandlerFactory=w,this._requestHandler=null,this._protocol=new l({sendMessage:(S,L)=>{v(S,L)},handleMessage:(S,L,D)=>this._handleMessage(S,L,D),handleEvent:(S,L,D)=>this._handleEvent(S,L,D)})}onmessage(v){this._protocol.handleMessage(v)}_handleMessage(v,w,S){if(v===b&&w===p)return this.initialize(S[0],S[1],S[2]);const L=v===b?this._requestHandler:this._localChannels.get(v);if(!L)return Promise.reject(new Error(`Missing channel ${v} on worker thread`));if(typeof L[w]!="function")return Promise.reject(new Error(`Missing method ${w} on worker thread channel ${v}`));try{return Promise.resolve(L[w].apply(L,S))}catch(D){return Promise.reject(D)}}_handleEvent(v,w,S){const L=v===b?this._requestHandler:this._localChannels.get(v);if(!L)throw new Error(`Missing channel ${v} on worker thread`);if(u(w)){const D=L[w].call(L,S);if(typeof D!="function")throw new Error(`Missing dynamic event ${w} on request handler.`);return D}if(r(w)){const D=L[w];if(typeof D!="function")throw new Error(`Missing event ${w} on request handler.`);return D}throw new Error(`Malformed event name ${w}`)}getChannel(v){if(!this._remoteChannels.has(v)){const w=this._protocol.createProxyToRemoteChannel(v);this._remoteChannels.set(v,w)}return this._remoteChannels.get(v)}async initialize(v,w,S){if(this._protocol.setWorkerId(v),this._requestHandlerFactory){this._requestHandler=this._requestHandlerFactory(this);return}if(w&&(typeof w.baseUrl<"u"&&delete w.baseUrl,typeof w.paths<"u"&&typeof w.paths.vs<"u"&&delete w.paths.vs,typeof w.trustedTypesPolicy<"u"&&delete w.trustedTypesPolicy,w.catchError=!0,globalThis.require.config(w)),_){const L=E.FileAccess.asBrowserUri(`${S}.js`).toString(!0);return new Promise((D,T)=>{oe([`${L}`],D,T)}).then(D=>{if(this._requestHandler=D.create(this),!this._requestHandler)throw new Error("No RequestHandler!")})}return new Promise((L,D)=>{(globalThis.require||oe)([S],M=>{if(this._requestHandler=M.create(this),!this._requestHandler){D(new Error("No RequestHandler!"));return}L()},D)})}}e.SimpleWorkerServer=C;function f(h){return new C(h,null)}}),define(ne[646],se([1,0,103,8,42,361,2,13,3]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.WorkerDescriptor=void 0,e.createWebWorker=l;const b=!1;let p;typeof self=="object"&&self.constructor&&self.constructor.name==="DedicatedWorkerGlobalScope"&&globalThis.workerttPolicy!==void 0?p=globalThis.workerttPolicy:p=(0,d.createTrustedTypesPolicy)("defaultWorkerFactory",{createScriptURL:a=>a});function n(a,r){const u=globalThis.MonacoEnvironment;if(u){if(typeof u.getWorker=="function")return u.getWorker("workerMain.js",r);if(typeof u.getWorkerUrl=="function"){const C=u.getWorkerUrl("workerMain.js",r);return new Worker(p?p.createScriptURL(C):C,{name:r,type:b?"module":void 0})}}if(typeof oe=="function"){const C=oe.toUrl("vs/base/worker/workerMain.js"),f="vs/base/worker/defaultWorkerFactory.js",h=oe.toUrl(f).slice(0,-f.length),v=o(r,C,h);return new Worker(p?p.createScriptURL(v):v,{name:r,type:b?"module":void 0})}if(a){const C=o(r,a.toString(!0)),f=new Worker(p?p.createScriptURL(C):C,{name:r,type:b?"module":void 0});return b?t(f):f}throw new Error("You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker")}function o(a,r,u){const C=/^((http:)|(https:)|(file:)|(vscode-file:))/.test(r);if(!(C&&r.substring(0,globalThis.origin.length)!==globalThis.origin)){const h=r.lastIndexOf("?"),v=r.lastIndexOf("#",h),w=h>0?new URLSearchParams(r.substring(h+1,~v?v:void 0)):new URLSearchParams;I.COI.addSearchParam(w,!0,!0),w.toString()?r=`${r}?${w.toString()}#${a}`:r=`${r}#${a}`}!b&&!C&&(r=new URL(r,globalThis.origin).toString());const f=new Blob([(0,m.coalesce)([`/*${a}*/`,u?`globalThis.MonacoEnvironment = { baseUrl: '${u}' };`:void 0,`globalThis._VSCODE_NLS_MESSAGES = ${JSON.stringify((0,_.getNLSMessages)())};`,`globalThis._VSCODE_NLS_LANGUAGE = ${JSON.stringify((0,_.getNLSLanguage)())};`,`globalThis._VSCODE_FILE_ROOT = '${globalThis._VSCODE_FILE_ROOT}';`,"const ttPolicy = globalThis.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });","globalThis.workerttPolicy = ttPolicy;",b?`await import(ttPolicy?.createScriptURL('${r}') ?? '${r}');`:`importScripts(ttPolicy?.createScriptURL('${r}') ?? '${r}');`,b?"globalThis.postMessage({ type: 'vscode-worker-ready' });":void 0,`/*${a}*/`]).join("")],{type:"application/javascript"});return URL.createObjectURL(f)}function t(a){return new Promise((r,u)=>{a.onmessage=function(C){C.data.type==="vscode-worker-ready"&&(a.onmessage=null,r(a))},a.onerror=u})}function i(a){return typeof a.then=="function"}class s extends y.Disposable{constructor(r,u,C,f,h,v){super(),this.id=C,this.label=f;const w=n(r,f);i(w)?this.worker=w:this.worker=Promise.resolve(w),this.postMessage(u,[]),this.worker.then(S=>{S.onmessage=function(L){h(L.data)},S.onmessageerror=v,typeof S.addEventListener=="function"&&S.addEventListener("error",v)}),this._register((0,y.toDisposable)(()=>{this.worker?.then(S=>{S.onmessage=null,S.onmessageerror=null,S.removeEventListener("error",v),S.terminate()}),this.worker=null}))}getId(){return this.id}postMessage(r,u){this.worker?.then(C=>{try{C.postMessage(r,u)}catch(f){(0,k.onUnexpectedError)(f),(0,k.onUnexpectedError)(new Error(`FAILED to post message to '${this.label}'-worker`,{cause:f}))}})}}class g{constructor(r,u){this.amdModuleId=r,this.label=u,this.esmModuleLocation=b?I.FileAccess.asBrowserUri(`${r}.esm.js`):void 0}}e.WorkerDescriptor=g;class c{static{this.LAST_WORKER_ID=0}constructor(){this._webWorkerFailedBeforeError=!1}create(r,u,C){const f=++c.LAST_WORKER_ID;if(this._webWorkerFailedBeforeError)throw this._webWorkerFailedBeforeError;return new s(r.esmModuleLocation,r.amdModuleId,f,r.label||"anonymous"+f,u,h=>{(0,E.logOnceWebWorkerWarning)(h),this._webWorkerFailedBeforeError=h,C(h)})}}function l(a,r){const u=typeof a=="string"?new g(a,r):a;return new E.SimpleWorkerClient(new c,u)}}),define(ne[647],se([1,0,14,6,2,252,19]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InMemoryStorageDatabase=e.Storage=e.StorageState=e.StorageHint=void 0;var m;(function(n){n[n.STORAGE_DOES_NOT_EXIST=0]="STORAGE_DOES_NOT_EXIST",n[n.STORAGE_IN_MEMORY=1]="STORAGE_IN_MEMORY"})(m||(e.StorageHint=m={}));var _;(function(n){n[n.None=0]="None",n[n.Initialized=1]="Initialized",n[n.Closed=2]="Closed"})(_||(e.StorageState=_={}));class b extends I.Disposable{static{this.DEFAULT_FLUSH_DELAY=100}constructor(o,t=Object.create(null)){super(),this.database=o,this.options=t,this._onDidChangeStorage=this._register(new k.PauseableEmitter),this.onDidChangeStorage=this._onDidChangeStorage.event,this.state=_.None,this.cache=new Map,this.flushDelayer=this._register(new d.ThrottledDelayer(b.DEFAULT_FLUSH_DELAY)),this.pendingDeletes=new Set,this.pendingInserts=new Map,this.whenFlushedCallbacks=[],this.registerListeners()}registerListeners(){this._register(this.database.onDidChangeItemsExternal(o=>this.onDidChangeItemsExternal(o)))}onDidChangeItemsExternal(o){this._onDidChangeStorage.pause();try{o.changed?.forEach((t,i)=>this.acceptExternal(i,t)),o.deleted?.forEach(t=>this.acceptExternal(t,void 0))}finally{this._onDidChangeStorage.resume()}}acceptExternal(o,t){if(this.state===_.Closed)return;let i=!1;(0,y.isUndefinedOrNull)(t)?i=this.cache.delete(o):this.cache.get(o)!==t&&(this.cache.set(o,t),i=!0),i&&this._onDidChangeStorage.fire({key:o,external:!0})}get(o,t){const i=this.cache.get(o);return(0,y.isUndefinedOrNull)(i)?t:i}getBoolean(o,t){const i=this.get(o);return(0,y.isUndefinedOrNull)(i)?t:i==="true"}getNumber(o,t){const i=this.get(o);return(0,y.isUndefinedOrNull)(i)?t:parseInt(i,10)}async set(o,t,i=!1){if(this.state===_.Closed)return;if((0,y.isUndefinedOrNull)(t))return this.delete(o,i);const s=(0,y.isObject)(t)||Array.isArray(t)?(0,E.stringify)(t):String(t);if(this.cache.get(o)!==s)return this.cache.set(o,s),this.pendingInserts.set(o,s),this.pendingDeletes.delete(o),this._onDidChangeStorage.fire({key:o,external:i}),this.doFlush()}async delete(o,t=!1){if(!(this.state===_.Closed||!this.cache.delete(o)))return this.pendingDeletes.has(o)||this.pendingDeletes.add(o),this.pendingInserts.delete(o),this._onDidChangeStorage.fire({key:o,external:t}),this.doFlush()}get hasPending(){return this.pendingInserts.size>0||this.pendingDeletes.size>0}async flushPending(){if(!this.hasPending)return;const o={insert:this.pendingInserts,delete:this.pendingDeletes};return this.pendingDeletes=new Set,this.pendingInserts=new Map,this.database.updateItems(o).finally(()=>{if(!this.hasPending)for(;this.whenFlushedCallbacks.length;)this.whenFlushedCallbacks.pop()?.()})}async doFlush(o){return this.options.hint===m.STORAGE_IN_MEMORY?this.flushPending():this.flushDelayer.trigger(()=>this.flushPending(),o)}}e.Storage=b;class p{constructor(){this.onDidChangeItemsExternal=k.Event.None,this.items=new Map}async updateItems(o){o.insert?.forEach((t,i)=>this.items.set(i,t)),o.delete?.forEach(t=>this.items.delete(t))}}e.InMemoryStorageDatabase=p}),define(ne[362],se([1,0,2,6,5]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ElementSizeObserver=void 0;class E extends d.Disposable{constructor(m,_){super(),this._onDidChange=this._register(new k.Emitter),this.onDidChange=this._onDidChange.event,this._referenceDomElement=m,this._width=-1,this._height=-1,this._resizeObserver=null,this.measureReferenceDomElement(!1,_)}dispose(){this.stopObserving(),super.dispose()}getWidth(){return this._width}getHeight(){return this._height}startObserving(){if(!this._resizeObserver&&this._referenceDomElement){let m=null;const _=()=>{m?this.observe({width:m.width,height:m.height}):this.observe()};let b=!1,p=!1;const n=()=>{if(b&&!p)try{b=!1,p=!0,_()}finally{(0,I.scheduleAtNextAnimationFrame)((0,I.getWindow)(this._referenceDomElement),()=>{p=!1,n()})}};this._resizeObserver=new ResizeObserver(o=>{o&&o[0]&&o[0].contentRect?m={width:o[0].contentRect.width,height:o[0].contentRect.height}:m=null,b=!0,n()}),this._resizeObserver.observe(this._referenceDomElement)}}stopObserving(){this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null)}observe(m){this.measureReferenceDomElement(!0,m)}measureReferenceDomElement(m,_){let b=0,p=0;_?(b=_.width,p=_.height):this._referenceDomElement&&(b=this._referenceDomElement.clientWidth,p=this._referenceDomElement.clientHeight),b=Math.max(5,b),p=Math.max(5,p),(this._width!==b||this._height!==p)&&(this._width=b,this._height=p,m&&this._onDidChange.fire())}}e.ElementSizeObserver=E}),define(ne[648],se([1,0,5,18,57,19,3]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ManagedHoverWidget=void 0;class m{constructor(b,p,n){this.hoverDelegate=b,this.target=p,this.fadeInAnimation=n}async update(b,p,n){if(this._cancellationTokenSource&&(this._cancellationTokenSource.dispose(!0),this._cancellationTokenSource=void 0),this.isDisposed)return;let o;if(b===void 0||(0,E.isString)(b)||(0,d.isHTMLElement)(b))o=b;else if(!(0,E.isFunction)(b.markdown))o=b.markdown??b.markdownNotSupportedFallback;else{this._hoverWidget||this.show((0,y.localize)(69,"Loading..."),p,n),this._cancellationTokenSource=new k.CancellationTokenSource;const t=this._cancellationTokenSource.token;if(o=await b.markdown(t),o===void 0&&(o=b.markdownNotSupportedFallback),this.isDisposed||t.isCancellationRequested)return}this.show(o,p,n)}show(b,p,n){const o=this._hoverWidget;if(this.hasContent(b)){const t={content:b,target:this.target,actions:n?.actions,linkHandler:n?.linkHandler,trapFocus:n?.trapFocus,appearance:{showPointer:this.hoverDelegate.placement==="element",skipFadeInAnimation:!this.fadeInAnimation||!!o,showHoverHint:n?.appearance?.showHoverHint},position:{hoverPosition:2}};this._hoverWidget=this.hoverDelegate.showHover(t,p)}o?.dispose()}hasContent(b){return b?(0,I.isMarkdownString)(b)?!!b.value:!0:!1}get isDisposed(){return this._hoverWidget?.isDisposed}dispose(){this._hoverWidget?.dispose(),this._cancellationTokenSource?.dispose(!0),this._cancellationTokenSource=void 0}}e.ManagedHoverWidget=m}),define(ne[649],se([1,0,5,39,56]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewContentWidgets=void 0;class E extends I.ViewPart{constructor(o,t){super(o),this._viewDomNode=t,this._widgets={},this.domNode=(0,k.createFastDomNode)(document.createElement("div")),I.PartFingerprints.write(this.domNode,1),this.domNode.setClassName("contentWidgets"),this.domNode.setPosition("absolute"),this.domNode.setTop(0),this.overflowingContentWidgetsDomNode=(0,k.createFastDomNode)(document.createElement("div")),I.PartFingerprints.write(this.overflowingContentWidgetsDomNode,2),this.overflowingContentWidgetsDomNode.setClassName("overflowingContentWidgets")}dispose(){super.dispose(),this._widgets={}}onConfigurationChanged(o){const t=Object.keys(this._widgets);for(const i of t)this._widgets[i].onConfigurationChanged(o);return!0}onDecorationsChanged(o){return!0}onFlushed(o){return!0}onLineMappingChanged(o){return this._updateAnchorsViewPositions(),!0}onLinesChanged(o){return this._updateAnchorsViewPositions(),!0}onLinesDeleted(o){return this._updateAnchorsViewPositions(),!0}onLinesInserted(o){return this._updateAnchorsViewPositions(),!0}onScrollChanged(o){return!0}onZonesChanged(o){return!0}_updateAnchorsViewPositions(){const o=Object.keys(this._widgets);for(const t of o)this._widgets[t].updateAnchorViewPosition()}addWidget(o){const t=new y(this._context,this._viewDomNode,o);this._widgets[t.id]=t,t.allowEditorOverflow?this.overflowingContentWidgetsDomNode.appendChild(t.domNode):this.domNode.appendChild(t.domNode),this.setShouldRender()}setWidgetPosition(o,t,i,s,g){this._widgets[o.getId()].setPosition(t,i,s,g),this.setShouldRender()}removeWidget(o){const t=o.getId();if(this._widgets.hasOwnProperty(t)){const i=this._widgets[t];delete this._widgets[t];const s=i.domNode.domNode;s.remove(),s.removeAttribute("monaco-visible-content-widget"),this.setShouldRender()}}shouldSuppressMouseDownOnWidget(o){return this._widgets.hasOwnProperty(o)?this._widgets[o].suppressMouseDown:!1}onBeforeRender(o){const t=Object.keys(this._widgets);for(const i of t)this._widgets[i].onBeforeRender(o)}prepareRender(o){const t=Object.keys(this._widgets);for(const i of t)this._widgets[i].prepareRender(o)}render(o){const t=Object.keys(this._widgets);for(const i of t)this._widgets[i].render(o)}}e.ViewContentWidgets=E;class y{constructor(o,t,i){this._primaryAnchor=new m(null,null),this._secondaryAnchor=new m(null,null),this._context=o,this._viewDomNode=t,this._actual=i,this.domNode=(0,k.createFastDomNode)(this._actual.getDomNode()),this.id=this._actual.getId(),this.allowEditorOverflow=this._actual.allowEditorOverflow||!1,this.suppressMouseDown=this._actual.suppressMouseDown||!1;const s=this._context.configuration.options,g=s.get(146);this._fixedOverflowWidgets=s.get(42),this._contentWidth=g.contentWidth,this._contentLeft=g.contentLeft,this._lineHeight=s.get(67),this._affinity=null,this._preference=[],this._cachedDomNodeOffsetWidth=-1,this._cachedDomNodeOffsetHeight=-1,this._maxWidth=this._getMaxWidth(),this._isVisible=!1,this._renderData=null,this.domNode.setPosition(this._fixedOverflowWidgets&&this.allowEditorOverflow?"fixed":"absolute"),this.domNode.setDisplay("none"),this.domNode.setVisibility("hidden"),this.domNode.setAttribute("widgetId",this.id),this.domNode.setMaxWidth(this._maxWidth)}onConfigurationChanged(o){const t=this._context.configuration.options;if(this._lineHeight=t.get(67),o.hasChanged(146)){const i=t.get(146);this._contentLeft=i.contentLeft,this._contentWidth=i.contentWidth,this._maxWidth=this._getMaxWidth()}}updateAnchorViewPosition(){this._setPosition(this._affinity,this._primaryAnchor.modelPosition,this._secondaryAnchor.modelPosition)}_setPosition(o,t,i){this._affinity=o,this._primaryAnchor=s(t,this._context.viewModel,this._affinity),this._secondaryAnchor=s(i,this._context.viewModel,this._affinity);function s(g,c,l){if(!g)return new m(null,null);const a=c.model.validatePosition(g);if(c.coordinatesConverter.modelPositionIsVisible(a)){const r=c.coordinatesConverter.convertModelPositionToViewPosition(a,l??void 0);return new m(g,r)}return new m(g,null)}}_getMaxWidth(){const o=this.domNode.domNode.ownerDocument,t=o.defaultView;return this.allowEditorOverflow?t?.innerWidth||o.documentElement.offsetWidth||o.body.offsetWidth:this._contentWidth}setPosition(o,t,i,s){this._setPosition(s,o,t),this._preference=i,this._primaryAnchor.viewPosition&&this._preference&&this._preference.length>0?this.domNode.setDisplay("block"):this.domNode.setDisplay("none"),this._cachedDomNodeOffsetWidth=-1,this._cachedDomNodeOffsetHeight=-1}_layoutBoxInViewport(o,t,i,s){const g=o.top,c=g,l=o.top+o.height,a=s.viewportHeight-l,r=g-i,u=c>=i,C=l,f=a>=i;let h=o.left;return h+t>s.scrollLeft+s.viewportWidth&&(h=s.scrollLeft+s.viewportWidth-t),ha){const f=C-(a-s);C-=f,i-=f}if(C=w,D=C+i<=f.height-S;return this._fixedOverflowWidgets?{fitsAbove:L,aboveTop:Math.max(u,w),fitsBelow:D,belowTop:C,left:v}:{fitsAbove:L,aboveTop:g,fitsBelow:D,belowTop:c,left:h}}_prepareRenderWidgetAtExactPositionOverflowing(o){return new _(o.top,o.left+this._contentLeft)}_getAnchorsCoordinates(o){const t=g(this._primaryAnchor.viewPosition,this._affinity,this._lineHeight),i=this._secondaryAnchor.viewPosition?.lineNumber===this._primaryAnchor.viewPosition?.lineNumber?this._secondaryAnchor.viewPosition:null,s=g(i,this._affinity,this._lineHeight);return{primary:t,secondary:s};function g(c,l,a){if(!c)return null;const r=o.visibleRangeForPosition(c);if(!r)return null;const u=c.column===1&&l===3?0:r.left,C=o.getVerticalOffsetForLineNumber(c.lineNumber)-o.scrollTop;return new b(C,u,a)}}_reduceAnchorCoordinates(o,t,i){if(!t)return o;const s=this._context.configuration.options.get(50);let g=t.left;return go.endLineNumber||this.domNode.setMaxWidth(this._maxWidth)}prepareRender(o){this._renderData=this._prepareRenderWidget(o)}render(o){if(!this._renderData||this._renderData.kind==="offViewport"){this._isVisible&&(this.domNode.removeAttribute("monaco-visible-content-widget"),this._isVisible=!1,this._renderData?.kind==="offViewport"&&this._renderData.preserveFocus?this.domNode.setTop(-1e3):this.domNode.setVisibility("hidden")),typeof this._actual.afterRender=="function"&&p(this._actual.afterRender,this._actual,null);return}this.allowEditorOverflow?(this.domNode.setTop(this._renderData.coordinate.top),this.domNode.setLeft(this._renderData.coordinate.left)):(this.domNode.setTop(this._renderData.coordinate.top+o.scrollTop-o.bigNumbersDelta),this.domNode.setLeft(this._renderData.coordinate.left)),this._isVisible||(this.domNode.setVisibility("inherit"),this.domNode.setAttribute("monaco-visible-content-widget","true"),this._isVisible=!0),typeof this._actual.afterRender=="function"&&p(this._actual.afterRender,this._actual,this._renderData.position)}}class m{constructor(o,t){this.modelPosition=o,this.viewPosition=t}}class _{constructor(o,t){this.top=o,this.left=t,this._coordinateBrand=void 0}}class b{constructor(o,t,i){this.top=o,this.left=t,this.height=i,this._anchorCoordinateBrand=void 0}}function p(n,o,...t){try{return n.call(o,...t)}catch{return null}}}),define(ne[650],se([1,0,39,56,5,492]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewOverlayWidgets=void 0;class E extends k.ViewPart{constructor(m,_){super(m),this._viewDomNode=_;const p=this._context.configuration.options.get(146);this._widgets={},this._verticalScrollbarWidth=p.verticalScrollbarWidth,this._minimapWidth=p.minimap.minimapWidth,this._horizontalScrollbarHeight=p.horizontalScrollbarHeight,this._editorHeight=p.height,this._editorWidth=p.width,this._viewDomNodeRect={top:0,left:0,width:0,height:0},this._domNode=(0,d.createFastDomNode)(document.createElement("div")),k.PartFingerprints.write(this._domNode,4),this._domNode.setClassName("overlayWidgets"),this.overflowingOverlayWidgetsDomNode=(0,d.createFastDomNode)(document.createElement("div")),k.PartFingerprints.write(this.overflowingOverlayWidgetsDomNode,5),this.overflowingOverlayWidgetsDomNode.setClassName("overflowingOverlayWidgets")}dispose(){super.dispose(),this._widgets={}}getDomNode(){return this._domNode}onConfigurationChanged(m){const b=this._context.configuration.options.get(146);return this._verticalScrollbarWidth=b.verticalScrollbarWidth,this._minimapWidth=b.minimap.minimapWidth,this._horizontalScrollbarHeight=b.horizontalScrollbarHeight,this._editorHeight=b.height,this._editorWidth=b.width,!0}addWidget(m){const _=(0,d.createFastDomNode)(m.getDomNode());this._widgets[m.getId()]={widget:m,preference:null,domNode:_},_.setPosition("absolute"),_.setAttribute("widgetId",m.getId()),m.allowEditorOverflow?this.overflowingOverlayWidgetsDomNode.appendChild(_):this._domNode.appendChild(_),this.setShouldRender(),this._updateMaxMinWidth()}setWidgetPosition(m,_){const b=this._widgets[m.getId()],p=_?_.preference:null,n=_?.stackOridinal;return b.preference===p&&b.stack===n?(this._updateMaxMinWidth(),!1):(b.preference=p,b.stack=n,this.setShouldRender(),this._updateMaxMinWidth(),!0)}removeWidget(m){const _=m.getId();if(this._widgets.hasOwnProperty(_)){const p=this._widgets[_].domNode.domNode;delete this._widgets[_],p.remove(),this.setShouldRender(),this._updateMaxMinWidth()}}_updateMaxMinWidth(){let m=0;const _=Object.keys(this._widgets);for(let b=0,p=_.length;b0);_.sort((p,n)=>(this._widgets[p].stack||0)-(this._widgets[n].stack||0));for(let p=0,n=_.length;p{this._instantiateSome(1)})),this._register((0,d.runWhenWindowIdle)((0,d.getWindow)(this._editor.getDomNode()),()=>{this._instantiateSome(2)})),this._register((0,d.runWhenWindowIdle)((0,d.getWindow)(this._editor.getDomNode()),()=>{this._instantiateSome(3)},5e3))}saveViewState(){const m={};for(const[_,b]of this._instances)typeof b.saveViewState=="function"&&(m[_]=b.saveViewState());return m}restoreViewState(m){for(const[_,b]of this._instances)typeof b.restoreViewState=="function"&&b.restoreViewState(m[_])}get(m){return this._instantiateById(m),this._instances.get(m)||null}onBeforeInteractionEvent(){this._instantiateSome(2)}onAfterModelAttached(){return(0,d.runWhenWindowIdle)((0,d.getWindow)(this._editor?.getDomNode()),()=>{this._instantiateSome(1)},50)}_instantiateSome(m){if(this._finishedInstantiation[m])return;this._finishedInstantiation[m]=!0;const _=this._findPendingContributionsByInstantiation(m);for(const b of _)this._instantiateById(b.id)}_findPendingContributionsByInstantiation(m){const _=[];for(const[,b]of this._pending)b.instantiation===m&&_.push(b);return _}_instantiateById(m){const _=this._pending.get(m);if(_){if(this._pending.delete(m),!this._instantiationService||!this._editor)throw new Error("Cannot instantiate contributions before being initialized!");try{const b=this._instantiationService.createInstance(_.ctor,this._editor);this._instances.set(_.id,b),typeof b.restoreViewState=="function"&&_.instantiation!==0&&console.warn(`Editor contribution '${_.id}' should be eager instantiated because it uses saveViewState / restoreViewState.`)}catch(b){(0,k.onUnexpectedError)(b)}}}}e.CodeEditorContributions=E}),define(ne[363],se([1,0,173,2,21,65]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorSash=e.SashLayout=void 0;class y{resetSash(){this._sashRatio.set(void 0,void 0)}constructor(b,p){this._options=b,this.dimensions=p,this.sashLeft=(0,E.derivedWithSetter)(this,n=>{const o=this._sashRatio.read(n)??this._options.splitViewDefaultRatio.read(n);return this._computeSashLeft(o,n)},(n,o)=>{const t=this.dimensions.width.get();this._sashRatio.set(n/t,o)}),this._sashRatio=(0,I.observableValue)(this,void 0)}_computeSashLeft(b,p){const n=this.dimensions.width.read(p),o=Math.floor(this._options.splitViewDefaultRatio.read(p)*n),t=this._options.enableSplitViewResizing.read(p)?Math.floor(b*n):o,i=100;return n<=i*2?o:tn-i?n-i:t}}e.SashLayout=y;class m extends k.Disposable{constructor(b,p,n,o,t,i){super(),this._domNode=b,this._dimensions=p,this._enabled=n,this._boundarySashes=o,this.sashLeft=t,this._resetSash=i,this._sash=this._register(new d.Sash(this._domNode,{getVerticalSashTop:s=>0,getVerticalSashLeft:s=>this.sashLeft.get(),getVerticalSashHeight:s=>this._dimensions.height.get()},{orientation:0})),this._startSashPosition=void 0,this._register(this._sash.onDidStart(()=>{this._startSashPosition=this.sashLeft.get()})),this._register(this._sash.onDidChange(s=>{this.sashLeft.set(this._startSashPosition+(s.currentX-s.startX),void 0)})),this._register(this._sash.onDidEnd(()=>this._sash.layout())),this._register(this._sash.onDidReset(()=>this._resetSash())),this._register((0,I.autorun)(s=>{const g=this._boundarySashes.read(s);g&&(this._sash.orthogonalEndSash=g.bottom)})),this._register((0,I.autorun)(s=>{const g=this._enabled.read(s);this._sash.state=g?3:0,this.sashLeft.read(s),this._dimensions.height.read(s),this._sash.layout()}))}}e.DiffEditorSash=m}),define(ne[652],se([1,0,5,41,26,2,16,30,3]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlineDiffDeletedCodeMargin=void 0;class b extends E.Disposable{get visibility(){return this._visibility}set visibility(n){this._visibility!==n&&(this._visibility=n,this._diffActions.style.visibility=n?"visible":"hidden")}constructor(n,o,t,i,s,g,c,l,a){super(),this._getViewZoneId=n,this._marginDomNode=o,this._modifiedEditor=t,this._diff=i,this._editor=s,this._viewLineCounts=g,this._originalTextModel=c,this._contextMenuService=l,this._clipboardService=a,this._visibility=!1,this._marginDomNode.style.zIndex="10",this._diffActions=document.createElement("div"),this._diffActions.className=m.ThemeIcon.asClassName(I.Codicon.lightBulb)+" lightbulb-glyph",this._diffActions.style.position="absolute";const r=this._modifiedEditor.getOption(67);this._diffActions.style.right="0px",this._diffActions.style.visibility="hidden",this._diffActions.style.height=`${r}px`,this._diffActions.style.lineHeight=`${r}px`,this._marginDomNode.appendChild(this._diffActions);let u=0;const C=t.getOption(128)&&!y.isIOS,f=(h,v)=>{this._contextMenuService.showContextMenu({domForShadowRoot:C?t.getDomNode()??void 0:void 0,getAnchor:()=>({x:h,y:v}),getActions:()=>{const w=[],S=i.modified.isEmpty;return w.push(new k.Action("diff.clipboard.copyDeletedContent",S?i.original.length>1?(0,_.localize)(99,"Copy deleted lines"):(0,_.localize)(100,"Copy deleted line"):i.original.length>1?(0,_.localize)(101,"Copy changed lines"):(0,_.localize)(102,"Copy changed line"),void 0,!0,async()=>{const D=this._originalTextModel.getValueInRange(i.original.toExclusiveRange());await this._clipboardService.writeText(D)})),i.original.length>1&&w.push(new k.Action("diff.clipboard.copyDeletedLineContent",S?(0,_.localize)(103,"Copy deleted line ({0})",i.original.startLineNumber+u):(0,_.localize)(104,"Copy changed line ({0})",i.original.startLineNumber+u),void 0,!0,async()=>{let D=this._originalTextModel.getLineContent(i.original.startLineNumber+u);D===""&&(D=this._originalTextModel.getEndOfLineSequence()===0?` `:`\r `),await this._clipboardService.writeText(D)})),t.getOption(92)||w.push(new k.Action("diff.inline.revertChange",(0,_.localize)(105,"Revert this change"),void 0,!0,async()=>{this._editor.revert(this._diff)})),w},autoSelectFirstItem:!0})};this._register((0,d.addStandardDisposableListener)(this._diffActions,"mousedown",h=>{if(!h.leftButton)return;const{top:v,height:w}=(0,d.getDomNodePagePosition)(this._diffActions),S=Math.floor(r/3);h.preventDefault(),f(h.posx,v+w+S)})),this._register(t.onMouseMove(h=>{(h.target.type===8||h.target.type===5)&&h.target.detail.viewZoneId===this._getViewZoneId()?(u=this._updateLightBulbPosition(this._marginDomNode,h.event.browserEvent.y,r),this.visibility=!0):this.visibility=!1})),this._register(t.onMouseDown(h=>{h.event.leftButton&&(h.target.type===8||h.target.type===5)&&h.target.detail.viewZoneId===this._getViewZoneId()&&(h.event.preventDefault(),u=this._updateLightBulbPosition(this._marginDomNode,h.event.browserEvent.y,r),f(h.event.posx,h.event.posy+r))}))}_updateLightBulbPosition(n,o,t){const{top:i}=(0,d.getDomNodePagePosition)(n),s=o-i,g=Math.floor(s/t),c=g*t;if(this._diffActions.style.top=`${c}px`,this._viewLineCounts){let l=0;for(let a=0;a{const C=this._diffModel.read(r)?.diff.read(r);if(!C)return o;const f=this._editors.modifiedSelections.read(r);if(f.every(S=>S.isEmpty()))return o;const h=new m.LineRangeSet(f.map(S=>m.LineRange.fromRangeInclusive(S))),w=C.mappings.filter(S=>S.lineRangeMapping.innerChanges&&h.intersects(S.lineRangeMapping.modified)).map(S=>({mapping:S,rangeMappings:S.lineRangeMapping.innerChanges.filter(L=>f.some(D=>_.Range.areIntersecting(L.modifiedRange,D)))}));return w.length===0||w.every(S=>S.rangeMappings.length===0)?o:w}),this._register((0,y.autorunWithStore)((r,u)=>{if(!this._options.shouldRenderOldRevertArrows.read(r))return;const C=this._diffModel.read(r),f=C?.diff.read(r);if(!C||!f||C.movedTextToCompare.read(r))return;const h=[],v=this._selectedDiffs.read(r),w=new Set(v.map(S=>S.mapping));if(v.length>0){const S=this._editors.modifiedSelections.read(r),L=u.add(new i(S[S.length-1].positionLineNumber,this._widget,v.flatMap(D=>D.rangeMappings),!0));this._editors.modified.addGlyphMarginWidget(L),h.push(L)}for(const S of f.mappings)if(!w.has(S)&&!S.lineRangeMapping.modified.isEmpty&&S.lineRangeMapping.innerChanges){const L=u.add(new i(S.lineRangeMapping.modified.startLineNumber,this._widget,S.lineRangeMapping,!1));this._editors.modified.addGlyphMarginWidget(L),h.push(L)}u.add((0,E.toDisposable)(()=>{for(const S of h)this._editors.modified.removeGlyphMarginWidget(S)}))}))}}e.RevertButtonsFeature=t;class i extends E.Disposable{static{this.counter=0}getId(){return this._id}constructor(g,c,l,a){super(),this._lineNumber=g,this._widget=c,this._diffs=l,this._revertSelection=a,this._id=`revertButton${i.counter++}`,this._domNode=(0,d.h)("div.revertButton",{title:this._revertSelection?(0,n.localize)(122,"Revert Selected Changes"):(0,n.localize)(123,"Revert Change")},[(0,k.renderIcon)(I.Codicon.arrowRight)]).root,this._register((0,d.addDisposableListener)(this._domNode,d.EventType.MOUSE_DOWN,r=>{r.button!==2&&(r.stopPropagation(),r.preventDefault())})),this._register((0,d.addDisposableListener)(this._domNode,d.EventType.MOUSE_UP,r=>{r.stopPropagation(),r.preventDefault()})),this._register((0,d.addDisposableListener)(this._domNode,d.EventType.CLICK,r=>{this._diffs instanceof b.LineRangeMapping?this._widget.revert(this._diffs):this._widget.revertRangeMappings(this._diffs),r.stopPropagation(),r.preventDefault()}))}getDomNode(){return this._domNode}getPosition(){return{lane:p.GlyphMarginLane.Right,range:{startColumn:1,startLineNumber:this._lineNumber,endColumn:1,endLineNumber:this._lineNumber},zIndex:10001}}}e.RevertButton=i}),define(ne[88],se([1,0,67,18,2,21,362,9,4,113]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RefCounted=e.DisposableCancellationTokenSource=e.ManagedOverlayWidget=e.PlaceholderViewZone=e.ViewZoneOverlayWidget=e.ObservableElementSizeObserver=void 0,e.joinCombine=p,e.applyObservableDecorations=n,e.appendRemoveOnDispose=o,e.prependRemoveOnDispose=t,e.animatedObservable=s,e.applyStyle=r,e.applyViewZones=u,e.translatePosition=f,e.filterWithPrevious=v;function p(D,T,M,A){if(D.length===0)return T;if(T.length===0)return D;const P=[];let N=0,O=0;for(;NV?(P.push(x),O++):(P.push(A(F,x)),N++,O++)}for(;N`Apply decorations from ${T.debugName}`},P=>{const N=T.read(P);A.set(N)})),M.add({dispose:()=>{A.clear()}}),M}function o(D,T){return D.appendChild(T),(0,I.toDisposable)(()=>{T.remove()})}function t(D,T){return D.prepend(T),(0,I.toDisposable)(()=>{T.remove()})}class i extends I.Disposable{get width(){return this._width}get height(){return this._height}get automaticLayout(){return this._automaticLayout}constructor(T,M){super(),this._automaticLayout=!1,this.elementSizeObserver=this._register(new y.ElementSizeObserver(T,M)),this._width=(0,E.observableValue)(this,this.elementSizeObserver.getWidth()),this._height=(0,E.observableValue)(this,this.elementSizeObserver.getHeight()),this._register(this.elementSizeObserver.onDidChange(A=>(0,E.transaction)(P=>{this._width.set(this.elementSizeObserver.getWidth(),P),this._height.set(this.elementSizeObserver.getHeight(),P)})))}observe(T){this.elementSizeObserver.observe(T)}setAutomaticLayout(T){this._automaticLayout=T,T?this.elementSizeObserver.startObserving():this.elementSizeObserver.stopObserving()}}e.ObservableElementSizeObserver=i;function s(D,T,M){let A=T.get(),P=A,N=A;const O=(0,E.observableValue)("animatedValue",A);let F=-1;const x=300;let W;M.add((0,E.autorunHandleChanges)({createEmptyChangeSummary:()=>({animate:!1}),handleChange:(q,H)=>(q.didChange(T)&&(H.animate=H.animate||q.change),!0)},(q,H)=>{W!==void 0&&(D.cancelAnimationFrame(W),W=void 0),P=N,A=T.read(q),F=Date.now()-(H.animate?0:x),V()}));function V(){const q=Date.now()-F;N=Math.floor(g(q,P,A-P,x)),q{this._actualTop.set(A,void 0)},this.onComputedHeight=A=>{this._actualHeight.set(A,void 0)}}}e.PlaceholderViewZone=l;class a{static{this._counter=0}constructor(T,M){this._editor=T,this._domElement=M,this._overlayWidgetId=`managedOverlayWidget-${a._counter++}`,this._overlayWidget={getId:()=>this._overlayWidgetId,getDomNode:()=>this._domElement,getPosition:()=>null},this._editor.addOverlayWidget(this._overlayWidget)}dispose(){this._editor.removeOverlayWidget(this._overlayWidget)}}e.ManagedOverlayWidget=a;function r(D,T){return(0,E.autorun)(M=>{for(let[A,P]of Object.entries(T))P&&typeof P=="object"&&"read"in P&&(P=P.read(M)),typeof P=="number"&&(P=`${P}px`),A=A.replace(/[A-Z]/g,N=>"-"+N.toLowerCase()),D.style[A]=P})}function u(D,T,M,A){const P=new I.DisposableStore,N=[];return P.add((0,E.autorunWithStore)((O,F)=>{const x=T.read(O),W=new Map,V=new Map;M&&M(!0),D.changeViewZones(q=>{for(const H of N)q.removeZone(H),A?.delete(H);N.length=0;for(const H of x){const z=q.addZone(H);H.setZoneId&&H.setZoneId(z),N.push(z),A?.add(z),W.set(H,z)}}),M&&M(!1),F.add((0,E.autorunHandleChanges)({createEmptyChangeSummary(){return{zoneIds:[]}},handleChange(q,H){const z=V.get(q.changedObservable);return z!==void 0&&H.zoneIds.push(z),!0}},(q,H)=>{for(const z of x)z.onChange&&(V.set(z.onChange,W.get(z)),z.onChange.read(q));M&&M(!0),D.changeViewZones(z=>{for(const U of H.zoneIds)z.layoutZone(U)}),M&&M(!1)}))})),P.add({dispose(){M&&M(!0),D.changeViewZones(O=>{for(const F of N)O.removeZone(F)}),A?.clear(),M&&M(!1)}}),P}class C extends k.CancellationTokenSource{dispose(){super.dispose(!0)}}e.DisposableCancellationTokenSource=C;function f(D,T){const M=(0,d.findLast)(T,P=>P.original.startLineNumber<=D.lineNumber);if(!M)return _.Range.fromPositions(D);if(M.original.endLineNumberExclusive<=D.lineNumber){const P=D.lineNumber-M.original.endLineNumberExclusive+M.modified.endLineNumberExclusive;return _.Range.fromPositions(new m.Position(P,D.column))}if(!M.innerChanges)return _.Range.fromPositions(new m.Position(M.modified.startLineNumber,1));const A=(0,d.findLast)(M.innerChanges,P=>P.originalRange.getStartPosition().isBeforeOrEqual(D));if(!A){const P=D.lineNumber-M.original.startLineNumber+M.modified.startLineNumber;return _.Range.fromPositions(new m.Position(P,D.column))}if(A.originalRange.containsPosition(D))return A.modifiedRange;{const P=h(A.originalRange.getEndPosition(),D);return _.Range.fromPositions(P.addToPosition(A.modifiedRange.getEndPosition()))}}function h(D,T){return D.lineNumber===T.lineNumber?new b.TextLength(0,T.column-D.column):new b.TextLength(T.lineNumber-D.lineNumber,T.column-1)}function v(D,T){let M;return D.filter(A=>{const P=T(A,M);return M=A,P})}class w{static create(T,M=void 0){return new S(T,T,M)}static createWithDisposable(T,M,A=void 0){const P=new I.DisposableStore;return P.add(M),P.add(T),new S(T,P,A)}}e.RefCounted=w;class S extends w{constructor(T,M,A){super(),this.object=T,this._disposable=M,this._debugOwner=A,this._refCount=1,this._isDisposed=!1,this._owners=[],A&&this._addOwner(A)}_addOwner(T){T&&this._owners.push(T)}createNewRef(T){return this._refCount++,T&&this._addOwner(T),new L(this,T)}dispose(){this._isDisposed||(this._isDisposed=!0,this._decreaseRefCount(this._debugOwner))}_decreaseRefCount(T){if(this._refCount--,this._refCount===0&&this._disposable.dispose(),T){const M=this._owners.indexOf(T);M!==-1&&this._owners.splice(M,1)}}}class L extends w{constructor(T,M){super(),this._base=T,this._debugOwner=M,this._isDisposed=!1}get object(){return this._base.object}createNewRef(T){return this._base.createNewRef(T)}dispose(){this._isDisposed||(this._isDisposed=!0,this._base._decreaseRefCount(this._debugOwner))}}}),define(ne[364],se([1,0,5,87,41,13,67,26,2,21,30,88,68,3]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MovedBlocksLinesFeature=void 0;class i extends _.Disposable{static{this.movedCodeBlockPadding=4}constructor(l,a,r,u,C){super(),this._rootElement=l,this._diffModel=a,this._originalEditorLayoutInfo=r,this._modifiedEditorLayoutInfo=u,this._editors=C,this._originalScrollTop=(0,b.observableFromEvent)(this,this._editors.original.onDidScrollChange,()=>this._editors.original.getScrollTop()),this._modifiedScrollTop=(0,b.observableFromEvent)(this,this._editors.modified.onDidScrollChange,()=>this._editors.modified.getScrollTop()),this._viewZonesChanged=(0,b.observableSignalFromEvent)("onDidChangeViewZones",this._editors.modified.onDidChangeViewZones),this.width=(0,b.observableValue)(this,0),this._modifiedViewZonesChangedSignal=(0,b.observableSignalFromEvent)("modified.onDidChangeViewZones",this._editors.modified.onDidChangeViewZones),this._originalViewZonesChangedSignal=(0,b.observableSignalFromEvent)("original.onDidChangeViewZones",this._editors.original.onDidChangeViewZones),this._state=(0,b.derivedWithStore)(this,(S,L)=>{this._element.replaceChildren();const D=this._diffModel.read(S),T=D?.diff.read(S)?.movedTexts;if(!T||T.length===0){this.width.set(0,void 0);return}this._viewZonesChanged.read(S);const M=this._originalEditorLayoutInfo.read(S),A=this._modifiedEditorLayoutInfo.read(S);if(!M||!A){this.width.set(0,void 0);return}this._modifiedViewZonesChangedSignal.read(S),this._originalViewZonesChangedSignal.read(S);const P=T.map(q=>{function H(ie,ue){const he=ue.getTopForLineNumber(ie.startLineNumber,!0),pe=ue.getTopForLineNumber(ie.endLineNumberExclusive,!0);return(he+pe)/2}const z=H(q.lineRangeMapping.original,this._editors.original),U=this._originalScrollTop.read(S),j=H(q.lineRangeMapping.modified,this._editors.modified),Y=this._modifiedScrollTop.read(S),G=z-U,K=j-Y,R=Math.min(z,j),J=Math.max(z,j);return{range:new o.OffsetRange(R,J),from:G,to:K,fromWithoutScroll:z,toWithoutScroll:j,move:q}});P.sort((0,E.tieBreakComparators)((0,E.compareBy)(q=>q.fromWithoutScroll>q.toWithoutScroll,E.booleanComparator),(0,E.compareBy)(q=>q.fromWithoutScroll>q.toWithoutScroll?q.fromWithoutScroll:-q.toWithoutScroll,E.numberComparator)));const N=s.compute(P.map(q=>q.range)),O=10,F=M.verticalScrollbarWidth,x=(N.getTrackCount()-1)*10+O*2,W=F+x+(A.contentLeft-i.movedCodeBlockPadding);let V=0;for(const q of P){const H=N.getTrack(V),z=F+O+H*10,U=15,j=15,Y=W,G=A.glyphMarginWidth+A.lineNumbersWidth,K=18,R=document.createElementNS("http://www.w3.org/2000/svg","rect");R.classList.add("arrow-rectangle"),R.setAttribute("x",`${Y-G}`),R.setAttribute("y",`${q.to-K/2}`),R.setAttribute("width",`${G}`),R.setAttribute("height",`${K}`),this._element.appendChild(R);const J=document.createElementNS("http://www.w3.org/2000/svg","g"),ie=document.createElementNS("http://www.w3.org/2000/svg","path");ie.setAttribute("d",`M 0 ${q.from} L ${z} ${q.from} L ${z} ${q.to} L ${Y-j} ${q.to}`),ie.setAttribute("fill","none"),J.appendChild(ie);const ue=document.createElementNS("http://www.w3.org/2000/svg","polygon");ue.classList.add("arrow"),L.add((0,b.autorun)(he=>{ie.classList.toggle("currentMove",q.move===D.activeMovedText.read(he)),ue.classList.toggle("currentMove",q.move===D.activeMovedText.read(he))})),ue.setAttribute("points",`${Y-j},${q.to-U/2} ${Y},${q.to} ${Y-j},${q.to+U/2}`),J.appendChild(ue),this._element.appendChild(J),V++}this.width.set(x,void 0)}),this._element=document.createElementNS("http://www.w3.org/2000/svg","svg"),this._element.setAttribute("class","moved-blocks-lines"),this._rootElement.appendChild(this._element),this._register((0,_.toDisposable)(()=>this._element.remove())),this._register((0,b.autorun)(S=>{const L=this._originalEditorLayoutInfo.read(S),D=this._modifiedEditorLayoutInfo.read(S);!L||!D||(this._element.style.left=`${L.width-L.verticalScrollbarWidth}px`,this._element.style.height=`${L.height}px`,this._element.style.width=`${L.verticalScrollbarWidth+L.contentLeft-i.movedCodeBlockPadding+this.width.read(S)}px`)})),this._register((0,b.recomputeInitiallyAndOnChange)(this._state));const f=(0,b.derived)(S=>{const D=this._diffModel.read(S)?.diff.read(S);return D?D.movedTexts.map(T=>({move:T,original:new n.PlaceholderViewZone((0,b.constObservable)(T.lineRangeMapping.original.startLineNumber-1),18),modified:new n.PlaceholderViewZone((0,b.constObservable)(T.lineRangeMapping.modified.startLineNumber-1),18)})):[]});this._register((0,n.applyViewZones)(this._editors.original,f.map(S=>S.map(L=>L.original)))),this._register((0,n.applyViewZones)(this._editors.modified,f.map(S=>S.map(L=>L.modified)))),this._register((0,b.autorunWithStore)((S,L)=>{const D=f.read(S);for(const T of D)L.add(new g(this._editors.original,T.original,T.move,"original",this._diffModel.get())),L.add(new g(this._editors.modified,T.modified,T.move,"modified",this._diffModel.get()))}));const h=(0,b.observableSignalFromEvent)("original.onDidFocusEditorWidget",S=>this._editors.original.onDidFocusEditorWidget(()=>setTimeout(()=>S(void 0),0))),v=(0,b.observableSignalFromEvent)("modified.onDidFocusEditorWidget",S=>this._editors.modified.onDidFocusEditorWidget(()=>setTimeout(()=>S(void 0),0)));let w="modified";this._register((0,b.autorunHandleChanges)({createEmptyChangeSummary:()=>{},handleChange:(S,L)=>(S.didChange(h)&&(w="original"),S.didChange(v)&&(w="modified"),!0)},S=>{h.read(S),v.read(S);const L=this._diffModel.read(S);if(!L)return;const D=L.diff.read(S);let T;if(D&&w==="original"){const M=this._editors.originalCursor.read(S);M&&(T=D.movedTexts.find(A=>A.lineRangeMapping.original.contains(M.lineNumber)))}if(D&&w==="modified"){const M=this._editors.modifiedCursor.read(S);M&&(T=D.movedTexts.find(A=>A.lineRangeMapping.modified.contains(M.lineNumber)))}T!==L.movedTextToCompare.get()&&L.movedTextToCompare.set(void 0,void 0),L.setActiveMovedText(T)}))}}e.MovedBlocksLinesFeature=i;class s{static compute(l){const a=[],r=[];for(const u of l){let C=a.findIndex(f=>!f.intersectsStrict(u));C===-1&&(a.length>=6?C=(0,y.findMaxIdx)(a,(0,E.compareBy)(h=>h.intersectWithRangeLength(u),E.numberComparator)):(C=a.length,a.push(new o.OffsetRangeSet))),a[C].addRange(u),r.push(C)}return new s(a.length,r)}constructor(l,a){this._trackCount=l,this.trackPerLineIdx=a}getTrack(l){return this.trackPerLineIdx[l]}getTrackCount(){return this._trackCount}}class g extends n.ViewZoneOverlayWidget{constructor(l,a,r,u,C){const f=(0,d.h)("div.diff-hidden-lines-widget");super(l,a,f.root),this._editor=l,this._move=r,this._kind=u,this._diffModel=C,this._nodes=(0,d.h)("div.diff-moved-code-block",{style:{marginRight:"4px"}},[(0,d.h)("div.text-content@textContent"),(0,d.h)("div.action-bar@actionBar")]),f.root.appendChild(this._nodes.root);const h=(0,b.observableFromEvent)(this._editor.onDidLayoutChange,()=>this._editor.getLayoutInfo());this._register((0,n.applyStyle)(this._nodes.root,{paddingRight:h.map(D=>D.verticalScrollbarWidth)}));let v;r.changes.length>0?v=this._kind==="original"?(0,t.localize)(118,"Code moved with changes to line {0}-{1}",this._move.lineRangeMapping.modified.startLineNumber,this._move.lineRangeMapping.modified.endLineNumberExclusive-1):(0,t.localize)(119,"Code moved with changes from line {0}-{1}",this._move.lineRangeMapping.original.startLineNumber,this._move.lineRangeMapping.original.endLineNumberExclusive-1):v=this._kind==="original"?(0,t.localize)(120,"Code moved to line {0}-{1}",this._move.lineRangeMapping.modified.startLineNumber,this._move.lineRangeMapping.modified.endLineNumberExclusive-1):(0,t.localize)(121,"Code moved from line {0}-{1}",this._move.lineRangeMapping.original.startLineNumber,this._move.lineRangeMapping.original.endLineNumberExclusive-1);const w=this._register(new k.ActionBar(this._nodes.actionBar,{highlightToggledItems:!0})),S=new I.Action("",v,"",!1);w.push(S,{icon:!1,label:!0});const L=new I.Action("","Compare",p.ThemeIcon.asClassName(m.Codicon.compareChanges),!0,()=>{this._editor.focus(),this._diffModel.movedTextToCompare.set(this._diffModel.movedTextToCompare.get()===r?void 0:this._move,void 0)});this._register((0,b.autorun)(D=>{const T=this._diffModel.movedTextToCompare.read(D)===r;L.checked=T})),w.push(L,{icon:!1,label:!0})}}}),define(ne[654],se([1,0,5,2,21,55,68]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorGutter=void 0;class m extends k.Disposable{constructor(p,n,o){super(),this._editor=p,this._domNode=n,this.itemProvider=o,this.scrollTop=(0,I.observableFromEvent)(this,this._editor.onDidScrollChange,s=>this._editor.getScrollTop()),this.isScrollTopZero=this.scrollTop.map(s=>s===0),this.modelAttached=(0,I.observableFromEvent)(this,this._editor.onDidChangeModel,s=>this._editor.hasModel()),this.editorOnDidChangeViewZones=(0,I.observableSignalFromEvent)("onDidChangeViewZones",this._editor.onDidChangeViewZones),this.editorOnDidContentSizeChange=(0,I.observableSignalFromEvent)("onDidContentSizeChange",this._editor.onDidContentSizeChange),this.domNodeSizeChanged=(0,I.observableSignal)("domNodeSizeChanged"),this.views=new Map,this._domNode.className="gutter monaco-editor";const t=this._domNode.appendChild((0,d.h)("div.scroll-decoration",{role:"presentation",ariaHidden:"true",style:{width:"100%"}}).root),i=new ResizeObserver(()=>{(0,I.transaction)(s=>{this.domNodeSizeChanged.trigger(s)})});i.observe(this._domNode),this._register((0,k.toDisposable)(()=>i.disconnect())),this._register((0,I.autorun)(s=>{t.className=this.isScrollTopZero.read(s)?"":"scroll-decoration"})),this._register((0,I.autorun)(s=>this.render(s)))}dispose(){super.dispose(),(0,d.reset)(this._domNode)}render(p){if(!this.modelAttached.read(p))return;this.domNodeSizeChanged.read(p),this.editorOnDidChangeViewZones.read(p),this.editorOnDidContentSizeChange.read(p);const n=this.scrollTop.read(p),o=this._editor.getVisibleRanges(),t=new Set(this.views.keys()),i=y.OffsetRange.ofStartAndLength(0,this._domNode.clientHeight);if(!i.isEmpty)for(const s of o){const g=new E.LineRange(s.startLineNumber,s.endLineNumber+1),c=this.itemProvider.getIntersectingGutterItems(g,p);(0,I.transaction)(l=>{for(const a of c){if(!a.range.intersect(g))continue;t.delete(a.id);let r=this.views.get(a.id);if(r)r.item.set(a,l);else{const h=document.createElement("div");this._domNode.appendChild(h);const v=(0,I.observableValue)("item",a),w=this.itemProvider.createView(v,h);r=new _(v,w,h),this.views.set(a.id,r)}const u=a.range.startLineNumber<=this._editor.getModel().getLineCount()?this._editor.getTopForLineNumber(a.range.startLineNumber,!0)-n:this._editor.getBottomForLineNumber(a.range.startLineNumber-1,!1)-n,f=(a.range.endLineNumberExclusive===1?Math.max(u,this._editor.getTopForLineNumber(a.range.startLineNumber,!1)-n):Math.max(u,this._editor.getBottomForLineNumber(a.range.endLineNumberExclusive-1,!0)-n))-u;r.domNode.style.top=`${u}px`,r.domNode.style.height=`${f}px`,r.gutterItemView.layout(y.OffsetRange.ofStartAndLength(u,f),i)}})}for(const s of t){const g=this.views.get(s);g.gutterItemView.dispose(),g.domNode.remove(),this.views.delete(s)}}}e.EditorGutter=m;class _{constructor(p,n,o){this.item=p,this.gutterItemView=n,this.domNode=o}}}),define(ne[365],se([1,0,41]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ActionRunnerWithContext=void 0;class k extends d.ActionRunner{constructor(E){super(),this._getContext=E}runAction(E,y){const m=this._getContext();return super.runAction(E,m)}}e.ActionRunnerWithContext=k}),define(ne[37],se([1,0,13,60,16,197,147,3]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorOptions=e.editorOptionsRegistry=e.EDITOR_FONT_DEFAULTS=e.unicodeHighlightConfigKeys=e.inUntrustedWorkspace=e.ShowLightbulbIconMode=e.EditorLayoutInfoComputer=e.EditorFontVariations=e.EditorFontLigatures=e.TextEditorCursorStyle=e.ApplyUpdateResult=e.ComputeOptionsMemory=e.ConfigurationChangedEvent=e.MINIMAP_GUTTER_WIDTH=void 0,e.boolean=s,e.clampedInt=c,e.clampedFloat=a,e.stringSet=C,e.filterValidationDecorations=ge,e.MINIMAP_GUTTER_WIDTH=8;class _{constructor(fe){this._values=fe}hasChanged(fe){return this._values[fe]}}e.ConfigurationChangedEvent=_;class b{constructor(){this.stableMinimapLayoutInput=null,this.stableFitMaxMinimapScale=0,this.stableFitRemainingWidth=0}}e.ComputeOptionsMemory=b;class p{constructor(fe,_e,xe,be){this.id=fe,this.name=_e,this.defaultValue=xe,this.schema=be}applyUpdate(fe,_e){return o(fe,_e)}compute(fe,_e,xe){return xe}}class n{constructor(fe,_e){this.newValue=fe,this.didChange=_e}}e.ApplyUpdateResult=n;function o(Fe,fe){if(typeof Fe!="object"||typeof fe!="object"||!Fe||!fe)return new n(fe,Fe!==fe);if(Array.isArray(Fe)||Array.isArray(fe)){const xe=Array.isArray(Fe)&&Array.isArray(fe)&&d.equals(Fe,fe);return new n(fe,!xe)}let _e=!1;for(const xe in fe)if(fe.hasOwnProperty(xe)){const be=o(Fe[xe],fe[xe]);be.didChange&&(Fe[xe]=be.newValue,_e=!0)}return new n(Fe,_e)}class t{constructor(fe){this.schema=void 0,this.id=fe,this.name="_never_",this.defaultValue=void 0}applyUpdate(fe,_e){return o(fe,_e)}validate(fe){return this.defaultValue}}class i{constructor(fe,_e,xe,be){this.id=fe,this.name=_e,this.defaultValue=xe,this.schema=be}applyUpdate(fe,_e){return o(fe,_e)}validate(fe){return typeof fe>"u"?this.defaultValue:fe}compute(fe,_e,xe){return xe}}function s(Fe,fe){return typeof Fe>"u"?fe:Fe==="false"?!1:!!Fe}class g extends i{constructor(fe,_e,xe,be=void 0){typeof be<"u"&&(be.type="boolean",be.default=xe),super(fe,_e,xe,be)}validate(fe){return s(fe,this.defaultValue)}}function c(Fe,fe,_e,xe){if(typeof Fe>"u")return fe;let be=parseInt(Fe,10);return isNaN(be)?fe:(be=Math.max(_e,be),be=Math.min(xe,be),be|0)}class l extends i{static clampedInt(fe,_e,xe,be){return c(fe,_e,xe,be)}constructor(fe,_e,xe,be,ve,we=void 0){typeof we<"u"&&(we.type="integer",we.default=xe,we.minimum=be,we.maximum=ve),super(fe,_e,xe,we),this.minimum=be,this.maximum=ve}validate(fe){return l.clampedInt(fe,this.defaultValue,this.minimum,this.maximum)}}function a(Fe,fe,_e,xe){if(typeof Fe>"u")return fe;const be=r.float(Fe,fe);return r.clamp(be,_e,xe)}class r extends i{static clamp(fe,_e,xe){return fe<_e?_e:fe>xe?xe:fe}static float(fe,_e){if(typeof fe=="number")return fe;if(typeof fe>"u")return _e;const xe=parseFloat(fe);return isNaN(xe)?_e:xe}constructor(fe,_e,xe,be,ve){typeof ve<"u"&&(ve.type="number",ve.default=xe),super(fe,_e,xe,ve),this.validationFn=be}validate(fe){return this.validationFn(r.float(fe,this.defaultValue))}}class u extends i{static string(fe,_e){return typeof fe!="string"?_e:fe}constructor(fe,_e,xe,be=void 0){typeof be<"u"&&(be.type="string",be.default=xe),super(fe,_e,xe,be)}validate(fe){return u.string(fe,this.defaultValue)}}function C(Fe,fe,_e,xe){return typeof Fe!="string"?fe:xe&&Fe in xe?xe[Fe]:_e.indexOf(Fe)===-1?fe:Fe}class f extends i{constructor(fe,_e,xe,be,ve=void 0){typeof ve<"u"&&(ve.type="string",ve.enum=be,ve.default=xe),super(fe,_e,xe,ve),this._allowedValues=be}validate(fe){return C(fe,this.defaultValue,this._allowedValues)}}class h extends p{constructor(fe,_e,xe,be,ve,we,Te=void 0){typeof Te<"u"&&(Te.type="string",Te.enum=ve,Te.default=be),super(fe,_e,xe,Te),this._allowedValues=ve,this._convert=we}validate(fe){return typeof fe!="string"?this.defaultValue:this._allowedValues.indexOf(fe)===-1?this.defaultValue:this._convert(fe)}}function v(Fe){switch(Fe){case"none":return 0;case"keep":return 1;case"brackets":return 2;case"advanced":return 3;case"full":return 4}}class w extends p{constructor(){super(2,"accessibilitySupport",0,{type:"string",enum:["auto","on","off"],enumDescriptions:[m.localize(183,"Use platform APIs to detect when a Screen Reader is attached."),m.localize(184,"Optimize for usage with a Screen Reader."),m.localize(185,"Assume a screen reader is not attached.")],default:"auto",tags:["accessibility"],description:m.localize(186,"Controls if the UI should run in a mode where it is optimized for screen readers.")})}validate(fe){switch(fe){case"auto":return 0;case"off":return 1;case"on":return 2}return this.defaultValue}compute(fe,_e,xe){return xe===0?fe.accessibilitySupport:xe}}class S extends p{constructor(){const fe={insertSpace:!0,ignoreEmptyLines:!0};super(23,"comments",fe,{"editor.comments.insertSpace":{type:"boolean",default:fe.insertSpace,description:m.localize(187,"Controls whether a space character is inserted when commenting.")},"editor.comments.ignoreEmptyLines":{type:"boolean",default:fe.ignoreEmptyLines,description:m.localize(188,"Controls if empty lines should be ignored with toggle, add or remove actions for line comments.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{insertSpace:s(_e.insertSpace,this.defaultValue.insertSpace),ignoreEmptyLines:s(_e.ignoreEmptyLines,this.defaultValue.ignoreEmptyLines)}}}function L(Fe){switch(Fe){case"blink":return 1;case"smooth":return 2;case"phase":return 3;case"expand":return 4;case"solid":return 5}}var D;(function(Fe){Fe[Fe.Line=1]="Line",Fe[Fe.Block=2]="Block",Fe[Fe.Underline=3]="Underline",Fe[Fe.LineThin=4]="LineThin",Fe[Fe.BlockOutline=5]="BlockOutline",Fe[Fe.UnderlineThin=6]="UnderlineThin"})(D||(e.TextEditorCursorStyle=D={}));function T(Fe){switch(Fe){case"line":return D.Line;case"block":return D.Block;case"underline":return D.Underline;case"line-thin":return D.LineThin;case"block-outline":return D.BlockOutline;case"underline-thin":return D.UnderlineThin}}class M extends t{constructor(){super(143)}compute(fe,_e,xe){const be=["monaco-editor"];return _e.get(39)&&be.push(_e.get(39)),fe.extraEditorClassName&&be.push(fe.extraEditorClassName),_e.get(74)==="default"?be.push("mouse-default"):_e.get(74)==="copy"&&be.push("mouse-copy"),_e.get(112)&&be.push("showUnused"),_e.get(141)&&be.push("showDeprecated"),be.join(" ")}}class A extends g{constructor(){super(37,"emptySelectionClipboard",!0,{description:m.localize(189,"Controls whether copying without a selection copies the current line.")})}compute(fe,_e,xe){return xe&&fe.emptySelectionClipboard}}class P extends p{constructor(){const fe={cursorMoveOnType:!0,seedSearchStringFromSelection:"always",autoFindInSelection:"never",globalFindClipboard:!1,addExtraSpaceOnTop:!0,loop:!0};super(41,"find",fe,{"editor.find.cursorMoveOnType":{type:"boolean",default:fe.cursorMoveOnType,description:m.localize(190,"Controls whether the cursor should jump to find matches while typing.")},"editor.find.seedSearchStringFromSelection":{type:"string",enum:["never","always","selection"],default:fe.seedSearchStringFromSelection,enumDescriptions:[m.localize(191,"Never seed search string from the editor selection."),m.localize(192,"Always seed search string from the editor selection, including word at cursor position."),m.localize(193,"Only seed search string from the editor selection.")],description:m.localize(194,"Controls whether the search string in the Find Widget is seeded from the editor selection.")},"editor.find.autoFindInSelection":{type:"string",enum:["never","always","multiline"],default:fe.autoFindInSelection,enumDescriptions:[m.localize(195,"Never turn on Find in Selection automatically (default)."),m.localize(196,"Always turn on Find in Selection automatically."),m.localize(197,"Turn on Find in Selection automatically when multiple lines of content are selected.")],description:m.localize(198,"Controls the condition for turning on Find in Selection automatically.")},"editor.find.globalFindClipboard":{type:"boolean",default:fe.globalFindClipboard,description:m.localize(199,"Controls whether the Find Widget should read or modify the shared find clipboard on macOS."),included:I.isMacintosh},"editor.find.addExtraSpaceOnTop":{type:"boolean",default:fe.addExtraSpaceOnTop,description:m.localize(200,"Controls whether the Find Widget should add extra lines on top of the editor. When true, you can scroll beyond the first line when the Find Widget is visible.")},"editor.find.loop":{type:"boolean",default:fe.loop,description:m.localize(201,"Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{cursorMoveOnType:s(_e.cursorMoveOnType,this.defaultValue.cursorMoveOnType),seedSearchStringFromSelection:typeof fe.seedSearchStringFromSelection=="boolean"?fe.seedSearchStringFromSelection?"always":"never":C(_e.seedSearchStringFromSelection,this.defaultValue.seedSearchStringFromSelection,["never","always","selection"]),autoFindInSelection:typeof fe.autoFindInSelection=="boolean"?fe.autoFindInSelection?"always":"never":C(_e.autoFindInSelection,this.defaultValue.autoFindInSelection,["never","always","multiline"]),globalFindClipboard:s(_e.globalFindClipboard,this.defaultValue.globalFindClipboard),addExtraSpaceOnTop:s(_e.addExtraSpaceOnTop,this.defaultValue.addExtraSpaceOnTop),loop:s(_e.loop,this.defaultValue.loop)}}}class N extends p{static{this.OFF='"liga" off, "calt" off'}static{this.ON='"liga" on, "calt" on'}constructor(){super(51,"fontLigatures",N.OFF,{anyOf:[{type:"boolean",description:m.localize(202,"Enables/Disables font ligatures ('calt' and 'liga' font features). Change this to a string for fine-grained control of the 'font-feature-settings' CSS property.")},{type:"string",description:m.localize(203,"Explicit 'font-feature-settings' CSS property. A boolean can be passed instead if one only needs to turn on/off ligatures.")}],description:m.localize(204,"Configures font ligatures or font features. Can be either a boolean to enable/disable ligatures or a string for the value of the CSS 'font-feature-settings' property."),default:!1})}validate(fe){return typeof fe>"u"?this.defaultValue:typeof fe=="string"?fe==="false"||fe.length===0?N.OFF:fe==="true"?N.ON:fe:fe?N.ON:N.OFF}}e.EditorFontLigatures=N;class O extends p{static{this.OFF="normal"}static{this.TRANSLATE="translate"}constructor(){super(54,"fontVariations",O.OFF,{anyOf:[{type:"boolean",description:m.localize(205,"Enables/Disables the translation from font-weight to font-variation-settings. Change this to a string for fine-grained control of the 'font-variation-settings' CSS property.")},{type:"string",description:m.localize(206,"Explicit 'font-variation-settings' CSS property. A boolean can be passed instead if one only needs to translate font-weight to font-variation-settings.")}],description:m.localize(207,"Configures font variations. Can be either a boolean to enable/disable the translation from font-weight to font-variation-settings or a string for the value of the CSS 'font-variation-settings' property."),default:!1})}validate(fe){return typeof fe>"u"?this.defaultValue:typeof fe=="string"?fe==="false"?O.OFF:fe==="true"?O.TRANSLATE:fe:fe?O.TRANSLATE:O.OFF}compute(fe,_e,xe){return fe.fontInfo.fontVariationSettings}}e.EditorFontVariations=O;class F extends t{constructor(){super(50)}compute(fe,_e,xe){return fe.fontInfo}}class x extends i{constructor(){super(52,"fontSize",e.EDITOR_FONT_DEFAULTS.fontSize,{type:"number",minimum:6,maximum:100,default:e.EDITOR_FONT_DEFAULTS.fontSize,description:m.localize(208,"Controls the font size in pixels.")})}validate(fe){const _e=r.float(fe,this.defaultValue);return _e===0?e.EDITOR_FONT_DEFAULTS.fontSize:r.clamp(_e,6,100)}compute(fe,_e,xe){return fe.fontInfo.fontSize}}class W extends p{static{this.SUGGESTION_VALUES=["normal","bold","100","200","300","400","500","600","700","800","900"]}static{this.MINIMUM_VALUE=1}static{this.MAXIMUM_VALUE=1e3}constructor(){super(53,"fontWeight",e.EDITOR_FONT_DEFAULTS.fontWeight,{anyOf:[{type:"number",minimum:W.MINIMUM_VALUE,maximum:W.MAXIMUM_VALUE,errorMessage:m.localize(209,'Only "normal" and "bold" keywords or numbers between 1 and 1000 are allowed.')},{type:"string",pattern:"^(normal|bold|1000|[1-9][0-9]{0,2})$"},{enum:W.SUGGESTION_VALUES}],default:e.EDITOR_FONT_DEFAULTS.fontWeight,description:m.localize(210,'Controls the font weight. Accepts "normal" and "bold" keywords or numbers between 1 and 1000.')})}validate(fe){return fe==="normal"||fe==="bold"?fe:String(l.clampedInt(fe,e.EDITOR_FONT_DEFAULTS.fontWeight,W.MINIMUM_VALUE,W.MAXIMUM_VALUE))}}class V extends p{constructor(){const fe={multiple:"peek",multipleDefinitions:"peek",multipleTypeDefinitions:"peek",multipleDeclarations:"peek",multipleImplementations:"peek",multipleReferences:"peek",multipleTests:"peek",alternativeDefinitionCommand:"editor.action.goToReferences",alternativeTypeDefinitionCommand:"editor.action.goToReferences",alternativeDeclarationCommand:"editor.action.goToReferences",alternativeImplementationCommand:"",alternativeReferenceCommand:"",alternativeTestsCommand:""},_e={type:"string",enum:["peek","gotoAndPeek","goto"],default:fe.multiple,enumDescriptions:[m.localize(211,"Show Peek view of the results (default)"),m.localize(212,"Go to the primary result and show a Peek view"),m.localize(213,"Go to the primary result and enable Peek-less navigation to others")]},xe=["","editor.action.referenceSearch.trigger","editor.action.goToReferences","editor.action.peekImplementation","editor.action.goToImplementation","editor.action.peekTypeDefinition","editor.action.goToTypeDefinition","editor.action.peekDeclaration","editor.action.revealDeclaration","editor.action.peekDefinition","editor.action.revealDefinitionAside","editor.action.revealDefinition"];super(58,"gotoLocation",fe,{"editor.gotoLocation.multiple":{deprecationMessage:m.localize(214,"This setting is deprecated, please use separate settings like 'editor.editor.gotoLocation.multipleDefinitions' or 'editor.editor.gotoLocation.multipleImplementations' instead.")},"editor.gotoLocation.multipleDefinitions":{description:m.localize(215,"Controls the behavior the 'Go to Definition'-command when multiple target locations exist."),..._e},"editor.gotoLocation.multipleTypeDefinitions":{description:m.localize(216,"Controls the behavior the 'Go to Type Definition'-command when multiple target locations exist."),..._e},"editor.gotoLocation.multipleDeclarations":{description:m.localize(217,"Controls the behavior the 'Go to Declaration'-command when multiple target locations exist."),..._e},"editor.gotoLocation.multipleImplementations":{description:m.localize(218,"Controls the behavior the 'Go to Implementations'-command when multiple target locations exist."),..._e},"editor.gotoLocation.multipleReferences":{description:m.localize(219,"Controls the behavior the 'Go to References'-command when multiple target locations exist."),..._e},"editor.gotoLocation.alternativeDefinitionCommand":{type:"string",default:fe.alternativeDefinitionCommand,enum:xe,description:m.localize(220,"Alternative command id that is being executed when the result of 'Go to Definition' is the current location.")},"editor.gotoLocation.alternativeTypeDefinitionCommand":{type:"string",default:fe.alternativeTypeDefinitionCommand,enum:xe,description:m.localize(221,"Alternative command id that is being executed when the result of 'Go to Type Definition' is the current location.")},"editor.gotoLocation.alternativeDeclarationCommand":{type:"string",default:fe.alternativeDeclarationCommand,enum:xe,description:m.localize(222,"Alternative command id that is being executed when the result of 'Go to Declaration' is the current location.")},"editor.gotoLocation.alternativeImplementationCommand":{type:"string",default:fe.alternativeImplementationCommand,enum:xe,description:m.localize(223,"Alternative command id that is being executed when the result of 'Go to Implementation' is the current location.")},"editor.gotoLocation.alternativeReferenceCommand":{type:"string",default:fe.alternativeReferenceCommand,enum:xe,description:m.localize(224,"Alternative command id that is being executed when the result of 'Go to Reference' is the current location.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{multiple:C(_e.multiple,this.defaultValue.multiple,["peek","gotoAndPeek","goto"]),multipleDefinitions:_e.multipleDefinitions??C(_e.multipleDefinitions,"peek",["peek","gotoAndPeek","goto"]),multipleTypeDefinitions:_e.multipleTypeDefinitions??C(_e.multipleTypeDefinitions,"peek",["peek","gotoAndPeek","goto"]),multipleDeclarations:_e.multipleDeclarations??C(_e.multipleDeclarations,"peek",["peek","gotoAndPeek","goto"]),multipleImplementations:_e.multipleImplementations??C(_e.multipleImplementations,"peek",["peek","gotoAndPeek","goto"]),multipleReferences:_e.multipleReferences??C(_e.multipleReferences,"peek",["peek","gotoAndPeek","goto"]),multipleTests:_e.multipleTests??C(_e.multipleTests,"peek",["peek","gotoAndPeek","goto"]),alternativeDefinitionCommand:u.string(_e.alternativeDefinitionCommand,this.defaultValue.alternativeDefinitionCommand),alternativeTypeDefinitionCommand:u.string(_e.alternativeTypeDefinitionCommand,this.defaultValue.alternativeTypeDefinitionCommand),alternativeDeclarationCommand:u.string(_e.alternativeDeclarationCommand,this.defaultValue.alternativeDeclarationCommand),alternativeImplementationCommand:u.string(_e.alternativeImplementationCommand,this.defaultValue.alternativeImplementationCommand),alternativeReferenceCommand:u.string(_e.alternativeReferenceCommand,this.defaultValue.alternativeReferenceCommand),alternativeTestsCommand:u.string(_e.alternativeTestsCommand,this.defaultValue.alternativeTestsCommand)}}}class q extends p{constructor(){const fe={enabled:!0,delay:300,hidingDelay:300,sticky:!0,above:!0};super(60,"hover",fe,{"editor.hover.enabled":{type:"boolean",default:fe.enabled,description:m.localize(225,"Controls whether the hover is shown.")},"editor.hover.delay":{type:"number",default:fe.delay,minimum:0,maximum:1e4,description:m.localize(226,"Controls the delay in milliseconds after which the hover is shown.")},"editor.hover.sticky":{type:"boolean",default:fe.sticky,description:m.localize(227,"Controls whether the hover should remain visible when mouse is moved over it.")},"editor.hover.hidingDelay":{type:"integer",minimum:0,default:fe.hidingDelay,description:m.localize(228,"Controls the delay in milliseconds after which the hover is hidden. Requires `editor.hover.sticky` to be enabled.")},"editor.hover.above":{type:"boolean",default:fe.above,description:m.localize(229,"Prefer showing hovers above the line, if there's space.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),delay:l.clampedInt(_e.delay,this.defaultValue.delay,0,1e4),sticky:s(_e.sticky,this.defaultValue.sticky),hidingDelay:l.clampedInt(_e.hidingDelay,this.defaultValue.hidingDelay,0,6e5),above:s(_e.above,this.defaultValue.above)}}}class H extends t{constructor(){super(146)}compute(fe,_e,xe){return H.computeLayout(_e,{memory:fe.memory,outerWidth:fe.outerWidth,outerHeight:fe.outerHeight,isDominatedByLongLines:fe.isDominatedByLongLines,lineHeight:fe.fontInfo.lineHeight,viewLineCount:fe.viewLineCount,lineNumbersDigitCount:fe.lineNumbersDigitCount,typicalHalfwidthCharacterWidth:fe.fontInfo.typicalHalfwidthCharacterWidth,maxDigitWidth:fe.fontInfo.maxDigitWidth,pixelRatio:fe.pixelRatio,glyphMarginDecorationLaneCount:fe.glyphMarginDecorationLaneCount})}static computeContainedMinimapLineCount(fe){const _e=fe.height/fe.lineHeight,xe=Math.floor(fe.paddingTop/fe.lineHeight);let be=Math.floor(fe.paddingBottom/fe.lineHeight);fe.scrollBeyondLastLine&&(be=Math.max(be,_e-1));const ve=(xe+fe.viewLineCount+be)/(fe.pixelRatio*fe.height),we=Math.floor(fe.viewLineCount/ve);return{typicalViewportLineCount:_e,extraLinesBeforeFirstLine:xe,extraLinesBeyondLastLine:be,desiredRatio:ve,minimapLineCount:we}}static _computeMinimapLayout(fe,_e){const xe=fe.outerWidth,be=fe.outerHeight,ve=fe.pixelRatio;if(!fe.minimap.enabled)return{renderMinimap:0,minimapLeft:0,minimapWidth:0,minimapHeightIsEditorHeight:!1,minimapIsSampling:!1,minimapScale:1,minimapLineHeight:1,minimapCanvasInnerWidth:0,minimapCanvasInnerHeight:Math.floor(ve*be),minimapCanvasOuterWidth:0,minimapCanvasOuterHeight:be};const we=_e.stableMinimapLayoutInput,Te=we&&fe.outerHeight===we.outerHeight&&fe.lineHeight===we.lineHeight&&fe.typicalHalfwidthCharacterWidth===we.typicalHalfwidthCharacterWidth&&fe.pixelRatio===we.pixelRatio&&fe.scrollBeyondLastLine===we.scrollBeyondLastLine&&fe.paddingTop===we.paddingTop&&fe.paddingBottom===we.paddingBottom&&fe.minimap.enabled===we.minimap.enabled&&fe.minimap.side===we.minimap.side&&fe.minimap.size===we.minimap.size&&fe.minimap.showSlider===we.minimap.showSlider&&fe.minimap.renderCharacters===we.minimap.renderCharacters&&fe.minimap.maxColumn===we.minimap.maxColumn&&fe.minimap.scale===we.minimap.scale&&fe.verticalScrollbarWidth===we.verticalScrollbarWidth&&fe.isViewportWrapping===we.isViewportWrapping,Pe=fe.lineHeight,Be=fe.typicalHalfwidthCharacterWidth,He=fe.scrollBeyondLastLine,$e=fe.minimap.renderCharacters;let je=ve>=2?Math.round(fe.minimap.scale*2):fe.minimap.scale;const Xe=fe.minimap.maxColumn,et=fe.minimap.size,dt=fe.minimap.side,at=fe.verticalScrollbarWidth,st=fe.viewLineCount,pt=fe.remainingWidth,bt=fe.isViewportWrapping,De=$e?2:3;let Ie=Math.floor(ve*be);const Re=Ie/ve;let Se=!1,We=!1,qe=De*je,Ue=je/ve,Je=1;if(et==="fill"||et==="fit"){const{typicalViewportLineCount:Ve,extraLinesBeforeFirstLine:Ye,extraLinesBeyondLastLine:Ze,desiredRatio:nt,minimapLineCount:ct}=H.computeContainedMinimapLineCount({viewLineCount:st,scrollBeyondLastLine:He,paddingTop:fe.paddingTop,paddingBottom:fe.paddingBottom,height:be,lineHeight:Pe,pixelRatio:ve});if(st/ct>1)Se=!0,We=!0,je=1,qe=1,Ue=je/ve;else{let ft=!1,gt=je+1;if(et==="fit"){const mt=Math.ceil((Ye+st+Ze)*qe);bt&&Te&&pt<=_e.stableFitRemainingWidth?(ft=!0,gt=_e.stableFitMaxMinimapScale):ft=mt>Ie}if(et==="fill"||ft){Se=!0;const mt=je;qe=Math.min(Pe*ve,Math.max(1,Math.floor(1/nt))),bt&&Te&&pt<=_e.stableFitRemainingWidth&&(gt=_e.stableFitMaxMinimapScale),je=Math.min(gt,Math.max(1,Math.floor(qe/De))),je>mt&&(Je=Math.min(2,je/mt)),Ue=je/ve/Je,Ie=Math.ceil(Math.max(Ve,Ye+st+Ze)*qe),bt?(_e.stableMinimapLayoutInput=fe,_e.stableFitRemainingWidth=pt,_e.stableFitMaxMinimapScale=je):(_e.stableMinimapLayoutInput=null,_e.stableFitRemainingWidth=0)}}}const tt=Math.floor(Xe*Ue),Qe=Math.min(tt,Math.max(0,Math.floor((pt-at-2)*Ue/(Be+Ue)))+e.MINIMAP_GUTTER_WIDTH);let rt=Math.floor(ve*Qe);const Ct=rt/ve;rt=Math.floor(rt*Je);const ut=$e?1:2,ot=dt==="left"?0:xe-Qe-at;return{renderMinimap:ut,minimapLeft:ot,minimapWidth:Qe,minimapHeightIsEditorHeight:Se,minimapIsSampling:We,minimapScale:je,minimapLineHeight:qe,minimapCanvasInnerWidth:rt,minimapCanvasInnerHeight:Ie,minimapCanvasOuterWidth:Ct,minimapCanvasOuterHeight:Re}}static computeLayout(fe,_e){const xe=_e.outerWidth|0,be=_e.outerHeight|0,ve=_e.lineHeight|0,we=_e.lineNumbersDigitCount|0,Te=_e.typicalHalfwidthCharacterWidth,Pe=_e.maxDigitWidth,Be=_e.pixelRatio,He=_e.viewLineCount,$e=fe.get(138),je=$e==="inherit"?fe.get(137):$e,Xe=je==="inherit"?fe.get(133):je,et=fe.get(136),dt=_e.isDominatedByLongLines,at=fe.get(57),st=fe.get(68).renderType!==0,pt=fe.get(69),bt=fe.get(106),De=fe.get(84),Ie=fe.get(73),Re=fe.get(104),Se=Re.verticalScrollbarSize,We=Re.verticalHasArrows,qe=Re.arrowSize,Ue=Re.horizontalScrollbarSize,Je=fe.get(43),tt=fe.get(111)!=="never";let Qe=fe.get(66);Je&&tt&&(Qe+=16);let rt=0;if(st){const Dt=Math.max(we,pt);rt=Math.round(Dt*Pe)}let Ct=0;at&&(Ct=ve*_e.glyphMarginDecorationLaneCount);let ut=0,ot=ut+Ct,Ve=ot+rt,Ye=Ve+Qe;const Ze=xe-Ct-rt-Qe;let nt=!1,ct=!1,ht=-1;je==="inherit"&&dt?(nt=!0,ct=!0):Xe==="on"||Xe==="bounded"?ct=!0:Xe==="wordWrapColumn"&&(ht=et);const ft=H._computeMinimapLayout({outerWidth:xe,outerHeight:be,lineHeight:ve,typicalHalfwidthCharacterWidth:Te,pixelRatio:Be,scrollBeyondLastLine:bt,paddingTop:De.top,paddingBottom:De.bottom,minimap:Ie,verticalScrollbarWidth:Se,viewLineCount:He,remainingWidth:Ze,isViewportWrapping:ct},_e.memory||new b);ft.renderMinimap!==0&&ft.minimapLeft===0&&(ut+=ft.minimapWidth,ot+=ft.minimapWidth,Ve+=ft.minimapWidth,Ye+=ft.minimapWidth);const gt=Ze-ft.minimapWidth,mt=Math.max(1,Math.floor((gt-Se-2)/Te)),vt=We?qe:0;return ct&&(ht=Math.max(1,mt),Xe==="bounded"&&(ht=Math.min(ht,et))),{width:xe,height:be,glyphMarginLeft:ut,glyphMarginWidth:Ct,glyphMarginDecorationLaneCount:_e.glyphMarginDecorationLaneCount,lineNumbersLeft:ot,lineNumbersWidth:rt,decorationsLeft:Ve,decorationsWidth:Qe,contentLeft:Ye,contentWidth:gt,minimap:ft,viewportColumn:mt,isWordWrapMinified:nt,isViewportWrapping:ct,wrappingColumn:ht,verticalScrollbarWidth:Se,horizontalScrollbarHeight:Ue,overviewRuler:{top:vt,width:Se,height:be-2*vt,right:0}}}}e.EditorLayoutInfoComputer=H;class z extends p{constructor(){super(140,"wrappingStrategy","simple",{"editor.wrappingStrategy":{enumDescriptions:[m.localize(230,"Assumes that all characters are of the same width. This is a fast algorithm that works correctly for monospace fonts and certain scripts (like Latin characters) where glyphs are of equal width."),m.localize(231,"Delegates wrapping points computation to the browser. This is a slow algorithm, that might cause freezes for large files, but it works correctly in all cases.")],type:"string",enum:["simple","advanced"],default:"simple",description:m.localize(232,"Controls the algorithm that computes wrapping points. Note that when in accessibility mode, advanced will be used for the best experience.")}})}validate(fe){return C(fe,"simple",["simple","advanced"])}compute(fe,_e,xe){return _e.get(2)===2?"advanced":xe}}var U;(function(Fe){Fe.Off="off",Fe.OnCode="onCode",Fe.On="on"})(U||(e.ShowLightbulbIconMode=U={}));class j extends p{constructor(){const fe={enabled:U.OnCode};super(65,"lightbulb",fe,{"editor.lightbulb.enabled":{type:"string",tags:["experimental"],enum:[U.Off,U.OnCode,U.On],default:fe.enabled,enumDescriptions:[m.localize(233,"Disable the code action menu."),m.localize(234,"Show the code action menu when the cursor is on lines with code."),m.localize(235,"Show the code action menu when the cursor is on lines with code or on empty lines.")],description:m.localize(236,"Enables the Code Action lightbulb in the editor.")}})}validate(fe){return!fe||typeof fe!="object"?this.defaultValue:{enabled:C(fe.enabled,this.defaultValue.enabled,[U.Off,U.OnCode,U.On])}}}class Y extends p{constructor(){const fe={enabled:!0,maxLineCount:5,defaultModel:"outlineModel",scrollWithEditor:!0};super(116,"stickyScroll",fe,{"editor.stickyScroll.enabled":{type:"boolean",default:fe.enabled,description:m.localize(237,"Shows the nested current scopes during the scroll at the top of the editor."),tags:["experimental"]},"editor.stickyScroll.maxLineCount":{type:"number",default:fe.maxLineCount,minimum:1,maximum:20,description:m.localize(238,"Defines the maximum number of sticky lines to show.")},"editor.stickyScroll.defaultModel":{type:"string",enum:["outlineModel","foldingProviderModel","indentationModel"],default:fe.defaultModel,description:m.localize(239,"Defines the model to use for determining which lines to stick. If the outline model does not exist, it will fall back on the folding provider model which falls back on the indentation model. This order is respected in all three cases.")},"editor.stickyScroll.scrollWithEditor":{type:"boolean",default:fe.scrollWithEditor,description:m.localize(240,"Enable scrolling of Sticky Scroll with the editor's horizontal scrollbar.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),maxLineCount:l.clampedInt(_e.maxLineCount,this.defaultValue.maxLineCount,1,20),defaultModel:C(_e.defaultModel,this.defaultValue.defaultModel,["outlineModel","foldingProviderModel","indentationModel"]),scrollWithEditor:s(_e.scrollWithEditor,this.defaultValue.scrollWithEditor)}}}class G extends p{constructor(){const fe={enabled:"on",fontSize:0,fontFamily:"",padding:!1};super(142,"inlayHints",fe,{"editor.inlayHints.enabled":{type:"string",default:fe.enabled,description:m.localize(241,"Enables the inlay hints in the editor."),enum:["on","onUnlessPressed","offUnlessPressed","off"],markdownEnumDescriptions:[m.localize(242,"Inlay hints are enabled"),m.localize(243,"Inlay hints are showing by default and hide when holding {0}",I.isMacintosh?"Ctrl+Option":"Ctrl+Alt"),m.localize(244,"Inlay hints are hidden by default and show when holding {0}",I.isMacintosh?"Ctrl+Option":"Ctrl+Alt"),m.localize(245,"Inlay hints are disabled")]},"editor.inlayHints.fontSize":{type:"number",default:fe.fontSize,markdownDescription:m.localize(246,"Controls font size of inlay hints in the editor. As default the {0} is used when the configured value is less than {1} or greater than the editor font size.","`#editor.fontSize#`","`5`")},"editor.inlayHints.fontFamily":{type:"string",default:fe.fontFamily,markdownDescription:m.localize(247,"Controls font family of inlay hints in the editor. When set to empty, the {0} is used.","`#editor.fontFamily#`")},"editor.inlayHints.padding":{type:"boolean",default:fe.padding,description:m.localize(248,"Enables the padding around the inlay hints in the editor.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return typeof _e.enabled=="boolean"&&(_e.enabled=_e.enabled?"on":"off"),{enabled:C(_e.enabled,this.defaultValue.enabled,["on","off","offUnlessPressed","onUnlessPressed"]),fontSize:l.clampedInt(_e.fontSize,this.defaultValue.fontSize,0,100),fontFamily:u.string(_e.fontFamily,this.defaultValue.fontFamily),padding:s(_e.padding,this.defaultValue.padding)}}}class K extends p{constructor(){super(66,"lineDecorationsWidth",10)}validate(fe){return typeof fe=="string"&&/^\d+(\.\d+)?ch$/.test(fe)?-parseFloat(fe.substring(0,fe.length-2)):l.clampedInt(fe,this.defaultValue,0,1e3)}compute(fe,_e,xe){return xe<0?l.clampedInt(-xe*fe.fontInfo.typicalHalfwidthCharacterWidth,this.defaultValue,0,1e3):xe}}class R extends r{constructor(){super(67,"lineHeight",e.EDITOR_FONT_DEFAULTS.lineHeight,fe=>r.clamp(fe,0,150),{markdownDescription:m.localize(249,`Controls the line height. - Use 0 to automatically compute the line height from the font size. - Values between 0 and 8 will be used as a multiplier with the font size. - Values greater than or equal to 8 will be used as effective values.`)})}compute(fe,_e,xe){return fe.fontInfo.lineHeight}}class J extends p{constructor(){const fe={enabled:!0,size:"proportional",side:"right",showSlider:"mouseover",autohide:!1,renderCharacters:!0,maxColumn:120,scale:1,showRegionSectionHeaders:!0,showMarkSectionHeaders:!0,sectionHeaderFontSize:9,sectionHeaderLetterSpacing:1};super(73,"minimap",fe,{"editor.minimap.enabled":{type:"boolean",default:fe.enabled,description:m.localize(250,"Controls whether the minimap is shown.")},"editor.minimap.autohide":{type:"boolean",default:fe.autohide,description:m.localize(251,"Controls whether the minimap is hidden automatically.")},"editor.minimap.size":{type:"string",enum:["proportional","fill","fit"],enumDescriptions:[m.localize(252,"The minimap has the same size as the editor contents (and might scroll)."),m.localize(253,"The minimap will stretch or shrink as necessary to fill the height of the editor (no scrolling)."),m.localize(254,"The minimap will shrink as necessary to never be larger than the editor (no scrolling).")],default:fe.size,description:m.localize(255,"Controls the size of the minimap.")},"editor.minimap.side":{type:"string",enum:["left","right"],default:fe.side,description:m.localize(256,"Controls the side where to render the minimap.")},"editor.minimap.showSlider":{type:"string",enum:["always","mouseover"],default:fe.showSlider,description:m.localize(257,"Controls when the minimap slider is shown.")},"editor.minimap.scale":{type:"number",default:fe.scale,minimum:1,maximum:3,enum:[1,2,3],description:m.localize(258,"Scale of content drawn in the minimap: 1, 2 or 3.")},"editor.minimap.renderCharacters":{type:"boolean",default:fe.renderCharacters,description:m.localize(259,"Render the actual characters on a line as opposed to color blocks.")},"editor.minimap.maxColumn":{type:"number",default:fe.maxColumn,description:m.localize(260,"Limit the width of the minimap to render at most a certain number of columns.")},"editor.minimap.showRegionSectionHeaders":{type:"boolean",default:fe.showRegionSectionHeaders,description:m.localize(261,"Controls whether named regions are shown as section headers in the minimap.")},"editor.minimap.showMarkSectionHeaders":{type:"boolean",default:fe.showMarkSectionHeaders,description:m.localize(262,"Controls whether MARK: comments are shown as section headers in the minimap.")},"editor.minimap.sectionHeaderFontSize":{type:"number",default:fe.sectionHeaderFontSize,description:m.localize(263,"Controls the font size of section headers in the minimap.")},"editor.minimap.sectionHeaderLetterSpacing":{type:"number",default:fe.sectionHeaderLetterSpacing,description:m.localize(264,"Controls the amount of space (in pixels) between characters of section header. This helps the readability of the header in small font sizes.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),autohide:s(_e.autohide,this.defaultValue.autohide),size:C(_e.size,this.defaultValue.size,["proportional","fill","fit"]),side:C(_e.side,this.defaultValue.side,["right","left"]),showSlider:C(_e.showSlider,this.defaultValue.showSlider,["always","mouseover"]),renderCharacters:s(_e.renderCharacters,this.defaultValue.renderCharacters),scale:l.clampedInt(_e.scale,1,1,3),maxColumn:l.clampedInt(_e.maxColumn,this.defaultValue.maxColumn,1,1e4),showRegionSectionHeaders:s(_e.showRegionSectionHeaders,this.defaultValue.showRegionSectionHeaders),showMarkSectionHeaders:s(_e.showMarkSectionHeaders,this.defaultValue.showMarkSectionHeaders),sectionHeaderFontSize:r.clamp(_e.sectionHeaderFontSize??this.defaultValue.sectionHeaderFontSize,4,32),sectionHeaderLetterSpacing:r.clamp(_e.sectionHeaderLetterSpacing??this.defaultValue.sectionHeaderLetterSpacing,0,5)}}}function ie(Fe){return Fe==="ctrlCmd"?I.isMacintosh?"metaKey":"ctrlKey":"altKey"}class ue extends p{constructor(){super(84,"padding",{top:0,bottom:0},{"editor.padding.top":{type:"number",default:0,minimum:0,maximum:1e3,description:m.localize(265,"Controls the amount of space between the top edge of the editor and the first line.")},"editor.padding.bottom":{type:"number",default:0,minimum:0,maximum:1e3,description:m.localize(266,"Controls the amount of space between the bottom edge of the editor and the last line.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{top:l.clampedInt(_e.top,0,0,1e3),bottom:l.clampedInt(_e.bottom,0,0,1e3)}}}class he extends p{constructor(){const fe={enabled:!0,cycle:!0};super(86,"parameterHints",fe,{"editor.parameterHints.enabled":{type:"boolean",default:fe.enabled,description:m.localize(267,"Enables a pop-up that shows parameter documentation and type information as you type.")},"editor.parameterHints.cycle":{type:"boolean",default:fe.cycle,description:m.localize(268,"Controls whether the parameter hints menu cycles or closes when reaching the end of the list.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),cycle:s(_e.cycle,this.defaultValue.cycle)}}}class pe extends t{constructor(){super(144)}compute(fe,_e,xe){return fe.pixelRatio}}class ae extends p{constructor(){super(88,"placeholder",void 0)}validate(fe){return typeof fe>"u"?this.defaultValue:typeof fe=="string"?fe:this.defaultValue}}class ee extends p{constructor(){const fe={other:"on",comments:"off",strings:"off"},_e=[{type:"boolean"},{type:"string",enum:["on","inline","off"],enumDescriptions:[m.localize(269,"Quick suggestions show inside the suggest widget"),m.localize(270,"Quick suggestions show as ghost text"),m.localize(271,"Quick suggestions are disabled")]}];super(90,"quickSuggestions",fe,{type:"object",additionalProperties:!1,properties:{strings:{anyOf:_e,default:fe.strings,description:m.localize(272,"Enable quick suggestions inside strings.")},comments:{anyOf:_e,default:fe.comments,description:m.localize(273,"Enable quick suggestions inside comments.")},other:{anyOf:_e,default:fe.other,description:m.localize(274,"Enable quick suggestions outside of strings and comments.")}},default:fe,markdownDescription:m.localize(275,"Controls whether suggestions should automatically show up while typing. This can be controlled for typing in comments, strings, and other code. Quick suggestion can be configured to show as ghost text or with the suggest widget. Also be aware of the {0}-setting which controls if suggestions are triggered by special characters.","`#editor.suggestOnTriggerCharacters#`")}),this.defaultValue=fe}validate(fe){if(typeof fe=="boolean"){const Be=fe?"on":"off";return{comments:Be,strings:Be,other:Be}}if(!fe||typeof fe!="object")return this.defaultValue;const{other:_e,comments:xe,strings:be}=fe,ve=["on","inline","off"];let we,Te,Pe;return typeof _e=="boolean"?we=_e?"on":"off":we=C(_e,this.defaultValue.other,ve),typeof xe=="boolean"?Te=xe?"on":"off":Te=C(xe,this.defaultValue.comments,ve),typeof be=="boolean"?Pe=be?"on":"off":Pe=C(be,this.defaultValue.strings,ve),{other:we,comments:Te,strings:Pe}}}class de extends p{constructor(){super(68,"lineNumbers",{renderType:1,renderFn:null},{type:"string",enum:["off","on","relative","interval"],enumDescriptions:[m.localize(276,"Line numbers are not rendered."),m.localize(277,"Line numbers are rendered as absolute number."),m.localize(278,"Line numbers are rendered as distance in lines to cursor position."),m.localize(279,"Line numbers are rendered every 10 lines.")],default:"on",description:m.localize(280,"Controls the display of line numbers.")})}validate(fe){let _e=this.defaultValue.renderType,xe=this.defaultValue.renderFn;return typeof fe<"u"&&(typeof fe=="function"?(_e=4,xe=fe):fe==="interval"?_e=3:fe==="relative"?_e=2:fe==="on"?_e=1:_e=0),{renderType:_e,renderFn:xe}}}function ge(Fe){const fe=Fe.get(99);return fe==="editable"?Fe.get(92):fe!=="on"}class X extends p{constructor(){const fe=[],_e={type:"number",description:m.localize(281,"Number of monospace characters at which this editor ruler will render.")};super(103,"rulers",fe,{type:"array",items:{anyOf:[_e,{type:["object"],properties:{column:_e,color:{type:"string",description:m.localize(282,"Color of this editor ruler."),format:"color-hex"}}}]},default:fe,description:m.localize(283,"Render vertical rulers after a certain number of monospace characters. Use multiple values for multiple rulers. No rulers are drawn if array is empty.")})}validate(fe){if(Array.isArray(fe)){const _e=[];for(const xe of fe)if(typeof xe=="number")_e.push({column:l.clampedInt(xe,0,0,1e4),color:null});else if(xe&&typeof xe=="object"){const be=xe;_e.push({column:l.clampedInt(be.column,0,0,1e4),color:be.color})}return _e.sort((xe,be)=>xe.column-be.column),_e}return this.defaultValue}}class B extends p{constructor(){super(93,"readOnlyMessage",void 0)}validate(fe){return!fe||typeof fe!="object"?this.defaultValue:fe}}function $(Fe,fe){if(typeof Fe!="string")return fe;switch(Fe){case"hidden":return 2;case"visible":return 3;default:return 1}}class Q extends p{constructor(){const fe={vertical:1,horizontal:1,arrowSize:11,useShadows:!0,verticalHasArrows:!1,horizontalHasArrows:!1,horizontalScrollbarSize:12,horizontalSliderSize:12,verticalScrollbarSize:14,verticalSliderSize:14,handleMouseWheel:!0,alwaysConsumeMouseWheel:!0,scrollByPage:!1,ignoreHorizontalScrollbarInContentHeight:!1};super(104,"scrollbar",fe,{"editor.scrollbar.vertical":{type:"string",enum:["auto","visible","hidden"],enumDescriptions:[m.localize(284,"The vertical scrollbar will be visible only when necessary."),m.localize(285,"The vertical scrollbar will always be visible."),m.localize(286,"The vertical scrollbar will always be hidden.")],default:"auto",description:m.localize(287,"Controls the visibility of the vertical scrollbar.")},"editor.scrollbar.horizontal":{type:"string",enum:["auto","visible","hidden"],enumDescriptions:[m.localize(288,"The horizontal scrollbar will be visible only when necessary."),m.localize(289,"The horizontal scrollbar will always be visible."),m.localize(290,"The horizontal scrollbar will always be hidden.")],default:"auto",description:m.localize(291,"Controls the visibility of the horizontal scrollbar.")},"editor.scrollbar.verticalScrollbarSize":{type:"number",default:fe.verticalScrollbarSize,description:m.localize(292,"The width of the vertical scrollbar.")},"editor.scrollbar.horizontalScrollbarSize":{type:"number",default:fe.horizontalScrollbarSize,description:m.localize(293,"The height of the horizontal scrollbar.")},"editor.scrollbar.scrollByPage":{type:"boolean",default:fe.scrollByPage,description:m.localize(294,"Controls whether clicks scroll by page or jump to click position.")},"editor.scrollbar.ignoreHorizontalScrollbarInContentHeight":{type:"boolean",default:fe.ignoreHorizontalScrollbarInContentHeight,description:m.localize(295,"When set, the horizontal scrollbar will not increase the size of the editor's content.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe,xe=l.clampedInt(_e.horizontalScrollbarSize,this.defaultValue.horizontalScrollbarSize,0,1e3),be=l.clampedInt(_e.verticalScrollbarSize,this.defaultValue.verticalScrollbarSize,0,1e3);return{arrowSize:l.clampedInt(_e.arrowSize,this.defaultValue.arrowSize,0,1e3),vertical:$(_e.vertical,this.defaultValue.vertical),horizontal:$(_e.horizontal,this.defaultValue.horizontal),useShadows:s(_e.useShadows,this.defaultValue.useShadows),verticalHasArrows:s(_e.verticalHasArrows,this.defaultValue.verticalHasArrows),horizontalHasArrows:s(_e.horizontalHasArrows,this.defaultValue.horizontalHasArrows),handleMouseWheel:s(_e.handleMouseWheel,this.defaultValue.handleMouseWheel),alwaysConsumeMouseWheel:s(_e.alwaysConsumeMouseWheel,this.defaultValue.alwaysConsumeMouseWheel),horizontalScrollbarSize:xe,horizontalSliderSize:l.clampedInt(_e.horizontalSliderSize,xe,0,1e3),verticalScrollbarSize:be,verticalSliderSize:l.clampedInt(_e.verticalSliderSize,be,0,1e3),scrollByPage:s(_e.scrollByPage,this.defaultValue.scrollByPage),ignoreHorizontalScrollbarInContentHeight:s(_e.ignoreHorizontalScrollbarInContentHeight,this.defaultValue.ignoreHorizontalScrollbarInContentHeight)}}}e.inUntrustedWorkspace="inUntrustedWorkspace",e.unicodeHighlightConfigKeys={allowedCharacters:"editor.unicodeHighlight.allowedCharacters",invisibleCharacters:"editor.unicodeHighlight.invisibleCharacters",nonBasicASCII:"editor.unicodeHighlight.nonBasicASCII",ambiguousCharacters:"editor.unicodeHighlight.ambiguousCharacters",includeComments:"editor.unicodeHighlight.includeComments",includeStrings:"editor.unicodeHighlight.includeStrings",allowedLocales:"editor.unicodeHighlight.allowedLocales"};class Z extends p{constructor(){const fe={nonBasicASCII:e.inUntrustedWorkspace,invisibleCharacters:!0,ambiguousCharacters:!0,includeComments:e.inUntrustedWorkspace,includeStrings:!0,allowedCharacters:{},allowedLocales:{_os:!0,_vscode:!0}};super(126,"unicodeHighlight",fe,{[e.unicodeHighlightConfigKeys.nonBasicASCII]:{restricted:!0,type:["boolean","string"],enum:[!0,!1,e.inUntrustedWorkspace],default:fe.nonBasicASCII,description:m.localize(296,"Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.")},[e.unicodeHighlightConfigKeys.invisibleCharacters]:{restricted:!0,type:"boolean",default:fe.invisibleCharacters,description:m.localize(297,"Controls whether characters that just reserve space or have no width at all are highlighted.")},[e.unicodeHighlightConfigKeys.ambiguousCharacters]:{restricted:!0,type:"boolean",default:fe.ambiguousCharacters,description:m.localize(298,"Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.")},[e.unicodeHighlightConfigKeys.includeComments]:{restricted:!0,type:["boolean","string"],enum:[!0,!1,e.inUntrustedWorkspace],default:fe.includeComments,description:m.localize(299,"Controls whether characters in comments should also be subject to Unicode highlighting.")},[e.unicodeHighlightConfigKeys.includeStrings]:{restricted:!0,type:["boolean","string"],enum:[!0,!1,e.inUntrustedWorkspace],default:fe.includeStrings,description:m.localize(300,"Controls whether characters in strings should also be subject to Unicode highlighting.")},[e.unicodeHighlightConfigKeys.allowedCharacters]:{restricted:!0,type:"object",default:fe.allowedCharacters,description:m.localize(301,"Defines allowed characters that are not being highlighted."),additionalProperties:{type:"boolean"}},[e.unicodeHighlightConfigKeys.allowedLocales]:{restricted:!0,type:"object",additionalProperties:{type:"boolean"},default:fe.allowedLocales,description:m.localize(302,"Unicode characters that are common in allowed locales are not being highlighted.")}})}applyUpdate(fe,_e){let xe=!1;_e.allowedCharacters&&fe&&(k.equals(fe.allowedCharacters,_e.allowedCharacters)||(fe={...fe,allowedCharacters:_e.allowedCharacters},xe=!0)),_e.allowedLocales&&fe&&(k.equals(fe.allowedLocales,_e.allowedLocales)||(fe={...fe,allowedLocales:_e.allowedLocales},xe=!0));const be=super.applyUpdate(fe,_e);return xe?new n(be.newValue,!0):be}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{nonBasicASCII:Ce(_e.nonBasicASCII,e.inUntrustedWorkspace,[!0,!1,e.inUntrustedWorkspace]),invisibleCharacters:s(_e.invisibleCharacters,this.defaultValue.invisibleCharacters),ambiguousCharacters:s(_e.ambiguousCharacters,this.defaultValue.ambiguousCharacters),includeComments:Ce(_e.includeComments,e.inUntrustedWorkspace,[!0,!1,e.inUntrustedWorkspace]),includeStrings:Ce(_e.includeStrings,e.inUntrustedWorkspace,[!0,!1,e.inUntrustedWorkspace]),allowedCharacters:this.validateBooleanMap(fe.allowedCharacters,this.defaultValue.allowedCharacters),allowedLocales:this.validateBooleanMap(fe.allowedLocales,this.defaultValue.allowedLocales)}}validateBooleanMap(fe,_e){if(typeof fe!="object"||!fe)return _e;const xe={};for(const[be,ve]of Object.entries(fe))ve===!0&&(xe[be]=!0);return xe}}class te extends p{constructor(){const fe={enabled:!0,mode:"subwordSmart",showToolbar:"onHover",suppressSuggestions:!1,keepOnBlur:!1,fontFamily:"default"};super(62,"inlineSuggest",fe,{"editor.inlineSuggest.enabled":{type:"boolean",default:fe.enabled,description:m.localize(303,"Controls whether to automatically show inline suggestions in the editor.")},"editor.inlineSuggest.showToolbar":{type:"string",default:fe.showToolbar,enum:["always","onHover","never"],enumDescriptions:[m.localize(304,"Show the inline suggestion toolbar whenever an inline suggestion is shown."),m.localize(305,"Show the inline suggestion toolbar when hovering over an inline suggestion."),m.localize(306,"Never show the inline suggestion toolbar.")],description:m.localize(307,"Controls when to show the inline suggestion toolbar.")},"editor.inlineSuggest.suppressSuggestions":{type:"boolean",default:fe.suppressSuggestions,description:m.localize(308,"Controls how inline suggestions interact with the suggest widget. If enabled, the suggest widget is not shown automatically when inline suggestions are available.")},"editor.inlineSuggest.fontFamily":{type:"string",default:fe.fontFamily,description:m.localize(309,"Controls the font family of the inline suggestions.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),mode:C(_e.mode,this.defaultValue.mode,["prefix","subword","subwordSmart"]),showToolbar:C(_e.showToolbar,this.defaultValue.showToolbar,["always","onHover","never"]),suppressSuggestions:s(_e.suppressSuggestions,this.defaultValue.suppressSuggestions),keepOnBlur:s(_e.keepOnBlur,this.defaultValue.keepOnBlur),fontFamily:u.string(_e.fontFamily,this.defaultValue.fontFamily)}}}class re extends p{constructor(){const fe={enabled:!1,showToolbar:"onHover",fontFamily:"default",keepOnBlur:!1};super(63,"experimentalInlineEdit",fe,{"editor.experimentalInlineEdit.enabled":{type:"boolean",default:fe.enabled,description:m.localize(310,"Controls whether to show inline edits in the editor.")},"editor.experimentalInlineEdit.showToolbar":{type:"string",default:fe.showToolbar,enum:["always","onHover","never"],enumDescriptions:[m.localize(311,"Show the inline edit toolbar whenever an inline suggestion is shown."),m.localize(312,"Show the inline edit toolbar when hovering over an inline suggestion."),m.localize(313,"Never show the inline edit toolbar.")],description:m.localize(314,"Controls when to show the inline edit toolbar.")},"editor.experimentalInlineEdit.fontFamily":{type:"string",default:fe.fontFamily,description:m.localize(315,"Controls the font family of the inline edit.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),showToolbar:C(_e.showToolbar,this.defaultValue.showToolbar,["always","onHover","never"]),fontFamily:u.string(_e.fontFamily,this.defaultValue.fontFamily),keepOnBlur:s(_e.keepOnBlur,this.defaultValue.keepOnBlur)}}}class le extends p{constructor(){const fe={enabled:E.EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.enabled,independentColorPoolPerBracketType:E.EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions.independentColorPoolPerBracketType};super(15,"bracketPairColorization",fe,{"editor.bracketPairColorization.enabled":{type:"boolean",default:fe.enabled,markdownDescription:m.localize(316,"Controls whether bracket pair colorization is enabled or not. Use {0} to override the bracket highlight colors.","`#workbench.colorCustomizations#`")},"editor.bracketPairColorization.independentColorPoolPerBracketType":{type:"boolean",default:fe.independentColorPoolPerBracketType,description:m.localize(317,"Controls whether each bracket type has its own independent color pool.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),independentColorPoolPerBracketType:s(_e.independentColorPoolPerBracketType,this.defaultValue.independentColorPoolPerBracketType)}}}class me extends p{constructor(){const fe={bracketPairs:!1,bracketPairsHorizontal:"active",highlightActiveBracketPair:!0,indentation:!0,highlightActiveIndentation:!0};super(16,"guides",fe,{"editor.guides.bracketPairs":{type:["boolean","string"],enum:[!0,"active",!1],enumDescriptions:[m.localize(318,"Enables bracket pair guides."),m.localize(319,"Enables bracket pair guides only for the active bracket pair."),m.localize(320,"Disables bracket pair guides.")],default:fe.bracketPairs,description:m.localize(321,"Controls whether bracket pair guides are enabled or not.")},"editor.guides.bracketPairsHorizontal":{type:["boolean","string"],enum:[!0,"active",!1],enumDescriptions:[m.localize(322,"Enables horizontal guides as addition to vertical bracket pair guides."),m.localize(323,"Enables horizontal guides only for the active bracket pair."),m.localize(324,"Disables horizontal bracket pair guides.")],default:fe.bracketPairsHorizontal,description:m.localize(325,"Controls whether horizontal bracket pair guides are enabled or not.")},"editor.guides.highlightActiveBracketPair":{type:"boolean",default:fe.highlightActiveBracketPair,description:m.localize(326,"Controls whether the editor should highlight the active bracket pair.")},"editor.guides.indentation":{type:"boolean",default:fe.indentation,description:m.localize(327,"Controls whether the editor should render indent guides.")},"editor.guides.highlightActiveIndentation":{type:["boolean","string"],enum:[!0,"always",!1],enumDescriptions:[m.localize(328,"Highlights the active indent guide."),m.localize(329,"Highlights the active indent guide even if bracket guides are highlighted."),m.localize(330,"Do not highlight the active indent guide.")],default:fe.highlightActiveIndentation,description:m.localize(331,"Controls whether the editor should highlight the active indent guide.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{bracketPairs:Ce(_e.bracketPairs,this.defaultValue.bracketPairs,[!0,!1,"active"]),bracketPairsHorizontal:Ce(_e.bracketPairsHorizontal,this.defaultValue.bracketPairsHorizontal,[!0,!1,"active"]),highlightActiveBracketPair:s(_e.highlightActiveBracketPair,this.defaultValue.highlightActiveBracketPair),indentation:s(_e.indentation,this.defaultValue.indentation),highlightActiveIndentation:Ce(_e.highlightActiveIndentation,this.defaultValue.highlightActiveIndentation,[!0,!1,"always"])}}}function Ce(Fe,fe,_e){const xe=_e.indexOf(Fe);return xe===-1?fe:_e[xe]}class ye extends p{constructor(){const fe={insertMode:"insert",filterGraceful:!0,snippetsPreventQuickSuggestions:!1,localityBonus:!1,shareSuggestSelections:!1,selectionMode:"always",showIcons:!0,showStatusBar:!1,preview:!1,previewMode:"subwordSmart",showInlineDetails:!0,showMethods:!0,showFunctions:!0,showConstructors:!0,showDeprecated:!0,matchOnWordStartOnly:!0,showFields:!0,showVariables:!0,showClasses:!0,showStructs:!0,showInterfaces:!0,showModules:!0,showProperties:!0,showEvents:!0,showOperators:!0,showUnits:!0,showValues:!0,showConstants:!0,showEnums:!0,showEnumMembers:!0,showKeywords:!0,showWords:!0,showColors:!0,showFiles:!0,showReferences:!0,showFolders:!0,showTypeParameters:!0,showSnippets:!0,showUsers:!0,showIssues:!0};super(119,"suggest",fe,{"editor.suggest.insertMode":{type:"string",enum:["insert","replace"],enumDescriptions:[m.localize(332,"Insert suggestion without overwriting text right of the cursor."),m.localize(333,"Insert suggestion and overwrite text right of the cursor.")],default:fe.insertMode,description:m.localize(334,"Controls whether words are overwritten when accepting completions. Note that this depends on extensions opting into this feature.")},"editor.suggest.filterGraceful":{type:"boolean",default:fe.filterGraceful,description:m.localize(335,"Controls whether filtering and sorting suggestions accounts for small typos.")},"editor.suggest.localityBonus":{type:"boolean",default:fe.localityBonus,description:m.localize(336,"Controls whether sorting favors words that appear close to the cursor.")},"editor.suggest.shareSuggestSelections":{type:"boolean",default:fe.shareSuggestSelections,markdownDescription:m.localize(337,"Controls whether remembered suggestion selections are shared between multiple workspaces and windows (needs `#editor.suggestSelection#`).")},"editor.suggest.selectionMode":{type:"string",enum:["always","never","whenTriggerCharacter","whenQuickSuggestion"],enumDescriptions:[m.localize(338,"Always select a suggestion when automatically triggering IntelliSense."),m.localize(339,"Never select a suggestion when automatically triggering IntelliSense."),m.localize(340,"Select a suggestion only when triggering IntelliSense from a trigger character."),m.localize(341,"Select a suggestion only when triggering IntelliSense as you type.")],default:fe.selectionMode,markdownDescription:m.localize(342,"Controls whether a suggestion is selected when the widget shows. Note that this only applies to automatically triggered suggestions ({0} and {1}) and that a suggestion is always selected when explicitly invoked, e.g via `Ctrl+Space`.","`#editor.quickSuggestions#`","`#editor.suggestOnTriggerCharacters#`")},"editor.suggest.snippetsPreventQuickSuggestions":{type:"boolean",default:fe.snippetsPreventQuickSuggestions,description:m.localize(343,"Controls whether an active snippet prevents quick suggestions.")},"editor.suggest.showIcons":{type:"boolean",default:fe.showIcons,description:m.localize(344,"Controls whether to show or hide icons in suggestions.")},"editor.suggest.showStatusBar":{type:"boolean",default:fe.showStatusBar,description:m.localize(345,"Controls the visibility of the status bar at the bottom of the suggest widget.")},"editor.suggest.preview":{type:"boolean",default:fe.preview,description:m.localize(346,"Controls whether to preview the suggestion outcome in the editor.")},"editor.suggest.showInlineDetails":{type:"boolean",default:fe.showInlineDetails,description:m.localize(347,"Controls whether suggest details show inline with the label or only in the details widget.")},"editor.suggest.maxVisibleSuggestions":{type:"number",deprecationMessage:m.localize(348,"This setting is deprecated. The suggest widget can now be resized.")},"editor.suggest.filteredTypes":{type:"object",deprecationMessage:m.localize(349,"This setting is deprecated, please use separate settings like 'editor.suggest.showKeywords' or 'editor.suggest.showSnippets' instead.")},"editor.suggest.showMethods":{type:"boolean",default:!0,markdownDescription:m.localize(350,"When enabled IntelliSense shows `method`-suggestions.")},"editor.suggest.showFunctions":{type:"boolean",default:!0,markdownDescription:m.localize(351,"When enabled IntelliSense shows `function`-suggestions.")},"editor.suggest.showConstructors":{type:"boolean",default:!0,markdownDescription:m.localize(352,"When enabled IntelliSense shows `constructor`-suggestions.")},"editor.suggest.showDeprecated":{type:"boolean",default:!0,markdownDescription:m.localize(353,"When enabled IntelliSense shows `deprecated`-suggestions.")},"editor.suggest.matchOnWordStartOnly":{type:"boolean",default:!0,markdownDescription:m.localize(354,"When enabled IntelliSense filtering requires that the first character matches on a word start. For example, `c` on `Console` or `WebContext` but _not_ on `description`. When disabled IntelliSense will show more results but still sorts them by match quality.")},"editor.suggest.showFields":{type:"boolean",default:!0,markdownDescription:m.localize(355,"When enabled IntelliSense shows `field`-suggestions.")},"editor.suggest.showVariables":{type:"boolean",default:!0,markdownDescription:m.localize(356,"When enabled IntelliSense shows `variable`-suggestions.")},"editor.suggest.showClasses":{type:"boolean",default:!0,markdownDescription:m.localize(357,"When enabled IntelliSense shows `class`-suggestions.")},"editor.suggest.showStructs":{type:"boolean",default:!0,markdownDescription:m.localize(358,"When enabled IntelliSense shows `struct`-suggestions.")},"editor.suggest.showInterfaces":{type:"boolean",default:!0,markdownDescription:m.localize(359,"When enabled IntelliSense shows `interface`-suggestions.")},"editor.suggest.showModules":{type:"boolean",default:!0,markdownDescription:m.localize(360,"When enabled IntelliSense shows `module`-suggestions.")},"editor.suggest.showProperties":{type:"boolean",default:!0,markdownDescription:m.localize(361,"When enabled IntelliSense shows `property`-suggestions.")},"editor.suggest.showEvents":{type:"boolean",default:!0,markdownDescription:m.localize(362,"When enabled IntelliSense shows `event`-suggestions.")},"editor.suggest.showOperators":{type:"boolean",default:!0,markdownDescription:m.localize(363,"When enabled IntelliSense shows `operator`-suggestions.")},"editor.suggest.showUnits":{type:"boolean",default:!0,markdownDescription:m.localize(364,"When enabled IntelliSense shows `unit`-suggestions.")},"editor.suggest.showValues":{type:"boolean",default:!0,markdownDescription:m.localize(365,"When enabled IntelliSense shows `value`-suggestions.")},"editor.suggest.showConstants":{type:"boolean",default:!0,markdownDescription:m.localize(366,"When enabled IntelliSense shows `constant`-suggestions.")},"editor.suggest.showEnums":{type:"boolean",default:!0,markdownDescription:m.localize(367,"When enabled IntelliSense shows `enum`-suggestions.")},"editor.suggest.showEnumMembers":{type:"boolean",default:!0,markdownDescription:m.localize(368,"When enabled IntelliSense shows `enumMember`-suggestions.")},"editor.suggest.showKeywords":{type:"boolean",default:!0,markdownDescription:m.localize(369,"When enabled IntelliSense shows `keyword`-suggestions.")},"editor.suggest.showWords":{type:"boolean",default:!0,markdownDescription:m.localize(370,"When enabled IntelliSense shows `text`-suggestions.")},"editor.suggest.showColors":{type:"boolean",default:!0,markdownDescription:m.localize(371,"When enabled IntelliSense shows `color`-suggestions.")},"editor.suggest.showFiles":{type:"boolean",default:!0,markdownDescription:m.localize(372,"When enabled IntelliSense shows `file`-suggestions.")},"editor.suggest.showReferences":{type:"boolean",default:!0,markdownDescription:m.localize(373,"When enabled IntelliSense shows `reference`-suggestions.")},"editor.suggest.showCustomcolors":{type:"boolean",default:!0,markdownDescription:m.localize(374,"When enabled IntelliSense shows `customcolor`-suggestions.")},"editor.suggest.showFolders":{type:"boolean",default:!0,markdownDescription:m.localize(375,"When enabled IntelliSense shows `folder`-suggestions.")},"editor.suggest.showTypeParameters":{type:"boolean",default:!0,markdownDescription:m.localize(376,"When enabled IntelliSense shows `typeParameter`-suggestions.")},"editor.suggest.showSnippets":{type:"boolean",default:!0,markdownDescription:m.localize(377,"When enabled IntelliSense shows `snippet`-suggestions.")},"editor.suggest.showUsers":{type:"boolean",default:!0,markdownDescription:m.localize(378,"When enabled IntelliSense shows `user`-suggestions.")},"editor.suggest.showIssues":{type:"boolean",default:!0,markdownDescription:m.localize(379,"When enabled IntelliSense shows `issues`-suggestions.")}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{insertMode:C(_e.insertMode,this.defaultValue.insertMode,["insert","replace"]),filterGraceful:s(_e.filterGraceful,this.defaultValue.filterGraceful),snippetsPreventQuickSuggestions:s(_e.snippetsPreventQuickSuggestions,this.defaultValue.filterGraceful),localityBonus:s(_e.localityBonus,this.defaultValue.localityBonus),shareSuggestSelections:s(_e.shareSuggestSelections,this.defaultValue.shareSuggestSelections),selectionMode:C(_e.selectionMode,this.defaultValue.selectionMode,["always","never","whenQuickSuggestion","whenTriggerCharacter"]),showIcons:s(_e.showIcons,this.defaultValue.showIcons),showStatusBar:s(_e.showStatusBar,this.defaultValue.showStatusBar),preview:s(_e.preview,this.defaultValue.preview),previewMode:C(_e.previewMode,this.defaultValue.previewMode,["prefix","subword","subwordSmart"]),showInlineDetails:s(_e.showInlineDetails,this.defaultValue.showInlineDetails),showMethods:s(_e.showMethods,this.defaultValue.showMethods),showFunctions:s(_e.showFunctions,this.defaultValue.showFunctions),showConstructors:s(_e.showConstructors,this.defaultValue.showConstructors),showDeprecated:s(_e.showDeprecated,this.defaultValue.showDeprecated),matchOnWordStartOnly:s(_e.matchOnWordStartOnly,this.defaultValue.matchOnWordStartOnly),showFields:s(_e.showFields,this.defaultValue.showFields),showVariables:s(_e.showVariables,this.defaultValue.showVariables),showClasses:s(_e.showClasses,this.defaultValue.showClasses),showStructs:s(_e.showStructs,this.defaultValue.showStructs),showInterfaces:s(_e.showInterfaces,this.defaultValue.showInterfaces),showModules:s(_e.showModules,this.defaultValue.showModules),showProperties:s(_e.showProperties,this.defaultValue.showProperties),showEvents:s(_e.showEvents,this.defaultValue.showEvents),showOperators:s(_e.showOperators,this.defaultValue.showOperators),showUnits:s(_e.showUnits,this.defaultValue.showUnits),showValues:s(_e.showValues,this.defaultValue.showValues),showConstants:s(_e.showConstants,this.defaultValue.showConstants),showEnums:s(_e.showEnums,this.defaultValue.showEnums),showEnumMembers:s(_e.showEnumMembers,this.defaultValue.showEnumMembers),showKeywords:s(_e.showKeywords,this.defaultValue.showKeywords),showWords:s(_e.showWords,this.defaultValue.showWords),showColors:s(_e.showColors,this.defaultValue.showColors),showFiles:s(_e.showFiles,this.defaultValue.showFiles),showReferences:s(_e.showReferences,this.defaultValue.showReferences),showFolders:s(_e.showFolders,this.defaultValue.showFolders),showTypeParameters:s(_e.showTypeParameters,this.defaultValue.showTypeParameters),showSnippets:s(_e.showSnippets,this.defaultValue.showSnippets),showUsers:s(_e.showUsers,this.defaultValue.showUsers),showIssues:s(_e.showIssues,this.defaultValue.showIssues)}}}class Le extends p{constructor(){super(114,"smartSelect",{selectLeadingAndTrailingWhitespace:!0,selectSubwords:!0},{"editor.smartSelect.selectLeadingAndTrailingWhitespace":{description:m.localize(380,"Whether leading and trailing whitespace should always be selected."),default:!0,type:"boolean"},"editor.smartSelect.selectSubwords":{description:m.localize(381,"Whether subwords (like 'foo' in 'fooBar' or 'foo_bar') should be selected."),default:!0,type:"boolean"}})}validate(fe){return!fe||typeof fe!="object"?this.defaultValue:{selectLeadingAndTrailingWhitespace:s(fe.selectLeadingAndTrailingWhitespace,this.defaultValue.selectLeadingAndTrailingWhitespace),selectSubwords:s(fe.selectSubwords,this.defaultValue.selectSubwords)}}}class Ee extends p{constructor(){const fe=[];super(131,"wordSegmenterLocales",fe,{anyOf:[{description:m.localize(382,"Locales to be used for word segmentation when doing word related navigations or operations. Specify the BCP 47 language tag of the word you wish to recognize (e.g., ja, zh-CN, zh-Hant-TW, etc.)."),type:"string"},{description:m.localize(383,"Locales to be used for word segmentation when doing word related navigations or operations. Specify the BCP 47 language tag of the word you wish to recognize (e.g., ja, zh-CN, zh-Hant-TW, etc.)."),type:"array",items:{type:"string"}}]})}validate(fe){if(typeof fe=="string"&&(fe=[fe]),Array.isArray(fe)){const _e=[];for(const xe of fe)if(typeof xe=="string")try{Intl.Segmenter.supportedLocalesOf(xe).length>0&&_e.push(xe)}catch{}return _e}return this.defaultValue}}class Me extends p{constructor(){super(139,"wrappingIndent",1,{"editor.wrappingIndent":{type:"string",enum:["none","same","indent","deepIndent"],enumDescriptions:[m.localize(384,"No indentation. Wrapped lines begin at column 1."),m.localize(385,"Wrapped lines get the same indentation as the parent."),m.localize(386,"Wrapped lines get +1 indentation toward the parent."),m.localize(387,"Wrapped lines get +2 indentation toward the parent.")],description:m.localize(388,"Controls the indentation of wrapped lines."),default:"same"}})}validate(fe){switch(fe){case"none":return 0;case"same":return 1;case"indent":return 2;case"deepIndent":return 3}return 1}compute(fe,_e,xe){return _e.get(2)===2?0:xe}}class Ae extends t{constructor(){super(147)}compute(fe,_e,xe){const be=_e.get(146);return{isDominatedByLongLines:fe.isDominatedByLongLines,isWordWrapMinified:be.isWordWrapMinified,isViewportWrapping:be.isViewportWrapping,wrappingColumn:be.wrappingColumn}}}class Ne extends p{constructor(){const fe={enabled:!0,showDropSelector:"afterDrop"};super(36,"dropIntoEditor",fe,{"editor.dropIntoEditor.enabled":{type:"boolean",default:fe.enabled,markdownDescription:m.localize(389,"Controls whether you can drag and drop a file into a text editor by holding down the `Shift` key (instead of opening the file in an editor).")},"editor.dropIntoEditor.showDropSelector":{type:"string",markdownDescription:m.localize(390,"Controls if a widget is shown when dropping files into the editor. This widget lets you control how the file is dropped."),enum:["afterDrop","never"],enumDescriptions:[m.localize(391,"Show the drop selector widget after a file is dropped into the editor."),m.localize(392,"Never show the drop selector widget. Instead the default drop provider is always used.")],default:"afterDrop"}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),showDropSelector:C(_e.showDropSelector,this.defaultValue.showDropSelector,["afterDrop","never"])}}}class Ke extends p{constructor(){const fe={enabled:!0,showPasteSelector:"afterPaste"};super(85,"pasteAs",fe,{"editor.pasteAs.enabled":{type:"boolean",default:fe.enabled,markdownDescription:m.localize(393,"Controls whether you can paste content in different ways.")},"editor.pasteAs.showPasteSelector":{type:"string",markdownDescription:m.localize(394,"Controls if a widget is shown when pasting content in to the editor. This widget lets you control how the file is pasted."),enum:["afterPaste","never"],enumDescriptions:[m.localize(395,"Show the paste selector widget after content is pasted into the editor."),m.localize(396,"Never show the paste selector widget. Instead the default pasting behavior is always used.")],default:"afterPaste"}})}validate(fe){if(!fe||typeof fe!="object")return this.defaultValue;const _e=fe;return{enabled:s(_e.enabled,this.defaultValue.enabled),showPasteSelector:C(_e.showPasteSelector,this.defaultValue.showPasteSelector,["afterPaste","never"])}}}const ze="Consolas, 'Courier New', monospace",Ge="Menlo, Monaco, 'Courier New', monospace",it="'Droid Sans Mono', 'monospace', monospace";e.EDITOR_FONT_DEFAULTS={fontFamily:I.isMacintosh?Ge:I.isLinux?it:ze,fontWeight:"normal",fontSize:I.isMacintosh?12:14,lineHeight:0,letterSpacing:0},e.editorOptionsRegistry=[];function Oe(Fe){return e.editorOptionsRegistry[Fe.id]=Fe,Fe}e.EditorOptions={acceptSuggestionOnCommitCharacter:Oe(new g(0,"acceptSuggestionOnCommitCharacter",!0,{markdownDescription:m.localize(397,"Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`;`) can be a commit character that accepts a suggestion and types that character.")})),acceptSuggestionOnEnter:Oe(new f(1,"acceptSuggestionOnEnter","on",["on","smart","off"],{markdownEnumDescriptions:["",m.localize(398,"Only accept a suggestion with `Enter` when it makes a textual change."),""],markdownDescription:m.localize(399,"Controls whether suggestions should be accepted on `Enter`, in addition to `Tab`. Helps to avoid ambiguity between inserting new lines or accepting suggestions.")})),accessibilitySupport:Oe(new w),accessibilityPageSize:Oe(new l(3,"accessibilityPageSize",10,1,1073741824,{description:m.localize(400,"Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 500. Warning: this has a performance implication for numbers larger than the default."),tags:["accessibility"]})),ariaLabel:Oe(new u(4,"ariaLabel",m.localize(401,"Editor content"))),ariaRequired:Oe(new g(5,"ariaRequired",!1,void 0)),screenReaderAnnounceInlineSuggestion:Oe(new g(8,"screenReaderAnnounceInlineSuggestion",!0,{description:m.localize(402,"Control whether inline suggestions are announced by a screen reader."),tags:["accessibility"]})),autoClosingBrackets:Oe(new f(6,"autoClosingBrackets","languageDefined",["always","languageDefined","beforeWhitespace","never"],{enumDescriptions:["",m.localize(403,"Use language configurations to determine when to autoclose brackets."),m.localize(404,"Autoclose brackets only when the cursor is to the left of whitespace."),""],description:m.localize(405,"Controls whether the editor should automatically close brackets after the user adds an opening bracket.")})),autoClosingComments:Oe(new f(7,"autoClosingComments","languageDefined",["always","languageDefined","beforeWhitespace","never"],{enumDescriptions:["",m.localize(406,"Use language configurations to determine when to autoclose comments."),m.localize(407,"Autoclose comments only when the cursor is to the left of whitespace."),""],description:m.localize(408,"Controls whether the editor should automatically close comments after the user adds an opening comment.")})),autoClosingDelete:Oe(new f(9,"autoClosingDelete","auto",["always","auto","never"],{enumDescriptions:["",m.localize(409,"Remove adjacent closing quotes or brackets only if they were automatically inserted."),""],description:m.localize(410,"Controls whether the editor should remove adjacent closing quotes or brackets when deleting.")})),autoClosingOvertype:Oe(new f(10,"autoClosingOvertype","auto",["always","auto","never"],{enumDescriptions:["",m.localize(411,"Type over closing quotes or brackets only if they were automatically inserted."),""],description:m.localize(412,"Controls whether the editor should type over closing quotes or brackets.")})),autoClosingQuotes:Oe(new f(11,"autoClosingQuotes","languageDefined",["always","languageDefined","beforeWhitespace","never"],{enumDescriptions:["",m.localize(413,"Use language configurations to determine when to autoclose quotes."),m.localize(414,"Autoclose quotes only when the cursor is to the left of whitespace."),""],description:m.localize(415,"Controls whether the editor should automatically close quotes after the user adds an opening quote.")})),autoIndent:Oe(new h(12,"autoIndent",4,"full",["none","keep","brackets","advanced","full"],v,{enumDescriptions:[m.localize(416,"The editor will not insert indentation automatically."),m.localize(417,"The editor will keep the current line's indentation."),m.localize(418,"The editor will keep the current line's indentation and honor language defined brackets."),m.localize(419,"The editor will keep the current line's indentation, honor language defined brackets and invoke special onEnterRules defined by languages."),m.localize(420,"The editor will keep the current line's indentation, honor language defined brackets, invoke special onEnterRules defined by languages, and honor indentationRules defined by languages.")],description:m.localize(421,"Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.")})),automaticLayout:Oe(new g(13,"automaticLayout",!1)),autoSurround:Oe(new f(14,"autoSurround","languageDefined",["languageDefined","quotes","brackets","never"],{enumDescriptions:[m.localize(422,"Use language configurations to determine when to automatically surround selections."),m.localize(423,"Surround with quotes but not brackets."),m.localize(424,"Surround with brackets but not quotes."),""],description:m.localize(425,"Controls whether the editor should automatically surround selections when typing quotes or brackets.")})),bracketPairColorization:Oe(new le),bracketPairGuides:Oe(new me),stickyTabStops:Oe(new g(117,"stickyTabStops",!1,{description:m.localize(426,"Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.")})),codeLens:Oe(new g(17,"codeLens",!0,{description:m.localize(427,"Controls whether the editor shows CodeLens.")})),codeLensFontFamily:Oe(new u(18,"codeLensFontFamily","",{description:m.localize(428,"Controls the font family for CodeLens.")})),codeLensFontSize:Oe(new l(19,"codeLensFontSize",0,0,100,{type:"number",default:0,minimum:0,maximum:100,markdownDescription:m.localize(429,"Controls the font size in pixels for CodeLens. When set to 0, 90% of `#editor.fontSize#` is used.")})),colorDecorators:Oe(new g(20,"colorDecorators",!0,{description:m.localize(430,"Controls whether the editor should render the inline color decorators and color picker.")})),colorDecoratorActivatedOn:Oe(new f(149,"colorDecoratorsActivatedOn","clickAndHover",["clickAndHover","hover","click"],{enumDescriptions:[m.localize(431,"Make the color picker appear both on click and hover of the color decorator"),m.localize(432,"Make the color picker appear on hover of the color decorator"),m.localize(433,"Make the color picker appear on click of the color decorator")],description:m.localize(434,"Controls the condition to make a color picker appear from a color decorator")})),colorDecoratorsLimit:Oe(new l(21,"colorDecoratorsLimit",500,1,1e6,{markdownDescription:m.localize(435,"Controls the max number of color decorators that can be rendered in an editor at once.")})),columnSelection:Oe(new g(22,"columnSelection",!1,{description:m.localize(436,"Enable that the selection with the mouse and keys is doing column selection.")})),comments:Oe(new S),contextmenu:Oe(new g(24,"contextmenu",!0)),copyWithSyntaxHighlighting:Oe(new g(25,"copyWithSyntaxHighlighting",!0,{description:m.localize(437,"Controls whether syntax highlighting should be copied into the clipboard.")})),cursorBlinking:Oe(new h(26,"cursorBlinking",1,"blink",["blink","smooth","phase","expand","solid"],L,{description:m.localize(438,"Control the cursor animation style.")})),cursorSmoothCaretAnimation:Oe(new f(27,"cursorSmoothCaretAnimation","off",["off","explicit","on"],{enumDescriptions:[m.localize(439,"Smooth caret animation is disabled."),m.localize(440,"Smooth caret animation is enabled only when the user moves the cursor with an explicit gesture."),m.localize(441,"Smooth caret animation is always enabled.")],description:m.localize(442,"Controls whether the smooth caret animation should be enabled.")})),cursorStyle:Oe(new h(28,"cursorStyle",D.Line,"line",["line","block","underline","line-thin","block-outline","underline-thin"],T,{description:m.localize(443,"Controls the cursor style.")})),cursorSurroundingLines:Oe(new l(29,"cursorSurroundingLines",0,0,1073741824,{description:m.localize(444,"Controls the minimal number of visible leading lines (minimum 0) and trailing lines (minimum 1) surrounding the cursor. Known as 'scrollOff' or 'scrollOffset' in some other editors.")})),cursorSurroundingLinesStyle:Oe(new f(30,"cursorSurroundingLinesStyle","default",["default","all"],{enumDescriptions:[m.localize(445,"`cursorSurroundingLines` is enforced only when triggered via the keyboard or API."),m.localize(446,"`cursorSurroundingLines` is enforced always.")],markdownDescription:m.localize(447,"Controls when `#editor.cursorSurroundingLines#` should be enforced.")})),cursorWidth:Oe(new l(31,"cursorWidth",0,0,1073741824,{markdownDescription:m.localize(448,"Controls the width of the cursor when `#editor.cursorStyle#` is set to `line`.")})),disableLayerHinting:Oe(new g(32,"disableLayerHinting",!1)),disableMonospaceOptimizations:Oe(new g(33,"disableMonospaceOptimizations",!1)),domReadOnly:Oe(new g(34,"domReadOnly",!1)),dragAndDrop:Oe(new g(35,"dragAndDrop",!0,{description:m.localize(449,"Controls whether the editor should allow moving selections via drag and drop.")})),emptySelectionClipboard:Oe(new A),dropIntoEditor:Oe(new Ne),stickyScroll:Oe(new Y),experimentalWhitespaceRendering:Oe(new f(38,"experimentalWhitespaceRendering","svg",["svg","font","off"],{enumDescriptions:[m.localize(450,"Use a new rendering method with svgs."),m.localize(451,"Use a new rendering method with font characters."),m.localize(452,"Use the stable rendering method.")],description:m.localize(453,"Controls whether whitespace is rendered with a new, experimental method.")})),extraEditorClassName:Oe(new u(39,"extraEditorClassName","")),fastScrollSensitivity:Oe(new r(40,"fastScrollSensitivity",5,Fe=>Fe<=0?5:Fe,{markdownDescription:m.localize(454,"Scrolling speed multiplier when pressing `Alt`.")})),find:Oe(new P),fixedOverflowWidgets:Oe(new g(42,"fixedOverflowWidgets",!1)),folding:Oe(new g(43,"folding",!0,{description:m.localize(455,"Controls whether the editor has code folding enabled.")})),foldingStrategy:Oe(new f(44,"foldingStrategy","auto",["auto","indentation"],{enumDescriptions:[m.localize(456,"Use a language-specific folding strategy if available, else the indentation-based one."),m.localize(457,"Use the indentation-based folding strategy.")],description:m.localize(458,"Controls the strategy for computing folding ranges.")})),foldingHighlight:Oe(new g(45,"foldingHighlight",!0,{description:m.localize(459,"Controls whether the editor should highlight folded ranges.")})),foldingImportsByDefault:Oe(new g(46,"foldingImportsByDefault",!1,{description:m.localize(460,"Controls whether the editor automatically collapses import ranges.")})),foldingMaximumRegions:Oe(new l(47,"foldingMaximumRegions",5e3,10,65e3,{description:m.localize(461,"The maximum number of foldable regions. Increasing this value may result in the editor becoming less responsive when the current source has a large number of foldable regions.")})),unfoldOnClickAfterEndOfLine:Oe(new g(48,"unfoldOnClickAfterEndOfLine",!1,{description:m.localize(462,"Controls whether clicking on the empty content after a folded line will unfold the line.")})),fontFamily:Oe(new u(49,"fontFamily",e.EDITOR_FONT_DEFAULTS.fontFamily,{description:m.localize(463,"Controls the font family.")})),fontInfo:Oe(new F),fontLigatures2:Oe(new N),fontSize:Oe(new x),fontWeight:Oe(new W),fontVariations:Oe(new O),formatOnPaste:Oe(new g(55,"formatOnPaste",!1,{description:m.localize(464,"Controls whether the editor should automatically format the pasted content. A formatter must be available and the formatter should be able to format a range in a document.")})),formatOnType:Oe(new g(56,"formatOnType",!1,{description:m.localize(465,"Controls whether the editor should automatically format the line after typing.")})),glyphMargin:Oe(new g(57,"glyphMargin",!0,{description:m.localize(466,"Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.")})),gotoLocation:Oe(new V),hideCursorInOverviewRuler:Oe(new g(59,"hideCursorInOverviewRuler",!1,{description:m.localize(467,"Controls whether the cursor should be hidden in the overview ruler.")})),hover:Oe(new q),inDiffEditor:Oe(new g(61,"inDiffEditor",!1)),letterSpacing:Oe(new r(64,"letterSpacing",e.EDITOR_FONT_DEFAULTS.letterSpacing,Fe=>r.clamp(Fe,-5,20),{description:m.localize(468,"Controls the letter spacing in pixels.")})),lightbulb:Oe(new j),lineDecorationsWidth:Oe(new K),lineHeight:Oe(new R),lineNumbers:Oe(new de),lineNumbersMinChars:Oe(new l(69,"lineNumbersMinChars",5,1,300)),linkedEditing:Oe(new g(70,"linkedEditing",!1,{description:m.localize(469,"Controls whether the editor has linked editing enabled. Depending on the language, related symbols such as HTML tags, are updated while editing.")})),links:Oe(new g(71,"links",!0,{description:m.localize(470,"Controls whether the editor should detect links and make them clickable.")})),matchBrackets:Oe(new f(72,"matchBrackets","always",["always","near","never"],{description:m.localize(471,"Highlight matching brackets.")})),minimap:Oe(new J),mouseStyle:Oe(new f(74,"mouseStyle","text",["text","default","copy"])),mouseWheelScrollSensitivity:Oe(new r(75,"mouseWheelScrollSensitivity",1,Fe=>Fe===0?1:Fe,{markdownDescription:m.localize(472,"A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.")})),mouseWheelZoom:Oe(new g(76,"mouseWheelZoom",!1,{markdownDescription:I.isMacintosh?m.localize(473,"Zoom the font of the editor when using mouse wheel and holding `Cmd`."):m.localize(474,"Zoom the font of the editor when using mouse wheel and holding `Ctrl`.")})),multiCursorMergeOverlapping:Oe(new g(77,"multiCursorMergeOverlapping",!0,{description:m.localize(475,"Merge multiple cursors when they are overlapping.")})),multiCursorModifier:Oe(new h(78,"multiCursorModifier","altKey","alt",["ctrlCmd","alt"],ie,{markdownEnumDescriptions:[m.localize(476,"Maps to `Control` on Windows and Linux and to `Command` on macOS."),m.localize(477,"Maps to `Alt` on Windows and Linux and to `Option` on macOS.")],markdownDescription:m.localize(478,"The modifier to be used to add multiple cursors with the mouse. The Go to Definition and Open Link mouse gestures will adapt such that they do not conflict with the [multicursor modifier](https://code.visualstudio.com/docs/editor/codebasics#_multicursor-modifier).")})),multiCursorPaste:Oe(new f(79,"multiCursorPaste","spread",["spread","full"],{markdownEnumDescriptions:[m.localize(479,"Each cursor pastes a single line of the text."),m.localize(480,"Each cursor pastes the full text.")],markdownDescription:m.localize(481,"Controls pasting when the line count of the pasted text matches the cursor count.")})),multiCursorLimit:Oe(new l(80,"multiCursorLimit",1e4,1,1e5,{markdownDescription:m.localize(482,"Controls the max number of cursors that can be in an active editor at once.")})),occurrencesHighlight:Oe(new f(81,"occurrencesHighlight","singleFile",["off","singleFile","multiFile"],{markdownEnumDescriptions:[m.localize(483,"Does not highlight occurrences."),m.localize(484,"Highlights occurrences only in the current file."),m.localize(485,"Experimental: Highlights occurrences across all valid open files.")],markdownDescription:m.localize(486,"Controls whether occurrences should be highlighted across open files.")})),overviewRulerBorder:Oe(new g(82,"overviewRulerBorder",!0,{description:m.localize(487,"Controls whether a border should be drawn around the overview ruler.")})),overviewRulerLanes:Oe(new l(83,"overviewRulerLanes",3,0,3)),padding:Oe(new ue),pasteAs:Oe(new Ke),parameterHints:Oe(new he),peekWidgetDefaultFocus:Oe(new f(87,"peekWidgetDefaultFocus","tree",["tree","editor"],{enumDescriptions:[m.localize(488,"Focus the tree when opening peek"),m.localize(489,"Focus the editor when opening peek")],description:m.localize(490,"Controls whether to focus the inline editor or the tree in the peek widget.")})),placeholder:Oe(new ae),definitionLinkOpensInPeek:Oe(new g(89,"definitionLinkOpensInPeek",!1,{description:m.localize(491,"Controls whether the Go to Definition mouse gesture always opens the peek widget.")})),quickSuggestions:Oe(new ee),quickSuggestionsDelay:Oe(new l(91,"quickSuggestionsDelay",10,0,1073741824,{description:m.localize(492,"Controls the delay in milliseconds after which quick suggestions will show up.")})),readOnly:Oe(new g(92,"readOnly",!1)),readOnlyMessage:Oe(new B),renameOnType:Oe(new g(94,"renameOnType",!1,{description:m.localize(493,"Controls whether the editor auto renames on type."),markdownDeprecationMessage:m.localize(494,"Deprecated, use `editor.linkedEditing` instead.")})),renderControlCharacters:Oe(new g(95,"renderControlCharacters",!0,{description:m.localize(495,"Controls whether the editor should render control characters."),restricted:!0})),renderFinalNewline:Oe(new f(96,"renderFinalNewline",I.isLinux?"dimmed":"on",["off","on","dimmed"],{description:m.localize(496,"Render last line number when the file ends with a newline.")})),renderLineHighlight:Oe(new f(97,"renderLineHighlight","line",["none","gutter","line","all"],{enumDescriptions:["","","",m.localize(497,"Highlights both the gutter and the current line.")],description:m.localize(498,"Controls how the editor should render the current line highlight.")})),renderLineHighlightOnlyWhenFocus:Oe(new g(98,"renderLineHighlightOnlyWhenFocus",!1,{description:m.localize(499,"Controls if the editor should render the current line highlight only when the editor is focused.")})),renderValidationDecorations:Oe(new f(99,"renderValidationDecorations","editable",["editable","on","off"])),renderWhitespace:Oe(new f(100,"renderWhitespace","selection",["none","boundary","selection","trailing","all"],{enumDescriptions:["",m.localize(500,"Render whitespace characters except for single spaces between words."),m.localize(501,"Render whitespace characters only on selected text."),m.localize(502,"Render only trailing whitespace characters."),""],description:m.localize(503,"Controls how the editor should render whitespace characters.")})),revealHorizontalRightPadding:Oe(new l(101,"revealHorizontalRightPadding",15,0,1e3)),roundedSelection:Oe(new g(102,"roundedSelection",!0,{description:m.localize(504,"Controls whether selections should have rounded corners.")})),rulers:Oe(new X),scrollbar:Oe(new Q),scrollBeyondLastColumn:Oe(new l(105,"scrollBeyondLastColumn",4,0,1073741824,{description:m.localize(505,"Controls the number of extra characters beyond which the editor will scroll horizontally.")})),scrollBeyondLastLine:Oe(new g(106,"scrollBeyondLastLine",!0,{description:m.localize(506,"Controls whether the editor will scroll beyond the last line.")})),scrollPredominantAxis:Oe(new g(107,"scrollPredominantAxis",!0,{description:m.localize(507,"Scroll only along the predominant axis when scrolling both vertically and horizontally at the same time. Prevents horizontal drift when scrolling vertically on a trackpad.")})),selectionClipboard:Oe(new g(108,"selectionClipboard",!0,{description:m.localize(508,"Controls whether the Linux primary clipboard should be supported."),included:I.isLinux})),selectionHighlight:Oe(new g(109,"selectionHighlight",!0,{description:m.localize(509,"Controls whether the editor should highlight matches similar to the selection.")})),selectOnLineNumbers:Oe(new g(110,"selectOnLineNumbers",!0)),showFoldingControls:Oe(new f(111,"showFoldingControls","mouseover",["always","never","mouseover"],{enumDescriptions:[m.localize(510,"Always show the folding controls."),m.localize(511,"Never show the folding controls and reduce the gutter size."),m.localize(512,"Only show the folding controls when the mouse is over the gutter.")],description:m.localize(513,"Controls when the folding controls on the gutter are shown.")})),showUnused:Oe(new g(112,"showUnused",!0,{description:m.localize(514,"Controls fading out of unused code.")})),showDeprecated:Oe(new g(141,"showDeprecated",!0,{description:m.localize(515,"Controls strikethrough deprecated variables.")})),inlayHints:Oe(new G),snippetSuggestions:Oe(new f(113,"snippetSuggestions","inline",["top","bottom","inline","none"],{enumDescriptions:[m.localize(516,"Show snippet suggestions on top of other suggestions."),m.localize(517,"Show snippet suggestions below other suggestions."),m.localize(518,"Show snippets suggestions with other suggestions."),m.localize(519,"Do not show snippet suggestions.")],description:m.localize(520,"Controls whether snippets are shown with other suggestions and how they are sorted.")})),smartSelect:Oe(new Le),smoothScrolling:Oe(new g(115,"smoothScrolling",!1,{description:m.localize(521,"Controls whether the editor will scroll using an animation.")})),stopRenderingLineAfter:Oe(new l(118,"stopRenderingLineAfter",1e4,-1,1073741824)),suggest:Oe(new ye),inlineSuggest:Oe(new te),inlineEdit:Oe(new re),inlineCompletionsAccessibilityVerbose:Oe(new g(150,"inlineCompletionsAccessibilityVerbose",!1,{description:m.localize(522,"Controls whether the accessibility hint should be provided to screen reader users when an inline completion is shown.")})),suggestFontSize:Oe(new l(120,"suggestFontSize",0,0,1e3,{markdownDescription:m.localize(523,"Font size for the suggest widget. When set to {0}, the value of {1} is used.","`0`","`#editor.fontSize#`")})),suggestLineHeight:Oe(new l(121,"suggestLineHeight",0,0,1e3,{markdownDescription:m.localize(524,"Line height for the suggest widget. When set to {0}, the value of {1} is used. The minimum value is 8.","`0`","`#editor.lineHeight#`")})),suggestOnTriggerCharacters:Oe(new g(122,"suggestOnTriggerCharacters",!0,{description:m.localize(525,"Controls whether suggestions should automatically show up when typing trigger characters.")})),suggestSelection:Oe(new f(123,"suggestSelection","first",["first","recentlyUsed","recentlyUsedByPrefix"],{markdownEnumDescriptions:[m.localize(526,"Always select the first suggestion."),m.localize(527,"Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log` because `log` has been completed recently."),m.localize(528,"Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`.")],description:m.localize(529,"Controls how suggestions are pre-selected when showing the suggest list.")})),tabCompletion:Oe(new f(124,"tabCompletion","off",["on","off","onlySnippets"],{enumDescriptions:[m.localize(530,"Tab complete will insert the best matching suggestion when pressing tab."),m.localize(531,"Disable tab completions."),m.localize(532,"Tab complete snippets when their prefix match. Works best when 'quickSuggestions' aren't enabled.")],description:m.localize(533,"Enables tab completions.")})),tabIndex:Oe(new l(125,"tabIndex",0,-1,1073741824)),unicodeHighlight:Oe(new Z),unusualLineTerminators:Oe(new f(127,"unusualLineTerminators","prompt",["auto","off","prompt"],{enumDescriptions:[m.localize(534,"Unusual line terminators are automatically removed."),m.localize(535,"Unusual line terminators are ignored."),m.localize(536,"Unusual line terminators prompt to be removed.")],description:m.localize(537,"Remove unusual line terminators that might cause problems.")})),useShadowDOM:Oe(new g(128,"useShadowDOM",!0)),useTabStops:Oe(new g(129,"useTabStops",!0,{description:m.localize(538,"Spaces and tabs are inserted and deleted in alignment with tab stops.")})),wordBreak:Oe(new f(130,"wordBreak","normal",["normal","keepAll"],{markdownEnumDescriptions:[m.localize(539,"Use the default line break rule."),m.localize(540,"Word breaks should not be used for Chinese/Japanese/Korean (CJK) text. Non-CJK text behavior is the same as for normal.")],description:m.localize(541,"Controls the word break rules used for Chinese/Japanese/Korean (CJK) text.")})),wordSegmenterLocales:Oe(new Ee),wordSeparators:Oe(new u(132,"wordSeparators",y.USUAL_WORD_SEPARATORS,{description:m.localize(542,"Characters that will be used as word separators when doing word related navigations or operations.")})),wordWrap:Oe(new f(133,"wordWrap","off",["off","on","wordWrapColumn","bounded"],{markdownEnumDescriptions:[m.localize(543,"Lines will never wrap."),m.localize(544,"Lines will wrap at the viewport width."),m.localize(545,"Lines will wrap at `#editor.wordWrapColumn#`."),m.localize(546,"Lines will wrap at the minimum of viewport and `#editor.wordWrapColumn#`.")],description:m.localize(547,"Controls how lines should wrap.")})),wordWrapBreakAfterCharacters:Oe(new u(134,"wordWrapBreakAfterCharacters"," })]?|/&.,;\xA2\xB0\u2032\u2033\u2030\u2103\u3001\u3002\uFF61\uFF64\uFFE0\uFF0C\uFF0E\uFF1A\uFF1B\uFF1F\uFF01\uFF05\u30FB\uFF65\u309D\u309E\u30FD\u30FE\u30FC\u30A1\u30A3\u30A5\u30A7\u30A9\u30C3\u30E3\u30E5\u30E7\u30EE\u30F5\u30F6\u3041\u3043\u3045\u3047\u3049\u3063\u3083\u3085\u3087\u308E\u3095\u3096\u31F0\u31F1\u31F2\u31F3\u31F4\u31F5\u31F6\u31F7\u31F8\u31F9\u31FA\u31FB\u31FC\u31FD\u31FE\u31FF\u3005\u303B\uFF67\uFF68\uFF69\uFF6A\uFF6B\uFF6C\uFF6D\uFF6E\uFF6F\uFF70\u201D\u3009\u300B\u300D\u300F\u3011\u3015\uFF09\uFF3D\uFF5D\uFF63")),wordWrapBreakBeforeCharacters:Oe(new u(135,"wordWrapBreakBeforeCharacters","([{\u2018\u201C\u3008\u300A\u300C\u300E\u3010\u3014\uFF08\uFF3B\uFF5B\uFF62\xA3\xA5\uFF04\uFFE1\uFFE5+\uFF0B")),wordWrapColumn:Oe(new l(136,"wordWrapColumn",80,1,1073741824,{markdownDescription:m.localize(548,"Controls the wrapping column of the editor when `#editor.wordWrap#` is `wordWrapColumn` or `bounded`.")})),wordWrapOverride1:Oe(new f(137,"wordWrapOverride1","inherit",["off","on","inherit"])),wordWrapOverride2:Oe(new f(138,"wordWrapOverride2","inherit",["off","on","inherit"])),editorClassName:Oe(new M),defaultColorDecorators:Oe(new g(148,"defaultColorDecorators",!1,{markdownDescription:m.localize(549,"Controls whether inline color decorations should be shown using the default document color provider")})),pixelRatio:Oe(new pe),tabFocusMode:Oe(new g(145,"tabFocusMode",!1,{markdownDescription:m.localize(550,"Controls whether the editor receives tabs or defers them to the workbench for navigation.")})),layoutInfo:Oe(new H),wrappingInfo:Oe(new Ae),wrappingIndent:Oe(new Me),wrappingStrategy:Oe(new z)}}),define(ne[655],se([1,0,5,39,11,74,37,9,4,226]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewCursor=e.CursorPlurality=void 0;class p{constructor(i,s,g,c,l,a,r){this.top=i,this.left=s,this.paddingLeft=g,this.width=c,this.height=l,this.textContent=a,this.textContentClassName=r}}var n;(function(t){t[t.Single=0]="Single",t[t.MultiPrimary=1]="MultiPrimary",t[t.MultiSecondary=2]="MultiSecondary"})(n||(e.CursorPlurality=n={}));class o{constructor(i,s){this._context=i;const g=this._context.configuration.options,c=g.get(50);this._cursorStyle=g.get(28),this._lineHeight=g.get(67),this._typicalHalfwidthCharacterWidth=c.typicalHalfwidthCharacterWidth,this._lineCursorWidth=Math.min(g.get(31),this._typicalHalfwidthCharacterWidth),this._isVisible=!0,this._domNode=(0,k.createFastDomNode)(document.createElement("div")),this._domNode.setClassName(`cursor ${b.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`),this._domNode.setHeight(this._lineHeight),this._domNode.setTop(0),this._domNode.setLeft(0),(0,E.applyFontInfo)(this._domNode,c),this._domNode.setDisplay("none"),this._position=new m.Position(1,1),this._pluralityClass="",this.setPlurality(s),this._lastRenderedContent="",this._renderData=null}getDomNode(){return this._domNode}getPosition(){return this._position}setPlurality(i){switch(i){default:case n.Single:this._pluralityClass="";break;case n.MultiPrimary:this._pluralityClass="cursor-primary";break;case n.MultiSecondary:this._pluralityClass="cursor-secondary";break}}show(){this._isVisible||(this._domNode.setVisibility("inherit"),this._isVisible=!0)}hide(){this._isVisible&&(this._domNode.setVisibility("hidden"),this._isVisible=!1)}onConfigurationChanged(i){const s=this._context.configuration.options,g=s.get(50);return this._cursorStyle=s.get(28),this._lineHeight=s.get(67),this._typicalHalfwidthCharacterWidth=g.typicalHalfwidthCharacterWidth,this._lineCursorWidth=Math.min(s.get(31),this._typicalHalfwidthCharacterWidth),(0,E.applyFontInfo)(this._domNode,g),!0}onCursorPositionChanged(i,s){return s?this._domNode.domNode.style.transitionProperty="none":this._domNode.domNode.style.transitionProperty="",this._position=i,!0}_getGraphemeAwarePosition(){const{lineNumber:i,column:s}=this._position,g=this._context.viewModel.getLineContent(i),[c,l]=I.getCharContainingOffset(g,s-1);return[new m.Position(i,c+1),g.substring(c,l)]}_prepareRender(i){let s="",g="";const[c,l]=this._getGraphemeAwarePosition();if(this._cursorStyle===y.TextEditorCursorStyle.Line||this._cursorStyle===y.TextEditorCursorStyle.LineThin){const v=i.visibleRangeForPosition(c);if(!v||v.outsideRenderedLine)return null;const w=d.getWindow(this._domNode.domNode);let S;this._cursorStyle===y.TextEditorCursorStyle.Line?(S=d.computeScreenAwareSize(w,this._lineCursorWidth>0?this._lineCursorWidth:2),S>2&&(s=l,g=this._getTokenClassName(c))):S=d.computeScreenAwareSize(w,1);let L=v.left,D=0;S>=2&&L>=1&&(D=1,L-=D);const T=i.getVerticalOffsetForLineNumber(c.lineNumber)-i.bigNumbersDelta;return new p(T,L,D,S,this._lineHeight,s,g)}const a=i.linesVisibleRangesForRange(new _.Range(c.lineNumber,c.column,c.lineNumber,c.column+l.length),!1);if(!a||a.length===0)return null;const r=a[0];if(r.outsideRenderedLine||r.ranges.length===0)return null;const u=r.ranges[0],C=l===" "?this._typicalHalfwidthCharacterWidth:u.width<1?this._typicalHalfwidthCharacterWidth:u.width;this._cursorStyle===y.TextEditorCursorStyle.Block&&(s=l,g=this._getTokenClassName(c));let f=i.getVerticalOffsetForLineNumber(c.lineNumber)-i.bigNumbersDelta,h=this._lineHeight;return(this._cursorStyle===y.TextEditorCursorStyle.Underline||this._cursorStyle===y.TextEditorCursorStyle.UnderlineThin)&&(f+=this._lineHeight-2,h=2),new p(f,u.left,0,C,h,s,g)}_getTokenClassName(i){const s=this._context.viewModel.getViewLineData(i.lineNumber),g=s.tokens.findTokenIndexAtOffset(i.column-1);return s.tokens.getClassName(g)}prepareRender(i){this._renderData=this._prepareRender(i)}render(i){return this._renderData?(this._lastRenderedContent!==this._renderData.textContent&&(this._lastRenderedContent=this._renderData.textContent,this._domNode.domNode.textContent=this._lastRenderedContent),this._domNode.setClassName(`cursor ${this._pluralityClass} ${b.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME} ${this._renderData.textContentClassName}`),this._domNode.setDisplay("block"),this._domNode.setTop(this._renderData.top),this._domNode.setLeft(this._renderData.left),this._domNode.setPaddingLeft(this._renderData.paddingLeft),this._domNode.setWidth(this._renderData.width),this._domNode.setLineHeight(this._renderData.height),this._domNode.setHeight(this._renderData.height),{domNode:this._domNode.domNode,position:this._position,contentLeft:this._renderData.left,height:this._renderData.height,width:2}):(this._domNode.setDisplay("none"),null)}}e.ViewCursor=o}),define(ne[261],se([1,0,16,37,165]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FontInfo=e.SERIALIZED_FONT_INFO_VERSION=e.BareFontInfo=void 0;const E=d.isMacintosh?1.5:1.35,y=8;class m{static createFromValidatedSettings(p,n,o){const t=p.get(49),i=p.get(53),s=p.get(52),g=p.get(51),c=p.get(54),l=p.get(67),a=p.get(64);return m._create(t,i,s,g,c,l,a,n,o)}static _create(p,n,o,t,i,s,g,c,l){s===0?s=E*o:s{this._evictUntrustedReadingsTimeout=-1,this._evictUntrustedReadings(o)},5e3))}_evictUntrustedReadings(o){const t=this._ensureCache(o),i=t.getValues();let s=!1;for(const g of i)g.isTrusted||(s=!0,t.remove(g));s&&this._onDidChange.fire()}readFontInfo(o,t){const i=this._ensureCache(o);if(!i.has(t)){let s=this._actualReadFontInfo(o,t);(s.typicalHalfwidthCharacterWidth<=2||s.typicalFullwidthCharacterWidth<=2||s.spaceWidth<=2||s.maxDigitWidth<=2)&&(s=new _.FontInfo({pixelRatio:k.PixelRatio.getInstance(o).value,fontFamily:s.fontFamily,fontWeight:s.fontWeight,fontSize:s.fontSize,fontFeatureSettings:s.fontFeatureSettings,fontVariationSettings:s.fontVariationSettings,lineHeight:s.lineHeight,letterSpacing:s.letterSpacing,isMonospace:s.isMonospace,typicalHalfwidthCharacterWidth:Math.max(s.typicalHalfwidthCharacterWidth,5),typicalFullwidthCharacterWidth:Math.max(s.typicalFullwidthCharacterWidth,5),canUseHalfwidthRightwardsArrow:s.canUseHalfwidthRightwardsArrow,spaceWidth:Math.max(s.spaceWidth,5),middotWidth:Math.max(s.middotWidth,5),wsmiddotWidth:Math.max(s.wsmiddotWidth,5),maxDigitWidth:Math.max(s.maxDigitWidth,5)},!1)),this._writeToCache(o,t,s)}return i.get(t)}_createRequest(o,t,i,s){const g=new y.CharWidthRequest(o,t);return i.push(g),s?.push(g),g}_actualReadFontInfo(o,t){const i=[],s=[],g=this._createRequest("n",0,i,s),c=this._createRequest("\uFF4D",0,i,null),l=this._createRequest(" ",0,i,s),a=this._createRequest("0",0,i,s),r=this._createRequest("1",0,i,s),u=this._createRequest("2",0,i,s),C=this._createRequest("3",0,i,s),f=this._createRequest("4",0,i,s),h=this._createRequest("5",0,i,s),v=this._createRequest("6",0,i,s),w=this._createRequest("7",0,i,s),S=this._createRequest("8",0,i,s),L=this._createRequest("9",0,i,s),D=this._createRequest("\u2192",0,i,s),T=this._createRequest("\uFFEB",0,i,null),M=this._createRequest("\xB7",0,i,s),A=this._createRequest("\u2E31",0,i,null),P="|/-_ilm%";for(let W=0,V=P.length;W.001){O=!1;break}}let x=!0;return O&&T.width!==F&&(x=!1),T.width>D.width&&(x=!1),new _.FontInfo({pixelRatio:k.PixelRatio.getInstance(o).value,fontFamily:t.fontFamily,fontWeight:t.fontWeight,fontSize:t.fontSize,fontFeatureSettings:t.fontFeatureSettings,fontVariationSettings:t.fontVariationSettings,lineHeight:t.lineHeight,letterSpacing:t.letterSpacing,isMonospace:O,typicalHalfwidthCharacterWidth:g.width,typicalFullwidthCharacterWidth:c.width,canUseHalfwidthRightwardsArrow:x,spaceWidth:l.width,middotWidth:M.width,wsmiddotWidth:A.width,maxDigitWidth:N},!0)}}e.FontMeasurementsImpl=b;class p{constructor(){this._keys=Object.create(null),this._values=Object.create(null)}has(o){const t=o.getId();return!!this._values[t]}get(o){const t=o.getId();return this._values[t]}put(o,t){const i=o.getId();this._keys[i]=o,this._values[i]=t}remove(o){const t=o.getId();delete this._keys[t],delete this._values[t]}getValues(){return Object.keys(this._keys).map(o=>this._values[o])}}e.FontMeasurements=new b}),define(ne[116],se([1,0,11,16,160]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StringBuilder=void 0,e.getPlatformTextDecoder=p,e.decodeUTF16LE=n;let E;function y(){return E||(E=new TextDecoder("UTF-16LE")),E}let m;function _(){return m||(m=new TextDecoder("UTF-16BE")),m}let b;function p(){return b||(b=k.isLittleEndian()?y():_()),b}function n(i,s,g){const c=new Uint16Array(i.buffer,s,g);return g>0&&(c[0]===65279||c[0]===65534)?o(i,s,g):y().decode(c)}function o(i,s,g){const c=[];let l=0;for(let a=0;a=this._capacity){this._flushBuffer(),this._completedStrings[this._completedStrings.length]=s;return}for(let c=0;cg});class p{static create(c){return new p(new WeakRef(c))}constructor(c){this.targetWindow=c}createLineBreaksComputer(c,l,a,r,u){const C=[],f=[];return{addRequest:(h,v,w)=>{C.push(h),f.push(v)},finalize:()=>n((0,I.assertIsDefined)(this.targetWindow.deref()),C,c,l,a,r,u,f)}}}e.DOMLineBreaksComputerFactory=p;function n(g,c,l,a,r,u,C,f){function h(H){const z=f[H];if(z){const U=_.LineInjectedText.applyInjectedText(c[H],z),j=z.map(G=>G.options),Y=z.map(G=>G.column-1);return new m.ModelLineProjectionData(Y,j,[U.length],[],0)}else return null}if(r===-1){const H=[];for(let z=0,U=c.length;zv?(U=0,j=0):Y=v-R}const G=z.substr(U),K=o(G,j,a,Y,T,L);M[H]=U,A[H]=j,P[H]=G,N[H]=K[0],O[H]=K[1]}const F=T.build(),x=b?.createHTML(F)??F;D.innerHTML=x,D.style.position="absolute",D.style.top="10000",C==="keepAll"?(D.style.wordBreak="keep-all",D.style.overflowWrap="anywhere"):(D.style.wordBreak="inherit",D.style.overflowWrap="break-word"),g.document.body.appendChild(D);const W=document.createRange(),V=Array.prototype.slice.call(D.children,0),q=[];for(let H=0;Hue.options),J=ie.map(ue=>ue.column-1)):(R=null,J=null),q[H]=new m.ModelLineProjectionData(J,R,U,K,Y)}return D.remove(),q}function o(g,c,l,a,r,u){if(u!==0){const L=String(u);r.appendString('
      ');const C=g.length;let f=c,h=0;const v=[],w=[];let S=0");for(let L=0;L"),v[L]=h,w[L]=f;const D=S;S=L+1"),v[g.length]=h,w[g.length]=f,r.appendString("
      "),[v,w]}function t(g,c,l,a){if(l.length<=1)return null;const r=Array.prototype.slice.call(c.children,0),u=[];try{i(g,r,a,0,null,l.length-1,null,u)}catch(C){return console.log(C),null}return u.length===0?null:(u.push(l.length),u)}function i(g,c,l,a,r,u,C,f){if(a===u||(r=r||s(g,c,l[a],l[a+1]),C=C||s(g,c,l[u],l[u+1]),Math.abs(r[0].top-C[0].top)<=.1))return;if(a+1===u){f.push(u);return}const h=a+(u-a)/2|0,v=s(g,c,l[h],l[h+1]);i(g,c,l,a,r,h,v,f),i(g,c,l,h,v,u,C,f)}function s(g,c,l,a){return g.setStart(c[l/16384|0].firstChild,l%16384),g.setEnd(c[a/16384|0].firstChild,a%16384),g.getClientRects()}}),define(ne[262],se([1,0,39,103,8,116]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.VisibleLinesCollection=e.RenderedLinesCollection=void 0;class y{constructor(p){this._lineFactory=p,this._set(1,[])}flush(){this._set(1,[])}_set(p,n){this._lines=n,this._rendLineNumberStart=p}_get(){return{rendLineNumberStart:this._rendLineNumberStart,lines:this._lines}}getStartLineNumber(){return this._rendLineNumberStart}getEndLineNumber(){return this._rendLineNumberStart+this._lines.length-1}getCount(){return this._lines.length}getLine(p){const n=p-this._rendLineNumberStart;if(n<0||n>=this._lines.length)throw new I.BugIndicatingError("Illegal value for lineNumber");return this._lines[n]}onLinesDeleted(p,n){if(this.getCount()===0)return null;const o=this.getStartLineNumber(),t=this.getEndLineNumber();if(nt)return null;let i=0,s=0;for(let c=o;c<=t;c++){const l=c-this._rendLineNumberStart;p<=c&&c<=n&&(s===0?(i=l,s=1):s++)}if(p=t&&g<=i&&(this._lines[g-this._rendLineNumberStart].onContentChanged(),s=!0);return s}onLinesInserted(p,n){if(this.getCount()===0)return null;const o=n-p+1,t=this.getStartLineNumber(),i=this.getEndLineNumber();if(p<=t)return this._rendLineNumberStart+=o,null;if(p>i)return null;if(o+p>i)return this._lines.splice(p-this._rendLineNumberStart,i-p+1);const s=[];for(let r=0;ro)continue;const c=Math.max(n,g.fromLineNumber),l=Math.min(o,g.toLineNumber);for(let a=c;a<=l;a++){const r=a-this._rendLineNumberStart;this._lines[r].onTokensChanged(),t=!0}}return t}}e.RenderedLinesCollection=y;class m{constructor(p){this._lineFactory=p,this.domNode=this._createDomNode(),this._linesCollection=new y(this._lineFactory)}_createDomNode(){const p=(0,d.createFastDomNode)(document.createElement("div"));return p.setClassName("view-layer"),p.setPosition("absolute"),p.domNode.setAttribute("role","presentation"),p.domNode.setAttribute("aria-hidden","true"),p}onConfigurationChanged(p){return!!p.hasChanged(146)}onFlushed(p){return this._linesCollection.flush(),!0}onLinesChanged(p){return this._linesCollection.onLinesChanged(p.fromLineNumber,p.count)}onLinesDeleted(p){const n=this._linesCollection.onLinesDeleted(p.fromLineNumber,p.toLineNumber);if(n)for(let o=0,t=n.length;op})}constructor(p,n,o){this._domNode=p,this._lineFactory=n,this._viewportData=o}render(p,n,o,t){const i={rendLineNumberStart:p.rendLineNumberStart,lines:p.lines.slice(0),linesLength:p.linesLength};if(i.rendLineNumberStart+i.linesLength-1n){const s=n,g=Math.min(o,i.rendLineNumberStart-1);s<=g&&(this._insertLinesBefore(i,s,g,t,n),i.linesLength+=g-s+1)}else if(i.rendLineNumberStart0&&(this._removeLinesBefore(i,s),i.linesLength-=s)}if(i.rendLineNumberStart=n,i.rendLineNumberStart+i.linesLength-1o){const s=Math.max(0,o-i.rendLineNumberStart+1),c=i.linesLength-1-s+1;c>0&&(this._removeLinesAfter(i,c),i.linesLength-=c)}return this._finishRendering(i,!1,t),i}_renderUntouchedLines(p,n,o,t,i){const s=p.rendLineNumberStart,g=p.lines;for(let c=n;c<=o;c++){const l=s+c;g[c].layoutLine(l,t[l-i],this._viewportData.lineHeight)}}_insertLinesBefore(p,n,o,t,i){const s=[];let g=0;for(let c=n;c<=o;c++)s[g++]=this._lineFactory.createLine();p.lines=s.concat(p.lines)}_removeLinesBefore(p,n){for(let o=0;o=0;g--){const c=p.lines[g];t[g]&&(c.setDomNode(s),s=s.previousSibling)}}_finishRenderingInvalidLines(p,n,o){const t=document.createElement("div");_._ttPolicy&&(n=_._ttPolicy.createHTML(n)),t.innerHTML=n;for(let i=0;inew m(this._dynamicOverlays)}),this.domNode=this._visibleLines.domNode;const t=this._context.configuration.options.get(50);(0,k.applyFontInfo)(this.domNode,t),this.domNode.setClassName("view-overlays")}shouldRender(){if(super.shouldRender())return!0;for(let n=0,o=this._dynamicOverlays.length;nt.shouldRender());for(let t=0,i=o.length;t'),s.appendString(g),s.appendString(""),!0)}layoutLine(n,o,t){this._domNode&&(this._domNode.setTop(o),this._domNode.setHeight(t))}}e.ViewOverlayLine=m;class _ extends y{constructor(n){super(n);const t=this._context.configuration.options.get(146);this._contentWidth=t.contentWidth,this.domNode.setHeight(0)}onConfigurationChanged(n){const t=this._context.configuration.options.get(146);return this._contentWidth=t.contentWidth,super.onConfigurationChanged(n)||!0}onScrollChanged(n){return super.onScrollChanged(n)||n.scrollWidthChanged}_viewOverlaysRender(n){super._viewOverlaysRender(n),this.domNode.setWidth(Math.max(n.scrollWidth,this._contentWidth))}}e.ContentViewOverlays=_;class b extends y{constructor(n){super(n);const o=this._context.configuration.options,t=o.get(146);this._contentLeft=t.contentLeft,this.domNode.setClassName("margin-view-overlays"),this.domNode.setWidth(1),(0,k.applyFontInfo)(this.domNode,o.get(50))}onConfigurationChanged(n){const o=this._context.configuration.options;(0,k.applyFontInfo)(this.domNode,o.get(50));const t=o.get(146);return this._contentLeft=t.contentLeft,super.onConfigurationChanged(n)||!0}onScrollChanged(n){return super.onScrollChanged(n)||n.scrollHeightChanged}_viewOverlaysRender(n){super._viewOverlaysRender(n);const o=Math.min(n.scrollHeight,1e6);this.domNode.setHeight(o),this.domNode.setWidth(this._contentLeft)}}e.MarginViewOverlays=b}),define(ne[367],se([1,0,160,116]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TextChange=void 0,e.compressConsecutiveTextChanges=y;function I(_){return _.replace(/\n/g,"\\n").replace(/\r/g,"\\r")}class E{get oldLength(){return this.oldText.length}get oldEnd(){return this.oldPosition+this.oldText.length}get newLength(){return this.newText.length}get newEnd(){return this.newPosition+this.newText.length}constructor(b,p,n,o){this.oldPosition=b,this.oldText=p,this.newPosition=n,this.newText=o}toString(){return this.oldText.length===0?`(insert@${this.oldPosition} "${I(this.newText)}")`:this.newText.length===0?`(delete@${this.oldPosition} "${I(this.oldText)}")`:`(replace@${this.oldPosition} "${I(this.oldText)}" with "${I(this.newText)}")`}static _writeStringSize(b){return 4+2*b.length}static _writeString(b,p,n){const o=p.length;d.writeUInt32BE(b,o,n),n+=4;for(let t=0;tn&&(n=t)}return n}else{if(typeof E=="string")return _?E==="*"?5:E===m?10:0:0;if(E){const{language:n,pattern:o,scheme:t,hasAccessToAllModels:i,notebookType:s}=E;if(!_&&!i)return 0;s&&b&&(y=b);let g=0;if(t)if(t===y.scheme)g=10;else if(t==="*")g=5;else return 0;if(n)if(n===m)g=10;else if(n==="*")g=Math.max(g,5);else return 0;if(s)if(s===p)g=10;else if(s==="*"&&p!==void 0)g=Math.max(g,5);else return 0;if(o){let c;if(typeof o=="string"?c=o:c={...o,base:(0,k.normalize)(o.base)},c===y.fsPath||(0,d.match)(c,y.fsPath))g=10;else return 0}return g}else return 0}}}),define(ne[658],se([1,0,6,2,40,368]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LanguageFeatureRegistry=void 0;function y(p){return typeof p=="string"?!1:Array.isArray(p)?p.every(y):!!p.exclusive}class m{constructor(n,o,t,i,s){this.uri=n,this.languageId=o,this.notebookUri=t,this.notebookType=i,this.recursive=s}equals(n){return this.notebookType===n.notebookType&&this.languageId===n.languageId&&this.uri.toString()===n.uri.toString()&&this.notebookUri?.toString()===n.notebookUri?.toString()&&this.recursive===n.recursive}}class _{constructor(n){this._notebookInfoResolver=n,this._clock=0,this._entries=[],this._onDidChange=new d.Emitter,this.onDidChange=this._onDidChange.event}register(n,o){let t={selector:n,provider:o,_score:-1,_time:this._clock++};return this._entries.push(t),this._lastCandidate=void 0,this._onDidChange.fire(this._entries.length),(0,k.toDisposable)(()=>{if(t){const i=this._entries.indexOf(t);i>=0&&(this._entries.splice(i,1),this._lastCandidate=void 0,this._onDidChange.fire(this._entries.length),t=void 0)}})}has(n){return this.all(n).length>0}all(n){if(!n)return[];this._updateScores(n,!1);const o=[];for(const t of this._entries)t._score>0&&o.push(t.provider);return o}ordered(n,o=!1){const t=[];return this._orderedForEach(n,o,i=>t.push(i.provider)),t}orderedGroups(n){const o=[];let t,i;return this._orderedForEach(n,!1,s=>{t&&i===s._score?t.push(s.provider):(i=s._score,t=[s.provider],o.push(t))}),o}_orderedForEach(n,o,t){this._updateScores(n,o);for(const i of this._entries)i._score>0&&t(i)}_updateScores(n,o){const t=this._notebookInfoResolver?.(n.uri),i=t?new m(n.uri,n.getLanguageId(),t.uri,t.type,o):new m(n.uri,n.getLanguageId(),void 0,void 0,o);if(!this._lastCandidate?.equals(i)){this._lastCandidate=i;for(const s of this._entries)if(s._score=(0,E.score)(s.selector,i.uri,i.languageId,(0,I.shouldSynchronizeModel)(n),i.notebookUri,i.notebookType),y(s.selector)&&s._score>0)if(o)s._score=0;else{for(const g of this._entries)g._score=0;s._score=1e3;break}this._entries.sort(_._compareByScoreAndTime)}}static _compareByScoreAndTime(n,o){return n._scoreo._score?-1:b(n.selector)&&!b(o.selector)?1:!b(n.selector)&&b(o.selector)?-1:n._timeo._time?-1:0}}e.LanguageFeatureRegistry=_;function b(p){return typeof p=="string"?!1:Array.isArray(p)?p.some(b):!!p.isBuiltin}}),define(ne[27],se([1,0,26,22,4,585,3]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlineEditTriggerKind=e.TreeSitterTokenizationRegistry=e.TokenizationRegistry=e.LazyTokenizationSupport=e.InlayHintKind=e.Command=e.NewSymbolNameTriggerKind=e.NewSymbolNameTag=e.FoldingRangeKind=e.TextEdit=e.SymbolKinds=e.symbolKindNames=e.DocumentHighlightKind=e.SignatureHelpTriggerKind=e.DocumentPasteTriggerKind=e.SelectedSuggestionInfo=e.InlineCompletionTriggerKind=e.CompletionItemKinds=e.HoverVerbosityAction=e.EncodedTokenizationResult=e.TokenizationResult=e.Token=void 0,e.isLocationLink=c,e.getAriaLabelForSymbol=l;class m{constructor(D,T,M){this.offset=D,this.type=T,this.language=M,this._tokenBrand=void 0}toString(){return"("+this.offset+", "+this.type+")"}}e.Token=m;class _{constructor(D,T){this.tokens=D,this.endState=T,this._tokenizationResultBrand=void 0}}e.TokenizationResult=_;class b{constructor(D,T){this.tokens=D,this.endState=T,this._encodedTokenizationResultBrand=void 0}}e.EncodedTokenizationResult=b;var p;(function(L){L[L.Increase=0]="Increase",L[L.Decrease=1]="Decrease"})(p||(e.HoverVerbosityAction=p={}));var n;(function(L){const D=new Map;D.set(0,d.Codicon.symbolMethod),D.set(1,d.Codicon.symbolFunction),D.set(2,d.Codicon.symbolConstructor),D.set(3,d.Codicon.symbolField),D.set(4,d.Codicon.symbolVariable),D.set(5,d.Codicon.symbolClass),D.set(6,d.Codicon.symbolStruct),D.set(7,d.Codicon.symbolInterface),D.set(8,d.Codicon.symbolModule),D.set(9,d.Codicon.symbolProperty),D.set(10,d.Codicon.symbolEvent),D.set(11,d.Codicon.symbolOperator),D.set(12,d.Codicon.symbolUnit),D.set(13,d.Codicon.symbolValue),D.set(15,d.Codicon.symbolEnum),D.set(14,d.Codicon.symbolConstant),D.set(15,d.Codicon.symbolEnum),D.set(16,d.Codicon.symbolEnumMember),D.set(17,d.Codicon.symbolKeyword),D.set(27,d.Codicon.symbolSnippet),D.set(18,d.Codicon.symbolText),D.set(19,d.Codicon.symbolColor),D.set(20,d.Codicon.symbolFile),D.set(21,d.Codicon.symbolReference),D.set(22,d.Codicon.symbolCustomColor),D.set(23,d.Codicon.symbolFolder),D.set(24,d.Codicon.symbolTypeParameter),D.set(25,d.Codicon.account),D.set(26,d.Codicon.issues);function T(P){let N=D.get(P);return N||(console.info("No codicon found for CompletionItemKind "+P),N=d.Codicon.symbolProperty),N}L.toIcon=T;const M=new Map;M.set("method",0),M.set("function",1),M.set("constructor",2),M.set("field",3),M.set("variable",4),M.set("class",5),M.set("struct",6),M.set("interface",7),M.set("module",8),M.set("property",9),M.set("event",10),M.set("operator",11),M.set("unit",12),M.set("value",13),M.set("constant",14),M.set("enum",15),M.set("enum-member",16),M.set("enumMember",16),M.set("keyword",17),M.set("snippet",27),M.set("text",18),M.set("color",19),M.set("file",20),M.set("reference",21),M.set("customcolor",22),M.set("folder",23),M.set("type-parameter",24),M.set("typeParameter",24),M.set("account",25),M.set("issue",26);function A(P,N){let O=M.get(P);return typeof O>"u"&&!N&&(O=9),O}L.fromString=A})(n||(e.CompletionItemKinds=n={}));var o;(function(L){L[L.Automatic=0]="Automatic",L[L.Explicit=1]="Explicit"})(o||(e.InlineCompletionTriggerKind=o={}));class t{constructor(D,T,M,A){this.range=D,this.text=T,this.completionKind=M,this.isSnippetText=A}equals(D){return I.Range.lift(this.range).equalsRange(D.range)&&this.text===D.text&&this.completionKind===D.completionKind&&this.isSnippetText===D.isSnippetText}}e.SelectedSuggestionInfo=t;var i;(function(L){L[L.Automatic=0]="Automatic",L[L.PasteAs=1]="PasteAs"})(i||(e.DocumentPasteTriggerKind=i={}));var s;(function(L){L[L.Invoke=1]="Invoke",L[L.TriggerCharacter=2]="TriggerCharacter",L[L.ContentChange=3]="ContentChange"})(s||(e.SignatureHelpTriggerKind=s={}));var g;(function(L){L[L.Text=0]="Text",L[L.Read=1]="Read",L[L.Write=2]="Write"})(g||(e.DocumentHighlightKind=g={}));function c(L){return L&&k.URI.isUri(L.uri)&&I.Range.isIRange(L.range)&&(I.Range.isIRange(L.originSelectionRange)||I.Range.isIRange(L.targetSelectionRange))}e.symbolKindNames={17:(0,y.localize)(669,"array"),16:(0,y.localize)(670,"boolean"),4:(0,y.localize)(671,"class"),13:(0,y.localize)(672,"constant"),8:(0,y.localize)(673,"constructor"),9:(0,y.localize)(674,"enumeration"),21:(0,y.localize)(675,"enumeration member"),23:(0,y.localize)(676,"event"),7:(0,y.localize)(677,"field"),0:(0,y.localize)(678,"file"),11:(0,y.localize)(679,"function"),10:(0,y.localize)(680,"interface"),19:(0,y.localize)(681,"key"),5:(0,y.localize)(682,"method"),1:(0,y.localize)(683,"module"),2:(0,y.localize)(684,"namespace"),20:(0,y.localize)(685,"null"),15:(0,y.localize)(686,"number"),18:(0,y.localize)(687,"object"),24:(0,y.localize)(688,"operator"),3:(0,y.localize)(689,"package"),6:(0,y.localize)(690,"property"),14:(0,y.localize)(691,"string"),22:(0,y.localize)(692,"struct"),25:(0,y.localize)(693,"type parameter"),12:(0,y.localize)(694,"variable")};function l(L,D){return(0,y.localize)(695,"{0} ({1})",L,e.symbolKindNames[D])}var a;(function(L){const D=new Map;D.set(0,d.Codicon.symbolFile),D.set(1,d.Codicon.symbolModule),D.set(2,d.Codicon.symbolNamespace),D.set(3,d.Codicon.symbolPackage),D.set(4,d.Codicon.symbolClass),D.set(5,d.Codicon.symbolMethod),D.set(6,d.Codicon.symbolProperty),D.set(7,d.Codicon.symbolField),D.set(8,d.Codicon.symbolConstructor),D.set(9,d.Codicon.symbolEnum),D.set(10,d.Codicon.symbolInterface),D.set(11,d.Codicon.symbolFunction),D.set(12,d.Codicon.symbolVariable),D.set(13,d.Codicon.symbolConstant),D.set(14,d.Codicon.symbolString),D.set(15,d.Codicon.symbolNumber),D.set(16,d.Codicon.symbolBoolean),D.set(17,d.Codicon.symbolArray),D.set(18,d.Codicon.symbolObject),D.set(19,d.Codicon.symbolKey),D.set(20,d.Codicon.symbolNull),D.set(21,d.Codicon.symbolEnumMember),D.set(22,d.Codicon.symbolStruct),D.set(23,d.Codicon.symbolEvent),D.set(24,d.Codicon.symbolOperator),D.set(25,d.Codicon.symbolTypeParameter);function T(M){let A=D.get(M);return A||(console.info("No codicon found for SymbolKind "+M),A=d.Codicon.symbolProperty),A}L.toIcon=T})(a||(e.SymbolKinds=a={}));class r{}e.TextEdit=r;class u{static{this.Comment=new u("comment")}static{this.Imports=new u("imports")}static{this.Region=new u("region")}static fromValue(D){switch(D){case"comment":return u.Comment;case"imports":return u.Imports;case"region":return u.Region}return new u(D)}constructor(D){this.value=D}}e.FoldingRangeKind=u;var C;(function(L){L[L.AIGenerated=1]="AIGenerated"})(C||(e.NewSymbolNameTag=C={}));var f;(function(L){L[L.Invoke=0]="Invoke",L[L.Automatic=1]="Automatic"})(f||(e.NewSymbolNameTriggerKind=f={}));var h;(function(L){function D(T){return!T||typeof T!="object"?!1:typeof T.id=="string"&&typeof T.title=="string"}L.is=D})(h||(e.Command=h={}));var v;(function(L){L[L.Type=1]="Type",L[L.Parameter=2]="Parameter"})(v||(e.InlayHintKind=v={}));class w{constructor(D){this.createSupport=D,this._tokenizationSupport=null}dispose(){this._tokenizationSupport&&this._tokenizationSupport.then(D=>{D&&D.dispose()})}get tokenizationSupport(){return this._tokenizationSupport||(this._tokenizationSupport=this.createSupport()),this._tokenizationSupport}}e.LazyTokenizationSupport=w,e.TokenizationRegistry=new E.TokenizationRegistry,e.TreeSitterTokenizationRegistry=new E.TokenizationRegistry;var S;(function(L){L[L.Invoke=0]="Invoke",L[L.Automatic=1]="Automatic"})(S||(e.InlineEditTriggerKind=S={}))}),define(ne[177],se([1,0,27]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.NullState=void 0,e.nullTokenize=k,e.nullTokenizeEncoded=I,e.NullState=new class{clone(){return this}equals(E){return this===E}};function k(E,y){return new d.TokenizationResult([new d.Token(0,"",E)],y)}function I(E,y){const m=new Uint32Array(2);return m[0]=0,m[1]=(E<<0|0|0|32768|2<<24)>>>0,new d.EncodedTokenizationResult(m,y===null?e.NullState:y)}}),define(ne[208],se([1,0,11,116,4]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BracketsUtils=e.RichEditBrackets=e.RichEditBracket=void 0,e.createBracketOrRegExp=g;class E{constructor(r,u,C,f,h,v){this._richEditBracketBrand=void 0,this.languageId=r,this.index=u,this.open=C,this.close=f,this.forwardRegex=h,this.reversedRegex=v,this._openSet=E._toSet(this.open),this._closeSet=E._toSet(this.close)}isOpen(r){return this._openSet.has(r)}isClose(r){return this._closeSet.has(r)}static _toSet(r){const u=new Set;for(const C of r)u.add(C);return u}}e.RichEditBracket=E;function y(a){const r=a.length;a=a.map(v=>[v[0].toLowerCase(),v[1].toLowerCase()]);const u=[];for(let v=0;v{const[S,L]=v,[D,T]=w;return S===D||S===T||L===D||L===T},f=(v,w)=>{const S=Math.min(v,w),L=Math.max(v,w);for(let D=0;D0&&h.push({open:w,close:S})}return h}class m{constructor(r,u){this._richEditBracketsBrand=void 0;const C=y(u);this.brackets=C.map((f,h)=>new E(r,h,f.open,f.close,n(f.open,f.close,C,h),o(f.open,f.close,C,h))),this.forwardRegex=t(this.brackets),this.reversedRegex=i(this.brackets),this.textIsBracket={},this.textIsOpenBracket={},this.maxBracketLength=0;for(const f of this.brackets){for(const h of f.open)this.textIsBracket[h]=f,this.textIsOpenBracket[h]=!0,this.maxBracketLength=Math.max(this.maxBracketLength,h.length);for(const h of f.close)this.textIsBracket[h]=f,this.textIsOpenBracket[h]=!1,this.maxBracketLength=Math.max(this.maxBracketLength,h.length)}}}e.RichEditBrackets=m;function _(a,r,u,C){for(let f=0,h=r.length;f=0&&C.push(w);for(const w of v.close)w.indexOf(a)>=0&&C.push(w)}}function b(a,r){return a.length-r.length}function p(a){if(a.length<=1)return a;const r=[],u=new Set;for(const C of a)u.has(C)||(r.push(C),u.add(C));return r}function n(a,r,u,C){let f=[];f=f.concat(a),f=f.concat(r);for(let h=0,v=f.length;h=0;v--)f[h++]=C.charCodeAt(v);return k.getPlatformTextDecoder().decode(f)}let r=null,u=null;return function(f){return r!==f&&(r=f,u=a(r)),u}}();class l{static _findPrevBracketInText(r,u,C,f){const h=C.match(r);if(!h)return null;const v=C.length-(h.index||0),w=h[0].length,S=f+v;return new I.Range(u,S-w+1,u,S+1)}static findPrevBracketInRange(r,u,C,f,h){const w=c(C).substring(C.length-h,C.length-f);return this._findPrevBracketInText(r,u,w,f)}static findNextBracketInText(r,u,C,f){const h=C.match(r);if(!h)return null;const v=h.index||0,w=h[0].length;if(w===0)return null;const S=f+v;return new I.Range(u,S+1,u,S+1+w)}static findNextBracketInRange(r,u,C,f,h){const v=C.substring(f,h);return this.findNextBracketInText(r,u,v,f)}}e.BracketsUtils=l}),define(ne[659],se([1,0,13,169,208]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BracketElectricCharacterSupport=void 0;class E{constructor(m){this._richEditBrackets=m}getElectricCharacters(){const m=[];if(this._richEditBrackets)for(const _ of this._richEditBrackets.brackets)for(const b of _.close){const p=b.charAt(b.length-1);m.push(p)}return(0,d.distinct)(m)}onElectricCharacter(m,_,b){if(!this._richEditBrackets||this._richEditBrackets.brackets.length===0)return null;const p=_.findTokenIndexAtOffset(b-1);if((0,k.ignoreBracketsInToken)(_.getStandardTokenType(p)))return null;const n=this._richEditBrackets.reversedRegex,o=_.getLineContent().substring(0,b-1)+m,t=I.BracketsUtils.findPrevBracketInRange(n,1,o,0,o.length);if(!t)return null;const i=o.substring(t.startColumn-1,t.endColumn-1).toLowerCase();if(this._richEditBrackets.textIsOpenBracket[i])return null;const g=_.getActualLineContentBefore(t.startColumn-1);return/^\s*$/.test(g)?{matchOpenBracket:i}:null}}e.BracketElectricCharacterSupport=E}),define(ne[660],se([1,0,297,208]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ClosingBracketKind=e.OpeningBracketKind=e.BracketKindBase=e.LanguageBracketsConfiguration=void 0;class I{constructor(p,n){this.languageId=p;const o=n.brackets?E(n.brackets):[],t=new d.CachedFunction(g=>{const c=new Set;return{info:new m(this,g,c),closing:c}}),i=new d.CachedFunction(g=>{const c=new Set,l=new Set;return{info:new _(this,g,c,l),opening:c,openingColorized:l}});for(const[g,c]of o){const l=t.get(g),a=i.get(c);l.closing.add(a.info),a.opening.add(l.info)}const s=n.colorizedBracketPairs?E(n.colorizedBracketPairs):o.filter(g=>!(g[0]==="<"&&g[1]===">"));for(const[g,c]of s){const l=t.get(g),a=i.get(c);l.closing.add(a.info),a.openingColorized.add(l.info),a.opening.add(l.info)}this._openingBrackets=new Map([...t.cachedValues].map(([g,c])=>[g,c.info])),this._closingBrackets=new Map([...i.cachedValues].map(([g,c])=>[g,c.info]))}get openingBrackets(){return[...this._openingBrackets.values()]}get closingBrackets(){return[...this._closingBrackets.values()]}getOpeningBracketInfo(p){return this._openingBrackets.get(p)}getClosingBracketInfo(p){return this._closingBrackets.get(p)}getBracketInfo(p){return this.getOpeningBracketInfo(p)||this.getClosingBracketInfo(p)}getBracketRegExp(p){const n=Array.from([...this._openingBrackets.keys(),...this._closingBrackets.keys()]);return(0,k.createBracketOrRegExp)(n,p)}}e.LanguageBracketsConfiguration=I;function E(b){return b.filter(([p,n])=>p!==""&&n!=="")}class y{constructor(p,n){this.config=p,this.bracketText=n}get languageId(){return this.config.languageId}}e.BracketKindBase=y;class m extends y{constructor(p,n,o){super(p,n),this.openedBrackets=o,this.isOpeningBracket=!0}}e.OpeningBracketKind=m;class _ extends y{constructor(p,n,o,t){super(p,n),this.openingBrackets=o,this.openingColorizedBrackets=t,this.isOpeningBracket=!1}closes(p){return p.config!==this.config?!1:this.openingBrackets.has(p)}closesColorized(p){return p.config!==this.config?!1:this.openingColorizedBrackets.has(p)}getOpeningBrackets(){return[...this.openingBrackets]}}e.ClosingBracketKind=_}),define(ne[369],se([1,0,11,83,27,177]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.tokenizeToString=m,e.tokenizeLineToHTML=_,e._tokenizeToString=b;const y={getInitialState:()=>E.NullState,tokenizeEncoded:(p,n,o)=>(0,E.nullTokenizeEncoded)(0,o)};async function m(p,n,o){if(!o)return b(n,p.languageIdCodec,y);const t=await I.TokenizationRegistry.getOrCreate(o);return b(n,p.languageIdCodec,t||y)}function _(p,n,o,t,i,s,g){let c="
      ",l=t,a=0,r=!0;for(let u=0,C=n.getCount();u0;)g&&r?(h+=" ",r=!1):(h+=" ",r=!0),w--;break}case 60:h+="<",r=!1;break;case 62:h+=">",r=!1;break;case 38:h+="&",r=!1;break;case 0:h+="�",r=!1;break;case 65279:case 8232:case 8233:case 133:h+="\uFFFD",r=!1;break;case 13:h+="​",r=!1;break;case 32:g&&r?(h+=" ",r=!1):(h+=" ",r=!0);break;default:h+=String.fromCharCode(v),r=!1}}if(c+=`${h}`,f>i||l>=i)break}return c+="
      ",c}function b(p,n,o){let t='
      ';const i=d.splitLines(p);let s=o.getInitialState();for(let g=0,c=i.length;g0&&(t+="
      ");const a=o.tokenizeEncoded(l,!0,s);k.LineTokens.convertToEndOffset(a.tokens,l.length);const u=new k.LineTokens(a.tokens,l,n).inflate();let C=0;for(let f=0,h=u.getCount();f${d.escape(l.substring(C,w))}`,C=w}s=a.endState}return t+="
      ",t}}),define(ne[661],se([1,0,13,6,2,4,169,208,584]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BracketPairsTextModelPart=void 0;class b extends I.Disposable{get canBuildAST(){return this.textModel.getValueLength()<=5e6}constructor(s,g){super(),this.textModel=s,this.languageConfigurationService=g,this.bracketPairsTree=this._register(new I.MutableDisposable),this.onDidChangeEmitter=new k.Emitter,this.onDidChange=this.onDidChangeEmitter.event,this.bracketsRequested=!1}handleLanguageConfigurationServiceChange(s){(!s.languageId||this.bracketPairsTree.value?.object.didLanguageChange(s.languageId))&&(this.bracketPairsTree.clear(),this.updateBracketPairsTree())}handleDidChangeOptions(s){this.bracketPairsTree.clear(),this.updateBracketPairsTree()}handleDidChangeLanguage(s){this.bracketPairsTree.clear(),this.updateBracketPairsTree()}handleDidChangeContent(s){this.bracketPairsTree.value?.object.handleContentChanged(s)}handleDidChangeBackgroundTokenizationState(){this.bracketPairsTree.value?.object.handleDidChangeBackgroundTokenizationState()}handleDidChangeTokens(s){this.bracketPairsTree.value?.object.handleDidChangeTokens(s)}updateBracketPairsTree(){if(this.bracketsRequested&&this.canBuildAST){if(!this.bracketPairsTree.value){const s=new I.DisposableStore;this.bracketPairsTree.value=p(s.add(new _.BracketPairsTree(this.textModel,g=>this.languageConfigurationService.getLanguageConfiguration(g))),s),s.add(this.bracketPairsTree.value.object.onDidChange(g=>this.onDidChangeEmitter.fire(g))),this.onDidChangeEmitter.fire()}}else this.bracketPairsTree.value&&(this.bracketPairsTree.clear(),this.onDidChangeEmitter.fire())}getBracketPairsInRange(s){return this.bracketsRequested=!0,this.updateBracketPairsTree(),this.bracketPairsTree.value?.object.getBracketPairsInRange(s,!1)||d.CallbackIterable.empty}getBracketPairsInRangeWithMinIndentation(s){return this.bracketsRequested=!0,this.updateBracketPairsTree(),this.bracketPairsTree.value?.object.getBracketPairsInRange(s,!0)||d.CallbackIterable.empty}getBracketsInRange(s,g=!1){return this.bracketsRequested=!0,this.updateBracketPairsTree(),this.bracketPairsTree.value?.object.getBracketsInRange(s,g)||d.CallbackIterable.empty}findMatchingBracketUp(s,g,c){const l=this.textModel.validatePosition(g),a=this.textModel.getLanguageIdAtPosition(l.lineNumber,l.column);if(this.canBuildAST){const r=this.languageConfigurationService.getLanguageConfiguration(a).bracketsNew.getClosingBracketInfo(s);if(!r)return null;const u=this.getBracketPairsInRange(E.Range.fromPositions(g,g)).findLast(C=>r.closes(C.openingBracketInfo));return u?u.openingBracketRange:null}else{const r=s.toLowerCase(),u=this.languageConfigurationService.getLanguageConfiguration(a).brackets;if(!u)return null;const C=u.textIsBracket[r];return C?t(this._findMatchingBracketUp(C,l,n(c))):null}}matchBracket(s,g){if(this.canBuildAST){const c=this.getBracketPairsInRange(E.Range.fromPositions(s,s)).filter(l=>l.closingBracketRange!==void 0&&(l.openingBracketRange.containsPosition(s)||l.closingBracketRange.containsPosition(s))).findLastMaxBy((0,d.compareBy)(l=>l.openingBracketRange.containsPosition(s)?l.openingBracketRange:l.closingBracketRange,E.Range.compareRangesUsingStarts));return c?[c.openingBracketRange,c.closingBracketRange]:null}else{const c=n(g);return this._matchBracket(this.textModel.validatePosition(s),c)}}_establishBracketSearchOffsets(s,g,c,l){const a=g.getCount(),r=g.getLanguageId(l);let u=Math.max(0,s.column-1-c.maxBracketLength);for(let f=l-1;f>=0;f--){const h=g.getEndOffset(f);if(h<=u)break;if((0,y.ignoreBracketsInToken)(g.getStandardTokenType(f))||g.getLanguageId(f)!==r){u=h;break}}let C=Math.min(g.getLineContent().length,s.column-1+c.maxBracketLength);for(let f=l+1;f=C)break;if((0,y.ignoreBracketsInToken)(g.getStandardTokenType(f))||g.getLanguageId(f)!==r){C=h;break}}return{searchStartOffset:u,searchEndOffset:C}}_matchBracket(s,g){const c=s.lineNumber,l=this.textModel.tokenization.getLineTokens(c),a=this.textModel.getLineContent(c),r=l.findTokenIndexAtOffset(s.column-1);if(r<0)return null;const u=this.languageConfigurationService.getLanguageConfiguration(l.getLanguageId(r)).brackets;if(u&&!(0,y.ignoreBracketsInToken)(l.getStandardTokenType(r))){let{searchStartOffset:C,searchEndOffset:f}=this._establishBracketSearchOffsets(s,l,u,r),h=null;for(;;){const v=m.BracketsUtils.findNextBracketInRange(u.forwardRegex,c,a,C,f);if(!v)break;if(v.startColumn<=s.column&&s.column<=v.endColumn){const w=a.substring(v.startColumn-1,v.endColumn-1).toLowerCase(),S=this._matchFoundBracket(v,u.textIsBracket[w],u.textIsOpenBracket[w],g);if(S){if(S instanceof o)return null;h=S}}C=v.endColumn-1}if(h)return h}if(r>0&&l.getStartOffset(r)===s.column-1){const C=r-1,f=this.languageConfigurationService.getLanguageConfiguration(l.getLanguageId(C)).brackets;if(f&&!(0,y.ignoreBracketsInToken)(l.getStandardTokenType(C))){const{searchStartOffset:h,searchEndOffset:v}=this._establishBracketSearchOffsets(s,l,f,C),w=m.BracketsUtils.findPrevBracketInRange(f.reversedRegex,c,a,h,v);if(w&&w.startColumn<=s.column&&s.column<=w.endColumn){const S=a.substring(w.startColumn-1,w.endColumn-1).toLowerCase(),L=this._matchFoundBracket(w,f.textIsBracket[S],f.textIsOpenBracket[S],g);if(L)return L instanceof o?null:L}}}return null}_matchFoundBracket(s,g,c,l){if(!g)return null;const a=c?this._findMatchingBracketDown(g,s.getEndPosition(),l):this._findMatchingBracketUp(g,s.getStartPosition(),l);return a?a instanceof o?a:[s,a]:null}_findMatchingBracketUp(s,g,c){const l=s.languageId,a=s.reversedRegex;let r=-1,u=0;const C=(f,h,v,w)=>{for(;;){if(c&&++u%100===0&&!c())return o.INSTANCE;const S=m.BracketsUtils.findPrevBracketInRange(a,f,h,v,w);if(!S)break;const L=h.substring(S.startColumn-1,S.endColumn-1).toLowerCase();if(s.isOpen(L)?r++:s.isClose(L)&&r--,r===0)return S;w=S.startColumn-1}return null};for(let f=g.lineNumber;f>=1;f--){const h=this.textModel.tokenization.getLineTokens(f),v=h.getCount(),w=this.textModel.getLineContent(f);let S=v-1,L=w.length,D=w.length;f===g.lineNumber&&(S=h.findTokenIndexAtOffset(g.column-1),L=g.column-1,D=g.column-1);let T=!0;for(;S>=0;S--){const M=h.getLanguageId(S)===l&&!(0,y.ignoreBracketsInToken)(h.getStandardTokenType(S));if(M)T?L=h.getStartOffset(S):(L=h.getStartOffset(S),D=h.getEndOffset(S));else if(T&&L!==D){const A=C(f,w,L,D);if(A)return A}T=M}if(T&&L!==D){const M=C(f,w,L,D);if(M)return M}}return null}_findMatchingBracketDown(s,g,c){const l=s.languageId,a=s.forwardRegex;let r=1,u=0;const C=(h,v,w,S)=>{for(;;){if(c&&++u%100===0&&!c())return o.INSTANCE;const L=m.BracketsUtils.findNextBracketInRange(a,h,v,w,S);if(!L)break;const D=v.substring(L.startColumn-1,L.endColumn-1).toLowerCase();if(s.isOpen(D)?r++:s.isClose(D)&&r--,r===0)return L;w=L.endColumn-1}return null},f=this.textModel.getLineCount();for(let h=g.lineNumber;h<=f;h++){const v=this.textModel.tokenization.getLineTokens(h),w=v.getCount(),S=this.textModel.getLineContent(h);let L=0,D=0,T=0;h===g.lineNumber&&(L=v.findTokenIndexAtOffset(g.column-1),D=g.column-1,T=g.column-1);let M=!0;for(;L=1;r--){const u=this.textModel.tokenization.getLineTokens(r),C=u.getCount(),f=this.textModel.getLineContent(r);let h=C-1,v=f.length,w=f.length;if(r===g.lineNumber){h=u.findTokenIndexAtOffset(g.column-1),v=g.column-1,w=g.column-1;const L=u.getLanguageId(h);c!==L&&(c=L,l=this.languageConfigurationService.getLanguageConfiguration(c).brackets,a=this.languageConfigurationService.getLanguageConfiguration(c).bracketsNew)}let S=!0;for(;h>=0;h--){const L=u.getLanguageId(h);if(c!==L){if(l&&a&&S&&v!==w){const T=m.BracketsUtils.findPrevBracketInRange(l.reversedRegex,r,f,v,w);if(T)return this._toFoundBracket(a,T);S=!1}c=L,l=this.languageConfigurationService.getLanguageConfiguration(c).brackets,a=this.languageConfigurationService.getLanguageConfiguration(c).bracketsNew}const D=!!l&&!(0,y.ignoreBracketsInToken)(u.getStandardTokenType(h));if(D)S?v=u.getStartOffset(h):(v=u.getStartOffset(h),w=u.getEndOffset(h));else if(a&&l&&S&&v!==w){const T=m.BracketsUtils.findPrevBracketInRange(l.reversedRegex,r,f,v,w);if(T)return this._toFoundBracket(a,T)}S=D}if(a&&l&&S&&v!==w){const L=m.BracketsUtils.findPrevBracketInRange(l.reversedRegex,r,f,v,w);if(L)return this._toFoundBracket(a,L)}}return null}findNextBracket(s){const g=this.textModel.validatePosition(s);if(this.canBuildAST)return this.bracketsRequested=!0,this.updateBracketPairsTree(),this.bracketPairsTree.value?.object.getFirstBracketAfter(g)||null;const c=this.textModel.getLineCount();let l=null,a=null,r=null;for(let u=g.lineNumber;u<=c;u++){const C=this.textModel.tokenization.getLineTokens(u),f=C.getCount(),h=this.textModel.getLineContent(u);let v=0,w=0,S=0;if(u===g.lineNumber){v=C.findTokenIndexAtOffset(g.column-1),w=g.column-1,S=g.column-1;const D=C.getLanguageId(v);l!==D&&(l=D,a=this.languageConfigurationService.getLanguageConfiguration(l).brackets,r=this.languageConfigurationService.getLanguageConfiguration(l).bracketsNew)}let L=!0;for(;vD.closingBracketRange!==void 0&&D.range.strictContainsRange(S));return L?[L.openingBracketRange,L.closingBracketRange]:null}const l=n(g),a=this.textModel.getLineCount(),r=new Map;let u=[];const C=(S,L)=>{if(!r.has(S)){const D=[];for(let T=0,M=L?L.brackets.length:0;T{for(;;){if(l&&++f%100===0&&!l())return o.INSTANCE;const A=m.BracketsUtils.findNextBracketInRange(S.forwardRegex,L,D,T,M);if(!A)break;const P=D.substring(A.startColumn-1,A.endColumn-1).toLowerCase(),N=S.textIsBracket[P];if(N&&(N.isOpen(P)?u[N.index]++:N.isClose(P)&&u[N.index]--,u[N.index]===-1))return this._matchFoundBracket(A,N,!1,l);T=A.endColumn-1}return null};let v=null,w=null;for(let S=c.lineNumber;S<=a;S++){const L=this.textModel.tokenization.getLineTokens(S),D=L.getCount(),T=this.textModel.getLineContent(S);let M=0,A=0,P=0;if(S===c.lineNumber){M=L.findTokenIndexAtOffset(c.column-1),A=c.column-1,P=c.column-1;const O=L.getLanguageId(M);v!==O&&(v=O,w=this.languageConfigurationService.getLanguageConfiguration(v).brackets,C(v,w))}let N=!0;for(;Ms?.dispose()}}function n(i){if(typeof i>"u")return()=>!0;{const s=Date.now();return()=>Date.now()-s<=i}}class o{static{this.INSTANCE=new o}constructor(){this._searchCanceledBrand=void 0}}function t(i){return i instanceof o?null:i}}),define(ne[370],se([1,0,3,8,23,22,367,160,48]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditStack=e.MultiModelEditStackElement=e.SingleModelEditStackElement=e.SingleModelEditStackData=void 0,e.isEditStackElement=i;function b(g){return g.toString()}class p{static create(c,l){const a=c.getAlternativeVersionId(),r=t(c);return new p(a,a,r,r,l,l,[])}constructor(c,l,a,r,u,C,f){this.beforeVersionId=c,this.afterVersionId=l,this.beforeEOL=a,this.afterEOL=r,this.beforeCursorState=u,this.afterCursorState=C,this.changes=f}append(c,l,a,r,u){l.length>0&&(this.changes=(0,y.compressConsecutiveTextChanges)(this.changes,l)),this.afterEOL=a,this.afterVersionId=r,this.afterCursorState=u}static _writeSelectionsSize(c){return 4+4*4*(c?c.length:0)}static _writeSelections(c,l,a){if(m.writeUInt32BE(c,l?l.length:0,a),a+=4,l)for(const r of l)m.writeUInt32BE(c,r.selectionStartLineNumber,a),a+=4,m.writeUInt32BE(c,r.selectionStartColumn,a),a+=4,m.writeUInt32BE(c,r.positionLineNumber,a),a+=4,m.writeUInt32BE(c,r.positionColumn,a),a+=4;return a}static _readSelections(c,l,a){const r=m.readUInt32BE(c,l);l+=4;for(let u=0;ul.toString()).join(", ")}matchesResource(c){return(E.URI.isUri(this.model)?this.model:this.model.uri).toString()===c.toString()}setModel(c){this.model=c}canAppend(c){return this.model===c&&this._data instanceof p}append(c,l,a,r,u){this._data instanceof p&&this._data.append(c,l,a,r,u)}close(){this._data instanceof p&&(this._data=this._data.serialize())}open(){this._data instanceof p||(this._data=p.deserialize(this._data))}undo(){if(E.URI.isUri(this.model))throw new Error("Invalid SingleModelEditStackElement");this._data instanceof p&&(this._data=this._data.serialize());const c=p.deserialize(this._data);this.model._applyUndo(c.changes,c.beforeEOL,c.beforeVersionId,c.beforeCursorState)}redo(){if(E.URI.isUri(this.model))throw new Error("Invalid SingleModelEditStackElement");this._data instanceof p&&(this._data=this._data.serialize());const c=p.deserialize(this._data);this.model._applyRedo(c.changes,c.afterEOL,c.afterVersionId,c.afterCursorState)}heapSize(){return this._data instanceof p&&(this._data=this._data.serialize()),this._data.byteLength+168}}e.SingleModelEditStackElement=n;class o{get resources(){return this._editStackElementsArr.map(c=>c.resource)}constructor(c,l,a){this.label=c,this.code=l,this.type=1,this._isOpen=!0,this._editStackElementsArr=a.slice(0),this._editStackElementsMap=new Map;for(const r of this._editStackElementsArr){const u=b(r.resource);this._editStackElementsMap.set(u,r)}this._delegate=null}prepareUndoRedo(){if(this._delegate)return this._delegate.prepareUndoRedo(this)}matchesResource(c){const l=b(c);return this._editStackElementsMap.has(l)}setModel(c){const l=b(E.URI.isUri(c)?c:c.uri);this._editStackElementsMap.has(l)&&this._editStackElementsMap.get(l).setModel(c)}canAppend(c){if(!this._isOpen)return!1;const l=b(c.uri);return this._editStackElementsMap.has(l)?this._editStackElementsMap.get(l).canAppend(c):!1}append(c,l,a,r,u){const C=b(c.uri);this._editStackElementsMap.get(C).append(c,l,a,r,u)}close(){this._isOpen=!1}open(){}undo(){this._isOpen=!1;for(const c of this._editStackElementsArr)c.undo()}redo(){for(const c of this._editStackElementsArr)c.redo()}heapSize(c){const l=b(c);return this._editStackElementsMap.has(l)?this._editStackElementsMap.get(l).heapSize():0}split(){return this._editStackElementsArr}toString(){const c=[];for(const l of this._editStackElementsArr)c.push(`${(0,_.basename)(l.resource)}: ${l}`);return`{${c.join(", ")}}`}}e.MultiModelEditStackElement=o;function t(g){return g.getEOL()===` `?0:1}function i(g){return g?g instanceof n||g instanceof o:!1}class s{constructor(c,l){this._model=c,this._undoRedoService=l}pushStackElement(){const c=this._undoRedoService.getLastElement(this._model.uri);i(c)&&c.close()}popStackElement(){const c=this._undoRedoService.getLastElement(this._model.uri);i(c)&&c.open()}clear(){this._undoRedoService.removeElements(this._model.uri)}_getOrCreateEditStackElement(c,l){const a=this._undoRedoService.getLastElement(this._model.uri);if(i(a)&&a.canAppend(this._model))return a;const r=new n(d.localize(697,"Typing"),"undoredo.textBufferEdit",this._model,c);return this._undoRedoService.pushElement(r,l),r}pushEOL(c){const l=this._getOrCreateEditStackElement(null,void 0);this._model.setEOL(c),l.append(this._model,[],t(this._model),this._model.getAlternativeVersionId(),null)}pushEditOperation(c,l,a,r){const u=this._getOrCreateEditStackElement(c,r),C=this._model.applyEdits(l,!0),f=s._computeCursorState(a,C),h=C.map((v,w)=>({index:w,textChange:v.textChange}));return h.sort((v,w)=>v.textChange.oldPosition===w.textChange.oldPosition?v.index-w.index:v.textChange.oldPosition-w.textChange.oldPosition),u.append(this._model,h.map(v=>v.textChange),t(this._model),this._model.getAlternativeVersionId(),f),f}static _computeCursorState(c,l){try{return c?c(l):null}catch(a){return(0,k.onUnexpectedError)(a),null}}}e.EditStack=s}),define(ne[371],se([1,0,6,11,4,40,324,145,367,2]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PieceTreeTextBuffer=void 0;class p extends b.Disposable{constructor(o,t,i,s,g,c,l){super(),this._onDidChangeContent=this._register(new d.Emitter),this._BOM=t,this._mightContainNonBasicASCII=!c,this._mightContainRTL=s,this._mightContainUnusualLineTerminators=g,this._pieceTree=new y.PieceTreeBase(o,i,l)}mightContainRTL(){return this._mightContainRTL}mightContainUnusualLineTerminators(){return this._mightContainUnusualLineTerminators}resetMightContainUnusualLineTerminators(){this._mightContainUnusualLineTerminators=!1}mightContainNonBasicASCII(){return this._mightContainNonBasicASCII}getBOM(){return this._BOM}getEOL(){return this._pieceTree.getEOL()}createSnapshot(o){return this._pieceTree.createSnapshot(o?this._BOM:"")}getOffsetAt(o,t){return this._pieceTree.getOffsetAt(o,t)}getPositionAt(o){return this._pieceTree.getPositionAt(o)}getRangeAt(o,t){const i=o+t,s=this.getPositionAt(o),g=this.getPositionAt(i);return new I.Range(s.lineNumber,s.column,g.lineNumber,g.column)}getValueInRange(o,t=0){if(o.isEmpty())return"";const i=this._getEndOfLine(t);return this._pieceTree.getValueInRange(o,i)}getValueLengthInRange(o,t=0){if(o.isEmpty())return 0;if(o.startLineNumber===o.endLineNumber)return o.endColumn-o.startColumn;const i=this.getOffsetAt(o.startLineNumber,o.startColumn),s=this.getOffsetAt(o.endLineNumber,o.endColumn);let g=0;const c=this._getEndOfLine(t),l=this.getEOL();if(c.length!==l.length){const a=c.length-l.length,r=o.endLineNumber-o.startLineNumber;g=a*r}return s-i+g}getCharacterCountInRange(o,t=0){if(this._mightContainNonBasicASCII){let i=0;const s=o.startLineNumber,g=o.endLineNumber;for(let c=s;c<=g;c++){const l=this.getLineContent(c),a=c===s?o.startColumn-1:0,r=c===g?o.endColumn-1:l.length;for(let u=a;uS.sortIndex-L.sortIndex)}this._mightContainRTL=s,this._mightContainUnusualLineTerminators=g,this._mightContainNonBasicASCII=c;const h=this._doApplyEdits(a);let v=null;if(t&&C.length>0){C.sort((w,S)=>S.lineNumber-w.lineNumber),v=[];for(let w=0,S=C.length;w0&&C[w-1].lineNumber===L)continue;const D=C[w].oldContent,T=this.getLineContent(L);T.length===0||T===D||k.firstNonWhitespaceIndex(T)!==-1||v.push(L)}}return this._onDidChangeContent.fire(),new E.ApplyEditsResult(f,h,v)}_reduceOperations(o){return o.length<1e3?o:[this._toSingleEditOperation(o)]}_toSingleEditOperation(o){let t=!1;const i=o[0].range,s=o[o.length-1].range,g=new I.Range(i.startLineNumber,i.startColumn,s.endLineNumber,s.endColumn);let c=i.startLineNumber,l=i.startColumn;const a=[];for(let h=0,v=o.length;h0&&a.push(w.text),c=S.endLineNumber,l=S.endColumn}const r=a.join(""),[u,C,f]=(0,m.countEOL)(r);return{sortIndex:0,identifier:o[0].identifier,range:g,rangeOffset:this.getOffsetAt(g.startLineNumber,g.startColumn),rangeLength:this.getValueLengthInRange(g,0),text:r,eolCount:u,firstLineLength:C,lastLineLength:f,forceMoveMarkers:t,isAutoWhitespaceEdit:!1}}_doApplyEdits(o){o.sort(p._sortOpsDescending);const t=[];for(let i=0;i0){const f=a.eolCount+1;f===1?C=new I.Range(r,u,r,u+a.firstLineLength):C=new I.Range(r,u,r+f-1,a.lastLineLength+1)}else C=new I.Range(r,u,r,u);i=C.endLineNumber,s=C.endColumn,t.push(C),g=a}return t}static _sortOpsAscending(o,t){const i=I.Range.compareRangesUsingEnds(o.range,t.range);return i===0?o.sortIndex-t.sortIndex:i}static _sortOpsDescending(o,t){const i=I.Range.compareRangesUsingEnds(o.range,t.range);return i===0?t.sortIndex-o.sortIndex:-i}}e.PieceTreeTextBuffer=p}),define(ne[662],se([1,0,11,324,371]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PieceTreeTextBufferBuilder=void 0;class E{constructor(_,b,p,n,o,t,i,s,g){this._chunks=_,this._bom=b,this._cr=p,this._lf=n,this._crlf=o,this._containsRTL=t,this._containsUnusualLineTerminators=i,this._isBasicASCII=s,this._normalizeEOL=g}_getEOL(_){const b=this._cr+this._lf+this._crlf,p=this._cr+this._crlf;return b===0?_===1?` `:`\r `:p>b/2?`\r `:` `}create(_){const b=this._getEOL(_),p=this._chunks;if(this._normalizeEOL&&(b===`\r `&&(this._cr>0||this._lf>0)||b===` `&&(this._cr>0||this._crlf>0)))for(let o=0,t=p.length;o=55296&&b<=56319?(this._acceptChunk1(_.substr(0,_.length-1),!1),this._hasPreviousChar=!0,this._previousChar=b):(this._acceptChunk1(_,!1),this._hasPreviousChar=!1,this._previousChar=b)}_acceptChunk1(_,b){!b&&_.length===0||(this._hasPreviousChar?this._acceptChunk2(String.fromCharCode(this._previousChar)+_):this._acceptChunk2(_))}_acceptChunk2(_){const b=(0,k.createLineStarts)(this._tmpLineStarts,_);this.chunks.push(new k.StringBuffer(_,b.lineStarts)),this.cr+=b.cr,this.lf+=b.lf,this.crlf+=b.crlf,b.isBasicASCII||(this.isBasicASCII=!1,this.containsRTL||(this.containsRTL=d.containsRTL(_)),this.containsUnusualLineTerminators||(this.containsUnusualLineTerminators=d.containsUnusualLineTerminators(_)))}finish(_=!0){return this._finish(),new E(this.chunks,this.BOM,this.cr,this.lf,this.crlf,this.containsRTL,this.containsUnusualLineTerminators,this.isBasicASCII,_)}_finish(){if(this.chunks.length===0&&this._acceptChunk1("",!0),this._hasPreviousChar){this._hasPreviousChar=!1;const _=this.chunks[this.chunks.length-1];_.buffer+=String.fromCharCode(this._previousChar);const b=(0,k.createLineStartsFast)(_.buffer);_.lineStarts=b,this._previousChar===13&&this.cr++}}}e.PieceTreeTextBufferBuilder=y}),define(ne[663],se([1,0,14,8,16,54,145,55,68,177,576,330,83]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DefaultBackgroundTokenizer=e.RangePriorityQueueImpl=e.TokenizationStateStore=e.TrackingTokenizationStateStore=e.TokenizerWithStateStoreAndTextModel=e.TokenizerWithStateStore=void 0;class t{constructor(u,C){this.tokenizationSupport=C,this.initialState=this.tokenizationSupport.getInitialState(),this.store=new s(u)}getStartState(u){return this.store.getStartState(u,this.initialState)}getFirstInvalidLine(){return this.store.getFirstInvalidLine(this.initialState)}}e.TokenizerWithStateStore=t;class i extends t{constructor(u,C,f,h){super(u,C),this._textModel=f,this._languageIdCodec=h}updateTokensUntilLine(u,C){const f=this._textModel.getLanguageId();for(;;){const h=this.getFirstInvalidLine();if(!h||h.lineNumber>C)break;const v=this._textModel.getLineContent(h.lineNumber),w=l(this._languageIdCodec,f,this.tokenizationSupport,v,!0,h.startState);u.add(h.lineNumber,w.tokens),this.store.setEndState(h.lineNumber,w.endState)}}getTokenTypeIfInsertingCharacter(u,C){const f=this.getStartState(u.lineNumber);if(!f)return 0;const h=this._textModel.getLanguageId(),v=this._textModel.getLineContent(u.lineNumber),w=v.substring(0,u.column-1)+C+v.substring(u.column-1),S=l(this._languageIdCodec,h,this.tokenizationSupport,w,!0,f),L=new o.LineTokens(S.tokens,w,this._languageIdCodec);if(L.getCount()===0)return 0;const D=L.findTokenIndexAtOffset(u.column-1);return L.getStandardTokenType(D)}tokenizeLineWithEdit(u,C,f){const h=u.lineNumber,v=u.column,w=this.getStartState(h);if(!w)return null;const S=this._textModel.getLineContent(h),L=S.substring(0,v-1)+f+S.substring(v-1+C),D=this._textModel.getLanguageIdAtPosition(h,0),T=l(this._languageIdCodec,D,this.tokenizationSupport,L,!0,w);return new o.LineTokens(T.tokens,L,this._languageIdCodec)}hasAccurateTokensForLine(u){const C=this.store.getFirstInvalidEndStateLineNumberOrMax();return u1&&S>=1;S--){const L=this._textModel.getLineFirstNonWhitespaceColumn(S);if(L!==0&&L0&&f>0&&(f--,C--),this._lineEndStates.replace(u.startLineNumber,f,C)}}e.TokenizationStateStore=g;class c{constructor(){this._ranges=[]}get min(){return this._ranges.length===0?null:this._ranges[0].start}delete(u){const C=this._ranges.findIndex(f=>f.contains(u));if(C!==-1){const f=this._ranges[C];f.start===u?f.endExclusive===u+1?this._ranges.splice(C,1):this._ranges[C]=new _.OffsetRange(u+1,f.endExclusive):f.endExclusive===u+1?this._ranges[C]=new _.OffsetRange(f.start,u):this._ranges.splice(C,1,new _.OffsetRange(f.start,u),new _.OffsetRange(u+1,f.endExclusive))}}addRange(u){_.OffsetRange.addRange(u,this._ranges)}addRangeAndResize(u,C){let f=0;for(;!(f>=this._ranges.length||u.start<=this._ranges[f].endExclusive);)f++;let h=f;for(;!(h>=this._ranges.length||u.endExclusiveu.toString()).join(" + ")}}e.RangePriorityQueueImpl=c;function l(r,u,C,f,h,v){let w=null;if(C)try{w=C.tokenizeEncoded(f,h,v.clone())}catch(S){(0,k.onUnexpectedError)(S)}return w||(w=(0,b.nullTokenizeEncoded)(r.encodeLanguageId(u),v)),o.LineTokens.convertToEndOffset(w.tokens,f.length),w}class a{constructor(u,C){this._tokenizerWithStateStore=u,this._backgroundTokenStore=C,this._isDisposed=!1,this._isScheduled=!1}dispose(){this._isDisposed=!0}handleChanges(){this._beginBackgroundTokenization()}_beginBackgroundTokenization(){this._isScheduled||!this._tokenizerWithStateStore._textModel.isAttachedToEditor()||!this._hasLinesToTokenize()||(this._isScheduled=!0,(0,d.runWhenGlobalIdle)(u=>{this._isScheduled=!1,this._backgroundTokenizeWithDeadline(u)}))}_backgroundTokenizeWithDeadline(u){const C=Date.now()+u.timeRemaining(),f=()=>{this._isDisposed||!this._tokenizerWithStateStore._textModel.isAttachedToEditor()||!this._hasLinesToTokenize()||(this._backgroundTokenizeForAtLeast1ms(),Date.now()1||this._tokenizeOneInvalidLine(C)>=u)break;while(this._hasLinesToTokenize());this._backgroundTokenStore.setTokens(C.finalize()),this.checkFinished()}_hasLinesToTokenize(){return this._tokenizerWithStateStore?!this._tokenizerWithStateStore.store.allStatesValid():!1}_tokenizeOneInvalidLine(u){const C=this._tokenizerWithStateStore?.getFirstInvalidLine();return C?(this._tokenizerWithStateStore.updateTokensUntilLine(u,C.lineNumber),C.lineNumber):this._tokenizerWithStateStore._textModel.getLineCount()+1}checkFinished(){this._isDisposed||this._tokenizerWithStateStore.store.allStatesValid()&&this._backgroundTokenStore.backgroundTokenizationFinished()}requestTokens(u,C){this._tokenizerWithStateStore.store.invalidateEndStateRange(new m.LineRange(u,C))}}e.DefaultBackgroundTokenizer=a}),define(ne[263],se([1,0,13,14,6,2,55]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractTokens=e.AttachedViewHandler=e.AttachedViews=void 0;class m{constructor(){this._onDidChangeVisibleRanges=new I.Emitter,this.onDidChangeVisibleRanges=this._onDidChangeVisibleRanges.event,this._views=new Set}attachView(){const o=new _(t=>{this._onDidChangeVisibleRanges.fire({view:o,state:t})});return this._views.add(o),o}detachView(o){this._views.delete(o),this._onDidChangeVisibleRanges.fire({view:o,state:void 0})}}e.AttachedViews=m;class _{constructor(o){this.handleStateChange=o}setVisibleLines(o,t){const i=o.map(s=>new y.LineRange(s.startLineNumber,s.endLineNumber+1));this.handleStateChange({visibleLineRanges:i,stabilized:t})}}class b extends E.Disposable{get lineRanges(){return this._lineRanges}constructor(o){super(),this._refreshTokens=o,this.runner=this._register(new k.RunOnceScheduler(()=>this.update(),50)),this._computedLineRanges=[],this._lineRanges=[]}update(){(0,d.equals)(this._computedLineRanges,this._lineRanges,(o,t)=>o.equals(t))||(this._computedLineRanges=this._lineRanges,this._refreshTokens())}handleStateChange(o){this._lineRanges=o.visibleLineRanges,o.stabilized?(this.runner.cancel(),this.update()):this.runner.schedule()}}e.AttachedViewHandler=b;class p extends E.Disposable{get backgroundTokenizationState(){return this._backgroundTokenizationState}constructor(o,t,i){super(),this._languageIdCodec=o,this._textModel=t,this.getLanguageId=i,this._backgroundTokenizationState=1,this._onDidChangeBackgroundTokenizationState=this._register(new I.Emitter),this.onDidChangeBackgroundTokenizationState=this._onDidChangeBackgroundTokenizationState.event,this._onDidChangeTokens=this._register(new I.Emitter),this.onDidChangeTokens=this._onDidChangeTokens.event}tokenizeIfCheap(o){this.isCheapToTokenize(o)&&this.forceTokenization(o)}}e.AbstractTokens=p}),define(ne[664],se([1,0,27,83,263]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TreeSitterTokens=void 0;class E extends I.AbstractTokens{constructor(m,_,b,p){super(_,b,p),this._treeSitterService=m,this._tokenizationSupport=null,this._initialize()}_initialize(){const m=this.getLanguageId();(!this._tokenizationSupport||this._lastLanguageId!==m)&&(this._lastLanguageId=m,this._tokenizationSupport=d.TreeSitterTokenizationRegistry.get(m))}getLineTokens(m){const _=this._textModel.getLineContent(m);if(this._tokenizationSupport){const b=this._tokenizationSupport.tokenizeEncoded(m,this._textModel);if(b)return new k.LineTokens(b,_,this._languageIdCodec)}return k.LineTokens.createEmpty(_,this._languageIdCodec)}resetTokenization(m=!0){m&&this._onDidChangeTokens.fire({semanticTokensApplied:!1,ranges:[{fromLineNumber:1,toLineNumber:this._textModel.getLineCount()}]}),this._initialize()}handleDidChangeAttached(){}handleDidChangeContent(m){m.isFlush&&this.resetTokenization(!1)}forceTokenization(m){}hasAccurateTokensForLine(m){return!0}isCheapToTokenize(m){return!0}getTokenTypeIfInsertingCharacter(m,_,b){return 0}tokenizeLineWithEdit(m,_,b){return null}get hasTokens(){return this._treeSitterService.getParseResult(this._textModel)!==void 0}}e.TreeSitterTokens=E}),define(ne[372],se([1,0,18,6,72,22,9,4,23,27,238]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.KeyMod=void 0,e.createMonacoBaseAPI=o;class n{static{this.CtrlCmd=2048}static{this.Shift=1024}static{this.Alt=512}static{this.WinCtrl=256}static chord(i,s){return(0,I.KeyChord)(i,s)}}e.KeyMod=n;function o(){return{editor:void 0,languages:void 0,CancellationTokenSource:d.CancellationTokenSource,Emitter:k.Emitter,KeyCode:p.KeyCode,KeyMod:n,Position:y.Position,Range:m.Range,Selection:_.Selection,SelectionDirection:p.SelectionDirection,MarkerSeverity:p.MarkerSeverity,MarkerTag:p.MarkerTag,Uri:E.URI,Token:b.Token}}}),define(ne[665],se([1,0,160,16]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.encodeSemanticTokensDto=y;function I(_){for(let b=0,p=_.length;bthis._checkStopModelSync(),Math.round(e.STOP_SYNC_MODEL_DELTA_TIME_MS/2)),this._register(g)}}dispose(){for(const t in this._syncedModels)(0,k.dispose)(this._syncedModels[t]);this._syncedModels=Object.create(null),this._syncedModelsLastUsedTime=Object.create(null),super.dispose()}ensureSyncedResources(t,i=!1){for(const s of t){const g=s.toString();this._syncedModels[g]||this._beginModelSync(s,i),this._syncedModels[g]&&(this._syncedModelsLastUsedTime[g]=new Date().getTime())}}_checkStopModelSync(){const t=new Date().getTime(),i=[];for(const s in this._syncedModelsLastUsedTime)t-this._syncedModelsLastUsedTime[s]>e.STOP_SYNC_MODEL_DELTA_TIME_MS&&i.push(s);for(const s of i)this._stopModelSync(s)}_beginModelSync(t,i){const s=this._modelService.getModel(t);if(!s||!i&&s.isTooLargeForSyncing())return;const g=t.toString();this._proxy.$acceptNewModel({url:s.uri.toString(),lines:s.getLinesContent(),EOL:s.getEOL(),versionId:s.getVersionId()});const c=new k.DisposableStore;c.add(s.onDidChangeContent(l=>{this._proxy.$acceptModelChanged(g.toString(),l)})),c.add(s.onWillDispose(()=>{this._stopModelSync(g)})),c.add((0,k.toDisposable)(()=>{this._proxy.$acceptRemovedModel(g)})),this._syncedModels[g]=c}_stopModelSync(t){const i=this._syncedModels[t];delete this._syncedModels[t],delete this._syncedModelsLastUsedTime[t],(0,k.dispose)(i)}}e.WorkerTextModelSyncClient=b;class p{constructor(){this._models=Object.create(null)}getModel(t){return this._models[t]}getModels(){const t=[];return Object.keys(this._models).forEach(i=>t.push(this._models[i])),t}$acceptNewModel(t){this._models[t.url]=new n(I.URI.parse(t.url),t.lines,t.EOL,t.versionId)}$acceptModelChanged(t,i){if(!this._models[t])return;this._models[t].onEvents(i)}$acceptRemovedModel(t){this._models[t]&&delete this._models[t]}}e.WorkerTextModelSyncServer=p;class n extends _.MirrorTextModel{get uri(){return this._uri}get eol(){return this._eol}getValue(){return this.getText()}findMatches(t){const i=[];for(let s=0;sthis._lines.length)i=this._lines.length,s=this._lines[i-1].length+1,g=!0;else{const c=this._lines[i-1].length+1;s<1?(s=1,g=!0):s>c&&(s=c,g=!0)}return g?{lineNumber:i,column:s}:t}}e.MirrorModel=n}),define(ne[666],se([1,0,190,4,564,570,372,326,54,328,561,60,42,563,582,373]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorSimpleWorker=e.BaseEditorSimpleWorker=void 0,e.create=a;const g=!1;class c{constructor(){this._workerTextModelSyncServer=new s.WorkerTextModelSyncServer}dispose(){}_getModel(u){return this._workerTextModelSyncServer.getModel(u)}_getModels(){return this._workerTextModelSyncServer.getModels()}$acceptNewModel(u){this._workerTextModelSyncServer.$acceptNewModel(u)}$acceptModelChanged(u,C){this._workerTextModelSyncServer.$acceptModelChanged(u,C)}$acceptRemovedModel(u){this._workerTextModelSyncServer.$acceptRemovedModel(u)}async $computeUnicodeHighlights(u,C,f){const h=this._getModel(u);return h?b.UnicodeTextModelHighlighter.computeUnicodeHighlights(h,C,f):{ranges:[],hasMore:!1,ambiguousCharacterCount:0,invisibleCharacterCount:0,nonBasicAsciiCharacterCount:0}}async $findSectionHeaders(u,C){const f=this._getModel(u);return f?(0,i.findSectionHeaders)(f,C):[]}async $computeDiff(u,C,f,h){const v=this._getModel(u),w=this._getModel(C);return!v||!w?null:l.computeDiff(v,w,f,h)}static computeDiff(u,C,f,h){const v=h==="advanced"?p.linesDiffComputers.getDefault():p.linesDiffComputers.getLegacy(),w=u.getLinesContent(),S=C.getLinesContent(),L=v.computeDiff(w,S,f),D=L.changes.length>0?!1:this._modelsAreIdentical(u,C);function T(M){return M.map(A=>[A.original.startLineNumber,A.original.endLineNumberExclusive,A.modified.startLineNumber,A.modified.endLineNumberExclusive,A.innerChanges?.map(P=>[P.originalRange.startLineNumber,P.originalRange.startColumn,P.originalRange.endLineNumber,P.originalRange.endColumn,P.modifiedRange.startLineNumber,P.modifiedRange.startColumn,P.modifiedRange.endLineNumber,P.modifiedRange.endColumn])])}return{identical:D,quitEarly:L.hitTimeout,changes:T(L.changes),moves:L.moves.map(M=>[M.lineRangeMapping.original.startLineNumber,M.lineRangeMapping.original.endLineNumberExclusive,M.lineRangeMapping.modified.startLineNumber,M.lineRangeMapping.modified.endLineNumberExclusive,T(M.changes)])}}static _modelsAreIdentical(u,C){const f=u.getLineCount(),h=C.getLineCount();if(f!==h)return!1;for(let v=1;v<=f;v++){const w=u.getLineContent(v),S=C.getLineContent(v);if(w!==S)return!1}return!0}static{this._diffLimit=1e5}async $computeMoreMinimalEdits(u,C,f){const h=this._getModel(u);if(!h)return C;const v=[];let w;C=C.slice(0).sort((L,D)=>{if(L.range&&D.range)return k.Range.compareRangesUsingStarts(L.range,D.range);const T=L.range?0:1,M=D.range?0:1;return T-M});let S=0;for(let L=1;Ll._diffLimit){v.push({range:L,text:D});continue}const A=(0,d.stringDiff)(M,D,f),P=h.offsetAt(k.Range.lift(L).getStartPosition());for(const N of A){const O=h.positionAt(P+N.originalStart),F=h.positionAt(P+N.originalStart+N.originalLength),x={text:D.substr(N.modifiedStart,N.modifiedLength),range:{startLineNumber:O.lineNumber,startColumn:O.column,endLineNumber:F.lineNumber,endColumn:F.column}};h.getValueInRange(x.range)!==x.text&&v.push(x)}}return typeof w=="number"&&v.push({eol:w,text:"",range:{startLineNumber:0,startColumn:0,endLineNumber:0,endColumn:0}}),v}async $computeLinks(u){const C=this._getModel(u);return C?(0,I.computeLinks)(C):null}async $computeDefaultDocumentColors(u){const C=this._getModel(u);return C?(0,t.computeDefaultDocumentColors)(C):null}static{this._suggestionsLimit=1e4}async $textualSuggest(u,C,f,h){const v=new _.StopWatch,w=new RegExp(f,h),S=new Set;e:for(const L of u){const D=this._getModel(L);if(D){for(const T of D.words(w))if(!(T===C||!isNaN(Number(T)))&&(S.add(T),S.size>l._suggestionsLimit))break e}}return{words:Array.from(S),duration:v.elapsed()}}async $computeWordRanges(u,C,f,h){const v=this._getModel(u);if(!v)return Object.create(null);const w=new RegExp(f,h),S=Object.create(null);for(let L=C.startLineNumber;Lthis._host.$fhr(S,L),w={host:(0,n.createProxyObject)(f,h),getMirrorModels:()=>this._getModels()};return this._foreignModuleFactory?(this._foreignModule=this._foreignModuleFactory(w,C),Promise.resolve((0,n.getAllMethodNames)(this._foreignModule))):new Promise((S,L)=>{const D=T=>{this._foreignModule=T.create(w,C),S((0,n.getAllMethodNames)(this._foreignModule))};if(!g)oe([`${u}`],D,L);else{const T=o.FileAccess.asBrowserUri(`${u}.js`).toString(!0);new Promise((M,A)=>{oe([`${T}`],M,A)}).then(D).catch(L)}})}$fmr(u,C){if(!this._foreignModule||typeof this._foreignModule[u]!="function")return Promise.reject(new Error("Missing requestHandler or method: "+u));try{return Promise.resolve(this._foreignModule[u].apply(this._foreignModule,C))}catch(f){return Promise.reject(f)}}}e.EditorSimpleWorker=l;function a(r){return new l(m.EditorWorkerHost.getChannel(r),null)}typeof importScripts=="function"&&(globalThis.monaco=(0,y.createMonacoBaseAPI)())}),define(ne[107],se([1,0,3]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneServicesNLS=e.ToggleHighContrastNLS=e.StandaloneCodeEditorNLS=e.QuickOutlineNLS=e.QuickCommandNLS=e.QuickHelpNLS=e.GoToLineNLS=e.InspectTokensNLS=void 0;var k;(function(n){n.inspectTokensAction=d.localize(698,"Developer: Inspect Tokens")})(k||(e.InspectTokensNLS=k={}));var I;(function(n){n.gotoLineActionLabel=d.localize(699,"Go to Line/Column...")})(I||(e.GoToLineNLS=I={}));var E;(function(n){n.helpQuickAccessActionLabel=d.localize(700,"Show all Quick Access Providers")})(E||(e.QuickHelpNLS=E={}));var y;(function(n){n.quickCommandActionLabel=d.localize(701,"Command Palette"),n.quickCommandHelp=d.localize(702,"Show And Run Commands")})(y||(e.QuickCommandNLS=y={}));var m;(function(n){n.quickOutlineActionLabel=d.localize(703,"Go to Symbol..."),n.quickOutlineByCategoryActionLabel=d.localize(704,"Go to Symbol by Category...")})(m||(e.QuickOutlineNLS=m={}));var _;(function(n){n.editorViewAccessibleLabel=d.localize(705,"Editor content")})(_||(e.StandaloneCodeEditorNLS=_={}));var b;(function(n){n.toggleHighContrast=d.localize(706,"Toggle High Contrast Theme")})(b||(e.ToggleHighContrastNLS=b={}));var p;(function(n){n.bulkEditServiceSummary=d.localize(707,"Made {0} edits in {1} files")})(p||(e.StandaloneServicesNLS=p={}))}),define(ne[136],se([1,0,3,11,116,150,598]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RenderLineOutput2=e.RenderLineOutput=e.CharacterMapping=e.DomPosition=e.RenderLineInput=e.LineRange=void 0,e.renderViewLine=o,e.renderViewLine2=i;class m{constructor(S,L){this.startOffset=S,this.endOffset=L}equals(S){return this.startOffset===S.startOffset&&this.endOffset===S.endOffset}}e.LineRange=m;class _{constructor(S,L,D,T,M,A,P,N,O,F,x,W,V,q,H,z,U,j,Y){this.useMonospaceOptimizations=S,this.canUseHalfwidthRightwardsArrow=L,this.lineContent=D,this.continuesWithWrappedLine=T,this.isBasicASCII=M,this.containsRTL=A,this.fauxIndentLength=P,this.lineTokens=N,this.lineDecorations=O.sort(E.LineDecoration.compare),this.tabSize=F,this.startVisibleColumn=x,this.spaceWidth=W,this.stopRenderingLineAfter=H,this.renderWhitespace=z==="all"?4:z==="boundary"?1:z==="selection"?2:z==="trailing"?3:0,this.renderControlCharacters=U,this.fontLigatures=j,this.selectionsOnLine=Y&&Y.sort((R,J)=>R.startOffset>>16}static getCharIndex(S){return(S&65535)>>>0}constructor(S,L){this.length=S,this._data=new Uint32Array(this.length),this._horizontalOffset=new Uint32Array(this.length)}setColumnInfo(S,L,D,T){const M=(L<<16|D<<0)>>>0;this._data[S-1]=M,this._horizontalOffset[S-1]=T}getHorizontalOffset(S){return this._horizontalOffset.length===0?0:this._horizontalOffset[S-1]}charOffsetToPartData(S){return this.length===0?0:S<0?this._data[0]:S>=this.length?this._data[this.length-1]:this._data[S]}getDomPosition(S){const L=this.charOffsetToPartData(S-1),D=p.getPartIndex(L),T=p.getCharIndex(L);return new b(D,T)}getColumn(S,L){return this.partDataToCharOffset(S.partIndex,L,S.charIndex)+1}partDataToCharOffset(S,L,D){if(this.length===0)return 0;const T=(S<<16|D<<0)>>>0;let M=0,A=this.length-1;for(;M+1>>1,z=this._data[H];if(z===T)return H;z>T?A=H:M=H}if(M===A)return M;const P=this._data[M],N=this._data[A];if(P===T)return M;if(N===T)return A;const O=p.getPartIndex(P),F=p.getCharIndex(P),x=p.getPartIndex(N);let W;O!==x?W=L:W=p.getCharIndex(N);const V=D-F,q=W-D;return V<=q?M:A}}e.CharacterMapping=p;class n{constructor(S,L,D){this._renderLineOutputBrand=void 0,this.characterMapping=S,this.containsRTL=L,this.containsForeignElements=D}}e.RenderLineOutput=n;function o(w,S){if(w.lineContent.length===0){if(w.lineDecorations.length>0){S.appendString("");let L=0,D=0,T=0;for(const A of w.lineDecorations)(A.type===1||A.type===2)&&(S.appendString(''),A.type===1&&(T|=1,L++),A.type===2&&(T|=2,D++));S.appendString("");const M=new p(1,L+D);return M.setColumnInfo(1,L,0,0),new n(M,!1,T)}return S.appendString(""),new n(new p(0,0),!1,0)}return f(g(w),S)}class t{constructor(S,L,D,T){this.characterMapping=S,this.html=L,this.containsRTL=D,this.containsForeignElements=T}}e.RenderLineOutput2=t;function i(w){const S=new I.StringBuilder(1e4),L=o(w,S);return new t(L.characterMapping,S.build(),L.containsRTL,L.containsForeignElements)}class s{constructor(S,L,D,T,M,A,P,N,O,F,x,W,V,q,H,z){this.fontIsMonospace=S,this.canUseHalfwidthRightwardsArrow=L,this.lineContent=D,this.len=T,this.isOverflowing=M,this.overflowingCharCount=A,this.parts=P,this.containsForeignElements=N,this.fauxIndentLength=O,this.tabSize=F,this.startVisibleColumn=x,this.containsRTL=W,this.spaceWidth=V,this.renderSpaceCharCode=q,this.renderWhitespace=H,this.renderControlCharacters=z}}function g(w){const S=w.lineContent;let L,D,T;w.stopRenderingLineAfter!==-1&&w.stopRenderingLineAfter0){for(let P=0,N=w.lineDecorations.length;P0&&(M[A++]=new y.LinePart(D,"",0,!1));let P=D;for(let N=0,O=L.getCount();N=T){const V=S?k.containsRTL(w.substring(P,T)):!1;M[A++]=new y.LinePart(T,x,0,V);break}const W=S?k.containsRTL(w.substring(P,F)):!1;M[A++]=new y.LinePart(F,x,0,W),P=F}return M}function l(w,S,L){let D=0;const T=[];let M=0;if(L)for(let A=0,P=S.length;A=50&&(T[M++]=new y.LinePart(V+1,F,x,W),q=V+1,V=-1);q!==O&&(T[M++]=new y.LinePart(O,F,x,W))}else T[M++]=N;D=O}else for(let A=0,P=S.length;A50){const x=N.type,W=N.metadata,V=N.containsRTL,q=Math.ceil(F/50);for(let H=1;H=8234&&w<=8238||w>=8294&&w<=8297||w>=8206&&w<=8207||w===1564}function r(w,S){const L=[];let D=new y.LinePart(0,"",0,!1),T=0;for(const M of S){const A=M.endIndex;for(;TD.endIndex&&(D=new y.LinePart(T,M.type,M.metadata,M.containsRTL),L.push(D)),D=new y.LinePart(T+1,"mtkcontrol",M.metadata,!1),L.push(D))}T>D.endIndex&&(D=new y.LinePart(A,M.type,M.metadata,M.containsRTL),L.push(D))}return L}function u(w,S,L,D){const T=w.continuesWithWrappedLine,M=w.fauxIndentLength,A=w.tabSize,P=w.startVisibleColumn,N=w.useMonospaceOptimizations,O=w.selectionsOnLine,F=w.renderWhitespace===1,x=w.renderWhitespace===3,W=w.renderSpaceWidth!==w.spaceWidth,V=[];let q=0,H=0,z=D[H].type,U=D[H].containsRTL,j=D[H].endIndex;const Y=D.length;let G=!1,K=k.firstNonWhitespaceIndex(S),R;K===-1?(G=!0,K=L,R=L):R=k.lastNonWhitespaceIndex(S);let J=!1,ie=0,ue=O&&O[ie],he=P%A;for(let ae=M;ae=ue.endOffset&&(ie++,ue=O&&O[ie]);let de;if(aeR)de=!0;else if(ee===9)de=!0;else if(ee===32)if(F)if(J)de=!0;else{const ge=ae+1ae),de&&x&&(de=G||ae>R),de&&U&&ae>=K&&ae<=R&&(de=!1),J){if(!de||!N&&he>=A){if(W){const ge=q>0?V[q-1].endIndex:M;for(let X=ge+1;X<=ae;X++)V[q++]=new y.LinePart(X,"mtkw",1,!1)}else V[q++]=new y.LinePart(ae,"mtkw",1,!1);he=he%A}}else(ae===j||de&&ae>M)&&(V[q++]=new y.LinePart(ae,z,0,U),he=he%A);for(ee===9?he=A:k.isFullWidthCharacter(ee)?he+=2:he++,J=de;ae===j&&(H++,H0?S.charCodeAt(L-1):0,ee=L>1?S.charCodeAt(L-2):0;ae===32&&ee!==32&&ee!==9||(pe=!0)}else pe=!0;if(pe)if(W){const ae=q>0?V[q-1].endIndex:M;for(let ee=ae+1;ee<=L;ee++)V[q++]=new y.LinePart(ee,"mtkw",1,!1)}else V[q++]=new y.LinePart(L,"mtkw",1,!1);else V[q++]=new y.LinePart(L,z,0,U);return V}function C(w,S,L,D){D.sort(E.LineDecoration.compare);const T=E.LineDecorationsNormalizer.normalize(w,D),M=T.length;let A=0;const P=[];let N=0,O=0;for(let x=0,W=L.length;xO&&(O=j.startOffset,P[N++]=new y.LinePart(O,H,z,U)),j.endOffset+1<=q)O=j.endOffset+1,P[N++]=new y.LinePart(O,H+" "+j.className,z|j.metadata,U),A++;else{O=q,P[N++]=new y.LinePart(O,H+" "+j.className,z|j.metadata,U);break}}q>O&&(O=q,P[N++]=new y.LinePart(O,H,z,U))}const F=L[L.length-1].endIndex;if(A'):S.appendString("");for(let ue=0,he=O.length;ue=F&&(Z+=re)}}for(X&&(S.appendString(' style="width:'),S.appendString(String(q*$)),S.appendString('px"')),S.appendASCIICharCode(62);G1?S.appendCharCode(8594):S.appendCharCode(65515);for(let re=2;re<=te;re++)S.appendCharCode(160)}else Z=2,te=1,S.appendCharCode(H),S.appendCharCode(8204);R+=Z,J+=te,G>=F&&(K+=te)}}else for(S.appendASCIICharCode(62);G=F&&(K+=Z)}B?ie++:ie=0,G>=A&&!Y&&pe.isPseudoAfter()&&(Y=!0,j.setColumnInfo(G+1,ue,R,J)),S.appendString("")}return Y||j.setColumnInfo(A+1,O.length-1,R,J),P&&(S.appendString(''),S.appendString(d.localize(708,"Show more ({0})",v(N))),S.appendString("")),S.appendString(""),new n(j,V,T)}function h(w){return w.toString(16).toUpperCase().padStart(4,"0")}function v(w){return w<1024?d.localize(709,"{0} chars",w):w<1024*1024?`${(w/1024).toFixed(1)} KB`:`${(w/1024/1024).toFixed(1)} MB`}}),define(ne[667],se([1,0,103,74,37,116,150,136,95]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RenderOptions=e.LineSource=void 0,e.renderLines=p;const b=(0,d.createTrustedTypesPolicy)("diffEditorWidget",{createHTML:i=>i});function p(i,s,g,c){(0,k.applyFontInfo)(c,s.fontInfo);const l=g.length>0,a=new E.StringBuilder(1e4);let r=0,u=0;const C=[];for(let w=0;w');const C=s.getLineContent(),f=_.ViewLineRenderingData.isBasicASCII(C,l),h=_.ViewLineRenderingData.containsRTL(C,f,a),v=(0,m.renderViewLine)(new m.RenderLineInput(r.fontInfo.isMonospace&&!r.disableMonospaceOptimizations,r.fontInfo.canUseHalfwidthRightwardsArrow,C,!1,f,h,0,s,g,r.tabSize,0,r.fontInfo.spaceWidth,r.fontInfo.middotWidth,r.fontInfo.wsmiddotWidth,r.stopRenderingLineAfter,r.renderWhitespace,r.renderControlCharacters,r.fontLigatures!==I.EditorFontLigatures.OFF,null),u);return u.appendString(""),v.characterMapping.getHorizontalOffset(v.characterMapping.length)}}),define(ne[374],se([1,0,6,2,311,27]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MinimapTokensColorTracker=void 0;class y extends k.Disposable{static{this._INSTANCE=null}static getInstance(){return this._INSTANCE||(this._INSTANCE=(0,k.markAsSingleton)(new y)),this._INSTANCE}constructor(){super(),this._onDidChange=new d.Emitter,this.onDidChange=this._onDidChange.event,this._updateColorMap(),this._register(E.TokenizationRegistry.onDidChange(_=>{_.changedColorMap&&this._updateColorMap()}))}_updateColorMap(){const _=E.TokenizationRegistry.getColorMap();if(!_){this._colors=[I.RGBA8.Empty],this._backgroundIsLight=!0;return}this._colors=[I.RGBA8.Empty];for(let p=1;p<_.length;p++){const n=_[p].rgba;this._colors[p]=new I.RGBA8(n.r,n.g,n.b,Math.round(n.a*255))}const b=_[2].getRelativeLuminance();this._backgroundIsLight=b>=.5,this._onDidChange.fire(void 0)}getColor(_){return(_<1||_>=this._colors.length)&&(_=2),this._colors[_]}backgroundIsLight(){return this._backgroundIsLight}}e.MinimapTokensColorTracker=y}),define(ne[375],se([1,0,9,4,95,37]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewModelDecorations=void 0,e.isModelDecorationVisible=m,e.isModelDecorationInComment=_,e.isModelDecorationInString=b;class y{constructor(o,t,i,s,g){this.editorId=o,this.model=t,this.configuration=i,this._linesCollection=s,this._coordinatesConverter=g,this._decorationsCache=Object.create(null),this._cachedModelDecorationsResolver=null,this._cachedModelDecorationsResolverViewRange=null}_clearCachedModelDecorationsResolver(){this._cachedModelDecorationsResolver=null,this._cachedModelDecorationsResolverViewRange=null}dispose(){this._decorationsCache=Object.create(null),this._clearCachedModelDecorationsResolver()}reset(){this._decorationsCache=Object.create(null),this._clearCachedModelDecorationsResolver()}onModelDecorationsChanged(){this._decorationsCache=Object.create(null),this._clearCachedModelDecorationsResolver()}onLineMappingChanged(){this._decorationsCache=Object.create(null),this._clearCachedModelDecorationsResolver()}_getOrCreateViewModelDecoration(o){const t=o.id;let i=this._decorationsCache[t];if(!i){const s=o.range,g=o.options;let c;if(g.isWholeLine){const l=this._coordinatesConverter.convertModelPositionToViewPosition(new d.Position(s.startLineNumber,1),0,!1,!0),a=this._coordinatesConverter.convertModelPositionToViewPosition(new d.Position(s.endLineNumber,this.model.getLineMaxColumn(s.endLineNumber)),1);c=new k.Range(l.lineNumber,l.column,a.lineNumber,a.column)}else c=this._coordinatesConverter.convertModelRangeToViewRange(s,1);i=new I.ViewModelDecoration(c,g),this._decorationsCache[t]=i}return i}getMinimapDecorationsInRange(o){return this._getDecorationsInRange(o,!0,!1).decorations}getDecorationsViewportData(o){let t=this._cachedModelDecorationsResolver!==null;return t=t&&o.equalsRange(this._cachedModelDecorationsResolverViewRange),t||(this._cachedModelDecorationsResolver=this._getDecorationsInRange(o,!1,!1),this._cachedModelDecorationsResolverViewRange=o),this._cachedModelDecorationsResolver}getInlineDecorationsOnLine(o,t=!1,i=!1){const s=new k.Range(o,this._linesCollection.getViewLineMinColumn(o),o,this._linesCollection.getViewLineMaxColumn(o));return this._getDecorationsInRange(s,t,i).inlineDecorations[0]}_getDecorationsInRange(o,t,i){const s=this._linesCollection.getDecorationsInRange(o,this.editorId,(0,E.filterValidationDecorations)(this.configuration.options),t,i),g=o.startLineNumber,c=o.endLineNumber,l=[];let a=0;const r=[];for(let u=g;u<=c;u++)r[u-g]=[];for(let u=0,C=s.length;ut===1)}function b(n,o){return p(n,o.range,t=>t===2)}function p(n,o,t){for(let i=o.startLineNumber;i<=o.endLineNumber;i++){const s=n.tokenization.getLineTokens(i),g=i===o.startLineNumber,c=i===o.endLineNumber;let l=g?s.findTokenIndexAtOffset(o.startColumn-1):0;for(;lo.endColumn-1);){if(!t(s.getStandardTokenType(l)))return!1;l++}}return!0}}),define(ne[209],se([1,0,6,2,16]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ClickLinkGesture=e.ClickLinkOptions=e.ClickLinkKeyboardEvent=e.ClickLinkMouseEvent=void 0;function E(n,o){return!!n[o]}class y{constructor(o,t){this.target=o.target,this.isLeftClick=o.event.leftButton,this.isMiddleClick=o.event.middleButton,this.isRightClick=o.event.rightButton,this.hasTriggerModifier=E(o.event,t.triggerModifier),this.hasSideBySideModifier=E(o.event,t.triggerSideBySideModifier),this.isNoneOrSingleMouseDown=o.event.detail<=1}}e.ClickLinkMouseEvent=y;class m{constructor(o,t){this.keyCodeIsTriggerKey=o.keyCode===t.triggerKey,this.keyCodeIsSideBySideKey=o.keyCode===t.triggerSideBySideKey,this.hasTriggerModifier=E(o,t.triggerModifier)}}e.ClickLinkKeyboardEvent=m;class _{constructor(o,t,i,s){this.triggerKey=o,this.triggerModifier=t,this.triggerSideBySideKey=i,this.triggerSideBySideModifier=s}equals(o){return this.triggerKey===o.triggerKey&&this.triggerModifier===o.triggerModifier&&this.triggerSideBySideKey===o.triggerSideBySideKey&&this.triggerSideBySideModifier===o.triggerSideBySideModifier}}e.ClickLinkOptions=_;function b(n){return n==="altKey"?I.isMacintosh?new _(57,"metaKey",6,"altKey"):new _(5,"ctrlKey",6,"altKey"):I.isMacintosh?new _(6,"altKey",57,"metaKey"):new _(6,"altKey",5,"ctrlKey")}class p extends k.Disposable{constructor(o,t){super(),this._onMouseMoveOrRelevantKeyDown=this._register(new d.Emitter),this.onMouseMoveOrRelevantKeyDown=this._onMouseMoveOrRelevantKeyDown.event,this._onExecute=this._register(new d.Emitter),this.onExecute=this._onExecute.event,this._onCancel=this._register(new d.Emitter),this.onCancel=this._onCancel.event,this._editor=o,this._extractLineNumberFromMouseEvent=t?.extractLineNumberFromMouseEvent??(i=>i.target.position?i.target.position.lineNumber:0),this._opts=b(this._editor.getOption(78)),this._lastMouseMoveEvent=null,this._hasTriggerKeyOnMouseDown=!1,this._lineNumberOnMouseDown=0,this._register(this._editor.onDidChangeConfiguration(i=>{if(i.hasChanged(78)){const s=b(this._editor.getOption(78));if(this._opts.equals(s))return;this._opts=s,this._lastMouseMoveEvent=null,this._hasTriggerKeyOnMouseDown=!1,this._lineNumberOnMouseDown=0,this._onCancel.fire()}})),this._register(this._editor.onMouseMove(i=>this._onEditorMouseMove(new y(i,this._opts)))),this._register(this._editor.onMouseDown(i=>this._onEditorMouseDown(new y(i,this._opts)))),this._register(this._editor.onMouseUp(i=>this._onEditorMouseUp(new y(i,this._opts)))),this._register(this._editor.onKeyDown(i=>this._onEditorKeyDown(new m(i,this._opts)))),this._register(this._editor.onKeyUp(i=>this._onEditorKeyUp(new m(i,this._opts)))),this._register(this._editor.onMouseDrag(()=>this._resetHandler())),this._register(this._editor.onDidChangeCursorSelection(i=>this._onDidChangeCursorSelection(i))),this._register(this._editor.onDidChangeModel(i=>this._resetHandler())),this._register(this._editor.onDidChangeModelContent(()=>this._resetHandler())),this._register(this._editor.onDidScrollChange(i=>{(i.scrollTopChanged||i.scrollLeftChanged)&&this._resetHandler()}))}_onDidChangeCursorSelection(o){o.selection&&o.selection.startColumn!==o.selection.endColumn&&this._resetHandler()}_onEditorMouseMove(o){this._lastMouseMoveEvent=o,this._onMouseMoveOrRelevantKeyDown.fire([o,null])}_onEditorMouseDown(o){this._hasTriggerKeyOnMouseDown=o.hasTriggerModifier,this._lineNumberOnMouseDown=this._extractLineNumberFromMouseEvent(o)}_onEditorMouseUp(o){const t=this._extractLineNumberFromMouseEvent(o);this._hasTriggerKeyOnMouseDown&&this._lineNumberOnMouseDown&&this._lineNumberOnMouseDown===t&&this._onExecute.fire(o)}_onEditorKeyDown(o){this._lastMouseMoveEvent&&(o.keyCodeIsTriggerKey||o.keyCodeIsSideBySideKey&&o.hasTriggerModifier)?this._onMouseMoveOrRelevantKeyDown.fire([this._lastMouseMoveEvent,o]):o.hasTriggerModifier&&this._onCancel.fire()}_onEditorKeyUp(o){o.keyCodeIsTriggerKey&&this._onCancel.fire()}_resetHandler(){this._lastMouseMoveEvent=null,this._hasTriggerKeyOnMouseDown=!1,this._onCancel.fire()}}e.ClickLinkGesture=p}),define(ne[178],se([1,0,8,6,187,2,45,48,11,4,3]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ReferencesModel=e.FileReferences=e.FilePreview=e.OneReference=void 0;class n{constructor(g,c,l,a){this.isProviderFirst=g,this.parent=c,this.link=l,this._rangeCallback=a,this.id=I.defaultGenerator.nextId()}get uri(){return this.link.uri}get range(){return this._range??this.link.targetSelectionRange??this.link.range}set range(g){this._range=g,this._rangeCallback(this)}get ariaMessage(){const g=this.parent.getPreview(this)?.preview(this.range);return g?(0,p.localize)(996,"{0} in {1} on line {2} at column {3}",g.value,(0,m.basename)(this.uri),this.range.startLineNumber,this.range.startColumn):(0,p.localize)(995,"in {0} on line {1} at column {2}",(0,m.basename)(this.uri),this.range.startLineNumber,this.range.startColumn)}}e.OneReference=n;class o{constructor(g){this._modelReference=g}dispose(){this._modelReference.dispose()}preview(g,c=8){const l=this._modelReference.object.textEditorModel;if(!l)return;const{startLineNumber:a,startColumn:r,endLineNumber:u,endColumn:C}=g,f=l.getWordUntilPosition({lineNumber:a,column:r-c}),h=new b.Range(a,f.startColumn,a,r),v=new b.Range(u,C,u,1073741824),w=l.getValueInRange(h).replace(/^\s+/,""),S=l.getValueInRange(g),L=l.getValueInRange(v).replace(/\s+$/,"");return{value:w+S+L,highlight:{start:w.length,end:w.length+S.length}}}}e.FilePreview=o;class t{constructor(g,c){this.parent=g,this.uri=c,this.children=[],this._previews=new y.ResourceMap}dispose(){(0,E.dispose)(this._previews.values()),this._previews.clear()}getPreview(g){return this._previews.get(g.uri)}get ariaMessage(){const g=this.children.length;return g===1?(0,p.localize)(997,"1 symbol in {0}, full path {1}",(0,m.basename)(this.uri),this.uri.fsPath):(0,p.localize)(998,"{0} symbols in {1}, full path {2}",g,(0,m.basename)(this.uri),this.uri.fsPath)}async resolve(g){if(this._previews.size!==0)return this;for(const c of this.children)if(!this._previews.has(c.uri))try{const l=await g.createModelReference(c.uri);this._previews.set(c.uri,new o(l))}catch(l){(0,d.onUnexpectedError)(l)}return this}}e.FileReferences=t;class i{constructor(g,c){this.groups=[],this.references=[],this._onDidChangeReferenceRange=new k.Emitter,this.onDidChangeReferenceRange=this._onDidChangeReferenceRange.event,this._links=g,this._title=c;const[l]=g;g.sort(i._compareReferences);let a;for(const r of g)if((!a||!m.extUri.isEqual(a.uri,r.uri,!0))&&(a=new t(this,r.uri),this.groups.push(a)),a.children.length===0||i._compareReferences(r,a.children[a.children.length-1])!==0){const u=new n(l===r,a,r,C=>this._onDidChangeReferenceRange.fire(C));this.references.push(u),a.children.push(u)}}dispose(){(0,E.dispose)(this.groups),this._onDidChangeReferenceRange.dispose(),this.groups.length=0}clone(){return new i(this._links,this._title)}get title(){return this._title}get isEmpty(){return this.groups.length===0}get ariaMessage(){return this.isEmpty?(0,p.localize)(999,"No results found"):this.references.length===1?(0,p.localize)(1e3,"Found 1 symbol in {0}",this.references[0].uri.fsPath):this.groups.length===1?(0,p.localize)(1001,"Found {0} symbols in {1}",this.references.length,this.groups[0].uri.fsPath):(0,p.localize)(1002,"Found {0} symbols in {1} files",this.references.length,this.groups.length)}nextOrPreviousReference(g,c){const{parent:l}=g;let a=l.children.indexOf(g);const r=l.children.length,u=l.parent.groups.length;return u===1||c&&a+10?(c?a=(a+1)%r:a=(a+r-1)%r,l.children[a]):(a=l.parent.groups.indexOf(l),c?(a=(a+1)%u,l.parent.groups[a].children[0]):(a=(a+u-1)%u,l.parent.groups[a].children[l.parent.groups[a].children.length-1]))}nearestReference(g,c){const l=this.references.map((a,r)=>({idx:r,prefixLen:_.commonPrefixLength(a.uri.toString(),g.toString()),offsetDist:Math.abs(a.range.startLineNumber-c.lineNumber)*100+Math.abs(a.range.startColumn-c.column)})).sort((a,r)=>a.prefixLen>r.prefixLen?-1:a.prefixLenr.offsetDist?1:0)[0];if(l)return this.references[l.idx]}referenceAt(g,c){for(const l of this.references)if(l.uri.toString()===g.toString()&&b.Range.containsPosition(l.range,c))return l}firstReference(){for(const g of this.references)if(g.isProviderFirst)return g;return this.references[0]}static _compareReferences(g,c){return m.extUri.compare(g.uri,c.uri)||b.Range.compareRangesUsingStarts(g.range,c.range)}}e.ReferencesModel=i}),define(ne[668],se([1,0,13,14]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContentHoverComputer=void 0;class I{get anchor(){return this._anchor}set anchor(y){this._anchor=y}get shouldFocus(){return this._shouldFocus}set shouldFocus(y){this._shouldFocus=y}get source(){return this._source}set source(y){this._source=y}get insistOnKeepingHoverVisible(){return this._insistOnKeepingHoverVisible}set insistOnKeepingHoverVisible(y){this._insistOnKeepingHoverVisible=y}constructor(y,m){this._editor=y,this._participants=m,this._anchor=null,this._shouldFocus=!1,this._source=0,this._insistOnKeepingHoverVisible=!1}static _getLineDecorations(y,m){if(m.type!==1&&!m.supportsMarkerHover)return[];const _=y.getModel(),b=m.range.startLineNumber;if(b>_.getLineCount())return[];const p=_.getLineMaxColumn(b);return y.getLineDecorations(b).filter(n=>{if(n.options.isWholeLine)return!0;const o=n.range.startLineNumber===b?n.range.startColumn:1,t=n.range.endLineNumber===b?n.range.endColumn:p;if(n.options.showIfCollapsed){if(o>m.range.startColumn+1||m.range.endColumn-1>t)return!1}else if(o>m.range.startColumn||m.range.endColumn>t)return!1;return!0})}computeAsync(y){const m=this._anchor;if(!this._editor.hasModel()||!m)return k.AsyncIterableObject.EMPTY;const _=I._getLineDecorations(this._editor,m);return k.AsyncIterableObject.merge(this._participants.map(b=>b.computeAsync?b.computeAsync(m,_,y):k.AsyncIterableObject.EMPTY))}computeSync(){if(!this._editor.hasModel()||!this._anchor)return[];const y=I._getLineDecorations(this._editor,this._anchor);let m=[];for(const _ of this._participants)m=m.concat(_.computeSync(this._anchor,y));return(0,d.coalesce)(m)}}e.ContentHoverComputer=I}),define(ne[264],se([1,0,3]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DECREASE_HOVER_VERBOSITY_ACTION_LABEL=e.DECREASE_HOVER_VERBOSITY_ACTION_ID=e.INCREASE_HOVER_VERBOSITY_ACTION_LABEL=e.INCREASE_HOVER_VERBOSITY_ACTION_ID=e.GO_TO_BOTTOM_HOVER_ACTION_ID=e.GO_TO_TOP_HOVER_ACTION_ID=e.PAGE_DOWN_HOVER_ACTION_ID=e.PAGE_UP_HOVER_ACTION_ID=e.SCROLL_RIGHT_HOVER_ACTION_ID=e.SCROLL_LEFT_HOVER_ACTION_ID=e.SCROLL_DOWN_HOVER_ACTION_ID=e.SCROLL_UP_HOVER_ACTION_ID=e.SHOW_DEFINITION_PREVIEW_HOVER_ACTION_ID=e.SHOW_OR_FOCUS_HOVER_ACTION_ID=void 0,e.SHOW_OR_FOCUS_HOVER_ACTION_ID="editor.action.showHover",e.SHOW_DEFINITION_PREVIEW_HOVER_ACTION_ID="editor.action.showDefinitionPreviewHover",e.SCROLL_UP_HOVER_ACTION_ID="editor.action.scrollUpHover",e.SCROLL_DOWN_HOVER_ACTION_ID="editor.action.scrollDownHover",e.SCROLL_LEFT_HOVER_ACTION_ID="editor.action.scrollLeftHover",e.SCROLL_RIGHT_HOVER_ACTION_ID="editor.action.scrollRightHover",e.PAGE_UP_HOVER_ACTION_ID="editor.action.pageUpHover",e.PAGE_DOWN_HOVER_ACTION_ID="editor.action.pageDownHover",e.GO_TO_TOP_HOVER_ACTION_ID="editor.action.goToTopHover",e.GO_TO_BOTTOM_HOVER_ACTION_ID="editor.action.goToBottomHover",e.INCREASE_HOVER_VERBOSITY_ACTION_ID="editor.action.increaseHoverVerbosityLevel",e.INCREASE_HOVER_VERBOSITY_ACTION_LABEL=d.localize(1006,"Increase Hover Verbosity Level"),e.DECREASE_HOVER_VERBOSITY_ACTION_ID="editor.action.decreaseHoverVerbosityLevel",e.DECREASE_HOVER_VERBOSITY_ACTION_LABEL=d.localize(1007,"Decrease Hover Verbosity Level")}),define(ne[376],se([1,0,14,8,6,2]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HoverOperation=e.HoverResult=void 0;class y{constructor(b,p,n){this.value=b,this.isComplete=p,this.hasLoadingMessage=n}}e.HoverResult=y;class m extends E.Disposable{constructor(b,p){super(),this._editor=b,this._computer=p,this._onResult=this._register(new I.Emitter),this.onResult=this._onResult.event,this._firstWaitScheduler=this._register(new d.RunOnceScheduler(()=>this._triggerAsyncComputation(),0)),this._secondWaitScheduler=this._register(new d.RunOnceScheduler(()=>this._triggerSyncComputation(),0)),this._loadingMessageScheduler=this._register(new d.RunOnceScheduler(()=>this._triggerLoadingMessage(),0)),this._state=0,this._asyncIterable=null,this._asyncIterableDone=!1,this._result=[]}dispose(){this._asyncIterable&&(this._asyncIterable.cancel(),this._asyncIterable=null),super.dispose()}get _hoverTime(){return this._editor.getOption(60).delay}get _firstWaitTime(){return this._hoverTime/2}get _secondWaitTime(){return this._hoverTime-this._firstWaitTime}get _loadingMessageTime(){return 3*this._hoverTime}_setState(b,p=!0){this._state=b,p&&this._fireResult()}_triggerAsyncComputation(){this._setState(2),this._secondWaitScheduler.schedule(this._secondWaitTime),this._computer.computeAsync?(this._asyncIterableDone=!1,this._asyncIterable=(0,d.createCancelableAsyncIterable)(b=>this._computer.computeAsync(b)),(async()=>{try{for await(const b of this._asyncIterable)b&&(this._result.push(b),this._fireResult());this._asyncIterableDone=!0,(this._state===3||this._state===4)&&this._setState(0)}catch(b){(0,k.onUnexpectedError)(b)}})()):this._asyncIterableDone=!0}_triggerSyncComputation(){this._computer.computeSync&&(this._result=this._result.concat(this._computer.computeSync())),this._setState(this._asyncIterableDone?0:3)}_triggerLoadingMessage(){this._state===3&&this._setState(4)}_fireResult(){if(this._state===1||this._state===2)return;const b=this._state===0,p=this._state===4;this._onResult.fire(new y(this._result.slice(0),b,p))}start(b){if(b===0)this._state===0&&(this._setState(1),this._firstWaitScheduler.schedule(this._firstWaitTime),this._loadingMessageScheduler.schedule(this._loadingMessageTime));else switch(this._state){case 0:this._triggerAsyncComputation(),this._secondWaitScheduler.cancel(),this._triggerSyncComputation();break;case 2:this._secondWaitScheduler.cancel(),this._triggerSyncComputation();break}}cancel(){this._firstWaitScheduler.cancel(),this._secondWaitScheduler.cancel(),this._loadingMessageScheduler.cancel(),this._asyncIterable&&(this._asyncIterable.cancel(),this._asyncIterable=null),this._result=[],this._setState(0,!1)}}e.HoverOperation=m}),define(ne[210],se([1,0,5]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isMousePositionWithinElement=k;function k(I,E,y){const m=d.getDomNodePagePosition(I);return!(Em.left+m.width||ym.top+m.height)}}),define(ne[669],se([1,0,13,57,40]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MarginHoverComputer=void 0;class E{get lineNumber(){return this._lineNumber}set lineNumber(m){this._lineNumber=m}get lane(){return this._laneOrLine}set lane(m){this._laneOrLine=m}constructor(m){this._editor=m,this._lineNumber=-1,this._laneOrLine=I.GlyphMarginLane.Center}computeSync(){const m=n=>({value:n}),_=this._editor.getLineDecorations(this._lineNumber),b=[],p=this._laneOrLine==="lineNo";if(!_)return b;for(const n of _){const o=n.options.glyphMargin?.position??I.GlyphMarginLane.Center;if(!p&&o!==this._laneOrLine)continue;const t=p?n.options.lineNumberHoverMessage:n.options.glyphMarginHoverMessage;!t||(0,k.isEmptyMarkdownString)(t)||b.push(...(0,d.asArray)(t).map(m))}return b}}e.MarginHoverComputer=E}),define(ne[670],se([1,0,255,2,9,5]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ResizableContentWidget=void 0;const y=30,m=24;class _ extends k.Disposable{constructor(p,n=new E.Dimension(10,10)){super(),this._editor=p,this.allowEditorOverflow=!0,this.suppressMouseDown=!1,this._resizableNode=this._register(new d.ResizableHTMLElement),this._contentPosition=null,this._isResizing=!1,this._resizableNode.domNode.style.position="absolute",this._resizableNode.minSize=E.Dimension.lift(n),this._resizableNode.layout(n.height,n.width),this._resizableNode.enableSashes(!0,!0,!0,!0),this._register(this._resizableNode.onDidResize(o=>{this._resize(new E.Dimension(o.dimension.width,o.dimension.height)),o.done&&(this._isResizing=!1)})),this._register(this._resizableNode.onDidWillResize(()=>{this._isResizing=!0}))}get isResizing(){return this._isResizing}getDomNode(){return this._resizableNode.domNode}getPosition(){return this._contentPosition}get position(){return this._contentPosition?.position?I.Position.lift(this._contentPosition.position):void 0}_availableVerticalSpaceAbove(p){const n=this._editor.getDomNode(),o=this._editor.getScrolledVisiblePosition(p);return!n||!o?void 0:E.getDomNodePagePosition(n).top+o.top-y}_availableVerticalSpaceBelow(p){const n=this._editor.getDomNode(),o=this._editor.getScrolledVisiblePosition(p);if(!n||!o)return;const t=E.getDomNodePagePosition(n),i=E.getClientArea(n.ownerDocument.body),s=t.top+o.top+o.height;return i.height-s-m}_findPositionPreference(p,n){const o=Math.min(this._availableVerticalSpaceBelow(n)??1/0,p),t=Math.min(this._availableVerticalSpaceAbove(n)??1/0,p),i=Math.min(Math.max(t,o),p),s=Math.min(p,i);let g;return this._editor.getOption(60).above?g=s<=t?1:2:g=s<=o?2:1,g===1?this._resizableNode.enableSashes(!0,!0,!1,!1):this._resizableNode.enableSashes(!1,!0,!0,!1),g}_resize(p){this._resizableNode.layout(p.height,p.width)}}e.ResizableContentWidget=_}),define(ne[377],se([1,0,8,2,9,4,42,22]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlayHintsFragments=e.InlayHintItem=e.InlayHintAnchor=void 0,e.asCommandLink=n;class _{constructor(t,i){this.range=t,this.direction=i}}e.InlayHintAnchor=_;class b{constructor(t,i,s){this.hint=t,this.anchor=i,this.provider=s,this._isResolved=!1}with(t){const i=new b(this.hint,t.anchor,this.provider);return i._isResolved=this._isResolved,i._currentResolve=this._currentResolve,i}async resolve(t){if(typeof this.provider.resolveInlayHint=="function"){if(this._currentResolve)return await this._currentResolve,t.isCancellationRequested?void 0:this.resolve(t);this._isResolved||(this._currentResolve=this._doResolve(t).finally(()=>this._currentResolve=void 0)),await this._currentResolve}}async _doResolve(t){try{const i=await Promise.resolve(this.provider.resolveInlayHint(this.hint,t));this.hint.tooltip=i?.tooltip??this.hint.tooltip,this.hint.label=i?.label??this.hint.label,this.hint.textEdits=i?.textEdits??this.hint.textEdits,this._isResolved=!0}catch(i){(0,d.onUnexpectedExternalError)(i),this._isResolved=!1}}}e.InlayHintItem=b;class p{static{this._emptyInlayHintList=Object.freeze({dispose(){},hints:[]})}static async create(t,i,s,g){const c=[],l=t.ordered(i).reverse().map(a=>s.map(async r=>{try{const u=await a.provideInlayHints(i,r,g);(u?.hints.length||a.onDidChangeInlayHints)&&c.push([u??p._emptyInlayHintList,a])}catch(u){(0,d.onUnexpectedExternalError)(u)}}));if(await Promise.all(l.flat()),g.isCancellationRequested||i.isDisposed())throw new d.CancellationError;return new p(s,c,i)}constructor(t,i,s){this._disposables=new k.DisposableStore,this.ranges=t,this.provider=new Set;const g=[];for(const[c,l]of i){this._disposables.add(c),this.provider.add(l);for(const a of c.hints){const r=s.validatePosition(a.position);let u="before";const C=p._getRangeAtPosition(s,r);let f;C.getStartPosition().isBefore(r)?(f=E.Range.fromPositions(C.getStartPosition(),r),u="after"):(f=E.Range.fromPositions(r,C.getEndPosition()),u="before"),g.push(new b(a,new _(f,u),l))}}this.items=g.sort((c,l)=>I.Position.compare(c.hint.position,l.hint.position))}dispose(){this._disposables.dispose()}static _getRangeAtPosition(t,i){const s=i.lineNumber,g=t.getWordAtPosition(i);if(g)return new E.Range(s,g.startColumn,s,g.endColumn);t.tokenization.tokenizeIfCheap(s);const c=t.tokenization.getLineTokens(s),l=i.column-1,a=c.findTokenIndexAtOffset(l);let r=c.getStartOffset(a),u=c.getEndOffset(a);return u-r===1&&(r===l&&a>1?(r=c.getStartOffset(a-1),u=c.getEndOffset(a-1)):u===l&&aq.toString?q.toString():""+q).join(" -> ")}`));const V=new k.DeferredPromise;return D.set(F,V.p),(async()=>{if(!W){const q=L(F);for(const H of q){const z=await A(H);if(z&&z.items.length>0)return}}try{return r instanceof m.Position?await F.provideInlineCompletions(u,r,C,f):await F.provideInlineEdits?.(u,r,C,f)}catch(q){(0,y.onUnexpectedExternalError)(q);return}})().then(q=>V.complete(q),q=>V.error(q)),V.p}const P=await Promise.all(w.map(async F=>({provider:F,completions:await A(F)}))),N=new Map,O=[];for(const F of P){const x=F.completions;if(!x)continue;const W=new s(x,F.provider);O.push(W);for(const V of x.items){const q=g.from(V,W,v,u,h);N.set(q.hash(),q)}}return new i(Array.from(N.values()),new Set(N.keys()),O)}class i{constructor(r,u,C){this.completions=r,this.hashs=u,this.providerResults=C}has(r){return this.hashs.has(r.hash())}dispose(){for(const r of this.providerResults)r.removeRef()}}e.InlineCompletionProviderResult=i;class s{constructor(r,u){this.inlineCompletions=r,this.provider=u,this.refCount=1}addRef(){this.refCount++}removeRef(){this.refCount--,this.refCount===0&&this.provider.freeInlineCompletions(this.inlineCompletions)}}e.InlineCompletionList=s;class g{static from(r,u,C,f,h){let v,w,S=r.range?_.Range.lift(r.range):C;if(typeof r.insertText=="string"){if(v=r.insertText,h&&r.completeBracketPairs){v=l(v,S.getStartPosition(),f,h);const L=v.length-r.insertText.length;L!==0&&(S=new _.Range(S.startLineNumber,S.startColumn,S.endLineNumber,S.endColumn+L))}w=void 0}else if("snippet"in r.insertText){const L=r.insertText.snippet.length;if(h&&r.completeBracketPairs){r.insertText.snippet=l(r.insertText.snippet,S.getStartPosition(),f,h);const T=r.insertText.snippet.length-L;T!==0&&(S=new _.Range(S.startLineNumber,S.startColumn,S.endLineNumber,S.endColumn+T))}const D=new o.SnippetParser().parse(r.insertText.snippet);D.children.length===1&&D.children[0]instanceof o.Text?(v=D.children[0].value,w=void 0):(v=D.toString(),w={snippet:r.insertText.snippet,range:S})}else(0,d.assertNever)(r.insertText);return new g(v,r.command,S,v,w,r.additionalTextEdits||(0,n.getReadonlyEmptyArray)(),r,u)}constructor(r,u,C,f,h,v,w,S){this.filterText=r,this.command=u,this.range=C,this.insertText=f,this.snippetInfo=h,this.additionalTextEdits=v,this.sourceInlineCompletion=w,this.source=S,r=r.replace(/\r\n|\r/g,` `),f=r.replace(/\r\n|\r/g,` `)}withRange(r){return new g(this.filterText,this.command,r,this.insertText,this.snippetInfo,this.additionalTextEdits,this.sourceInlineCompletion,this.source)}hash(){return JSON.stringify({insertText:this.insertText,range:this.range.toString()})}toSingleTextEdit(){return new p.SingleTextEdit(this.range,this.insertText)}}e.InlineCompletionItem=g;function c(a,r){const u=r.getWordAtPosition(a),C=r.getLineMaxColumn(a.lineNumber);return u?new _.Range(a.lineNumber,u.startColumn,a.lineNumber,C):_.Range.fromPositions(a,a.with(void 0,C))}function l(a,r,u,C){const h=u.getLineContent(r.lineNumber).substring(0,r.column-1)+a,w=u.tokenization.tokenizeLineWithEdit(r,h.length-(r.column-1),a)?.sliceAndInflate(r.column-1,h.length,0);return w?(0,b.fixBracketsInLine)(w,C):a}}),define(ne[379],se([1,0,5,102,2,21,65,112]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PlaceholderTextContribution=void 0;class _ extends I.Disposable{static{this.ID="editor.contrib.placeholderText"}constructor(n){super(),this._editor=n,this._editorObs=(0,m.observableCodeEditor)(this._editor),this._placeholderText=this._editorObs.getOption(88),this._state=(0,E.derivedOpts)({owner:this,equalsFn:k.structuralEquals},o=>{const t=this._placeholderText.read(o);if(t&&this._editorObs.valueIsEmpty.read(o))return{placeholder:t}}),this._shouldViewBeAlive=b(this,o=>this._state.read(o)?.placeholder!==void 0),this._view=(0,y.derivedWithStore)((o,t)=>{if(!this._shouldViewBeAlive.read(o))return;const i=(0,d.h)("div.editorPlaceholder");t.add((0,E.autorun)(s=>{const g=this._state.read(s),c=g?.placeholder!==void 0;i.root.style.display=c?"block":"none",i.root.innerText=g?.placeholder??""})),t.add((0,E.autorun)(s=>{const g=this._editorObs.layoutInfo.read(s);i.root.style.left=`${g.contentLeft}px`,i.root.style.width=g.contentWidth-g.verticalScrollbarWidth+"px",i.root.style.top=`${this._editor.getTopForLineNumber(0)}px`})),t.add((0,E.autorun)(s=>{i.root.style.fontFamily=this._editorObs.getOption(49).read(s),i.root.style.fontSize=this._editorObs.getOption(52).read(s)+"px",i.root.style.lineHeight=this._editorObs.getOption(67).read(s)+"px"})),t.add(this._editorObs.createOverlayWidget({allowEditorOverflow:!1,minContentWidthInPx:(0,E.constObservable)(0),position:(0,E.constObservable)(null),domNode:i.root}))}),this._view.recomputeInitiallyAndOnChange(this._store)}}e.PlaceholderTextContribution=_;function b(p,n){return(0,E.derivedObservableWithCache)(p,(o,t)=>t===!0?!0:n(o))}}),define(ne[380],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AccessibleViewRegistry=void 0,e.AccessibleViewRegistry=new class{constructor(){this._implementations=[]}register(k){return this._implementations.push(k),{dispose:()=>{const I=this._implementations.indexOf(k);I!==-1&&this._implementations.splice(I,1)}}}getImplementations(){return this._implementations}}}),define(ne[381],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isLocalizedString=d,e.isICommandActionToggleInfo=k;function d(I){return I&&typeof I=="object"&&typeof I.original=="string"&&typeof I.value=="string"}function k(I){return I?I.condition!==void 0:!1}}),define(ne[671],se([1,0,3]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Categories=void 0,e.Categories=Object.freeze({View:(0,d.localize2)(1477,"View"),Help:(0,d.localize2)(1478,"Help"),Test:(0,d.localize2)(1479,"Test"),File:(0,d.localize2)(1480,"File"),Preferences:(0,d.localize2)(1481,"Preferences"),Developer:(0,d.localize2)(1482,"Developer")})}),define(ne[672],se([1,0,8,3]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Scanner=void 0;function I(..._){switch(_.length){case 1:return(0,k.localize)(1532,"Did you mean {0}?",_[0]);case 2:return(0,k.localize)(1533,"Did you mean {0} or {1}?",_[0],_[1]);case 3:return(0,k.localize)(1534,"Did you mean {0}, {1} or {2}?",_[0],_[1],_[2]);default:return}}const E=(0,k.localize)(1535,"Did you forget to open or close the quote?"),y=(0,k.localize)(1536,"Did you forget to escape the '/' (slash) character? Put two backslashes before it to escape, e.g., '\\\\/'.");class m{constructor(){this._input="",this._start=0,this._current=0,this._tokens=[],this._errors=[],this.stringRe=/[a-zA-Z0-9_<>\-\./\\:\*\?\+\[\]\^,#@;"%\$\p{L}-]+/uy}static getLexeme(b){switch(b.type){case 0:return"(";case 1:return")";case 2:return"!";case 3:return b.isTripleEq?"===":"==";case 4:return b.isTripleEq?"!==":"!=";case 5:return"<";case 6:return"<=";case 7:return">=";case 8:return">=";case 9:return"=~";case 10:return b.lexeme;case 11:return"true";case 12:return"false";case 13:return"in";case 14:return"not";case 15:return"&&";case 16:return"||";case 17:return b.lexeme;case 18:return b.lexeme;case 19:return b.lexeme;case 20:return"EOF";default:throw(0,d.illegalState)(`unhandled token type: ${JSON.stringify(b)}; have you forgotten to add a case?`)}}static{this._regexFlags=new Set(["i","g","s","m","y","u"].map(b=>b.charCodeAt(0)))}static{this._keywords=new Map([["not",14],["in",13],["false",12],["true",11]])}reset(b){return this._input=b,this._start=0,this._current=0,this._tokens=[],this._errors=[],this}scan(){for(;!this._isAtEnd();)switch(this._start=this._current,this._advance()){case 40:this._addToken(0);break;case 41:this._addToken(1);break;case 33:if(this._match(61)){const p=this._match(61);this._tokens.push({type:4,offset:this._start,isTripleEq:p})}else this._addToken(2);break;case 39:this._quotedString();break;case 47:this._regex();break;case 61:if(this._match(61)){const p=this._match(61);this._tokens.push({type:3,offset:this._start,isTripleEq:p})}else this._match(126)?this._addToken(9):this._error(I("==","=~"));break;case 60:this._addToken(this._match(61)?6:5);break;case 62:this._addToken(this._match(61)?8:7);break;case 38:this._match(38)?this._addToken(15):this._error(I("&&"));break;case 124:this._match(124)?this._addToken(16):this._error(I("||"));break;case 32:case 13:case 9:case 10:case 160:break;default:this._string()}return this._start=this._current,this._addToken(20),Array.from(this._tokens)}_match(b){return this._isAtEnd()||this._input.charCodeAt(this._current)!==b?!1:(this._current++,!0)}_advance(){return this._input.charCodeAt(this._current++)}_peek(){return this._isAtEnd()?0:this._input.charCodeAt(this._current)}_addToken(b){this._tokens.push({type:b,offset:this._start})}_error(b){const p=this._start,n=this._input.substring(this._start,this._current),o={type:19,offset:this._start,lexeme:n};this._errors.push({offset:p,lexeme:n,additionalInfo:b}),this._tokens.push(o)}_string(){this.stringRe.lastIndex=this._start;const b=this.stringRe.exec(this._input);if(b){this._current=this._start+b[0].length;const p=this._input.substring(this._start,this._current),n=m._keywords.get(p);n?this._addToken(n):this._tokens.push({type:17,lexeme:p,offset:this._start})}}_quotedString(){for(;this._peek()!==39&&!this._isAtEnd();)this._advance();if(this._isAtEnd()){this._error(E);return}this._advance(),this._tokens.push({type:18,lexeme:this._input.substring(this._start+1,this._current-1),offset:this._start+1})}_regex(){let b=this._current,p=!1,n=!1;for(;;){if(b>=this._input.length){this._current=b,this._error(y);return}const t=this._input.charCodeAt(b);if(p)p=!1;else if(t===47&&!n){b++;break}else t===91?n=!0:t===92?p=!0:t===93&&(n=!1);b++}for(;b=this._input.length}}e.Scanner=m}),define(ne[673],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorOpenSource=void 0;var d;(function(k){k[k.API=0]="API",k[k.USER=1]="USER"})(d||(e.EditorOpenSource=d={}))}),define(ne[674],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ExtensionIdentifierSet=e.ExtensionIdentifier=void 0;class d{constructor(E){this.value=E,this._lower=E.toLowerCase()}static toKey(E){return typeof E=="string"?E.toLowerCase():E._lower}}e.ExtensionIdentifier=d;class k{constructor(E){if(this._set=new Set,E)for(const y of E)this.add(y)}add(E){this._set.add(d.toKey(E))}has(E){return this._set.has(d.toKey(E))}}e.ExtensionIdentifierSet=k}),define(ne[382],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FileKind=void 0;var d;(function(k){k[k.FILE=0]="FILE",k[k.FOLDER=1]="FOLDER",k[k.ROOT_FOLDER=2]="ROOT_FOLDER"})(d||(e.FileKind=d={}))}),define(ne[675],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.showHistoryKeybindingHint=d;function d(k){return k.lookupKeybinding("history.showPrevious")?.getElectronAccelerator()==="Up"&&k.lookupKeybinding("history.showNext")?.getElectronAccelerator()==="Down"}}),define(ne[265],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SyncDescriptor=void 0;class d{constructor(I,E=[],y=!1){this.ctor=I,this.staticArguments=E,this.supportsDelayedInstantiation=y}}e.SyncDescriptor=d}),define(ne[49],se([1,0,265]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.registerSingleton=I,e.getSingletonServiceDescriptors=E;const k=[];function I(y,m,_){m instanceof d.SyncDescriptor||(m=new d.SyncDescriptor(m,[],!!_)),k.push([y,m])}function E(){return k}}),define(ne[676],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Graph=e.Node=void 0;class d{constructor(E,y){this.key=E,this.data=y,this.incoming=new Map,this.outgoing=new Map}}e.Node=d;class k{constructor(E){this._hashFn=E,this._nodes=new Map}roots(){const E=[];for(const y of this._nodes.values())y.outgoing.size===0&&E.push(y);return E}insertEdge(E,y){const m=this.lookupOrInsertNode(E),_=this.lookupOrInsertNode(y);m.outgoing.set(_.key,_),_.incoming.set(m.key,m)}removeNode(E){const y=this._hashFn(E);this._nodes.delete(y);for(const m of this._nodes.values())m.outgoing.delete(y),m.incoming.delete(y)}lookupOrInsertNode(E){const y=this._hashFn(E);let m=this._nodes.get(y);return m||(m=new d(y,E),this._nodes.set(y,m)),m}isEmpty(){return this._nodes.size===0}toString(){const E=[];for(const[y,m]of this._nodes)E.push(`${y} (-> incoming)[${[...m.incoming.keys()].join(", ")}] (outgoing ->)[${[...m.outgoing.keys()].join(",")}] `);return E.join(` `)}findCycleSlow(){for(const[E,y]of this._nodes){const m=new Set([E]),_=this._findCycle(y,m);if(_)return _}}_findCycle(E,y){for(const[m,_]of E.outgoing){if(y.has(m))return[...y,m].join(" -> ");y.add(m);const b=this._findCycle(_,y);if(b)return b;y.delete(m)}}}e.Graph=k}),define(ne[7],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IInstantiationService=e._util=void 0,e.createDecorator=I;var d;(function(E){E.serviceIds=new Map,E.DI_TARGET="$di$target",E.DI_DEPENDENCIES="$di$dependencies";function y(m){return m[E.DI_DEPENDENCIES]||[]}E.getServiceDependencies=y})(d||(e._util=d={})),e.IInstantiationService=I("instantiationService");function k(E,y,m){y[d.DI_TARGET]===y?y[d.DI_DEPENDENCIES].push({id:E,index:m}):(y[d.DI_DEPENDENCIES]=[{id:E,index:m}],y[d.DI_TARGET]=y)}function I(E){if(d.serviceIds.has(E))return d.serviceIds.get(E);const y=function(m,_,b){if(arguments.length!==3)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");k(y,m,b)};return y.toString=()=>E,d.serviceIds.set(E,y),y}}),define(ne[152],se([1,0,7,22,19]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ResourceFileEdit=e.ResourceTextEdit=e.ResourceEdit=e.IBulkEditService=void 0,e.IBulkEditService=(0,d.createDecorator)("IWorkspaceEditService");class E{constructor(b){this.metadata=b}static convert(b){return b.edits.map(p=>{if(y.is(p))return y.lift(p);if(m.is(p))return m.lift(p);throw new Error("Unsupported edit")})}}e.ResourceEdit=E;class y extends E{static is(b){return b instanceof y?!0:(0,I.isObject)(b)&&k.URI.isUri(b.resource)&&(0,I.isObject)(b.textEdit)}static lift(b){return b instanceof y?b:new y(b.resource,b.textEdit,b.versionId,b.metadata)}constructor(b,p,n=void 0,o){super(o),this.resource=b,this.textEdit=p,this.versionId=n}}e.ResourceTextEdit=y;class m extends E{static is(b){return b instanceof m?!0:(0,I.isObject)(b)&&(!!b.newResource||!!b.oldResource)}static lift(b){return b instanceof m?b:new m(b.oldResource,b.newResource,b.options,b.metadata)}constructor(b,p,n={},o){super(o),this.oldResource=b,this.newResource=p,this.options=n}}e.ResourceFileEdit=m}),define(ne[34],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ICodeEditorService=void 0,e.ICodeEditorService=(0,d.createDecorator)("codeEditorService")});var ce=this&&this.__param||function(oe,e){return function(d,k){e(d,k,oe)}};define(ne[383],se([1,0,5,114,26,57,2,21,65,30,19,112,88,55,9,4,27,3,7]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";var a;Object.defineProperty(e,"__esModule",{value:!0}),e.HideUnchangedRegionsFeature=void 0;let r=class extends y.Disposable{static{a=this}static{this._breadcrumbsSourceFactory=(0,m.observableValue)(a,()=>({dispose(){},getBreadcrumbItems(h,v){return[]}}))}static setBreadcrumbsSourceFactory(h){this._breadcrumbsSourceFactory.set(h,void 0)}get isUpdatingHiddenAreas(){return this._isUpdatingHiddenAreas}constructor(h,v,w,S){super(),this._editors=h,this._diffModel=v,this._options=w,this._instantiationService=S,this._modifiedOutlineSource=(0,_.derivedDisposable)(this,M=>{const A=this._editors.modifiedModel.read(M),P=a._breadcrumbsSourceFactory.read(M);return!A||!P?void 0:P(A,this._instantiationService)}),this._isUpdatingHiddenAreas=!1,this._register(this._editors.original.onDidChangeCursorPosition(M=>{if(M.reason===1)return;const A=this._diffModel.get();(0,m.transaction)(P=>{for(const N of this._editors.original.getSelections()||[])A?.ensureOriginalLineIsVisible(N.getStartPosition().lineNumber,0,P),A?.ensureOriginalLineIsVisible(N.getEndPosition().lineNumber,0,P)})})),this._register(this._editors.modified.onDidChangeCursorPosition(M=>{if(M.reason===1)return;const A=this._diffModel.get();(0,m.transaction)(P=>{for(const N of this._editors.modified.getSelections()||[])A?.ensureModifiedLineIsVisible(N.getStartPosition().lineNumber,0,P),A?.ensureModifiedLineIsVisible(N.getEndPosition().lineNumber,0,P)})}));const L=this._diffModel.map((M,A)=>{const P=M?.unchangedRegions.read(A)??[];return P.length===1&&P[0].modifiedLineNumber===1&&P[0].lineCount===this._editors.modifiedModel.read(A)?.getLineCount()?[]:P});this.viewZones=(0,m.derivedWithStore)(this,(M,A)=>{const P=this._modifiedOutlineSource.read(M);if(!P)return{origViewZones:[],modViewZones:[]};const N=[],O=[],F=this._options.renderSideBySide.read(M),x=this._options.compactMode.read(M),W=L.read(M);for(let V=0;Vq.getHiddenOriginalRange(U).startLineNumber-1),z=new o.PlaceholderViewZone(H,12);N.push(z),A.add(new u(this._editors.original,z,q,!F))}{const H=(0,m.derived)(this,U=>q.getHiddenModifiedRange(U).startLineNumber-1),z=new o.PlaceholderViewZone(H,12);O.push(z),A.add(new u(this._editors.modified,z,q))}}else{{const H=(0,m.derived)(this,U=>q.getHiddenOriginalRange(U).startLineNumber-1),z=new o.PlaceholderViewZone(H,24);N.push(z),A.add(new C(this._editors.original,z,q,q.originalUnchangedRange,!F,P,U=>this._diffModel.get().ensureModifiedLineIsVisible(U,2,void 0),this._options))}{const H=(0,m.derived)(this,U=>q.getHiddenModifiedRange(U).startLineNumber-1),z=new o.PlaceholderViewZone(H,24);O.push(z),A.add(new C(this._editors.modified,z,q,q.modifiedUnchangedRange,!1,P,U=>this._diffModel.get().ensureModifiedLineIsVisible(U,2,void 0),this._options))}}}return{origViewZones:N,modViewZones:O}});const D={description:"unchanged lines",className:"diff-unchanged-lines",isWholeLine:!0},T={description:"Fold Unchanged",glyphMarginHoverMessage:new E.MarkdownString(void 0,{isTrusted:!0,supportThemeIcons:!0}).appendMarkdown((0,c.localize)(111,"Fold Unchanged Region")),glyphMarginClassName:"fold-unchanged "+b.ThemeIcon.asClassName(I.Codicon.fold),zIndex:10001};this._register((0,o.applyObservableDecorations)(this._editors.original,(0,m.derived)(this,M=>{const A=L.read(M),P=A.map(N=>({range:N.originalUnchangedRange.toInclusiveRange(),options:D}));for(const N of A)N.shouldHideControls(M)&&P.push({range:s.Range.fromPositions(new i.Position(N.originalLineNumber,1)),options:T});return P}))),this._register((0,o.applyObservableDecorations)(this._editors.modified,(0,m.derived)(this,M=>{const A=L.read(M),P=A.map(N=>({range:N.modifiedUnchangedRange.toInclusiveRange(),options:D}));for(const N of A)N.shouldHideControls(M)&&P.push({range:t.LineRange.ofLength(N.modifiedLineNumber,1).toInclusiveRange(),options:T});return P}))),this._register((0,m.autorun)(M=>{const A=L.read(M);this._isUpdatingHiddenAreas=!0;try{this._editors.original.setHiddenAreas(A.map(P=>P.getHiddenOriginalRange(M).toInclusiveRange()).filter(p.isDefined)),this._editors.modified.setHiddenAreas(A.map(P=>P.getHiddenModifiedRange(M).toInclusiveRange()).filter(p.isDefined))}finally{this._isUpdatingHiddenAreas=!1}})),this._register(this._editors.modified.onMouseUp(M=>{if(!M.event.rightButton&&M.target.position&&M.target.element?.className.includes("fold-unchanged")){const A=M.target.position.lineNumber,P=this._diffModel.get();if(!P)return;const N=P.unchangedRegions.get().find(O=>O.modifiedUnchangedRange.includes(A));if(!N)return;N.collapseAll(void 0),M.event.stopPropagation(),M.event.preventDefault()}})),this._register(this._editors.original.onMouseUp(M=>{if(!M.event.rightButton&&M.target.position&&M.target.element?.className.includes("fold-unchanged")){const A=M.target.position.lineNumber,P=this._diffModel.get();if(!P)return;const N=P.unchangedRegions.get().find(O=>O.originalUnchangedRange.includes(A));if(!N)return;N.collapseAll(void 0),M.event.stopPropagation(),M.event.preventDefault()}}))}};e.HideUnchangedRegionsFeature=r,e.HideUnchangedRegionsFeature=r=a=ke([ce(3,l.IInstantiationService)],r);class u extends o.ViewZoneOverlayWidget{constructor(h,v,w,S=!1){const L=(0,d.h)("div.diff-hidden-lines-widget");super(h,v,L.root),this._unchangedRegion=w,this._hide=S,this._nodes=(0,d.h)("div.diff-hidden-lines-compact",[(0,d.h)("div.line-left",[]),(0,d.h)("div.text@text",[]),(0,d.h)("div.line-right",[])]),L.root.appendChild(this._nodes.root),this._hide&&this._nodes.root.replaceChildren(),this._register((0,m.autorun)(D=>{if(!this._hide){const T=this._unchangedRegion.getHiddenModifiedRange(D).length,M=(0,c.localize)(112,"{0} hidden lines",T);this._nodes.text.innerText=M}}))}}class C extends o.ViewZoneOverlayWidget{constructor(h,v,w,S,L,D,T,M){const A=(0,d.h)("div.diff-hidden-lines-widget");super(h,v,A.root),this._editor=h,this._unchangedRegion=w,this._unchangedRegionRange=S,this._hide=L,this._modifiedOutlineSource=D,this._revealModifiedHiddenLine=T,this._options=M,this._nodes=(0,d.h)("div.diff-hidden-lines",[(0,d.h)("div.top@top",{title:(0,c.localize)(113,"Click or drag to show more above")}),(0,d.h)("div.center@content",{style:{display:"flex"}},[(0,d.h)("div@first",{style:{display:"flex",justifyContent:"center",alignItems:"center",flexShrink:"0"}},[(0,d.$)("a",{title:(0,c.localize)(114,"Show Unchanged Region"),role:"button",onclick:()=>{this._unchangedRegion.showAll(void 0)}},...(0,k.renderLabelWithIcons)("$(unfold)"))]),(0,d.h)("div@others",{style:{display:"flex",justifyContent:"center",alignItems:"center"}})]),(0,d.h)("div.bottom@bottom",{title:(0,c.localize)(115,"Click or drag to show more below"),role:"button"})]),A.root.appendChild(this._nodes.root),this._hide?(0,d.reset)(this._nodes.first):this._register((0,o.applyStyle)(this._nodes.first,{width:(0,n.observableCodeEditor)(this._editor).layoutInfoContentLeft})),this._register((0,m.autorun)(N=>{const O=this._unchangedRegion.visibleLineCountTop.read(N)+this._unchangedRegion.visibleLineCountBottom.read(N)===this._unchangedRegion.lineCount;this._nodes.bottom.classList.toggle("canMoveTop",!O),this._nodes.bottom.classList.toggle("canMoveBottom",this._unchangedRegion.visibleLineCountBottom.read(N)>0),this._nodes.top.classList.toggle("canMoveTop",this._unchangedRegion.visibleLineCountTop.read(N)>0),this._nodes.top.classList.toggle("canMoveBottom",!O);const F=this._unchangedRegion.isDragged.read(N),x=this._editor.getDomNode();x&&(x.classList.toggle("draggingUnchangedRegion",!!F),F==="top"?(x.classList.toggle("canMoveTop",this._unchangedRegion.visibleLineCountTop.read(N)>0),x.classList.toggle("canMoveBottom",!O)):F==="bottom"?(x.classList.toggle("canMoveTop",!O),x.classList.toggle("canMoveBottom",this._unchangedRegion.visibleLineCountBottom.read(N)>0)):(x.classList.toggle("canMoveTop",!1),x.classList.toggle("canMoveBottom",!1)))}));const P=this._editor;this._register((0,d.addDisposableListener)(this._nodes.top,"mousedown",N=>{if(N.button!==0)return;this._nodes.top.classList.toggle("dragging",!0),this._nodes.root.classList.toggle("dragging",!0),N.preventDefault();const O=N.clientY;let F=!1;const x=this._unchangedRegion.visibleLineCountTop.get();this._unchangedRegion.isDragged.set("top",void 0);const W=(0,d.getWindow)(this._nodes.top),V=(0,d.addDisposableListener)(W,"mousemove",H=>{const U=H.clientY-O;F=F||Math.abs(U)>2;const j=Math.round(U/P.getOption(67)),Y=Math.max(0,Math.min(x+j,this._unchangedRegion.getMaxVisibleLineCountTop()));this._unchangedRegion.visibleLineCountTop.set(Y,void 0)}),q=(0,d.addDisposableListener)(W,"mouseup",H=>{F||this._unchangedRegion.showMoreAbove(this._options.hideUnchangedRegionsRevealLineCount.get(),void 0),this._nodes.top.classList.toggle("dragging",!1),this._nodes.root.classList.toggle("dragging",!1),this._unchangedRegion.isDragged.set(void 0,void 0),V.dispose(),q.dispose()})})),this._register((0,d.addDisposableListener)(this._nodes.bottom,"mousedown",N=>{if(N.button!==0)return;this._nodes.bottom.classList.toggle("dragging",!0),this._nodes.root.classList.toggle("dragging",!0),N.preventDefault();const O=N.clientY;let F=!1;const x=this._unchangedRegion.visibleLineCountBottom.get();this._unchangedRegion.isDragged.set("bottom",void 0);const W=(0,d.getWindow)(this._nodes.bottom),V=(0,d.addDisposableListener)(W,"mousemove",H=>{const U=H.clientY-O;F=F||Math.abs(U)>2;const j=Math.round(U/P.getOption(67)),Y=Math.max(0,Math.min(x-j,this._unchangedRegion.getMaxVisibleLineCountBottom())),G=this._unchangedRegionRange.endLineNumberExclusive>P.getModel().getLineCount()?P.getContentHeight():P.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);this._unchangedRegion.visibleLineCountBottom.set(Y,void 0);const K=this._unchangedRegionRange.endLineNumberExclusive>P.getModel().getLineCount()?P.getContentHeight():P.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);P.setScrollTop(P.getScrollTop()+(K-G))}),q=(0,d.addDisposableListener)(W,"mouseup",H=>{if(this._unchangedRegion.isDragged.set(void 0,void 0),!F){const z=P.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);this._unchangedRegion.showMoreBelow(this._options.hideUnchangedRegionsRevealLineCount.get(),void 0);const U=P.getTopForLineNumber(this._unchangedRegionRange.endLineNumberExclusive);P.setScrollTop(P.getScrollTop()+(U-z))}this._nodes.bottom.classList.toggle("dragging",!1),this._nodes.root.classList.toggle("dragging",!1),V.dispose(),q.dispose()})})),this._register((0,m.autorun)(N=>{const O=[];if(!this._hide){const F=w.getHiddenModifiedRange(N).length,x=(0,c.localize)(116,"{0} hidden lines",F),W=(0,d.$)("span",{title:(0,c.localize)(117,"Double click to unfold")},x);W.addEventListener("dblclick",H=>{H.button===0&&(H.preventDefault(),this._unchangedRegion.showAll(void 0))}),O.push(W);const V=this._unchangedRegion.getHiddenModifiedRange(N),q=this._modifiedOutlineSource.getBreadcrumbItems(V,N);if(q.length>0){O.push((0,d.$)("span",void 0,"\xA0\xA0|\xA0\xA0"));for(let H=0;H{this._revealModifiedHiddenLine(z.startLineNumber)}}}}(0,d.reset)(this._nodes.others,...O)}))}}}),define(ne[43],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ILanguageService=void 0,e.ILanguageService=(0,d.createDecorator)("languageService")}),define(ne[100],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IEditorWorkerService=void 0,e.IEditorWorkerService=(0,d.createDecorator)("editorWorkerService")}),define(ne[17],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ILanguageFeaturesService=void 0,e.ILanguageFeaturesService=(0,d.createDecorator)("ILanguageFeaturesService")}),define(ne[677],se([1,0,658,17,49]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LanguageFeaturesService=void 0;class E{constructor(){this.referenceProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.renameProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.newSymbolNamesProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.codeActionProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.definitionProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.typeDefinitionProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.declarationProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.implementationProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentSymbolProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.inlayHintsProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.colorProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.codeLensProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentFormattingEditProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentRangeFormattingEditProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.onTypeFormattingEditProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.signatureHelpProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.hoverProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentHighlightProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.multiDocumentHighlightProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.selectionRangeProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.foldingRangeProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.linkProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.inlineCompletionsProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.inlineEditProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.completionProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.linkedEditingRangeProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentRangeSemanticTokensProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentSemanticTokensProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentDropEditProvider=new d.LanguageFeatureRegistry(this._score.bind(this)),this.documentPasteEditProvider=new d.LanguageFeatureRegistry(this._score.bind(this))}_score(m){return this._notebookTypeResolver?.(m)}}e.LanguageFeaturesService=E,(0,I.registerSingleton)(k.ILanguageFeaturesService,E,1)}),define(ne[266],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IMarkerDecorationsService=void 0,e.IMarkerDecorationsService=(0,d.createDecorator)("markerDecorationsService")}),define(ne[51],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IModelService=void 0,e.IModelService=(0,d.createDecorator)("modelService")}),define(ne[78],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ITextModelService=void 0,e.ITextModelService=(0,d.createDecorator)("textModelService")}),define(ne[267],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ISemanticTokensStylingService=void 0,e.ISemanticTokensStylingService=(0,d.createDecorator)("semanticTokensStylingService")}),define(ne[211],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ITextResourcePropertiesService=e.ITextResourceConfigurationService=void 0,e.ITextResourceConfigurationService=(0,d.createDecorator)("textResourceConfigurationService"),e.ITextResourcePropertiesService=(0,d.createDecorator)("textResourcePropertiesService")}),define(ne[384],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ITreeSitterParserService=void 0,e.ITreeSitterParserService=(0,d.createDecorator)("treeSitterParserService")}),define(ne[678],se([1,0,49,7,327]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ITreeViewsDnDService=void 0,e.ITreeViewsDnDService=(0,k.createDecorator)("treeViewsDndService"),(0,d.registerSingleton)(e.ITreeViewsDnDService,I.TreeViewsDnDService,1)}),define(ne[385],se([1,0,33,2,17,130,100]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DefaultDocumentColorProvider=void 0;let m=class{constructor(p){this._editorWorkerService=p}async provideDocumentColors(p,n){return this._editorWorkerService.computeDefaultDocumentColors(p.uri)}provideColorPresentations(p,n,o){const t=n.range,i=n.color,s=i.alpha,g=new d.Color(new d.RGBA(Math.round(255*i.red),Math.round(255*i.green),Math.round(255*i.blue),s)),c=s?d.Color.Format.CSS.formatRGB(g):d.Color.Format.CSS.formatRGBA(g),l=s?d.Color.Format.CSS.formatHSL(g):d.Color.Format.CSS.formatHSLA(g),a=s?d.Color.Format.CSS.formatHex(g):d.Color.Format.CSS.formatHexA(g),r=[];return r.push({label:c,textEdit:{range:t,text:c}}),r.push({label:l,textEdit:{range:t,text:l}}),r.push({label:a,textEdit:{range:t,text:a}}),r}};e.DefaultDocumentColorProvider=m,e.DefaultDocumentColorProvider=m=ke([ce(0,y.IEditorWorkerService)],m);let _=class extends k.Disposable{constructor(p,n){super(),this._register(p.colorProvider.register("*",new m(n)))}};_=ke([ce(0,I.ILanguageFeaturesService),ce(1,y.IEditorWorkerService)],_),(0,E.registerEditorFeature)(_)}),define(ne[268],se([1,0,152,135]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.createCombinedWorkspaceEdit=I,e.sortEditsByYieldTo=E;function I(y,m,_){return(typeof _.insertText=="string"?_.insertText==="":_.insertText.snippet==="")?{edits:_.additionalEdit?.edits??[]}:{edits:[...m.map(b=>new d.ResourceTextEdit(y,{range:b,text:typeof _.insertText=="string"?k.SnippetParser.escape(_.insertText)+"$0":_.insertText.snippet,insertAsSnippet:!0})),..._.additionalEdit?.edits??[]]}}function E(y){function m(o,t){return"mimeType"in o?o.mimeType===t.handledMimeType:!!t.kind&&o.kind.contains(t.kind)}const _=new Map;for(const o of y)for(const t of o.yieldTo??[])for(const i of y)if(i!==o&&m(t,i)){let s=_.get(o);s||(s=[],_.set(o,s)),s.push(i)}if(!_.size)return Array.from(y);const b=new Set,p=[];function n(o){if(!o.length)return[];const t=o[0];if(p.includes(t))return console.warn("Yield to cycle detected",t),o;if(b.has(t))return n(o.slice(1));let i=[];const s=_.get(t);return s&&(p.push(t),i=n(s),p.pop()),b.add(t),[...i,t,...n(o.slice(1))]}return n(Array.from(y))}}),define(ne[679],se([1,0,103,6,2,21,11,74,37,9,4,116,43,40,83,150,136,204,205,517]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ttPolicy=e.AdditionalLinesWidget=e.GhostTextView=e.GHOST_TEXT_DESCRIPTION=void 0,e.GHOST_TEXT_DESCRIPTION="ghost-text";let a=class extends I.Disposable{constructor(f,h,v){super(),this.editor=f,this.model=h,this.languageService=v,this.isDisposed=(0,E.observableValue)(this,!1),this.currentTextModel=(0,E.observableFromEvent)(this,this.editor.onDidChangeModel,()=>this.editor.getModel()),this.uiState=(0,E.derived)(this,w=>{if(this.isDisposed.read(w))return;const S=this.currentTextModel.read(w);if(S!==this.model.targetTextModel.read(w))return;const L=this.model.ghostText.read(w);if(!L)return;const D=L instanceof c.GhostTextReplacement?L.columnRange:void 0,T=[],M=[];function A(x,W){if(M.length>0){const V=M[M.length-1];W&&V.decorations.push(new s.LineDecoration(V.content.length+1,V.content.length+1+x[0].length,W,0)),V.content+=x[0],x=x.slice(1)}for(const V of x)M.push({content:V,decorations:W?[new s.LineDecoration(1,V.length+1,W,0)]:[]})}const P=S.getLineContent(L.lineNumber);let N,O=0;for(const x of L.parts){let W=x.lines;N===void 0?(T.push({column:x.column,text:W[0],preview:x.preview}),W=W.slice(1)):A([P.substring(O,x.column-1)],void 0),W.length>0&&(A(W,e.GHOST_TEXT_DESCRIPTION),N===void 0&&x.column<=P.length&&(N=x.column)),O=x.column-1}N!==void 0&&A([P.substring(O)],void 0);const F=N!==void 0?new l.ColumnRange(N,P.length+1):void 0;return{replacedRange:D,inlineTexts:T,additionalLines:M,hiddenRange:F,lineNumber:L.lineNumber,additionalReservedLineCount:this.model.minReservedLineCount.read(w),targetTextModel:S}}),this.decorations=(0,E.derived)(this,w=>{const S=this.uiState.read(w);if(!S)return[];const L=[];S.replacedRange&&L.push({range:S.replacedRange.toRange(S.lineNumber),options:{inlineClassName:"inline-completion-text-to-replace",description:"GhostTextReplacement"}}),S.hiddenRange&&L.push({range:S.hiddenRange.toRange(S.lineNumber),options:{inlineClassName:"ghost-text-hidden",description:"ghost-text-hidden"}});for(const D of S.inlineTexts)L.push({range:p.Range.fromPositions(new b.Position(S.lineNumber,D.column)),options:{description:e.GHOST_TEXT_DESCRIPTION,after:{content:D.text,inlineClassName:D.preview?"ghost-text-decoration-preview":"ghost-text-decoration",cursorStops:t.InjectedTextCursorStops.Left},showIfCollapsed:!0}});return L}),this.additionalLinesWidget=this._register(new r(this.editor,this.languageService.languageIdCodec,(0,E.derived)(w=>{const S=this.uiState.read(w);return S?{lineNumber:S.lineNumber,additionalLines:S.additionalLines,minReservedLineCount:S.additionalReservedLineCount,targetTextModel:S.targetTextModel}:void 0}))),this._register((0,I.toDisposable)(()=>{this.isDisposed.set(!0,void 0)})),this._register((0,l.applyObservableDecorations)(this.editor,this.decorations))}ownsViewZone(f){return this.additionalLinesWidget.viewZoneId===f}};e.GhostTextView=a,e.GhostTextView=a=ke([ce(2,o.ILanguageService)],a);class r extends I.Disposable{get viewZoneId(){return this._viewZoneId}constructor(f,h,v){super(),this.editor=f,this.languageIdCodec=h,this.lines=v,this._viewZoneId=void 0,this.editorOptionsChanged=(0,E.observableSignalFromEvent)("editorOptionChanged",k.Event.filter(this.editor.onDidChangeConfiguration,w=>w.hasChanged(33)||w.hasChanged(118)||w.hasChanged(100)||w.hasChanged(95)||w.hasChanged(51)||w.hasChanged(50)||w.hasChanged(67))),this._register((0,E.autorun)(w=>{const S=this.lines.read(w);this.editorOptionsChanged.read(w),S?this.updateLines(S.lineNumber,S.additionalLines,S.minReservedLineCount):this.clear()}))}dispose(){super.dispose(),this.clear()}clear(){this.editor.changeViewZones(f=>{this._viewZoneId&&(f.removeZone(this._viewZoneId),this._viewZoneId=void 0)})}updateLines(f,h,v){const w=this.editor.getModel();if(!w)return;const{tabSize:S}=w.getOptions();this.editor.changeViewZones(L=>{this._viewZoneId&&(L.removeZone(this._viewZoneId),this._viewZoneId=void 0);const D=Math.max(h.length,v);if(D>0){const T=document.createElement("div");u(T,S,h,this.editor.getOptions(),this.languageIdCodec),this._viewZoneId=L.addZone({afterLineNumber:f,heightInLines:D,domNode:T,afterColumnAffinity:1})}})}}e.AdditionalLinesWidget=r;function u(C,f,h,v,w){const S=v.get(33),L=v.get(118),D="none",T=v.get(95),M=v.get(51),A=v.get(50),P=v.get(67),N=new n.StringBuilder(1e4);N.appendString('
      ');for(let x=0,W=h.length;x');const H=y.isBasicASCII(q),z=y.containsRTL(q),U=i.LineTokens.createEmpty(q,w);(0,g.renderViewLine)(new g.RenderLineInput(A.isMonospace&&!S,A.canUseHalfwidthRightwardsArrow,q,!1,H,z,0,U,V.decorations,f,0,A.spaceWidth,A.middotWidth,A.wsmiddotWidth,L,D,T,M!==_.EditorFontLigatures.OFF,null),N),N.appendString("
      ")}N.appendString(""),(0,m.applyFontInfo)(C,A);const O=N.build(),F=e.ttPolicy?e.ttPolicy.createHTML(O):O;C.innerHTML=F}e.ttPolicy=(0,d.createTrustedTypesPolicy)("editorGhostText",{createHTML:C=>C})}),define(ne[680],se([1,0,147,17,27,2,45]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TextualMultiDocumentHighlightFeature=void 0;class m{constructor(){this.selector={language:"*"}}provideDocumentHighlights(p,n,o){const t=[],i=p.getWordAtPosition({lineNumber:n.lineNumber,column:n.column});return i?p.isDisposed()?void 0:p.findMatches(i.word,!0,!1,!0,d.USUAL_WORD_SEPARATORS,!1).map(g=>({range:g.range,kind:I.DocumentHighlightKind.Text})):Promise.resolve(t)}provideMultiDocumentHighlights(p,n,o,t){const i=new y.ResourceMap,s=p.getWordAtPosition({lineNumber:n.lineNumber,column:n.column});if(!s)return Promise.resolve(i);for(const g of[p,...o]){if(g.isDisposed())continue;const l=g.findMatches(s.word,!0,!1,!0,d.USUAL_WORD_SEPARATORS,!1).map(a=>({range:a.range,kind:I.DocumentHighlightKind.Text}));l&&i.set(g.uri,l)}return i}}let _=class extends E.Disposable{constructor(p){super(),this._register(p.documentHighlightProvider.register("*",new m)),this._register(p.multiDocumentHighlightProvider.register("*",new m))}};e.TextualMultiDocumentHighlightFeature=_,e.TextualMultiDocumentHighlightFeature=_=ke([ce(0,k.ILanguageFeaturesService)],_)}),define(ne[153],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IStandaloneThemeService=void 0,e.IStandaloneThemeService=(0,d.createDecorator)("themeService")}),define(ne[137],se([1,0,3,7]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AccessibilitySignal=e.SoundSource=e.Sound=e.AcknowledgeDocCommentsToken=e.IAccessibilitySignalService=void 0,e.IAccessibilitySignalService=(0,k.createDecorator)("accessibilitySignalService"),e.AcknowledgeDocCommentsToken=Symbol("AcknowledgeDocCommentsToken");class I{static register(_){return new I(_.fileName)}static{this.error=I.register({fileName:"error.mp3"})}static{this.warning=I.register({fileName:"warning.mp3"})}static{this.success=I.register({fileName:"success.mp3"})}static{this.foldedArea=I.register({fileName:"foldedAreas.mp3"})}static{this.break=I.register({fileName:"break.mp3"})}static{this.quickFixes=I.register({fileName:"quickFixes.mp3"})}static{this.taskCompleted=I.register({fileName:"taskCompleted.mp3"})}static{this.taskFailed=I.register({fileName:"taskFailed.mp3"})}static{this.terminalBell=I.register({fileName:"terminalBell.mp3"})}static{this.diffLineInserted=I.register({fileName:"diffLineInserted.mp3"})}static{this.diffLineDeleted=I.register({fileName:"diffLineDeleted.mp3"})}static{this.diffLineModified=I.register({fileName:"diffLineModified.mp3"})}static{this.chatRequestSent=I.register({fileName:"chatRequestSent.mp3"})}static{this.chatResponseReceived1=I.register({fileName:"chatResponseReceived1.mp3"})}static{this.chatResponseReceived2=I.register({fileName:"chatResponseReceived2.mp3"})}static{this.chatResponseReceived3=I.register({fileName:"chatResponseReceived3.mp3"})}static{this.chatResponseReceived4=I.register({fileName:"chatResponseReceived4.mp3"})}static{this.clear=I.register({fileName:"clear.mp3"})}static{this.save=I.register({fileName:"save.mp3"})}static{this.format=I.register({fileName:"format.mp3"})}static{this.voiceRecordingStarted=I.register({fileName:"voiceRecordingStarted.mp3"})}static{this.voiceRecordingStopped=I.register({fileName:"voiceRecordingStopped.mp3"})}static{this.progress=I.register({fileName:"progress.mp3"})}constructor(_){this.fileName=_}}e.Sound=I;class E{constructor(_){this.randomOneOf=_}}e.SoundSource=E;class y{constructor(_,b,p,n,o,t){this.sound=_,this.name=b,this.legacySoundSettingsKey=p,this.settingsKey=n,this.legacyAnnouncementSettingsKey=o,this.announcementMessage=t}static{this._signals=new Set}static register(_){const b=new E("randomOneOf"in _.sound?_.sound.randomOneOf:[_.sound]),p=new y(b,_.name,_.legacySoundSettingsKey,_.settingsKey,_.legacyAnnouncementSettingsKey,_.announcementMessage);return y._signals.add(p),p}static{this.errorAtPosition=y.register({name:(0,d.localize)(1428,"Error at Position"),sound:I.error,announcementMessage:(0,d.localize)(1429,"Error"),settingsKey:"accessibility.signals.positionHasError",delaySettingsKey:"accessibility.signalOptions.delays.errorAtPosition"})}static{this.warningAtPosition=y.register({name:(0,d.localize)(1430,"Warning at Position"),sound:I.warning,announcementMessage:(0,d.localize)(1431,"Warning"),settingsKey:"accessibility.signals.positionHasWarning",delaySettingsKey:"accessibility.signalOptions.delays.warningAtPosition"})}static{this.errorOnLine=y.register({name:(0,d.localize)(1432,"Error on Line"),sound:I.error,legacySoundSettingsKey:"audioCues.lineHasError",legacyAnnouncementSettingsKey:"accessibility.alert.error",announcementMessage:(0,d.localize)(1433,"Error on Line"),settingsKey:"accessibility.signals.lineHasError"})}static{this.warningOnLine=y.register({name:(0,d.localize)(1434,"Warning on Line"),sound:I.warning,legacySoundSettingsKey:"audioCues.lineHasWarning",legacyAnnouncementSettingsKey:"accessibility.alert.warning",announcementMessage:(0,d.localize)(1435,"Warning on Line"),settingsKey:"accessibility.signals.lineHasWarning"})}static{this.foldedArea=y.register({name:(0,d.localize)(1436,"Folded Area on Line"),sound:I.foldedArea,legacySoundSettingsKey:"audioCues.lineHasFoldedArea",legacyAnnouncementSettingsKey:"accessibility.alert.foldedArea",announcementMessage:(0,d.localize)(1437,"Folded"),settingsKey:"accessibility.signals.lineHasFoldedArea"})}static{this.break=y.register({name:(0,d.localize)(1438,"Breakpoint on Line"),sound:I.break,legacySoundSettingsKey:"audioCues.lineHasBreakpoint",legacyAnnouncementSettingsKey:"accessibility.alert.breakpoint",announcementMessage:(0,d.localize)(1439,"Breakpoint"),settingsKey:"accessibility.signals.lineHasBreakpoint"})}static{this.inlineSuggestion=y.register({name:(0,d.localize)(1440,"Inline Suggestion on Line"),sound:I.quickFixes,legacySoundSettingsKey:"audioCues.lineHasInlineSuggestion",settingsKey:"accessibility.signals.lineHasInlineSuggestion"})}static{this.terminalQuickFix=y.register({name:(0,d.localize)(1441,"Terminal Quick Fix"),sound:I.quickFixes,legacySoundSettingsKey:"audioCues.terminalQuickFix",legacyAnnouncementSettingsKey:"accessibility.alert.terminalQuickFix",announcementMessage:(0,d.localize)(1442,"Quick Fix"),settingsKey:"accessibility.signals.terminalQuickFix"})}static{this.onDebugBreak=y.register({name:(0,d.localize)(1443,"Debugger Stopped on Breakpoint"),sound:I.break,legacySoundSettingsKey:"audioCues.onDebugBreak",legacyAnnouncementSettingsKey:"accessibility.alert.onDebugBreak",announcementMessage:(0,d.localize)(1444,"Breakpoint"),settingsKey:"accessibility.signals.onDebugBreak"})}static{this.noInlayHints=y.register({name:(0,d.localize)(1445,"No Inlay Hints on Line"),sound:I.error,legacySoundSettingsKey:"audioCues.noInlayHints",legacyAnnouncementSettingsKey:"accessibility.alert.noInlayHints",announcementMessage:(0,d.localize)(1446,"No Inlay Hints"),settingsKey:"accessibility.signals.noInlayHints"})}static{this.taskCompleted=y.register({name:(0,d.localize)(1447,"Task Completed"),sound:I.taskCompleted,legacySoundSettingsKey:"audioCues.taskCompleted",legacyAnnouncementSettingsKey:"accessibility.alert.taskCompleted",announcementMessage:(0,d.localize)(1448,"Task Completed"),settingsKey:"accessibility.signals.taskCompleted"})}static{this.taskFailed=y.register({name:(0,d.localize)(1449,"Task Failed"),sound:I.taskFailed,legacySoundSettingsKey:"audioCues.taskFailed",legacyAnnouncementSettingsKey:"accessibility.alert.taskFailed",announcementMessage:(0,d.localize)(1450,"Task Failed"),settingsKey:"accessibility.signals.taskFailed"})}static{this.terminalCommandFailed=y.register({name:(0,d.localize)(1451,"Terminal Command Failed"),sound:I.error,legacySoundSettingsKey:"audioCues.terminalCommandFailed",legacyAnnouncementSettingsKey:"accessibility.alert.terminalCommandFailed",announcementMessage:(0,d.localize)(1452,"Command Failed"),settingsKey:"accessibility.signals.terminalCommandFailed"})}static{this.terminalCommandSucceeded=y.register({name:(0,d.localize)(1453,"Terminal Command Succeeded"),sound:I.success,announcementMessage:(0,d.localize)(1454,"Command Succeeded"),settingsKey:"accessibility.signals.terminalCommandSucceeded"})}static{this.terminalBell=y.register({name:(0,d.localize)(1455,"Terminal Bell"),sound:I.terminalBell,legacySoundSettingsKey:"audioCues.terminalBell",legacyAnnouncementSettingsKey:"accessibility.alert.terminalBell",announcementMessage:(0,d.localize)(1456,"Terminal Bell"),settingsKey:"accessibility.signals.terminalBell"})}static{this.notebookCellCompleted=y.register({name:(0,d.localize)(1457,"Notebook Cell Completed"),sound:I.taskCompleted,legacySoundSettingsKey:"audioCues.notebookCellCompleted",legacyAnnouncementSettingsKey:"accessibility.alert.notebookCellCompleted",announcementMessage:(0,d.localize)(1458,"Notebook Cell Completed"),settingsKey:"accessibility.signals.notebookCellCompleted"})}static{this.notebookCellFailed=y.register({name:(0,d.localize)(1459,"Notebook Cell Failed"),sound:I.taskFailed,legacySoundSettingsKey:"audioCues.notebookCellFailed",legacyAnnouncementSettingsKey:"accessibility.alert.notebookCellFailed",announcementMessage:(0,d.localize)(1460,"Notebook Cell Failed"),settingsKey:"accessibility.signals.notebookCellFailed"})}static{this.diffLineInserted=y.register({name:(0,d.localize)(1461,"Diff Line Inserted"),sound:I.diffLineInserted,legacySoundSettingsKey:"audioCues.diffLineInserted",settingsKey:"accessibility.signals.diffLineInserted"})}static{this.diffLineDeleted=y.register({name:(0,d.localize)(1462,"Diff Line Deleted"),sound:I.diffLineDeleted,legacySoundSettingsKey:"audioCues.diffLineDeleted",settingsKey:"accessibility.signals.diffLineDeleted"})}static{this.diffLineModified=y.register({name:(0,d.localize)(1463,"Diff Line Modified"),sound:I.diffLineModified,legacySoundSettingsKey:"audioCues.diffLineModified",settingsKey:"accessibility.signals.diffLineModified"})}static{this.chatRequestSent=y.register({name:(0,d.localize)(1464,"Chat Request Sent"),sound:I.chatRequestSent,legacySoundSettingsKey:"audioCues.chatRequestSent",legacyAnnouncementSettingsKey:"accessibility.alert.chatRequestSent",announcementMessage:(0,d.localize)(1465,"Chat Request Sent"),settingsKey:"accessibility.signals.chatRequestSent"})}static{this.chatResponseReceived=y.register({name:(0,d.localize)(1466,"Chat Response Received"),legacySoundSettingsKey:"audioCues.chatResponseReceived",sound:{randomOneOf:[I.chatResponseReceived1,I.chatResponseReceived2,I.chatResponseReceived3,I.chatResponseReceived4]},settingsKey:"accessibility.signals.chatResponseReceived"})}static{this.progress=y.register({name:(0,d.localize)(1467,"Progress"),sound:I.progress,legacySoundSettingsKey:"audioCues.chatResponsePending",legacyAnnouncementSettingsKey:"accessibility.alert.progress",announcementMessage:(0,d.localize)(1468,"Progress"),settingsKey:"accessibility.signals.progress"})}static{this.clear=y.register({name:(0,d.localize)(1469,"Clear"),sound:I.clear,legacySoundSettingsKey:"audioCues.clear",legacyAnnouncementSettingsKey:"accessibility.alert.clear",announcementMessage:(0,d.localize)(1470,"Clear"),settingsKey:"accessibility.signals.clear"})}static{this.save=y.register({name:(0,d.localize)(1471,"Save"),sound:I.save,legacySoundSettingsKey:"audioCues.save",legacyAnnouncementSettingsKey:"accessibility.alert.save",announcementMessage:(0,d.localize)(1472,"Save"),settingsKey:"accessibility.signals.save"})}static{this.format=y.register({name:(0,d.localize)(1473,"Format"),sound:I.format,legacySoundSettingsKey:"audioCues.format",legacyAnnouncementSettingsKey:"accessibility.alert.format",announcementMessage:(0,d.localize)(1474,"Format"),settingsKey:"accessibility.signals.format"})}static{this.voiceRecordingStarted=y.register({name:(0,d.localize)(1475,"Voice Recording Started"),sound:I.voiceRecordingStarted,legacySoundSettingsKey:"audioCues.voiceRecordingStarted",settingsKey:"accessibility.signals.voiceRecordingStarted"})}static{this.voiceRecordingStopped=y.register({name:(0,d.localize)(1476,"Voice Recording Stopped"),sound:I.voiceRecordingStopped,legacySoundSettingsKey:"audioCues.voiceRecordingStopped",settingsKey:"accessibility.signals.voiceRecordingStopped"})}}e.AccessibilitySignal=y}),define(ne[117],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IClipboardService=void 0,e.IClipboardService=(0,d.createDecorator)("clipboardService")}),define(ne[24],se([1,0,6,53,2,73,19,7]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CommandsRegistry=e.ICommandService=void 0,e.ICommandService=(0,m.createDecorator)("commandService"),e.CommandsRegistry=new class{constructor(){this._commands=new Map,this._onDidRegisterCommand=new d.Emitter,this.onDidRegisterCommand=this._onDidRegisterCommand.event}registerCommand(_,b){if(!_)throw new Error("invalid command");if(typeof _=="string"){if(!b)throw new Error("invalid command");return this.registerCommand({id:_,handler:b})}if(_.metadata&&Array.isArray(_.metadata.args)){const i=[];for(const g of _.metadata.args)i.push(g.constraint);const s=_.handler;_.handler=function(g,...c){return(0,y.validateConstraints)(c,i),s(g,...c)}}const{id:p}=_;let n=this._commands.get(p);n||(n=new E.LinkedList,this._commands.set(p,n));const o=n.unshift(_),t=(0,I.toDisposable)(()=>{o(),this._commands.get(p)?.isEmpty()&&this._commands.delete(p)});return this._onDidRegisterCommand.fire(p),t}registerCommandAlias(_,b){return e.CommandsRegistry.registerCommand(_,(p,...n)=>p.get(e.ICommandService).executeCommand(b,...n))}getCommand(_){const b=this._commands.get(_);if(!(!b||b.isEmpty()))return k.Iterable.first(b)}getCommands(){const _=new Map;for(const b of this._commands.keys()){const p=this.getCommand(b);p&&_.set(b,p)}return _}},e.CommandsRegistry.registerCommand("noop",()=>{})}),define(ne[386],se([1,0,18,8,2,19,22,51,24,17]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CodeLensModel=void 0,e.getCodeLensModel=n;class p{constructor(){this.lenses=[],this._disposables=new I.DisposableStore}dispose(){this._disposables.dispose()}get isDisposed(){return this._disposables.isDisposed}add(t,i){this._disposables.add(t);for(const s of t.lenses)this.lenses.push({symbol:s,provider:i})}}e.CodeLensModel=p;async function n(o,t,i){const s=o.ordered(t),g=new Map,c=new p,l=s.map(async(a,r)=>{g.set(a,r);try{const u=await Promise.resolve(a.provideCodeLenses(t,i));u&&c.add(u,a)}catch(u){(0,k.onUnexpectedExternalError)(u)}});return await Promise.all(l),c.lenses=c.lenses.sort((a,r)=>a.symbol.range.startLineNumberr.symbol.range.startLineNumber?1:g.get(a.provider)g.get(r.provider)?1:a.symbol.range.startColumnr.symbol.range.startColumn?1:0),c}_.CommandsRegistry.registerCommand("_executeCodeLensProvider",function(o,...t){let[i,s]=t;(0,E.assertType)(y.URI.isUri(i)),(0,E.assertType)(typeof s=="number"||!s);const{codeLensProvider:g}=o.get(b.ILanguageFeaturesService),c=o.get(m.IModelService).getModel(i);if(!c)throw(0,k.illegalArgument)();const l=[],a=new I.DisposableStore;return n(g,c,d.CancellationToken.None).then(r=>{a.add(r);const u=[];for(const C of r.lenses)s==null||C.symbol.command?l.push(C.symbol):s-- >0&&C.provider.resolveCodeLens&&u.push(Promise.resolve(C.provider.resolveCodeLens(c,C.symbol,d.CancellationToken.None)).then(f=>l.push(f||C.symbol)));return Promise.all(u)}).then(()=>l).finally(()=>{setTimeout(()=>a.dispose(),100)})})}),define(ne[681],se([1,0,13,18,8,2,19,22,4,51,24,17]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LinksList=e.Link=void 0,e.getLinks=i;class o{constructor(g,c){this._link=g,this._provider=c}toJSON(){return{range:this.range,url:this.url,tooltip:this.tooltip}}get range(){return this._link.range}get url(){return this._link.url}get tooltip(){return this._link.tooltip}async resolve(g){return this._link.url?this._link.url:typeof this._provider.resolveLink=="function"?Promise.resolve(this._provider.resolveLink(this._link,g)).then(c=>(this._link=c||this._link,this._link.url?this.resolve(g):Promise.reject(new Error("missing")))):Promise.reject(new Error("missing"))}}e.Link=o;class t{constructor(g){this._disposables=new E.DisposableStore;let c=[];for(const[l,a]of g){const r=l.links.map(u=>new o(u,a));c=t._union(c,r),(0,E.isDisposable)(l)&&this._disposables.add(l)}this.links=c}dispose(){this._disposables.dispose(),this.links.length=0}static _union(g,c){const l=[];let a,r,u,C;for(a=0,u=0,r=g.length,C=c.length;aPromise.resolve(r.provideLinks(g,c)).then(C=>{C&&(l[u]=[C,r])},I.onUnexpectedExternalError));return Promise.all(a).then(()=>{const r=new t((0,d.coalesce)(l));return c.isCancellationRequested?(r.dispose(),new t([])):r})}p.CommandsRegistry.registerCommand("_executeLinkProvider",async(s,...g)=>{let[c,l]=g;(0,y.assertType)(c instanceof m.URI),typeof l!="number"&&(l=0);const{linkProvider:a}=s.get(n.ILanguageFeaturesService),r=s.get(b.IModelService).getModel(c);if(!r)return[];const u=await i(a,r,k.CancellationToken.None);if(!u)return[];for(let f=0;f0?h[0]:[]}async function g(C,f,h,v,w){const S=s(C,f),L=await Promise.all(S.map(async D=>{let T,M=null;try{T=await D.provideDocumentSemanticTokens(f,D===h?v:null,w)}catch(A){M=A,T=null}return(!T||!n(T)&&!o(T))&&(T=null),new t(D,T,M)}));for(const D of L){if(D.error)throw D.error;if(D.tokens)return D}return L.length>0?L[0]:null}function c(C,f){const h=C.orderedGroups(f);return h.length>0?h[0]:null}class l{constructor(f,h){this.provider=f,this.tokens=h}}function a(C,f){return C.has(f)}function r(C,f){const h=C.orderedGroups(f);return h.length>0?h[0]:[]}async function u(C,f,h,v){const w=r(C,f),S=await Promise.all(w.map(async L=>{let D;try{D=await L.provideDocumentRangeSemanticTokens(f,h,v)}catch(T){(0,k.onUnexpectedExternalError)(T),D=null}return(!D||!n(D))&&(D=null),new l(L,D)}));for(const L of S)if(L.tokens)return L;return S.length>0?S[0]:null}y.CommandsRegistry.registerCommand("_provideDocumentSemanticTokensLegend",async(C,...f)=>{const[h]=f;(0,m.assertType)(h instanceof I.URI);const v=C.get(E.IModelService).getModel(h);if(!v)return;const{documentSemanticTokensProvider:w}=C.get(p.ILanguageFeaturesService),S=c(w,v);return S?S[0].getLegend():C.get(y.ICommandService).executeCommand("_provideDocumentRangeSemanticTokensLegend",h)}),y.CommandsRegistry.registerCommand("_provideDocumentSemanticTokens",async(C,...f)=>{const[h]=f;(0,m.assertType)(h instanceof I.URI);const v=C.get(E.IModelService).getModel(h);if(!v)return;const{documentSemanticTokensProvider:w}=C.get(p.ILanguageFeaturesService);if(!i(w,v))return C.get(y.ICommandService).executeCommand("_provideDocumentRangeSemanticTokens",h,v.getFullModelRange());const S=await g(w,v,null,null,d.CancellationToken.None);if(!S)return;const{provider:L,tokens:D}=S;if(!D||!n(D))return;const T=(0,_.encodeSemanticTokensDto)({id:0,type:"full",data:D.data});return D.resultId&&L.releaseDocumentSemanticTokens(D.resultId),T}),y.CommandsRegistry.registerCommand("_provideDocumentRangeSemanticTokensLegend",async(C,...f)=>{const[h,v]=f;(0,m.assertType)(h instanceof I.URI);const w=C.get(E.IModelService).getModel(h);if(!w)return;const{documentRangeSemanticTokensProvider:S}=C.get(p.ILanguageFeaturesService),L=r(S,w);if(L.length===0)return;if(L.length===1)return L[0].getLegend();if(!v||!b.Range.isIRange(v))return console.warn("provideDocumentRangeSemanticTokensLegend might be out-of-sync with provideDocumentRangeSemanticTokens unless a range argument is passed in"),L[0].getLegend();const D=await u(S,w,b.Range.lift(v),d.CancellationToken.None);if(D)return D.provider.getLegend()}),y.CommandsRegistry.registerCommand("_provideDocumentRangeSemanticTokens",async(C,...f)=>{const[h,v]=f;(0,m.assertType)(h instanceof I.URI),(0,m.assertType)(b.Range.isIRange(v));const w=C.get(E.IModelService).getModel(h);if(!w)return;const{documentRangeSemanticTokensProvider:S}=C.get(p.ILanguageFeaturesService),L=await u(S,w,b.Range.lift(v),d.CancellationToken.None);if(!(!L||!L.tokens))return(0,_.encodeSemanticTokensDto)({id:0,type:"full",data:L.tokens.data})})}),define(ne[28],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IConfigurationService=void 0,e.toValuesTree=k,e.addToValueTree=I,e.removeFromValueTree=E,e.getConfigurationValue=m,e.getLanguageTagSettingPlainKey=_,e.IConfigurationService=(0,d.createDecorator)("configurationService");function k(b,p){const n=Object.create(null);for(const o in b)I(n,o,b[o],p);return n}function I(b,p,n,o){const t=p.split("."),i=t.pop();let s=b;for(let g=0;g"u"?n:i}function _(b){return b.replace(/[\[\]]/g,"")}}),define(ne[388],se([1,0,18,8,22,4,51,24,17,385,28]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getColors=n,e.getColorPresentations=o;async function n(l,a,r,u=!0){return g(new t,l,a,r,u)}function o(l,a,r,u){return Promise.resolve(r.provideColorPresentations(l,a,u))}class t{constructor(){}async compute(a,r,u,C){const f=await a.provideDocumentColors(r,u);if(Array.isArray(f))for(const h of f)C.push({colorInfo:h,provider:a});return Array.isArray(f)}}class i{constructor(){}async compute(a,r,u,C){const f=await a.provideDocumentColors(r,u);if(Array.isArray(f))for(const h of f)C.push({range:h.range,color:[h.color.red,h.color.green,h.color.blue,h.color.alpha]});return Array.isArray(f)}}class s{constructor(a){this.colorInfo=a}async compute(a,r,u,C){const f=await a.provideColorPresentations(r,this.colorInfo,d.CancellationToken.None);return Array.isArray(f)&&C.push(...f),Array.isArray(f)}}async function g(l,a,r,u,C){let f=!1,h;const v=[],w=a.ordered(r);for(let S=w.length-1;S>=0;S--){const L=w[S];if(L instanceof b.DefaultDocumentColorProvider)h=L;else try{await l.compute(L,r,u,v)&&(f=!0)}catch(D){(0,k.onUnexpectedExternalError)(D)}}return f?v:h&&C?(await l.compute(h,r,u,v),v):[]}function c(l,a){const{colorProvider:r}=l.get(_.ILanguageFeaturesService),u=l.get(y.IModelService).getModel(a);if(!u)throw(0,k.illegalArgument)();const C=l.get(p.IConfigurationService).getValue("editor.defaultColorDecorators",{resource:a});return{model:u,colorProviderRegistry:r,isDefaultColorDecoratorsEnabled:C}}m.CommandsRegistry.registerCommand("_executeDocumentColorProvider",function(l,...a){const[r]=a;if(!(r instanceof I.URI))throw(0,k.illegalArgument)();const{model:u,colorProviderRegistry:C,isDefaultColorDecoratorsEnabled:f}=c(l,r);return g(new i,C,u,d.CancellationToken.None,f)}),m.CommandsRegistry.registerCommand("_executeColorPresentationProvider",function(l,...a){const[r,u]=a,{uri:C,range:f}=u;if(!(C instanceof I.URI)||!Array.isArray(r)||r.length!==4||!E.Range.isIRange(f))throw(0,k.illegalArgument)();const{model:h,colorProviderRegistry:v,isDefaultColorDecoratorsEnabled:w}=c(l,C),[S,L,D,T]=r;return g(new s({range:f,color:{red:S,green:L,blue:D,alpha:T}}),v,h,d.CancellationToken.None,w)})}),define(ne[389],se([1,0,2,27,177,344,28]),function(oe,e,d,k,I,E,y){"use strict";var m;Object.defineProperty(e,"__esModule",{value:!0}),e.MonarchTokenizer=void 0;const _=5;class b{static{this._INSTANCE=new b(_)}static create(a,r){return this._INSTANCE.create(a,r)}constructor(a){this._maxCacheDepth=a,this._entries=Object.create(null)}create(a,r){if(a!==null&&a.depth>=this._maxCacheDepth)return new p(a,r);let u=p.getStackElementId(a);u.length>0&&(u+="|"),u+=r;let C=this._entries[u];return C||(C=new p(a,r),this._entries[u]=C,C)}}class p{constructor(a,r){this.parent=a,this.state=r,this.depth=(this.parent?this.parent.depth:0)+1}static getStackElementId(a){let r="";for(;a!==null;)r.length>0&&(r+="|"),r+=a.state,a=a.parent;return r}static _equals(a,r){for(;a!==null&&r!==null;){if(a===r)return!0;if(a.state!==r.state)return!1;a=a.parent,r=r.parent}return a===null&&r===null}equals(a){return p._equals(this,a)}push(a){return b.create(this,a)}pop(){return this.parent}popall(){let a=this;for(;a.parent;)a=a.parent;return a}switchTo(a){return b.create(this.parent,a)}}class n{constructor(a,r){this.languageId=a,this.state=r}equals(a){return this.languageId===a.languageId&&this.state.equals(a.state)}clone(){return this.state.clone()===this.state?this:new n(this.languageId,this.state)}}class o{static{this._INSTANCE=new o(_)}static create(a,r){return this._INSTANCE.create(a,r)}constructor(a){this._maxCacheDepth=a,this._entries=Object.create(null)}create(a,r){if(r!==null)return new t(a,r);if(a!==null&&a.depth>=this._maxCacheDepth)return new t(a,r);const u=p.getStackElementId(a);let C=this._entries[u];return C||(C=new t(a,null),this._entries[u]=C,C)}}class t{constructor(a,r){this.stack=a,this.embeddedLanguageData=r}clone(){return(this.embeddedLanguageData?this.embeddedLanguageData.clone():null)===this.embeddedLanguageData?this:o.create(this.stack,this.embeddedLanguageData)}equals(a){return!(a instanceof t)||!this.stack.equals(a.stack)?!1:this.embeddedLanguageData===null&&a.embeddedLanguageData===null?!0:this.embeddedLanguageData===null||a.embeddedLanguageData===null?!1:this.embeddedLanguageData.equals(a.embeddedLanguageData)}}class i{constructor(){this._tokens=[],this._languageId=null,this._lastTokenType=null,this._lastTokenLanguage=null}enterLanguage(a){this._languageId=a}emit(a,r){this._lastTokenType===r&&this._lastTokenLanguage===this._languageId||(this._lastTokenType=r,this._lastTokenLanguage=this._languageId,this._tokens.push(new k.Token(a,r,this._languageId)))}nestedLanguageTokenize(a,r,u,C){const f=u.languageId,h=u.state,v=k.TokenizationRegistry.get(f);if(!v)return this.enterLanguage(f),this.emit(C,""),h;const w=v.tokenize(a,r,h);if(C!==0)for(const S of w.tokens)this._tokens.push(new k.Token(S.offset+C,S.type,S.language));else this._tokens=this._tokens.concat(w.tokens);return this._lastTokenType=null,this._lastTokenLanguage=null,this._languageId=null,w.endState}finalize(a){return new k.TokenizationResult(this._tokens,a)}}class s{constructor(a,r){this._languageService=a,this._theme=r,this._prependTokens=null,this._tokens=[],this._currentLanguageId=0,this._lastTokenMetadata=0}enterLanguage(a){this._currentLanguageId=this._languageService.languageIdCodec.encodeLanguageId(a)}emit(a,r){const u=this._theme.match(this._currentLanguageId,r)|1024;this._lastTokenMetadata!==u&&(this._lastTokenMetadata=u,this._tokens.push(a),this._tokens.push(u))}static _merge(a,r,u){const C=a!==null?a.length:0,f=r.length,h=u!==null?u.length:0;if(C===0&&f===0&&h===0)return new Uint32Array(0);if(C===0&&f===0)return u;if(f===0&&h===0)return a;const v=new Uint32Array(C+f+h);a!==null&&v.set(a);for(let w=0;w{if(h)return;let w=!1;for(let S=0,L=v.changedLanguages.length;S{v.affectsConfiguration("editor.maxTokenizationLineLength")&&(this._maxTokenizationLineLength=this._configurationService.getValue("editor.maxTokenizationLineLength",{overrideIdentifier:this._languageId}))}))}getLoadStatus(){const a=[];for(const r in this._embeddedLanguages){const u=k.TokenizationRegistry.get(r);if(u){if(u instanceof m){const C=u.getLoadStatus();C.loaded===!1&&a.push(C.promise)}continue}k.TokenizationRegistry.isResolved(r)||a.push(k.TokenizationRegistry.getOrCreate(r))}return a.length===0?{loaded:!0}:{loaded:!1,promise:Promise.all(a).then(r=>{})}}getInitialState(){const a=b.create(null,this._lexer.start);return o.create(a,null)}tokenize(a,r,u){if(a.length>=this._maxTokenizationLineLength)return(0,I.nullTokenize)(this._languageId,u);const C=new i,f=this._tokenize(a,r,u,C);return C.finalize(f)}tokenizeEncoded(a,r,u){if(a.length>=this._maxTokenizationLineLength)return(0,I.nullTokenizeEncoded)(this._languageService.languageIdCodec.encodeLanguageId(this._languageId),u);const C=new s(this._languageService,this._standaloneThemeService.getColorTheme().tokenTheme),f=this._tokenize(a,r,u,C);return C.finalize(f)}_tokenize(a,r,u,C){return u.embeddedLanguageData?this._nestedTokenize(a,r,u,0,C):this._myTokenize(a,r,u,0,C)}_findLeavingNestedLanguageOffset(a,r){let u=this._lexer.tokenizer[r.stack.state];if(!u&&(u=E.findRules(this._lexer,r.stack.state),!u))throw E.createError(this._lexer,"tokenizer state is not defined: "+r.stack.state);let C=-1,f=!1;for(const h of u){if(!E.isIAction(h.action)||h.action.nextEmbedded!=="@pop")continue;f=!0;let v=h.resolveRegex(r.stack.state);const w=v.source;if(w.substr(0,4)==="^(?:"&&w.substr(w.length-1,1)===")"){const L=(v.ignoreCase?"i":"")+(v.unicode?"u":"");v=new RegExp(w.substr(4,w.length-5),L)}const S=a.search(v);S===-1||S!==0&&h.matchOnlyAtLineStart||(C===-1||S0&&f.nestedLanguageTokenize(v,!1,u.embeddedLanguageData,C);const w=a.substring(h);return this._myTokenize(w,r,u,C+h,f)}_safeRuleName(a){return a?a.name:"(unknown)"}_myTokenize(a,r,u,C,f){f.enterLanguage(this._languageId);const h=a.length,v=r&&this._lexer.includeLF?a+` `:a,w=v.length;let S=u.embeddedLanguageData,L=u.stack,D=0,T=null,M=!0;for(;M||D=w)break;M=!1;let U=this._lexer.tokenizer[O];if(!U&&(U=E.findRules(this._lexer,O),!U))throw E.createError(this._lexer,"tokenizer state is not defined: "+O);const j=v.substr(D);for(const Y of U)if((D===0||!Y.matchOnlyAtLineStart)&&(F=j.match(Y.resolveRegex(O)),F)){x=F[0],W=Y.action;break}}if(F||(F=[""],x=""),W||(D=this._lexer.maxStack)throw E.createError(this._lexer,"maximum tokenizer stack size reached: ["+L.state+","+L.parent.state+",...]");L=L.push(O)}else if(W.next==="@pop"){if(L.depth<=1)throw E.createError(this._lexer,"trying to pop an empty stack in rule: "+this._safeRuleName(V));L=L.pop()}else if(W.next==="@popall")L=L.popall();else{let U=E.substituteMatches(this._lexer,W.next,x,F,O);if(U[0]==="@"&&(U=U.substr(1)),E.findRules(this._lexer,U))L=L.push(U);else throw E.createError(this._lexer,"trying to set a next state '"+U+"' that is undefined in rule: "+this._safeRuleName(V))}}W.log&&typeof W.log=="string"&&E.log(this._lexer,this._lexer.languageId+": "+E.substituteMatches(this._lexer,W.log,x,F,O))}if(H===null)throw E.createError(this._lexer,"lexer rule has no well-defined action in rule: "+this._safeRuleName(V));const z=U=>{const j=this._languageService.getLanguageIdByLanguageName(U)||this._languageService.getLanguageIdByMimeType(U)||U,Y=this._getNestedEmbeddedLanguageData(j);if(D0)throw E.createError(this._lexer,"groups cannot be nested: "+this._safeRuleName(V));if(F.length!==H.length+1)throw E.createError(this._lexer,"matched number of groups does not match the number of actions in rule: "+this._safeRuleName(V));let U=0;for(let j=1;ji});class p{static colorizeElement(s,g,c,l){l=l||{};const a=l.theme||"vs",r=l.mimeType||c.getAttribute("lang")||c.getAttribute("data-lang");if(!r)return console.error("Mode not detected"),Promise.resolve();const u=g.getLanguageIdByMimeType(r)||r;s.setTheme(a);const C=c.firstChild?c.firstChild.nodeValue:"";c.className+=" "+a;const f=h=>{const v=b?.createHTML(h)??h;c.innerHTML=v};return this.colorize(g,C||"",u,l).then(f,h=>console.error(h))}static async colorize(s,g,c,l){const a=s.languageIdCodec;let r=4;l&&typeof l.tabSize=="number"&&(r=l.tabSize),k.startsWithUTF8BOM(g)&&(g=g.substr(1));const u=k.splitLines(g);if(!s.isRegisteredLanguageId(c))return o(u,r,a);const C=await I.TokenizationRegistry.getOrCreate(c);return C?n(u,r,C,a):o(u,r,a)}static colorizeLine(s,g,c,l,a=4){const r=m.ViewLineRenderingData.isBasicASCII(s,g),u=m.ViewLineRenderingData.containsRTL(s,r,c);return(0,y.renderViewLine2)(new y.RenderLineInput(!1,!0,s,!1,r,u,0,l,[],a,0,0,0,0,-1,"none",!1,!1,null)).html}static colorizeModelLine(s,g,c=4){const l=s.getLineContent(g);s.tokenization.forceTokenization(g);const r=s.tokenization.getLineTokens(g).inflate();return this.colorizeLine(l,s.mightContainNonBasicASCII(),s.mightContainRTL(),r,c)}}e.Colorizer=p;function n(i,s,g,c){return new Promise((l,a)=>{const r=()=>{const u=t(i,s,g,c);if(g instanceof _.MonarchTokenizer){const C=g.getLoadStatus();if(C.loaded===!1){C.promise.then(r,a);return}}l(u)};r()})}function o(i,s,g){let c=[];const a=new Uint32Array(2);a[0]=0,a[1]=33587200;for(let r=0,u=i.length;r")}return c.join("")}function t(i,s,g,c){let l=[],a=g.getInitialState();for(let r=0,u=i.length;r"),a=f.endState}return l.join("")}}),define(ne[12],se([1,0,16,11,672,7,3]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IContextKeyService=e.RawContextKey=e.ContextKeyOrExpr=e.ContextKeyAndExpr=e.ContextKeyNotRegexExpr=e.ContextKeyRegexExpr=e.ContextKeySmallerEqualsExpr=e.ContextKeySmallerExpr=e.ContextKeyGreaterEqualsExpr=e.ContextKeyGreaterExpr=e.ContextKeyNotExpr=e.ContextKeyNotEqualsExpr=e.ContextKeyNotInExpr=e.ContextKeyInExpr=e.ContextKeyEqualsExpr=e.ContextKeyDefinedExpr=e.ContextKeyTrueExpr=e.ContextKeyFalseExpr=e.ContextKeyExpr=e.Parser=void 0,e.expressionsAreEqualWithConstantSubstitution=r,e.implies=U;const m=new Map;m.set("false",!1),m.set("true",!0),m.set("isMac",d.isMacintosh),m.set("isLinux",d.isLinux),m.set("isWindows",d.isWindows),m.set("isWeb",d.isWeb),m.set("isMacNative",d.isMacintosh&&!d.isWeb),m.set("isEdge",d.isEdge),m.set("isFirefox",d.isFirefox),m.set("isChrome",d.isChrome),m.set("isSafari",d.isSafari);const _=Object.prototype.hasOwnProperty,b={regexParsingWithErrorRecovery:!0},p=(0,y.localize)(1514,"Empty context key expression"),n=(0,y.localize)(1515,"Did you forget to write an expression? You can also put 'false' or 'true' to always evaluate to false or true, respectively."),o=(0,y.localize)(1516,"'in' after 'not'."),t=(0,y.localize)(1517,"closing parenthesis ')'"),i=(0,y.localize)(1518,"Unexpected token"),s=(0,y.localize)(1519,"Did you forget to put && or || before the token?"),g=(0,y.localize)(1520,"Unexpected end of expression"),c=(0,y.localize)(1521,"Did you forget to put a context key?");class l{static{this._parseError=new Error}constructor(K=b){this._config=K,this._scanner=new I.Scanner,this._tokens=[],this._current=0,this._parsingErrors=[],this._flagsGYRe=/g|y/g}parse(K){if(K===""){this._parsingErrors.push({message:p,offset:0,lexeme:"",additionalInfo:n});return}this._tokens=this._scanner.reset(K).scan(),this._current=0,this._parsingErrors=[];try{const R=this._expr();if(!this._isAtEnd()){const J=this._peek(),ie=J.type===17?s:void 0;throw this._parsingErrors.push({message:i,offset:J.offset,lexeme:I.Scanner.getLexeme(J),additionalInfo:ie}),l._parseError}return R}catch(R){if(R!==l._parseError)throw R;return}}_expr(){return this._or()}_or(){const K=[this._and()];for(;this._matchOne(16);){const R=this._and();K.push(R)}return K.length===1?K[0]:a.or(...K)}_and(){const K=[this._term()];for(;this._matchOne(15);){const R=this._term();K.push(R)}return K.length===1?K[0]:a.and(...K)}_term(){if(this._matchOne(2)){const K=this._peek();switch(K.type){case 11:return this._advance(),C.INSTANCE;case 12:return this._advance(),f.INSTANCE;case 0:{this._advance();const R=this._expr();return this._consume(1,t),R?.negate()}case 17:return this._advance(),D.create(K.lexeme);default:throw this._errExpectedButGot("KEY | true | false | '(' expression ')'",K)}}return this._primary()}_primary(){const K=this._peek();switch(K.type){case 11:return this._advance(),a.true();case 12:return this._advance(),a.false();case 0:{this._advance();const R=this._expr();return this._consume(1,t),R}case 17:{const R=K.lexeme;if(this._advance(),this._matchOne(9)){const ie=this._peek();if(!this._config.regexParsingWithErrorRecovery){if(this._advance(),ie.type!==10)throw this._errExpectedButGot("REGEX",ie);const ue=ie.lexeme,he=ue.lastIndexOf("/"),pe=he===ue.length-1?void 0:this._removeFlagsGY(ue.substring(he+1));let ae;try{ae=new RegExp(ue.substring(1,he),pe)}catch{throw this._errExpectedButGot("REGEX",ie)}return O.create(R,ae)}switch(ie.type){case 10:case 19:{const ue=[ie.lexeme];this._advance();let he=this._peek(),pe=0;for(let X=0;X=0){const ee=ue.slice(pe+1,ae),de=ue[ae+1]==="i"?"i":"";try{he=new RegExp(ee,de)}catch{throw this._errExpectedButGot("REGEX",ie)}}}if(he===null)throw this._errExpectedButGot("REGEX",ie);return O.create(R,he)}default:throw this._errExpectedButGot("REGEX",this._peek())}}if(this._matchOne(14)){this._consume(13,o);const ie=this._value();return a.notIn(R,ie)}switch(this._peek().type){case 3:{this._advance();const ie=this._value();if(this._previous().type===18)return a.equals(R,ie);switch(ie){case"true":return a.has(R);case"false":return a.not(R);default:return a.equals(R,ie)}}case 4:{this._advance();const ie=this._value();if(this._previous().type===18)return a.notEquals(R,ie);switch(ie){case"true":return a.not(R);case"false":return a.has(R);default:return a.notEquals(R,ie)}}case 5:return this._advance(),P.create(R,this._value());case 6:return this._advance(),N.create(R,this._value());case 7:return this._advance(),M.create(R,this._value());case 8:return this._advance(),A.create(R,this._value());case 13:return this._advance(),a.in(R,this._value());default:return a.has(R)}}case 20:throw this._parsingErrors.push({message:g,offset:K.offset,lexeme:"",additionalInfo:c}),l._parseError;default:throw this._errExpectedButGot(`true | false | KEY | KEY '=~' REGEX | KEY ('==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'not' 'in') value`,this._peek())}}_value(){const K=this._peek();switch(K.type){case 17:case 18:return this._advance(),K.lexeme;case 11:return this._advance(),"true";case 12:return this._advance(),"false";case 13:return this._advance(),"in";default:return""}}_removeFlagsGY(K){return K.replaceAll(this._flagsGYRe,"")}_previous(){return this._tokens[this._current-1]}_matchOne(K){return this._check(K)?(this._advance(),!0):!1}_advance(){return this._isAtEnd()||this._current++,this._previous()}_consume(K,R){if(this._check(K))return this._advance();throw this._errExpectedButGot(R,this._peek())}_errExpectedButGot(K,R,J){const ie=(0,y.localize)(1522,`Expected: {0} Received: '{1}'.`,K,I.Scanner.getLexeme(R)),ue=R.offset,he=I.Scanner.getLexeme(R);return this._parsingErrors.push({message:ie,offset:ue,lexeme:he,additionalInfo:J}),l._parseError}_check(K){return this._peek().type===K}_peek(){return this._tokens[this._current]}_isAtEnd(){return this._peek().type===20}}e.Parser=l;class a{static false(){return C.INSTANCE}static true(){return f.INSTANCE}static has(K){return h.create(K)}static equals(K,R){return v.create(K,R)}static notEquals(K,R){return L.create(K,R)}static regex(K,R){return O.create(K,R)}static in(K,R){return w.create(K,R)}static notIn(K,R){return S.create(K,R)}static not(K){return D.create(K)}static and(...K){return W.create(K,null,!0)}static or(...K){return V.create(K,null,!0)}static{this._parser=new l({regexParsingWithErrorRecovery:!1})}static deserialize(K){return K==null?void 0:this._parser.parse(K)}}e.ContextKeyExpr=a;function r(G,K){const R=G?G.substituteConstants():void 0,J=K?K.substituteConstants():void 0;return!R&&!J?!0:!R||!J?!1:R.equals(J)}function u(G,K){return G.cmp(K)}class C{static{this.INSTANCE=new C}constructor(){this.type=0}cmp(K){return this.type-K.type}equals(K){return K.type===this.type}substituteConstants(){return this}evaluate(K){return!1}serialize(){return"false"}keys(){return[]}negate(){return f.INSTANCE}}e.ContextKeyFalseExpr=C;class f{static{this.INSTANCE=new f}constructor(){this.type=1}cmp(K){return this.type-K.type}equals(K){return K.type===this.type}substituteConstants(){return this}evaluate(K){return!0}serialize(){return"true"}keys(){return[]}negate(){return C.INSTANCE}}e.ContextKeyTrueExpr=f;class h{static create(K,R=null){const J=m.get(K);return typeof J=="boolean"?J?f.INSTANCE:C.INSTANCE:new h(K,R)}constructor(K,R){this.key=K,this.negated=R,this.type=2}cmp(K){return K.type!==this.type?this.type-K.type:H(this.key,K.key)}equals(K){return K.type===this.type?this.key===K.key:!1}substituteConstants(){const K=m.get(this.key);return typeof K=="boolean"?K?f.INSTANCE:C.INSTANCE:this}evaluate(K){return!!K.getValue(this.key)}serialize(){return this.key}keys(){return[this.key]}negate(){return this.negated||(this.negated=D.create(this.key,this)),this.negated}}e.ContextKeyDefinedExpr=h;class v{static create(K,R,J=null){if(typeof R=="boolean")return R?h.create(K,J):D.create(K,J);const ie=m.get(K);return typeof ie=="boolean"?R===(ie?"true":"false")?f.INSTANCE:C.INSTANCE:new v(K,R,J)}constructor(K,R,J){this.key=K,this.value=R,this.negated=J,this.type=4}cmp(K){return K.type!==this.type?this.type-K.type:z(this.key,this.value,K.key,K.value)}equals(K){return K.type===this.type?this.key===K.key&&this.value===K.value:!1}substituteConstants(){const K=m.get(this.key);if(typeof K=="boolean"){const R=K?"true":"false";return this.value===R?f.INSTANCE:C.INSTANCE}return this}evaluate(K){return K.getValue(this.key)==this.value}serialize(){return`${this.key} == '${this.value}'`}keys(){return[this.key]}negate(){return this.negated||(this.negated=L.create(this.key,this.value,this)),this.negated}}e.ContextKeyEqualsExpr=v;class w{static create(K,R){return new w(K,R)}constructor(K,R){this.key=K,this.valueKey=R,this.type=10,this.negated=null}cmp(K){return K.type!==this.type?this.type-K.type:z(this.key,this.valueKey,K.key,K.valueKey)}equals(K){return K.type===this.type?this.key===K.key&&this.valueKey===K.valueKey:!1}substituteConstants(){return this}evaluate(K){const R=K.getValue(this.valueKey),J=K.getValue(this.key);return Array.isArray(R)?R.includes(J):typeof J=="string"&&typeof R=="object"&&R!==null?_.call(R,J):!1}serialize(){return`${this.key} in '${this.valueKey}'`}keys(){return[this.key,this.valueKey]}negate(){return this.negated||(this.negated=S.create(this.key,this.valueKey)),this.negated}}e.ContextKeyInExpr=w;class S{static create(K,R){return new S(K,R)}constructor(K,R){this.key=K,this.valueKey=R,this.type=11,this._negated=w.create(K,R)}cmp(K){return K.type!==this.type?this.type-K.type:this._negated.cmp(K._negated)}equals(K){return K.type===this.type?this._negated.equals(K._negated):!1}substituteConstants(){return this}evaluate(K){return!this._negated.evaluate(K)}serialize(){return`${this.key} not in '${this.valueKey}'`}keys(){return this._negated.keys()}negate(){return this._negated}}e.ContextKeyNotInExpr=S;class L{static create(K,R,J=null){if(typeof R=="boolean")return R?D.create(K,J):h.create(K,J);const ie=m.get(K);return typeof ie=="boolean"?R===(ie?"true":"false")?C.INSTANCE:f.INSTANCE:new L(K,R,J)}constructor(K,R,J){this.key=K,this.value=R,this.negated=J,this.type=5}cmp(K){return K.type!==this.type?this.type-K.type:z(this.key,this.value,K.key,K.value)}equals(K){return K.type===this.type?this.key===K.key&&this.value===K.value:!1}substituteConstants(){const K=m.get(this.key);if(typeof K=="boolean"){const R=K?"true":"false";return this.value===R?C.INSTANCE:f.INSTANCE}return this}evaluate(K){return K.getValue(this.key)!=this.value}serialize(){return`${this.key} != '${this.value}'`}keys(){return[this.key]}negate(){return this.negated||(this.negated=v.create(this.key,this.value,this)),this.negated}}e.ContextKeyNotEqualsExpr=L;class D{static create(K,R=null){const J=m.get(K);return typeof J=="boolean"?J?C.INSTANCE:f.INSTANCE:new D(K,R)}constructor(K,R){this.key=K,this.negated=R,this.type=3}cmp(K){return K.type!==this.type?this.type-K.type:H(this.key,K.key)}equals(K){return K.type===this.type?this.key===K.key:!1}substituteConstants(){const K=m.get(this.key);return typeof K=="boolean"?K?C.INSTANCE:f.INSTANCE:this}evaluate(K){return!K.getValue(this.key)}serialize(){return`!${this.key}`}keys(){return[this.key]}negate(){return this.negated||(this.negated=h.create(this.key,this)),this.negated}}e.ContextKeyNotExpr=D;function T(G,K){if(typeof G=="string"){const R=parseFloat(G);isNaN(R)||(G=R)}return typeof G=="string"||typeof G=="number"?K(G):C.INSTANCE}class M{static create(K,R,J=null){return T(R,ie=>new M(K,ie,J))}constructor(K,R,J){this.key=K,this.value=R,this.negated=J,this.type=12}cmp(K){return K.type!==this.type?this.type-K.type:z(this.key,this.value,K.key,K.value)}equals(K){return K.type===this.type?this.key===K.key&&this.value===K.value:!1}substituteConstants(){return this}evaluate(K){return typeof this.value=="string"?!1:parseFloat(K.getValue(this.key))>this.value}serialize(){return`${this.key} > ${this.value}`}keys(){return[this.key]}negate(){return this.negated||(this.negated=N.create(this.key,this.value,this)),this.negated}}e.ContextKeyGreaterExpr=M;class A{static create(K,R,J=null){return T(R,ie=>new A(K,ie,J))}constructor(K,R,J){this.key=K,this.value=R,this.negated=J,this.type=13}cmp(K){return K.type!==this.type?this.type-K.type:z(this.key,this.value,K.key,K.value)}equals(K){return K.type===this.type?this.key===K.key&&this.value===K.value:!1}substituteConstants(){return this}evaluate(K){return typeof this.value=="string"?!1:parseFloat(K.getValue(this.key))>=this.value}serialize(){return`${this.key} >= ${this.value}`}keys(){return[this.key]}negate(){return this.negated||(this.negated=P.create(this.key,this.value,this)),this.negated}}e.ContextKeyGreaterEqualsExpr=A;class P{static create(K,R,J=null){return T(R,ie=>new P(K,ie,J))}constructor(K,R,J){this.key=K,this.value=R,this.negated=J,this.type=14}cmp(K){return K.type!==this.type?this.type-K.type:z(this.key,this.value,K.key,K.value)}equals(K){return K.type===this.type?this.key===K.key&&this.value===K.value:!1}substituteConstants(){return this}evaluate(K){return typeof this.value=="string"?!1:parseFloat(K.getValue(this.key))new N(K,ie,J))}constructor(K,R,J){this.key=K,this.value=R,this.negated=J,this.type=15}cmp(K){return K.type!==this.type?this.type-K.type:z(this.key,this.value,K.key,K.value)}equals(K){return K.type===this.type?this.key===K.key&&this.value===K.value:!1}substituteConstants(){return this}evaluate(K){return typeof this.value=="string"?!1:parseFloat(K.getValue(this.key))<=this.value}serialize(){return`${this.key} <= ${this.value}`}keys(){return[this.key]}negate(){return this.negated||(this.negated=M.create(this.key,this.value,this)),this.negated}}e.ContextKeySmallerEqualsExpr=N;class O{static create(K,R){return new O(K,R)}constructor(K,R){this.key=K,this.regexp=R,this.type=7,this.negated=null}cmp(K){if(K.type!==this.type)return this.type-K.type;if(this.keyK.key)return 1;const R=this.regexp?this.regexp.source:"",J=K.regexp?K.regexp.source:"";return RJ?1:0}equals(K){if(K.type===this.type){const R=this.regexp?this.regexp.source:"",J=K.regexp?K.regexp.source:"";return this.key===K.key&&R===J}return!1}substituteConstants(){return this}evaluate(K){const R=K.getValue(this.key);return this.regexp?this.regexp.test(R):!1}serialize(){const K=this.regexp?`/${this.regexp.source}/${this.regexp.flags}`:"/invalid/";return`${this.key} =~ ${K}`}keys(){return[this.key]}negate(){return this.negated||(this.negated=F.create(this)),this.negated}}e.ContextKeyRegexExpr=O;class F{static create(K){return new F(K)}constructor(K){this._actual=K,this.type=8}cmp(K){return K.type!==this.type?this.type-K.type:this._actual.cmp(K._actual)}equals(K){return K.type===this.type?this._actual.equals(K._actual):!1}substituteConstants(){return this}evaluate(K){return!this._actual.evaluate(K)}serialize(){return`!(${this._actual.serialize()})`}keys(){return this._actual.keys()}negate(){return this._actual}}e.ContextKeyNotRegexExpr=F;function x(G){let K=null;for(let R=0,J=G.length;RK.expr.length)return 1;for(let R=0,J=this.expr.length;R1;){const he=ie[ie.length-1];if(he.type!==9)break;ie.pop();const pe=ie.pop(),ae=ie.length===0,ee=V.create(he.expr.map(de=>W.create([de,pe],null,J)),null,ae);ee&&(ie.push(ee),ie.sort(u))}if(ie.length===1)return ie[0];if(J){for(let he=0;heK.serialize()).join(" && ")}keys(){const K=[];for(const R of this.expr)K.push(...R.keys());return K}negate(){if(!this.negated){const K=[];for(const R of this.expr)K.push(R.negate());this.negated=V.create(K,this,!0)}return this.negated}}e.ContextKeyAndExpr=W;class V{static create(K,R,J){return V._normalizeArr(K,R,J)}constructor(K,R){this.expr=K,this.negated=R,this.type=9}cmp(K){if(K.type!==this.type)return this.type-K.type;if(this.expr.lengthK.expr.length)return 1;for(let R=0,J=this.expr.length;RK.serialize()).join(" || ")}keys(){const K=[];for(const R of this.expr)K.push(...R.keys());return K}negate(){if(!this.negated){const K=[];for(const R of this.expr)K.push(R.negate());for(;K.length>1;){const R=K.shift(),J=K.shift(),ie=[];for(const ue of Y(R))for(const he of Y(J))ie.push(W.create([ue,he],null,!1));K.unshift(V.create(ie,null,!1))}this.negated=V.create(K,this,!0)}return this.negated}}e.ContextKeyOrExpr=V;class q extends h{static{this._info=[]}static all(){return q._info.values()}constructor(K,R,J){super(K,null),this._defaultValue=R,typeof J=="object"?q._info.push({...J,key:K}):J!==!0&&q._info.push({key:K,description:J,type:R!=null?typeof R:void 0})}bindTo(K){return K.createKey(this.key,this._defaultValue)}getValue(K){return K.getContextKeyValue(this.key)}toNegated(){return this.negate()}isEqualTo(K){return v.create(this.key,K)}}e.RawContextKey=q,e.IContextKeyService=(0,E.createDecorator)("contextKeyService");function H(G,K){return GK?1:0}function z(G,K,R,J){return GR?1:KJ?1:0}function U(G,K){if(G.type===0||K.type===1)return!0;if(G.type===9)return K.type===9?j(G.expr,K.expr):!1;if(K.type===9){for(const R of K.expr)if(U(G,R))return!0;return!1}if(G.type===6){if(K.type===6)return j(K.expr,G.expr);for(const R of G.expr)if(U(R,K))return!0;return!1}return G.equals(K)}function j(G,K){let R=0,J=0;for(;R{const i=this.model.read(o)?.state.read(o),s=!!i?.inlineCompletion&&i?.primaryGhostText!==void 0&&!i?.primaryGhostText.isEmpty();this.inlineCompletionVisible.set(s),i?.primaryGhostText&&i?.inlineCompletion&&this.suppressSuggestions.set(i.inlineCompletion.inlineCompletion.source.inlineCompletions.suppressSuggestions)})),this._register((0,d.autorun)(o=>{const t=this.model.read(o);let i=!1,s=!0;const g=t?.primaryGhostText.read(o);if(t?.selectedSuggestItem&&g&&g.parts.length>0){const{column:c,lines:l}=g.parts[0],a=l[0],r=t.textModel.getLineIndentColumn(g.lineNumber);if(c<=r){let C=(0,k.firstNonWhitespaceIndex)(a);C===-1&&(C=a.length-1),i=C>0;const f=t.textModel.getOptions().tabSize;s=I.CursorColumns.visibleColumnFromColumn(a,C+1,f){const[s,g,c]=i;(0,I.assertType)(E.URI.isUri(s)),(0,I.assertType)(y.Position.isIPosition(g)),(0,I.assertType)(typeof c=="string"||!c);const l=t.get(_.ILanguageFeaturesService),a=await t.get(b.ITextModelService).createModelReference(s);try{const r=await o(l.signatureHelpProvider,a.object.textEditorModel,y.Position.lift(g),{triggerKind:m.SignatureHelpTriggerKind.Invoke,isRetrigger:!1,triggerCharacter:c},d.CancellationToken.None);return r?(setTimeout(()=>r.dispose(),0),r.value):void 0}finally{a.dispose()}})}),define(ne[683],se([1,0,14,8,6,2,144,27,270]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ParameterHintsModel=void 0;var b;(function(o){o.Default={type:0};class t{constructor(g,c){this.request=g,this.previouslyActiveHints=c,this.type=2}}o.Pending=t;class i{constructor(g){this.hints=g,this.type=1}}o.Active=i})(b||(b={}));class p extends E.Disposable{static{this.DEFAULT_DELAY=120}constructor(t,i,s=p.DEFAULT_DELAY){super(),this._onChangedHints=this._register(new I.Emitter),this.onChangedHints=this._onChangedHints.event,this.triggerOnType=!1,this._state=b.Default,this._pendingTriggers=[],this._lastSignatureHelpResult=this._register(new E.MutableDisposable),this.triggerChars=new y.CharacterSet,this.retriggerChars=new y.CharacterSet,this.triggerId=0,this.editor=t,this.providers=i,this.throttledDelayer=new d.Delayer(s),this._register(this.editor.onDidBlurEditorWidget(()=>this.cancel())),this._register(this.editor.onDidChangeConfiguration(()=>this.onEditorConfigurationChange())),this._register(this.editor.onDidChangeModel(g=>this.onModelChanged())),this._register(this.editor.onDidChangeModelLanguage(g=>this.onModelChanged())),this._register(this.editor.onDidChangeCursorSelection(g=>this.onCursorChange(g))),this._register(this.editor.onDidChangeModelContent(g=>this.onModelContentChange())),this._register(this.providers.onDidChange(this.onModelChanged,this)),this._register(this.editor.onDidType(g=>this.onDidType(g))),this.onEditorConfigurationChange(),this.onModelChanged()}get state(){return this._state}set state(t){this._state.type===2&&this._state.request.cancel(),this._state=t}cancel(t=!1){this.state=b.Default,this.throttledDelayer.cancel(),t||this._onChangedHints.fire(void 0)}trigger(t,i){const s=this.editor.getModel();if(!s||!this.providers.has(s))return;const g=++this.triggerId;this._pendingTriggers.push(t),this.throttledDelayer.trigger(()=>this.doTrigger(g),i).catch(k.onUnexpectedError)}next(){if(this.state.type!==1)return;const t=this.state.hints.signatures.length,i=this.state.hints.activeSignature,s=i%t===t-1,g=this.editor.getOption(86).cycle;if((t<2||s)&&!g){this.cancel();return}this.updateActiveSignature(s&&g?0:i+1)}previous(){if(this.state.type!==1)return;const t=this.state.hints.signatures.length,i=this.state.hints.activeSignature,s=i===0,g=this.editor.getOption(86).cycle;if((t<2||s)&&!g){this.cancel();return}this.updateActiveSignature(s&&g?t-1:i-1)}updateActiveSignature(t){this.state.type===1&&(this.state=new b.Active({...this.state.hints,activeSignature:t}),this._onChangedHints.fire(this.state.hints))}async doTrigger(t){const i=this.state.type===1||this.state.type===2,s=this.getLastActiveHints();if(this.cancel(!0),this._pendingTriggers.length===0)return!1;const g=this._pendingTriggers.reduce(n);this._pendingTriggers=[];const c={triggerKind:g.triggerKind,triggerCharacter:g.triggerCharacter,isRetrigger:i,activeSignatureHelp:s};if(!this.editor.hasModel())return!1;const l=this.editor.getModel(),a=this.editor.getPosition();this.state=new b.Pending((0,d.createCancelablePromise)(r=>(0,_.provideSignatureHelp)(this.providers,l,a,c,r)),s);try{const r=await this.state.request;return t!==this.triggerId?(r?.dispose(),!1):!r||!r.value.signatures||r.value.signatures.length===0?(r?.dispose(),this._lastSignatureHelpResult.clear(),this.cancel(),!1):(this.state=new b.Active(r.value),this._lastSignatureHelpResult.value=r,this._onChangedHints.fire(this.state.hints),!0)}catch(r){return t===this.triggerId&&(this.state=b.Default),(0,k.onUnexpectedError)(r),!1}}getLastActiveHints(){switch(this.state.type){case 1:return this.state.hints;case 2:return this.state.previouslyActiveHints;default:return}}get isTriggered(){return this.state.type===1||this.state.type===2||this.throttledDelayer.isTriggered()}onModelChanged(){this.cancel(),this.triggerChars.clear(),this.retriggerChars.clear();const t=this.editor.getModel();if(t)for(const i of this.providers.ordered(t)){for(const s of i.signatureHelpTriggerCharacters||[])if(s.length){const g=s.charCodeAt(0);this.triggerChars.add(g),this.retriggerChars.add(g)}for(const s of i.signatureHelpRetriggerCharacters||[])s.length&&this.retriggerChars.add(s.charCodeAt(0))}}onDidType(t){if(!this.triggerOnType)return;const i=t.length-1,s=t.charCodeAt(i);(this.triggerChars.has(s)||this.isTriggered&&this.retriggerChars.has(s))&&this.trigger({triggerKind:m.SignatureHelpTriggerKind.TriggerCharacter,triggerCharacter:t.charAt(i)})}onCursorChange(t){t.source==="mouse"?this.cancel():this.isTriggered&&this.trigger({triggerKind:m.SignatureHelpTriggerKind.ContentChange})}onModelContentChange(){this.isTriggered&&this.trigger({triggerKind:m.SignatureHelpTriggerKind.ContentChange})}onEditorConfigurationChange(){this.triggerOnType=this.editor.getOption(86).enabled,this.triggerOnType||this.cancel()}dispose(){this.cancel(!0),super.dispose()}}e.ParameterHintsModel=p;function n(o,t){switch(t.triggerKind){case m.SignatureHelpTriggerKind.Invoke:return t;case m.SignatureHelpTriggerKind.ContentChange:return o;case m.SignatureHelpTriggerKind.TriggerCharacter:default:return t}}}),define(ne[684],se([1,0,12]),function(oe,e,d){"use strict";var k;Object.defineProperty(e,"__esModule",{value:!0}),e.SuggestAlternatives=void 0;let I=class{static{k=this}static{this.OtherSuggestions=new d.RawContextKey("hasOtherSuggestions",!1)}constructor(y,m){this._editor=y,this._index=0,this._ckOtherSuggestions=k.OtherSuggestions.bindTo(m)}dispose(){this.reset()}reset(){this._ckOtherSuggestions.reset(),this._listener?.dispose(),this._model=void 0,this._acceptNext=void 0,this._ignore=!1}set({model:y,index:m},_){if(y.items.length===0){this.reset();return}if(k._moveIndex(!0,y,m)===m){this.reset();return}this._acceptNext=_,this._model=y,this._index=m,this._listener=this._editor.onDidChangeCursorPosition(()=>{this._ignore||this.reset()}),this._ckOtherSuggestions.set(!0)}static _moveIndex(y,m,_){let b=_;for(let p=m.items.length;p>0&&(b=(b+m.items.length+(y?1:-1))%m.items.length,!(b===_||!m.items[b].completion.additionalTextEdits));p--);return b}next(){this._move(!0)}prev(){this._move(!1)}_move(y){if(this._model)try{this._ignore=!0,this._index=k._moveIndex(y,this._model,this._index),this._acceptNext({index:this._index,item:this._model.items[this._index],model:this._model})}finally{this._ignore=!1}}};e.SuggestAlternatives=I,e.SuggestAlternatives=I=k=ke([ce(1,d.IContextKeyService)],I)}),define(ne[685],se([1,0,12]),function(oe,e,d){"use strict";var k;Object.defineProperty(e,"__esModule",{value:!0}),e.WordContextKey=void 0;let I=class{static{k=this}static{this.AtEnd=new d.RawContextKey("atEndOfWord",!1)}constructor(y,m){this._editor=y,this._enabled=!1,this._ckAtEnd=k.AtEnd.bindTo(m),this._configListener=this._editor.onDidChangeConfiguration(_=>_.hasChanged(124)&&this._update()),this._update()}dispose(){this._configListener.dispose(),this._selectionListener?.dispose(),this._ckAtEnd.reset()}_update(){const y=this._editor.getOption(124)==="on";if(this._enabled!==y)if(this._enabled=y,this._enabled){const m=()=>{if(!this._editor.hasModel()){this._ckAtEnd.set(!1);return}const _=this._editor.getModel(),b=this._editor.getSelection(),p=_.getWordAtPosition(b.getStartPosition());if(!p){this._ckAtEnd.set(!1);return}this._ckAtEnd.set(p.endColumn===b.getStartPosition().column)};this._selectionListener=this._editor.onDidChangeCursorSelection(m),m()}else this._selectionListener&&(this._ckAtEnd.reset(),this._selectionListener.dispose(),this._selectionListener=void 0)}};e.WordContextKey=I,e.WordContextKey=I=k=ke([ce(1,d.IContextKeyService)],I)}),define(ne[61],se([1,0,12,7]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CONTEXT_ACCESSIBILITY_MODE_ENABLED=e.IAccessibilityService=void 0,e.IAccessibilityService=(0,k.createDecorator)("accessibilityService"),e.CONTEXT_ACCESSIBILITY_MODE_ENABLED=new d.RawContextKey("accessibilityModeEnabled",!1)}),define(ne[686],se([1,0,64,13,6,2,60,16,362,366,546,229,37,165,261,61,5,253]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ComputedEditorOptions=e.EditorConfiguration=void 0;let l=class extends E.Disposable{constructor(w,S,L,D,T){super(),this._accessibilityService=T,this._onDidChange=this._register(new I.Emitter),this.onDidChange=this._onDidChange.event,this._onDidChangeFast=this._register(new I.Emitter),this.onDidChangeFast=this._onDidChangeFast.event,this._isDominatedByLongLines=!1,this._viewLineCount=1,this._lineNumbersDigitCount=1,this._reservedHeight=0,this._glyphMarginDecorationLaneCount=1,this._computeOptionsMemory=new o.ComputeOptionsMemory,this.isSimpleWidget=w,this.contextMenuId=S,this._containerObserver=this._register(new _.ElementSizeObserver(D,L.dimension)),this._targetWindowId=(0,g.getWindow)(D).vscodeWindowId,this._rawOptions=h(L),this._validatedOptions=f.validateOptions(this._rawOptions),this.options=this._computeOptions(),this.options.get(13)&&this._containerObserver.startObserving(),this._register(t.EditorZoom.onDidChangeZoomLevel(()=>this._recomputeOptions())),this._register(n.TabFocus.onDidChangeTabFocus(()=>this._recomputeOptions())),this._register(this._containerObserver.onDidChange(()=>this._recomputeOptions())),this._register(b.FontMeasurements.onDidChange(()=>this._recomputeOptions())),this._register(c.PixelRatio.getInstance((0,g.getWindow)(D)).onDidChange(()=>this._recomputeOptions())),this._register(this._accessibilityService.onDidChangeScreenReaderOptimized(()=>this._recomputeOptions()))}_recomputeOptions(){const w=this._computeOptions(),S=f.checkEquals(this.options,w);S!==null&&(this.options=w,this._onDidChangeFast.fire(S),this._onDidChange.fire(S))}_computeOptions(){const w=this._readEnvConfiguration(),S=i.BareFontInfo.createFromValidatedSettings(this._validatedOptions,w.pixelRatio,this.isSimpleWidget),L=this._readFontInfo(S),D={memory:this._computeOptionsMemory,outerWidth:w.outerWidth,outerHeight:w.outerHeight-this._reservedHeight,fontInfo:L,extraEditorClassName:w.extraEditorClassName,isDominatedByLongLines:this._isDominatedByLongLines,viewLineCount:this._viewLineCount,lineNumbersDigitCount:this._lineNumbersDigitCount,emptySelectionClipboard:w.emptySelectionClipboard,pixelRatio:w.pixelRatio,tabFocusMode:n.TabFocus.getTabFocusMode(),accessibilitySupport:w.accessibilitySupport,glyphMarginDecorationLaneCount:this._glyphMarginDecorationLaneCount};return f.computeOptions(this._validatedOptions,D)}_readEnvConfiguration(){return{extraEditorClassName:r(),outerWidth:this._containerObserver.getWidth(),outerHeight:this._containerObserver.getHeight(),emptySelectionClipboard:d.isWebKit||d.isFirefox,pixelRatio:c.PixelRatio.getInstance((0,g.getWindowById)(this._targetWindowId,!0).window).value,accessibilitySupport:this._accessibilityService.isScreenReaderOptimized()?2:this._accessibilityService.getAccessibilitySupport()}}_readFontInfo(w){return b.FontMeasurements.readFontInfo((0,g.getWindowById)(this._targetWindowId,!0).window,w)}getRawOptions(){return this._rawOptions}updateOptions(w){const S=h(w);f.applyUpdate(this._rawOptions,S)&&(this._validatedOptions=f.validateOptions(this._rawOptions),this._recomputeOptions())}observeContainer(w){this._containerObserver.observe(w)}setIsDominatedByLongLines(w){this._isDominatedByLongLines!==w&&(this._isDominatedByLongLines=w,this._recomputeOptions())}setModelLineCount(w){const S=a(w);this._lineNumbersDigitCount!==S&&(this._lineNumbersDigitCount=S,this._recomputeOptions())}setViewLineCount(w){this._viewLineCount!==w&&(this._viewLineCount=w,this._recomputeOptions())}setReservedHeight(w){this._reservedHeight!==w&&(this._reservedHeight=w,this._recomputeOptions())}setGlyphMarginDecorationLaneCount(w){this._glyphMarginDecorationLaneCount!==w&&(this._glyphMarginDecorationLaneCount=w,this._recomputeOptions())}};e.EditorConfiguration=l,e.EditorConfiguration=l=ke([ce(4,s.IAccessibilityService)],l);function a(v){let w=0;for(;v;)v=Math.floor(v/10),w++;return w||1}function r(){let v="";return!d.isSafari&&!d.isWebkitWebView&&(v+="no-user-select "),d.isSafari&&(v+="no-minimap-shadow ",v+="enable-user-select "),m.isMacintosh&&(v+="mac "),v}class u{constructor(){this._values=[]}_read(w){return this._values[w]}get(w){return this._values[w]}_write(w,S){this._values[w]=S}}class C{constructor(){this._values=[]}_read(w){if(w>=this._values.length)throw new Error("Cannot read uninitialized value");return this._values[w]}get(w){return this._read(w)}_write(w,S){this._values[w]=S}}e.ComputedEditorOptions=C;class f{static validateOptions(w){const S=new u;for(const L of o.editorOptionsRegistry){const D=L.name==="_never_"?void 0:w[L.name];S._write(L.id,L.validate(D))}return S}static computeOptions(w,S){const L=new C;for(const D of o.editorOptionsRegistry)L._write(D.id,D.compute(S,L,w._read(D.id)));return L}static _deepEquals(w,S){if(typeof w!="object"||typeof S!="object"||!w||!S)return w===S;if(Array.isArray(w)||Array.isArray(S))return Array.isArray(w)&&Array.isArray(S)?k.equals(w,S):!1;if(Object.keys(w).length!==Object.keys(S).length)return!1;for(const L in w)if(!f._deepEquals(w[L],S[L]))return!1;return!0}static checkEquals(w,S){const L=[];let D=!1;for(const T of o.editorOptionsRegistry){const M=!f._deepEquals(w._read(T.id),S._read(T.id));L[T.id]=M,M&&(D=!0)}return D?new o.ConfigurationChangedEvent(L):null}static applyUpdate(w,S){let L=!1;for(const D of o.editorOptionsRegistry)if(S.hasOwnProperty(D.name)){const T=D.applyUpdate(w[D.name],S[D.name]);w[D.name]=T.newValue,L=L||T.didChange}return L}}function h(v){const w=y.deepClone(v);return(0,p.migrateOptions)(w),w}}),define(ne[687],se([1,0,6,53,2,60,225,22,3,24,28,12]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContextKeyService=e.AbstractContextKeyService=e.Context=void 0,e.setContext=v;const o="data-keybinding-context";class t{constructor(L,D){this._id=L,this._parent=D,this._value=Object.create(null),this._value._contextId=L}get value(){return{...this._value}}setValue(L,D){return this._value[L]!==D?(this._value[L]=D,!0):!1}removeValue(L){return L in this._value?(delete this._value[L],!0):!1}getValue(L){const D=this._value[L];return typeof D>"u"&&this._parent?this._parent.getValue(L):D}}e.Context=t;class i extends t{static{this.INSTANCE=new i}constructor(){super(-1,null)}setValue(L,D){return!1}removeValue(L){return!1}getValue(L){}}class s extends t{static{this._keyPrefix="config."}constructor(L,D,T){super(L,null),this._configurationService=D,this._values=y.TernarySearchTree.forConfigKeys(),this._listener=this._configurationService.onDidChangeConfiguration(M=>{if(M.source===7){const A=Array.from(this._values,([P])=>P);this._values.clear(),T.fire(new l(A))}else{const A=[];for(const P of M.affectedKeys){const N=`config.${P}`,O=this._values.findSuperstr(N);O!==void 0&&(A.push(...k.Iterable.map(O,([F])=>F)),this._values.deleteSuperstr(N)),this._values.has(N)&&(A.push(N),this._values.delete(N))}T.fire(new l(A))}})}dispose(){this._listener.dispose()}getValue(L){if(L.indexOf(s._keyPrefix)!==0)return super.getValue(L);if(this._values.has(L))return this._values.get(L);const D=L.substr(s._keyPrefix.length),T=this._configurationService.getValue(D);let M;switch(typeof T){case"number":case"boolean":case"string":M=T;break;default:Array.isArray(T)?M=JSON.stringify(T):M=T}return this._values.set(L,M),M}setValue(L,D){return super.setValue(L,D)}removeValue(L){return super.removeValue(L)}}class g{constructor(L,D,T){this._service=L,this._key=D,this._defaultValue=T,this.reset()}set(L){this._service.setContext(this._key,L)}reset(){typeof this._defaultValue>"u"?this._service.removeContext(this._key):this._service.setContext(this._key,this._defaultValue)}get(){return this._service.getContextKeyValue(this._key)}}class c{constructor(L){this.key=L}affectsSome(L){return L.has(this.key)}allKeysContainedIn(L){return this.affectsSome(L)}}class l{constructor(L){this.keys=L}affectsSome(L){for(const D of this.keys)if(L.has(D))return!0;return!1}allKeysContainedIn(L){return this.keys.every(D=>L.has(D))}}class a{constructor(L){this.events=L}affectsSome(L){for(const D of this.events)if(D.affectsSome(L))return!0;return!1}allKeysContainedIn(L){return this.events.every(D=>D.allKeysContainedIn(L))}}function r(S,L){return S.allKeysContainedIn(new Set(Object.keys(L)))}class u extends I.Disposable{constructor(L){super(),this._onDidChangeContext=this._register(new d.PauseableEmitter({merge:D=>new a(D)})),this.onDidChangeContext=this._onDidChangeContext.event,this._isDisposed=!1,this._myContextId=L}createKey(L,D){if(this._isDisposed)throw new Error("AbstractContextKeyService has been disposed");return new g(this,L,D)}bufferChangeEvents(L){this._onDidChangeContext.pause();try{L()}finally{this._onDidChangeContext.resume()}}createScoped(L){if(this._isDisposed)throw new Error("AbstractContextKeyService has been disposed");return new f(this,L)}contextMatchesRules(L){if(this._isDisposed)throw new Error("AbstractContextKeyService has been disposed");const D=this.getContextValuesContainer(this._myContextId);return L?L.evaluate(D):!0}getContextKeyValue(L){if(!this._isDisposed)return this.getContextValuesContainer(this._myContextId).getValue(L)}setContext(L,D){if(this._isDisposed)return;const T=this.getContextValuesContainer(this._myContextId);T&&T.setValue(L,D)&&this._onDidChangeContext.fire(new c(L))}removeContext(L){this._isDisposed||this.getContextValuesContainer(this._myContextId).removeValue(L)&&this._onDidChangeContext.fire(new c(L))}getContext(L){return this._isDisposed?i.INSTANCE:this.getContextValuesContainer(h(L))}dispose(){super.dispose(),this._isDisposed=!0}}e.AbstractContextKeyService=u;let C=class extends u{constructor(L){super(0),this._contexts=new Map,this._lastContextId=0;const D=this._register(new s(this._myContextId,L,this._onDidChangeContext));this._contexts.set(this._myContextId,D)}getContextValuesContainer(L){return this._isDisposed?i.INSTANCE:this._contexts.get(L)||i.INSTANCE}createChildContext(L=this._myContextId){if(this._isDisposed)throw new Error("ContextKeyService has been disposed");const D=++this._lastContextId;return this._contexts.set(D,new t(D,this.getContextValuesContainer(L))),D}disposeContext(L){this._isDisposed||this._contexts.delete(L)}};e.ContextKeyService=C,e.ContextKeyService=C=ke([ce(0,p.IConfigurationService)],C);class f extends u{constructor(L,D){if(super(L.createChildContext()),this._parentChangeListener=this._register(new I.MutableDisposable),this._parent=L,this._updateParentChangeListener(),this._domNode=D,this._domNode.hasAttribute(o)){let T="";this._domNode.classList&&(T=Array.from(this._domNode.classList.values()).join(", ")),console.error(`Element already has context attribute${T?": "+T:""}`)}this._domNode.setAttribute(o,String(this._myContextId))}_updateParentChangeListener(){this._parentChangeListener.value=this._parent.onDidChangeContext(L=>{const T=this._parent.getContextValuesContainer(this._myContextId).value;r(L,T)||this._onDidChangeContext.fire(L)})}dispose(){this._isDisposed||(this._parent.disposeContext(this._myContextId),this._domNode.removeAttribute(o),super.dispose())}getContextValuesContainer(L){return this._isDisposed?i.INSTANCE:this._parent.getContextValuesContainer(L)}createChildContext(L=this._myContextId){if(this._isDisposed)throw new Error("ScopedContextKeyService has been disposed");return this._parent.createChildContext(L)}disposeContext(L){this._isDisposed||this._parent.disposeContext(L)}}function h(S){for(;S;){if(S.hasAttribute(o)){const L=S.getAttribute(o);return L?parseInt(L,10):NaN}S=S.parentElement}return 0}function v(S,L,D){S.get(n.IContextKeyService).createKey(String(L),w(D))}function w(S){return(0,E.cloneAndChange)(S,L=>{if(typeof L=="object"&&L.$mid===1)return m.URI.revive(L).toString();if(L instanceof m.URI)return L.toString()})}b.CommandsRegistry.registerCommand("_setContext",v),b.CommandsRegistry.registerCommand({id:"getContextKeyInfo",handler(){return[...n.RawContextKey.all()].sort((S,L)=>S.key.localeCompare(L.key))},metadata:{description:(0,_.localize)(1513,"A command that returns information about context keys"),args:[]}}),b.CommandsRegistry.registerCommand("_generateContextKeyInfo",function(){const S=[],L=new Set;for(const D of n.RawContextKey.all())L.has(D.key)||(L.add(D.key),S.push(D));S.sort((D,T)=>D.key.localeCompare(T.key)),console.log(JSON.stringify(S,void 0,2))})}),define(ne[179],se([1,0,16,3,12]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InputFocusedContext=e.InputFocusedContextKey=e.ProductQualityContext=e.IsDevelopmentContext=e.IsMobileContext=e.IsIOSContext=e.IsMacNativeContext=e.IsWebContext=e.IsWindowsContext=e.IsLinuxContext=e.IsMacContext=void 0,e.IsMacContext=new I.RawContextKey("isMac",d.isMacintosh,(0,k.localize)(1523,"Whether the operating system is macOS")),e.IsLinuxContext=new I.RawContextKey("isLinux",d.isLinux,(0,k.localize)(1524,"Whether the operating system is Linux")),e.IsWindowsContext=new I.RawContextKey("isWindows",d.isWindows,(0,k.localize)(1525,"Whether the operating system is Windows")),e.IsWebContext=new I.RawContextKey("isWeb",d.isWeb,(0,k.localize)(1526,"Whether the platform is a web browser")),e.IsMacNativeContext=new I.RawContextKey("isMacNative",d.isMacintosh&&!d.isWeb,(0,k.localize)(1527,"Whether the operating system is macOS on a non-browser platform")),e.IsIOSContext=new I.RawContextKey("isIOS",d.isIOS,(0,k.localize)(1528,"Whether the operating system is iOS")),e.IsMobileContext=new I.RawContextKey("isMobile",d.isMobile,(0,k.localize)(1529,"Whether the platform is a mobile web browser")),e.IsDevelopmentContext=new I.RawContextKey("isDevelopment",!1,!0),e.ProductQualityContext=new I.RawContextKey("productQualityType","",(0,k.localize)(1530,"Quality type of VS Code")),e.InputFocusedContextKey="inputFocus",e.InputFocusedContext=new I.RawContextKey(e.InputFocusedContextKey,!1,(0,k.localize)(1531,"Whether keyboard focus is inside an input box"))}),define(ne[58],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IContextMenuService=e.IContextViewService=void 0,e.IContextViewService=(0,d.createDecorator)("contextViewService"),e.IContextMenuService=(0,d.createDecorator)("contextMenuService")}),define(ne[180],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IDialogService=void 0,e.IDialogService=(0,d.createDecorator)("dialogService")}),define(ne[271],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IEnvironmentService=void 0,e.IEnvironmentService=(0,d.createDecorator)("environmentService")}),define(ne[118],se([1,0,7,2,28,5]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.nativeHoverDelegate=e.WorkbenchHoverDelegate=e.IHoverService=void 0,e.IHoverService=(0,d.createDecorator)("hoverService");let y=class extends k.Disposable{get delay(){return this.isInstantlyHovering()?0:this._delay}constructor(_,b,p={},n,o){super(),this.placement=_,this.instantHover=b,this.overrideOptions=p,this.configurationService=n,this.hoverService=o,this.lastHoverHideTime=0,this.timeLimit=200,this.hoverDisposables=this._register(new k.DisposableStore),this._delay=this.configurationService.getValue("workbench.hover.delay"),this._register(this.configurationService.onDidChangeConfiguration(t=>{t.affectsConfiguration("workbench.hover.delay")&&(this._delay=this.configurationService.getValue("workbench.hover.delay"))}))}showHover(_,b){const p=typeof this.overrideOptions=="function"?this.overrideOptions(_,b):this.overrideOptions;this.hoverDisposables.clear();const n=(0,E.isHTMLElement)(_.target)?[_.target]:_.target.targetElements;for(const t of n)this.hoverDisposables.add((0,E.addStandardDisposableListener)(t,"keydown",i=>{i.equals(9)&&this.hoverService.hideHover()}));const o=(0,E.isHTMLElement)(_.content)?void 0:_.content.toString();return this.hoverService.showHover({..._,...p,persistence:{hideOnKeyDown:!0,...p.persistence},id:o,appearance:{..._.appearance,compact:!0,skipFadeInAnimation:this.isInstantlyHovering(),...p.appearance}},b)}isInstantlyHovering(){return this.instantHover&&Date.now()-this.lastHoverHideTimea):void 0}dispose(){if(!this._isDisposed){this._isDisposed=!0,(0,I.dispose)(this._children),this._children.clear();for(const s of this._servicesToMaybeDispose)(0,I.isDisposable)(s)&&s.dispose();this._servicesToMaybeDispose.clear()}}_throwIfDisposed(){if(this._isDisposed)throw new Error("InstantiationService has been disposed")}createChild(s,g){this._throwIfDisposed();const c=this,l=new class extends o{dispose(){c._children.delete(l),super.dispose()}}(s,this._strict,this,this._enableTracing);return this._children.add(l),g?.add(l),l}invokeFunction(s,...g){this._throwIfDisposed();const c=t.traceInvocation(this._enableTracing,s);let l=!1;try{return s({get:r=>{if(l)throw(0,k.illegalState)("service accessor is only valid during the invocation of its target method");const u=this._getOrCreateServiceInstance(r,c);if(!u)throw new Error(`[invokeFunction] unknown service '${r}'`);return u}},...g)}finally{l=!0,c.stop()}}createInstance(s,...g){this._throwIfDisposed();let c,l;return s instanceof E.SyncDescriptor?(c=t.traceCreation(this._enableTracing,s.ctor),l=this._createInstance(s.ctor,s.staticArguments.concat(g),c)):(c=t.traceCreation(this._enableTracing,s),l=this._createInstance(s,g,c)),c.stop(),l}_createInstance(s,g=[],c){const l=m._util.getServiceDependencies(s).sort((u,C)=>u.index-C.index),a=[];for(const u of l){const C=this._getOrCreateServiceInstance(u.id,c);C||this._throwIfStrict(`[createInstance] ${s.name} depends on UNKNOWN service ${u.id}.`,!1),a.push(C)}const r=l.length>0?l[0].index:g.length;if(g.length!==r){console.trace(`[createInstance] First service dependency of ${s.name} at position ${r+1} conflicts with ${g.length} static arguments`);const u=r-g.length;u>0?g=g.concat(new Array(u)):g=g.slice(0,r)}return Reflect.construct(s,g.concat(a))}_setCreatedServiceInstance(s,g){if(this._services.get(s)instanceof E.SyncDescriptor)this._services.set(s,g);else if(this._parent)this._parent._setCreatedServiceInstance(s,g);else throw new Error("illegalState - setting UNKNOWN service instance")}_getServiceInstanceOrDescriptor(s){const g=this._services.get(s);return!g&&this._parent?this._parent._getServiceInstanceOrDescriptor(s):g}_getOrCreateServiceInstance(s,g){this._globalGraph&&this._globalGraphImplicitDependency&&this._globalGraph.insertEdge(this._globalGraphImplicitDependency,String(s));const c=this._getServiceInstanceOrDescriptor(s);return c instanceof E.SyncDescriptor?this._safeCreateAndCacheServiceInstance(s,c,g.branch(s,!0)):(g.branch(s,!1),c)}_safeCreateAndCacheServiceInstance(s,g,c){if(this._activeInstantiations.has(s))throw new Error(`illegal state - RECURSIVELY instantiating service '${s}'`);this._activeInstantiations.add(s);try{return this._createAndCacheServiceInstance(s,g,c)}finally{this._activeInstantiations.delete(s)}}_createAndCacheServiceInstance(s,g,c){const l=new y.Graph(C=>C.id.toString());let a=0;const r=[{id:s,desc:g,_trace:c}],u=new Set;for(;r.length;){const C=r.pop();if(!u.has(String(C.id))){if(u.add(String(C.id)),l.lookupOrInsertNode(C),a++>1e3)throw new n(l);for(const f of m._util.getServiceDependencies(C.desc.ctor)){const h=this._getServiceInstanceOrDescriptor(f.id);if(h||this._throwIfStrict(`[createInstance] ${s} depends on ${f.id} which is NOT registered.`,!0),this._globalGraph?.insertEdge(String(C.id),String(f.id)),h instanceof E.SyncDescriptor){const v={id:f.id,desc:h,_trace:C._trace.branch(f.id,!0)};l.insertEdge(C,v),r.push(v)}}}}for(;;){const C=l.roots();if(C.length===0){if(!l.isEmpty())throw new n(l);break}for(const{data:f}of C){if(this._getServiceInstanceOrDescriptor(f.id)instanceof E.SyncDescriptor){const v=this._createServiceInstanceWithOwner(f.id,f.desc.ctor,f.desc.staticArguments,f.desc.supportsDelayedInstantiation,f._trace);this._setCreatedServiceInstance(f.id,v)}l.removeNode(f)}}return this._getServiceInstanceOrDescriptor(s)}_createServiceInstanceWithOwner(s,g,c=[],l,a){if(this._services.get(s)instanceof E.SyncDescriptor)return this._createServiceInstance(s,g,c,l,a,this._servicesToMaybeDispose);if(this._parent)return this._parent._createServiceInstanceWithOwner(s,g,c,l,a);throw new Error(`illegalState - creating UNKNOWN service instance ${g.name}`)}_createServiceInstance(s,g,c=[],l,a,r){if(l){const u=new o(void 0,this._strict,this,this._enableTracing);u._globalGraphImplicitDependency=String(s);const C=new Map,f=new d.GlobalIdleValue(()=>{const h=u._createInstance(g,c,a);for(const[v,w]of C){const S=h[v];if(typeof S=="function")for(const L of w)L.disposable=S.apply(h,L.listener)}return C.clear(),r.add(h),h});return new Proxy(Object.create(null),{get(h,v){if(!f.isInitialized&&typeof v=="string"&&(v.startsWith("onDid")||v.startsWith("onWill"))){let L=C.get(v);return L||(L=new b.LinkedList,C.set(v,L)),(T,M,A)=>{if(f.isInitialized)return f.value[v](T,M,A);{const P={listener:[T,M,A],disposable:void 0},N=L.push(P);return(0,I.toDisposable)(()=>{N(),P.disposable?.dispose()})}}}if(v in h)return h[v];const w=f.value;let S=w[v];return typeof S!="function"||(S=S.bind(w),h[v]=S),S},set(h,v,w){return f.value[v]=w,!0},getPrototypeOf(h){return g.prototype}})}else{const u=this._createInstance(g,c,a);return r.add(u),u}}_throwIfStrict(s,g){if(g&&console.warn(s),this._strict)throw new Error(s)}}e.InstantiationService=o;class t{static{this.all=new Set}static{this._None=new class extends t{constructor(){super(0,null)}stop(){}branch(){return this}}}static traceInvocation(s,g){return s?new t(2,g.name||new Error().stack.split(` `).slice(3,4).join(` `)):t._None}static traceCreation(s,g){return s?new t(1,g.name):t._None}static{this._totals=0}constructor(s,g){this.type=s,this.name=g,this._start=Date.now(),this._dep=[]}branch(s,g){const c=new t(3,s.toString());return this._dep.push([s,g,c]),c}stop(){const s=Date.now()-this._start;t._totals+=s;let g=!1;function c(a,r){const u=[],C=new Array(a+1).join(" ");for(const[f,h,v]of r._dep)if(h&&v){g=!0,u.push(`${C}CREATES -> ${f}`);const w=c(a+1,v);w&&u.push(w)}else u.push(`${C}uses -> ${f}`);return u.join(` `)}const l=[`${this.type===1?"CREATE":"CALL"} ${this.name}`,`${c(1,this)}`,`DONE, took ${s.toFixed(2)}ms (grand total ${t._totals.toFixed(2)}ms)`];(s>2||g)&&t.all.add(l.join(` `))}}e.Trace=t}),define(ne[689],se([1,0,8,247,140]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BaseResolvedKeybinding=void 0;class E extends I.ResolvedKeybinding{constructor(m,_){if(super(),_.length===0)throw(0,d.illegalArgument)("chords");this._os=m,this._chords=_}getLabel(){return k.UILabelProvider.toLabel(this._os,this._chords,m=>this._getLabel(m))}getAriaLabel(){return k.AriaLabelProvider.toLabel(this._os,this._chords,m=>this._getAriaLabel(m))}getElectronAccelerator(){return this._chords.length>1||this._chords[0].isDuplicateModifierCase()?null:k.ElectronAcceleratorLabelProvider.toLabel(this._os,this._chords,m=>this._getElectronAccelerator(m))}getUserSettingsLabel(){return k.UserSettingsLabelProvider.toLabel(this._os,this._chords,m=>this._getUserSettingsLabel(m))}hasMultipleChords(){return this._chords.length>1}getChords(){return this._chords.map(m=>this._getChord(m))}_getChord(m){return new I.ResolvedChord(m.ctrlKey,m.shiftKey,m.altKey,m.metaKey,this._getLabel(m),this._getAriaLabel(m))}getDispatchChords(){return this._chords.map(m=>this._getChordDispatch(m))}getSingleModifierDispatchChords(){return this._chords.map(m=>this._getSingleModifierChordDispatch(m))}}e.BaseResolvedKeybinding=E}),define(ne[31],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IKeybindingService=void 0,e.IKeybindingService=(0,d.createDecorator)("keybindingService")}),define(ne[391],se([1,0,5,174,2,31]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorHoverStatusBar=void 0;const y=d.$;let m=class extends I.Disposable{get hasContent(){return this._hasContent}constructor(b){super(),this._keybindingService=b,this.actions=[],this._hasContent=!1,this.hoverElement=y("div.hover-row.status-bar"),this.hoverElement.tabIndex=0,this.actionsElement=d.append(this.hoverElement,y("div.actions"))}addAction(b){const p=this._keybindingService.lookupKeybinding(b.commandId),n=p?p.getLabel():null;this._hasContent=!0;const o=this._register(k.HoverAction.render(this.actionsElement,b,n));return this.actions.push(o),o}append(b){const p=d.append(this.actionsElement,b);return this._hasContent=!0,p}};e.EditorHoverStatusBar=m,e.EditorHoverStatusBar=m=ke([ce(0,E.IKeybindingService)],m)}),define(ne[690],se([1,0,5,31,670,12,28,61,20,174,6]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";var n;Object.defineProperty(e,"__esModule",{value:!0}),e.ContentHoverWidget=void 0;const o=30,t=6;let i=class extends I.ResizableContentWidget{static{n=this}static{this.ID="editor.contrib.resizableContentHoverWidget"}static{this._lastDimensions=new d.Dimension(0,0)}get isVisibleFromKeyboard(){return this._renderedHover?.source===1}get isVisible(){return this._hoverVisibleKey.get()??!1}get isFocused(){return this._hoverFocusedKey.get()??!1}constructor(c,l,a,r,u){const C=c.getOption(67)+8,f=150,h=new d.Dimension(f,C);super(c,h),this._configurationService=a,this._accessibilityService=r,this._keybindingService=u,this._hover=this._register(new b.HoverWidget),this._onDidResize=this._register(new p.Emitter),this.onDidResize=this._onDidResize.event,this._minimumSize=h,this._hoverVisibleKey=_.EditorContextKeys.hoverVisible.bindTo(l),this._hoverFocusedKey=_.EditorContextKeys.hoverFocused.bindTo(l),d.append(this._resizableNode.domNode,this._hover.containerDomNode),this._resizableNode.domNode.style.zIndex="50",this._register(this._editor.onDidLayoutChange(()=>{this.isVisible&&this._updateMaxDimensions()})),this._register(this._editor.onDidChangeConfiguration(w=>{w.hasChanged(50)&&this._updateFont()}));const v=this._register(d.trackFocus(this._resizableNode.domNode));this._register(v.onDidFocus(()=>{this._hoverFocusedKey.set(!0)})),this._register(v.onDidBlur(()=>{this._hoverFocusedKey.set(!1)})),this._setRenderedHover(void 0),this._editor.addContentWidget(this)}dispose(){super.dispose(),this._renderedHover?.dispose(),this._editor.removeContentWidget(this)}getId(){return n.ID}static _applyDimensions(c,l,a){const r=typeof l=="number"?`${l}px`:l,u=typeof a=="number"?`${a}px`:a;c.style.width=r,c.style.height=u}_setContentsDomNodeDimensions(c,l){const a=this._hover.contentsDomNode;return n._applyDimensions(a,c,l)}_setContainerDomNodeDimensions(c,l){const a=this._hover.containerDomNode;return n._applyDimensions(a,c,l)}_setHoverWidgetDimensions(c,l){this._setContentsDomNodeDimensions(c,l),this._setContainerDomNodeDimensions(c,l),this._layoutContentWidget()}static _applyMaxDimensions(c,l,a){const r=typeof l=="number"?`${l}px`:l,u=typeof a=="number"?`${a}px`:a;c.style.maxWidth=r,c.style.maxHeight=u}_setHoverWidgetMaxDimensions(c,l){n._applyMaxDimensions(this._hover.contentsDomNode,c,l),n._applyMaxDimensions(this._hover.containerDomNode,c,l),this._hover.containerDomNode.style.setProperty("--vscode-hover-maxWidth",typeof c=="number"?`${c}px`:c),this._layoutContentWidget()}_setAdjustedHoverWidgetDimensions(c){this._setHoverWidgetMaxDimensions("none","none");const l=c.width,a=c.height;this._setHoverWidgetDimensions(l,a)}_updateResizableNodeMaxDimensions(){const c=this._findMaximumRenderingWidth()??1/0,l=this._findMaximumRenderingHeight()??1/0;this._resizableNode.maxSize=new d.Dimension(c,l),this._setHoverWidgetMaxDimensions(c,l)}_resize(c){n._lastDimensions=new d.Dimension(c.width,c.height),this._setAdjustedHoverWidgetDimensions(c),this._resizableNode.layout(c.height,c.width),this._updateResizableNodeMaxDimensions(),this._hover.scrollbar.scanDomNode(),this._editor.layoutContentWidget(this),this._onDidResize.fire()}_findAvailableSpaceVertically(){const c=this._renderedHover?.showAtPosition;if(c)return this._positionPreference===1?this._availableVerticalSpaceAbove(c):this._availableVerticalSpaceBelow(c)}_findMaximumRenderingHeight(){const c=this._findAvailableSpaceVertically();if(!c)return;let l=t;return Array.from(this._hover.contentsDomNode.children).forEach(a=>{l+=a.clientHeight}),Math.min(c,l)}_isHoverTextOverflowing(){this._hover.containerDomNode.style.setProperty("--vscode-hover-whiteSpace","nowrap"),this._hover.containerDomNode.style.setProperty("--vscode-hover-sourceWhiteSpace","nowrap");const c=Array.from(this._hover.contentsDomNode.children).some(l=>l.scrollWidth>l.clientWidth);return this._hover.containerDomNode.style.removeProperty("--vscode-hover-whiteSpace"),this._hover.containerDomNode.style.removeProperty("--vscode-hover-sourceWhiteSpace"),c}_findMaximumRenderingWidth(){if(!this._editor||!this._editor.hasModel())return;const c=this._isHoverTextOverflowing(),l=typeof this._contentWidth>"u"?0:this._contentWidth-2;return c||this._hover.containerDomNode.clientWidththis._renderedHover.closestMouseDistance+4?!1:(this._renderedHover.closestMouseDistance=Math.min(this._renderedHover.closestMouseDistance,r),!0)}_setRenderedHover(c){this._renderedHover?.dispose(),this._renderedHover=c,this._hoverVisibleKey.set(!!c),this._hover.containerDomNode.classList.toggle("hidden",!c)}_updateFont(){const{fontSize:c,lineHeight:l}=this._editor.getOption(50),a=this._hover.contentsDomNode;a.style.fontSize=`${c}px`,a.style.lineHeight=`${l/c}`,Array.prototype.slice.call(this._hover.contentsDomNode.getElementsByClassName("code")).forEach(u=>this._editor.applyFontInfo(u))}_updateContent(c){const l=this._hover.contentsDomNode;l.style.paddingBottom="",l.textContent="",l.appendChild(c)}_layoutContentWidget(){this._editor.layoutContentWidget(this),this._hover.onContentsChanged()}_updateMaxDimensions(){const c=Math.max(this._editor.getLayoutInfo().height/4,250,n._lastDimensions.height),l=Math.max(this._editor.getLayoutInfo().width*.66,500,n._lastDimensions.width);this._setHoverWidgetMaxDimensions(l,c)}_render(c){this._setRenderedHover(c),this._updateFont(),this._updateContent(c.domNode),this._updateMaxDimensions(),this.onContentsChanged(),this._editor.render()}getPosition(){return this._renderedHover?{position:this._renderedHover.showAtPosition,secondaryPosition:this._renderedHover.showAtSecondaryPosition,positionAffinity:this._renderedHover.shouldAppearBeforeContent?3:void 0,preference:[this._positionPreference??1]}:null}show(c){if(!this._editor||!this._editor.hasModel())return;this._render(c);const l=d.getTotalHeight(this._hover.containerDomNode),a=c.showAtPosition;this._positionPreference=this._findPositionPreference(l,a)??1,this.onContentsChanged(),c.shouldFocus&&this._hover.containerDomNode.focus(),this._onDidResize.fire();const u=this._hover.containerDomNode.ownerDocument.activeElement===this._hover.containerDomNode&&(0,b.getHoverAccessibleViewHint)(this._configurationService.getValue("accessibility.verbosity.hover")===!0&&this._accessibilityService.isScreenReaderOptimized(),this._keybindingService.lookupKeybinding("editor.action.accessibleView")?.getAriaLabel()??"");u&&(this._hover.contentsDomNode.ariaLabel=this._hover.contentsDomNode.textContent+", "+u)}hide(){if(!this._renderedHover)return;const c=this._renderedHover.shouldFocus||this._hoverFocusedKey.get();this._setRenderedHover(void 0),this._resizableNode.maxSize=new d.Dimension(1/0,1/0),this._resizableNode.clearSashHoverState(),this._hoverFocusedKey.set(!1),this._editor.layoutContentWidget(this),c&&this._editor.focus()}_removeConstraintsRenderNormally(){const c=this._editor.getLayoutInfo();this._resizableNode.layout(c.height,c.width),this._setHoverWidgetDimensions("auto","auto")}setMinimumDimensions(c){this._minimumSize=new d.Dimension(Math.max(this._minimumSize.width,c.width),Math.max(this._minimumSize.height,c.height)),this._updateMinimumWidth()}_updateMinimumWidth(){const c=typeof this._contentWidth>"u"?this._minimumSize.width:Math.min(this._contentWidth,this._minimumSize.width);this._resizableNode.minSize=new d.Dimension(c,this._minimumSize.height)}onContentsChanged(){this._removeConstraintsRenderNormally();const c=this._hover.containerDomNode;let l=d.getTotalHeight(c),a=d.getTotalWidth(c);if(this._resizableNode.layout(l,a),this._setHoverWidgetDimensions(a,l),l=d.getTotalHeight(c),a=d.getTotalWidth(c),this._contentWidth=a,this._updateMinimumWidth(),this._resizableNode.layout(l,a),this._renderedHover?.showAtPosition){const r=d.getTotalHeight(this._hover.containerDomNode);this._positionPreference=this._findPositionPreference(r,this._renderedHover.showAtPosition)}this._layoutContentWidget()}focus(){this._hover.containerDomNode.focus()}scrollUp(){const c=this._hover.scrollbar.getScrollPosition().scrollTop,l=this._editor.getOption(50);this._hover.scrollbar.setScrollPosition({scrollTop:c-l.lineHeight})}scrollDown(){const c=this._hover.scrollbar.getScrollPosition().scrollTop,l=this._editor.getOption(50);this._hover.scrollbar.setScrollPosition({scrollTop:c+l.lineHeight})}scrollLeft(){const c=this._hover.scrollbar.getScrollPosition().scrollLeft;this._hover.scrollbar.setScrollPosition({scrollLeft:c-o})}scrollRight(){const c=this._hover.scrollbar.getScrollPosition().scrollLeft;this._hover.scrollbar.setScrollPosition({scrollLeft:c+o})}pageUp(){const c=this._hover.scrollbar.getScrollPosition().scrollTop,l=this._hover.scrollbar.getScrollDimensions().height;this._hover.scrollbar.setScrollPosition({scrollTop:c-l})}pageDown(){const c=this._hover.scrollbar.getScrollPosition().scrollTop,l=this._hover.scrollbar.getScrollDimensions().height;this._hover.scrollbar.setScrollPosition({scrollTop:c+l})}goToTop(){this._hover.scrollbar.setScrollPosition({scrollTop:0})}goToBottom(){this._hover.scrollbar.setScrollPosition({scrollTop:this._hover.scrollbar.getScrollDimensions().scrollHeight})}};e.ContentHoverWidget=i,e.ContentHoverWidget=i=n=ke([ce(1,E.IContextKeyService),ce(2,y.IConfigurationService),ce(3,m.IAccessibilityService),ce(4,k.IKeybindingService)],i);function s(g,c,l,a,r,u){const C=l+r/2,f=a+u/2,h=Math.max(Math.abs(g-C)-r/2,0),v=Math.max(Math.abs(c-f)-u/2,0);return Math.sqrt(h*h+v*v)}}),define(ne[392],se([1,0,12]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.KeybindingResolver=e.NoMatchingKb=void 0,e.NoMatchingKb={kind:0};const k={kind:1};function I(_,b,p){return{kind:2,commandId:_,commandArgs:b,isBubble:p}}class E{constructor(b,p,n){this._log=n,this._defaultKeybindings=b,this._defaultBoundCommands=new Map;for(const o of b){const t=o.command;t&&t.charAt(0)!=="-"&&this._defaultBoundCommands.set(t,!0)}this._map=new Map,this._lookupMap=new Map,this._keybindings=E.handleRemovals([].concat(b).concat(p));for(let o=0,t=this._keybindings.length;o"u"){this._map.set(b,[p]),this._addToLookupMap(p);return}for(let o=n.length-1;o>=0;o--){const t=n[o];if(t.command===p.command)continue;let i=!0;for(let s=1;s"u"?(p=[b],this._lookupMap.set(b.command,p)):p.push(b)}_removeFromLookupMap(b){if(!b.command)return;const p=this._lookupMap.get(b.command);if(!(typeof p>"u")){for(let n=0,o=p.length;n"u"||n.length===0)return null;if(n.length===1)return n[0];for(let o=n.length-1;o>=0;o--){const t=n[o];if(p.contextMatchesRules(t.when))return t}return n[n.length-1]}resolve(b,p,n){const o=[...p,n];this._log(`| Resolving ${o}`);const t=this._map.get(o[0]);if(t===void 0)return this._log("\\ No keybinding entries."),e.NoMatchingKb;let i=null;if(o.length<2)i=t;else{i=[];for(let g=0,c=t.length;gl.chords.length)continue;let a=!0;for(let r=1;r=0;n--){const o=p[n];if(E._contextMatchesRules(b,o.when))return o}return null}static _contextMatchesRules(b,p){return p?p.evaluate(b):!0}}e.KeybindingResolver=E;function y(_){return _?`${_.serialize()}`:"no when condition"}function m(_){return _.extensionId?_.isBuiltinExtension?`built-in extension ${_.extensionId}`:`user extension ${_.extensionId}`:_.isDefault?"built-in":"user"}}),define(ne[691],se([1,0,14,8,6,300,2,3,392]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractKeybindingService=void 0;const b=/^(cursor|delete|undo|redo|tab|editor\.action\.clipboard)/;class p extends y.Disposable{get onDidUpdateKeybindings(){return this._onDidUpdateKeybindings?this._onDidUpdateKeybindings.event:I.Event.None}get inChordMode(){return this._currentChords.length>0}constructor(t,i,s,g,c){super(),this._contextKeyService=t,this._commandService=i,this._telemetryService=s,this._notificationService=g,this._logService=c,this._onDidUpdateKeybindings=this._register(new I.Emitter),this._currentChords=[],this._currentChordChecker=new d.IntervalTimer,this._currentChordStatusMessage=null,this._ignoreSingleModifiers=n.EMPTY,this._currentSingleModifier=null,this._currentSingleModifierClearTimeout=new d.TimeoutTimer,this._currentlyDispatchingCommandId=null,this._logging=!1}dispose(){super.dispose()}_log(t){this._logging&&this._logService.info(`[KeybindingService]: ${t}`)}getKeybindings(){return this._getResolver().getKeybindings()}lookupKeybinding(t,i){const s=this._getResolver().lookupPrimaryKeybinding(t,i||this._contextKeyService);if(s)return s.resolvedKeybinding}dispatchEvent(t,i){return this._dispatch(t,i)}softDispatch(t,i){this._log("/ Soft dispatching keyboard event");const s=this.resolveKeyboardEvent(t);if(s.hasMultipleChords())return console.warn("keyboard event should not be mapped to multiple chords"),_.NoMatchingKb;const[g]=s.getDispatchChords();if(g===null)return this._log("\\ Keyboard event cannot be dispatched"),_.NoMatchingKb;const c=this._contextKeyService.getContext(i),l=this._currentChords.map(({keypress:a})=>a);return this._getResolver().resolve(c,l,g)}_scheduleLeaveChordMode(){const t=Date.now();this._currentChordChecker.cancelAndSet(()=>{if(!this._documentHasFocus()){this._leaveChordMode();return}Date.now()-t>5e3&&this._leaveChordMode()},500)}_expectAnotherChord(t,i){switch(this._currentChords.push({keypress:t,label:i}),this._currentChords.length){case 0:throw(0,k.illegalState)("impossible");case 1:this._currentChordStatusMessage=this._notificationService.status(m.localize(1538,"({0}) was pressed. Waiting for second key of chord...",i));break;default:{const s=this._currentChords.map(({label:g})=>g).join(", ");this._currentChordStatusMessage=this._notificationService.status(m.localize(1539,"({0}) was pressed. Waiting for next key of chord...",s))}}this._scheduleLeaveChordMode(),E.IME.enabled&&E.IME.disable()}_leaveChordMode(){this._currentChordStatusMessage&&(this._currentChordStatusMessage.dispose(),this._currentChordStatusMessage=null),this._currentChordChecker.cancel(),this._currentChords=[],E.IME.enable()}_dispatch(t,i){return this._doDispatch(this.resolveKeyboardEvent(t),i,!1)}_singleModifierDispatch(t,i){const s=this.resolveKeyboardEvent(t),[g]=s.getSingleModifierDispatchChords();if(g)return this._ignoreSingleModifiers.has(g)?(this._log(`+ Ignoring single modifier ${g} due to it being pressed together with other keys.`),this._ignoreSingleModifiers=n.EMPTY,this._currentSingleModifierClearTimeout.cancel(),this._currentSingleModifier=null,!1):(this._ignoreSingleModifiers=n.EMPTY,this._currentSingleModifier===null?(this._log(`+ Storing single modifier for possible chord ${g}.`),this._currentSingleModifier=g,this._currentSingleModifierClearTimeout.cancelAndSet(()=>{this._log("+ Clearing single modifier due to 300ms elapsed."),this._currentSingleModifier=null},300),!1):g===this._currentSingleModifier?(this._log(`/ Dispatching single modifier chord ${g} ${g}`),this._currentSingleModifierClearTimeout.cancel(),this._currentSingleModifier=null,this._doDispatch(s,i,!0)):(this._log(`+ Clearing single modifier due to modifier mismatch: ${this._currentSingleModifier} ${g}`),this._currentSingleModifierClearTimeout.cancel(),this._currentSingleModifier=null,!1));const[c]=s.getChords();return this._ignoreSingleModifiers=new n(c),this._currentSingleModifier!==null&&this._log("+ Clearing single modifier due to other key up."),this._currentSingleModifierClearTimeout.cancel(),this._currentSingleModifier=null,!1}_doDispatch(t,i,s=!1){let g=!1;if(t.hasMultipleChords())return console.warn("Unexpected keyboard event mapped to multiple chords"),!1;let c=null,l=null;if(s){const[C]=t.getSingleModifierDispatchChords();c=C,l=C?[C]:[]}else[c]=t.getDispatchChords(),l=this._currentChords.map(({keypress:C})=>C);if(c===null)return this._log("\\ Keyboard event cannot be dispatched in keydown phase."),g;const a=this._contextKeyService.getContext(i),r=t.getLabel(),u=this._getResolver().resolve(a,l,c);switch(u.kind){case 0:{if(this._logService.trace("KeybindingService#dispatch",r,"[ No matching keybinding ]"),this.inChordMode){const C=this._currentChords.map(({label:f})=>f).join(", ");this._log(`+ Leaving multi-chord mode: Nothing bound to "${C}, ${r}".`),this._notificationService.status(m.localize(1540,"The key combination ({0}, {1}) is not a command.",C,r),{hideAfter:10*1e3}),this._leaveChordMode(),g=!0}return g}case 1:return this._logService.trace("KeybindingService#dispatch",r,"[ Several keybindings match - more chords needed ]"),g=!0,this._expectAnotherChord(c,r),this._log(this._currentChords.length===1?"+ Entering multi-chord mode...":"+ Continuing multi-chord mode..."),g;case 2:{if(this._logService.trace("KeybindingService#dispatch",r,`[ Will dispatch command ${u.commandId} ]`),u.commandId===null||u.commandId===""){if(this.inChordMode){const C=this._currentChords.map(({label:f})=>f).join(", ");this._log(`+ Leaving chord mode: Nothing bound to "${C}, ${r}".`),this._notificationService.status(m.localize(1541,"The key combination ({0}, {1}) is not a command.",C,r),{hideAfter:10*1e3}),this._leaveChordMode(),g=!0}}else{this.inChordMode&&this._leaveChordMode(),u.isBubble||(g=!0),this._log(`+ Invoking command ${u.commandId}.`),this._currentlyDispatchingCommandId=u.commandId;try{typeof u.commandArgs>"u"?this._commandService.executeCommand(u.commandId).then(void 0,C=>this._notificationService.warn(C)):this._commandService.executeCommand(u.commandId,u.commandArgs).then(void 0,C=>this._notificationService.warn(C))}finally{this._currentlyDispatchingCommandId=null}b.test(u.commandId)||this._telemetryService.publicLog2("workbenchActionExecuted",{id:u.commandId,from:"keybinding",detail:t.getUserSettingsLabel()??void 0})}return g}}}mightProducePrintableCharacter(t){return t.ctrlKey||t.metaKey?!1:t.keyCode>=31&&t.keyCode<=56||t.keyCode>=21&&t.keyCode<=30}}e.AbstractKeybindingService=p;class n{static{this.EMPTY=new n(null)}constructor(t){this._ctrlKey=t?t.ctrlKey:!1,this._shiftKey=t?t.shiftKey:!1,this._altKey=t?t.altKey:!1,this._metaKey=t?t.metaKey:!1}has(t){switch(t){case"ctrl":return this._ctrlKey;case"shift":return this._shiftKey;case"alt":return this._altKey;case"meta":return this._metaKey}}}}),define(ne[393],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ResolvedKeybindingItem=void 0,e.toEmptyArrayIfContainsNull=k;class d{constructor(E,y,m,_,b,p,n){this._resolvedKeybindingItemBrand=void 0,this.resolvedKeybinding=E,this.chords=E?k(E.getDispatchChords()):[],E&&this.chords.length===0&&(this.chords=k(E.getSingleModifierDispatchChords())),this.bubble=y?y.charCodeAt(0)===94:!1,this.command=this.bubble?y.substr(1):y,this.commandArgs=m,this.when=_,this.isDefault=b,this.extensionId=p,this.isBuiltinExtension=n}}e.ResolvedKeybindingItem=d;function k(I){const E=[];for(let y=0,m=I.length;ythis._toKeyCodeChord(n)));return p.length>0?[new y(p,b)]:[]}}e.USLayoutResolvedKeybinding=y}),define(ne[181],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ILabelService=void 0,e.ILabelService=(0,d.createDecorator)("labelService")}),define(ne[119],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ILayoutService=void 0,e.ILayoutService=(0,d.createDecorator)("layoutService")}),define(ne[394],se([1,0,5,52,13,6,34,49,119]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorScopedLayoutService=void 0;let b=class{get mainContainer(){return(0,I.firstOrDefault)(this._codeEditorService.listCodeEditors())?.getContainerDomNode()??k.mainWindow.document.body}get activeContainer(){return(this._codeEditorService.getFocusedCodeEditor()??this._codeEditorService.getActiveCodeEditor())?.getContainerDomNode()??this.mainContainer}get mainContainerDimension(){return d.getClientArea(this.mainContainer)}get activeContainerDimension(){return d.getClientArea(this.activeContainer)}get containers(){return(0,I.coalesce)(this._codeEditorService.listCodeEditors().map(o=>o.getContainerDomNode()))}getContainer(){return this.activeContainer}whenContainerStylesLoaded(){}focus(){this._codeEditorService.getFocusedCodeEditor()?.focus()}constructor(o){this._codeEditorService=o,this.onDidLayoutMainContainer=E.Event.None,this.onDidLayoutActiveContainer=E.Event.None,this.onDidLayoutContainer=E.Event.None,this.onDidChangeActiveContainer=E.Event.None,this.onDidAddContainer=E.Event.None,this.mainContainerOffset={top:0,quickPickTop:0},this.activeContainerOffset={top:0,quickPickTop:0}}};b=ke([ce(0,y.ICodeEditorService)],b);let p=class extends b{get mainContainer(){return this._container}constructor(o,t){super(t),this._container=o}};e.EditorScopedLayoutService=p,e.EditorScopedLayoutService=p=ke([ce(1,y.ICodeEditorService)],p),(0,m.registerSingleton)(_.ILayoutService,b,1)}),define(ne[693],se([1,0,5,52,6,2,61,28,12,119]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AccessibilityService=void 0;let p=class extends E.Disposable{constructor(o,t,i){super(),this._contextKeyService=o,this._layoutService=t,this._configurationService=i,this._accessibilitySupport=0,this._onDidChangeScreenReaderOptimized=new I.Emitter,this._onDidChangeReducedMotion=new I.Emitter,this._onDidChangeLinkUnderline=new I.Emitter,this._accessibilityModeEnabledContext=y.CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);const s=()=>this._accessibilityModeEnabledContext.set(this.isScreenReaderOptimized());this._register(this._configurationService.onDidChangeConfiguration(c=>{c.affectsConfiguration("editor.accessibilitySupport")&&(s(),this._onDidChangeScreenReaderOptimized.fire()),c.affectsConfiguration("workbench.reduceMotion")&&(this._configMotionReduced=this._configurationService.getValue("workbench.reduceMotion"),this._onDidChangeReducedMotion.fire())})),s(),this._register(this.onDidChangeScreenReaderOptimized(()=>s()));const g=k.mainWindow.matchMedia("(prefers-reduced-motion: reduce)");this._systemMotionReduced=g.matches,this._configMotionReduced=this._configurationService.getValue("workbench.reduceMotion"),this._linkUnderlinesEnabled=this._configurationService.getValue("accessibility.underlineLinks"),this.initReducedMotionListeners(g),this.initLinkUnderlineListeners()}initReducedMotionListeners(o){this._register((0,d.addDisposableListener)(o,"change",()=>{this._systemMotionReduced=o.matches,this._configMotionReduced==="auto"&&this._onDidChangeReducedMotion.fire()}));const t=()=>{const i=this.isMotionReduced();this._layoutService.mainContainer.classList.toggle("reduce-motion",i),this._layoutService.mainContainer.classList.toggle("enable-motion",!i)};t(),this._register(this.onDidChangeReducedMotion(()=>t()))}initLinkUnderlineListeners(){this._register(this._configurationService.onDidChangeConfiguration(t=>{if(t.affectsConfiguration("accessibility.underlineLinks")){const i=this._configurationService.getValue("accessibility.underlineLinks");this._linkUnderlinesEnabled=i,this._onDidChangeLinkUnderline.fire()}}));const o=()=>{const t=this._linkUnderlinesEnabled;this._layoutService.mainContainer.classList.toggle("underline-links",t)};o(),this._register(this.onDidChangeLinkUnderlines(()=>o()))}onDidChangeLinkUnderlines(o){return this._onDidChangeLinkUnderline.event(o)}get onDidChangeScreenReaderOptimized(){return this._onDidChangeScreenReaderOptimized.event}isScreenReaderOptimized(){const o=this._configurationService.getValue("editor.accessibilitySupport");return o==="on"||o==="auto"&&this._accessibilitySupport===2}get onDidChangeReducedMotion(){return this._onDidChangeReducedMotion.event}isMotionReduced(){const o=this._configMotionReduced;return o==="on"||o==="auto"&&this._systemMotionReduced}getAccessibilitySupport(){return this._accessibilitySupport}};e.AccessibilityService=p,e.AccessibilityService=p=ke([ce(0,_.IContextKeyService),ce(1,b.ILayoutService),ce(2,m.IConfigurationService)],p)}),define(ne[395],se([1,0,353,2,119,5]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContextViewService=e.ContextViewHandler=void 0;let y=class extends k.Disposable{constructor(b){super(),this.layoutService=b,this.contextView=this._register(new d.ContextView(this.layoutService.mainContainer,1)),this.layout(),this._register(b.onDidLayoutContainer(()=>this.layout()))}showContextView(b,p,n){let o;p?p===this.layoutService.getContainer((0,E.getWindow)(p))?o=1:n?o=3:o=2:o=1,this.contextView.setContainer(p??this.layoutService.activeContainer,o),this.contextView.show(b);const t={close:()=>{this.openContextView===t&&this.hideContextView()}};return this.openContextView=t,t}layout(){this.contextView.layout()}hideContextView(b){this.contextView.hide(b),this.openContextView=void 0}};e.ContextViewHandler=y,e.ContextViewHandler=y=ke([ce(0,I.ILayoutService)],y);class m extends y{getContextViewElement(){return this.contextView.getViewElement()}}e.ContextViewService=m}),define(ne[62],se([1,0,6,2,12,7]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CONTEXT_LOG_LEVEL=e.MultiplexLogger=e.ConsoleLogger=e.AbstractLogger=e.DEFAULT_LOG_LEVEL=e.LogLevel=e.ILogService=void 0,e.LogLevelToString=p,e.ILogService=(0,E.createDecorator)("logService");var y;(function(n){n[n.Off=0]="Off",n[n.Trace=1]="Trace",n[n.Debug=2]="Debug",n[n.Info=3]="Info",n[n.Warning=4]="Warning",n[n.Error=5]="Error"})(y||(e.LogLevel=y={})),e.DEFAULT_LOG_LEVEL=y.Info;class m extends k.Disposable{constructor(){super(...arguments),this.level=e.DEFAULT_LOG_LEVEL,this._onDidChangeLogLevel=this._register(new d.Emitter),this.onDidChangeLogLevel=this._onDidChangeLogLevel.event}setLevel(o){this.level!==o&&(this.level=o,this._onDidChangeLogLevel.fire(this.level))}getLevel(){return this.level}checkLogLevel(o){return this.level!==y.Off&&this.level<=o}}e.AbstractLogger=m;class _ extends m{constructor(o=e.DEFAULT_LOG_LEVEL,t=!0){super(),this.useColors=t,this.setLevel(o)}trace(o,...t){this.checkLogLevel(y.Trace)&&(this.useColors?console.log("%cTRACE","color: #888",o,...t):console.log(o,...t))}debug(o,...t){this.checkLogLevel(y.Debug)&&(this.useColors?console.log("%cDEBUG","background: #eee; color: #888",o,...t):console.log(o,...t))}info(o,...t){this.checkLogLevel(y.Info)&&(this.useColors?console.log("%c INFO","color: #33f",o,...t):console.log(o,...t))}warn(o,...t){this.checkLogLevel(y.Warning)&&(this.useColors?console.log("%c WARN","color: #993",o,...t):console.log(o,...t))}error(o,...t){this.checkLogLevel(y.Error)&&(this.useColors?console.log("%c ERR","color: #f33",o,...t):console.error(o,...t))}}e.ConsoleLogger=_;class b extends m{constructor(o){super(),this.loggers=o,o.length&&this.setLevel(o[0].getLevel())}setLevel(o){for(const t of this.loggers)t.setLevel(o);super.setLevel(o)}trace(o,...t){for(const i of this.loggers)i.trace(o,...t)}debug(o,...t){for(const i of this.loggers)i.debug(o,...t)}info(o,...t){for(const i of this.loggers)i.info(o,...t)}warn(o,...t){for(const i of this.loggers)i.warn(o,...t)}error(o,...t){for(const i of this.loggers)i.error(o,...t)}dispose(){for(const o of this.loggers)o.dispose();super.dispose()}}e.MultiplexLogger=b;function p(n){switch(n){case y.Trace:return"trace";case y.Debug:return"debug";case y.Info:return"info";case y.Warning:return"warn";case y.Error:return"error";case y.Off:return"off"}}e.CONTEXT_LOG_LEVEL=new I.RawContextKey("logLevel",p(y.Info))}),define(ne[212],se([1,0,64,5,93,47,296,14,6,2,128,11,310,23,61,62]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TextAreaWrapper=e.ClipboardEventUtils=e.TextAreaInput=e.InMemoryClipboardMetadataManager=e.CopyOptions=e.TextAreaSyntethicEvents=void 0;var g;(function(u){u.Tap="-monaco-textarea-synthetic-tap"})(g||(e.TextAreaSyntethicEvents=g={})),e.CopyOptions={forceCopyWithSyntaxHighlighting:!1};class c{static{this.INSTANCE=new c}constructor(){this._lastState=null}set(C,f){this._lastState={lastCopiedValue:C,data:f}}get(C){return this._lastState&&this._lastState.lastCopiedValue===C?this._lastState.data:(this._lastState=null,null)}}e.InMemoryClipboardMetadataManager=c;class l{constructor(){this._lastTypeTextLength=0}handleCompositionUpdate(C){C=C||"";const f={text:C,replacePrevCharCnt:this._lastTypeTextLength,replaceNextCharCnt:0,positionDelta:0};return this._lastTypeTextLength=C.length,f}}let a=class extends b.Disposable{get textAreaState(){return this._textAreaState}constructor(C,f,h,v,w,S){super(),this._host=C,this._textArea=f,this._OS=h,this._browser=v,this._accessibilityService=w,this._logService=S,this._onFocus=this._register(new _.Emitter),this.onFocus=this._onFocus.event,this._onBlur=this._register(new _.Emitter),this.onBlur=this._onBlur.event,this._onKeyDown=this._register(new _.Emitter),this.onKeyDown=this._onKeyDown.event,this._onKeyUp=this._register(new _.Emitter),this.onKeyUp=this._onKeyUp.event,this._onCut=this._register(new _.Emitter),this.onCut=this._onCut.event,this._onPaste=this._register(new _.Emitter),this.onPaste=this._onPaste.event,this._onType=this._register(new _.Emitter),this.onType=this._onType.event,this._onCompositionStart=this._register(new _.Emitter),this.onCompositionStart=this._onCompositionStart.event,this._onCompositionUpdate=this._register(new _.Emitter),this.onCompositionUpdate=this._onCompositionUpdate.event,this._onCompositionEnd=this._register(new _.Emitter),this.onCompositionEnd=this._onCompositionEnd.event,this._onSelectionChangeRequest=this._register(new _.Emitter),this.onSelectionChangeRequest=this._onSelectionChangeRequest.event,this._asyncFocusGainWriteScreenReaderContent=this._register(new b.MutableDisposable),this._asyncTriggerCut=this._register(new m.RunOnceScheduler(()=>this._onCut.fire(),0)),this._textAreaState=o.TextAreaState.EMPTY,this._selectionChangeListener=null,this._accessibilityService.isScreenReaderOptimized()&&this.writeNativeTextAreaContent("ctor"),this._register(_.Event.runAndSubscribe(this._accessibilityService.onDidChangeScreenReaderOptimized,()=>{this._accessibilityService.isScreenReaderOptimized()&&!this._asyncFocusGainWriteScreenReaderContent.value?this._asyncFocusGainWriteScreenReaderContent.value=this._register(new m.RunOnceScheduler(()=>this.writeNativeTextAreaContent("asyncFocusGain"),0)):this._asyncFocusGainWriteScreenReaderContent.clear()})),this._hasFocus=!1,this._currentComposition=null;let L=null;this._register(this._textArea.onKeyDown(D=>{const T=new E.StandardKeyboardEvent(D);(T.keyCode===114||this._currentComposition&&T.keyCode===1)&&T.stopPropagation(),T.equals(9)&&T.preventDefault(),L=T,this._onKeyDown.fire(T)})),this._register(this._textArea.onKeyUp(D=>{const T=new E.StandardKeyboardEvent(D);this._onKeyUp.fire(T)})),this._register(this._textArea.onCompositionStart(D=>{o._debugComposition&&console.log("[compositionstart]",D);const T=new l;if(this._currentComposition){this._currentComposition=T;return}if(this._currentComposition=T,this._OS===2&&L&&L.equals(114)&&this._textAreaState.selectionStart===this._textAreaState.selectionEnd&&this._textAreaState.selectionStart>0&&this._textAreaState.value.substr(this._textAreaState.selectionStart-1,1)===D.data&&(L.code==="ArrowRight"||L.code==="ArrowLeft")){o._debugComposition&&console.log("[compositionstart] Handling long press case on macOS + arrow key",D),T.handleCompositionUpdate("x"),this._onCompositionStart.fire({data:D.data});return}if(this._browser.isAndroid){this._onCompositionStart.fire({data:D.data});return}this._onCompositionStart.fire({data:D.data})})),this._register(this._textArea.onCompositionUpdate(D=>{o._debugComposition&&console.log("[compositionupdate]",D);const T=this._currentComposition;if(!T)return;if(this._browser.isAndroid){const A=o.TextAreaState.readFromTextArea(this._textArea,this._textAreaState),P=o.TextAreaState.deduceAndroidCompositionInput(this._textAreaState,A);this._textAreaState=A,this._onType.fire(P),this._onCompositionUpdate.fire(D);return}const M=T.handleCompositionUpdate(D.data);this._textAreaState=o.TextAreaState.readFromTextArea(this._textArea,this._textAreaState),this._onType.fire(M),this._onCompositionUpdate.fire(D)})),this._register(this._textArea.onCompositionEnd(D=>{o._debugComposition&&console.log("[compositionend]",D);const T=this._currentComposition;if(!T)return;if(this._currentComposition=null,this._browser.isAndroid){const A=o.TextAreaState.readFromTextArea(this._textArea,this._textAreaState),P=o.TextAreaState.deduceAndroidCompositionInput(this._textAreaState,A);this._textAreaState=A,this._onType.fire(P),this._onCompositionEnd.fire();return}const M=T.handleCompositionUpdate(D.data);this._textAreaState=o.TextAreaState.readFromTextArea(this._textArea,this._textAreaState),this._onType.fire(M),this._onCompositionEnd.fire()})),this._register(this._textArea.onInput(D=>{if(o._debugComposition&&console.log("[input]",D),this._textArea.setIgnoreSelectionChangeTime("received input event"),this._currentComposition)return;const T=o.TextAreaState.readFromTextArea(this._textArea,this._textAreaState),M=o.TextAreaState.deduceInput(this._textAreaState,T,this._OS===2);M.replacePrevCharCnt===0&&M.text.length===1&&(n.isHighSurrogate(M.text.charCodeAt(0))||M.text.charCodeAt(0)===127)||(this._textAreaState=T,(M.text!==""||M.replacePrevCharCnt!==0||M.replaceNextCharCnt!==0||M.positionDelta!==0)&&this._onType.fire(M))})),this._register(this._textArea.onCut(D=>{this._textArea.setIgnoreSelectionChangeTime("received cut event"),this._ensureClipboardGetsEditorSelection(D),this._asyncTriggerCut.schedule()})),this._register(this._textArea.onCopy(D=>{this._ensureClipboardGetsEditorSelection(D)})),this._register(this._textArea.onPaste(D=>{if(this._textArea.setIgnoreSelectionChangeTime("received paste event"),D.preventDefault(),!D.clipboardData)return;let[T,M]=e.ClipboardEventUtils.getTextData(D.clipboardData);T&&(M=M||c.INSTANCE.get(T),this._onPaste.fire({text:T,metadata:M}))})),this._register(this._textArea.onFocus(()=>{const D=this._hasFocus;this._setHasFocus(!0),this._accessibilityService.isScreenReaderOptimized()&&this._browser.isSafari&&!D&&this._hasFocus&&(this._asyncFocusGainWriteScreenReaderContent.value||(this._asyncFocusGainWriteScreenReaderContent.value=new m.RunOnceScheduler(()=>this.writeNativeTextAreaContent("asyncFocusGain"),0)),this._asyncFocusGainWriteScreenReaderContent.value.schedule())})),this._register(this._textArea.onBlur(()=>{this._currentComposition&&(this._currentComposition=null,this.writeNativeTextAreaContent("blurWithoutCompositionEnd"),this._onCompositionEnd.fire()),this._setHasFocus(!1)})),this._register(this._textArea.onSyntheticTap(()=>{this._browser.isAndroid&&this._currentComposition&&(this._currentComposition=null,this.writeNativeTextAreaContent("tapWithoutCompositionEnd"),this._onCompositionEnd.fire())}))}_installSelectionChangeListener(){let C=0;return k.addDisposableListener(this._textArea.ownerDocument,"selectionchange",f=>{if(y.inputLatency.onSelectionChange(),!this._hasFocus||this._currentComposition||!this._browser.isChrome)return;const h=Date.now(),v=h-C;if(C=h,v<5)return;const w=h-this._textArea.getIgnoreSelectionChangeTime();if(this._textArea.resetSelectionChangeTime(),w<100||!this._textAreaState.selection)return;const S=this._textArea.getValue();if(this._textAreaState.value!==S)return;const L=this._textArea.getSelectionStart(),D=this._textArea.getSelectionEnd();if(this._textAreaState.selectionStart===L&&this._textAreaState.selectionEnd===D)return;const T=this._textAreaState.deduceEditorPosition(L),M=this._host.deduceModelPosition(T[0],T[1],T[2]),A=this._textAreaState.deduceEditorPosition(D),P=this._host.deduceModelPosition(A[0],A[1],A[2]),N=new t.Selection(M.lineNumber,M.column,P.lineNumber,P.column);this._onSelectionChangeRequest.fire(N)})}dispose(){super.dispose(),this._selectionChangeListener&&(this._selectionChangeListener.dispose(),this._selectionChangeListener=null)}focusTextArea(){this._setHasFocus(!0),this.refreshFocusState()}isFocused(){return this._hasFocus}refreshFocusState(){this._setHasFocus(this._textArea.hasFocus())}_setHasFocus(C){this._hasFocus!==C&&(this._hasFocus=C,this._selectionChangeListener&&(this._selectionChangeListener.dispose(),this._selectionChangeListener=null),this._hasFocus&&(this._selectionChangeListener=this._installSelectionChangeListener()),this._hasFocus&&this.writeNativeTextAreaContent("focusgain"),this._hasFocus?this._onFocus.fire():this._onBlur.fire())}_setAndWriteTextAreaState(C,f){this._hasFocus||(f=f.collapseSelection()),f.writeToTextArea(C,this._textArea,this._hasFocus),this._textAreaState=f}writeNativeTextAreaContent(C){!this._accessibilityService.isScreenReaderOptimized()&&C==="render"||this._currentComposition||(this._logService.trace(`writeTextAreaState(reason: ${C})`),this._setAndWriteTextAreaState(C,this._host.getScreenReaderContent()))}_ensureClipboardGetsEditorSelection(C){const f=this._host.getDataToCopy(),h={version:1,isFromEmptySelection:f.isFromEmptySelection,multicursorText:f.multicursorText,mode:f.mode};c.INSTANCE.set(this._browser.isFirefox?f.text.replace(/\r\n/g,` `):f.text,h),C.preventDefault(),C.clipboardData&&e.ClipboardEventUtils.setTextData(C.clipboardData,f.text,f.html,h)}};e.TextAreaInput=a,e.TextAreaInput=a=ke([ce(4,i.IAccessibilityService),ce(5,s.ILogService)],a),e.ClipboardEventUtils={getTextData(u){const C=u.getData(p.Mimes.text);let f=null;const h=u.getData("vscode-editor-data");if(typeof h=="string")try{f=JSON.parse(h),f.version!==1&&(f=null)}catch{}return C.length===0&&f===null&&u.files.length>0?[Array.prototype.slice.call(u.files,0).map(w=>w.name).join(` `),null]:[C,f]},setTextData(u,C,f,h){u.setData(p.Mimes.text,C),typeof f=="string"&&u.setData("text/html",f),u.setData("vscode-editor-data",JSON.stringify(h))}};class r extends b.Disposable{get ownerDocument(){return this._actual.ownerDocument}constructor(C){super(),this._actual=C,this.onKeyDown=this._register(new I.DomEmitter(this._actual,"keydown")).event,this.onKeyUp=this._register(new I.DomEmitter(this._actual,"keyup")).event,this.onCompositionStart=this._register(new I.DomEmitter(this._actual,"compositionstart")).event,this.onCompositionUpdate=this._register(new I.DomEmitter(this._actual,"compositionupdate")).event,this.onCompositionEnd=this._register(new I.DomEmitter(this._actual,"compositionend")).event,this.onBeforeInput=this._register(new I.DomEmitter(this._actual,"beforeinput")).event,this.onInput=this._register(new I.DomEmitter(this._actual,"input")).event,this.onCut=this._register(new I.DomEmitter(this._actual,"cut")).event,this.onCopy=this._register(new I.DomEmitter(this._actual,"copy")).event,this.onPaste=this._register(new I.DomEmitter(this._actual,"paste")).event,this.onFocus=this._register(new I.DomEmitter(this._actual,"focus")).event,this.onBlur=this._register(new I.DomEmitter(this._actual,"blur")).event,this._onSyntheticTap=this._register(new _.Emitter),this.onSyntheticTap=this._onSyntheticTap.event,this._ignoreSelectionChangeTime=0,this._register(this.onKeyDown(()=>y.inputLatency.onKeyDown())),this._register(this.onBeforeInput(()=>y.inputLatency.onBeforeInput())),this._register(this.onInput(()=>y.inputLatency.onInput())),this._register(this.onKeyUp(()=>y.inputLatency.onKeyUp())),this._register(k.addDisposableListener(this._actual,g.Tap,()=>this._onSyntheticTap.fire()))}hasFocus(){const C=k.getShadowRoot(this._actual);return C?C.activeElement===this._actual:this._actual.isConnected?k.getActiveElement()===this._actual:!1}setIgnoreSelectionChangeTime(C){this._ignoreSelectionChangeTime=Date.now()}getIgnoreSelectionChangeTime(){return this._ignoreSelectionChangeTime}resetSelectionChangeTime(){this._ignoreSelectionChangeTime=0}getValue(){return this._actual.value}setValue(C,f){const h=this._actual;h.value!==f&&(this.setIgnoreSelectionChangeTime("setValue"),h.value=f)}getSelectionStart(){return this._actual.selectionDirection==="backward"?this._actual.selectionEnd:this._actual.selectionStart}getSelectionEnd(){return this._actual.selectionDirection==="backward"?this._actual.selectionStart:this._actual.selectionEnd}setSelectionRange(C,f,h){const v=this._actual;let w=null;const S=k.getShadowRoot(v);S?w=S.activeElement:w=k.getActiveElement();const L=k.getWindow(w),D=w===v,T=v.selectionStart,M=v.selectionEnd;if(D&&T===f&&M===h){d.isFirefox&&L.parent!==L&&v.focus();return}if(D){this.setIgnoreSelectionChangeTime("setSelectionRange"),v.setSelectionRange(f,h),d.isFirefox&&L.parent!==L&&v.focus();return}try{const A=k.saveParentsScrollTop(v);this.setIgnoreSelectionChangeTime("setSelectionRange"),v.focus(),v.setSelectionRange(f,h),k.restoreParentsScrollTop(v,A)}catch{}}}e.TextAreaWrapper=r}),define(ne[79],se([1,0,129,45,141,271,49,7,62,42]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LanguageFeatureDebounceService=e.ILanguageFeatureDebounceService=void 0,e.ILanguageFeatureDebounceService=(0,m.createDecorator)("ILanguageFeatureDebounceService");var p;(function(i){const s=new WeakMap;let g=0;function c(l){let a=s.get(l);return a===void 0&&(a=++g,s.set(l,a)),a}i.of=c})(p||(p={}));class n{constructor(s){this._default=s}get(s){return this._default}update(s,g){return this._default}default(){return this._default}}class o{constructor(s,g,c,l,a,r){this._logService=s,this._name=g,this._registry=c,this._default=l,this._min=a,this._max=r,this._cache=new k.LRUCache(50,.7)}_key(s){return s.id+this._registry.all(s).reduce((g,c)=>(0,d.doHash)(p.of(c),g),0)}get(s){const g=this._key(s),c=this._cache.get(g);return c?(0,I.clamp)(c.value,this._min,this._max):this.default()}update(s,g){const c=this._key(s);let l=this._cache.get(c);l||(l=new I.SlidingWindowAverage(6),this._cache.set(c,l));const a=(0,I.clamp)(l.update(g),this._min,this._max);return(0,b.matchesScheme)(s.uri,"output")||this._logService.trace(`[DEBOUNCE: ${this._name}] for ${s.uri.toString()} is ${a}ms`),a}_overall(){const s=new I.MovingAverage;for(const[,g]of this._cache)s.update(g.value);return s.value}default(){const s=this._overall()|0||this._default;return(0,I.clamp)(s,this._min,this._max)}}let t=class{constructor(s,g){this._logService=s,this._data=new Map,this._isDev=g.isExtensionDevelopment||!g.isBuilt}for(s,g,c){const l=c?.min??50,a=c?.max??l**2,r=c?.key??void 0,u=`${p.of(s)},${l}${r?","+r:""}`;let C=this._data.get(u);return C||(this._isDev?(this._logService.debug(`[DEBOUNCE: ${g}] is disabled in developed mode`),C=new n(l*1.5)):C=new o(this._logService,g,s,this._overallAverage()|0||l*1.5,l,a),this._data.set(u,C)),C}_overallAverage(){const s=new I.MovingAverage;for(const g of this._data.values())s.update(g.default());return s.value}};e.LanguageFeatureDebounceService=t,e.LanguageFeatureDebounceService=t=ke([ce(0,_.ILogService),ce(1,E.IEnvironmentService)],t),(0,y.registerSingleton)(e.ILanguageFeatureDebounceService,t,1)}),define(ne[182],se([1,0,13,18,8,53,45,9,4,79,7,49,51,2,17]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OutlineModelService=e.IOutlineModelService=e.OutlineModel=e.OutlineGroup=e.OutlineElement=e.TreeElement=void 0;class s{remove(){this.parent?.children.delete(this.id)}static findId(u,C){let f;typeof u=="string"?f=`${C.id}/${u}`:(f=`${C.id}/${u.name}`,C.children.get(f)!==void 0&&(f=`${C.id}/${u.name}_${u.range.startLineNumber}_${u.range.startColumn}`));let h=f;for(let v=0;C.children.get(h)!==void 0;v++)h=`${f}_${v}`;return h}static empty(u){return u.children.size===0}}e.TreeElement=s;class g extends s{constructor(u,C,f){super(),this.id=u,this.parent=C,this.symbol=f,this.children=new Map}}e.OutlineElement=g;class c extends s{constructor(u,C,f,h){super(),this.id=u,this.parent=C,this.label=f,this.order=h,this.children=new Map}}e.OutlineGroup=c;class l extends s{static create(u,C,f){const h=new k.CancellationTokenSource(f),v=new l(C.uri),w=u.ordered(C),S=w.map((D,T)=>{const M=s.findId(`provider_${T}`,v),A=new c(M,v,D.displayName??"Unknown Outline Provider",T);return Promise.resolve(D.provideDocumentSymbols(C,h.token)).then(P=>{for(const N of P||[])l._makeOutlineElement(N,A);return A},P=>((0,I.onUnexpectedExternalError)(P),A)).then(P=>{s.empty(P)?P.remove():v._groups.set(M,P)})}),L=u.onDidChange(()=>{const D=u.ordered(C);(0,d.equals)(D,w)||h.cancel()});return Promise.all(S).then(()=>h.token.isCancellationRequested&&!f.isCancellationRequested?l.create(u,C,f):v._compact()).finally(()=>{h.dispose(),L.dispose(),h.dispose()})}static _makeOutlineElement(u,C){const f=s.findId(u,C),h=new g(f,C,u);if(u.children)for(const v of u.children)l._makeOutlineElement(v,h);C.children.set(h.id,h)}constructor(u){super(),this.uri=u,this.id="root",this.parent=void 0,this._groups=new Map,this.children=new Map,this.id="root",this.parent=void 0}_compact(){let u=0;for(const[C,f]of this._groups)f.children.size===0?this._groups.delete(C):u+=1;if(u!==1)this.children=this._groups;else{const C=E.Iterable.first(this._groups.values());for(const[,f]of C.children)f.parent=this,this.children.set(f.id,f)}return this}getTopLevelSymbols(){const u=[];for(const C of this.children.values())C instanceof g?u.push(C.symbol):u.push(...E.Iterable.map(C.children.values(),f=>f.symbol));return u.sort((C,f)=>_.Range.compareRangesUsingStarts(C.range,f.range))}asListOfDocumentSymbols(){const u=this.getTopLevelSymbols(),C=[];return l._flattenDocumentSymbols(C,u,""),C.sort((f,h)=>m.Position.compare(_.Range.getStartPosition(f.range),_.Range.getStartPosition(h.range))||m.Position.compare(_.Range.getEndPosition(h.range),_.Range.getEndPosition(f.range)))}static _flattenDocumentSymbols(u,C,f){for(const h of C)u.push({kind:h.kind,tags:h.tags,name:h.name,detail:h.detail,containerName:h.containerName||f,range:h.range,selectionRange:h.selectionRange,children:void 0}),h.children&&l._flattenDocumentSymbols(u,h.children,h.name)}}e.OutlineModel=l,e.IOutlineModelService=(0,p.createDecorator)("IOutlineModelService");let a=class{constructor(u,C,f){this._languageFeaturesService=u,this._disposables=new t.DisposableStore,this._cache=new y.LRUCache(10,.7),this._debounceInformation=C.for(u.documentSymbolProvider,"DocumentSymbols",{min:350}),this._disposables.add(f.onModelRemoved(h=>{this._cache.delete(h.id)}))}dispose(){this._disposables.dispose()}async getOrCreate(u,C){const f=this._languageFeaturesService.documentSymbolProvider,h=f.ordered(u);let v=this._cache.get(u.id);if(!v||v.versionId!==u.getVersionId()||!(0,d.equals)(v.provider,h)){const S=new k.CancellationTokenSource;v={versionId:u.getVersionId(),provider:h,promiseCnt:0,source:S,promise:l.create(f,u,S.token),model:void 0},this._cache.set(u.id,v);const L=Date.now();v.promise.then(D=>{v.model=D,this._debounceInformation.update(u,Date.now()-L)}).catch(D=>{this._cache.delete(u.id)})}if(v.model)return v.model;v.promiseCnt+=1;const w=C.onCancellationRequested(()=>{--v.promiseCnt===0&&(v.source.cancel(),this._cache.delete(u.id))});try{return await v.promise}finally{w.dispose()}}};e.OutlineModelService=a,e.OutlineModelService=a=ke([ce(0,i.ILanguageFeaturesService),ce(1,b.ILanguageFeatureDebounceService),ce(2,o.IModelService)],a),(0,n.registerSingleton)(e.IOutlineModelService,a,1)}),define(ne[694],se([1,0,13,21,383,88,17,182,2,6]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0});let p=class extends _.Disposable{constructor(o,t,i){super(),this._textModel=o,this._languageFeaturesService=t,this._outlineModelService=i,this._currentModel=(0,k.observableValue)(this,void 0);const s=(0,k.observableSignalFromEvent)("documentSymbolProvider.onDidChange",this._languageFeaturesService.documentSymbolProvider.onDidChange),g=(0,k.observableSignalFromEvent)("_textModel.onDidChangeContent",b.Event.debounce(c=>this._textModel.onDidChangeContent(c),()=>{},100));this._register((0,k.autorunWithStore)(async(c,l)=>{s.read(c),g.read(c);const a=l.add(new E.DisposableCancellationTokenSource),r=await this._outlineModelService.getOrCreate(this._textModel,a.token);l.isDisposed||this._currentModel.set(r,void 0)}))}getBreadcrumbItems(o,t){const i=this._currentModel.read(t);if(!i)return[];const s=i.asListOfDocumentSymbols().filter(g=>o.contains(g.range.startLineNumber)&&!o.contains(g.range.endLineNumber));return s.sort((0,d.reverseOrder)((0,d.compareBy)(g=>g.range.endLineNumber-g.range.startLineNumber,d.numberComparator))),s.map(g=>({name:g.name,kind:g.kind,startLineNumber:g.range.startLineNumber}))}};p=ke([ce(1,y.ILanguageFeaturesService),ce(2,m.IOutlineModelService)],p),I.HideUnchangedRegionsFeature.setBreadcrumbsSourceFactory((n,o)=>o.createInstance(p,n))}),define(ne[695],se([1,0,18,19,22,78,182,24]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),m.CommandsRegistry.registerCommand("_executeDocumentSymbolProvider",async function(_,...b){const[p]=b;(0,k.assertType)(I.URI.isUri(p));const n=_.get(y.IOutlineModelService),t=await _.get(E.ITextModelService).createModelReference(p);try{return(await n.getOrCreate(t.object.textEditorModel,d.CancellationToken.None)).getTopLevelSymbols()}finally{t.dispose()}})}),define(ne[696],se([1,0,64,5,52,14,6,129,2,22,119,62]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";var o;Object.defineProperty(e,"__esModule",{value:!0}),e.BrowserClipboardService=void 0;const t="application/vnd.code.resources";let i=class extends _.Disposable{static{o=this}constructor(g,c){super(),this.layoutService=g,this.logService=c,this.mapTextToType=new Map,this.findText="",this.resources=[],this.resourcesStateHash=void 0,(d.isSafari||d.isWebkitWebView)&&this.installWebKitWriteTextWorkaround(),this._register(y.Event.runAndSubscribe(k.onDidRegisterWindow,({window:l,disposables:a})=>{a.add((0,k.addDisposableListener)(l.document,"copy",()=>this.clearResourcesState()))},{window:I.mainWindow,disposables:this._store}))}installWebKitWriteTextWorkaround(){const g=()=>{const c=new E.DeferredPromise;this.webKitPendingClipboardWritePromise&&!this.webKitPendingClipboardWritePromise.isSettled&&this.webKitPendingClipboardWritePromise.cancel(),this.webKitPendingClipboardWritePromise=c,(0,k.getActiveWindow)().navigator.clipboard.write([new ClipboardItem({"text/plain":c.p})]).catch(async l=>{(!(l instanceof Error)||l.name!=="NotAllowedError"||!c.isRejected)&&this.logService.error(l)})};this._register(y.Event.runAndSubscribe(this.layoutService.onDidAddContainer,({container:c,disposables:l})=>{l.add((0,k.addDisposableListener)(c,"click",g)),l.add((0,k.addDisposableListener)(c,"keydown",g))},{container:this.layoutService.mainContainer,disposables:this._store}))}async writeText(g,c){if(this.clearResourcesState(),c){this.mapTextToType.set(c,g);return}if(this.webKitPendingClipboardWritePromise)return this.webKitPendingClipboardWritePromise.complete(g);try{return await(0,k.getActiveWindow)().navigator.clipboard.writeText(g)}catch(l){console.error(l)}this.fallbackWriteText(g)}fallbackWriteText(g){const c=(0,k.getActiveDocument)(),l=c.activeElement,a=c.body.appendChild((0,k.$)("textarea",{"aria-hidden":!0}));a.style.height="1px",a.style.width="1px",a.style.position="absolute",a.value=g,a.focus(),a.select(),c.execCommand("copy"),(0,k.isHTMLElement)(l)&&l.focus(),a.remove()}async readText(g){if(g)return this.mapTextToType.get(g)||"";try{return await(0,k.getActiveWindow)().navigator.clipboard.readText()}catch(c){console.error(c)}return""}async readFindText(){return this.findText}async writeFindText(g){this.findText=g}static{this.MAX_RESOURCE_STATE_SOURCE_LENGTH=1e3}async readResources(){try{const c=await(0,k.getActiveWindow)().navigator.clipboard.read();for(const l of c)if(l.types.includes(`web ${t}`)){const a=await l.getType(`web ${t}`);return JSON.parse(await a.text()).map(u=>b.URI.from(u))}}catch{}const g=await this.computeResourcesStateHash();return this.resourcesStateHash!==g&&this.clearResourcesState(),this.resources}async computeResourcesStateHash(){if(this.resources.length===0)return;const g=await this.readText();return(0,m.hash)(g.substring(0,o.MAX_RESOURCE_STATE_SOURCE_LENGTH))}clearInternalState(){this.clearResourcesState()}clearResourcesState(){this.resources=[],this.resourcesStateHash=void 0}};e.BrowserClipboardService=i,e.BrowserClipboardService=i=o=ke([ce(0,p.ILayoutService),ce(1,n.ILogService)],i)}),define(ne[697],se([1,0,2,62]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LogService=void 0;class I extends d.Disposable{constructor(y,m=[]){super(),this.logger=new k.MultiplexLogger([y,...m]),this._register(y.onDidChangeLogLevel(_=>this.setLevel(_)))}get onDidChangeLogLevel(){return this.logger.onDidChangeLogLevel}setLevel(y){this.logger.setLevel(y)}getLevel(){return this.logger.getLevel()}trace(y,...m){this.logger.trace(y,...m)}debug(y,...m){this.logger.debug(y,...m)}info(y,...m){this.logger.info(y,...m)}warn(y,...m){this.logger.warn(y,...m)}error(y,...m){this.logger.error(y,...m)}}e.LogService=I}),define(ne[108],se([1,0,111,3,7]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IMarkerService=e.IMarkerData=e.MarkerSeverity=void 0;var E;(function(m){m[m.Hint=1]="Hint",m[m.Info=2]="Info",m[m.Warning=4]="Warning",m[m.Error=8]="Error"})(E||(e.MarkerSeverity=E={})),function(m){function _(t,i){return i-t}m.compare=_;const b=Object.create(null);b[m.Error]=(0,k.localize)(1569,"Error"),b[m.Warning]=(0,k.localize)(1570,"Warning"),b[m.Info]=(0,k.localize)(1571,"Info");function p(t){return b[t]||""}m.toString=p;function n(t){switch(t){case d.default.Error:return m.Error;case d.default.Warning:return m.Warning;case d.default.Info:return m.Info;case d.default.Ignore:return m.Hint}}m.fromSeverity=n;function o(t){switch(t){case m.Error:return d.default.Error;case m.Warning:return d.default.Warning;case m.Info:return d.default.Info;case m.Hint:return d.default.Ignore}}m.toSeverity=o}(E||(e.MarkerSeverity=E={}));var y;(function(m){const _="";function b(n){return p(n,!0)}m.makeKey=b;function p(n,o){const t=[_];return n.source?t.push(n.source.replace("\xA6","\\\xA6")):t.push(_),n.code?typeof n.code=="string"?t.push(n.code.replace("\xA6","\\\xA6")):t.push(n.code.value.replace("\xA6","\\\xA6")):t.push(_),n.severity!==void 0&&n.severity!==null?t.push(E.toString(n.severity)):t.push(_),n.message&&o?t.push(n.message.replace("\xA6","\\\xA6")):t.push(_),n.startLineNumber!==void 0&&n.startLineNumber!==null?t.push(n.startLineNumber.toString()):t.push(_),n.startColumn!==void 0&&n.startColumn!==null?t.push(n.startColumn.toString()):t.push(_),n.endLineNumber!==void 0&&n.endLineNumber!==null?t.push(n.endLineNumber.toString()):t.push(_),n.endColumn!==void 0&&n.endColumn!==null?t.push(n.endColumn.toString()):t.push(_),t.push(_),t.join("\xA6")}m.makeKeyOptionalMessage=p})(y||(e.IMarkerData=y={})),e.IMarkerService=(0,I.createDecorator)("markerService")}),define(ne[698],se([1,0,13,6,2,73,11,22,4,49,7,108,28]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IMarkerNavigationService=e.MarkerList=e.MarkerCoordinate=void 0;class t{constructor(c,l,a){this.marker=c,this.index=l,this.total=a}}e.MarkerCoordinate=t;let i=class{constructor(c,l,a){this._markerService=l,this._configService=a,this._onDidChange=new k.Emitter,this.onDidChange=this._onDidChange.event,this._dispoables=new I.DisposableStore,this._markers=[],this._nextIdx=-1,m.URI.isUri(c)?this._resourceFilter=f=>f.toString()===c.toString():c&&(this._resourceFilter=c);const r=this._configService.getValue("problems.sortOrder"),u=(f,h)=>{let v=(0,y.compare)(f.resource.toString(),h.resource.toString());return v===0&&(r==="position"?v=_.Range.compareRangesUsingStarts(f,h)||n.MarkerSeverity.compare(f.severity,h.severity):v=n.MarkerSeverity.compare(f.severity,h.severity)||_.Range.compareRangesUsingStarts(f,h)),v},C=()=>{this._markers=this._markerService.read({resource:m.URI.isUri(c)?c:void 0,severities:n.MarkerSeverity.Error|n.MarkerSeverity.Warning|n.MarkerSeverity.Info}),typeof c=="function"&&(this._markers=this._markers.filter(f=>this._resourceFilter(f.resource))),this._markers.sort(u)};C(),this._dispoables.add(l.onMarkerChanged(f=>{(!this._resourceFilter||f.some(h=>this._resourceFilter(h)))&&(C(),this._nextIdx=-1,this._onDidChange.fire())}))}dispose(){this._dispoables.dispose(),this._onDidChange.dispose()}matches(c){return!this._resourceFilter&&!c?!0:!this._resourceFilter||!c?!1:this._resourceFilter(c)}get selected(){const c=this._markers[this._nextIdx];return c&&new t(c,this._nextIdx+1,this._markers.length)}_initIdx(c,l,a){let r=!1,u=this._markers.findIndex(C=>C.resource.toString()===c.uri.toString());u<0&&(u=(0,d.binarySearch)(this._markers,{resource:c.uri},(C,f)=>(0,y.compare)(C.resource.toString(),f.resource.toString())),u<0&&(u=~u));for(let C=u;Cr.resource.toString()===c.toString());if(!(a<0)){for(;ai[1])}}class p{constructor(t){this.errors=0,this.infos=0,this.warnings=0,this.unknowns=0,this._data=new E.ResourceMap,this._service=t,this._subscription=t.onMarkerChanged(this._update,this)}dispose(){this._subscription.dispose()}_update(t){for(const i of t){const s=this._data.get(i);s&&this._substract(s);const g=this._resourceStats(i);this._add(g),this._data.set(i,g)}}_resourceStats(t){const i={errors:0,warnings:0,infos:0,unknowns:0};if(e.unsupportedSchemas.has(t.scheme))return i;for(const{severity:s}of this._service.read({resource:t}))s===_.MarkerSeverity.Error?i.errors+=1:s===_.MarkerSeverity.Warning?i.warnings+=1:s===_.MarkerSeverity.Info?i.infos+=1:i.unknowns+=1;return i}_substract(t){this.errors-=t.errors,this.warnings-=t.warnings,this.infos-=t.infos,this.unknowns-=t.unknowns}_add(t){this.errors+=t.errors,this.warnings+=t.warnings,this.infos+=t.infos,this.unknowns+=t.unknowns}}class n{constructor(){this._onMarkerChanged=new k.DebounceEmitter({delay:0,merge:n._merge}),this.onMarkerChanged=this._onMarkerChanged.event,this._data=new b,this._stats=new p(this)}dispose(){this._stats.dispose(),this._onMarkerChanged.dispose()}remove(t,i){for(const s of i||[])this.changeOne(t,s,[])}changeOne(t,i,s){if((0,d.isFalsyOrEmpty)(s))this._data.delete(i,t)&&this._onMarkerChanged.fire([i]);else{const g=[];for(const c of s){const l=n._toMarker(t,i,c);l&&g.push(l)}this._data.set(i,t,g),this._onMarkerChanged.fire([i])}}static _toMarker(t,i,s){let{code:g,severity:c,message:l,source:a,startLineNumber:r,startColumn:u,endLineNumber:C,endColumn:f,relatedInformation:h,tags:v}=s;if(l)return r=r>0?r:1,u=u>0?u:1,C=C>=r?C:r,f=f>0?f:u,{resource:i,owner:t,code:g,severity:c,message:l,source:a,startLineNumber:r,startColumn:u,endLineNumber:C,endColumn:f,relatedInformation:h,tags:v}}changeAll(t,i){const s=[],g=this._data.values(t);if(g)for(const c of g){const l=I.Iterable.first(c);l&&(s.push(l.resource),this._data.delete(l.resource,t))}if((0,d.isNonEmptyArray)(i)){const c=new E.ResourceMap;for(const{resource:l,marker:a}of i){const r=n._toMarker(t,l,a);if(!r)continue;const u=c.get(l);u?u.push(r):(c.set(l,[r]),s.push(l))}for(const[l,a]of c)this._data.set(l,t,a)}s.length>0&&this._onMarkerChanged.fire(s)}read(t=Object.create(null)){let{owner:i,resource:s,severities:g,take:c}=t;if((!c||c<0)&&(c=-1),i&&s){const l=this._data.get(s,i);if(l){const a=[];for(const r of l)if(n._accept(r,g)){const u=a.push(r);if(c>0&&u===c)break}return a}else return[]}else if(!i&&!s){const l=[];for(const a of this._data.values())for(const r of a)if(n._accept(r,g)){const u=l.push(r);if(c>0&&u===c)return l}return l}else{const l=this._data.values(s??i),a=[];for(const r of l)for(const u of r)if(n._accept(u,g)){const C=a.push(u);if(c>0&&C===c)return a}return a}}static _accept(t,i){return i===void 0||(i&t.severity)===t.severity}static _merge(t){const i=new E.ResourceMap;for(const s of t)for(const g of s)i.set(g,!0);return Array.from(i.keys())}}e.MarkerService=n}),define(ne[50],se([1,0,111,7]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.NoOpNotification=e.INotificationService=e.Severity=void 0,e.Severity=d.default,e.INotificationService=(0,k.createDecorator)("notificationService");class I{}e.NoOpNotification=I}),define(ne[396],se([1,0,5,258,41,346,8,6,2,152,268,3,12,58,7,31,50,508]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";var c;Object.defineProperty(e,"__esModule",{value:!0}),e.PostEditWidgetManager=void 0;let l=class extends _.Disposable{static{c=this}static{this.baseId="editor.widget.postEditWidget"}constructor(u,C,f,h,v,w,S,L,D,T){super(),this.typeId=u,this.editor=C,this.showCommand=h,this.range=v,this.edits=w,this.onSelectNewEdit=S,this._contextMenuService=L,this._keybindingService=T,this.allowEditorOverflow=!0,this.suppressMouseDown=!0,this.create(),this.visibleContext=f.bindTo(D),this.visibleContext.set(!0),this._register((0,_.toDisposable)(()=>this.visibleContext.reset())),this.editor.addContentWidget(this),this.editor.layoutContentWidget(this),this._register((0,_.toDisposable)(()=>this.editor.removeContentWidget(this))),this._register(this.editor.onDidChangeCursorPosition(M=>{v.containsPosition(M.position)||this.dispose()})),this._register(m.Event.runAndSubscribe(T.onDidUpdateKeybindings,()=>{this._updateButtonTitle()}))}_updateButtonTitle(){const u=this._keybindingService.lookupKeybinding(this.showCommand.id)?.getLabel();this.button.element.title=this.showCommand.label+(u?` (${u})`:"")}create(){this.domNode=d.$(".post-edit-widget"),this.button=this._register(new k.Button(this.domNode,{supportIcons:!0})),this.button.label="$(insert)",this._register(d.addDisposableListener(this.domNode,d.EventType.CLICK,()=>this.showSelector()))}getId(){return c.baseId+"."+this.typeId}getDomNode(){return this.domNode}getPosition(){return{position:this.range.getEndPosition(),preference:[2]}}showSelector(){this._contextMenuService.showContextMenu({getAnchor:()=>{const u=d.getDomNodePagePosition(this.button.element);return{x:u.left+u.width,y:u.top+u.height}},getActions:()=>this.edits.allEdits.map((u,C)=>(0,I.toAction)({id:"",label:u.title,checked:C===this.edits.activeEditIndex,run:()=>{if(C!==this.edits.activeEditIndex)return this.onSelectNewEdit(C)}}))})}};l=c=ke([ce(7,t.IContextMenuService),ce(8,o.IContextKeyService),ce(9,s.IKeybindingService)],l);let a=class extends _.Disposable{constructor(u,C,f,h,v,w,S){super(),this._id=u,this._editor=C,this._visibleContext=f,this._showCommand=h,this._instantiationService=v,this._bulkEditService=w,this._notificationService=S,this._currentWidget=this._register(new _.MutableDisposable),this._register(m.Event.any(C.onDidChangeModel,C.onDidChangeModelContent)(()=>this.clear()))}async applyEditAndShowIfNeeded(u,C,f,h,v){const w=this._editor.getModel();if(!w||!u.length)return;const S=C.allEdits.at(C.activeEditIndex);if(!S)return;const L=async F=>{const x=this._editor.getModel();x&&(await x.undo(),this.applyEditAndShowIfNeeded(u,{activeEditIndex:F,allEdits:C.allEdits},f,h,v))},D=(F,x)=>{(0,y.isCancellationError)(F)||(this._notificationService.error(x),f&&this.show(u[0],C,L))};let T;try{T=await h(S,v)}catch(F){return D(F,(0,n.localize)(845,`Error resolving edit '{0}': {1}`,S.title,(0,E.toErrorMessage)(F)))}if(v.isCancellationRequested)return;const M=(0,p.createCombinedWorkspaceEdit)(w.uri,u,T),A=u[0],P=w.deltaDecorations([],[{range:A,options:{description:"paste-line-suffix",stickiness:0}}]);this._editor.focus();let N,O;try{N=await this._bulkEditService.apply(M,{editor:this._editor,token:v}),O=w.getDecorationRange(P[0])}catch(F){return D(F,(0,n.localize)(846,`Error applying edit '{0}': {1}`,S.title,(0,E.toErrorMessage)(F)))}finally{w.deltaDecorations(P,[])}v.isCancellationRequested||f&&N.isApplied&&C.allEdits.length>1&&this.show(O??A,C,L)}show(u,C,f){this.clear(),this._editor.hasModel()&&(this._currentWidget.value=this._instantiationService.createInstance(l,this._id,this._editor,this._visibleContext,this._showCommand,u,C,f))}clear(){this._currentWidget.clear()}tryShowSelector(){this._currentWidget.value?.showSelector()}};e.PostEditWidgetManager=a,e.PostEditWidgetManager=a=ke([ce(4,i.IInstantiationService),ce(5,b.IBulkEditService),ce(6,g.INotificationService)],a)}),define(ne[397],se([1,0,21,189]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.observableConfigValue=I,e.bindContextKey=E;function I(y,m,_){return(0,k.observableFromEventOpts)({debugName:()=>`Configuration Key "${y}"`},b=>_.onDidChangeConfiguration(p=>{p.affectsConfiguration(y)&&b(p)}),()=>_.getValue(y)??m)}function E(y,m,_){const b=y.bindTo(m);return(0,d.autorunOpts)({debugName:()=>`Set Context Key "${y.key}"`},p=>{b.set(_(p))})}}),define(ne[700],se([1,0,349,171,21,7]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.wrapInReloadableClass1=_;class y{constructor(n){this.instantiationService=n}init(...n){}}function m(p,n){return class extends n{constructor(){super(...arguments),this._autorun=void 0}init(...t){this._autorun=(0,I.autorunWithStore)((i,s)=>{const g=(0,k.readHotReloadableExport)(p(),i);s.add(this.instantiationService.createInstance(g,...t))})}dispose(){this._autorun?.dispose()}}}function _(p){return(0,d.isHotReloadEnabled)()?m(p,b):p()}let b=class extends y{constructor(n,o){super(o),this.init(n)}};b=ke([ce(1,E.IInstantiationService)],b)}),define(ne[59],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IOpenerService=void 0,e.extractSelection=k,e.IOpenerService=(0,d.createDecorator)("openerService");function k(I){let E;const y=/^L?(\d+)(?:,(\d+))?(-L?(\d+)(?:,(\d+))?)?/.exec(I.fragment);return y&&(E={startLineNumber:parseInt(y[1]),startColumn:y[2]?parseInt(y[2]):1,endLineNumber:y[4]?parseInt(y[4]):void 0,endColumn:y[4]?y[5]?parseInt(y[5]):1:void 0},I=I.with({fragment:""})),{selection:E,uri:I}}}),define(ne[701],se([1,0,5,52,18,73,45,252,42,48,22,34,24,673,59]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OpenerService=void 0;let s=class{constructor(a){this._commandService=a}async open(a,r){if(!(0,_.matchesScheme)(a,_.Schemas.command))return!1;if(!r?.allowCommands||(typeof a=="string"&&(a=p.URI.parse(a)),Array.isArray(r.allowCommands)&&!r.allowCommands.includes(a.path)))return!0;let u=[];try{u=(0,m.parse)(decodeURIComponent(a.query))}catch{try{u=(0,m.parse)(a.query)}catch{}}return Array.isArray(u)||(u=[u]),await this._commandService.executeCommand(a.path,...u),!0}};s=ke([ce(0,o.ICommandService)],s);let g=class{constructor(a){this._editorService=a}async open(a,r){typeof a=="string"&&(a=p.URI.parse(a));const{selection:u,uri:C}=(0,i.extractSelection)(a);return a=C,a.scheme===_.Schemas.file&&(a=(0,b.normalizePath)(a)),await this._editorService.openCodeEditor({resource:a,options:{selection:u,source:r?.fromUserGesture?t.EditorOpenSource.USER:t.EditorOpenSource.API,...r?.editorOptions}},this._editorService.getFocusedCodeEditor(),r?.openToSide),!0}};g=ke([ce(0,n.ICodeEditorService)],g);let c=class{constructor(a,r){this._openers=new E.LinkedList,this._validators=new E.LinkedList,this._resolvers=new E.LinkedList,this._resolvedUriTargets=new y.ResourceMap(u=>u.with({path:null,fragment:null,query:null}).toString()),this._externalOpeners=new E.LinkedList,this._defaultExternalOpener={openExternal:async u=>((0,_.matchesSomeScheme)(u,_.Schemas.http,_.Schemas.https)?d.windowOpenNoOpener(u):k.mainWindow.location.href=u,!0)},this._openers.push({open:async(u,C)=>C?.openExternal||(0,_.matchesSomeScheme)(u,_.Schemas.mailto,_.Schemas.http,_.Schemas.https,_.Schemas.vsls)?(await this._doOpenExternal(u,C),!0):!1}),this._openers.push(new s(r)),this._openers.push(new g(a))}registerOpener(a){return{dispose:this._openers.unshift(a)}}async open(a,r){const u=typeof a=="string"?p.URI.parse(a):a,C=this._resolvedUriTargets.get(u)??a;for(const f of this._validators)if(!await f.shouldOpen(C,r))return!1;for(const f of this._openers)if(await f.open(a,r))return!0;return!1}async resolveExternalUri(a,r){for(const u of this._resolvers)try{const C=await u.resolveExternalUri(a,r);if(C)return this._resolvedUriTargets.has(C.resolved)||this._resolvedUriTargets.set(C.resolved,a),C}catch{}throw new Error("Could not resolve external URI: "+a.toString())}async _doOpenExternal(a,r){const u=typeof a=="string"?p.URI.parse(a):a;let C;try{C=(await this.resolveExternalUri(u,r)).resolved}catch{C=u}let f;if(typeof a=="string"&&u.toString()===C.toString()?f=a:f=encodeURI(C.toString(!0)),r?.allowContributedOpeners){const h=typeof r?.allowContributedOpeners=="string"?r?.allowContributedOpeners:void 0;for(const v of this._externalOpeners)if(await v.openExternal(f,{sourceUri:u,preferredOpenerId:h},I.CancellationToken.None))return!0}return this._defaultExternalOpener.openExternal(f,{sourceUri:u},I.CancellationToken.None)}dispose(){this._validators.clear()}};e.OpenerService=c,e.OpenerService=c=ke([ce(0,n.ICodeEditorService),ce(1,o.ICommandService)],c)}),define(ne[702],se([1,0,5,93,47,69,6,2,59,44,118,543]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Link=void 0;let n=class extends m.Disposable{get enabled(){return this._enabled}set enabled(t){t?(this.el.setAttribute("aria-disabled","false"),this.el.tabIndex=0,this.el.style.pointerEvents="auto",this.el.style.opacity="1",this.el.style.cursor="pointer",this._enabled=!1):(this.el.setAttribute("aria-disabled","true"),this.el.tabIndex=-1,this.el.style.pointerEvents="none",this.el.style.opacity="0.4",this.el.style.cursor="default",this._enabled=!0),this._enabled=t}constructor(t,i,s={},g,c){super(),this._link=i,this._hoverService=g,this._enabled=!0,this.el=(0,d.append)(t,(0,d.$)("a.monaco-link",{tabIndex:i.tabIndex??0,href:i.href},i.label)),this.hoverDelegate=s.hoverDelegate??(0,b.getDefaultHoverDelegate)("mouse"),this.setTooltip(i.title),this.el.setAttribute("role","button");const l=this._register(new k.DomEmitter(this.el,"click")),a=this._register(new k.DomEmitter(this.el,"keypress")),r=y.Event.chain(a.event,f=>f.map(h=>new I.StandardKeyboardEvent(h)).filter(h=>h.keyCode===3)),u=this._register(new k.DomEmitter(this.el,E.EventType.Tap)).event;this._register(E.Gesture.addTarget(this.el));const C=y.Event.any(l.event,r,u);this._register(C(f=>{this.enabled&&(d.EventHelper.stop(f,!0),s?.opener?s.opener(this._link.href):c.open(this._link.href,{allowCommands:!0}))})),this.enabled=!0}setTooltip(t){this.hoverDelegate.showNativeHover?this.el.title=t??"":!this.hover&&t?this.hover=this._register(this._hoverService.setupManagedHover(this.hoverDelegate,this.el,t)):this.hover&&this.hover.update(t)}};e.Link=n,e.Link=n=ke([ce(3,p.IHoverService),ce(4,_.IOpenerService)],n)}),define(ne[96],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IEditorProgressService=e.Progress=e.emptyProgressRunner=e.IProgressService=void 0,e.IProgressService=(0,d.createDecorator)("progressService"),e.emptyProgressRunner=Object.freeze({total(){},worked(){},done(){}});class k{static{this.None=Object.freeze({report(){}})}constructor(E){this.callback=E}report(E){this._value=E,this.callback(this._value)}}e.Progress=k,e.IEditorProgressService=(0,d.createDecorator)("editorProgressService")}),define(ne[703],se([1,0,14,18,2,19]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PickerQuickAccessProvider=e.TriggerAction=void 0;var y;(function(p){p[p.NO_ACTION=0]="NO_ACTION",p[p.CLOSE_PICKER=1]="CLOSE_PICKER",p[p.REFRESH_PICKER=2]="REFRESH_PICKER",p[p.REMOVE_ITEM=3]="REMOVE_ITEM"})(y||(e.TriggerAction=y={}));function m(p){const n=p;return Array.isArray(n.items)}function _(p){const n=p;return!!n.picks&&n.additionalPicks instanceof Promise}class b extends I.Disposable{constructor(n,o){super(),this.prefix=n,this.options=o}provide(n,o,t){const i=new I.DisposableStore;n.canAcceptInBackground=!!this.options?.canAcceptInBackground,n.matchOnLabel=n.matchOnDescription=n.matchOnDetail=n.sortByLabel=!1;let s;const g=i.add(new I.MutableDisposable),c=async()=>{const a=g.value=new I.DisposableStore;s?.dispose(!0),n.busy=!1,s=new k.CancellationTokenSource(o);const r=s.token;let u=n.value.substring(this.prefix.length);this.options?.shouldSkipTrimPickFilter||(u=u.trim());const C=this._getPicks(u,a,r,t),f=(v,w)=>{let S,L;if(m(v)?(S=v.items,L=v.active):S=v,S.length===0){if(w)return!1;(u.length>0||n.hideInput)&&this.options?.noResultsPick&&((0,E.isFunction)(this.options.noResultsPick)?S=[this.options.noResultsPick(u)]:S=[this.options.noResultsPick])}return n.items=S,L&&(n.activeItems=[L]),!0},h=async v=>{let w=!1,S=!1;await Promise.all([(async()=>{typeof v.mergeDelay=="number"&&(await(0,d.timeout)(v.mergeDelay),r.isCancellationRequested)||S||(w=f(v.picks,!0))})(),(async()=>{n.busy=!0;try{const L=await v.additionalPicks;if(r.isCancellationRequested)return;let D,T;m(v.picks)?(D=v.picks.items,T=v.picks.active):D=v.picks;let M,A;if(m(L)?(M=L.items,A=L.active):M=L,M.length>0||!w){let P;if(!T&&!A){const N=n.activeItems[0];N&&D.indexOf(N)!==-1&&(P=N)}f({items:[...D,...M],active:T||A||P})}}finally{r.isCancellationRequested||(n.busy=!1),S=!0}})()])};if(C!==null)if(_(C))await h(C);else if(!(C instanceof Promise))f(C);else{n.busy=!0;try{const v=await C;if(r.isCancellationRequested)return;_(v)?await h(v):f(v)}finally{r.isCancellationRequested||(n.busy=!1)}}};i.add(n.onDidChangeValue(()=>c())),c(),i.add(n.onDidAccept(a=>{if(t?.handleAccept){a.inBackground||n.hide(),t.handleAccept?.(n.activeItems[0]);return}const[r]=n.selectedItems;typeof r?.accept=="function"&&(a.inBackground||n.hide(),r.accept(n.keyMods,a))}));const l=async(a,r)=>{if(typeof r.trigger!="function")return;const u=r.buttons?.indexOf(a)??-1;if(u>=0){const C=r.trigger(u,n.keyMods),f=typeof C=="number"?C:await C;if(o.isCancellationRequested)return;switch(f){case y.NO_ACTION:break;case y.CLOSE_PICKER:n.hide();break;case y.REFRESH_PICKER:c();break;case y.REMOVE_ITEM:{const h=n.items.indexOf(r);if(h!==-1){const v=n.items.slice(),w=v.splice(h,1),S=n.activeItems.filter(D=>D!==w[0]),L=n.keepScrollPosition;n.keepScrollPosition=!0,n.items=v,S&&(n.activeItems=S),n.keepScrollPosition=L}break}}}};return i.add(n.onDidTriggerItemButton(({button:a,item:r})=>l(a,r))),i.add(n.onDidTriggerSeparatorButton(({button:a,separator:r})=>l(a,r))),i}}e.PickerQuickAccessProvider=b}),define(ne[704],se([1,0,5,260,2,111,228]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QuickInputBox=void 0;const y=d.$;class m extends I.Disposable{constructor(b,p,n){super(),this.parent=b,this.onKeyDown=t=>d.addStandardDisposableListener(this.findInput.inputBox.inputElement,d.EventType.KEY_DOWN,t),this.onDidChange=t=>this.findInput.onDidChange(t),this.container=d.append(this.parent,y(".quick-input-box")),this.findInput=this._register(new k.FindInput(this.container,void 0,{label:"",inputBoxStyles:p,toggleStyles:n}));const o=this.findInput.inputBox.inputElement;o.role="combobox",o.ariaHasPopup="menu",o.ariaAutoComplete="list",o.ariaExpanded="true"}get value(){return this.findInput.getValue()}set value(b){this.findInput.setValue(b)}select(b=null){this.findInput.inputBox.select(b)}getSelection(){return this.findInput.inputBox.getSelection()}isSelectionAtEnd(){return this.findInput.inputBox.isSelectionAtEnd()}get placeholder(){return this.findInput.inputBox.inputElement.getAttribute("placeholder")||""}set placeholder(b){this.findInput.inputBox.setPlaceHolder(b)}get password(){return this.findInput.inputBox.inputElement.type==="password"}set password(b){this.findInput.inputBox.inputElement.type=b?"password":"text"}set enabled(b){this.findInput.inputBox.inputElement.toggleAttribute("readonly",!b)}set toggles(b){this.findInput.setAdditionalToggles(b)}setAttribute(b,p){this.findInput.inputBox.inputElement.setAttribute(b,p)}showDecoration(b){b===E.default.Ignore?this.findInput.clearMessage():this.findInput.showMessage({type:b===E.default.Info?1:b===E.default.Warning?2:3,content:""})}stylesForType(b){return this.findInput.inputBox.stylesForType(b===E.default.Info?1:b===E.default.Warning?2:3)}setFocus(){this.findInput.focus()}layout(){this.findInput.inputBox.layout()}}e.QuickInputBox=m}),define(ne[398],se([1,0,5,93,6,47,69,114,187,446,3,228]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.quickInputButtonToAction=i,e.renderQuickInputDescription=s;const n={},o=new _.IdGenerator("quick-input-button-icon-");function t(g){if(!g)return;let c;const l=g.dark.toString();return n[l]?c=n[l]:(c=o.nextId(),d.createCSSRule(`.${c}, .hc-light .${c}`,`background-image: ${d.asCSSUrl(g.light||g.dark)}`),d.createCSSRule(`.vs-dark .${c}, .hc-black .${c}`,`background-image: ${d.asCSSUrl(g.dark)}`),n[l]=c),c}function i(g,c,l){let a=g.iconClass||t(g.iconPath);return g.alwaysVisible&&(a=a?`${a} always-visible`:"always-visible"),{id:c,label:"",tooltip:g.tooltip||"",class:a,enabled:!0,run:l}}function s(g,c,l){d.reset(c);const a=(0,b.parseLinkedText)(g);let r=0;for(const u of a.nodes)if(typeof u=="string")c.append(...(0,m.renderLabelWithIcons)(u));else{let C=u.title;!C&&u.href.startsWith("command:")?C=(0,p.localize)(1598,"Click to execute command '{0}'",u.href.substring(8)):C||(C=u.href);const f=d.$("a",{href:u.href,title:C,tabIndex:r++},u.label);f.style.textDecoration="underline";const h=D=>{d.isEventLike(D)&&d.EventHelper.stop(D,!0),l.callback(u.href)},v=l.disposables.add(new k.DomEmitter(f,d.EventType.CLICK)).event,w=l.disposables.add(new k.DomEmitter(f,d.EventType.KEY_DOWN)).event,S=I.Event.chain(w,D=>D.filter(T=>{const M=new E.StandardKeyboardEvent(T);return M.equals(10)||M.equals(3)}));l.disposables.add(y.Gesture.addTarget(f));const L=l.disposables.add(new k.DomEmitter(f,y.EventType.Tap)).event;I.Event.any(v,L,S)(h,null,l.disposables),c.appendChild(f)}}}),define(ne[66],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IQuickInputService=e.quickPickItemScorerAccessor=e.QuickPickItemScorerAccessor=e.QuickInputButtonLocation=e.QuickPickFocus=e.ItemActivation=e.QuickInputHideReason=e.NO_KEY_MODS=void 0,e.NO_KEY_MODS={ctrlCmd:!1,alt:!1};var k;(function(_){_[_.Blur=1]="Blur",_[_.Gesture=2]="Gesture",_[_.Other=3]="Other"})(k||(e.QuickInputHideReason=k={}));var I;(function(_){_[_.NONE=0]="NONE",_[_.FIRST=1]="FIRST",_[_.SECOND=2]="SECOND",_[_.LAST=3]="LAST"})(I||(e.ItemActivation=I={}));var E;(function(_){_[_.First=1]="First",_[_.Second=2]="Second",_[_.Last=3]="Last",_[_.Next=4]="Next",_[_.Previous=5]="Previous",_[_.NextPage=6]="NextPage",_[_.PreviousPage=7]="PreviousPage",_[_.NextSeparator=8]="NextSeparator",_[_.PreviousSeparator=9]="PreviousSeparator"})(E||(e.QuickPickFocus=E={}));var y;(function(_){_[_.Title=1]="Title",_[_.Inline=2]="Inline"})(y||(e.QuickInputButtonLocation=y={}));class m{constructor(b){this.options=b}}e.QuickPickItemScorerAccessor=m,e.quickPickItemScorerAccessor=new m,e.IQuickInputService=(0,d.createDecorator)("quickInputService")}),define(ne[272],se([1,0,5,47,175,13,14,26,6,2,16,111,30,3,66,398,28,118,12,228]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QuickInputHoverDelegate=e.InputBox=e.QuickPick=e.backButton=e.endOfQuickInputBoxContext=e.EndOfQuickInputBoxContextKey=e.endOfQuickInputBoxContextKeyValue=e.QuickInputTypeContextKey=e.quickInputTypeContextKeyValue=e.inQuickInputContext=e.InQuickInputContextKey=e.inQuickInputContextKeyValue=void 0,e.inQuickInputContextKeyValue="inQuickInput",e.InQuickInputContextKey=new l.RawContextKey(e.inQuickInputContextKeyValue,!1,(0,t.localize)(1580,"Whether keyboard focus is inside the quick input control")),e.inQuickInputContext=l.ContextKeyExpr.has(e.inQuickInputContextKeyValue),e.quickInputTypeContextKeyValue="quickInputType",e.QuickInputTypeContextKey=new l.RawContextKey(e.quickInputTypeContextKeyValue,void 0,(0,t.localize)(1581,"The type of the currently visible quick input")),e.endOfQuickInputBoxContextKeyValue="cursorAtEndOfQuickInputBox",e.EndOfQuickInputBoxContextKey=new l.RawContextKey(e.endOfQuickInputBoxContextKeyValue,!1,(0,t.localize)(1582,"Whether the cursor in the quick input is at the end of the input box")),e.endOfQuickInputBoxContext=l.ContextKeyExpr.has(e.endOfQuickInputBoxContextKeyValue),e.backButton={iconClass:o.ThemeIcon.asClassName(m.Codicon.quickInputBack),tooltip:(0,t.localize)(1583,"Back"),handle:-1};class a extends b.Disposable{static{this.noPromptMessage=(0,t.localize)(1584,"Press 'Enter' to confirm your input or 'Escape' to cancel")}constructor(h){super(),this.ui=h,this._widgetUpdated=!1,this.visible=!1,this._enabled=!0,this._busy=!1,this._ignoreFocusOut=!1,this._leftButtons=[],this._rightButtons=[],this._inlineButtons=[],this.buttonsUpdated=!1,this._toggles=[],this.togglesUpdated=!1,this.noValidationMessage=a.noPromptMessage,this._severity=n.default.Ignore,this.onDidTriggerButtonEmitter=this._register(new _.Emitter),this.onDidHideEmitter=this._register(new _.Emitter),this.onWillHideEmitter=this._register(new _.Emitter),this.onDisposeEmitter=this._register(new _.Emitter),this.visibleDisposables=this._register(new b.DisposableStore),this.onDidHide=this.onDidHideEmitter.event}get title(){return this._title}set title(h){this._title=h,this.update()}get description(){return this._description}set description(h){this._description=h,this.update()}get step(){return this._steps}set step(h){this._steps=h,this.update()}get totalSteps(){return this._totalSteps}set totalSteps(h){this._totalSteps=h,this.update()}get enabled(){return this._enabled}set enabled(h){this._enabled=h,this.update()}get contextKey(){return this._contextKey}set contextKey(h){this._contextKey=h,this.update()}get busy(){return this._busy}set busy(h){this._busy=h,this.update()}get ignoreFocusOut(){return this._ignoreFocusOut}set ignoreFocusOut(h){const v=this._ignoreFocusOut!==h&&!p.isIOS;this._ignoreFocusOut=h&&!p.isIOS,v&&this.update()}get titleButtons(){return this._leftButtons.length?[...this._leftButtons,this._rightButtons]:this._rightButtons}get buttons(){return[...this._leftButtons,...this._rightButtons,...this._inlineButtons]}set buttons(h){this._leftButtons=h.filter(v=>v===e.backButton),this._rightButtons=h.filter(v=>v!==e.backButton&&v.location!==i.QuickInputButtonLocation.Inline),this._inlineButtons=h.filter(v=>v.location===i.QuickInputButtonLocation.Inline),this.buttonsUpdated=!0,this.update()}get toggles(){return this._toggles}set toggles(h){this._toggles=h??[],this.togglesUpdated=!0,this.update()}get validationMessage(){return this._validationMessage}set validationMessage(h){this._validationMessage=h,this.update()}get severity(){return this._severity}set severity(h){this._severity=h,this.update()}show(){this.visible||(this.visibleDisposables.add(this.ui.onDidTriggerButton(h=>{this.buttons.indexOf(h)!==-1&&this.onDidTriggerButtonEmitter.fire(h)})),this.ui.show(this),this.visible=!0,this._lastValidationMessage=void 0,this._lastSeverity=void 0,this.buttons.length&&(this.buttonsUpdated=!0),this.toggles.length&&(this.togglesUpdated=!0),this.update())}hide(){this.visible&&this.ui.hide()}didHide(h=i.QuickInputHideReason.Other){this.visible=!1,this.visibleDisposables.clear(),this.onDidHideEmitter.fire({reason:h})}willHide(h=i.QuickInputHideReason.Other){this.onWillHideEmitter.fire({reason:h})}update(){if(!this.visible)return;const h=this.getTitle();h&&this.ui.title.textContent!==h?this.ui.title.textContent=h:!h&&this.ui.title.innerHTML!==" "&&(this.ui.title.innerText="\xA0");const v=this.getDescription();if(this.ui.description1.textContent!==v&&(this.ui.description1.textContent=v),this.ui.description2.textContent!==v&&(this.ui.description2.textContent=v),this._widgetUpdated&&(this._widgetUpdated=!1,this._widget?d.reset(this.ui.widget,this._widget):d.reset(this.ui.widget)),this.busy&&!this.busyDelay&&(this.busyDelay=new y.TimeoutTimer,this.busyDelay.setIfNotSet(()=>{this.visible&&this.ui.progressBar.infinite()},800)),!this.busy&&this.busyDelay&&(this.ui.progressBar.stop(),this.busyDelay.cancel(),this.busyDelay=void 0),this.buttonsUpdated){this.buttonsUpdated=!1,this.ui.leftActionBar.clear();const S=this._leftButtons.map((T,M)=>(0,s.quickInputButtonToAction)(T,`id-${M}`,async()=>this.onDidTriggerButtonEmitter.fire(T)));this.ui.leftActionBar.push(S,{icon:!0,label:!1}),this.ui.rightActionBar.clear();const L=this._rightButtons.map((T,M)=>(0,s.quickInputButtonToAction)(T,`id-${M}`,async()=>this.onDidTriggerButtonEmitter.fire(T)));this.ui.rightActionBar.push(L,{icon:!0,label:!1}),this.ui.inlineActionBar.clear();const D=this._inlineButtons.map((T,M)=>(0,s.quickInputButtonToAction)(T,`id-${M}`,async()=>this.onDidTriggerButtonEmitter.fire(T)));this.ui.inlineActionBar.push(D,{icon:!0,label:!1})}if(this.togglesUpdated){this.togglesUpdated=!1;const S=this.toggles?.filter(L=>L instanceof I.Toggle)??[];this.ui.inputBox.toggles=S}this.ui.ignoreFocusOut=this.ignoreFocusOut,this.ui.setEnabled(this.enabled),this.ui.setContextKey(this.contextKey);const w=this.validationMessage||this.noValidationMessage;this._lastValidationMessage!==w&&(this._lastValidationMessage=w,d.reset(this.ui.message),(0,s.renderQuickInputDescription)(w,this.ui.message,{callback:S=>{this.ui.linkOpenerDelegate(S)},disposables:this.visibleDisposables})),this._lastSeverity!==this.severity&&(this._lastSeverity=this.severity,this.showMessageDecoration(this.severity))}getTitle(){return this.title&&this.step?`${this.title} (${this.getSteps()})`:this.title?this.title:this.step?this.getSteps():""}getDescription(){return this.description||""}getSteps(){return this.step&&this.totalSteps?(0,t.localize)(1585,"{0}/{1}",this.step,this.totalSteps):this.step?String(this.step):""}showMessageDecoration(h){if(this.ui.inputBox.showDecoration(h),h!==n.default.Ignore){const v=this.ui.inputBox.stylesForType(h);this.ui.message.style.color=v.foreground?`${v.foreground}`:"",this.ui.message.style.backgroundColor=v.background?`${v.background}`:"",this.ui.message.style.border=v.border?`1px solid ${v.border}`:"",this.ui.message.style.marginBottom="-2px"}else this.ui.message.style.color="",this.ui.message.style.backgroundColor="",this.ui.message.style.border="",this.ui.message.style.marginBottom=""}dispose(){this.hide(),this.onDisposeEmitter.fire(),super.dispose()}}class r extends a{constructor(){super(...arguments),this._value="",this.onDidChangeValueEmitter=this._register(new _.Emitter),this.onWillAcceptEmitter=this._register(new _.Emitter),this.onDidAcceptEmitter=this._register(new _.Emitter),this.onDidCustomEmitter=this._register(new _.Emitter),this._items=[],this.itemsUpdated=!1,this._canSelectMany=!1,this._canAcceptInBackground=!1,this._matchOnDescription=!1,this._matchOnDetail=!1,this._matchOnLabel=!0,this._matchOnLabelMode="fuzzy",this._sortByLabel=!0,this._keepScrollPosition=!1,this._itemActivation=i.ItemActivation.FIRST,this._activeItems=[],this.activeItemsUpdated=!1,this.activeItemsToConfirm=[],this.onDidChangeActiveEmitter=this._register(new _.Emitter),this._selectedItems=[],this.selectedItemsUpdated=!1,this.selectedItemsToConfirm=[],this.onDidChangeSelectionEmitter=this._register(new _.Emitter),this.onDidTriggerItemButtonEmitter=this._register(new _.Emitter),this.onDidTriggerSeparatorButtonEmitter=this._register(new _.Emitter),this.valueSelectionUpdated=!0,this._ok="default",this._customButton=!1,this._focusEventBufferer=new _.EventBufferer,this.type="quickPick",this.filterValue=h=>h,this.onDidChangeValue=this.onDidChangeValueEmitter.event,this.onWillAccept=this.onWillAcceptEmitter.event,this.onDidAccept=this.onDidAcceptEmitter.event,this.onDidChangeActive=this.onDidChangeActiveEmitter.event,this.onDidChangeSelection=this.onDidChangeSelectionEmitter.event,this.onDidTriggerItemButton=this.onDidTriggerItemButtonEmitter.event,this.onDidTriggerSeparatorButton=this.onDidTriggerSeparatorButtonEmitter.event}static{this.DEFAULT_ARIA_LABEL=(0,t.localize)(1586,"Type to narrow down results.")}get quickNavigate(){return this._quickNavigate}set quickNavigate(h){this._quickNavigate=h,this.update()}get value(){return this._value}set value(h){this.doSetValue(h)}doSetValue(h,v){this._value!==h&&(this._value=h,v||this.update(),this.visible&&this.ui.list.filter(this.filterValue(this._value))&&this.trySelectFirst(),this.onDidChangeValueEmitter.fire(this._value))}set ariaLabel(h){this._ariaLabel=h,this.update()}get ariaLabel(){return this._ariaLabel}get placeholder(){return this._placeholder}set placeholder(h){this._placeholder=h,this.update()}get items(){return this._items}get scrollTop(){return this.ui.list.scrollTop}set scrollTop(h){this.ui.list.scrollTop=h}set items(h){this._items=h,this.itemsUpdated=!0,this.update()}get canSelectMany(){return this._canSelectMany}set canSelectMany(h){this._canSelectMany=h,this.update()}get canAcceptInBackground(){return this._canAcceptInBackground}set canAcceptInBackground(h){this._canAcceptInBackground=h}get matchOnDescription(){return this._matchOnDescription}set matchOnDescription(h){this._matchOnDescription=h,this.update()}get matchOnDetail(){return this._matchOnDetail}set matchOnDetail(h){this._matchOnDetail=h,this.update()}get matchOnLabel(){return this._matchOnLabel}set matchOnLabel(h){this._matchOnLabel=h,this.update()}get matchOnLabelMode(){return this._matchOnLabelMode}set matchOnLabelMode(h){this._matchOnLabelMode=h,this.update()}get sortByLabel(){return this._sortByLabel}set sortByLabel(h){this._sortByLabel=h,this.update()}get keepScrollPosition(){return this._keepScrollPosition}set keepScrollPosition(h){this._keepScrollPosition=h}get itemActivation(){return this._itemActivation}set itemActivation(h){this._itemActivation=h}get activeItems(){return this._activeItems}set activeItems(h){this._activeItems=h,this.activeItemsUpdated=!0,this.update()}get selectedItems(){return this._selectedItems}set selectedItems(h){this._selectedItems=h,this.selectedItemsUpdated=!0,this.update()}get keyMods(){return this._quickNavigate?i.NO_KEY_MODS:this.ui.keyMods}get valueSelection(){const h=this.ui.inputBox.getSelection();if(h)return[h.start,h.end]}set valueSelection(h){this._valueSelection=h,this.valueSelectionUpdated=!0,this.update()}get customButton(){return this._customButton}set customButton(h){this._customButton=h,this.update()}get customLabel(){return this._customButtonLabel}set customLabel(h){this._customButtonLabel=h,this.update()}get customHover(){return this._customButtonHover}set customHover(h){this._customButtonHover=h,this.update()}get ok(){return this._ok}set ok(h){this._ok=h,this.update()}get hideInput(){return!!this._hideInput}set hideInput(h){this._hideInput=h,this.update()}trySelectFirst(){this.canSelectMany||this.ui.list.focus(i.QuickPickFocus.First)}show(){this.visible||(this.visibleDisposables.add(this.ui.inputBox.onDidChange(h=>{this.doSetValue(h,!0)})),this.visibleDisposables.add(this.ui.onDidAccept(()=>{this.canSelectMany?this.ui.list.getCheckedElements().length||(this._selectedItems=[],this.onDidChangeSelectionEmitter.fire(this.selectedItems)):this.activeItems[0]&&(this._selectedItems=[this.activeItems[0]],this.onDidChangeSelectionEmitter.fire(this.selectedItems)),this.handleAccept(!1)})),this.visibleDisposables.add(this.ui.onDidCustom(()=>{this.onDidCustomEmitter.fire()})),this.visibleDisposables.add(this._focusEventBufferer.wrapEvent(this.ui.list.onDidChangeFocus,(h,v)=>v)(h=>{this.activeItemsUpdated||this.activeItemsToConfirm!==this._activeItems&&(0,E.equals)(h,this._activeItems,(v,w)=>v===w)||(this._activeItems=h,this.onDidChangeActiveEmitter.fire(h))})),this.visibleDisposables.add(this.ui.list.onDidChangeSelection(({items:h,event:v})=>{if(this.canSelectMany){h.length&&this.ui.list.setSelectedElements([]);return}this.selectedItemsToConfirm!==this._selectedItems&&(0,E.equals)(h,this._selectedItems,(w,S)=>w===S)||(this._selectedItems=h,this.onDidChangeSelectionEmitter.fire(h),h.length&&this.handleAccept(d.isMouseEvent(v)&&v.button===1))})),this.visibleDisposables.add(this.ui.list.onChangedCheckedElements(h=>{!this.canSelectMany||!this.visible||this.selectedItemsToConfirm!==this._selectedItems&&(0,E.equals)(h,this._selectedItems,(v,w)=>v===w)||(this._selectedItems=h,this.onDidChangeSelectionEmitter.fire(h))})),this.visibleDisposables.add(this.ui.list.onButtonTriggered(h=>this.onDidTriggerItemButtonEmitter.fire(h))),this.visibleDisposables.add(this.ui.list.onSeparatorButtonTriggered(h=>this.onDidTriggerSeparatorButtonEmitter.fire(h))),this.visibleDisposables.add(this.registerQuickNavigation()),this.valueSelectionUpdated=!0),super.show()}handleAccept(h){let v=!1;this.onWillAcceptEmitter.fire({veto:()=>v=!0}),v||this.onDidAcceptEmitter.fire({inBackground:h})}registerQuickNavigation(){return d.addDisposableListener(this.ui.container,d.EventType.KEY_UP,h=>{if(this.canSelectMany||!this._quickNavigate)return;const v=new k.StandardKeyboardEvent(h),w=v.keyCode;this._quickNavigate.keybindings.some(D=>{const T=D.getChords();return T.length>1?!1:T[0].shiftKey&&w===4?!(v.ctrlKey||v.altKey||v.metaKey):!!(T[0].altKey&&w===6||T[0].ctrlKey&&w===5||T[0].metaKey&&w===57)})&&(this.activeItems[0]&&(this._selectedItems=[this.activeItems[0]],this.onDidChangeSelectionEmitter.fire(this.selectedItems),this.handleAccept(!1)),this._quickNavigate=void 0)})}update(){if(!this.visible)return;const h=this.keepScrollPosition?this.scrollTop:0,v=!!this.description,w={title:!!this.title||!!this.step||!!this.titleButtons.length,description:v,checkAll:this.canSelectMany&&!this._hideCheckAll,checkBox:this.canSelectMany,inputBox:!this._hideInput,progressBar:!this._hideInput||v,visibleCount:!0,count:this.canSelectMany&&!this._hideCountBadge,ok:this.ok==="default"?this.canSelectMany:this.ok,list:!0,message:!!this.validationMessage,customButton:this.customButton};this.ui.setVisibilities(w),super.update(),this.ui.inputBox.value!==this.value&&(this.ui.inputBox.value=this.value),this.valueSelectionUpdated&&(this.valueSelectionUpdated=!1,this.ui.inputBox.select(this._valueSelection&&{start:this._valueSelection[0],end:this._valueSelection[1]})),this.ui.inputBox.placeholder!==(this.placeholder||"")&&(this.ui.inputBox.placeholder=this.placeholder||"");let S=this.ariaLabel;!S&&w.inputBox&&(S=this.placeholder||r.DEFAULT_ARIA_LABEL,this.title&&(S+=` - ${this.title}`)),this.ui.list.ariaLabel!==S&&(this.ui.list.ariaLabel=S??null),this.ui.list.matchOnDescription=this.matchOnDescription,this.ui.list.matchOnDetail=this.matchOnDetail,this.ui.list.matchOnLabel=this.matchOnLabel,this.ui.list.matchOnLabelMode=this.matchOnLabelMode,this.ui.list.sortByLabel=this.sortByLabel,this.itemsUpdated&&(this.itemsUpdated=!1,this._focusEventBufferer.bufferEvents(()=>{switch(this.ui.list.setElements(this.items),this.ui.list.shouldLoop=!this.canSelectMany,this.ui.list.filter(this.filterValue(this.ui.inputBox.value)),this._itemActivation){case i.ItemActivation.NONE:this._itemActivation=i.ItemActivation.FIRST;break;case i.ItemActivation.SECOND:this.ui.list.focus(i.QuickPickFocus.Second),this._itemActivation=i.ItemActivation.FIRST;break;case i.ItemActivation.LAST:this.ui.list.focus(i.QuickPickFocus.Last),this._itemActivation=i.ItemActivation.FIRST;break;default:this.trySelectFirst();break}})),this.ui.container.classList.contains("show-checkboxes")!==!!this.canSelectMany&&(this.canSelectMany?this.ui.list.clearFocus():this.trySelectFirst()),this.activeItemsUpdated&&(this.activeItemsUpdated=!1,this.activeItemsToConfirm=this._activeItems,this.ui.list.setFocusedElements(this.activeItems),this.activeItemsToConfirm===this._activeItems&&(this.activeItemsToConfirm=null)),this.selectedItemsUpdated&&(this.selectedItemsUpdated=!1,this.selectedItemsToConfirm=this._selectedItems,this.canSelectMany?this.ui.list.setCheckedElements(this.selectedItems):this.ui.list.setSelectedElements(this.selectedItems),this.selectedItemsToConfirm===this._selectedItems&&(this.selectedItemsToConfirm=null)),this.ui.customButton.label=this.customLabel||"",this.ui.customButton.element.title=this.customHover||"",w.inputBox||(this.ui.list.domFocus(),this.canSelectMany&&this.ui.list.focus(i.QuickPickFocus.First)),this.keepScrollPosition&&(this.scrollTop=h)}focus(h){this.ui.list.focus(h),this.canSelectMany&&this.ui.list.domFocus()}accept(h){h&&!this._canAcceptInBackground||this.activeItems[0]&&(this._selectedItems=[this.activeItems[0]],this.onDidChangeSelectionEmitter.fire(this.selectedItems),this.handleAccept(h??!1))}}e.QuickPick=r;class u extends a{constructor(){super(...arguments),this._value="",this.valueSelectionUpdated=!0,this._password=!1,this.onDidValueChangeEmitter=this._register(new _.Emitter),this.onDidAcceptEmitter=this._register(new _.Emitter),this.type="inputBox",this.onDidChangeValue=this.onDidValueChangeEmitter.event,this.onDidAccept=this.onDidAcceptEmitter.event}get value(){return this._value}set value(h){this._value=h||"",this.update()}get placeholder(){return this._placeholder}set placeholder(h){this._placeholder=h,this.update()}get password(){return this._password}set password(h){this._password=h,this.update()}show(){this.visible||(this.visibleDisposables.add(this.ui.inputBox.onDidChange(h=>{h!==this.value&&(this._value=h,this.onDidValueChangeEmitter.fire(h))})),this.visibleDisposables.add(this.ui.onDidAccept(()=>this.onDidAcceptEmitter.fire())),this.valueSelectionUpdated=!0),super.show()}update(){if(!this.visible)return;this.ui.container.classList.remove("hidden-input");const h={title:!!this.title||!!this.step||!!this.titleButtons.length,description:!!this.description||!!this.step,inputBox:!0,message:!0,progressBar:!0};this.ui.setVisibilities(h),super.update(),this.ui.inputBox.value!==this.value&&(this.ui.inputBox.value=this.value),this.valueSelectionUpdated&&(this.valueSelectionUpdated=!1,this.ui.inputBox.select(this._valueSelection&&{start:this._valueSelection[0],end:this._valueSelection[1]})),this.ui.inputBox.placeholder!==(this.placeholder||"")&&(this.ui.inputBox.placeholder=this.placeholder||""),this.ui.inputBox.password!==this.password&&(this.ui.inputBox.password=this.password)}}e.InputBox=u;let C=class extends c.WorkbenchHoverDelegate{constructor(h,v){super("element",!1,w=>this.getOverrideOptions(w),h,v)}getOverrideOptions(h){const v=(d.isHTMLElement(h.content)?h.content.textContent??"":typeof h.content=="string"?h.content:h.content.value).includes(` `);return{persistence:{hideOnKeyDown:!1},appearance:{showHoverHint:v,skipFadeInAnimation:!0}}}};e.QuickInputHoverDelegate=C,e.QuickInputHoverDelegate=C=ke([ce(0,g.IConfigurationService),ce(1,c.IHoverService)],C)}),define(ne[38],se([1,0,90,19]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Registry=void 0;class I{constructor(){this.data=new Map}add(y,m){d.ok(k.isString(y)),d.ok(k.isObject(m)),d.ok(!this.data.has(y),"There is already an extension with this id"),this.data.set(y,m)}as(y){return this.data.get(y)||null}}e.Registry=new I}),define(ne[399],se([1,0,38]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LocalSelectionTransfer=e.Extensions=e.CodeDataTransfers=void 0,e.CodeDataTransfers={EDITORS:"CodeEditors",FILES:"CodeFiles"};class k{}e.Extensions={DragAndDropContribution:"workbench.contributions.dragAndDrop"},d.Registry.add(e.Extensions.DragAndDropContribution,new k);class I{static{this.INSTANCE=new I}constructor(){}static getInstance(){return I.INSTANCE}hasData(y){return y&&y===this.proto}getData(y){if(this.hasData(y))return this.data}}e.LocalSelectionTransfer=I}),define(ne[400],se([1,0,224,194,128,22,399]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.toVSDataTransfer=m,e.toExternalVSDataTransfer=p;function m(n){const o=new k.VSDataTransfer;for(const t of n.items){const i=t.type;if(t.kind==="string"){const s=new Promise(g=>t.getAsString(g));o.append(i,(0,k.createStringDataTransferItem)(s))}else if(t.kind==="file"){const s=t.getAsFile();s&&o.append(i,_(s))}}return o}function _(n){const o=n.path?E.URI.parse(n.path):void 0;return(0,k.createFileDataTransferItem)(n.name,o,async()=>new Uint8Array(await n.arrayBuffer()))}const b=Object.freeze([y.CodeDataTransfers.EDITORS,y.CodeDataTransfers.FILES,d.DataTransfers.RESOURCES,d.DataTransfers.INTERNAL_URI_LIST]);function p(n,o=!1){const t=m(n),i=t.get(d.DataTransfers.INTERNAL_URI_LIST);if(i)t.replace(I.Mimes.uriList,i);else if(o||!t.has(I.Mimes.uriList)){const s=[];for(const g of n.items){const c=g.getAsFile();if(c){const l=c.path;try{l?s.push(E.URI.file(l).toString()):s.push(E.URI.parse(c.name,!0).toString())}catch{}}}s.length&&t.replace(I.Mimes.uriList,(0,k.createStringDataTransferItem)(k.UriList.create(s)))}for(const s of b)t.delete(s);return t}}),define(ne[273],se([1,0,6,38]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Extensions=void 0,e.Extensions={JSONContribution:"base.contributions.json"};function I(m){return m.length>0&&m.charAt(m.length-1)==="#"?m.substring(0,m.length-1):m}class E{constructor(){this._onDidChangeSchema=new d.Emitter,this.schemasById={}}registerSchema(_,b){this.schemasById[I(_)]=b,this._onDidChangeSchema.fire(_)}notifySchemaChanged(_){this._onDidChangeSchema.fire(_)}}const y=new E;k.Registry.add(e.Extensions.JSONContribution,y)}),define(ne[109],se([1,0,13,6,19,3,28,273,38]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.OVERRIDE_PROPERTY_REGEX=e.OVERRIDE_PROPERTY_PATTERN=e.resourceLanguageSettingsSchemaId=e.resourceSettings=e.windowSettings=e.machineOverridableSettings=e.machineSettings=e.applicationSettings=e.allSettings=e.Extensions=void 0,e.overrideIdentifiersFromKey=t,e.getDefaultValue=i,e.validateProperty=g,e.Extensions={Configuration:"base.contributions.configuration"},e.allSettings={properties:{},patternProperties:{}},e.applicationSettings={properties:{},patternProperties:{}},e.machineSettings={properties:{},patternProperties:{}},e.machineOverridableSettings={properties:{},patternProperties:{}},e.windowSettings={properties:{},patternProperties:{}},e.resourceSettings={properties:{},patternProperties:{}},e.resourceLanguageSettingsSchemaId="vscode://schemas/settings/resourceLanguage";const b=_.Registry.as(m.Extensions.JSONContribution);class p{constructor(){this.registeredConfigurationDefaults=[],this.overrideIdentifiers=new Set,this._onDidSchemaChange=new k.Emitter,this._onDidUpdateConfiguration=new k.Emitter,this.configurationDefaultsOverrides=new Map,this.defaultLanguageConfigurationOverridesNode={id:"defaultOverrides",title:E.localize(1503,"Default Language Configuration Overrides"),properties:{}},this.configurationContributors=[this.defaultLanguageConfigurationOverridesNode],this.resourceLanguageSettingsSchema={properties:{},patternProperties:{},additionalProperties:!0,allowTrailingCommas:!0,allowComments:!0},this.configurationProperties={},this.policyConfigurations=new Map,this.excludedConfigurationProperties={},b.registerSchema(e.resourceLanguageSettingsSchemaId,this.resourceLanguageSettingsSchema),this.registerOverridePropertyPatternKey()}registerConfiguration(l,a=!0){this.registerConfigurations([l],a)}registerConfigurations(l,a=!0){const r=new Set;this.doRegisterConfigurations(l,a,r),b.registerSchema(e.resourceLanguageSettingsSchemaId,this.resourceLanguageSettingsSchema),this._onDidSchemaChange.fire(),this._onDidUpdateConfiguration.fire({properties:r})}registerDefaultConfigurations(l){const a=new Set;this.doRegisterDefaultConfigurations(l,a),this._onDidSchemaChange.fire(),this._onDidUpdateConfiguration.fire({properties:a,defaultsOverrides:!0})}doRegisterDefaultConfigurations(l,a){this.registeredConfigurationDefaults.push(...l);const r=[];for(const{overrides:u,source:C}of l)for(const f in u){a.add(f);const h=this.configurationDefaultsOverrides.get(f)??this.configurationDefaultsOverrides.set(f,{configurationDefaultOverrides:[]}).get(f),v=u[f];if(h.configurationDefaultOverrides.push({value:v,source:C}),e.OVERRIDE_PROPERTY_REGEX.test(f)){const w=this.mergeDefaultConfigurationsForOverrideIdentifier(f,v,C,h.configurationDefaultOverrideValue);if(!w)continue;h.configurationDefaultOverrideValue=w,this.updateDefaultOverrideProperty(f,w,C),r.push(...t(f))}else{const w=this.mergeDefaultConfigurationsForConfigurationProperty(f,v,C,h.configurationDefaultOverrideValue);if(!w)continue;h.configurationDefaultOverrideValue=w;const S=this.configurationProperties[f];S&&(this.updatePropertyDefaultValue(f,S),this.updateSchema(f,S))}}this.doRegisterOverrideIdentifiers(r)}updateDefaultOverrideProperty(l,a,r){const u={type:"object",default:a.value,description:E.localize(1504,"Configure settings to be overridden for the {0} language.",(0,y.getLanguageTagSettingPlainKey)(l)),$ref:e.resourceLanguageSettingsSchemaId,defaultDefaultValue:a.value,source:r,defaultValueSource:r};this.configurationProperties[l]=u,this.defaultLanguageConfigurationOverridesNode.properties[l]=u}mergeDefaultConfigurationsForOverrideIdentifier(l,a,r,u){const C=u?.value||{},f=u?.source??new Map;if(!(f instanceof Map)){console.error("objectConfigurationSources is not a Map");return}for(const h of Object.keys(a)){const v=a[h];if(I.isObject(v)&&(I.isUndefined(C[h])||I.isObject(C[h]))){if(C[h]={...C[h]??{},...v},r)for(const S in v)f.set(`${h}.${S}`,r)}else C[h]=v,r?f.set(h,r):f.delete(h)}return{value:C,source:f}}mergeDefaultConfigurationsForConfigurationProperty(l,a,r,u){const C=this.configurationProperties[l],f=u?.value??C?.defaultDefaultValue;let h=r;if(I.isObject(a)&&(C!==void 0&&C.type==="object"||C===void 0&&(I.isUndefined(f)||I.isObject(f)))){if(h=u?.source??new Map,!(h instanceof Map)){console.error("defaultValueSource is not a Map");return}for(const w in a)r&&h.set(`${l}.${w}`,r);a={...I.isObject(f)?f:{},...a}}return{value:a,source:h}}registerOverrideIdentifiers(l){this.doRegisterOverrideIdentifiers(l),this._onDidSchemaChange.fire()}doRegisterOverrideIdentifiers(l){for(const a of l)this.overrideIdentifiers.add(a);this.updateOverridePropertyPatternKey()}doRegisterConfigurations(l,a,r){l.forEach(u=>{this.validateAndRegisterProperties(u,a,u.extensionInfo,u.restrictedProperties,void 0,r),this.configurationContributors.push(u),this.registerJSONConfiguration(u)})}validateAndRegisterProperties(l,a=!0,r,u,C=3,f){C=I.isUndefinedOrNull(l.scope)?C:l.scope;const h=l.properties;if(h)for(const w in h){const S=h[w];if(a&&g(w,S)){delete h[w];continue}if(S.source=r,S.defaultDefaultValue=h[w].default,this.updatePropertyDefaultValue(w,S),e.OVERRIDE_PROPERTY_REGEX.test(w)?S.scope=void 0:(S.scope=I.isUndefinedOrNull(S.scope)?C:S.scope,S.restricted=I.isUndefinedOrNull(S.restricted)?!!u?.includes(w):S.restricted),h[w].hasOwnProperty("included")&&!h[w].included){this.excludedConfigurationProperties[w]=h[w],delete h[w];continue}else this.configurationProperties[w]=h[w],h[w].policy?.name&&this.policyConfigurations.set(h[w].policy.name,w);!h[w].deprecationMessage&&h[w].markdownDeprecationMessage&&(h[w].deprecationMessage=h[w].markdownDeprecationMessage),f.add(w)}const v=l.allOf;if(v)for(const w of v)this.validateAndRegisterProperties(w,a,r,u,C,f)}getConfigurationProperties(){return this.configurationProperties}getPolicyConfigurations(){return this.policyConfigurations}registerJSONConfiguration(l){const a=r=>{const u=r.properties;if(u)for(const f in u)this.updateSchema(f,u[f]);r.allOf?.forEach(a)};a(l)}updateSchema(l,a){switch(e.allSettings.properties[l]=a,a.scope){case 1:e.applicationSettings.properties[l]=a;break;case 2:e.machineSettings.properties[l]=a;break;case 6:e.machineOverridableSettings.properties[l]=a;break;case 3:e.windowSettings.properties[l]=a;break;case 4:e.resourceSettings.properties[l]=a;break;case 5:e.resourceSettings.properties[l]=a,this.resourceLanguageSettingsSchema.properties[l]=a;break}}updateOverridePropertyPatternKey(){for(const l of this.overrideIdentifiers.values()){const a=`[${l}]`,r={type:"object",description:E.localize(1505,"Configure editor settings to be overridden for a language."),errorMessage:E.localize(1506,"This setting does not support per-language configuration."),$ref:e.resourceLanguageSettingsSchemaId};this.updatePropertyDefaultValue(a,r),e.allSettings.properties[a]=r,e.applicationSettings.properties[a]=r,e.machineSettings.properties[a]=r,e.machineOverridableSettings.properties[a]=r,e.windowSettings.properties[a]=r,e.resourceSettings.properties[a]=r}}registerOverridePropertyPatternKey(){const l={type:"object",description:E.localize(1507,"Configure editor settings to be overridden for a language."),errorMessage:E.localize(1508,"This setting does not support per-language configuration."),$ref:e.resourceLanguageSettingsSchemaId};e.allSettings.patternProperties[e.OVERRIDE_PROPERTY_PATTERN]=l,e.applicationSettings.patternProperties[e.OVERRIDE_PROPERTY_PATTERN]=l,e.machineSettings.patternProperties[e.OVERRIDE_PROPERTY_PATTERN]=l,e.machineOverridableSettings.patternProperties[e.OVERRIDE_PROPERTY_PATTERN]=l,e.windowSettings.patternProperties[e.OVERRIDE_PROPERTY_PATTERN]=l,e.resourceSettings.patternProperties[e.OVERRIDE_PROPERTY_PATTERN]=l,this._onDidSchemaChange.fire()}updatePropertyDefaultValue(l,a){const r=this.configurationDefaultsOverrides.get(l)?.configurationDefaultOverrideValue;let u,C;r&&(!a.disallowConfigurationDefault||!r.source)&&(u=r.value,C=r.source),I.isUndefined(u)&&(u=a.defaultDefaultValue,C=void 0),I.isUndefined(u)&&(u=i(a.type)),a.default=u,a.defaultValueSource=C}}const n="\\[([^\\]]+)\\]",o=new RegExp(n,"g");e.OVERRIDE_PROPERTY_PATTERN=`^(${n})+$`,e.OVERRIDE_PROPERTY_REGEX=new RegExp(e.OVERRIDE_PROPERTY_PATTERN);function t(c){const l=[];if(e.OVERRIDE_PROPERTY_REGEX.test(c)){let a=o.exec(c);for(;a?.length;){const r=a[1].trim();r&&l.push(r),a=o.exec(c)}}return(0,d.distinct)(l)}function i(c){switch(Array.isArray(c)?c[0]:c){case"boolean":return!1;case"integer":case"number":return 0;case"string":return"";case"array":return[];case"object":return{};default:return null}}const s=new p;_.Registry.add(e.Extensions.Configuration,s);function g(c,l){return c.trim()?e.OVERRIDE_PROPERTY_REGEX.test(c)?E.localize(1510,"Cannot register '{0}'. This matches property pattern '\\\\[.*\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.",c):s.getConfigurationProperties()[c]!==void 0?E.localize(1511,"Cannot register '{0}'. This property is already registered.",c):l.policy?.name&&s.getPolicyConfigurations().get(l.policy?.name)!==void 0?E.localize(1512,"Cannot register '{0}'. The associated policy {1} is already registered with {2}.",c,l.policy?.name,s.getPolicyConfigurations().get(l.policy?.name)):null:E.localize(1509,"Cannot register an empty property")}}),define(ne[274],se([1,0,308,37,197,3,109,38]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.editorConfigurationBaseNode=void 0,e.isEditorConfigurationKey=o,e.isDiffEditorConfigurationKey=t,e.editorConfigurationBaseNode=Object.freeze({id:"editor",order:5,type:"object",title:E.localize(133,"Editor"),scope:5});const _={...e.editorConfigurationBaseNode,properties:{"editor.tabSize":{type:"number",default:I.EDITOR_MODEL_DEFAULTS.tabSize,minimum:1,markdownDescription:E.localize(134,"The number of spaces a tab is equal to. This setting is overridden based on the file contents when {0} is on.","`#editor.detectIndentation#`")},"editor.indentSize":{anyOf:[{type:"string",enum:["tabSize"]},{type:"number",minimum:1}],default:"tabSize",markdownDescription:E.localize(135,'The number of spaces used for indentation or `"tabSize"` to use the value from `#editor.tabSize#`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.')},"editor.insertSpaces":{type:"boolean",default:I.EDITOR_MODEL_DEFAULTS.insertSpaces,markdownDescription:E.localize(136,"Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when {0} is on.","`#editor.detectIndentation#`")},"editor.detectIndentation":{type:"boolean",default:I.EDITOR_MODEL_DEFAULTS.detectIndentation,markdownDescription:E.localize(137,"Controls whether {0} and {1} will be automatically detected when a file is opened based on the file contents.","`#editor.tabSize#`","`#editor.insertSpaces#`")},"editor.trimAutoWhitespace":{type:"boolean",default:I.EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,description:E.localize(138,"Remove trailing auto inserted whitespace.")},"editor.largeFileOptimizations":{type:"boolean",default:I.EDITOR_MODEL_DEFAULTS.largeFileOptimizations,description:E.localize(139,"Special handling for large files to disable certain memory intensive features.")},"editor.wordBasedSuggestions":{enum:["off","currentDocument","matchingDocuments","allDocuments"],default:"matchingDocuments",enumDescriptions:[E.localize(140,"Turn off Word Based Suggestions."),E.localize(141,"Only suggest words from the active document."),E.localize(142,"Suggest words from all open documents of the same language."),E.localize(143,"Suggest words from all open documents.")],description:E.localize(144,"Controls whether completions should be computed based on words in the document and from which documents they are computed.")},"editor.semanticHighlighting.enabled":{enum:[!0,!1,"configuredByTheme"],enumDescriptions:[E.localize(145,"Semantic highlighting enabled for all color themes."),E.localize(146,"Semantic highlighting disabled for all color themes."),E.localize(147,"Semantic highlighting is configured by the current color theme's `semanticHighlighting` setting.")],default:"configuredByTheme",description:E.localize(148,"Controls whether the semanticHighlighting is shown for the languages that support it.")},"editor.stablePeek":{type:"boolean",default:!1,markdownDescription:E.localize(149,"Keep peek editors open even when double-clicking their content or when hitting `Escape`.")},"editor.maxTokenizationLineLength":{type:"integer",default:2e4,description:E.localize(150,"Lines above this length will not be tokenized for performance reasons")},"editor.experimental.asyncTokenization":{type:"boolean",default:!0,description:E.localize(151,"Controls whether the tokenization should happen asynchronously on a web worker."),tags:["experimental"]},"editor.experimental.asyncTokenizationLogging":{type:"boolean",default:!1,description:E.localize(152,"Controls whether async tokenization should be logged. For debugging only.")},"editor.experimental.asyncTokenizationVerification":{type:"boolean",default:!1,description:E.localize(153,"Controls whether async tokenization should be verified against legacy background tokenization. Might slow down tokenization. For debugging only."),tags:["experimental"]},"editor.experimental.treeSitterTelemetry":{type:"boolean",default:!1,markdownDescription:E.localize(154,"Controls whether tree sitter parsing should be turned on and telemetry collected. Setting `editor.experimental.preferTreeSitter` for specific languages will take precedence."),tags:["experimental"]},"editor.language.brackets":{type:["array","null"],default:null,description:E.localize(155,"Defines the bracket symbols that increase or decrease the indentation."),items:{type:"array",items:[{type:"string",description:E.localize(156,"The opening bracket character or string sequence.")},{type:"string",description:E.localize(157,"The closing bracket character or string sequence.")}]}},"editor.language.colorizedBracketPairs":{type:["array","null"],default:null,description:E.localize(158,"Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled."),items:{type:"array",items:[{type:"string",description:E.localize(159,"The opening bracket character or string sequence.")},{type:"string",description:E.localize(160,"The closing bracket character or string sequence.")}]}},"diffEditor.maxComputationTime":{type:"number",default:d.diffEditorDefaultOptions.maxComputationTime,description:E.localize(161,"Timeout in milliseconds after which diff computation is cancelled. Use 0 for no timeout.")},"diffEditor.maxFileSize":{type:"number",default:d.diffEditorDefaultOptions.maxFileSize,description:E.localize(162,"Maximum file size in MB for which to compute diffs. Use 0 for no limit.")},"diffEditor.renderSideBySide":{type:"boolean",default:d.diffEditorDefaultOptions.renderSideBySide,description:E.localize(163,"Controls whether the diff editor shows the diff side by side or inline.")},"diffEditor.renderSideBySideInlineBreakpoint":{type:"number",default:d.diffEditorDefaultOptions.renderSideBySideInlineBreakpoint,description:E.localize(164,"If the diff editor width is smaller than this value, the inline view is used.")},"diffEditor.useInlineViewWhenSpaceIsLimited":{type:"boolean",default:d.diffEditorDefaultOptions.useInlineViewWhenSpaceIsLimited,description:E.localize(165,"If enabled and the editor width is too small, the inline view is used.")},"diffEditor.renderMarginRevertIcon":{type:"boolean",default:d.diffEditorDefaultOptions.renderMarginRevertIcon,description:E.localize(166,"When enabled, the diff editor shows arrows in its glyph margin to revert changes.")},"diffEditor.renderGutterMenu":{type:"boolean",default:d.diffEditorDefaultOptions.renderGutterMenu,description:E.localize(167,"When enabled, the diff editor shows a special gutter for revert and stage actions.")},"diffEditor.ignoreTrimWhitespace":{type:"boolean",default:d.diffEditorDefaultOptions.ignoreTrimWhitespace,description:E.localize(168,"When enabled, the diff editor ignores changes in leading or trailing whitespace.")},"diffEditor.renderIndicators":{type:"boolean",default:d.diffEditorDefaultOptions.renderIndicators,description:E.localize(169,"Controls whether the diff editor shows +/- indicators for added/removed changes.")},"diffEditor.codeLens":{type:"boolean",default:d.diffEditorDefaultOptions.diffCodeLens,description:E.localize(170,"Controls whether the editor shows CodeLens.")},"diffEditor.wordWrap":{type:"string",enum:["off","on","inherit"],default:d.diffEditorDefaultOptions.diffWordWrap,markdownEnumDescriptions:[E.localize(171,"Lines will never wrap."),E.localize(172,"Lines will wrap at the viewport width."),E.localize(173,"Lines will wrap according to the {0} setting.","`#editor.wordWrap#`")]},"diffEditor.diffAlgorithm":{type:"string",enum:["legacy","advanced"],default:d.diffEditorDefaultOptions.diffAlgorithm,markdownEnumDescriptions:[E.localize(174,"Uses the legacy diffing algorithm."),E.localize(175,"Uses the advanced diffing algorithm.")],tags:["experimental"]},"diffEditor.hideUnchangedRegions.enabled":{type:"boolean",default:d.diffEditorDefaultOptions.hideUnchangedRegions.enabled,markdownDescription:E.localize(176,"Controls whether the diff editor shows unchanged regions.")},"diffEditor.hideUnchangedRegions.revealLineCount":{type:"integer",default:d.diffEditorDefaultOptions.hideUnchangedRegions.revealLineCount,markdownDescription:E.localize(177,"Controls how many lines are used for unchanged regions."),minimum:1},"diffEditor.hideUnchangedRegions.minimumLineCount":{type:"integer",default:d.diffEditorDefaultOptions.hideUnchangedRegions.minimumLineCount,markdownDescription:E.localize(178,"Controls how many lines are used as a minimum for unchanged regions."),minimum:1},"diffEditor.hideUnchangedRegions.contextLineCount":{type:"integer",default:d.diffEditorDefaultOptions.hideUnchangedRegions.contextLineCount,markdownDescription:E.localize(179,"Controls how many lines are used as context when comparing unchanged regions."),minimum:1},"diffEditor.experimental.showMoves":{type:"boolean",default:d.diffEditorDefaultOptions.experimental.showMoves,markdownDescription:E.localize(180,"Controls whether the diff editor should show detected code moves.")},"diffEditor.experimental.showEmptyDecorations":{type:"boolean",default:d.diffEditorDefaultOptions.experimental.showEmptyDecorations,description:E.localize(181,"Controls whether the diff editor shows empty decorations to see where characters got inserted or deleted.")},"diffEditor.experimental.useTrueInlineView":{type:"boolean",default:d.diffEditorDefaultOptions.experimental.useTrueInlineView,description:E.localize(182,"If enabled and the editor uses the inline view, word changes are rendered inline.")}}};function b(s){return typeof s.type<"u"||typeof s.anyOf<"u"}for(const s of k.editorOptionsRegistry){const g=s.schema;if(typeof g<"u")if(b(g))_.properties[`editor.${s.name}`]=g;else for(const c in g)Object.hasOwnProperty.call(g,c)&&(_.properties[c]=g[c])}let p=null;function n(){return p===null&&(p=Object.create(null),Object.keys(_.properties).forEach(s=>{p[s]=!0})),p}function o(s){return n()[`editor.${s}`]||!1}function t(s){return n()[`diffEditor.${s}`]||!1}m.Registry.as(y.Extensions.Configuration).registerConfiguration(_)}),define(ne[70],se([1,0,3,6,38,128,109]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PLAINTEXT_EXTENSION=e.PLAINTEXT_LANGUAGE_ID=e.ModesRegistry=e.EditorModesRegistry=e.Extensions=void 0,e.Extensions={ModesRegistry:"editor.modesRegistry"};class m{constructor(){this._onDidChangeLanguages=new k.Emitter,this.onDidChangeLanguages=this._onDidChangeLanguages.event,this._languages=[]}registerLanguage(b){return this._languages.push(b),this._onDidChangeLanguages.fire(void 0),{dispose:()=>{for(let p=0,n=this._languages.length;p{}};const r=new y.DisposableStore,u=r.add((0,d.renderMarkdown)(c,{...this._getRenderOptions(c,r),...l},a));return u.element.classList.add("rendered-markdown"),{element:u.element,dispose:()=>r.dispose()}}_getRenderOptions(c,l){return{codeBlockRenderer:async(a,r)=>{let u;a?u=this._languageService.getLanguageIdByLanguageName(a):this._options.editor&&(u=this._options.editor.getModel()?.getLanguageId()),u||(u=b.PLAINTEXT_LANGUAGE_ID);const C=await(0,p.tokenizeToString)(this._languageService,r,u),f=document.createElement("span");if(f.innerHTML=o._ttpTokenizer?.createHTML(C)??C,this._options.editor){const h=this._options.editor.getOption(50);(0,m.applyFontInfo)(f,h)}else this._options.codeBlockFontFamily&&(f.style.fontFamily=this._options.codeBlockFontFamily);return this._options.codeBlockFontSize!==void 0&&(f.style.fontSize=this._options.codeBlockFontSize),f},asyncRenderCallback:()=>this._onDidRenderAsync.fire(),actionHandler:{callback:a=>i(this._openerService,a,c.isTrusted),disposables:l}}}};e.MarkdownRenderer=t,e.MarkdownRenderer=t=o=ke([ce(1,_.ILanguageService),ce(2,n.IOpenerService)],t);async function i(g,c,l){try{return await g.open(c,{fromUserGesture:!0,allowContributedOpeners:!0,allowCommands:s(l)})}catch(a){return(0,I.onUnexpectedError)(a),!1}}function s(g){return g===!0?!0:g&&Array.isArray(g.enabledCommands)?g.enabledCommands:!1}}),define(ne[705],se([1,0,2,6,5,31,28,37,174,85,59,7,120,57,3,16,61,46,480]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HoverWidget=void 0;const l=I.$;let a=class extends b.Widget{get _targetWindow(){return I.getWindow(this._target.targetElements[0])}get _targetDocumentElement(){return I.getWindow(this._target.targetElements[0]).document.documentElement}get isDisposed(){return this._isDisposed}get isMouseIn(){return this._lockMouseTracker.isMouseIn}get domNode(){return this._hover.containerDomNode}get onDispose(){return this._onDispose.event}get onRequestLayout(){return this._onRequestLayout.event}get anchor(){return this._hoverPosition===2?0:1}get x(){return this._x}get y(){return this._y}get isLocked(){return this._isLocked}set isLocked(f){this._isLocked!==f&&(this._isLocked=f,this._hoverContainer.classList.toggle("locked",this._isLocked))}constructor(f,h,v,w,S,L){super(),this._keybindingService=h,this._configurationService=v,this._openerService=w,this._instantiationService=S,this._accessibilityService=L,this._messageListeners=new d.DisposableStore,this._isDisposed=!1,this._forcePosition=!1,this._x=0,this._y=0,this._isLocked=!1,this._enableFocusTraps=!1,this._addedFocusTrap=!1,this._onDispose=this._register(new k.Emitter),this._onRequestLayout=this._register(new k.Emitter),this._linkHandler=f.linkHandler||(N=>(0,o.openLinkFromMarkdown)(this._openerService,N,(0,t.isMarkdownString)(f.content)?f.content.isTrusted:void 0)),this._target="targetElements"in f.target?f.target:new u(f.target),this._hoverPointer=f.appearance?.showPointer?l("div.workbench-hover-pointer"):void 0,this._hover=this._register(new _.HoverWidget),this._hover.containerDomNode.classList.add("workbench-hover","fadeIn"),f.appearance?.compact&&this._hover.containerDomNode.classList.add("workbench-hover","compact"),f.appearance?.skipFadeInAnimation&&this._hover.containerDomNode.classList.add("skip-fade-in"),f.additionalClasses&&this._hover.containerDomNode.classList.add(...f.additionalClasses),f.position?.forcePosition&&(this._forcePosition=!0),f.trapFocus&&(this._enableFocusTraps=!0),this._hoverPosition=f.position?.hoverPosition??3,this.onmousedown(this._hover.containerDomNode,N=>N.stopPropagation()),this.onkeydown(this._hover.containerDomNode,N=>{N.equals(9)&&this.dispose()}),this._register(I.addDisposableListener(this._targetWindow,"blur",()=>this.dispose()));const D=l("div.hover-row.markdown-hover"),T=l("div.hover-contents");if(typeof f.content=="string")T.textContent=f.content,T.style.whiteSpace="pre-wrap";else if(I.isHTMLElement(f.content))T.appendChild(f.content),T.classList.add("html-hover-contents");else{const N=f.content,O=this._instantiationService.createInstance(o.MarkdownRenderer,{codeBlockFontFamily:this._configurationService.getValue("editor").fontFamily||m.EDITOR_FONT_DEFAULTS.fontFamily}),{element:F}=O.render(N,{actionHandler:{callback:x=>this._linkHandler(x),disposables:this._messageListeners},asyncRenderCallback:()=>{T.classList.add("code-hover-contents"),this.layout(),this._onRequestLayout.fire()}});T.appendChild(F)}if(D.appendChild(T),this._hover.contentsDomNode.appendChild(D),f.actions&&f.actions.length>0){const N=l("div.hover-row.status-bar"),O=l("div.actions");f.actions.forEach(F=>{const x=this._keybindingService.lookupKeybinding(F.commandId),W=x?x.getLabel():null;_.HoverAction.render(O,{label:F.label,commandId:F.commandId,run:V=>{F.run(V),this.dispose()},iconClass:F.iconClass},W)}),N.appendChild(O),this._hover.containerDomNode.appendChild(N)}this._hoverContainer=l("div.workbench-hover-container"),this._hoverPointer&&this._hoverContainer.appendChild(this._hoverPointer),this._hoverContainer.appendChild(this._hover.containerDomNode);let M;if(f.actions&&f.actions.length>0?M=!1:f.persistence?.hideOnHover===void 0?M=typeof f.content=="string"||(0,t.isMarkdownString)(f.content)&&!f.content.value.includes("](")&&!f.content.value.includes(""):M=f.persistence.hideOnHover,f.appearance?.showHoverHint){const N=l("div.hover-row.status-bar"),O=l("div.info");O.textContent=(0,i.localize)(68,"Hold {0} key to mouse over",s.isMacintosh?"Option":"Alt"),N.appendChild(O),this._hover.containerDomNode.appendChild(N)}const A=[...this._target.targetElements];M||A.push(this._hoverContainer);const P=this._register(new r(A));if(this._register(P.onMouseOut(()=>{this._isLocked||this.dispose()})),M){const N=[...this._target.targetElements,this._hoverContainer];this._lockMouseTracker=this._register(new r(N)),this._register(this._lockMouseTracker.onMouseOut(()=>{this._isLocked||this.dispose()}))}else this._lockMouseTracker=P}addFocusTrap(){if(!this._enableFocusTraps||this._addedFocusTrap)return;this._addedFocusTrap=!0;const f=this._hover.containerDomNode,h=this.findLastFocusableChild(this._hover.containerDomNode);if(h){const v=I.prepend(this._hoverContainer,l("div")),w=I.append(this._hoverContainer,l("div"));v.tabIndex=0,w.tabIndex=0,this._register(I.addDisposableListener(w,"focus",S=>{f.focus(),S.preventDefault()})),this._register(I.addDisposableListener(v,"focus",S=>{h.focus(),S.preventDefault()}))}}findLastFocusableChild(f){if(f.hasChildNodes())for(let h=0;h=0)return S}const w=this.findLastFocusableChild(v);if(w)return w}}render(f){f.appendChild(this._hoverContainer);const v=this._hoverContainer.contains(this._hoverContainer.ownerDocument.activeElement)&&(0,_.getHoverAccessibleViewHint)(this._configurationService.getValue("accessibility.verbosity.hover")===!0&&this._accessibilityService.isScreenReaderOptimized(),this._keybindingService.lookupKeybinding("editor.action.accessibleView")?.getAriaLabel());v&&(0,c.status)(v),this.layout(),this.addFocusTrap()}layout(){this._hover.containerDomNode.classList.remove("right-aligned"),this._hover.contentsDomNode.style.maxHeight="";const f=A=>{const P=I.getDomNodeZoomLevel(A),N=A.getBoundingClientRect();return{top:N.top*P,bottom:N.bottom*P,right:N.right*P,left:N.left*P}},h=this._target.targetElements.map(A=>f(A)),{top:v,right:w,bottom:S,left:L}=h[0],D=w-L,T=S-v,M={top:v,right:w,bottom:S,left:L,width:D,height:T,center:{x:L+D/2,y:v+T/2}};if(this.adjustHorizontalHoverPosition(M),this.adjustVerticalHoverPosition(M),this.adjustHoverMaxHeight(M),this._hoverContainer.style.padding="",this._hoverContainer.style.margin="",this._hoverPointer){switch(this._hoverPosition){case 1:M.left+=3,M.right+=3,this._hoverContainer.style.paddingLeft="3px",this._hoverContainer.style.marginLeft="-3px";break;case 0:M.left-=3,M.right-=3,this._hoverContainer.style.paddingRight="3px",this._hoverContainer.style.marginRight="-3px";break;case 2:M.top+=3,M.bottom+=3,this._hoverContainer.style.paddingTop="3px",this._hoverContainer.style.marginTop="-3px";break;case 3:M.top-=3,M.bottom-=3,this._hoverContainer.style.paddingBottom="3px",this._hoverContainer.style.marginBottom="-3px";break}M.center.x=M.left+D/2,M.center.y=M.top+T/2}this.computeXCordinate(M),this.computeYCordinate(M),this._hoverPointer&&(this._hoverPointer.classList.remove("top"),this._hoverPointer.classList.remove("left"),this._hoverPointer.classList.remove("right"),this._hoverPointer.classList.remove("bottom"),this.setHoverPointerPosition(M)),this._hover.onContentsChanged()}computeXCordinate(f){const h=this._hover.containerDomNode.clientWidth+2;this._target.x!==void 0?this._x=this._target.x:this._hoverPosition===1?this._x=f.right:this._hoverPosition===0?this._x=f.left-h:(this._hoverPointer?this._x=f.center.x-this._hover.containerDomNode.clientWidth/2:this._x=f.left,this._x+h>=this._targetDocumentElement.clientWidth&&(this._hover.containerDomNode.classList.add("right-aligned"),this._x=Math.max(this._targetDocumentElement.clientWidth-h-2,this._targetDocumentElement.clientLeft))),this._xthis._targetWindow.innerHeight&&(this._y=f.bottom)}adjustHorizontalHoverPosition(f){if(this._target.x!==void 0)return;const h=this._hoverPointer?3:0;if(this._forcePosition){const v=h+2;this._hoverPosition===1?this._hover.containerDomNode.style.maxWidth=`${this._targetDocumentElement.clientWidth-f.right-v}px`:this._hoverPosition===0&&(this._hover.containerDomNode.style.maxWidth=`${f.left-v}px`);return}this._hoverPosition===1?this._targetDocumentElement.clientWidth-f.right=this._hover.containerDomNode.clientWidth+h?this._hoverPosition=0:this._hoverPosition=2):this._hoverPosition===0&&(f.left=this._hover.containerDomNode.clientWidth+h?this._hoverPosition=1:this._hoverPosition=2),f.left-this._hover.containerDomNode.clientWidth-h<=this._targetDocumentElement.clientLeft&&(this._hoverPosition=1))}adjustVerticalHoverPosition(f){if(this._target.y!==void 0||this._forcePosition)return;const h=this._hoverPointer?3:0;this._hoverPosition===3?f.top-this._hover.containerDomNode.clientHeight-h<0&&(this._hoverPosition=2):this._hoverPosition===2&&f.bottom+this._hover.containerDomNode.clientHeight+h>this._targetWindow.innerHeight&&(this._hoverPosition=3)}adjustHoverMaxHeight(f){let h=this._targetWindow.innerHeight/2;if(this._forcePosition){const v=(this._hoverPointer?3:0)+2;this._hoverPosition===3?h=Math.min(h,f.top-v):this._hoverPosition===2&&(h=Math.min(h,this._targetWindow.innerHeight-f.bottom-v))}if(this._hover.containerDomNode.style.maxHeight=`${h}px`,this._hover.contentsDomNode.clientHeightf.height?this._hoverPointer.style.top=`${f.center.y-(this._y-h)-3}px`:this._hoverPointer.style.top=`${Math.round(h/2)-3}px`;break}case 3:case 2:{this._hoverPointer.classList.add(this._hoverPosition===3?"bottom":"top");const h=this._hover.containerDomNode.clientWidth;let v=Math.round(h/2)-3;const w=this._x+v;(wf.right)&&(v=f.center.x-this._x-3),this._hoverPointer.style.left=`${v}px`;break}}}focus(){this._hover.containerDomNode.focus()}dispose(){this._isDisposed||(this._onDispose.fire(),this._hoverContainer.remove(),this._messageListeners.dispose(),this._target.dispose(),super.dispose()),this._isDisposed=!0}};e.HoverWidget=a,e.HoverWidget=a=ke([ce(1,E.IKeybindingService),ce(2,y.IConfigurationService),ce(3,p.IOpenerService),ce(4,n.IInstantiationService),ce(5,g.IAccessibilityService)],a);class r extends b.Widget{get onMouseOut(){return this._onMouseOut.event}get isMouseIn(){return this._isMouseIn}constructor(f){super(),this._elements=f,this._isMouseIn=!0,this._onMouseOut=this._register(new k.Emitter),this._elements.forEach(h=>this.onmouseover(h,()=>this._onTargetMouseOver(h))),this._elements.forEach(h=>this.onmouseleave(h,()=>this._onTargetMouseLeave(h)))}_onTargetMouseOver(f){this._isMouseIn=!0,this._clearEvaluateMouseStateTimeout(f)}_onTargetMouseLeave(f){this._isMouseIn=!1,this._evaluateMouseState(f)}_evaluateMouseState(f){this._clearEvaluateMouseStateTimeout(f),this._mouseTimeout=I.getWindow(f).setTimeout(()=>this._fireIfMouseOutside(),0)}_clearEvaluateMouseStateTimeout(f){this._mouseTimeout&&(I.getWindow(f).clearTimeout(this._mouseTimeout),this._mouseTimeout=void 0)}_fireIfMouseOutside(){this._isMouseIn||this._onMouseOut.fire()}}class u{constructor(f){this._element=f,this.targetElements=[this._element]}dispose(){}}}),define(ne[36],se([1,0,6,2,11,147,131,568,659,569,571,208,7,28,43,49,70,660]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ResolvedLanguageConfiguration=e.LanguageConfigurationRegistry=e.LanguageConfigurationChangeEvent=e.LanguageConfigurationService=e.ILanguageConfigurationService=e.LanguageConfigurationServiceChangeEvent=void 0,e.getIndentationAtPosition=h;class l{constructor(A){this.languageId=A}affects(A){return this.languageId?this.languageId===A:!0}}e.LanguageConfigurationServiceChangeEvent=l,e.ILanguageConfigurationService=(0,o.createDecorator)("languageConfigurationService");let a=class extends k.Disposable{constructor(A,P){super(),this.configurationService=A,this.languageService=P,this._registry=this._register(new D),this.onDidChangeEmitter=this._register(new d.Emitter),this.onDidChange=this.onDidChangeEmitter.event,this.configurations=new Map;const N=new Set(Object.values(u));this._register(this.configurationService.onDidChangeConfiguration(O=>{const F=O.change.keys.some(W=>N.has(W)),x=O.change.overrides.filter(([W,V])=>V.some(q=>N.has(q))).map(([W])=>W);if(F)this.configurations.clear(),this.onDidChangeEmitter.fire(new l(void 0));else for(const W of x)this.languageService.isRegisteredLanguageId(W)&&(this.configurations.delete(W),this.onDidChangeEmitter.fire(new l(W)))})),this._register(this._registry.onDidChange(O=>{this.configurations.delete(O.languageId),this.onDidChangeEmitter.fire(new l(O.languageId))}))}register(A,P,N){return this._registry.register(A,P,N)}getLanguageConfiguration(A){let P=this.configurations.get(A);return P||(P=r(A,this._registry,this.configurationService,this.languageService),this.configurations.set(A,P)),P}};e.LanguageConfigurationService=a,e.LanguageConfigurationService=a=ke([ce(0,t.IConfigurationService),ce(1,i.ILanguageService)],a);function r(M,A,P,N){let O=A.getLanguageConfiguration(M);if(!O){if(!N.isRegisteredLanguageId(M))return new T(M,{});O=new T(M,{})}const F=C(O.languageId,P),x=w([O.underlyingConfig,F]);return new T(O.languageId,x)}const u={brackets:"editor.language.brackets",colorizedBracketPairs:"editor.language.colorizedBracketPairs"};function C(M,A){const P=A.getValue(u.brackets,{overrideIdentifier:M}),N=A.getValue(u.colorizedBracketPairs,{overrideIdentifier:M});return{brackets:f(P),colorizedBracketPairs:f(N)}}function f(M){if(Array.isArray(M))return M.map(A=>{if(!(!Array.isArray(A)||A.length!==2))return[A[0],A[1]]}).filter(A=>!!A)}function h(M,A,P){const N=M.getLineContent(A);let O=I.getLeadingWhitespace(N);return O.length>P-1&&(O=O.substring(0,P-1)),O}class v{constructor(A){this.languageId=A,this._resolved=null,this._entries=[],this._order=0,this._resolved=null}register(A,P){const N=new S(A,P,++this._order);return this._entries.push(N),this._resolved=null,(0,k.toDisposable)(()=>{for(let O=0;OA.configuration)))}}function w(M){let A={comments:void 0,brackets:void 0,wordPattern:void 0,indentationRules:void 0,onEnterRules:void 0,autoClosingPairs:void 0,surroundingPairs:void 0,autoCloseBefore:void 0,folding:void 0,colorizedBracketPairs:void 0,__electricCharacterSupport:void 0};for(const P of M)A={comments:P.comments||A.comments,brackets:P.brackets||A.brackets,wordPattern:P.wordPattern||A.wordPattern,indentationRules:P.indentationRules||A.indentationRules,onEnterRules:P.onEnterRules||A.onEnterRules,autoClosingPairs:P.autoClosingPairs||A.autoClosingPairs,surroundingPairs:P.surroundingPairs||A.surroundingPairs,autoCloseBefore:P.autoCloseBefore||A.autoCloseBefore,folding:P.folding||A.folding,colorizedBracketPairs:P.colorizedBracketPairs||A.colorizedBracketPairs,__electricCharacterSupport:P.__electricCharacterSupport||A.__electricCharacterSupport};return A}class S{constructor(A,P,N){this.configuration=A,this.priority=P,this.order=N}static cmp(A,P){return A.priority===P.priority?A.order-P.order:A.priority-P.priority}}class L{constructor(A){this.languageId=A}}e.LanguageConfigurationChangeEvent=L;class D extends k.Disposable{constructor(){super(),this._entries=new Map,this._onDidChange=this._register(new d.Emitter),this.onDidChange=this._onDidChange.event,this._register(this.register(g.PLAINTEXT_LANGUAGE_ID,{brackets:[["(",")"],["[","]"],["{","}"]],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"`",close:"`"}],colorizedBracketPairs:[],folding:{offSide:!0}},0))}register(A,P,N=0){let O=this._entries.get(A);O||(O=new v(A),this._entries.set(A,O));const F=O.register(P,N);return this._onDidChange.fire(new L(A)),(0,k.toDisposable)(()=>{F.dispose(),this._onDidChange.fire(new L(A))})}getLanguageConfiguration(A){return this._entries.get(A)?.getResolvedConfiguration()||null}}e.LanguageConfigurationRegistry=D;class T{constructor(A,P){this.languageId=A,this.underlyingConfig=P,this._brackets=null,this._electricCharacter=null,this._onEnterSupport=this.underlyingConfig.brackets||this.underlyingConfig.indentationRules||this.underlyingConfig.onEnterRules?new p.OnEnterSupport(this.underlyingConfig):null,this.comments=T._handleComments(this.underlyingConfig),this.characterPair=new m.CharacterPairSupport(this.underlyingConfig),this.wordDefinition=this.underlyingConfig.wordPattern||E.DEFAULT_WORD_REGEXP,this.indentationRules=this.underlyingConfig.indentationRules,this.underlyingConfig.indentationRules?this.indentRulesSupport=new b.IndentRulesSupport(this.underlyingConfig.indentationRules):this.indentRulesSupport=null,this.foldingRules=this.underlyingConfig.folding||{},this.bracketsNew=new c.LanguageBracketsConfiguration(A,this.underlyingConfig)}getWordDefinition(){return(0,E.ensureValidWordDefinition)(this.wordDefinition)}get brackets(){return!this._brackets&&this.underlyingConfig.brackets&&(this._brackets=new n.RichEditBrackets(this.languageId,this.underlyingConfig.brackets)),this._brackets}get electricCharacter(){return this._electricCharacter||(this._electricCharacter=new _.BracketElectricCharacterSupport(this.brackets)),this._electricCharacter}onEnter(A,P,N,O){return this._onEnterSupport?this._onEnterSupport.onEnter(A,P,N,O):null}getAutoClosingPairs(){return new y.AutoClosingPairs(this.characterPair.getAutoClosingPairs())}getAutoCloseBeforeSet(A){return this.characterPair.getAutoCloseBeforeSet(A)}getSurroundingPairs(){return this.characterPair.getSurroundingPairs()}static _handleComments(A){const P=A.comments;if(!P)return null;const N={};if(P.lineComment&&(N.lineCommentToken=P.lineComment),P.blockComment){const[O,F]=P.blockComment;N.blockCommentStartToken=O,N.blockCommentEndToken=F}return N}}e.ResolvedLanguageConfiguration=T,(0,s.registerSingleton)(e.ILanguageConfigurationService,a,1)}),define(ne[401],se([1,0,14,2,361,646,4,36,666,51,211,13,62,54,8,17,232,105,55,52,5,373,326]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorWorkerClient=e.EditorWorkerService=void 0;const f=5*60*1e3;function h(T,M){const A=T.getModel(M);return!(!A||A.isTooLargeForSyncing())}let v=class extends k.Disposable{constructor(M,A,P,N,O,F){super(),this._languageConfigurationService=O,this._modelService=A,this._workerManager=this._register(new S(M,this._modelService)),this._logService=N,this._register(F.linkProvider.register({language:"*",hasAccessToAllModels:!0},{provideLinks:async(x,W)=>{if(!h(this._modelService,x.uri))return Promise.resolve({links:[]});const q=await(await this._workerWithResources([x.uri])).$computeLinks(x.uri.toString());return q&&{links:q}}})),this._register(F.completionProvider.register("*",new w(this._workerManager,P,this._modelService,this._languageConfigurationService)))}dispose(){super.dispose()}canComputeUnicodeHighlights(M){return h(this._modelService,M)}async computedUnicodeHighlights(M,A,P){return(await this._workerWithResources([M])).$computeUnicodeHighlights(M.toString(),A,P)}async computeDiff(M,A,P,N){const F=await(await this._workerWithResources([M,A],!0)).$computeDiff(M.toString(),A.toString(),P,N);if(!F)return null;return{identical:F.identical,quitEarly:F.quitEarly,changes:W(F.changes),moves:F.moves.map(V=>new g.MovedText(new c.LineRangeMapping(new l.LineRange(V[0],V[1]),new l.LineRange(V[2],V[3])),W(V[4])))};function W(V){return V.map(q=>new c.DetailedLineRangeMapping(new l.LineRange(q[0],q[1]),new l.LineRange(q[2],q[3]),q[4]?.map(H=>new c.RangeMapping(new y.Range(H[0],H[1],H[2],H[3]),new y.Range(H[4],H[5],H[6],H[7])))))}}async computeMoreMinimalEdits(M,A,P=!1){if((0,n.isNonEmptyArray)(A)){if(!h(this._modelService,M))return Promise.resolve(A);const N=t.StopWatch.create(),O=this._workerWithResources([M]).then(F=>F.$computeMoreMinimalEdits(M.toString(),A,P));return O.finally(()=>this._logService.trace("FORMAT#computeMoreMinimalEdits",M.toString(!0),N.elapsed())),Promise.race([O,(0,d.timeout)(1e3).then(()=>A)])}else return Promise.resolve(void 0)}canNavigateValueSet(M){return h(this._modelService,M)}async navigateValueSet(M,A,P){const N=this._modelService.getModel(M);if(!N)return null;const O=this._languageConfigurationService.getLanguageConfiguration(N.getLanguageId()).getWordDefinition(),F=O.source,x=O.flags;return(await this._workerWithResources([M])).$navigateValueSet(M.toString(),A,P,F,x)}canComputeWordRanges(M){return h(this._modelService,M)}async computeWordRanges(M,A){const P=this._modelService.getModel(M);if(!P)return Promise.resolve(null);const N=this._languageConfigurationService.getLanguageConfiguration(P.getLanguageId()).getWordDefinition(),O=N.source,F=N.flags;return(await this._workerWithResources([M])).$computeWordRanges(M.toString(),A,O,F)}async findSectionHeaders(M,A){return(await this._workerWithResources([M])).$findSectionHeaders(M.toString(),A)}async computeDefaultDocumentColors(M){return(await this._workerWithResources([M])).$computeDefaultDocumentColors(M.toString())}async _workerWithResources(M,A=!1){return await(await this._workerManager.withWorker()).workerWithSyncedResources(M,A)}};e.EditorWorkerService=v,e.EditorWorkerService=v=ke([ce(1,b.IModelService),ce(2,p.ITextResourceConfigurationService),ce(3,o.ILogService),ce(4,m.ILanguageConfigurationService),ce(5,s.ILanguageFeaturesService)],v);class w{constructor(M,A,P,N){this.languageConfigurationService=N,this._debugDisplayName="wordbasedCompletions",this._workerManager=M,this._configurationService=A,this._modelService=P}async provideCompletionItems(M,A){const P=this._configurationService.getValue(M.uri,A,"editor");if(P.wordBasedSuggestions==="off")return;const N=[];if(P.wordBasedSuggestions==="currentDocument")h(this._modelService,M.uri)&&N.push(M.uri);else for(const H of this._modelService.getModels())h(this._modelService,H.uri)&&(H===M?N.unshift(H.uri):(P.wordBasedSuggestions==="allDocuments"||H.getLanguageId()===M.getLanguageId())&&N.push(H.uri));if(N.length===0)return;const O=this.languageConfigurationService.getLanguageConfiguration(M.getLanguageId()).getWordDefinition(),F=M.getWordAtPosition(A),x=F?new y.Range(A.lineNumber,F.startColumn,A.lineNumber,F.endColumn):y.Range.fromPositions(A),W=x.setEndPosition(A.lineNumber,A.column),q=await(await this._workerManager.withWorker()).textualSuggest(N,F?.word,O);if(q)return{duration:q.duration,suggestions:q.words.map(H=>({kind:18,label:H,insertText:H,range:{insert:W,replace:x}}))}}}let S=class extends k.Disposable{constructor(M,A){super(),this._workerDescriptor=M,this._modelService=A,this._editorWorkerClient=null,this._lastWorkerUsedTime=new Date().getTime(),this._register(new r.WindowIntervalTimer).cancelAndSet(()=>this._checkStopIdleWorker(),Math.round(f/2),a.mainWindow),this._register(this._modelService.onModelRemoved(N=>this._checkStopEmptyWorker()))}dispose(){this._editorWorkerClient&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null),super.dispose()}_checkStopEmptyWorker(){if(!this._editorWorkerClient)return;this._modelService.getModels().length===0&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null)}_checkStopIdleWorker(){if(!this._editorWorkerClient)return;new Date().getTime()-this._lastWorkerUsedTime>f&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null)}withWorker(){return this._lastWorkerUsedTime=new Date().getTime(),this._editorWorkerClient||(this._editorWorkerClient=new D(this._workerDescriptor,!1,this._modelService)),Promise.resolve(this._editorWorkerClient)}};S=ke([ce(1,b.IModelService)],S);class L{constructor(M){this._instance=M,this.proxy=this._instance}dispose(){this._instance.dispose()}setChannel(M,A){throw new Error("Not supported")}}let D=class extends k.Disposable{constructor(M,A,P){super(),this._workerDescriptor=M,this._disposed=!1,this._modelService=P,this._keepIdleModels=A,this._worker=null,this._modelManager=null}fhr(M,A){throw new Error("Not implemented!")}_getOrCreateWorker(){if(!this._worker)try{this._worker=this._register((0,E.createWebWorker)(this._workerDescriptor)),C.EditorWorkerHost.setChannel(this._worker,this._createEditorWorkerHost())}catch(M){(0,I.logOnceWebWorkerWarning)(M),this._worker=this._createFallbackLocalWorker()}return this._worker}async _getProxy(){try{const M=this._getOrCreateWorker().proxy;return await M.$ping(),M}catch(M){return(0,I.logOnceWebWorkerWarning)(M),this._worker=this._createFallbackLocalWorker(),this._worker.proxy}}_createFallbackLocalWorker(){return new L(new _.EditorSimpleWorker(this._createEditorWorkerHost(),null))}_createEditorWorkerHost(){return{$fhr:(M,A)=>this.fhr(M,A)}}_getOrCreateModelManager(M){return this._modelManager||(this._modelManager=this._register(new u.WorkerTextModelSyncClient(M,this._modelService,this._keepIdleModels))),this._modelManager}async workerWithSyncedResources(M,A=!1){if(this._disposed)return Promise.reject((0,i.canceled)());const P=await this._getProxy();return this._getOrCreateModelManager(P).ensureSyncedResources(M,A),P}async textualSuggest(M,A,P){const N=await this.workerWithSyncedResources(M),O=P.source,F=P.flags;return N.$textualSuggest(M.map(x=>x.toString()),A,O,F)}dispose(){super.dispose(),this._disposed=!0}};e.EditorWorkerClient=D,e.EditorWorkerClient=D=ke([ce(2,b.IModelService)],D)}),define(ne[275],se([1,0,131,36,240]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getEnterAction=E;function E(y,m,_,b){m.tokenization.forceTokenization(_.startLineNumber);const p=m.getLanguageIdAtPosition(_.startLineNumber,_.startColumn),n=b.getLanguageConfiguration(p);if(!n)return null;const t=new I.IndentationContextProcessor(m,b).getProcessedTokenContextAroundRange(_),i=t.previousLineProcessedTokens.getLineContent(),s=t.beforeRangeProcessedTokens.getLineContent(),g=t.afterRangeProcessedTokens.getLineContent(),c=n.onEnter(y,i,s,g);if(!c)return null;const l=c.indentAction;let a=c.appendText;const r=c.removeText||0;a?l===d.IndentAction.Indent&&(a=" "+a):l===d.IndentAction.Indent||l===d.IndentAction.IndentOutdent?a=" ":a="";let u=(0,k.getIndentationAtPosition)(m,_.startLineNumber,_.startColumn);return r&&(u=u.substring(0,u.length-r)),{indentAction:l,appendText:a,removeText:r,indentation:u}}}),define(ne[183],se([1,0,11,94,4,23,275,36]),function(oe,e,d,k,I,E,y,m){"use strict";var _;Object.defineProperty(e,"__esModule",{value:!0}),e.ShiftCommand=void 0;const b=Object.create(null);function p(o,t){if(t<=0)return"";b[o]||(b[o]=["",o]);const i=b[o];for(let s=i.length;s<=t;s++)i[s]=i[s-1]+o;return i[t]}let n=_=class{static unshiftIndent(t,i,s,g,c){const l=k.CursorColumns.visibleColumnFromColumn(t,i,s);if(c){const a=p(" ",g),u=k.CursorColumns.prevIndentTabStop(l,g)/g;return p(a,u)}else{const a=" ",u=k.CursorColumns.prevRenderTabStop(l,s)/s;return p(a,u)}}static shiftIndent(t,i,s,g,c){const l=k.CursorColumns.visibleColumnFromColumn(t,i,s);if(c){const a=p(" ",g),u=k.CursorColumns.nextIndentTabStop(l,g)/g;return p(a,u)}else{const a=" ",u=k.CursorColumns.nextRenderTabStop(l,s)/s;return p(a,u)}}constructor(t,i,s){this._languageConfigurationService=s,this._opts=i,this._selection=t,this._selectionId=null,this._useLastEditRangeForCursorEndPosition=!1,this._selectionStartColumnStaysPut=!1}_addEditOperation(t,i,s){this._useLastEditRangeForCursorEndPosition?t.addTrackedEditOperation(i,s):t.addEditOperation(i,s)}getEditOperations(t,i){const s=this._selection.startLineNumber;let g=this._selection.endLineNumber;this._selection.endColumn===1&&s!==g&&(g=g-1);const{tabSize:c,indentSize:l,insertSpaces:a}=this._opts,r=s===g;if(this._opts.useTabStops){this._selection.isEmpty()&&/^\s*$/.test(t.getLineContent(s))&&(this._useLastEditRangeForCursorEndPosition=!0);let u=0,C=0;for(let f=s;f<=g;f++,u=C){C=0;const h=t.getLineContent(f);let v=d.firstNonWhitespaceIndex(h);if(this._opts.isUnshift&&(h.length===0||v===0)||!r&&!this._opts.isUnshift&&h.length===0)continue;if(v===-1&&(v=h.length),f>1&&k.CursorColumns.visibleColumnFromColumn(h,v+1,c)%l!==0&&t.tokenization.isCheapToTokenize(f-1)){const L=(0,y.getEnterAction)(this._opts.autoIndent,t,new I.Range(f-1,t.getLineMaxColumn(f-1),f-1,t.getLineMaxColumn(f-1)),this._languageConfigurationService);if(L){if(C=u,L.appendText)for(let D=0,T=L.appendText.length;Dx(H,K),unshiftIndent:K=>W(H,K)},H.languageConfigurationService);if(Y===null)return null;const G=(0,o.getIndentationAtPosition)(z,U.startLineNumber,U.startColumn);return Y===H.normalizeIndentation(G)?null:Y}static _getIndentationAndAutoClosingPairEdits(H,z,U,j,Y){const G=U.map(({selection:R,indentation:J})=>{if(Y!==null){const ie=this._getEditFromIndentationAndSelection(H,z,J,R,j,!1);return new T(ie,R,j,Y)}else{const ie=this._getEditFromIndentationAndSelection(H,z,J,R,j,!0);return F(ie.range,ie.text,!1)}}),K={shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!1};return new m.EditOperationResult(4,G,K)}static _getEditFromIndentationAndSelection(H,z,U,j,Y,G=!0){const K=j.startLineNumber,R=z.getLineFirstNonWhitespaceColumn(K);let J=H.normalizeIndentation(U);if(R!==0){const ue=z.getLineContent(K);J+=ue.substring(R-1,j.startColumn-1)}return J+=G?Y:"",{range:new b.Range(K,1,j.endLineNumber,j.endColumn),text:J}}}e.AutoIndentOperation=g;class c{static getEdits(H,z,U,j,Y,G){if(O(z,U,j,Y,G))return this._runAutoClosingOvertype(H,j,G)}static _runAutoClosingOvertype(H,z,U){const j=[];for(let Y=0,G=z.length;Ynew I.ReplaceCommand(new b.Range(K.positionLineNumber,K.positionColumn,K.positionLineNumber,K.positionColumn+1),"",!1));return new m.EditOperationResult(4,G,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!1})}}}e.AutoClosingOvertypeWithInterceptorsOperation=l;class a{static getEdits(H,z,U,j,Y,G){if(!G){const K=this.getAutoClosingPairClose(H,z,U,j,Y);if(K!==null)return this._runAutoClosingOpenCharType(U,j,Y,K)}}static _runAutoClosingOpenCharType(H,z,U,j){const Y=[];for(let G=0,K=H.length;G{const ee=ae.getPosition();return Y?{lineNumber:ee.lineNumber,beforeColumn:ee.column-j.length,afterColumn:ee.column}:{lineNumber:ee.lineNumber,beforeColumn:ee.column,afterColumn:ee.column}}),K=this._findAutoClosingPairOpen(H,z,G.map(ae=>new p.Position(ae.lineNumber,ae.beforeColumn)),j);if(!K)return null;let R,J;if((0,m.isQuote)(j)?(R=H.autoClosingQuotes,J=H.shouldAutoCloseBefore.quote):(H.blockCommentStartToken?K.open.includes(H.blockCommentStartToken):!1)?(R=H.autoClosingComments,J=H.shouldAutoCloseBefore.comment):(R=H.autoClosingBrackets,J=H.shouldAutoCloseBefore.bracket),R==="never")return null;const ue=this._findContainedAutoClosingPair(H,K),he=ue?ue.close:"";let pe=!0;for(const ae of G){const{lineNumber:ee,beforeColumn:de,afterColumn:ge}=ae,X=z.getLineContent(ee),B=X.substring(0,de-1),$=X.substring(ge-1);if($.startsWith(he)||(pe=!1),$.length>0){const re=$.charAt(0);if(!this._isBeforeClosingBrace(H,$)&&!J(re))return null}if(K.open.length===1&&(j==="'"||j==='"')&&R!=="always"){const re=(0,_.getMapForWordSeparators)(H.wordSeparators,[]);if(B.length>0){const le=B.charCodeAt(B.length-1);if(re.get(le)===0)return null}}if(!z.tokenization.isCheapToTokenize(ee))return null;z.tokenization.forceTokenization(ee);const Q=z.tokenization.getLineTokens(ee),Z=(0,t.createScopedLineTokens)(Q,de-1);if(!K.shouldAutoClose(Z,de-Z.firstCharOffset))return null;const te=K.findNeutralCharacter();if(te){const re=z.tokenization.getTokenTypeIfInsertingCharacter(ee,de,te);if(!K.isOK(re))return null}}return pe?K.close.substring(0,K.close.length-he.length):K.close}static _findContainedAutoClosingPair(H,z){if(z.open.length<=1)return null;const U=z.close.charAt(z.close.length-1),j=H.autoClosingPairs.autoClosingPairsCloseByEnd.get(U)||[];let Y=null;for(const G of j)G.open!==z.open&&z.open.includes(G.open)&&z.close.endsWith(G.close)&&(!Y||G.open.length>Y.open.length)&&(Y=G);return Y}static _findAutoClosingPairOpen(H,z,U,j){const Y=H.autoClosingPairs.autoClosingPairsOpenByEnd.get(j);if(!Y)return null;let G=null;for(const K of Y)if(G===null||K.open.length>G.open.length){let R=!0;for(const J of U)if(z.getValueInRange(new b.Range(J.lineNumber,J.column-K.open.length+1,J.lineNumber,J.column))+j!==K.open){R=!1;break}R&&(G=K)}return G}static _isBeforeClosingBrace(H,z){const U=z.charAt(0),j=H.autoClosingPairs.autoClosingPairsOpenByStart.get(U)||[],Y=H.autoClosingPairs.autoClosingPairsCloseByStart.get(U)||[],G=j.some(R=>z.startsWith(R.open)),K=Y.some(R=>z.startsWith(R.close));return!G&&K}}e.AutoClosingOpenCharTypeOperation=a;class r{static getEdits(H,z,U,j,Y){if(!Y&&this._isSurroundSelectionType(H,z,U,j))return this._runSurroundSelectionType(H,U,j)}static _runSurroundSelectionType(H,z,U){const j=[];for(let Y=0,G=z.length;Y=4){const R=(0,i.getIndentForEnter)(H.autoIndent,z,j,{unshiftIndent:J=>W(H,J),shiftIndent:J=>x(H,J),normalizeIndentation:J=>H.normalizeIndentation(J)},H.languageConfigurationService);if(R){let J=H.visibleColumnFromColumn(z,j.getEndPosition());const ie=j.endColumn,ue=z.getLineContent(j.endLineNumber),he=k.firstNonWhitespaceIndex(ue);if(he>=0?j=j.setEndPosition(j.endLineNumber,Math.max(j.endColumn,he+1)):j=j.setEndPosition(j.endLineNumber,z.getLineMaxColumn(j.endLineNumber)),U)return new I.ReplaceCommandWithoutChangingPosition(j,` `+H.normalizeIndentation(R.afterEnter),!0);{let pe=0;return ie<=he+1&&(H.insertSpaces||(J=Math.ceil(J/H.indentSize)),pe=Math.min(J+1-H.normalizeIndentation(R.afterEnter).length-1,0)),new I.ReplaceCommandWithOffsetCursorState(j,` `+H.normalizeIndentation(R.afterEnter),0,pe,!0)}}}return F(j,` `+H.normalizeIndentation(K),U)}static lineInsertBefore(H,z,U){if(z===null||U===null)return[];const j=[];for(let Y=0,G=U.length;Ythis._compositionType(U,ie,Y,G,K,R));return new m.EditOperationResult(4,J,{shouldPushStackElementBefore:A(H,4),shouldPushStackElementAfter:!1})}static _compositionType(H,z,U,j,Y,G){if(!z.isEmpty())return null;const K=z.getPosition(),R=Math.max(1,K.column-j),J=Math.min(H.getLineMaxColumn(K.lineNumber),K.column+Y),ie=new b.Range(K.lineNumber,R,K.lineNumber,J);return H.getValueInRange(ie)===U&&G===0?null:new I.ReplaceCommandWithOffsetCursorState(ie,U,0,G)}}e.CompositionOperation=v;class w{static getEdits(H,z,U){const j=[];for(let G=0,K=z.length;G1){let K;for(K=U-1;K>=1;K--){const ie=z.getLineContent(K);if(k.lastNonWhitespaceIndex(ie)>=0)break}if(K<1)return null;const R=z.getLineMaxColumn(K),J=(0,s.getEnterAction)(H.autoIndent,z,new b.Range(K,R,K,R),H.languageConfigurationService);J&&(Y=J.indentation+J.appendText)}return j&&(j===n.IndentAction.Indent&&(Y=x(H,Y)),j===n.IndentAction.Outdent&&(Y=W(H,Y)),Y=H.normalizeIndentation(Y)),Y||null}static _replaceJumpToNextIndent(H,z,U,j){let Y="";const G=U.getStartPosition();if(H.insertSpaces){const K=H.visibleColumnFromColumn(z,G),R=H.indentSize,J=R-K%R;for(let ie=0;ie2?J.charCodeAt(R.column-2):0)===92&&ue)return!1;if(q.autoClosingOvertype==="auto"){let pe=!1;for(let ae=0,ee=U.length;ae0){const f=this._cursors.getSelections();for(let h=0;hL&&(w=w.slice(0,L),S=!0);const D=c.from(this._model,this);return this._cursors.setStates(w),this._cursors.normalize(),this._columnSelectData=null,this._validateAutoClosedActions(),this._emitStateChangedIfNecessary(f,h,v,D,S)}setCursorColumnSelectData(f){this._columnSelectData=f}revealAll(f,h,v,w,S,L){const D=this._cursors.getViewPositions();let T=null,M=null;D.length>1?M=this._cursors.getViewSelections():T=p.Range.fromPositions(D[0],D[0]),f.emitViewEvent(new t.ViewRevealRangeRequestEvent(h,v,T,M,w,S,L))}revealPrimary(f,h,v,w,S,L){const T=[this._cursors.getPrimaryCursor().viewState.selection];f.emitViewEvent(new t.ViewRevealRangeRequestEvent(h,v,null,T,w,S,L))}saveState(){const f=[],h=this._cursors.getSelections();for(let v=0,w=h.length;v0){const S=E.CursorState.fromModelSelections(v.resultingSelection);this.setStates(f,"modelChange",v.isUndoing?5:v.isRedoing?6:2,S)&&this.revealAll(f,"modelChange",!1,0,!0,0)}else{const S=this._cursors.readSelectionFromMarkers();this.setStates(f,"modelChange",2,E.CursorState.fromModelSelections(S))}}}getSelection(){return this._cursors.getPrimaryCursor().modelState.selection}getTopMostViewPosition(){return this._cursors.getTopMostViewPosition()}getBottomMostViewPosition(){return this._cursors.getBottomMostViewPosition()}getCursorColumnSelectData(){if(this._columnSelectData)return this._columnSelectData;const f=this._cursors.getPrimaryCursor(),h=f.viewState.selectionStart.getStartPosition(),v=f.viewState.position;return{isReal:!1,fromViewLineNumber:h.lineNumber,fromViewVisualColumn:this.context.cursorConfig.visibleColumnFromColumn(this._viewModel,h),toViewLineNumber:v.lineNumber,toViewVisualColumn:this.context.cursorConfig.visibleColumnFromColumn(this._viewModel,v)}}getSelections(){return this._cursors.getSelections()}setSelections(f,h,v,w){this.setStates(f,h,w,E.CursorState.fromModelSelections(v))}getPrevEditOperationType(){return this._prevEditOperationType}setPrevEditOperationType(f){this._prevEditOperationType=f}_pushAutoClosedAction(f,h){const v=[],w=[];for(let D=0,T=f.length;D0&&this._pushAutoClosedAction(v,w),this._prevEditOperationType=f.type}f.shouldPushStackElementAfter&&this._model.pushStackElement()}_interpretCommandResult(f){(!f||f.length===0)&&(f=this._cursors.readSelectionFromMarkers()),this._columnSelectData=null,this._cursors.setSelections(f),this._cursors.normalize()}_emitStateChangedIfNecessary(f,h,v,w,S){const L=c.from(this._model,this);if(L.equals(w))return!1;const D=this._cursors.getSelections(),T=this._cursors.getViewSelections();if(f.emitViewEvent(new t.ViewCursorStateChangedEvent(T,D,v)),!w||w.cursorState.length!==L.cursorState.length||L.cursorState.some((M,A)=>!M.modelState.equals(w.cursorState[A].modelState))){const M=w?w.cursorState.map(P=>P.modelState.selection):null,A=w?w.modelVersionId:0;f.emitOutgoingEvent(new s.CursorStateChangedEvent(M,D,A,L.modelVersionId,h||"keyboard",v,S))}return!0}_findAutoClosingPairs(f){if(!f.length)return null;const h=[];for(let v=0,w=f.length;v=0)return null;const L=S.text.match(/([)\]}>'"`])([^)\]}>'"`]*)$/);if(!L)return null;const D=L[1],T=this.context.cursorConfig.autoClosingPairs.autoClosingPairsCloseSingleChar.get(D);if(!T||T.length!==1)return null;const M=T[0].open,A=S.text.length-L[2].length-1,P=S.text.lastIndexOf(M,A-1);if(P===-1)return null;h.push([P,A])}return h}executeEdits(f,h,v,w){let S=null;h==="snippet"&&(S=this._findAutoClosingPairs(v)),S&&(v[0]._isTracked=!0);const L=[],D=[],T=this._model.pushEditOperations(this.getSelections(),v,M=>{if(S)for(let P=0,N=S.length;P0&&this._pushAutoClosedAction(L,D)}_executeEdit(f,h,v,w=0){if(this.context.cursorConfig.readOnly)return;const S=c.from(this._model,this);this._cursors.stopTrackingSelections(),this._isHandling=!0;try{this._cursors.ensureValidState(),f()}catch(L){(0,d.onUnexpectedError)(L)}this._isHandling=!1,this._cursors.startTrackingSelections(),this._validateAutoClosedActions(),this._emitStateChangedIfNecessary(h,v,w,S,!1)&&this.revealAll(h,v,!1,0,!0,0)}getAutoClosedCharacters(){return l.getAllAutoClosedCharacters(this._autoClosedActions)}startComposition(f){this._compositionState=new u(this._model,this.getSelections())}endComposition(f,h){const v=this._compositionState?this._compositionState.deduceOutcome(this._model,this.getSelections()):null;this._compositionState=null,this._executeEdit(()=>{h==="keyboard"&&this._executeEditOperation(_.TypeOperations.compositionEndWithInterceptors(this._prevEditOperationType,this.context.cursorConfig,this._model,v,this.getSelections(),this.getAutoClosedCharacters()))},f,h)}type(f,h,v){this._executeEdit(()=>{if(v==="keyboard"){const w=h.length;let S=0;for(;S{const M=T.getPosition();return new n.Selection(M.lineNumber,M.column+S,M.lineNumber,M.column+S)});this.setSelections(f,L,D,0)}return}this._executeEdit(()=>{this._executeEditOperation(_.TypeOperations.compositionType(this._prevEditOperationType,this.context.cursorConfig,this._model,this.getSelections(),h,v,w,S))},f,L)}paste(f,h,v,w,S){this._executeEdit(()=>{this._executeEditOperation(_.TypeOperations.paste(this.context.cursorConfig,this._model,this.getSelections(),h,v,w||[]))},f,S,4)}cut(f,h){this._executeEdit(()=>{this._executeEditOperation(m.DeleteOperations.cut(this.context.cursorConfig,this._model,this.getSelections()))},f,h)}executeCommand(f,h,v){this._executeEdit(()=>{this._cursors.killSecondaryCursors(),this._executeEditOperation(new E.EditOperationResult(0,[h],{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!1}))},f,v)}executeCommands(f,h,v){this._executeEdit(()=>{this._executeEditOperation(new E.EditOperationResult(0,h,{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!1}))},f,v)}}e.CursorsController=g;class c{static from(f,h){return new c(f.getVersionId(),h.getCursorStates())}constructor(f,h){this.modelVersionId=f,this.cursorState=h}equals(f){if(!f||this.modelVersionId!==f.modelVersionId||this.cursorState.length!==f.cursorState.length)return!1;for(let h=0,v=this.cursorState.length;h=h.length||!h[v].strictContainsRange(f[v]))return!1;return!0}}class a{static executeCommands(f,h,v){const w={model:f,selectionsBefore:h,trackedRanges:[],trackedRangesDirection:[]},S=this._innerExecuteCommands(w,v);for(let L=0,D=w.trackedRanges.length;L0&&(L[0]._isTracked=!0);let D=f.model.pushEditOperations(f.selectionsBefore,L,M=>{const A=[];for(let O=0;OO.identifier.minor-F.identifier.minor,N=[];for(let O=0;O0?(A[O].sort(P),N[O]=h[O].computeCursorState(f.model,{getInverseEditOperations:()=>A[O],getTrackedSelection:F=>{const x=parseInt(F,10),W=f.model._getTrackedRange(f.trackedRanges[x]);return f.trackedRangesDirection[x]===0?new n.Selection(W.startLineNumber,W.startColumn,W.endLineNumber,W.endColumn):new n.Selection(W.endLineNumber,W.endColumn,W.startLineNumber,W.startColumn)}})):N[O]=f.selectionsBefore[O];return N});D||(D=f.selectionsBefore);const T=[];for(const M in S)S.hasOwnProperty(M)&&T.push(parseInt(M,10));T.sort((M,A)=>A-M);for(const M of T)D.splice(M,1);return D}static _arrayIsEmpty(f){for(let h=0,v=f.length;h{p.Range.isEmpty(P)&&N===""||w.push({identifier:{major:h,minor:S++},range:P,text:N,forceMoveMarkers:O,isAutoWhitespaceEdit:v.insertsAutoWhitespace})};let D=!1;const A={addEditOperation:L,addTrackedEditOperation:(P,N,O)=>{D=!0,L(P,N,O)},trackSelection:(P,N)=>{const O=n.Selection.liftSelection(P);let F;if(O.isEmpty())if(typeof N=="boolean")N?F=2:F=3;else{const V=f.model.getLineMaxColumn(O.startLineNumber);O.startColumn===V?F=2:F=3}else F=1;const x=f.trackedRanges.length,W=f.model._setTrackedRange(null,O,F);return f.trackedRanges[x]=W,f.trackedRangesDirection[x]=O.getDirection(),x.toString()}};try{v.getEditOperations(f.model,A)}catch(P){return(0,d.onUnexpectedError)(P),{operations:[],hadTrackedEditOperation:!1}}return{operations:w,hadTrackedEditOperation:D}}static _getLoserCursorMap(f){f=f.slice(0),f.sort((v,w)=>-p.Range.compareRangesUsingEnds(v.range,w.range));const h={};for(let v=1;vS.identifier.major?L=w.identifier.major:L=S.identifier.major,h[L.toString()]=!0;for(let D=0;D0&&v--}}return h}}e.CommandExecutor=a;class r{constructor(f,h,v){this.text=f,this.startSelection=h,this.endSelection=v}}class u{static _capture(f,h){const v=[];for(const w of h){if(w.startLineNumber!==w.endLineNumber)return null;v.push(new r(f.getLineContent(w.startLineNumber),w.startColumn-1,w.endColumn-1))}return v}constructor(f,h){this._original=u._capture(f,h)}deduceOutcome(f,h){if(!this._original)return null;const v=u._capture(f,h);if(!v||this._original.length!==v.length)return null;const w=[];for(let S=0,L=this._original.length;S{M.affects(this._languageId)&&this._onDidChangeLanguageConfiguration.fire({})})),this._register(k.Event.filter(b.TreeSitterTokenizationRegistry.onDidChange,M=>M.changedLanguages.includes(this._languageId))(()=>{this.createPreferredTokenProvider()})),this.createPreferredTokenProvider()}createGrammarTokens(){return this._register(new C(this._languageService.languageIdCodec,this._textModel,()=>this._languageId,this._attachedViews))}createTreeSitterTokens(){return this._register(new s.TreeSitterTokens(this._treeSitterService,this._languageService.languageIdCodec,this._textModel,()=>this._languageId))}createTokens(h){const v=this._tokens!==void 0;this._tokens?.dispose(),this._tokens=h?this.createTreeSitterTokens():this.createGrammarTokens(),this._tokensDisposables.clear(),this._tokensDisposables.add(this._tokens.onDidChangeTokens(w=>{this._emitModelTokensChangedEvent(w)})),this._tokensDisposables.add(this._tokens.onDidChangeBackgroundTokenizationState(w=>{this._bracketPairsTextModelPart.handleDidChangeBackgroundTokenizationState()})),v&&this._tokens.resetTokenization()}createPreferredTokenProvider(){b.TreeSitterTokenizationRegistry.get(this._languageId)?this._tokens instanceof s.TreeSitterTokens||this.createTokens(!0):this._tokens instanceof C||this.createTokens(!1)}handleLanguageConfigurationServiceChange(h){h.affects(this._languageId)&&this._onDidChangeLanguageConfiguration.fire({})}handleDidChangeContent(h){if(h.isFlush)this._semanticTokens.flush();else if(!h.isEolChange)for(const v of h.changes){const[w,S,L]=(0,E.countEOL)(v.text);this._semanticTokens.acceptEdit(v.range,w,S,L,v.text.length>0?v.text.charCodeAt(0):0)}this._tokens.handleDidChangeContent(h)}handleDidChangeAttached(){this._tokens.handleDidChangeAttached()}getLineTokens(h){this.validateLineNumber(h);const v=this._tokens.getLineTokens(h);return this._semanticTokens.addSparseTokens(h,v)}_emitModelTokensChangedEvent(h){this._textModel._isDisposing()||(this._bracketPairsTextModelPart.handleDidChangeTokens(h),this._onDidChangeTokens.fire(h))}validateLineNumber(h){if(h<1||h>this._textModel.getLineCount())throw new d.BugIndicatingError("Illegal value for lineNumber")}get hasTokens(){return this._tokens.hasTokens}resetTokenization(){this._tokens.resetTokenization()}get backgroundTokenizationState(){return this._tokens.backgroundTokenizationState}forceTokenization(h){this.validateLineNumber(h),this._tokens.forceTokenization(h)}hasAccurateTokensForLine(h){return this.validateLineNumber(h),this._tokens.hasAccurateTokensForLine(h)}isCheapToTokenize(h){return this.validateLineNumber(h),this._tokens.isCheapToTokenize(h)}tokenizeIfCheap(h){this.validateLineNumber(h),this._tokens.tokenizeIfCheap(h)}getTokenTypeIfInsertingCharacter(h,v,w){return this._tokens.getTokenTypeIfInsertingCharacter(h,v,w)}tokenizeLineWithEdit(h,v,w){return this._tokens.tokenizeLineWithEdit(h,v,w)}setSemanticTokens(h,v){this._semanticTokens.set(h,v),this._emitModelTokensChangedEvent({semanticTokensApplied:h!==null,ranges:[{fromLineNumber:1,toLineNumber:this._textModel.getLineCount()}]})}hasCompleteSemanticTokens(){return this._semanticTokens.isComplete()}hasSomeSemanticTokens(){return!this._semanticTokens.isEmpty()}setPartialSemanticTokens(h,v){if(this.hasCompleteSemanticTokens())return;const w=this._textModel.validateRange(this._semanticTokens.setPartial(h,v));this._emitModelTokensChangedEvent({semanticTokensApplied:!0,ranges:[{fromLineNumber:w.startLineNumber,toLineNumber:w.endLineNumber}]})}getWordAtPosition(h){this.assertNotDisposed();const v=this._textModel.validatePosition(h),w=this._textModel.getLineContent(v.lineNumber),S=this.getLineTokens(v.lineNumber),L=S.findTokenIndexAtOffset(v.column-1),[D,T]=r._findLanguageBoundaries(S,L),M=(0,_.getWordAtText)(v.column,this.getLanguageConfiguration(S.getLanguageId(L)).getWordDefinition(),w.substring(D,T),D);if(M&&M.startColumn<=h.column&&h.column<=M.endColumn)return M;if(L>0&&D===v.column-1){const[A,P]=r._findLanguageBoundaries(S,L-1),N=(0,_.getWordAtText)(v.column,this.getLanguageConfiguration(S.getLanguageId(L-1)).getWordDefinition(),w.substring(A,P),A);if(N&&N.startColumn<=h.column&&h.column<=N.endColumn)return N}return null}getLanguageConfiguration(h){return this._languageConfigurationService.getLanguageConfiguration(h)}static _findLanguageBoundaries(h,v){const w=h.getLanguageId(v);let S=0;for(let D=v;D>=0&&h.getLanguageId(D)===w;D--)S=h.getStartOffset(D);let L=h.getLineContent().length;for(let D=v,T=h.getCount();D{const D=this.getLanguageId();L.changedLanguages.indexOf(D)!==-1&&this.resetTokenization()})),this.resetTokenization(),this._register(S.onDidChangeVisibleRanges(({view:L,state:D})=>{if(D){let T=this._attachedViewStates.get(L);T||(T=new i.AttachedViewHandler(()=>this.refreshRanges(T.lineRanges)),this._attachedViewStates.set(L,T)),T.handleStateChange(D)}else this._attachedViewStates.deleteAndDispose(L)}))}resetTokenization(h=!0){this._tokens.flush(),this._debugBackgroundTokens?.flush(),this._debugBackgroundStates&&(this._debugBackgroundStates=new t.TrackingTokenizationStateStore(this._textModel.getLineCount())),h&&this._onDidChangeTokens.fire({semanticTokensApplied:!1,ranges:[{fromLineNumber:1,toLineNumber:this._textModel.getLineCount()}]});const v=()=>{if(this._textModel.isTooLargeForTokenization())return[null,null];const L=b.TokenizationRegistry.get(this.getLanguageId());if(!L)return[null,null];let D;try{D=L.getInitialState()}catch(T){return(0,d.onUnexpectedError)(T),[null,null]}return[L,D]},[w,S]=v();if(w&&S?this._tokenizer=new t.TokenizerWithStateStoreAndTextModel(this._textModel.getLineCount(),w,this._textModel,this._languageIdCodec):this._tokenizer=null,this._backgroundTokenizer.clear(),this._defaultBackgroundTokenizer=null,this._tokenizer){const L={setTokens:D=>{this.setTokens(D)},backgroundTokenizationFinished:()=>{if(this._backgroundTokenizationState===2)return;const D=2;this._backgroundTokenizationState=D,this._onDidChangeBackgroundTokenizationState.fire()},setEndState:(D,T)=>{if(!this._tokenizer)return;const M=this._tokenizer.store.getFirstInvalidEndStateLineNumber();M!==null&&D>=M&&this._tokenizer?.store.setEndState(D,T)}};w&&w.createBackgroundTokenizer&&!w.backgroundTokenizerShouldOnlyVerifyTokens&&(this._backgroundTokenizer.value=w.createBackgroundTokenizer(this._textModel,L)),!this._backgroundTokenizer.value&&!this._textModel.isTooLargeForTokenization()&&(this._backgroundTokenizer.value=this._defaultBackgroundTokenizer=new t.DefaultBackgroundTokenizer(this._tokenizer,L),this._defaultBackgroundTokenizer.handleChanges()),w?.backgroundTokenizerShouldOnlyVerifyTokens&&w.createBackgroundTokenizer?(this._debugBackgroundTokens=new l.ContiguousTokensStore(this._languageIdCodec),this._debugBackgroundStates=new t.TrackingTokenizationStateStore(this._textModel.getLineCount()),this._debugBackgroundTokenizer.clear(),this._debugBackgroundTokenizer.value=w.createBackgroundTokenizer(this._textModel,{setTokens:D=>{this._debugBackgroundTokens?.setMultilineTokens(D,this._textModel)},backgroundTokenizationFinished(){},setEndState:(D,T)=>{this._debugBackgroundStates?.setEndState(D,T)}})):(this._debugBackgroundTokens=void 0,this._debugBackgroundStates=void 0,this._debugBackgroundTokenizer.value=void 0)}this.refreshAllVisibleLineTokens()}handleDidChangeAttached(){this._defaultBackgroundTokenizer?.handleChanges()}handleDidChangeContent(h){if(h.isFlush)this.resetTokenization(!1);else if(!h.isEolChange){for(const v of h.changes){const[w,S]=(0,E.countEOL)(v.text);this._tokens.acceptEdit(v.range,w,S),this._debugBackgroundTokens?.acceptEdit(v.range,w,S)}this._debugBackgroundStates?.acceptChanges(h.changes),this._tokenizer&&this._tokenizer.store.acceptChanges(h.changes),this._defaultBackgroundTokenizer?.handleChanges()}}setTokens(h){const{changes:v}=this._tokens.setMultilineTokens(h,this._textModel);return v.length>0&&this._onDidChangeTokens.fire({semanticTokensApplied:!1,ranges:v}),{changes:v}}refreshAllVisibleLineTokens(){const h=y.LineRange.joinMany([...this._attachedViewStates].map(([v,w])=>w.lineRanges));this.refreshRanges(h)}refreshRanges(h){for(const v of h)this.refreshRange(v.startLineNumber,v.endLineNumberExclusive-1)}refreshRange(h,v){if(!this._tokenizer)return;h=Math.max(1,Math.min(this._textModel.getLineCount(),h)),v=Math.min(this._textModel.getLineCount(),v);const w=new c.ContiguousMultilineTokensBuilder,{heuristicTokens:S}=this._tokenizer.tokenizeHeuristically(w,h,v),L=this.setTokens(w.finalize());if(S)for(const D of L.changes)this._backgroundTokenizer.value?.requestTokens(D.fromLineNumber,D.toLineNumber+1);this._defaultBackgroundTokenizer?.checkFinished()}forceTokenization(h){const v=new c.ContiguousMultilineTokensBuilder;this._tokenizer?.updateTokensUntilLine(v,h),this.setTokens(v.finalize()),this._defaultBackgroundTokenizer?.checkFinished()}hasAccurateTokensForLine(h){return this._tokenizer?this._tokenizer.hasAccurateTokensForLine(h):!0}isCheapToTokenize(h){return this._tokenizer?this._tokenizer.isCheapToTokenize(h):!0}getLineTokens(h){const v=this._textModel.getLineContent(h),w=this._tokens.getTokens(this._textModel.getLanguageId(),h-1,v);if(this._debugBackgroundTokens&&this._debugBackgroundStates&&this._tokenizer&&this._debugBackgroundStates.getFirstInvalidEndStateLineNumberOrMax()>h&&this._tokenizer.store.getFirstInvalidEndStateLineNumberOrMax()>h){const S=this._debugBackgroundTokens.getTokens(this._textModel.getLanguageId(),h-1,v);!w.equals(S)&&this._debugBackgroundTokenizer.value?.reportMismatchingTokens&&this._debugBackgroundTokenizer.value.reportMismatchingTokens(h)}return w}getTokenTypeIfInsertingCharacter(h,v,w){if(!this._tokenizer)return 0;const S=this._textModel.validatePosition(new m.Position(h,v));return this.forceTokenization(S.lineNumber),this._tokenizer.getTokenTypeIfInsertingCharacter(S,w)}tokenizeLineWithEdit(h,v,w){if(!this._tokenizer)return null;const S=this._textModel.validatePosition(h);return this.forceTokenization(S.lineNumber),this._tokenizer.tokenizeLineWithEdit(S,v,w)}get hasTokens(){return this._tokens.hasTokens}}}),define(ne[708],se([1,0,42,48,22,70,382,30]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getIconClasses=b;const _=/(?:\/|^)(?:([^\/]+)\/)?([^\/]+)$/;function b(o,t,i,s,g){if(m.ThemeIcon.isThemeIcon(g))return[`codicon-${g.id}`,"predefined-file-icon"];if(I.URI.isUri(g))return[];const c=s===y.FileKind.ROOT_FOLDER?["rootfolder-icon"]:s===y.FileKind.FOLDER?["folder-icon"]:["file-icon"];if(i){let l;if(i.scheme===d.Schemas.data)l=k.DataUri.parseMetaData(i).get(k.DataUri.META_DATA_LABEL);else{const a=i.path.match(_);a?(l=n(a[2].toLowerCase()),a[1]&&c.push(`${n(a[1].toLowerCase())}-name-dir-icon`)):l=n(i.authority.toLowerCase())}if(s===y.FileKind.ROOT_FOLDER)c.push(`${l}-root-name-folder-icon`);else if(s===y.FileKind.FOLDER)c.push(`${l}-name-folder-icon`);else{if(l){if(c.push(`${l}-name-file-icon`),c.push("name-file-icon"),l.length<=255){const r=l.split(".");for(let u=1;u{h.mime===f.mime||h.userConfigured||(f.extension&&h.extension===f.extension&&console.warn(`Overwriting extension <<${f.extension}>> to now point to mime <<${f.mime}>>`),f.filename&&h.filename===f.filename&&console.warn(`Overwriting filename <<${f.filename}>> to now point to mime <<${f.mime}>>`),f.filepattern&&h.filepattern===f.filepattern&&console.warn(`Overwriting filepattern <<${f.filepattern}>> to now point to mime <<${f.mime}>>`),f.firstline&&h.firstline===f.firstline&&console.warn(`Overwriting firstline <<${f.firstline}>> to now point to mime <<${f.mime}>>`))})}function i(r,u){return{id:r.id,mime:r.mime,filename:r.filename,extension:r.extension,filepattern:r.filepattern,firstline:r.firstline,userConfigured:u,filenameLowercase:r.filename?r.filename.toLowerCase():void 0,extensionLowercase:r.extension?r.extension.toLowerCase():void 0,filepatternLowercase:r.filepattern?(0,d.parse)(r.filepattern.toLowerCase()):void 0,filepatternOnPath:r.filepattern?r.filepattern.indexOf(E.posix.sep)>=0:!1}}function s(){b=b.filter(r=>r.userConfigured),p=[]}function g(r,u){return c(r,u).map(C=>C.id)}function c(r,u){let C;if(r)switch(r.scheme){case I.Schemas.file:C=r.fsPath;break;case I.Schemas.data:{C=y.DataUri.parseMetaData(r).get(y.DataUri.META_DATA_LABEL);break}case I.Schemas.vscodeNotebookCell:C=void 0;break;default:C=r.path}if(!C)return[{id:"unknown",mime:k.Mimes.unknown}];C=C.toLowerCase();const f=(0,E.basename)(C),h=l(C,f,n);if(h)return[h,{id:_.PLAINTEXT_LANGUAGE_ID,mime:k.Mimes.text}];const v=l(C,f,p);if(v)return[v,{id:_.PLAINTEXT_LANGUAGE_ID,mime:k.Mimes.text}];if(u){const w=a(u);if(w)return[w,{id:_.PLAINTEXT_LANGUAGE_ID,mime:k.Mimes.text}]}return[{id:"unknown",mime:k.Mimes.unknown}]}function l(r,u,C){let f,h,v;for(let w=C.length-1;w>=0;w--){const S=C[w];if(u===S.filenameLowercase){f=S;break}if(S.filepattern&&(!h||S.filepattern.length>h.filepattern.length)){const L=S.filepatternOnPath?r:u;S.filepatternLowercase?.(L)&&(h=S)}S.extension&&(!v||S.extension.length>v.extension.length)&&u.endsWith(S.extensionLowercase)&&(v=S)}if(f)return f;if(h)return h;if(v)return v}function a(r){if((0,m.startsWithUTF8BOM)(r)&&(r=r.substr(1)),r.length>0)for(let u=b.length-1;u>=0;u--){const C=b[u];if(!C.firstline)continue;const f=r.match(C.firstline);if(f&&f.length>0)return C}}}),define(ne[710],se([1,0,6,2,11,709,70,109,38]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LanguagesRegistry=e.LanguageIdCodec=void 0;const b=Object.prototype.hasOwnProperty,p="vs.editor.nullLanguage";class n{constructor(){this._languageIdToLanguage=[],this._languageToLanguageId=new Map,this._register(p,0),this._register(y.PLAINTEXT_LANGUAGE_ID,1),this._nextLanguageId=2}_register(i,s){this._languageIdToLanguage[s]=i,this._languageToLanguageId.set(i,s)}register(i){if(this._languageToLanguageId.has(i))return;const s=this._nextLanguageId++;this._register(i,s)}encodeLanguageId(i){return this._languageToLanguageId.get(i)||0}decodeLanguageId(i){return this._languageIdToLanguage[i]||p}}e.LanguageIdCodec=n;class o extends k.Disposable{static{this.instanceCount=0}constructor(i=!0,s=!1){super(),this._onDidChange=this._register(new d.Emitter),this.onDidChange=this._onDidChange.event,o.instanceCount++,this._warnOnOverwrite=s,this.languageIdCodec=new n,this._dynamicLanguages=[],this._languages={},this._mimeTypesMap={},this._nameMap={},this._lowercaseNameMap={},i&&(this._initializeFromRegistry(),this._register(y.ModesRegistry.onDidChangeLanguages(g=>{this._initializeFromRegistry()})))}dispose(){o.instanceCount--,super.dispose()}_initializeFromRegistry(){this._languages={},this._mimeTypesMap={},this._nameMap={},this._lowercaseNameMap={},(0,E.clearPlatformLanguageAssociations)();const i=[].concat(y.ModesRegistry.getLanguages()).concat(this._dynamicLanguages);this._registerLanguages(i)}_registerLanguages(i){for(const s of i)this._registerLanguage(s);this._mimeTypesMap={},this._nameMap={},this._lowercaseNameMap={},Object.keys(this._languages).forEach(s=>{const g=this._languages[s];g.name&&(this._nameMap[g.name]=g.identifier),g.aliases.forEach(c=>{this._lowercaseNameMap[c.toLowerCase()]=g.identifier}),g.mimetypes.forEach(c=>{this._mimeTypesMap[c]=g.identifier})}),_.Registry.as(m.Extensions.Configuration).registerOverrideIdentifiers(this.getRegisteredLanguageIds()),this._onDidChange.fire()}_registerLanguage(i){const s=i.id;let g;b.call(this._languages,s)?g=this._languages[s]:(this.languageIdCodec.register(s),g={identifier:s,name:null,mimetypes:[],aliases:[],extensions:[],filenames:[],configurationFiles:[],icons:[]},this._languages[s]=g),this._mergeLanguage(g,i)}_mergeLanguage(i,s){const g=s.id;let c=null;if(Array.isArray(s.mimetypes)&&s.mimetypes.length>0&&(i.mimetypes.push(...s.mimetypes),c=s.mimetypes[0]),c||(c=`text/x-${g}`,i.mimetypes.push(c)),Array.isArray(s.extensions)){s.configuration?i.extensions=s.extensions.concat(i.extensions):i.extensions=i.extensions.concat(s.extensions);for(const r of s.extensions)(0,E.registerPlatformLanguageAssociation)({id:g,mime:c,extension:r},this._warnOnOverwrite)}if(Array.isArray(s.filenames))for(const r of s.filenames)(0,E.registerPlatformLanguageAssociation)({id:g,mime:c,filename:r},this._warnOnOverwrite),i.filenames.push(r);if(Array.isArray(s.filenamePatterns))for(const r of s.filenamePatterns)(0,E.registerPlatformLanguageAssociation)({id:g,mime:c,filepattern:r},this._warnOnOverwrite);if(typeof s.firstLine=="string"&&s.firstLine.length>0){let r=s.firstLine;r.charAt(0)!=="^"&&(r="^"+r);try{const u=new RegExp(r);(0,I.regExpLeadsToEndlessLoop)(u)||(0,E.registerPlatformLanguageAssociation)({id:g,mime:c,firstline:u},this._warnOnOverwrite)}catch(u){console.warn(`[${s.id}]: Invalid regular expression \`${r}\`: `,u)}}i.aliases.push(g);let l=null;if(typeof s.aliases<"u"&&Array.isArray(s.aliases)&&(s.aliases.length===0?l=[null]:l=s.aliases),l!==null)for(const r of l)!r||r.length===0||i.aliases.push(r);const a=l!==null&&l.length>0;if(!(a&&l[0]===null)){const r=(a?l[0]:null)||g;(a||!i.name)&&(i.name=r)}s.configuration&&i.configurationFiles.push(s.configuration),s.icon&&i.icons.push(s.icon)}isRegisteredLanguageId(i){return i?b.call(this._languages,i):!1}getRegisteredLanguageIds(){return Object.keys(this._languages)}getLanguageIdByLanguageName(i){const s=i.toLowerCase();return b.call(this._lowercaseNameMap,s)?this._lowercaseNameMap[s]:null}getLanguageIdByMimeType(i){return i&&b.call(this._mimeTypesMap,i)?this._mimeTypesMap[i]:null}guessLanguageIdByFilepathOrFirstLine(i,s){return!i&&!s?[]:(0,E.getLanguageIds)(i,s)}}e.LanguagesRegistry=o}),define(ne[711],se([1,0,6,2,710,13,27,70,21]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LanguageService=void 0;class b extends k.Disposable{static{this.instanceCount=0}constructor(o=!1){super(),this._onDidRequestBasicLanguageFeatures=this._register(new d.Emitter),this.onDidRequestBasicLanguageFeatures=this._onDidRequestBasicLanguageFeatures.event,this._onDidRequestRichLanguageFeatures=this._register(new d.Emitter),this.onDidRequestRichLanguageFeatures=this._onDidRequestRichLanguageFeatures.event,this._onDidChange=this._register(new d.Emitter({leakWarningThreshold:200})),this.onDidChange=this._onDidChange.event,this._requestedBasicLanguages=new Set,this._requestedRichLanguages=new Set,b.instanceCount++,this._registry=this._register(new I.LanguagesRegistry(!0,o)),this.languageIdCodec=this._registry.languageIdCodec,this._register(this._registry.onDidChange(()=>this._onDidChange.fire()))}dispose(){b.instanceCount--,super.dispose()}isRegisteredLanguageId(o){return this._registry.isRegisteredLanguageId(o)}getLanguageIdByLanguageName(o){return this._registry.getLanguageIdByLanguageName(o)}getLanguageIdByMimeType(o){return this._registry.getLanguageIdByMimeType(o)}guessLanguageIdByFilepathOrFirstLine(o,t){const i=this._registry.guessLanguageIdByFilepathOrFirstLine(o,t);return(0,E.firstOrDefault)(i,null)}createById(o){return new p(this.onDidChange,()=>this._createAndGetLanguageIdentifier(o))}createByFilepathOrFirstLine(o,t){return new p(this.onDidChange,()=>{const i=this.guessLanguageIdByFilepathOrFirstLine(o,t);return this._createAndGetLanguageIdentifier(i)})}_createAndGetLanguageIdentifier(o){return(!o||!this.isRegisteredLanguageId(o))&&(o=m.PLAINTEXT_LANGUAGE_ID),o}requestBasicLanguageFeatures(o){this._requestedBasicLanguages.has(o)||(this._requestedBasicLanguages.add(o),this._onDidRequestBasicLanguageFeatures.fire(o))}requestRichLanguageFeatures(o){this._requestedRichLanguages.has(o)||(this._requestedRichLanguages.add(o),this.requestBasicLanguageFeatures(o),y.TokenizationRegistry.getOrCreate(o),this._onDidRequestRichLanguageFeatures.fire(o))}}e.LanguageService=b;class p{constructor(o,t){this._value=(0,_.observableFromEvent)(this,o,()=>t()),this.onDidChange=d.Event.fromObservable(this._value)}get languageId(){return this._value.get()}}}),define(ne[712],se([1,0,5,2,120,43,376,59,174,669,210]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";var n;Object.defineProperty(e,"__esModule",{value:!0}),e.MarginHoverWidget=void 0;const o=d.$;let t=class extends k.Disposable{static{n=this}static{this.ID="editor.contrib.modesGlyphHoverWidget"}constructor(s,g,c){super(),this._renderDisposeables=this._register(new k.DisposableStore),this._editor=s,this._isVisible=!1,this._messages=[],this._hover=this._register(new _.HoverWidget),this._hover.containerDomNode.classList.toggle("hidden",!this._isVisible),this._markdownRenderer=this._register(new I.MarkdownRenderer({editor:this._editor},g,c)),this._computer=new b.MarginHoverComputer(this._editor),this._hoverOperation=this._register(new y.HoverOperation(this._editor,this._computer)),this._register(this._hoverOperation.onResult(l=>{this._withResult(l.value)})),this._register(this._editor.onDidChangeModelDecorations(()=>this._onModelDecorationsChanged())),this._register(this._editor.onDidChangeConfiguration(l=>{l.hasChanged(50)&&this._updateFont()})),this._register(d.addStandardDisposableListener(this._hover.containerDomNode,"mouseleave",l=>{this._onMouseLeave(l)})),this._editor.addOverlayWidget(this)}dispose(){this._editor.removeOverlayWidget(this),super.dispose()}getId(){return n.ID}getDomNode(){return this._hover.containerDomNode}getPosition(){return null}_updateFont(){Array.prototype.slice.call(this._hover.contentsDomNode.getElementsByClassName("code")).forEach(g=>this._editor.applyFontInfo(g))}_onModelDecorationsChanged(){this._isVisible&&(this._hoverOperation.cancel(),this._hoverOperation.start(0))}showsOrWillShow(s){const g=s.target;return g.type===2&&g.detail.glyphMarginLane?(this._startShowingAt(g.position.lineNumber,g.detail.glyphMarginLane),!0):g.type===3?(this._startShowingAt(g.position.lineNumber,"lineNo"),!0):!1}_startShowingAt(s,g){this._computer.lineNumber===s&&this._computer.lane===g||(this._hoverOperation.cancel(),this.hide(),this._computer.lineNumber=s,this._computer.lane=g,this._hoverOperation.start(0))}hide(){this._computer.lineNumber=-1,this._hoverOperation.cancel(),this._isVisible&&(this._isVisible=!1,this._hover.containerDomNode.classList.toggle("hidden",!this._isVisible))}_withResult(s){this._messages=s,this._messages.length>0?this._renderMessages(this._computer.lineNumber,this._messages):this.hide()}_renderMessages(s,g){this._renderDisposeables.clear();const c=document.createDocumentFragment();for(const l of g){const a=o("div.hover-row.markdown-hover"),r=d.append(a,o("div.hover-contents")),u=this._renderDisposeables.add(this._markdownRenderer.render(l.value));r.appendChild(u.element),c.appendChild(a)}this._updateContents(c),this._showAt(s)}_updateContents(s){this._hover.contentsDomNode.textContent="",this._hover.contentsDomNode.appendChild(s),this._updateFont()}_showAt(s){this._isVisible||(this._isVisible=!0,this._hover.containerDomNode.classList.toggle("hidden",!this._isVisible));const g=this._editor.getLayoutInfo(),c=this._editor.getTopForLineNumber(s),l=this._editor.getScrollTop(),a=this._editor.getOption(67),r=this._hover.containerDomNode.clientHeight,u=c-l-(r-a)/2,C=g.glyphMarginLeft+g.glyphMarginWidth+(this._computer.lane==="lineNo"?g.lineNumbersWidth:0);this._hover.containerDomNode.style.left=`${C}px`,this._hover.containerDomNode.style.top=`${Math.max(Math.round(u),0)}px`}_onMouseLeave(s){const g=this._editor.getDomNode();(!g||!(0,p.isMousePositionWithinElement)(g,s.x,s.y))&&this.hide()}};e.MarginHoverWidget=t,e.MarginHoverWidget=t=n=ke([ce(1,E.ILanguageService),ce(2,m.IOpenerService)],t)}),define(ne[713],se([1,0,2,7,14,210,712,196]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MarginHoverController=void 0;const m=!1;let _=class extends d.Disposable{static{this.ID="editor.contrib.marginHover"}constructor(p,n){super(),this._editor=p,this._instantiationService=n,this.shouldKeepOpenOnEditorMouseMoveOrLeave=!1,this._listenersStore=new d.DisposableStore,this._hoverState={mouseDown:!1},this._reactToEditorMouseMoveRunner=this._register(new I.RunOnceScheduler(()=>this._reactToEditorMouseMove(this._mouseMoveEvent),0)),this._hookListeners(),this._register(this._editor.onDidChangeConfiguration(o=>{o.hasChanged(60)&&(this._unhookListeners(),this._hookListeners())}))}_hookListeners(){const p=this._editor.getOption(60);this._hoverSettings={enabled:p.enabled,sticky:p.sticky,hidingDelay:p.hidingDelay},p.enabled?(this._listenersStore.add(this._editor.onMouseDown(n=>this._onEditorMouseDown(n))),this._listenersStore.add(this._editor.onMouseUp(()=>this._onEditorMouseUp())),this._listenersStore.add(this._editor.onMouseMove(n=>this._onEditorMouseMove(n))),this._listenersStore.add(this._editor.onKeyDown(n=>this._onKeyDown(n)))):(this._listenersStore.add(this._editor.onMouseMove(n=>this._onEditorMouseMove(n))),this._listenersStore.add(this._editor.onKeyDown(n=>this._onKeyDown(n)))),this._listenersStore.add(this._editor.onMouseLeave(n=>this._onEditorMouseLeave(n))),this._listenersStore.add(this._editor.onDidChangeModel(()=>{this._cancelScheduler(),this._hideWidgets()})),this._listenersStore.add(this._editor.onDidChangeModelContent(()=>this._cancelScheduler())),this._listenersStore.add(this._editor.onDidScrollChange(n=>this._onEditorScrollChanged(n)))}_unhookListeners(){this._listenersStore.clear()}_cancelScheduler(){this._mouseMoveEvent=void 0,this._reactToEditorMouseMoveRunner.cancel()}_onEditorScrollChanged(p){(p.scrollTopChanged||p.scrollLeftChanged)&&this._hideWidgets()}_onEditorMouseDown(p){this._hoverState.mouseDown=!0,!this._isMouseOnMarginHoverWidget(p)&&this._hideWidgets()}_isMouseOnMarginHoverWidget(p){const n=this._glyphWidget?.getDomNode();return n?(0,E.isMousePositionWithinElement)(n,p.event.posx,p.event.posy):!1}_onEditorMouseUp(){this._hoverState.mouseDown=!1}_onEditorMouseLeave(p){this.shouldKeepOpenOnEditorMouseMoveOrLeave||(this._cancelScheduler(),this._isMouseOnMarginHoverWidget(p))||m||this._hideWidgets()}_shouldNotRecomputeCurrentHoverWidget(p){const n=this._hoverSettings.sticky,o=this._isMouseOnMarginHoverWidget(p);return n&&o}_onEditorMouseMove(p){if(this.shouldKeepOpenOnEditorMouseMoveOrLeave)return;if(this._mouseMoveEvent=p,this._shouldNotRecomputeCurrentHoverWidget(p)){this._reactToEditorMouseMoveRunner.cancel();return}this._reactToEditorMouseMove(p)}_reactToEditorMouseMove(p){!p||this._tryShowHoverWidget(p)||m||this._hideWidgets()}_tryShowHoverWidget(p){return this._getOrCreateGlyphWidget().showsOrWillShow(p)}_onKeyDown(p){this._editor.hasModel()&&(p.keyCode===5||p.keyCode===6||p.keyCode===57||p.keyCode===4||this._hideWidgets())}_hideWidgets(){m||this._glyphWidget?.hide()}_getOrCreateGlyphWidget(){return this._glyphWidget||(this._glyphWidget=this._instantiationService.createInstance(y.MarginHoverWidget,this._editor)),this._glyphWidget}dispose(){super.dispose(),this._unhookListeners(),this._listenersStore.dispose(),this._glyphWidget?.dispose()}};e.MarginHoverController=_,e.MarginHoverController=_=ke([ce(1,k.IInstantiationService)],_)}),define(ne[714],se([1,0,11,183,75,230,23,240]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getReindentEditOperations=_;function _(p,n,o,t){if(p.getLineCount()===1&&p.getLineMaxColumn(1)===1)return[];const i=n.getLanguageConfiguration(p.getLanguageId()).indentRulesSupport;if(!i)return[];const s=new m.ProcessedIndentRulesSupport(p,i,n);for(t=Math.min(t,p.getLineCount());o<=t&&s.shouldIgnore(o);)o++;if(o>t-1)return[];const{tabSize:g,indentSize:c,insertSpaces:l}=p.getOptions(),a=(v,w)=>(w=w||1,k.ShiftCommand.shiftIndent(v,v.length+w,g,c,l)),r=(v,w)=>(w=w||1,k.ShiftCommand.unshiftIndent(v,v.length+w,g,c,l)),u=[],C=p.getLineContent(o);let f=d.getLeadingWhitespace(C),h=f;s.shouldIncrease(o)?(h=a(h),f=a(f)):s.shouldIndentNextLine(o)&&(h=a(h)),o++;for(let v=o;v<=t;v++){if(b(p,v))continue;const w=p.getLineContent(v),S=d.getLeadingWhitespace(w),L=h;s.shouldDecrease(v,L)&&(h=r(h),f=r(f)),S!==h&&u.push(I.EditOperation.replaceMove(new y.Selection(v,1,v,S.length+1),(0,E.normalizeIndentation)(h,c,l))),!s.shouldIgnore(v)&&(s.shouldIncrease(v,L)?(f=a(f),h=f):s.shouldIndentNextLine(v,L)?h=a(h):h=f)}return u}function b(p,n){return p.tokenization.isCheapToTokenize(n)?p.tokenization.getLineTokens(n).getStandardTokenType(0)===2:!1}}),define(ne[715],se([1,0,18,102,82,2,21,4,104,113,27,36,17,378,246]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlineCompletionWithUpdatedRange=e.UpToDateInlineCompletions=e.InlineCompletionsSource=void 0;let s=class extends E.Disposable{constructor(f,h,v,w,S){super(),this.textModel=f,this.versionId=h,this._debounceValue=v,this.languageFeaturesService=w,this.languageConfigurationService=S,this._updateOperation=this._register(new E.MutableDisposable),this.inlineCompletions=(0,y.disposableObservableValue)("inlineCompletions",void 0),this.suggestWidgetInlineCompletions=(0,y.disposableObservableValue)("suggestWidgetInlineCompletions",void 0),this._register(this.textModel.onDidChangeContent(()=>{this._updateOperation.clear()}))}fetch(f,h,v){const w=new c(f,h,this.textModel.getVersionId()),S=h.selectedSuggestionInfo?this.suggestWidgetInlineCompletions:this.inlineCompletions;if(this._updateOperation.value?.request.satisfies(w))return this._updateOperation.value.promise;if(S.get()?.request.satisfies(w))return Promise.resolve(!0);const L=!!this._updateOperation.value;this._updateOperation.clear();const D=new d.CancellationTokenSource,T=(async()=>{if((L||h.triggerKind===p.InlineCompletionTriggerKind.Automatic)&&await g(this._debounceValue.get(this.textModel),D.token),D.token.isCancellationRequested||this._store.isDisposed||this.textModel.getVersionId()!==w.versionId)return!1;const P=new Date,N=await(0,t.provideInlineCompletions)(this.languageFeaturesService.inlineCompletionsProvider,f,this.textModel,h,D.token,this.languageConfigurationService);if(D.token.isCancellationRequested||this._store.isDisposed||this.textModel.getVersionId()!==w.versionId)return!1;const O=new Date;this._debounceValue.update(this.textModel,O.getTime()-P.getTime());const F=new a(N,w,this.textModel,this.versionId);if(v){const x=v.toInlineCompletion(void 0);v.canBeReused(this.textModel,f)&&!N.has(x)&&F.prepend(v.inlineCompletion,x.range,!0)}return this._updateOperation.clear(),(0,y.transaction)(x=>{S.set(F,x)}),!0})(),M=new l(w,D,T);return this._updateOperation.value=M,T}clear(f){this._updateOperation.clear(),this.inlineCompletions.set(void 0,f),this.suggestWidgetInlineCompletions.set(void 0,f)}clearSuggestWidgetInlineCompletions(f){this._updateOperation.value?.request.context.selectedSuggestionInfo&&this._updateOperation.clear(),this.suggestWidgetInlineCompletions.set(void 0,f)}cancelUpdate(){this._updateOperation.clear()}};e.InlineCompletionsSource=s,e.InlineCompletionsSource=s=ke([ce(3,o.ILanguageFeaturesService),ce(4,n.ILanguageConfigurationService)],s);function g(C,f){return new Promise(h=>{let v;const w=setTimeout(()=>{v&&v.dispose(),h()},C);f&&(v=f.onCancellationRequested(()=>{clearTimeout(w),v&&v.dispose(),h()}))})}class c{constructor(f,h,v){this.position=f,this.context=h,this.versionId=v}satisfies(f){return this.position.equals(f.position)&&(0,k.equalsIfDefined)(this.context.selectedSuggestionInfo,f.context.selectedSuggestionInfo,(0,k.itemEquals)())&&(f.context.triggerKind===p.InlineCompletionTriggerKind.Automatic||this.context.triggerKind===p.InlineCompletionTriggerKind.Explicit)&&this.versionId===f.versionId}}class l{constructor(f,h,v){this.request=f,this.cancellationTokenSource=h,this.promise=v}dispose(){this.cancellationTokenSource.cancel()}}class a{get inlineCompletions(){return this._inlineCompletions}constructor(f,h,v,w){this.inlineCompletionProviderResult=f,this.request=h,this._textModel=v,this._versionId=w,this._refCount=1,this._prependedInlineCompletionItems=[];const S=v.deltaDecorations([],f.completions.map(L=>({range:L.range,options:{description:"inline-completion-tracking-range"}})));this._inlineCompletions=f.completions.map((L,D)=>new r(L,S[D],this._textModel,this._versionId))}clone(){return this._refCount++,this}dispose(){if(this._refCount--,this._refCount===0){setTimeout(()=>{this._textModel.isDisposed()||this._textModel.deltaDecorations(this._inlineCompletions.map(f=>f.decorationId),[])},0),this.inlineCompletionProviderResult.dispose();for(const f of this._prependedInlineCompletionItems)f.source.removeRef()}}prepend(f,h,v){v&&f.source.addRef();const w=this._textModel.deltaDecorations([],[{range:h,options:{description:"inline-completion-tracking-range"}}])[0];this._inlineCompletions.unshift(new r(f,w,this._textModel,this._versionId)),this._prependedInlineCompletionItems.push(f)}}e.UpToDateInlineCompletions=a;class r{get forwardStable(){return this.inlineCompletion.source.inlineCompletions.enableForwardStability??!1}constructor(f,h,v,w){this.inlineCompletion=f,this.decorationId=h,this._textModel=v,this._modelVersion=w,this.semanticId=JSON.stringify([this.inlineCompletion.filterText,this.inlineCompletion.insertText,this.inlineCompletion.range.getStartPosition().toString()]),this._updatedRange=(0,y.derivedOpts)({owner:this,equalsFn:m.Range.equalsRange},S=>(this._modelVersion.read(S),this._textModel.getDecorationRange(this.decorationId)))}toInlineCompletion(f){return this.inlineCompletion.withRange(this._updatedRange.read(f)??u)}toSingleTextEdit(f){return new _.SingleTextEdit(this._updatedRange.read(f)??u,this.inlineCompletion.insertText)}isVisible(f,h,v){const w=(0,i.singleTextRemoveCommonPrefix)(this._toFilterTextReplacement(v),f),S=this._updatedRange.read(v);if(!S||!this.inlineCompletion.range.getStartPosition().equals(S.getStartPosition())||h.lineNumber!==w.range.startLineNumber)return!1;const L=f.getValueInRange(w.range,1),D=w.text,T=Math.max(0,h.column-w.range.startColumn);let M=D.substring(0,T),A=D.substring(T),P=L.substring(0,T),N=L.substring(T);const O=f.getLineIndentColumn(w.range.startLineNumber);return w.range.startColumn<=O&&(P=P.trimStart(),P.length===0&&(N=N.trimStart()),M=M.trimStart(),M.length===0&&(A=A.trimStart())),M.startsWith(P)&&!!(0,I.matchesSubString)(N,A)}canBeReused(f,h){const v=this._updatedRange.read(void 0);return!!v&&v.containsPosition(h)&&this.isVisible(f,h,void 0)&&b.TextLength.ofRange(v).isGreaterThanOrEqualTo(b.TextLength.ofRange(this.inlineCompletion.range))}_toFilterTextReplacement(f){return new _.SingleTextEdit(this._updatedRange.read(f)??u,this.inlineCompletion.filterText)}}e.InlineCompletionWithUpdatedRange=r;const u=new m.Range(1,1,1,1)}),define(ne[716],se([1,0,11,183,4,23,131,36,338,241,275]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MoveLinesCommand=void 0;let n=class{constructor(t,i,s,g){this._languageConfigurationService=g,this._selection=t,this._isMovingDown=i,this._autoIndent=s,this._selectionId=null,this._moveEndLineSelectionShrink=!1}getEditOperations(t,i){const s=()=>t.getLanguageId(),g=(f,h)=>t.getLanguageIdAtPosition(f,h),c=t.getLineCount();if(this._isMovingDown&&this._selection.endLineNumber===c){this._selectionId=i.trackSelection(this._selection);return}if(!this._isMovingDown&&this._selection.startLineNumber===1){this._selectionId=i.trackSelection(this._selection);return}this._moveEndPositionDown=!1;let l=this._selection;l.startLineNumberT===l.startLineNumber?t.tokenization.getLineTokens(f):t.tokenization.getLineTokens(T),getLanguageId:s,getLanguageIdAtPosition:g},getLineContent:T=>T===l.startLineNumber?t.getLineContent(f):t.getLineContent(T)},D=(0,b.getGoodIndentForLine)(this._autoIndent,L,t.getLanguageIdAtPosition(f,1),l.startLineNumber,C,this._languageConfigurationService);if(D!==null){const T=d.getLeadingWhitespace(t.getLineContent(f)),M=_.getSpaceCnt(D,a),A=_.getSpaceCnt(T,a);M!==A&&(v=_.generateIndent(M,a,u)+this.trimStart(h))}}i.addEditOperation(new I.Range(l.startLineNumber,1,l.startLineNumber,1),v+` `);const S=this.matchEnterRuleMovingDown(t,C,a,l.startLineNumber,f,v);if(S!==null)S!==0&&this.getIndentEditsOfMovingBlock(t,i,l,a,u,S);else{const L={tokenization:{getLineTokens:T=>T===l.startLineNumber?t.tokenization.getLineTokens(f):T>=l.startLineNumber+1&&T<=l.endLineNumber+1?t.tokenization.getLineTokens(T-1):t.tokenization.getLineTokens(T),getLanguageId:s,getLanguageIdAtPosition:g},getLineContent:T=>T===l.startLineNumber?v:T>=l.startLineNumber+1&&T<=l.endLineNumber+1?t.getLineContent(T-1):t.getLineContent(T)},D=(0,b.getGoodIndentForLine)(this._autoIndent,L,t.getLanguageIdAtPosition(f,1),l.startLineNumber+1,C,this._languageConfigurationService);if(D!==null){const T=d.getLeadingWhitespace(t.getLineContent(l.startLineNumber)),M=_.getSpaceCnt(D,a),A=_.getSpaceCnt(T,a);if(M!==A){const P=M-A;this.getIndentEditsOfMovingBlock(t,i,l,a,u,P)}}}}else i.addEditOperation(new I.Range(l.startLineNumber,1,l.startLineNumber,1),v+` `)}else if(f=l.startLineNumber-1,h=t.getLineContent(f),i.addEditOperation(new I.Range(f,1,f+1,1),null),i.addEditOperation(new I.Range(l.endLineNumber,t.getLineMaxColumn(l.endLineNumber),l.endLineNumber,t.getLineMaxColumn(l.endLineNumber)),` `+h),this.shouldAutoIndent(t,l)){const v={tokenization:{getLineTokens:S=>S===f?t.tokenization.getLineTokens(l.startLineNumber):t.tokenization.getLineTokens(S),getLanguageId:s,getLanguageIdAtPosition:g},getLineContent:S=>S===f?t.getLineContent(l.startLineNumber):t.getLineContent(S)},w=this.matchEnterRule(t,C,a,l.startLineNumber,l.startLineNumber-2);if(w!==null)w!==0&&this.getIndentEditsOfMovingBlock(t,i,l,a,u,w);else{const S=(0,b.getGoodIndentForLine)(this._autoIndent,v,t.getLanguageIdAtPosition(l.startLineNumber,1),f,C,this._languageConfigurationService);if(S!==null){const L=d.getLeadingWhitespace(t.getLineContent(l.startLineNumber)),D=_.getSpaceCnt(S,a),T=_.getSpaceCnt(L,a);if(D!==T){const M=D-T;this.getIndentEditsOfMovingBlock(t,i,l,a,u,M)}}}}}this._selectionId=i.trackSelection(l)}buildIndentConverter(t,i,s){return{shiftIndent:g=>k.ShiftCommand.shiftIndent(g,g.length+1,t,i,s),unshiftIndent:g=>k.ShiftCommand.unshiftIndent(g,g.length+1,t,i,s)}}parseEnterResult(t,i,s,g,c){if(c){let l=c.indentation;c.indentAction===y.IndentAction.None||c.indentAction===y.IndentAction.Indent?l=c.indentation+c.appendText:c.indentAction===y.IndentAction.IndentOutdent?l=c.indentation:c.indentAction===y.IndentAction.Outdent&&(l=i.unshiftIndent(c.indentation)+c.appendText);const a=t.getLineContent(g);if(this.trimStart(a).indexOf(this.trimStart(l))>=0){const r=d.getLeadingWhitespace(t.getLineContent(g));let u=d.getLeadingWhitespace(l);const C=(0,b.getIndentMetadata)(t,g,this._languageConfigurationService);C!==null&&C&2&&(u=i.unshiftIndent(u));const f=_.getSpaceCnt(u,s),h=_.getSpaceCnt(r,s);return f-h}}return null}matchEnterRuleMovingDown(t,i,s,g,c,l){if(d.lastNonWhitespaceIndex(l)>=0){const a=t.getLineMaxColumn(c),r=(0,p.getEnterAction)(this._autoIndent,t,new I.Range(c,a,c,a),this._languageConfigurationService);return this.parseEnterResult(t,i,s,g,r)}else{let a=g-1;for(;a>=1;){const C=t.getLineContent(a);if(d.lastNonWhitespaceIndex(C)>=0)break;a--}if(a<1||g>t.getLineCount())return null;const r=t.getLineMaxColumn(a),u=(0,p.getEnterAction)(this._autoIndent,t,new I.Range(a,r,a,r),this._languageConfigurationService);return this.parseEnterResult(t,i,s,g,u)}}matchEnterRule(t,i,s,g,c,l){let a=c;for(;a>=1;){let C;if(a===c&&l!==void 0?C=l:C=t.getLineContent(a),d.lastNonWhitespaceIndex(C)>=0)break;a--}if(a<1||g>t.getLineCount())return null;const r=t.getLineMaxColumn(a),u=(0,p.getEnterAction)(this._autoIndent,t,new I.Range(a,r,a,r),this._languageConfigurationService);return this.parseEnterResult(t,i,s,g,u)}trimStart(t){return t.replace(/^\s+/,"")}shouldAutoIndent(t,i){if(this._autoIndent<4||!t.tokenization.isCheapToTokenize(i.startLineNumber))return!1;const s=t.getLanguageIdAtPosition(i.startLineNumber,1),g=t.getLanguageIdAtPosition(i.endLineNumber,1);return!(s!==g||this._languageConfigurationService.getLanguageConfiguration(s).indentRulesSupport===null)}getIndentEditsOfMovingBlock(t,i,s,g,c,l){for(let a=s.startLineNumber;a<=s.endLineNumber;a++){const r=t.getLineContent(a),u=d.getLeadingWhitespace(r),f=_.getSpaceCnt(u,g)+l,h=_.generateIndent(f,g,c);h!==u&&(i.addEditOperation(new I.Range(a,1,a,u.length+1),h),a===s.endLineNumber&&s.endColumn<=u.length+1&&h===""&&(this._moveEndLineSelectionShrink=!0))}}computeCursorState(t,i){let s=i.getTrackedSelection(this._selectionId);return this._moveEndPositionDown&&(s=s.setEndPosition(s.endLineNumber+1,1)),this._moveEndLineSelectionShrink&&s.startLineNumber{a.hasChanged(50)&&this._configureFont()}))}dispose(){this._disposables.dispose(),this._renderDisposeable.dispose()}_configureFont(){const c=this._editor.getOptions(),l=c.get(50),a=l.getMassagedFontFamily(),r=c.get(120)||l.fontSize,u=c.get(121)||l.lineHeight,C=l.fontWeight,f=`${r}px`,h=`${u}px`;this.domNode.style.fontSize=f,this.domNode.style.lineHeight=`${u/r}`,this.domNode.style.fontWeight=C,this.domNode.style.fontFeatureSettings=l.fontFeatureSettings,this._type.style.fontFamily=a,this._close.style.height=h,this._close.style.width=h}getLayoutInfo(){const c=this._editor.getOption(121)||this._editor.getOption(50).lineHeight,l=this._borderWidth,a=l*2;return{lineHeight:c,borderWidth:l,borderHeight:a,verticalPadding:22,horizontalPadding:14}}renderLoading(){this._type.textContent=n.localize(1345,"Loading..."),this._docs.textContent="",this.domNode.classList.remove("no-docs","no-type"),this.layout(this.size.width,this.getLayoutInfo().lineHeight*2),this._onDidChangeContents.fire(this)}renderItem(c,l){this._renderDisposeable.clear();let{detail:a,documentation:r}=c.completion;if(l){let u="";u+=`score: ${c.score[0]} `,u+=`prefix: ${c.word??"(no prefix)"} `,u+=`word: ${c.completion.filterText?c.completion.filterText+" (filterText)":c.textLabel} `,u+=`distance: ${c.distance} (localityBonus-setting) `,u+=`index: ${c.idx}, based on ${c.completion.sortText&&`sortText: "${c.completion.sortText}"`||"label"} `,u+=`commit_chars: ${c.completion.commitCharacters?.join("")} `,r=new m.MarkdownString().appendCodeblock("empty",u),a=`Provider: ${c.provider._debugDisplayName}`}if(!l&&!t(c)){this.clearContents();return}if(this.domNode.classList.remove("no-docs","no-type"),a){const u=a.length>1e5?`${a.substr(0,1e5)}\u2026`:a;this._type.textContent=u,this._type.title=u,d.show(this._type),this._type.classList.toggle("auto-wrap",!/\r?\n^\s+/gmi.test(u))}else d.clearNode(this._type),this._type.title="",d.hide(this._type),this.domNode.classList.add("no-type");if(d.clearNode(this._docs),typeof r=="string")this._docs.classList.remove("markdown-docs"),this._docs.textContent=r;else if(r){this._docs.classList.add("markdown-docs"),d.clearNode(this._docs);const u=this._markdownRenderer.render(r);this._docs.appendChild(u.element),this._renderDisposeable.add(u),this._renderDisposeable.add(this._markdownRenderer.onDidRenderAsync(()=>{this.layout(this._size.width,this._type.clientHeight+this._docs.clientHeight),this._onDidChangeContents.fire(this)}))}this.domNode.style.userSelect="text",this.domNode.tabIndex=-1,this._close.onmousedown=u=>{u.preventDefault(),u.stopPropagation()},this._close.onclick=u=>{u.preventDefault(),u.stopPropagation(),this._onDidClose.fire()},this._body.scrollTop=0,this.layout(this._size.width,this._type.clientHeight+this._docs.clientHeight),this._onDidChangeContents.fire(this)}clearContents(){this.domNode.classList.add("no-docs"),this._type.textContent="",this._docs.textContent=""}get isEmpty(){return this.domNode.classList.contains("no-docs")}get size(){return this._size}layout(c,l){const a=new d.Dimension(c,l);d.Dimension.equals(a,this._size)||(this._size=a,d.size(this.domNode,c,l)),this._scrollbar.scanDomNode()}scrollDown(c=8){this._body.scrollTop+=c}scrollUp(c=8){this._body.scrollTop-=c}scrollTop(){this._body.scrollTop=0}scrollBottom(){this._body.scrollTop=this._body.scrollHeight}pageDown(){this.scrollDown(80)}pageUp(){this.scrollUp(80)}set borderWidth(c){this._borderWidth=c}get borderWidth(){return this._borderWidth}};e.SuggestDetailsWidget=i,e.SuggestDetailsWidget=i=ke([ce(1,o.IInstantiationService)],i);class s{constructor(c,l){this.widget=c,this._editor=l,this.allowEditorOverflow=!0,this._disposables=new _.DisposableStore,this._added=!1,this._preferAlignAtTop=!0,this._resizable=new p.ResizableHTMLElement,this._resizable.domNode.classList.add("suggest-details-container"),this._resizable.domNode.appendChild(c.domNode),this._resizable.enableSashes(!1,!0,!0,!1);let a,r,u=0,C=0;this._disposables.add(this._resizable.onDidWillResize(()=>{a=this._topLeft,r=this._resizable.size})),this._disposables.add(this._resizable.onDidResize(f=>{if(a&&r){this.widget.layout(f.dimension.width,f.dimension.height);let h=!1;f.west&&(C=r.width-f.dimension.width,h=!0),f.north&&(u=r.height-f.dimension.height,h=!0),h&&this._applyTopLeft({top:a.top+u,left:a.left+C})}f.done&&(a=void 0,r=void 0,u=0,C=0,this._userSize=f.dimension)})),this._disposables.add(this.widget.onDidChangeContents(()=>{this._anchorBox&&this._placeAtAnchor(this._anchorBox,this._userSize??this.widget.size,this._preferAlignAtTop)}))}dispose(){this._resizable.dispose(),this._disposables.dispose(),this.hide()}getId(){return"suggest.details"}getDomNode(){return this._resizable.domNode}getPosition(){return this._topLeft?{preference:this._topLeft}:null}show(){this._added||(this._editor.addOverlayWidget(this),this._added=!0)}hide(c=!1){this._resizable.clearSashHoverState(),this._added&&(this._editor.removeOverlayWidget(this),this._added=!1,this._anchorBox=void 0,this._topLeft=void 0),c&&(this._userSize=void 0,this.widget.clearContents())}placeAtAnchor(c,l){const a=c.getBoundingClientRect();this._anchorBox=a,this._preferAlignAtTop=l,this._placeAtAnchor(this._anchorBox,this._userSize??this.widget.size,l)}_placeAtAnchor(c,l,a){const r=d.getClientArea(this.getDomNode().ownerDocument.body),u=this.widget.getLayoutInfo(),C=new d.Dimension(220,2*u.lineHeight),f=c.top,h=function(){const x=r.width-(c.left+c.width+u.borderWidth+u.horizontalPadding),W=-u.borderWidth+c.left+c.width,V=new d.Dimension(x,r.height-c.top-u.borderHeight-u.verticalPadding),q=V.with(void 0,c.top+c.height-u.borderHeight-u.verticalPadding);return{top:f,left:W,fit:x-l.width,maxSizeTop:V,maxSizeBottom:q,minSize:C.with(Math.min(x,C.width))}}(),v=function(){const x=c.left-u.borderWidth-u.horizontalPadding,W=Math.max(u.horizontalPadding,c.left-l.width-u.borderWidth),V=new d.Dimension(x,r.height-c.top-u.borderHeight-u.verticalPadding),q=V.with(void 0,c.top+c.height-u.borderHeight-u.verticalPadding);return{top:f,left:W,fit:x-l.width,maxSizeTop:V,maxSizeBottom:q,minSize:C.with(Math.min(x,C.width))}}(),w=function(){const x=c.left,W=-u.borderWidth+c.top+c.height,V=new d.Dimension(c.width-u.borderHeight,r.height-c.top-c.height-u.verticalPadding);return{top:W,left:x,fit:V.height-l.height,maxSizeBottom:V,maxSizeTop:V,minSize:C.with(V.width)}}(),S=[h,v,w],L=S.find(x=>x.fit>=0)??S.sort((x,W)=>W.fit-x.fit)[0],D=c.top+c.height-u.borderHeight;let T,M=l.height;const A=Math.max(L.maxSizeTop.height,L.maxSizeBottom.height);M>A&&(M=A);let P;a?M<=L.maxSizeTop.height?(T=!0,P=L.maxSizeTop):(T=!1,P=L.maxSizeBottom):M<=L.maxSizeBottom.height?(T=!1,P=L.maxSizeBottom):(T=!0,P=L.maxSizeTop);let{top:N,left:O}=L;!T&&M>c.height&&(N=D-M);const F=this._editor.getDomNode();if(F){const x=F.getBoundingClientRect();N-=x.top,O-=x.left}this._applyTopLeft({left:O,top:N}),this._resizable.enableSashes(!T,L===h,T,L!==h),this._resizable.minSize=L.minSize,this._resizable.maxSize=P,this._resizable.layout(M,Math.min(P.width,l.width)),this.widget.layout(this._resizable.size.width,this._resizable.size.height)}_applyTopLeft(c){this._topLeft=c,this._editor.layoutOverlayWidget(this)}}e.SuggestDetailsOverlay=s}),define(ne[403],se([1,0,13,45,60,19,22,28,109,38]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ConfigurationChangeEvent=e.Configuration=e.ConfigurationModelParser=e.ConfigurationModel=void 0;function p(g){return Object.isFrozen(g)?g:I.deepFreeze(g)}class n{static createEmptyModel(c){return new n({},[],[],void 0,c)}constructor(c,l,a,r,u){this._contents=c,this._keys=l,this._overrides=a,this.raw=r,this.logService=u,this.overrideConfigurations=new Map}get rawConfiguration(){if(!this._rawConfiguration)if(this.raw?.length){const c=this.raw.map(l=>{if(l instanceof n)return l;const a=new o("",this.logService);return a.parseRaw(l),a.configurationModel});this._rawConfiguration=c.reduce((l,a)=>a===l?a:l.merge(a),c[0])}else this._rawConfiguration=this;return this._rawConfiguration}get contents(){return this._contents}get overrides(){return this._overrides}get keys(){return this._keys}isEmpty(){return this._keys.length===0&&Object.keys(this._contents).length===0&&this._overrides.length===0}getValue(c){return c?(0,m.getConfigurationValue)(this.contents,c):this.contents}inspect(c,l){const a=this;return{get value(){return p(a.rawConfiguration.getValue(c))},get override(){return l?p(a.rawConfiguration.getOverrideValue(c,l)):void 0},get merged(){return p(l?a.rawConfiguration.override(l).getValue(c):a.rawConfiguration.getValue(c))},get overrides(){const r=[];for(const{contents:u,identifiers:C,keys:f}of a.rawConfiguration.overrides){const h=new n(u,f,[],void 0,a.logService).getValue(c);h!==void 0&&r.push({identifiers:C,value:h})}return r.length?p(r):void 0}}}getOverrideValue(c,l){const a=this.getContentsForOverrideIdentifer(l);return a?c?(0,m.getConfigurationValue)(a,c):a:void 0}override(c){let l=this.overrideConfigurations.get(c);return l||(l=this.createOverrideConfigurationModel(c),this.overrideConfigurations.set(c,l)),l}merge(...c){const l=I.deepClone(this.contents),a=I.deepClone(this.overrides),r=[...this.keys],u=this.raw?.length?[...this.raw]:[this];for(const C of c)if(u.push(...C.raw?.length?C.raw:[C]),!C.isEmpty()){this.mergeContents(l,C.contents);for(const f of C.overrides){const[h]=a.filter(v=>d.equals(v.identifiers,f.identifiers));h?(this.mergeContents(h.contents,f.contents),h.keys.push(...f.keys),h.keys=d.distinct(h.keys)):a.push(I.deepClone(f))}for(const f of C.keys)r.indexOf(f)===-1&&r.push(f)}return new n(l,r,a,u.every(C=>C instanceof n)?void 0:u,this.logService)}createOverrideConfigurationModel(c){const l=this.getContentsForOverrideIdentifer(c);if(!l||typeof l!="object"||!Object.keys(l).length)return this;const a={};for(const r of d.distinct([...Object.keys(this.contents),...Object.keys(l)])){let u=this.contents[r];const C=l[r];C&&(typeof u=="object"&&typeof C=="object"?(u=I.deepClone(u),this.mergeContents(u,C)):u=C),a[r]=u}return new n(a,this.keys,this.overrides,void 0,this.logService)}mergeContents(c,l){for(const a of Object.keys(l)){if(a in c&&E.isObject(c[a])&&E.isObject(l[a])){this.mergeContents(c[a],l[a]);continue}c[a]=I.deepClone(l[a])}}getContentsForOverrideIdentifer(c){let l=null,a=null;const r=u=>{u&&(a?this.mergeContents(a,u):a=I.deepClone(u))};for(const u of this.overrides)u.identifiers.length===1&&u.identifiers[0]===c?l=u.contents:u.identifiers.includes(c)&&r(u.contents);return r(l),a}toJSON(){return{contents:this.contents,overrides:this.overrides,keys:this.keys}}setValue(c,l){this.updateValue(c,l,!1)}removeValue(c){const l=this.keys.indexOf(c);l!==-1&&(this.keys.splice(l,1),(0,m.removeFromValueTree)(this.contents,c),_.OVERRIDE_PROPERTY_REGEX.test(c)&&this.overrides.splice(this.overrides.findIndex(a=>d.equals(a.identifiers,(0,_.overrideIdentifiersFromKey)(c))),1))}updateValue(c,l,a){if((0,m.addToValueTree)(this.contents,c,l,r=>this.logService.error(r)),a=a||this.keys.indexOf(c)===-1,a&&this.keys.push(c),_.OVERRIDE_PROPERTY_REGEX.test(c)){const r=(0,_.overrideIdentifiersFromKey)(c),u={identifiers:r,keys:Object.keys(this.contents[c]),contents:(0,m.toValuesTree)(this.contents[c],f=>this.logService.error(f))},C=this.overrides.findIndex(f=>d.equals(f.identifiers,r));C!==-1?this.overrides[C]=u:this.overrides.push(u)}}}e.ConfigurationModel=n;class o{constructor(c,l){this._name=c,this.logService=l,this._raw=null,this._configurationModel=null,this._restrictedConfigurations=[]}get configurationModel(){return this._configurationModel||n.createEmptyModel(this.logService)}parseRaw(c,l){this._raw=c;const{contents:a,keys:r,overrides:u,restricted:C,hasExcludedProperties:f}=this.doParseRaw(c,l);this._configurationModel=new n(a,r,u,f?[c]:void 0,this.logService),this._restrictedConfigurations=C||[]}doParseRaw(c,l){const a=b.Registry.as(_.Extensions.Configuration).getConfigurationProperties(),r=this.filter(c,a,!0,l);c=r.raw;const u=(0,m.toValuesTree)(c,h=>this.logService.error(`Conflict in settings file ${this._name}: ${h}`)),C=Object.keys(c),f=this.toOverrides(c,h=>this.logService.error(`Conflict in settings file ${this._name}: ${h}`));return{contents:u,keys:C,overrides:f,restricted:r.restricted,hasExcludedProperties:r.hasExcludedProperties}}filter(c,l,a,r){let u=!1;if(!r?.scopes&&!r?.skipRestricted&&!r?.exclude?.length)return{raw:c,restricted:[],hasExcludedProperties:u};const C={},f=[];for(const h in c)if(_.OVERRIDE_PROPERTY_REGEX.test(h)&&a){const v=this.filter(c[h],l,!1,r);C[h]=v.raw,u=u||v.hasExcludedProperties,f.push(...v.restricted)}else{const v=l[h],w=v?typeof v.scope<"u"?v.scope:3:void 0;v?.restricted&&f.push(h),!r.exclude?.includes(h)&&(r.include?.includes(h)||(w===void 0||r.scopes===void 0||r.scopes.includes(w))&&!(r.skipRestricted&&v?.restricted))?C[h]=c[h]:u=!0}return{raw:C,restricted:f,hasExcludedProperties:u}}toOverrides(c,l){const a=[];for(const r of Object.keys(c))if(_.OVERRIDE_PROPERTY_REGEX.test(r)){const u={};for(const C in c[r])u[C]=c[r][C];a.push({identifiers:(0,_.overrideIdentifiersFromKey)(r),keys:Object.keys(u),contents:(0,m.toValuesTree)(u,l)})}return a}}e.ConfigurationModelParser=o;class t{constructor(c,l,a,r,u,C,f,h,v,w,S,L,D){this.key=c,this.overrides=l,this._value=a,this.overrideIdentifiers=r,this.defaultConfiguration=u,this.policyConfiguration=C,this.applicationConfiguration=f,this.userConfiguration=h,this.localUserConfiguration=v,this.remoteUserConfiguration=w,this.workspaceConfiguration=S,this.folderConfigurationModel=L,this.memoryConfigurationModel=D}toInspectValue(c){return c?.value!==void 0||c?.override!==void 0||c?.overrides!==void 0?c:void 0}get userInspectValue(){return this._userInspectValue||(this._userInspectValue=this.userConfiguration.inspect(this.key,this.overrides.overrideIdentifier)),this._userInspectValue}get user(){return this.toInspectValue(this.userInspectValue)}}class i{constructor(c,l,a,r,u,C,f,h,v,w){this._defaultConfiguration=c,this._policyConfiguration=l,this._applicationConfiguration=a,this._localUserConfiguration=r,this._remoteUserConfiguration=u,this._workspaceConfiguration=C,this._folderConfigurations=f,this._memoryConfiguration=h,this._memoryConfigurationByResource=v,this.logService=w,this._workspaceConsolidatedConfiguration=null,this._foldersConsolidatedConfigurations=new k.ResourceMap,this._userConfiguration=null}getValue(c,l,a){return this.getConsolidatedConfigurationModel(c,l,a).getValue(c)}updateValue(c,l,a={}){let r;a.resource?(r=this._memoryConfigurationByResource.get(a.resource),r||(r=n.createEmptyModel(this.logService),this._memoryConfigurationByResource.set(a.resource,r))):r=this._memoryConfiguration,l===void 0?r.removeValue(c):r.setValue(c,l),a.resource||(this._workspaceConsolidatedConfiguration=null)}inspect(c,l,a){const r=this.getConsolidatedConfigurationModel(c,l,a),u=this.getFolderConfigurationModelForResource(l.resource,a),C=l.resource?this._memoryConfigurationByResource.get(l.resource)||this._memoryConfiguration:this._memoryConfiguration,f=new Set;for(const h of r.overrides)for(const v of h.identifiers)r.getOverrideValue(c,v)!==void 0&&f.add(v);return new t(c,l,r.getValue(c),f.size?[...f]:void 0,this._defaultConfiguration,this._policyConfiguration.isEmpty()?void 0:this._policyConfiguration,this.applicationConfiguration.isEmpty()?void 0:this.applicationConfiguration,this.userConfiguration,this.localUserConfiguration,this.remoteUserConfiguration,a?this._workspaceConfiguration:void 0,u||void 0,C)}get applicationConfiguration(){return this._applicationConfiguration}get userConfiguration(){return this._userConfiguration||(this._userConfiguration=this._remoteUserConfiguration.isEmpty()?this._localUserConfiguration:this._localUserConfiguration.merge(this._remoteUserConfiguration)),this._userConfiguration}get localUserConfiguration(){return this._localUserConfiguration}get remoteUserConfiguration(){return this._remoteUserConfiguration}getConsolidatedConfigurationModel(c,l,a){let r=this.getConsolidatedConfigurationModelForResource(l,a);return l.overrideIdentifier&&(r=r.override(l.overrideIdentifier)),!this._policyConfiguration.isEmpty()&&this._policyConfiguration.getValue(c)!==void 0&&(r=r.merge(this._policyConfiguration)),r}getConsolidatedConfigurationModelForResource({resource:c},l){let a=this.getWorkspaceConsolidatedConfiguration();if(l&&c){const r=l.getFolder(c);r&&(a=this.getFolderConsolidatedConfiguration(r.uri)||a);const u=this._memoryConfigurationByResource.get(c);u&&(a=a.merge(u))}return a}getWorkspaceConsolidatedConfiguration(){return this._workspaceConsolidatedConfiguration||(this._workspaceConsolidatedConfiguration=this._defaultConfiguration.merge(this.applicationConfiguration,this.userConfiguration,this._workspaceConfiguration,this._memoryConfiguration)),this._workspaceConsolidatedConfiguration}getFolderConsolidatedConfiguration(c){let l=this._foldersConsolidatedConfigurations.get(c);if(!l){const a=this.getWorkspaceConsolidatedConfiguration(),r=this._folderConfigurations.get(c);r?(l=a.merge(r),this._foldersConsolidatedConfigurations.set(c,l)):l=a}return l}getFolderConfigurationModelForResource(c,l){if(l&&c){const a=l.getFolder(c);if(a)return this._folderConfigurations.get(a.uri)}}toData(){return{defaults:{contents:this._defaultConfiguration.contents,overrides:this._defaultConfiguration.overrides,keys:this._defaultConfiguration.keys},policy:{contents:this._policyConfiguration.contents,overrides:this._policyConfiguration.overrides,keys:this._policyConfiguration.keys},application:{contents:this.applicationConfiguration.contents,overrides:this.applicationConfiguration.overrides,keys:this.applicationConfiguration.keys},user:{contents:this.userConfiguration.contents,overrides:this.userConfiguration.overrides,keys:this.userConfiguration.keys},workspace:{contents:this._workspaceConfiguration.contents,overrides:this._workspaceConfiguration.overrides,keys:this._workspaceConfiguration.keys},folders:[...this._folderConfigurations.keys()].reduce((c,l)=>{const{contents:a,overrides:r,keys:u}=this._folderConfigurations.get(l);return c.push([l,{contents:a,overrides:r,keys:u}]),c},[])}}static parse(c,l){const a=this.parseConfigurationModel(c.defaults,l),r=this.parseConfigurationModel(c.policy,l),u=this.parseConfigurationModel(c.application,l),C=this.parseConfigurationModel(c.user,l),f=this.parseConfigurationModel(c.workspace,l),h=c.folders.reduce((v,w)=>(v.set(y.URI.revive(w[0]),this.parseConfigurationModel(w[1],l)),v),new k.ResourceMap);return new i(a,r,u,C,n.createEmptyModel(l),f,h,n.createEmptyModel(l),new k.ResourceMap,l)}static parseConfigurationModel(c,l){return new n(c.contents,c.keys,c.overrides,void 0,l)}}e.Configuration=i;class s{constructor(c,l,a,r,u){this.change=c,this.previous=l,this.currentConfiguraiton=a,this.currentWorkspace=r,this.logService=u,this._marker=` `,this._markerCode1=this._marker.charCodeAt(0),this._markerCode2=46,this.affectedKeys=new Set,this._previousConfiguration=void 0;for(const C of c.keys)this.affectedKeys.add(C);for(const[,C]of c.overrides)for(const f of C)this.affectedKeys.add(f);this._affectsConfigStr=this._marker;for(const C of this.affectedKeys)this._affectsConfigStr+=C+this._marker}get previousConfiguration(){return!this._previousConfiguration&&this.previous&&(this._previousConfiguration=i.parse(this.previous.data,this.logService)),this._previousConfiguration}affectsConfiguration(c,l){const a=this._marker+c,r=this._affectsConfigStr.indexOf(a);if(r<0)return!1;const u=r+a.length;if(u>=this._affectsConfigStr.length)return!1;const C=this._affectsConfigStr.charCodeAt(u);if(C!==this._markerCode1&&C!==this._markerCode2)return!1;if(l){const f=this.previousConfiguration?this.previousConfiguration.getValue(c,l,this.previous?.workspace):void 0,h=this.currentConfiguraiton.getValue(c,l,this.currentWorkspace);return!I.equals(f,h)}return!0}}e.ConfigurationChangeEvent=s}),define(ne[717],se([1,0,2,403,109,38]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DefaultConfiguration=void 0;class y extends d.Disposable{get configurationModel(){return this._configurationModel}constructor(_){super(),this.logService=_,this._configurationModel=k.ConfigurationModel.createEmptyModel(this.logService)}reload(){return this.resetConfigurationModel(),this.configurationModel}getConfigurationDefaultOverrides(){return{}}resetConfigurationModel(){this._configurationModel=k.ConfigurationModel.createEmptyModel(this.logService);const _=E.Registry.as(I.Extensions.Configuration).getConfigurationProperties();this.updateConfigurationModel(Object.keys(_),_)}updateConfigurationModel(_,b){const p=this.getConfigurationDefaultOverrides();for(const n of _){const o=p[n],t=b[n];o!==void 0?this._configurationModel.setValue(n,o):t?this._configurationModel.setValue(n,t.default):this._configurationModel.removeValue(n)}}}e.DefaultConfiguration=y}),define(ne[121],se([1,0,140,16,24,38,2,73]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Extensions=e.KeybindingsRegistry=void 0;class _{constructor(){this._coreKeybindings=new m.LinkedList,this._extensionKeybindings=[],this._cachedMergedKeybindings=null}static bindToCurrentPlatform(n){if(k.OS===1){if(n&&n.win)return n.win}else if(k.OS===2){if(n&&n.mac)return n.mac}else if(n&&n.linux)return n.linux;return n}registerKeybindingRule(n){const o=_.bindToCurrentPlatform(n),t=new y.DisposableStore;if(o&&o.primary){const i=(0,d.decodeKeybinding)(o.primary,k.OS);i&&t.add(this._registerDefaultKeybinding(i,n.id,n.args,n.weight,0,n.when))}if(o&&Array.isArray(o.secondary))for(let i=0,s=o.secondary.length;i{c(),this._cachedMergedKeybindings=null})}getDefaultKeybindings(){return this._cachedMergedKeybindings||(this._cachedMergedKeybindings=Array.from(this._coreKeybindings).concat(this._extensionKeybindings),this._cachedMergedKeybindings.sort(b)),this._cachedMergedKeybindings.slice(0)}}e.KeybindingsRegistry=new _,e.Extensions={EditorModes:"platform.keybindingsRegistry"},E.Registry.add(e.Extensions.EditorModes,e.KeybindingsRegistry);function b(p,n){if(p.weight1!==n.weight1)return p.weight1-n.weight1;if(p.command&&n.command){if(p.commandn.command)return 1}return p.weight2-n.weight2}}),define(ne[29],se([1,0,41,30,6,2,73,24,12,7,121]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";var n;Object.defineProperty(e,"__esModule",{value:!0}),e.Action2=e.MenuItemAction=e.SubmenuItemAction=e.MenuRegistry=e.IMenuService=e.MenuId=void 0,e.isIMenuItem=o,e.isISubmenuItem=t,e.registerAction2=a;function o(r){return r.command!==void 0}function t(r){return r.submenu!==void 0}class i{static{this._instances=new Map}static{this.CommandPalette=new i("CommandPalette")}static{this.DebugBreakpointsContext=new i("DebugBreakpointsContext")}static{this.DebugCallStackContext=new i("DebugCallStackContext")}static{this.DebugConsoleContext=new i("DebugConsoleContext")}static{this.DebugVariablesContext=new i("DebugVariablesContext")}static{this.NotebookVariablesContext=new i("NotebookVariablesContext")}static{this.DebugHoverContext=new i("DebugHoverContext")}static{this.DebugWatchContext=new i("DebugWatchContext")}static{this.DebugToolBar=new i("DebugToolBar")}static{this.DebugToolBarStop=new i("DebugToolBarStop")}static{this.DebugCallStackToolbar=new i("DebugCallStackToolbar")}static{this.DebugCreateConfiguration=new i("DebugCreateConfiguration")}static{this.EditorContext=new i("EditorContext")}static{this.SimpleEditorContext=new i("SimpleEditorContext")}static{this.EditorContent=new i("EditorContent")}static{this.EditorLineNumberContext=new i("EditorLineNumberContext")}static{this.EditorContextCopy=new i("EditorContextCopy")}static{this.EditorContextPeek=new i("EditorContextPeek")}static{this.EditorContextShare=new i("EditorContextShare")}static{this.EditorTitle=new i("EditorTitle")}static{this.EditorTitleRun=new i("EditorTitleRun")}static{this.EditorTitleContext=new i("EditorTitleContext")}static{this.EditorTitleContextShare=new i("EditorTitleContextShare")}static{this.EmptyEditorGroup=new i("EmptyEditorGroup")}static{this.EmptyEditorGroupContext=new i("EmptyEditorGroupContext")}static{this.EditorTabsBarContext=new i("EditorTabsBarContext")}static{this.EditorTabsBarShowTabsSubmenu=new i("EditorTabsBarShowTabsSubmenu")}static{this.EditorTabsBarShowTabsZenModeSubmenu=new i("EditorTabsBarShowTabsZenModeSubmenu")}static{this.EditorActionsPositionSubmenu=new i("EditorActionsPositionSubmenu")}static{this.ExplorerContext=new i("ExplorerContext")}static{this.ExplorerContextShare=new i("ExplorerContextShare")}static{this.ExtensionContext=new i("ExtensionContext")}static{this.GlobalActivity=new i("GlobalActivity")}static{this.CommandCenter=new i("CommandCenter")}static{this.CommandCenterCenter=new i("CommandCenterCenter")}static{this.LayoutControlMenuSubmenu=new i("LayoutControlMenuSubmenu")}static{this.LayoutControlMenu=new i("LayoutControlMenu")}static{this.MenubarMainMenu=new i("MenubarMainMenu")}static{this.MenubarAppearanceMenu=new i("MenubarAppearanceMenu")}static{this.MenubarDebugMenu=new i("MenubarDebugMenu")}static{this.MenubarEditMenu=new i("MenubarEditMenu")}static{this.MenubarCopy=new i("MenubarCopy")}static{this.MenubarFileMenu=new i("MenubarFileMenu")}static{this.MenubarGoMenu=new i("MenubarGoMenu")}static{this.MenubarHelpMenu=new i("MenubarHelpMenu")}static{this.MenubarLayoutMenu=new i("MenubarLayoutMenu")}static{this.MenubarNewBreakpointMenu=new i("MenubarNewBreakpointMenu")}static{this.PanelAlignmentMenu=new i("PanelAlignmentMenu")}static{this.PanelPositionMenu=new i("PanelPositionMenu")}static{this.ActivityBarPositionMenu=new i("ActivityBarPositionMenu")}static{this.MenubarPreferencesMenu=new i("MenubarPreferencesMenu")}static{this.MenubarRecentMenu=new i("MenubarRecentMenu")}static{this.MenubarSelectionMenu=new i("MenubarSelectionMenu")}static{this.MenubarShare=new i("MenubarShare")}static{this.MenubarSwitchEditorMenu=new i("MenubarSwitchEditorMenu")}static{this.MenubarSwitchGroupMenu=new i("MenubarSwitchGroupMenu")}static{this.MenubarTerminalMenu=new i("MenubarTerminalMenu")}static{this.MenubarViewMenu=new i("MenubarViewMenu")}static{this.MenubarHomeMenu=new i("MenubarHomeMenu")}static{this.OpenEditorsContext=new i("OpenEditorsContext")}static{this.OpenEditorsContextShare=new i("OpenEditorsContextShare")}static{this.ProblemsPanelContext=new i("ProblemsPanelContext")}static{this.SCMInputBox=new i("SCMInputBox")}static{this.SCMChangesSeparator=new i("SCMChangesSeparator")}static{this.SCMChangesContext=new i("SCMChangesContext")}static{this.SCMIncomingChanges=new i("SCMIncomingChanges")}static{this.SCMIncomingChangesContext=new i("SCMIncomingChangesContext")}static{this.SCMIncomingChangesSetting=new i("SCMIncomingChangesSetting")}static{this.SCMOutgoingChanges=new i("SCMOutgoingChanges")}static{this.SCMOutgoingChangesContext=new i("SCMOutgoingChangesContext")}static{this.SCMOutgoingChangesSetting=new i("SCMOutgoingChangesSetting")}static{this.SCMIncomingChangesAllChangesContext=new i("SCMIncomingChangesAllChangesContext")}static{this.SCMIncomingChangesHistoryItemContext=new i("SCMIncomingChangesHistoryItemContext")}static{this.SCMOutgoingChangesAllChangesContext=new i("SCMOutgoingChangesAllChangesContext")}static{this.SCMOutgoingChangesHistoryItemContext=new i("SCMOutgoingChangesHistoryItemContext")}static{this.SCMChangeContext=new i("SCMChangeContext")}static{this.SCMResourceContext=new i("SCMResourceContext")}static{this.SCMResourceContextShare=new i("SCMResourceContextShare")}static{this.SCMResourceFolderContext=new i("SCMResourceFolderContext")}static{this.SCMResourceGroupContext=new i("SCMResourceGroupContext")}static{this.SCMSourceControl=new i("SCMSourceControl")}static{this.SCMSourceControlInline=new i("SCMSourceControlInline")}static{this.SCMSourceControlTitle=new i("SCMSourceControlTitle")}static{this.SCMHistoryTitle=new i("SCMHistoryTitle")}static{this.SCMTitle=new i("SCMTitle")}static{this.SearchContext=new i("SearchContext")}static{this.SearchActionMenu=new i("SearchActionContext")}static{this.StatusBarWindowIndicatorMenu=new i("StatusBarWindowIndicatorMenu")}static{this.StatusBarRemoteIndicatorMenu=new i("StatusBarRemoteIndicatorMenu")}static{this.StickyScrollContext=new i("StickyScrollContext")}static{this.TestItem=new i("TestItem")}static{this.TestItemGutter=new i("TestItemGutter")}static{this.TestProfilesContext=new i("TestProfilesContext")}static{this.TestMessageContext=new i("TestMessageContext")}static{this.TestMessageContent=new i("TestMessageContent")}static{this.TestPeekElement=new i("TestPeekElement")}static{this.TestPeekTitle=new i("TestPeekTitle")}static{this.TestCallStack=new i("TestCallStack")}static{this.TouchBarContext=new i("TouchBarContext")}static{this.TitleBarContext=new i("TitleBarContext")}static{this.TitleBarTitleContext=new i("TitleBarTitleContext")}static{this.TunnelContext=new i("TunnelContext")}static{this.TunnelPrivacy=new i("TunnelPrivacy")}static{this.TunnelProtocol=new i("TunnelProtocol")}static{this.TunnelPortInline=new i("TunnelInline")}static{this.TunnelTitle=new i("TunnelTitle")}static{this.TunnelLocalAddressInline=new i("TunnelLocalAddressInline")}static{this.TunnelOriginInline=new i("TunnelOriginInline")}static{this.ViewItemContext=new i("ViewItemContext")}static{this.ViewContainerTitle=new i("ViewContainerTitle")}static{this.ViewContainerTitleContext=new i("ViewContainerTitleContext")}static{this.ViewTitle=new i("ViewTitle")}static{this.ViewTitleContext=new i("ViewTitleContext")}static{this.CommentEditorActions=new i("CommentEditorActions")}static{this.CommentThreadTitle=new i("CommentThreadTitle")}static{this.CommentThreadActions=new i("CommentThreadActions")}static{this.CommentThreadAdditionalActions=new i("CommentThreadAdditionalActions")}static{this.CommentThreadTitleContext=new i("CommentThreadTitleContext")}static{this.CommentThreadCommentContext=new i("CommentThreadCommentContext")}static{this.CommentTitle=new i("CommentTitle")}static{this.CommentActions=new i("CommentActions")}static{this.CommentsViewThreadActions=new i("CommentsViewThreadActions")}static{this.InteractiveToolbar=new i("InteractiveToolbar")}static{this.InteractiveCellTitle=new i("InteractiveCellTitle")}static{this.InteractiveCellDelete=new i("InteractiveCellDelete")}static{this.InteractiveCellExecute=new i("InteractiveCellExecute")}static{this.InteractiveInputExecute=new i("InteractiveInputExecute")}static{this.InteractiveInputConfig=new i("InteractiveInputConfig")}static{this.ReplInputExecute=new i("ReplInputExecute")}static{this.IssueReporter=new i("IssueReporter")}static{this.NotebookToolbar=new i("NotebookToolbar")}static{this.NotebookStickyScrollContext=new i("NotebookStickyScrollContext")}static{this.NotebookCellTitle=new i("NotebookCellTitle")}static{this.NotebookCellDelete=new i("NotebookCellDelete")}static{this.NotebookCellInsert=new i("NotebookCellInsert")}static{this.NotebookCellBetween=new i("NotebookCellBetween")}static{this.NotebookCellListTop=new i("NotebookCellTop")}static{this.NotebookCellExecute=new i("NotebookCellExecute")}static{this.NotebookCellExecuteGoTo=new i("NotebookCellExecuteGoTo")}static{this.NotebookCellExecutePrimary=new i("NotebookCellExecutePrimary")}static{this.NotebookDiffCellInputTitle=new i("NotebookDiffCellInputTitle")}static{this.NotebookDiffCellMetadataTitle=new i("NotebookDiffCellMetadataTitle")}static{this.NotebookDiffCellOutputsTitle=new i("NotebookDiffCellOutputsTitle")}static{this.NotebookOutputToolbar=new i("NotebookOutputToolbar")}static{this.NotebookOutlineFilter=new i("NotebookOutlineFilter")}static{this.NotebookOutlineActionMenu=new i("NotebookOutlineActionMenu")}static{this.NotebookEditorLayoutConfigure=new i("NotebookEditorLayoutConfigure")}static{this.NotebookKernelSource=new i("NotebookKernelSource")}static{this.BulkEditTitle=new i("BulkEditTitle")}static{this.BulkEditContext=new i("BulkEditContext")}static{this.TimelineItemContext=new i("TimelineItemContext")}static{this.TimelineTitle=new i("TimelineTitle")}static{this.TimelineTitleContext=new i("TimelineTitleContext")}static{this.TimelineFilterSubMenu=new i("TimelineFilterSubMenu")}static{this.AccountsContext=new i("AccountsContext")}static{this.SidebarTitle=new i("SidebarTitle")}static{this.PanelTitle=new i("PanelTitle")}static{this.AuxiliaryBarTitle=new i("AuxiliaryBarTitle")}static{this.AuxiliaryBarHeader=new i("AuxiliaryBarHeader")}static{this.TerminalInstanceContext=new i("TerminalInstanceContext")}static{this.TerminalEditorInstanceContext=new i("TerminalEditorInstanceContext")}static{this.TerminalNewDropdownContext=new i("TerminalNewDropdownContext")}static{this.TerminalTabContext=new i("TerminalTabContext")}static{this.TerminalTabEmptyAreaContext=new i("TerminalTabEmptyAreaContext")}static{this.TerminalStickyScrollContext=new i("TerminalStickyScrollContext")}static{this.WebviewContext=new i("WebviewContext")}static{this.InlineCompletionsActions=new i("InlineCompletionsActions")}static{this.InlineEditsActions=new i("InlineEditsActions")}static{this.InlineEditActions=new i("InlineEditActions")}static{this.NewFile=new i("NewFile")}static{this.MergeInput1Toolbar=new i("MergeToolbar1Toolbar")}static{this.MergeInput2Toolbar=new i("MergeToolbar2Toolbar")}static{this.MergeBaseToolbar=new i("MergeBaseToolbar")}static{this.MergeInputResultToolbar=new i("MergeToolbarResultToolbar")}static{this.InlineSuggestionToolbar=new i("InlineSuggestionToolbar")}static{this.InlineEditToolbar=new i("InlineEditToolbar")}static{this.ChatContext=new i("ChatContext")}static{this.ChatCodeBlock=new i("ChatCodeblock")}static{this.ChatCompareBlock=new i("ChatCompareBlock")}static{this.ChatMessageTitle=new i("ChatMessageTitle")}static{this.ChatExecute=new i("ChatExecute")}static{this.ChatExecuteSecondary=new i("ChatExecuteSecondary")}static{this.ChatInputSide=new i("ChatInputSide")}static{this.AccessibleView=new i("AccessibleView")}static{this.MultiDiffEditorFileToolbar=new i("MultiDiffEditorFileToolbar")}static{this.DiffEditorHunkToolbar=new i("DiffEditorHunkToolbar")}static{this.DiffEditorSelectionToolbar=new i("DiffEditorSelectionToolbar")}constructor(u){if(i._instances.has(u))throw new TypeError(`MenuId with identifier '${u}' already exists. Use MenuId.for(ident) or a unique identifier`);i._instances.set(u,this),this.id=u}}e.MenuId=i,e.IMenuService=(0,b.createDecorator)("menuService");class s{static{this._all=new Map}static for(u){let C=this._all.get(u);return C||(C=new s(u),this._all.set(u,C)),C}static merge(u){const C=new Set;for(const f of u)f instanceof s&&C.add(f.id);return C}constructor(u){this.id=u,this.has=C=>C===u}}e.MenuRegistry=new class{constructor(){this._commands=new Map,this._menuItems=new Map,this._onDidChangeMenu=new I.MicrotaskEmitter({merge:s.merge}),this.onDidChangeMenu=this._onDidChangeMenu.event}addCommand(r){return this._commands.set(r.id,r),this._onDidChangeMenu.fire(s.for(i.CommandPalette)),(0,E.toDisposable)(()=>{this._commands.delete(r.id)&&this._onDidChangeMenu.fire(s.for(i.CommandPalette))})}getCommand(r){return this._commands.get(r)}getCommands(){const r=new Map;return this._commands.forEach((u,C)=>r.set(C,u)),r}appendMenuItem(r,u){let C=this._menuItems.get(r);C||(C=new y.LinkedList,this._menuItems.set(r,C));const f=C.push(u);return this._onDidChangeMenu.fire(s.for(r)),(0,E.toDisposable)(()=>{f(),this._onDidChangeMenu.fire(s.for(r))})}appendMenuItems(r){const u=new E.DisposableStore;for(const{id:C,item:f}of r)u.add(this.appendMenuItem(C,f));return u}getMenuItems(r){let u;return this._menuItems.has(r)?u=[...this._menuItems.get(r)]:u=[],r===i.CommandPalette&&this._appendImplicitItems(u),u}_appendImplicitItems(r){const u=new Set;for(const C of r)o(C)&&(u.add(C.command.id),C.alt&&u.add(C.alt.id));this._commands.forEach((C,f)=>{u.has(f)||r.push({command:C})})}};class g extends d.SubmenuAction{constructor(u,C,f){super(`submenuitem.${u.submenu.id}`,typeof u.title=="string"?u.title:u.title.value,f,"submenu"),this.item=u,this.hideActions=C}}e.SubmenuItemAction=g;let c=n=class{static label(u,C){return C?.renderShortTitle&&u.shortTitle?typeof u.shortTitle=="string"?u.shortTitle:u.shortTitle.value:typeof u.title=="string"?u.title:u.title.value}constructor(u,C,f,h,v,w,S){this.hideActions=h,this.menuKeybinding=v,this._commandService=S,this.id=u.id,this.label=n.label(u,f),this.tooltip=(typeof u.tooltip=="string"?u.tooltip:u.tooltip?.value)??"",this.enabled=!u.precondition||w.contextMatchesRules(u.precondition),this.checked=void 0;let L;if(u.toggled){const D=u.toggled.condition?u.toggled:{condition:u.toggled};this.checked=w.contextMatchesRules(D.condition),this.checked&&D.tooltip&&(this.tooltip=typeof D.tooltip=="string"?D.tooltip:D.tooltip.value),this.checked&&k.ThemeIcon.isThemeIcon(D.icon)&&(L=D.icon),this.checked&&D.title&&(this.label=typeof D.title=="string"?D.title:D.title.value)}L||(L=k.ThemeIcon.isThemeIcon(u.icon)?u.icon:void 0),this.item=u,this.alt=C?new n(C,void 0,f,h,void 0,w,S):void 0,this._options=f,this.class=L&&k.ThemeIcon.asClassName(L)}run(...u){let C=[];return this._options?.arg&&(C=[...C,this._options.arg]),this._options?.shouldForwardArgs&&(C=[...C,...u]),this._commandService.executeCommand(this.id,...C)}};e.MenuItemAction=c,e.MenuItemAction=c=n=ke([ce(5,_.IContextKeyService),ce(6,m.ICommandService)],c);class l{constructor(u){this.desc=u}}e.Action2=l;function a(r){const u=[],C=new r,{f1:f,menu:h,keybinding:v,...w}=C.desc;if(m.CommandsRegistry.getCommand(w.id))throw new Error(`Cannot register two commands with the same id: ${w.id}`);if(u.push(m.CommandsRegistry.registerCommand({id:w.id,handler:(S,...L)=>C.run(S,...L),metadata:w.metadata})),Array.isArray(h))for(const S of h)u.push(e.MenuRegistry.appendMenuItem(S.id,{command:{...w,precondition:S.precondition===null?void 0:w.precondition},...S}));else h&&u.push(e.MenuRegistry.appendMenuItem(h.id,{command:{...w,precondition:h.precondition===null?void 0:w.precondition},...h}));if(f&&(u.push(e.MenuRegistry.appendMenuItem(i.CommandPalette,{command:w,when:w.precondition})),u.push(e.MenuRegistry.addCommand(w))),Array.isArray(v))for(const S of v)u.push(p.KeybindingsRegistry.registerKeybindingRule({...S,id:w.id,when:w.precondition?_.ContextKeyExpr.and(w.precondition,S.when):S.when}));else v&&u.push(p.KeybindingsRegistry.registerKeybindingRule({...v,id:w.id,when:w.precondition?_.ContextKeyExpr.and(w.precondition,v.when):v.when}));return{dispose(){(0,E.dispose)(u)}}}}),define(ne[718],se([1,0,46,229,3,29]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ToggleTabFocusModeAction=void 0;class y extends E.Action2{static{this.ID="editor.action.toggleTabFocusMode"}constructor(){super({id:y.ID,title:I.localize2(1383,"Toggle Tab Key Moves Focus"),precondition:void 0,keybinding:{primary:2091,mac:{primary:1323},weight:100},metadata:{description:I.localize2(1384,"Determines whether the tab key moves focus around the workbench or inserts the tab character in the current editor. This is also called tab trapping, tab navigation, or tab focus mode.")},f1:!0})}run(){const b=!k.TabFocus.getTabFocusMode();k.TabFocus.setTabFocusMode(b),b?(0,d.alert)(I.localize(1381,"Pressing Tab will now move focus to the next focusable element")):(0,d.alert)(I.localize(1382,"Pressing Tab will now insert the tab character"))}}e.ToggleTabFocusModeAction=y,(0,E.registerAction2)(y)}),define(ne[404],se([1,0,260,641,12,121,3,2,5]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContextScopedReplaceInput=e.ContextScopedFindInput=e.historyNavigationVisible=void 0,e.registerAndCreateHistoryNavigationContext=i,e.historyNavigationVisible=new I.RawContextKey("suggestWidgetVisible",!1,(0,y.localize)(1537,"Whether suggestion are visible"));const b="historyNavigationWidgetFocus",p="historyNavigationForwardsEnabled",n="historyNavigationBackwardsEnabled";let o;const t=[];function i(c,l){if(t.includes(l))throw new Error("Cannot register the same widget multiple times");t.push(l);const a=new m.DisposableStore,r=new I.RawContextKey(b,!1).bindTo(c),u=new I.RawContextKey(p,!0).bindTo(c),C=new I.RawContextKey(n,!0).bindTo(c),f=()=>{r.set(!0),o=l},h=()=>{r.set(!1),o===l&&(o=void 0)};return(0,_.isActiveElement)(l.element)&&f(),a.add(l.onDidFocus(()=>f())),a.add(l.onDidBlur(()=>h())),a.add((0,m.toDisposable)(()=>{t.splice(t.indexOf(l),1),h()})),{historyNavigationForwardsEnablement:u,historyNavigationBackwardsEnablement:C,dispose(){a.dispose()}}}let s=class extends d.FindInput{constructor(l,a,r,u){super(l,a,r);const C=this._register(u.createScoped(this.inputBox.element));this._register(i(C,this.inputBox))}};e.ContextScopedFindInput=s,e.ContextScopedFindInput=s=ke([ce(3,I.IContextKeyService)],s);let g=class extends k.ReplaceInput{constructor(l,a,r,u,C=!1){super(l,a,C,r);const f=this._register(u.createScoped(this.inputBox.element));this._register(i(f,this.inputBox))}};e.ContextScopedReplaceInput=g,e.ContextScopedReplaceInput=g=ke([ce(3,I.IContextKeyService)],g),E.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"history.showPrevious",weight:200,when:I.ContextKeyExpr.and(I.ContextKeyExpr.has(b),I.ContextKeyExpr.equals(n,!0),I.ContextKeyExpr.not("isComposing"),e.historyNavigationVisible.isEqualTo(!1)),primary:16,secondary:[528],handler:c=>{o?.showPreviousValue()}}),E.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"history.showNext",weight:200,when:I.ContextKeyExpr.and(I.ContextKeyExpr.has(b),I.ContextKeyExpr.equals(p,!0),I.ContextKeyExpr.not("isComposing"),e.historyNavigationVisible.isEqualTo(!1)),primary:18,secondary:[530],handler:c=>{o?.showNextValue()}})}),define(ne[155],se([1,0,18,8,82,2,54,19,22,9,4,78,135,3,29,24,12,17,404]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QuickSuggestionsOptions=e.CompletionItemModel=e.CompletionOptions=e.CompletionItem=e.suggestWidgetStatusbarMenu=e.Context=void 0,e.getSnippetSuggestSupport=C,e.provideSuggestionItems=h,e.getSuggestionComparator=D,e.showSimpleSuggestions=T,e.Context={Visible:l.historyNavigationVisible,HasFocusedSuggestion:new g.RawContextKey("suggestWidgetHasFocusedSuggestion",!1,(0,t.localize)(1310,"Whether any suggestion is focused")),DetailsVisible:new g.RawContextKey("suggestWidgetDetailsVisible",!1,(0,t.localize)(1311,"Whether suggestion details are visible")),MultipleSuggestions:new g.RawContextKey("suggestWidgetMultipleSuggestions",!1,(0,t.localize)(1312,"Whether there are multiple suggestions to pick from")),MakesTextEdit:new g.RawContextKey("suggestionMakesTextEdit",!0,(0,t.localize)(1313,"Whether inserting the current suggestion yields in a change or has everything already been typed")),AcceptSuggestionsOnEnter:new g.RawContextKey("acceptSuggestionOnEnter",!0,(0,t.localize)(1314,"Whether suggestions are inserted when pressing Enter")),HasInsertAndReplaceRange:new g.RawContextKey("suggestionHasInsertAndReplaceRange",!1,(0,t.localize)(1315,"Whether the current suggestion has insert and replace behaviour")),InsertMode:new g.RawContextKey("suggestionInsertMode",void 0,{type:"string",description:(0,t.localize)(1316,"Whether the default behaviour is to insert or replace")}),CanResolve:new g.RawContextKey("suggestionCanResolve",!1,(0,t.localize)(1317,"Whether the current suggestion supports to resolve further details"))},e.suggestWidgetStatusbarMenu=new i.MenuId("suggestWidgetStatusBar");class a{constructor(P,N,O,F){this.position=P,this.completion=N,this.container=O,this.provider=F,this.isInvalid=!1,this.score=I.FuzzyScore.Default,this.distance=0,this.textLabel=typeof N.label=="string"?N.label:N.label?.label,this.labelLow=this.textLabel.toLowerCase(),this.isInvalid=!this.textLabel,this.sortTextLow=N.sortText&&N.sortText.toLowerCase(),this.filterTextLow=N.filterText&&N.filterText.toLowerCase(),this.extensionId=N.extensionId,p.Range.isIRange(N.range)?(this.editStart=new b.Position(N.range.startLineNumber,N.range.startColumn),this.editInsertEnd=new b.Position(N.range.endLineNumber,N.range.endColumn),this.editReplaceEnd=new b.Position(N.range.endLineNumber,N.range.endColumn),this.isInvalid=this.isInvalid||p.Range.spansMultipleLines(N.range)||N.range.startLineNumber!==P.lineNumber):(this.editStart=new b.Position(N.range.insert.startLineNumber,N.range.insert.startColumn),this.editInsertEnd=new b.Position(N.range.insert.endLineNumber,N.range.insert.endColumn),this.editReplaceEnd=new b.Position(N.range.replace.endLineNumber,N.range.replace.endColumn),this.isInvalid=this.isInvalid||p.Range.spansMultipleLines(N.range.insert)||p.Range.spansMultipleLines(N.range.replace)||N.range.insert.startLineNumber!==P.lineNumber||N.range.replace.startLineNumber!==P.lineNumber||N.range.insert.startColumn!==N.range.replace.startColumn),typeof F.resolveCompletionItem!="function"&&(this._resolveCache=Promise.resolve(),this._resolveDuration=0)}get isResolved(){return this._resolveDuration!==void 0}get resolveDuration(){return this._resolveDuration!==void 0?this._resolveDuration:-1}async resolve(P){if(!this._resolveCache){const N=P.onCancellationRequested(()=>{this._resolveCache=void 0,this._resolveDuration=void 0}),O=new y.StopWatch(!0);this._resolveCache=Promise.resolve(this.provider.resolveCompletionItem(this.completion,P)).then(F=>{Object.assign(this.completion,F),this._resolveDuration=O.elapsed()},F=>{(0,k.isCancellationError)(F)&&(this._resolveCache=void 0,this._resolveDuration=void 0)}).finally(()=>{N.dispose()})}return this._resolveCache}}e.CompletionItem=a;class r{static{this.default=new r}constructor(P=2,N=new Set,O=new Set,F=new Map,x=!0){this.snippetSortOrder=P,this.kindFilter=N,this.providerFilter=O,this.providerItemsToReuse=F,this.showDeprecated=x}}e.CompletionOptions=r;let u;function C(){return u}class f{constructor(P,N,O,F){this.items=P,this.needsClipboard=N,this.durations=O,this.disposable=F}}e.CompletionItemModel=f;async function h(A,P,N,O=r.default,F={triggerKind:0},x=d.CancellationToken.None){const W=new y.StopWatch;N=N.clone();const V=P.getWordAtPosition(N),q=V?new p.Range(N.lineNumber,V.startColumn,N.lineNumber,V.endColumn):p.Range.fromPositions(N),H={replace:q,insert:q.setEndPosition(N.lineNumber,N.column)},z=[],U=new E.DisposableStore,j=[];let Y=!1;const G=(R,J,ie)=>{let ue=!1;if(!J)return ue;for(const he of J.suggestions)if(!O.kindFilter.has(he.kind)){if(!O.showDeprecated&&he?.tags?.includes(1))continue;he.range||(he.range=H),he.sortText||(he.sortText=typeof he.label=="string"?he.label:he.label.label),!Y&&he.insertTextRules&&he.insertTextRules&4&&(Y=o.SnippetParser.guessNeedsClipboard(he.insertText)),z.push(new a(N,he,J,R)),ue=!0}return(0,E.isDisposable)(J)&&U.add(J),j.push({providerName:R._debugDisplayName??"unknown_provider",elapsedProvider:J.duration??-1,elapsedOverall:ie.elapsed()}),ue},K=(async()=>{if(!u||O.kindFilter.has(27))return;const R=O.providerItemsToReuse.get(u);if(R){R.forEach(ue=>z.push(ue));return}if(O.providerFilter.size>0&&!O.providerFilter.has(u))return;const J=new y.StopWatch,ie=await u.provideCompletionItems(P,N,F,x);G(u,ie,J)})();for(const R of A.orderedGroups(P)){let J=!1;if(await Promise.all(R.map(async ie=>{if(O.providerItemsToReuse.has(ie)){const ue=O.providerItemsToReuse.get(ie);ue.forEach(he=>z.push(he)),J=J||ue.length>0;return}if(!(O.providerFilter.size>0&&!O.providerFilter.has(ie)))try{const ue=new y.StopWatch,he=await ie.provideCompletionItems(P,N,F,x);J=G(ie,he,ue)||J}catch(ue){(0,k.onUnexpectedExternalError)(ue)}})),J||x.isCancellationRequested)break}return await K,x.isCancellationRequested?(U.dispose(),Promise.reject(new k.CancellationError)):new f(z.sort(D(O.snippetSortOrder)),Y,{entries:j,elapsed:W.elapsed()},U)}function v(A,P){if(A.sortTextLow&&P.sortTextLow){if(A.sortTextLowP.sortTextLow)return 1}return A.textLabelP.textLabel?1:A.completion.kind-P.completion.kind}function w(A,P){if(A.completion.kind!==P.completion.kind){if(A.completion.kind===27)return-1;if(P.completion.kind===27)return 1}return v(A,P)}function S(A,P){if(A.completion.kind!==P.completion.kind){if(A.completion.kind===27)return 1;if(P.completion.kind===27)return-1}return v(A,P)}const L=new Map;L.set(0,w),L.set(2,S),L.set(1,v);function D(A){return L.get(A)}s.CommandsRegistry.registerCommand("_executeCompletionItemProvider",async(A,...P)=>{const[N,O,F,x]=P;(0,m.assertType)(_.URI.isUri(N)),(0,m.assertType)(b.Position.isIPosition(O)),(0,m.assertType)(typeof F=="string"||!F),(0,m.assertType)(typeof x=="number"||!x);const{completionProvider:W}=A.get(c.ILanguageFeaturesService),V=await A.get(n.ITextModelService).createModelReference(N);try{const q={incomplete:!1,suggestions:[]},H=[],z=V.object.textEditorModel.validatePosition(O),U=await h(W,V.object.textEditorModel,z,void 0,{triggerCharacter:F??void 0,triggerKind:F?1:0});for(const j of U.items)H.length<(x??0)&&H.push(j.resolve(d.CancellationToken.None)),q.incomplete=q.incomplete||j.container.incomplete,q.suggestions.push(j.completion);try{return await Promise.all(H),q}finally{setTimeout(()=>U.disposable.dispose(),100)}}finally{V.dispose()}});function T(A,P){A.getContribution("editor.contrib.suggestController")?.triggerSuggest(new Set().add(P),void 0,!0)}class M{static isAllOff(P){return P.other==="off"&&P.comments==="off"&&P.strings==="off"}static isAllOn(P){return P.other==="on"&&P.comments==="on"&&P.strings==="on"}static valueFor(P,N){switch(N){case 1:return P.comments;case 2:return P.strings;default:return P.other}}}e.QuickSuggestionsOptions=M}),define(ne[719],se([1,0,16,3,12,179,121,272,66]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0});const b={weight:200,when:I.ContextKeyExpr.and(I.ContextKeyExpr.equals(m.quickInputTypeContextKeyValue,"quickPick"),m.inQuickInputContext),metadata:{description:(0,k.localize)(1587,"Used while in the context of the quick pick. If you change one keybinding for this command, you should change all of the other keybindings (modifier variants) of this command as well.")}};function p(g,c={}){y.KeybindingsRegistry.registerCommandAndKeybindingRule({...b,...g,secondary:o(g.primary,g.secondary??[],c)})}const n=d.isMacintosh?256:2048;function o(g,c,l={}){return l.withAltMod&&c.push(512+g),l.withCtrlMod&&(c.push(n+g),l.withAltMod&&c.push(512+n+g)),l.withCmdMod&&d.isMacintosh&&(c.push(2048+g),l.withCtrlMod&&c.push(2304+g),l.withAltMod&&(c.push(2560+g),l.withCtrlMod&&c.push(2816+g))),c}function t(g,c){return l=>{const a=l.get(_.IQuickInputService).currentQuickInput;if(a)return c&&a.quickNavigate?a.focus(c):a.focus(g)}}p({id:"quickInput.pageNext",primary:12,handler:t(_.QuickPickFocus.NextPage)},{withAltMod:!0,withCtrlMod:!0,withCmdMod:!0}),p({id:"quickInput.pagePrevious",primary:11,handler:t(_.QuickPickFocus.PreviousPage)},{withAltMod:!0,withCtrlMod:!0,withCmdMod:!0}),p({id:"quickInput.first",primary:n+14,handler:t(_.QuickPickFocus.First)},{withAltMod:!0,withCmdMod:!0}),p({id:"quickInput.last",primary:n+13,handler:t(_.QuickPickFocus.Last)},{withAltMod:!0,withCmdMod:!0}),p({id:"quickInput.next",primary:18,handler:t(_.QuickPickFocus.Next)},{withCtrlMod:!0}),p({id:"quickInput.previous",primary:16,handler:t(_.QuickPickFocus.Previous)},{withCtrlMod:!0});const i=(0,k.localize)(1588,"If we're in quick access mode, this will navigate to the next item. If we are not in quick access mode, this will navigate to the next separator."),s=(0,k.localize)(1589,"If we're in quick access mode, this will navigate to the previous item. If we are not in quick access mode, this will navigate to the previous separator.");d.isMacintosh?(p({id:"quickInput.nextSeparatorWithQuickAccessFallback",primary:2066,handler:t(_.QuickPickFocus.NextSeparator,_.QuickPickFocus.Next),metadata:{description:i}}),p({id:"quickInput.nextSeparator",primary:2578,secondary:[2322],handler:t(_.QuickPickFocus.NextSeparator)},{withCtrlMod:!0}),p({id:"quickInput.previousSeparatorWithQuickAccessFallback",primary:2064,handler:t(_.QuickPickFocus.PreviousSeparator,_.QuickPickFocus.Previous),metadata:{description:s}}),p({id:"quickInput.previousSeparator",primary:2576,secondary:[2320],handler:t(_.QuickPickFocus.PreviousSeparator)},{withCtrlMod:!0})):(p({id:"quickInput.nextSeparatorWithQuickAccessFallback",primary:530,handler:t(_.QuickPickFocus.NextSeparator,_.QuickPickFocus.Next),metadata:{description:i}}),p({id:"quickInput.nextSeparator",primary:2578,handler:t(_.QuickPickFocus.NextSeparator)}),p({id:"quickInput.previousSeparatorWithQuickAccessFallback",primary:528,handler:t(_.QuickPickFocus.PreviousSeparator,_.QuickPickFocus.Previous),metadata:{description:s}}),p({id:"quickInput.previousSeparator",primary:2576,handler:t(_.QuickPickFocus.PreviousSeparator)})),p({id:"quickInput.acceptInBackground",when:I.ContextKeyExpr.and(b.when,I.ContextKeyExpr.or(E.InputFocusedContext.negate(),m.endOfQuickInputBoxContext)),primary:17,weight:250,handler:g=>{g.get(_.IQuickInputService).currentQuickInput?.accept(!0)}},{withAltMod:!0,withCtrlMod:!0,withCmdMod:!0})}),define(ne[156],se([1,0,13,2,38]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QuickAccessRegistry=e.Extensions=e.DefaultQuickAccessFilterValue=void 0;var E;(function(m){m[m.PRESERVE=0]="PRESERVE",m[m.LAST=1]="LAST"})(E||(e.DefaultQuickAccessFilterValue=E={})),e.Extensions={Quickaccess:"workbench.contributions.quickaccess"};class y{constructor(){this.providers=[],this.defaultProvider=void 0}registerQuickAccessProvider(_){return _.prefix.length===0?this.defaultProvider=_:this.providers.push(_),this.providers.sort((b,p)=>p.prefix.length-b.prefix.length),(0,k.toDisposable)(()=>{this.providers.splice(this.providers.indexOf(_),1),this.defaultProvider===_&&(this.defaultProvider=void 0)})}getQuickAccessProviders(){return(0,d.coalesce)([this.defaultProvider,...this.providers])}getQuickAccessProvider(_){return _&&this.providers.find(p=>_.startsWith(p.prefix))||void 0||this.defaultProvider}}e.QuickAccessRegistry=y,I.Registry.add(e.Extensions.Quickaccess,new y)}),define(ne[720],se([1,0,3,38,2,31,156,66]),function(oe,e,d,k,I,E,y,m){"use strict";var _;Object.defineProperty(e,"__esModule",{value:!0}),e.HelpQuickAccessProvider=void 0;let b=class{static{_=this}static{this.PREFIX="?"}constructor(n,o){this.quickInputService=n,this.keybindingService=o,this.registry=k.Registry.as(y.Extensions.Quickaccess)}provide(n){const o=new I.DisposableStore;return o.add(n.onDidAccept(()=>{const[t]=n.selectedItems;t&&this.quickInputService.quickAccess.show(t.prefix,{preserveValue:!0})})),o.add(n.onDidChangeValue(t=>{const i=this.registry.getQuickAccessProvider(t.substr(_.PREFIX.length));i&&i.prefix&&i.prefix!==_.PREFIX&&this.quickInputService.quickAccess.show(i.prefix,{preserveValue:!0})})),n.items=this.getQuickAccessProviders().filter(t=>t.prefix!==_.PREFIX),o}getQuickAccessProviders(){return this.registry.getQuickAccessProviders().sort((o,t)=>o.prefix.localeCompare(t.prefix)).flatMap(o=>this.createPicks(o))}createPicks(n){return n.helpEntries.map(o=>{const t=o.prefix||n.prefix,i=t||"\u2026";return{prefix:t,label:i,keybinding:o.commandId?this.keybindingService.lookupKeybinding(o.commandId):void 0,ariaLabel:(0,d.localize)(1579,"{0}, {1}",i,o.description),description:o.description}})}};e.HelpQuickAccessProvider=b,e.HelpQuickAccessProvider=b=_=ke([ce(0,m.IQuickInputService),ce(1,E.IKeybindingService)],b)}),define(ne[721],se([1,0,38,156,107,720]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),d.Registry.as(k.Extensions.Quickaccess).registerQuickAccessProvider({ctor:E.HelpQuickAccessProvider,prefix:"",helpEntries:[{description:I.QuickHelpNLS.helpQuickAccessActionLabel}]})}),define(ne[722],se([1,0,14,18,6,2,7,156,66,38]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QuickAccessController=void 0;let p=class extends E.Disposable{constructor(o,t){super(),this.quickInputService=o,this.instantiationService=t,this.registry=b.Registry.as(m.Extensions.Quickaccess),this.mapProviderToDescriptor=new Map,this.lastAcceptedPickerValues=new Map,this.visibleQuickAccess=void 0}show(o="",t){this.doShowOrPick(o,!1,t)}doShowOrPick(o,t,i){const[s,g]=this.getOrInstantiateProvider(o,i?.enabledProviderPrefixes),c=this.visibleQuickAccess,l=c?.descriptor;if(c&&g&&l===g){o!==g.prefix&&!i?.preserveValue&&(c.picker.value=o),this.adjustValueSelection(c.picker,g,i);return}if(g&&!i?.preserveValue){let v;if(c&&l&&l!==g){const w=c.value.substr(l.prefix.length);w&&(v=`${g.prefix}${w}`)}if(!v){const w=s?.defaultFilterValue;w===m.DefaultQuickAccessFilterValue.LAST?v=this.lastAcceptedPickerValues.get(g):typeof w=="string"&&(v=`${g.prefix}${w}`)}typeof v=="string"&&(o=v)}const a=c?.picker?.valueSelection,r=c?.picker?.value,u=new E.DisposableStore,C=u.add(this.quickInputService.createQuickPick({useSeparators:!0}));C.value=o,this.adjustValueSelection(C,g,i),C.placeholder=i?.placeholder??g?.placeholder,C.quickNavigate=i?.quickNavigateConfiguration,C.hideInput=!!C.quickNavigate&&!c,(typeof i?.itemActivation=="number"||i?.quickNavigateConfiguration)&&(C.itemActivation=i?.itemActivation??_.ItemActivation.SECOND),C.contextKey=g?.contextKey,C.filterValue=v=>v.substring(g?g.prefix.length:0);let f;t&&(f=new d.DeferredPromise,u.add(I.Event.once(C.onWillAccept)(v=>{v.veto(),C.hide()}))),u.add(this.registerPickerListeners(C,s,g,o,i));const h=u.add(new k.CancellationTokenSource);if(s&&u.add(s.provide(C,h.token,i?.providerOptions)),I.Event.once(C.onDidHide)(()=>{C.selectedItems.length===0&&h.cancel(),u.dispose(),f?.complete(C.selectedItems.slice(0))}),C.show(),a&&r===o&&(C.valueSelection=a),t)return f?.p}adjustValueSelection(o,t,i){let s;i?.preserveValue?s=[o.value.length,o.value.length]:s=[t?.prefix.length??0,o.value.length],o.valueSelection=s}registerPickerListeners(o,t,i,s,g){const c=new E.DisposableStore,l=this.visibleQuickAccess={picker:o,descriptor:i,value:s};return c.add((0,E.toDisposable)(()=>{l===this.visibleQuickAccess&&(this.visibleQuickAccess=void 0)})),c.add(o.onDidChangeValue(a=>{const[r]=this.getOrInstantiateProvider(a,g?.enabledProviderPrefixes);r!==t?this.show(a,{enabledProviderPrefixes:g?.enabledProviderPrefixes,preserveValue:!0,providerOptions:g?.providerOptions}):l.value=a})),i&&c.add(o.onDidAccept(()=>{this.lastAcceptedPickerValues.set(i,o.value)})),c}getOrInstantiateProvider(o,t){const i=this.registry.getQuickAccessProvider(o);if(!i||t&&!t?.includes(i.prefix))return[void 0,void 0];let s=this.mapProviderToDescriptor.get(i);return s||(s=this.instantiationService.createInstance(i.ctor),this.mapProviderToDescriptor.set(i,s)),[s,i]}};e.QuickAccessController=p,e.QuickAccessController=p=ke([ce(0,_.IQuickInputService),ce(1,y.IInstantiationService)],p)}),define(ne[723],se([1,0,26,30,111,544]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SeverityIcon=void 0;var E;(function(y){function m(_){switch(_){case I.default.Ignore:return"severity-ignore "+k.ThemeIcon.asClassName(d.Codicon.info);case I.default.Info:return k.ThemeIcon.asClassName(d.Codicon.info);case I.default.Warning:return k.ThemeIcon.asClassName(d.Codicon.warning);case I.default.Error:return k.ThemeIcon.asClassName(d.Codicon.error);default:return""}}y.className=m})(E||(e.SeverityIcon=E={}))}),define(ne[101],se([1,0,6,2,19,647,7]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InMemoryStorageService=e.AbstractStorageService=e.WillSaveStateReason=e.IStorageService=e.TARGET_KEY=void 0,e.loadKeyTargets=_,e.TARGET_KEY="__$__targetStorageMarker",e.IStorageService=(0,y.createDecorator)("storageService");var m;(function(n){n[n.NONE=0]="NONE",n[n.SHUTDOWN=1]="SHUTDOWN"})(m||(e.WillSaveStateReason=m={}));function _(n){const o=n.get(e.TARGET_KEY);if(o)try{return JSON.parse(o)}catch{}return Object.create(null)}class b extends k.Disposable{static{this.DEFAULT_FLUSH_INTERVAL=60*1e3}constructor(o={flushInterval:b.DEFAULT_FLUSH_INTERVAL}){super(),this.options=o,this._onDidChangeValue=this._register(new d.PauseableEmitter),this._onDidChangeTarget=this._register(new d.PauseableEmitter),this._onWillSaveState=this._register(new d.Emitter),this.onWillSaveState=this._onWillSaveState.event,this._workspaceKeyTargets=void 0,this._profileKeyTargets=void 0,this._applicationKeyTargets=void 0}onDidChangeValue(o,t,i){return d.Event.filter(this._onDidChangeValue.event,s=>s.scope===o&&(t===void 0||s.key===t),i)}emitDidChangeValue(o,t){const{key:i,external:s}=t;if(i===e.TARGET_KEY){switch(o){case-1:this._applicationKeyTargets=void 0;break;case 0:this._profileKeyTargets=void 0;break;case 1:this._workspaceKeyTargets=void 0;break}this._onDidChangeTarget.fire({scope:o})}else this._onDidChangeValue.fire({scope:o,key:i,target:this.getKeyTargets(o)[i],external:s})}get(o,t,i){return this.getStorage(t)?.get(o,i)}getBoolean(o,t,i){return this.getStorage(t)?.getBoolean(o,i)}getNumber(o,t,i){return this.getStorage(t)?.getNumber(o,i)}store(o,t,i,s,g=!1){if((0,I.isUndefinedOrNull)(t)){this.remove(o,i,g);return}this.withPausedEmitters(()=>{this.updateKeyTarget(o,i,s),this.getStorage(i)?.set(o,t,g)})}remove(o,t,i=!1){this.withPausedEmitters(()=>{this.updateKeyTarget(o,t,void 0),this.getStorage(t)?.delete(o,i)})}withPausedEmitters(o){this._onDidChangeValue.pause(),this._onDidChangeTarget.pause();try{o()}finally{this._onDidChangeValue.resume(),this._onDidChangeTarget.resume()}}updateKeyTarget(o,t,i,s=!1){const g=this.getKeyTargets(t);typeof i=="number"?g[o]!==i&&(g[o]=i,this.getStorage(t)?.set(e.TARGET_KEY,JSON.stringify(g),s)):typeof g[o]=="number"&&(delete g[o],this.getStorage(t)?.set(e.TARGET_KEY,JSON.stringify(g),s))}get workspaceKeyTargets(){return this._workspaceKeyTargets||(this._workspaceKeyTargets=this.loadKeyTargets(1)),this._workspaceKeyTargets}get profileKeyTargets(){return this._profileKeyTargets||(this._profileKeyTargets=this.loadKeyTargets(0)),this._profileKeyTargets}get applicationKeyTargets(){return this._applicationKeyTargets||(this._applicationKeyTargets=this.loadKeyTargets(-1)),this._applicationKeyTargets}getKeyTargets(o){switch(o){case-1:return this.applicationKeyTargets;case 0:return this.profileKeyTargets;default:return this.workspaceKeyTargets}}loadKeyTargets(o){const t=this.getStorage(o);return t?_(t):Object.create(null)}}e.AbstractStorageService=b;class p extends b{constructor(){super(),this.applicationStorage=this._register(new E.Storage(new E.InMemoryStorageDatabase,{hint:E.StorageHint.STORAGE_IN_MEMORY})),this.profileStorage=this._register(new E.Storage(new E.InMemoryStorageDatabase,{hint:E.StorageHint.STORAGE_IN_MEMORY})),this.workspaceStorage=this._register(new E.Storage(new E.InMemoryStorageDatabase,{hint:E.StorageHint.STORAGE_IN_MEMORY})),this._register(this.workspaceStorage.onDidChangeStorage(o=>this.emitDidChangeValue(1,o))),this._register(this.profileStorage.onDidChangeStorage(o=>this.emitDidChangeValue(0,o))),this._register(this.applicationStorage.onDidChangeStorage(o=>this.emitDidChangeValue(-1,o)))}getStorage(o){switch(o){case-1:return this.applicationStorage;case 0:return this.profileStorage;default:return this.workspaceStorage}}}e.InMemoryStorageService=p}),define(ne[724],se([1,0,6,45,4,386,49,7,101,52,5]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CodeLensCache=e.ICodeLensCache=void 0,e.ICodeLensCache=(0,m.createDecorator)("ICodeLensCache");class n{constructor(i,s){this.lineCount=i,this.data=s}}let o=class{constructor(i){this._fakeProvider=new class{provideCodeLenses(){throw new Error("not supported")}},this._cache=new k.LRUCache(20,.75);const s="codelens/cache";(0,p.runWhenWindowIdle)(b.mainWindow,()=>i.remove(s,1));const g="codelens/cache2",c=i.get(g,1,"{}");this._deserialize(c);const l=d.Event.filter(i.onWillSaveState,a=>a.reason===_.WillSaveStateReason.SHUTDOWN);d.Event.once(l)(a=>{i.store(g,this._serialize(),1,1)})}put(i,s){const g=s.lenses.map(a=>({range:a.symbol.range,command:a.symbol.command&&{id:"",title:a.symbol.command?.title}})),c=new E.CodeLensModel;c.add({lenses:g,dispose:()=>{}},this._fakeProvider);const l=new n(i.getLineCount(),c);this._cache.set(i.uri.toString(),l)}get(i){const s=this._cache.get(i.uri.toString());return s&&s.lineCount===i.getLineCount()?s.data:void 0}delete(i){this._cache.delete(i.uri.toString())}_serialize(){const i=Object.create(null);for(const[s,g]of this._cache){const c=new Set;for(const l of g.data.lenses)c.add(l.symbol.range.startLineNumber);i[s]={lineCount:g.lineCount,lines:[...c.values()]}}return JSON.stringify(i)}_deserialize(i){try{const s=JSON.parse(i);for(const g in s){const c=s[g],l=[];for(const r of c.lines)l.push({range:new I.Range(r,1,r,11)});const a=new E.CodeLensModel;a.add({lenses:l,dispose(){}},this._fakeProvider),this._cache.set(g,new n(c.lineCount,a))}}catch{}}};e.CodeLensCache=o,e.CodeLensCache=o=ke([ce(0,_.IStorageService)],o),(0,y.registerSingleton)(e.ICodeLensCache,o,1)}),define(ne[405],se([1,0,14,2,45,225,27,28,49,7,101]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";var n;Object.defineProperty(e,"__esModule",{value:!0}),e.ISuggestMemoryService=e.SuggestMemoryService=e.PrefixMemory=e.LRUMemory=e.NoMemory=e.Memory=void 0;class o{constructor(l){this.name=l}select(l,a,r){if(r.length===0)return 0;const u=r[0].score[0];for(let C=0;Cv&&L.type===r[w].completion.kind&&L.insertText===r[w].completion.insertText&&(v=L.touch,h=w),r[w].completion.preselect&&f===-1)return f=w}return h!==-1?h:f!==-1?f:0}toJSON(){return this._cache.toJSON()}fromJSON(l){this._cache.clear();const a=0;for(const[r,u]of l)u.touch=a,u.type=typeof u.type=="number"?u.type:y.CompletionItemKinds.fromString(u.type),this._cache.set(r,u);this._seq=this._cache.size}}e.LRUMemory=i;class s extends o{constructor(){super("recentlyUsedByPrefix"),this._trie=E.TernarySearchTree.forStrings(),this._seq=0}memorize(l,a,r){const{word:u}=l.getWordUntilPosition(a),C=`${l.getLanguageId()}/${u}`;this._trie.set(C,{type:r.completion.kind,insertText:r.completion.insertText,touch:this._seq++})}select(l,a,r){const{word:u}=l.getWordUntilPosition(a);if(!u)return super.select(l,a,r);const C=`${l.getLanguageId()}/${u}`;let f=this._trie.get(C);if(f||(f=this._trie.findSubstr(C)),f)for(let h=0;hl.push([r,a])),l.sort((a,r)=>-(a[1].touch-r[1].touch)).forEach((a,r)=>a[1].touch=r),l.slice(0,200)}fromJSON(l){if(this._trie.clear(),l.length>0){this._seq=l[0][1].touch+1;for(const[a,r]of l)r.type=typeof r.type=="number"?r.type:y.CompletionItemKinds.fromString(r.type),this._trie.set(a,r)}}}e.PrefixMemory=s;let g=class{static{n=this}static{this._strategyCtors=new Map([["recentlyUsedByPrefix",s],["recentlyUsed",i],["first",t]])}static{this._storagePrefix="suggest/memories"}constructor(l,a){this._storageService=l,this._configService=a,this._disposables=new k.DisposableStore,this._persistSoon=new d.RunOnceScheduler(()=>this._saveState(),500),this._disposables.add(l.onWillSaveState(r=>{r.reason===p.WillSaveStateReason.SHUTDOWN&&this._saveState()}))}dispose(){this._disposables.dispose(),this._persistSoon.dispose()}memorize(l,a,r){this._withStrategy(l,a).memorize(l,a,r),this._persistSoon.schedule()}select(l,a,r){return this._withStrategy(l,a).select(l,a,r)}_withStrategy(l,a){const r=this._configService.getValue("editor.suggestSelection",{overrideIdentifier:l.getLanguageIdAtPosition(a.lineNumber,a.column),resource:l.uri});if(this._strategy?.name!==r){this._saveState();const u=n._strategyCtors.get(r)||t;this._strategy=new u;try{const f=this._configService.getValue("editor.suggest.shareSuggestSelections")?0:1,h=this._storageService.get(`${n._storagePrefix}/${r}`,f);h&&this._strategy.fromJSON(JSON.parse(h))}catch{}}return this._strategy}_saveState(){if(this._strategy){const a=this._configService.getValue("editor.suggest.shareSuggestSelections")?0:1,r=JSON.stringify(this._strategy);this._storageService.store(`${n._storagePrefix}/${this._strategy.name}`,r,a,1)}}};e.SuggestMemoryService=g,e.SuggestMemoryService=g=n=ke([ce(0,p.IStorageService),ce(1,m.IConfigurationService)],g),e.ISuggestMemoryService=(0,b.createDecorator)("ISuggestMemories"),(0,_.registerSingleton)(e.ISuggestMemoryService,g,1)}),define(ne[406],se([1,0,14,6,2,29,24,12,41,101,13,3,31]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";var t,i;Object.defineProperty(e,"__esModule",{value:!0}),e.MenuService=void 0,e.createConfigureKeybindingAction=u;let s=class{constructor(f,h,v){this._commandService=f,this._keybindingService=h,this._hiddenStates=new g(v)}createMenu(f,h,v){return new a(f,this._hiddenStates,{emitEventsForSubmenuChanges:!1,eventDebounceDelay:50,...v},this._commandService,this._keybindingService,h)}getMenuActions(f,h,v){const w=new a(f,this._hiddenStates,{emitEventsForSubmenuChanges:!1,eventDebounceDelay:50,...v},this._commandService,this._keybindingService,h),S=w.getActions(v);return w.dispose(),S}resetHiddenStates(f){this._hiddenStates.reset(f)}};e.MenuService=s,e.MenuService=s=ke([ce(0,y.ICommandService),ce(1,o.IKeybindingService),ce(2,b.IStorageService)],s);let g=class{static{t=this}static{this._key="menu.hiddenCommands"}constructor(f){this._storageService=f,this._disposables=new I.DisposableStore,this._onDidChange=new k.Emitter,this.onDidChange=this._onDidChange.event,this._ignoreChangeEvent=!1,this._hiddenByDefaultCache=new Map;try{const h=f.get(t._key,0,"{}");this._data=JSON.parse(h)}catch{this._data=Object.create(null)}this._disposables.add(f.onDidChangeValue(0,t._key,this._disposables)(()=>{if(!this._ignoreChangeEvent)try{const h=f.get(t._key,0,"{}");this._data=JSON.parse(h)}catch(h){console.log("FAILED to read storage after UPDATE",h)}this._onDidChange.fire()}))}dispose(){this._onDidChange.dispose(),this._disposables.dispose()}_isHiddenByDefault(f,h){return this._hiddenByDefaultCache.get(`${f.id}/${h}`)??!1}setDefaultState(f,h,v){this._hiddenByDefaultCache.set(`${f.id}/${h}`,v)}isHidden(f,h){const v=this._isHiddenByDefault(f,h),w=this._data[f.id]?.includes(h)??!1;return v?!w:w}updateHidden(f,h,v){this._isHiddenByDefault(f,h)&&(v=!v);const S=this._data[f.id];if(v)S?S.indexOf(h)<0&&S.push(h):this._data[f.id]=[h];else if(S){const L=S.indexOf(h);L>=0&&(0,p.removeFastWithoutKeepingOrder)(S,L),S.length===0&&delete this._data[f.id]}this._persist()}reset(f){if(f===void 0)this._data=Object.create(null),this._persist();else{for(const{id:h}of f)this._data[h]&&delete this._data[h];this._persist()}}_persist(){try{this._ignoreChangeEvent=!0;const f=JSON.stringify(this._data);this._storageService.store(t._key,f,0,0)}finally{this._ignoreChangeEvent=!1}}};g=t=ke([ce(0,b.IStorageService)],g);class c{constructor(f,h){this._id=f,this._collectContextKeysForSubmenus=h,this._menuGroups=[],this._allMenuIds=new Set,this._structureContextKeys=new Set,this._preconditionContextKeys=new Set,this._toggledContextKeys=new Set,this.refresh()}get allMenuIds(){return this._allMenuIds}get structureContextKeys(){return this._structureContextKeys}get preconditionContextKeys(){return this._preconditionContextKeys}get toggledContextKeys(){return this._toggledContextKeys}refresh(){this._menuGroups.length=0,this._allMenuIds.clear(),this._structureContextKeys.clear(),this._preconditionContextKeys.clear(),this._toggledContextKeys.clear();const f=this._sort(E.MenuRegistry.getMenuItems(this._id));let h;for(const v of f){const w=v.group||"";(!h||h[0]!==w)&&(h=[w,[]],this._menuGroups.push(h)),h[1].push(v),this._collectContextKeysAndSubmenuIds(v)}this._allMenuIds.add(this._id)}_sort(f){return f}_collectContextKeysAndSubmenuIds(f){if(c._fillInKbExprKeys(f.when,this._structureContextKeys),(0,E.isIMenuItem)(f)){if(f.command.precondition&&c._fillInKbExprKeys(f.command.precondition,this._preconditionContextKeys),f.command.toggled){const h=f.command.toggled.condition||f.command.toggled;c._fillInKbExprKeys(h,this._toggledContextKeys)}}else this._collectContextKeysForSubmenus&&(E.MenuRegistry.getMenuItems(f.submenu).forEach(this._collectContextKeysAndSubmenuIds,this),this._allMenuIds.add(f.submenu))}static _fillInKbExprKeys(f,h){if(f)for(const v of f.keys())h.add(v)}}let l=i=class extends c{constructor(f,h,v,w,S,L){super(f,v),this._hiddenStates=h,this._commandService=w,this._keybindingService=S,this._contextKeyService=L,this.refresh()}createActionGroups(f){const h=[];for(const v of this._menuGroups){const[w,S]=v;let L;for(const D of S)if(this._contextKeyService.contextMatchesRules(D.when)){const T=(0,E.isIMenuItem)(D);T&&this._hiddenStates.setDefaultState(this._id,D.command.id,!!D.isHiddenByDefault);const M=r(this._id,T?D.command:D,this._hiddenStates);if(T){const A=u(this._commandService,this._keybindingService,D.command.id,D.when);(L??=[]).push(new E.MenuItemAction(D.command,D.alt,f,M,A,this._contextKeyService,this._commandService))}else{const A=new i(D.submenu,this._hiddenStates,this._collectContextKeysForSubmenus,this._commandService,this._keybindingService,this._contextKeyService).createActionGroups(f),P=_.Separator.join(...A.map(N=>N[1]));P.length>0&&(L??=[]).push(new E.SubmenuItemAction(D,M,P))}}L&&L.length>0&&h.push([w,L])}return h}_sort(f){return f.sort(i._compareMenuItems)}static _compareMenuItems(f,h){const v=f.group,w=h.group;if(v!==w){if(v){if(!w)return-1}else return 1;if(v==="navigation")return-1;if(w==="navigation")return 1;const D=v.localeCompare(w);if(D!==0)return D}const S=f.order||0,L=h.order||0;return SL?1:i._compareTitles((0,E.isIMenuItem)(f)?f.command.title:f.title,(0,E.isIMenuItem)(h)?h.command.title:h.title)}static _compareTitles(f,h){const v=typeof f=="string"?f:f.original,w=typeof h=="string"?h:h.original;return v.localeCompare(w)}};l=i=ke([ce(3,y.ICommandService),ce(4,o.IKeybindingService),ce(5,m.IContextKeyService)],l);let a=class{constructor(f,h,v,w,S,L){this._disposables=new I.DisposableStore,this._menuInfo=new l(f,h,v.emitEventsForSubmenuChanges,w,S,L);const D=new d.RunOnceScheduler(()=>{this._menuInfo.refresh(),this._onDidChange.fire({menu:this,isStructuralChange:!0,isEnablementChange:!0,isToggleChange:!0})},v.eventDebounceDelay);this._disposables.add(D),this._disposables.add(E.MenuRegistry.onDidChangeMenu(P=>{for(const N of this._menuInfo.allMenuIds)if(P.has(N)){D.schedule();break}}));const T=this._disposables.add(new I.DisposableStore),M=P=>{let N=!1,O=!1,F=!1;for(const x of P)if(N=N||x.isStructuralChange,O=O||x.isEnablementChange,F=F||x.isToggleChange,N&&O&&F)break;return{menu:this,isStructuralChange:N,isEnablementChange:O,isToggleChange:F}},A=()=>{T.add(L.onDidChangeContext(P=>{const N=P.affectsSome(this._menuInfo.structureContextKeys),O=P.affectsSome(this._menuInfo.preconditionContextKeys),F=P.affectsSome(this._menuInfo.toggledContextKeys);(N||O||F)&&this._onDidChange.fire({menu:this,isStructuralChange:N,isEnablementChange:O,isToggleChange:F})})),T.add(h.onDidChange(P=>{this._onDidChange.fire({menu:this,isStructuralChange:!0,isEnablementChange:!1,isToggleChange:!1})}))};this._onDidChange=new k.DebounceEmitter({onWillAddFirstListener:A,onDidRemoveLastListener:T.clear.bind(T),delay:v.eventDebounceDelay,merge:M}),this.onDidChange=this._onDidChange.event}getActions(f){return this._menuInfo.createActionGroups(f)}dispose(){this._disposables.dispose(),this._onDidChange.dispose()}};a=ke([ce(3,y.ICommandService),ce(4,o.IKeybindingService),ce(5,m.IContextKeyService)],a);function r(C,f,h){const v=(0,E.isISubmenuItem)(f)?f.submenu.id:f.id,w=typeof f.title=="string"?f.title:f.title.value,S=(0,_.toAction)({id:`hide/${C.id}/${v}`,label:(0,n.localize)(1490,"Hide '{0}'",w),run(){h.updateHidden(C,v,!0)}}),L=(0,_.toAction)({id:`toggle/${C.id}/${v}`,label:w,get checked(){return!h.isHidden(C,v)},run(){h.updateHidden(C,v,!!this.checked)}});return{hide:S,toggle:L,get isHidden(){return!L.checked}}}function u(C,f,h,v=void 0,w=!0){return(0,_.toAction)({id:`configureKeybinding/${h}`,label:(0,n.localize)(1491,"Configure Keybinding"),enabled:w,run(){const L=!!!f.lookupKeybinding(h)&&v?v.serialize():void 0;C.executeCommand("workbench.action.openGlobalKeybindings",`@command:${h}`+(L?` +when:${L}`:""))}})}}),define(ne[63],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ITelemetryService=void 0,e.ITelemetryService=(0,d.createDecorator)("telemetryService")}),define(ne[15],se([1,0,3,22,34,9,51,78,29,24,12,7,121,38,63,19,62,5]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SelectAllCommand=e.RedoCommand=e.UndoCommand=e.EditorExtensionsRegistry=e.EditorAction2=e.MultiEditorAction=e.EditorAction=e.EditorCommand=e.ProxyCommand=e.MultiCommand=e.Command=void 0,e.registerModelAndPositionCommand=v,e.registerEditorCommand=w,e.registerEditorAction=S,e.registerMultiEditorAction=L,e.registerInstantiatedEditorAction=D,e.registerEditorContribution=T;class l{constructor(F){this.id=F.id,this.precondition=F.precondition,this._kbOpts=F.kbOpts,this._menuOpts=F.menuOpts,this.metadata=F.metadata}register(){if(Array.isArray(this._menuOpts)?this._menuOpts.forEach(this._registerMenuItem,this):this._menuOpts&&this._registerMenuItem(this._menuOpts),this._kbOpts){const F=Array.isArray(this._kbOpts)?this._kbOpts:[this._kbOpts];for(const x of F){let W=x.kbExpr;this.precondition&&(W?W=p.ContextKeyExpr.and(W,this.precondition):W=this.precondition);const V={id:this.id,weight:x.weight,args:x.args,when:W,primary:x.primary,secondary:x.secondary,win:x.win,linux:x.linux,mac:x.mac};o.KeybindingsRegistry.registerKeybindingRule(V)}}b.CommandsRegistry.registerCommand({id:this.id,handler:(F,x)=>this.runCommand(F,x),metadata:this.metadata})}_registerMenuItem(F){_.MenuRegistry.appendMenuItem(F.menuId,{group:F.group,command:{id:this.id,title:F.title,icon:F.icon,precondition:this.precondition},when:F.when,order:F.order})}}e.Command=l;class a extends l{constructor(){super(...arguments),this._implementations=[]}addImplementation(F,x,W,V){return this._implementations.push({priority:F,name:x,implementation:W,when:V}),this._implementations.sort((q,H)=>H.priority-q.priority),{dispose:()=>{for(let q=0;q{if(z.get(p.IContextKeyService).contextMatchesRules(W??void 0))return V(z,H,x)})}runCommand(F,x){return u.runEditorCommand(F,x,this.precondition,(W,V,q)=>this.runEditorCommand(W,V,q))}}e.EditorCommand=u;class C extends u{static convertOptions(F){let x;Array.isArray(F.menuOpts)?x=F.menuOpts:F.menuOpts?x=[F.menuOpts]:x=[];function W(V){return V.menuId||(V.menuId=_.MenuId.EditorContext),V.title||(V.title=F.label),V.when=p.ContextKeyExpr.and(F.precondition,V.when),V}return Array.isArray(F.contextMenuOpts)?x.push(...F.contextMenuOpts.map(W)):F.contextMenuOpts&&x.push(W(F.contextMenuOpts)),F.menuOpts=x,F}constructor(F){super(C.convertOptions(F)),this.label=F.label,this.alias=F.alias}runEditorCommand(F,x,W){return this.reportTelemetry(F,x),this.run(F,x,W||{})}reportTelemetry(F,x){F.get(i.ITelemetryService).publicLog2("editorActionInvoked",{name:this.label,id:this.id})}}e.EditorAction=C;class f extends C{constructor(){super(...arguments),this._implementations=[]}addImplementation(F,x){return this._implementations.push([F,x]),this._implementations.sort((W,V)=>V[0]-W[0]),{dispose:()=>{for(let W=0;W{const H=q.get(p.IContextKeyService),z=q.get(g.ILogService);if(!H.contextMatchesRules(this.desc.precondition??void 0)){z.debug("[EditorAction2] NOT running command because its precondition is FALSE",this.desc.id,this.desc.precondition?.serialize());return}return this.runEditorCommand(q,V,...x)})}}e.EditorAction2=h;function v(O,F){b.CommandsRegistry.registerCommand(O,function(x,...W){const V=x.get(n.IInstantiationService),[q,H]=W;(0,s.assertType)(k.URI.isUri(q)),(0,s.assertType)(E.Position.isIPosition(H));const z=x.get(y.IModelService).getModel(q);if(z){const U=E.Position.lift(H);return V.invokeFunction(F,z,U,...W.slice(2))}return x.get(m.ITextModelService).createModelReference(q).then(U=>new Promise((j,Y)=>{try{const G=V.invokeFunction(F,U.object.textEditorModel,E.Position.lift(H),W.slice(2));j(G)}catch(G){Y(G)}}).finally(()=>{U.dispose()}))})}function w(O){return P.INSTANCE.registerEditorCommand(O),O}function S(O){const F=new O;return P.INSTANCE.registerEditorAction(F),F}function L(O){return P.INSTANCE.registerEditorAction(O),O}function D(O){P.INSTANCE.registerEditorAction(O)}function T(O,F,x){P.INSTANCE.registerEditorContribution(O,F,x)}var M;(function(O){function F(H){return P.INSTANCE.getEditorCommand(H)}O.getEditorCommand=F;function x(){return P.INSTANCE.getEditorActions()}O.getEditorActions=x;function W(){return P.INSTANCE.getEditorContributions()}O.getEditorContributions=W;function V(H){return P.INSTANCE.getEditorContributions().filter(z=>H.indexOf(z.id)>=0)}O.getSomeEditorContributions=V;function q(){return P.INSTANCE.getDiffEditorContributions()}O.getDiffEditorContributions=q})(M||(e.EditorExtensionsRegistry=M={}));const A={EditorCommonContributions:"editor.contributions"};class P{static{this.INSTANCE=new P}constructor(){this.editorContributions=[],this.diffEditorContributions=[],this.editorActions=[],this.editorCommands=Object.create(null)}registerEditorContribution(F,x,W){this.editorContributions.push({id:F,ctor:x,instantiation:W})}getEditorContributions(){return this.editorContributions.slice(0)}getDiffEditorContributions(){return this.diffEditorContributions.slice(0)}registerEditorAction(F){F.register(),this.editorActions.push(F)}getEditorActions(){return this.editorActions}registerEditorCommand(F){F.register(),this.editorCommands[F.id]=F}getEditorCommand(F){return this.editorCommands[F]||null}}t.Registry.add(A.EditorCommonContributions,P.INSTANCE);function N(O){return O.register(),O}e.UndoCommand=N(new a({id:"undo",precondition:void 0,kbOpts:{weight:0,primary:2104},menuOpts:[{menuId:_.MenuId.MenubarEditMenu,group:"1_do",title:d.localize(62,"&&Undo"),order:1},{menuId:_.MenuId.CommandPalette,group:"",title:d.localize(63,"Undo"),order:1}]})),N(new r(e.UndoCommand,{id:"default:undo",precondition:void 0})),e.RedoCommand=N(new a({id:"redo",precondition:void 0,kbOpts:{weight:0,primary:2103,secondary:[3128],mac:{primary:3128}},menuOpts:[{menuId:_.MenuId.MenubarEditMenu,group:"1_do",title:d.localize(64,"&&Redo"),order:2},{menuId:_.MenuId.CommandPalette,group:"",title:d.localize(65,"Redo"),order:1}]})),N(new r(e.RedoCommand,{id:"default:redo",precondition:void 0})),e.SelectAllCommand=N(new a({id:"editor.action.selectAll",precondition:void 0,kbOpts:{weight:0,kbExpr:null,primary:2079},menuOpts:[{menuId:_.MenuId.MenubarSelectionMenu,group:"1_basic",title:d.localize(66,"&&Select All"),order:1},{menuId:_.MenuId.CommandPalette,group:"",title:d.localize(67,"Select All"),order:1}]}))}),define(ne[214],se([1,0,3,64,19,46,15,34,565,76,234,235,276,9,4,20,12,121,5,213]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CoreEditingCommands=e.CoreNavigationCommands=e.RevealLine_=e.EditorScroll_=e.CoreEditorCommand=void 0;const r=0;class u extends y.EditorCommand{runEditorCommand(P,N,O){const F=N._getViewModel();F&&this.runCoreEditorCommand(F,O||{})}}e.CoreEditorCommand=u;var C;(function(A){const P=function(O){if(!I.isObject(O))return!1;const F=O;return!(!I.isString(F.to)||!I.isUndefined(F.by)&&!I.isString(F.by)||!I.isUndefined(F.value)&&!I.isNumber(F.value)||!I.isUndefined(F.revealCursor)&&!I.isBoolean(F.revealCursor))};A.metadata={description:"Scroll editor in the given direction",args:[{name:"Editor scroll argument object",description:"Property-value pairs that can be passed through this argument:\n * 'to': A mandatory direction value.\n ```\n 'up', 'down'\n ```\n * 'by': Unit to move. Default is computed based on 'to' value.\n ```\n 'line', 'wrappedLine', 'page', 'halfPage', 'editor'\n ```\n * 'value': Number of units to move. Default is '1'.\n * 'revealCursor': If 'true' reveals the cursor if it is outside view port.\n ",constraint:P,schema:{type:"object",required:["to"],properties:{to:{type:"string",enum:["up","down"]},by:{type:"string",enum:["line","wrappedLine","page","halfPage","editor"]},value:{type:"number",default:1},revealCursor:{type:"boolean"}}}}]},A.RawDirection={Up:"up",Right:"right",Down:"down",Left:"left"},A.RawUnit={Line:"line",WrappedLine:"wrappedLine",Page:"page",HalfPage:"halfPage",Editor:"editor",Column:"column"};function N(O){let F;switch(O.to){case A.RawDirection.Up:F=1;break;case A.RawDirection.Right:F=2;break;case A.RawDirection.Down:F=3;break;case A.RawDirection.Left:F=4;break;default:return null}let x;switch(O.by){case A.RawUnit.Line:x=1;break;case A.RawUnit.WrappedLine:x=2;break;case A.RawUnit.Page:x=3;break;case A.RawUnit.HalfPage:x=4;break;case A.RawUnit.Editor:x=5;break;case A.RawUnit.Column:x=6;break;default:x=2}const W=Math.floor(O.value||1),V=!!O.revealCursor;return{direction:F,unit:x,value:W,revealCursor:V,select:!!O.select}}A.parse=N})(C||(e.EditorScroll_=C={}));var f;(function(A){const P=function(N){if(!I.isObject(N))return!1;const O=N;return!(!I.isNumber(O.lineNumber)&&!I.isString(O.lineNumber)||!I.isUndefined(O.at)&&!I.isString(O.at))};A.metadata={description:"Reveal the given line at the given logical position",args:[{name:"Reveal line argument object",description:"Property-value pairs that can be passed through this argument:\n * 'lineNumber': A mandatory line number value.\n * 'at': Logical position at which line has to be revealed.\n ```\n 'top', 'center', 'bottom'\n ```\n ",constraint:P,schema:{type:"object",required:["lineNumber"],properties:{lineNumber:{type:["number","string"]},at:{type:"string",enum:["top","center","bottom"]}}}}]},A.RawAtArgument={Top:"top",Center:"center",Bottom:"bottom"}})(f||(e.RevealLine_=f={}));class h{constructor(P){P.addImplementation(1e4,"code-editor",(N,O)=>{const F=N.get(m.ICodeEditorService).getFocusedCodeEditor();return F&&F.hasTextFocus()?this._runEditorCommand(N,F,O):!1}),P.addImplementation(1e3,"generic-dom-input-textarea",(N,O)=>{const F=(0,l.getActiveElement)();return F&&["input","textarea"].indexOf(F.tagName.toLowerCase())>=0?(this.runDOMCommand(F),!0):!1}),P.addImplementation(0,"generic-dom",(N,O)=>{const F=N.get(m.ICodeEditorService).getActiveCodeEditor();return F?(F.focus(),this._runEditorCommand(N,F,O)):!1})}_runEditorCommand(P,N,O){const F=this.runEditorCommand(P,N,O);return F||!0}}var v;(function(A){class P extends u{constructor(ie){super(ie),this._inSelectionMode=ie.inSelectionMode}runCoreEditorCommand(ie,ue){if(!ue.position)return;ie.model.pushStackElement(),ie.setCursorStates(ue.source,3,[n.CursorMoveCommands.moveTo(ie,ie.getPrimaryCursorState(),this._inSelectionMode,ue.position,ue.viewPosition)])&&ue.revealType!==2&&ie.revealAllCursors(ue.source,!0,!0)}}A.MoveTo=(0,y.registerEditorCommand)(new P({id:"_moveTo",inSelectionMode:!1,precondition:void 0})),A.MoveToSelect=(0,y.registerEditorCommand)(new P({id:"_moveToSelect",inSelectionMode:!0,precondition:void 0}));class N extends u{runCoreEditorCommand(ie,ue){ie.model.pushStackElement();const he=this._getColumnSelectResult(ie,ie.getPrimaryCursorState(),ie.getCursorColumnSelectData(),ue);he!==null&&(ie.setCursorStates(ue.source,3,he.viewStates.map(pe=>b.CursorState.fromViewState(pe))),ie.setCursorColumnSelectData({isReal:!0,fromViewLineNumber:he.fromLineNumber,fromViewVisualColumn:he.fromVisualColumn,toViewLineNumber:he.toLineNumber,toViewVisualColumn:he.toVisualColumn}),he.reversed?ie.revealTopMostCursor(ue.source):ie.revealBottomMostCursor(ue.source))}}A.ColumnSelect=(0,y.registerEditorCommand)(new class extends N{constructor(){super({id:"columnSelect",precondition:void 0})}_getColumnSelectResult(J,ie,ue,he){if(typeof he.position>"u"||typeof he.viewPosition>"u"||typeof he.mouseColumn>"u")return null;const pe=J.model.validatePosition(he.position),ae=J.coordinatesConverter.validateViewPosition(new t.Position(he.viewPosition.lineNumber,he.viewPosition.column),pe),ee=he.doColumnSelect?ue.fromViewLineNumber:ae.lineNumber,de=he.doColumnSelect?ue.fromViewVisualColumn:he.mouseColumn-1;return _.ColumnSelection.columnSelect(J.cursorConfig,J,ee,de,ae.lineNumber,he.mouseColumn-1)}}),A.CursorColumnSelectLeft=(0,y.registerEditorCommand)(new class extends N{constructor(){super({id:"cursorColumnSelectLeft",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:3599,linux:{primary:0}}})}_getColumnSelectResult(J,ie,ue,he){return _.ColumnSelection.columnSelectLeft(J.cursorConfig,J,ue)}}),A.CursorColumnSelectRight=(0,y.registerEditorCommand)(new class extends N{constructor(){super({id:"cursorColumnSelectRight",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:3601,linux:{primary:0}}})}_getColumnSelectResult(J,ie,ue,he){return _.ColumnSelection.columnSelectRight(J.cursorConfig,J,ue)}});class O extends N{constructor(ie){super(ie),this._isPaged=ie.isPaged}_getColumnSelectResult(ie,ue,he,pe){return _.ColumnSelection.columnSelectUp(ie.cursorConfig,ie,he,this._isPaged)}}A.CursorColumnSelectUp=(0,y.registerEditorCommand)(new O({isPaged:!1,id:"cursorColumnSelectUp",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:3600,linux:{primary:0}}})),A.CursorColumnSelectPageUp=(0,y.registerEditorCommand)(new O({isPaged:!0,id:"cursorColumnSelectPageUp",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:3595,linux:{primary:0}}}));class F extends N{constructor(ie){super(ie),this._isPaged=ie.isPaged}_getColumnSelectResult(ie,ue,he,pe){return _.ColumnSelection.columnSelectDown(ie.cursorConfig,ie,he,this._isPaged)}}A.CursorColumnSelectDown=(0,y.registerEditorCommand)(new F({isPaged:!1,id:"cursorColumnSelectDown",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:3602,linux:{primary:0}}})),A.CursorColumnSelectPageDown=(0,y.registerEditorCommand)(new F({isPaged:!0,id:"cursorColumnSelectPageDown",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:3596,linux:{primary:0}}}));class x extends u{constructor(){super({id:"cursorMove",precondition:void 0,metadata:n.CursorMove.metadata})}runCoreEditorCommand(ie,ue){const he=n.CursorMove.parse(ue);he&&this._runCursorMove(ie,ue.source,he)}_runCursorMove(ie,ue,he){ie.model.pushStackElement(),ie.setCursorStates(ue,3,x._move(ie,ie.getCursorStates(),he)),ie.revealAllCursors(ue,!0)}static _move(ie,ue,he){const pe=he.select,ae=he.value;switch(he.direction){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:return n.CursorMoveCommands.simpleMove(ie,ue,he.direction,pe,ae,he.unit);case 11:case 13:case 12:case 14:return n.CursorMoveCommands.viewportMove(ie,ue,he.direction,pe,ae);default:return null}}}A.CursorMoveImpl=x,A.CursorMove=(0,y.registerEditorCommand)(new x);class W extends u{constructor(ie){super(ie),this._staticArgs=ie.args}runCoreEditorCommand(ie,ue){let he=this._staticArgs;this._staticArgs.value===-1&&(he={direction:this._staticArgs.direction,unit:this._staticArgs.unit,select:this._staticArgs.select,value:ue.pageSize||ie.cursorConfig.pageSize}),ie.model.pushStackElement(),ie.setCursorStates(ue.source,3,n.CursorMoveCommands.simpleMove(ie,ie.getCursorStates(),he.direction,he.select,he.value,he.unit)),ie.revealAllCursors(ue.source,!0)}}A.CursorLeft=(0,y.registerEditorCommand)(new W({args:{direction:0,unit:0,select:!1,value:1},id:"cursorLeft",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:15,mac:{primary:15,secondary:[288]}}})),A.CursorLeftSelect=(0,y.registerEditorCommand)(new W({args:{direction:0,unit:0,select:!0,value:1},id:"cursorLeftSelect",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:1039}})),A.CursorRight=(0,y.registerEditorCommand)(new W({args:{direction:1,unit:0,select:!1,value:1},id:"cursorRight",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:17,mac:{primary:17,secondary:[292]}}})),A.CursorRightSelect=(0,y.registerEditorCommand)(new W({args:{direction:1,unit:0,select:!0,value:1},id:"cursorRightSelect",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:1041}})),A.CursorUp=(0,y.registerEditorCommand)(new W({args:{direction:2,unit:2,select:!1,value:1},id:"cursorUp",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:16,mac:{primary:16,secondary:[302]}}})),A.CursorUpSelect=(0,y.registerEditorCommand)(new W({args:{direction:2,unit:2,select:!0,value:1},id:"cursorUpSelect",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:1040,secondary:[3088],mac:{primary:1040},linux:{primary:1040}}})),A.CursorPageUp=(0,y.registerEditorCommand)(new W({args:{direction:2,unit:2,select:!1,value:-1},id:"cursorPageUp",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:11}})),A.CursorPageUpSelect=(0,y.registerEditorCommand)(new W({args:{direction:2,unit:2,select:!0,value:-1},id:"cursorPageUpSelect",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:1035}})),A.CursorDown=(0,y.registerEditorCommand)(new W({args:{direction:3,unit:2,select:!1,value:1},id:"cursorDown",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:18,mac:{primary:18,secondary:[300]}}})),A.CursorDownSelect=(0,y.registerEditorCommand)(new W({args:{direction:3,unit:2,select:!0,value:1},id:"cursorDownSelect",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:1042,secondary:[3090],mac:{primary:1042},linux:{primary:1042}}})),A.CursorPageDown=(0,y.registerEditorCommand)(new W({args:{direction:3,unit:2,select:!1,value:-1},id:"cursorPageDown",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:12}})),A.CursorPageDownSelect=(0,y.registerEditorCommand)(new W({args:{direction:3,unit:2,select:!0,value:-1},id:"cursorPageDownSelect",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:1036}})),A.CreateCursor=(0,y.registerEditorCommand)(new class extends u{constructor(){super({id:"createCursor",precondition:void 0})}runCoreEditorCommand(J,ie){if(!ie.position)return;let ue;ie.wholeLine?ue=n.CursorMoveCommands.line(J,J.getPrimaryCursorState(),!1,ie.position,ie.viewPosition):ue=n.CursorMoveCommands.moveTo(J,J.getPrimaryCursorState(),!1,ie.position,ie.viewPosition);const he=J.getCursorStates();if(he.length>1){const pe=ue.modelState?ue.modelState.position:null,ae=ue.viewState?ue.viewState.position:null;for(let ee=0,de=he.length;eeae&&(pe=ae);const ee=new i.Range(pe,1,pe,J.model.getLineMaxColumn(pe));let de=0;if(ue.at)switch(ue.at){case f.RawAtArgument.Top:de=3;break;case f.RawAtArgument.Center:de=1;break;case f.RawAtArgument.Bottom:de=4;break;default:break}const ge=J.coordinatesConverter.convertModelRangeToViewRange(ee);J.revealRange(ie.source,!1,ge,de,0)}}),A.SelectAll=new class extends h{constructor(){super(y.SelectAllCommand)}runDOMCommand(J){k.isFirefox&&(J.focus(),J.select()),J.ownerDocument.execCommand("selectAll")}runEditorCommand(J,ie,ue){const he=ie._getViewModel();he&&this.runCoreEditorCommand(he,ue)}runCoreEditorCommand(J,ie){J.model.pushStackElement(),J.setCursorStates("keyboard",3,[n.CursorMoveCommands.selectAll(J,J.getPrimaryCursorState())])}},A.SetSelection=(0,y.registerEditorCommand)(new class extends u{constructor(){super({id:"setSelection",precondition:void 0})}runCoreEditorCommand(J,ie){ie.selection&&(J.model.pushStackElement(),J.setCursorStates(ie.source,3,[b.CursorState.fromModelSelection(ie.selection)]))}})})(v||(e.CoreNavigationCommands=v={}));const w=g.ContextKeyExpr.and(s.EditorContextKeys.textInputFocus,s.EditorContextKeys.columnSelection);function S(A,P){c.KeybindingsRegistry.registerKeybindingRule({id:A,primary:P,when:w,weight:r+1})}S(v.CursorColumnSelectLeft.id,1039),S(v.CursorColumnSelectRight.id,1041),S(v.CursorColumnSelectUp.id,1040),S(v.CursorColumnSelectPageUp.id,1035),S(v.CursorColumnSelectDown.id,1042),S(v.CursorColumnSelectPageDown.id,1036);function L(A){return A.register(),A}var D;(function(A){class P extends y.EditorCommand{runEditorCommand(O,F,x){const W=F._getViewModel();W&&this.runCoreEditingCommand(F,W,x||{})}}A.CoreEditingCommand=P,A.LineBreakInsert=(0,y.registerEditorCommand)(new class extends P{constructor(){super({id:"lineBreakInsert",precondition:s.EditorContextKeys.writable,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:0,mac:{primary:301}}})}runCoreEditingCommand(N,O,F){N.pushUndoStop(),N.executeCommands(this.id,a.EnterOperation.lineBreakInsert(O.cursorConfig,O.model,O.getCursorStates().map(x=>x.modelState.selection)))}}),A.Outdent=(0,y.registerEditorCommand)(new class extends P{constructor(){super({id:"outdent",precondition:s.EditorContextKeys.writable,kbOpts:{weight:r,kbExpr:g.ContextKeyExpr.and(s.EditorContextKeys.editorTextFocus,s.EditorContextKeys.tabDoesNotMoveFocus),primary:1026}})}runCoreEditingCommand(N,O,F){N.pushUndoStop(),N.executeCommands(this.id,o.TypeOperations.outdent(O.cursorConfig,O.model,O.getCursorStates().map(x=>x.modelState.selection))),N.pushUndoStop()}}),A.Tab=(0,y.registerEditorCommand)(new class extends P{constructor(){super({id:"tab",precondition:s.EditorContextKeys.writable,kbOpts:{weight:r,kbExpr:g.ContextKeyExpr.and(s.EditorContextKeys.editorTextFocus,s.EditorContextKeys.tabDoesNotMoveFocus),primary:2}})}runCoreEditingCommand(N,O,F){N.pushUndoStop(),N.executeCommands(this.id,o.TypeOperations.tab(O.cursorConfig,O.model,O.getCursorStates().map(x=>x.modelState.selection))),N.pushUndoStop()}}),A.DeleteLeft=(0,y.registerEditorCommand)(new class extends P{constructor(){super({id:"deleteLeft",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:1,secondary:[1025],mac:{primary:1,secondary:[1025,294,257]}}})}runCoreEditingCommand(N,O,F){const[x,W]=p.DeleteOperations.deleteLeft(O.getPrevEditOperationType(),O.cursorConfig,O.model,O.getCursorStates().map(V=>V.modelState.selection),O.getCursorAutoClosedCharacters());x&&N.pushUndoStop(),N.executeCommands(this.id,W),O.setPrevEditOperationType(2)}}),A.DeleteRight=(0,y.registerEditorCommand)(new class extends P{constructor(){super({id:"deleteRight",precondition:void 0,kbOpts:{weight:r,kbExpr:s.EditorContextKeys.textInputFocus,primary:20,mac:{primary:20,secondary:[290,276]}}})}runCoreEditingCommand(N,O,F){const[x,W]=p.DeleteOperations.deleteRight(O.getPrevEditOperationType(),O.cursorConfig,O.model,O.getCursorStates().map(V=>V.modelState.selection));x&&N.pushUndoStop(),N.executeCommands(this.id,W),O.setPrevEditOperationType(3)}}),A.Undo=new class extends h{constructor(){super(y.UndoCommand)}runDOMCommand(N){N.ownerDocument.execCommand("undo")}runEditorCommand(N,O,F){if(!(!O.hasModel()||O.getOption(92)===!0))return O.getModel().undo()}},A.Redo=new class extends h{constructor(){super(y.RedoCommand)}runDOMCommand(N){N.ownerDocument.execCommand("redo")}runEditorCommand(N,O,F){if(!(!O.hasModel()||O.getOption(92)===!0))return O.getModel().redo()}}})(D||(e.CoreEditingCommands=D={}));class T extends y.Command{constructor(P,N,O){super({id:P,precondition:void 0,metadata:O}),this._handlerId=N}runCommand(P,N){const O=P.get(m.ICodeEditorService).getFocusedCodeEditor();O&&O.trigger("keyboard",this._handlerId,N)}}function M(A,P){L(new T("default:"+A,A)),L(new T(A,A,P))}M("type",{description:"Type",args:[{name:"args",schema:{type:"object",required:["text"],properties:{text:{type:"string"}}}}]}),M("replacePreviousChar"),M("compositionType"),M("compositionStart"),M("compositionEnd"),M("paste"),M("cut")}),define(ne[725],se([1,0,266,15]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MarkerDecorationsContribution=void 0;let I=class{static{this.ID="editor.contrib.markerDecorations"}constructor(y,m){}dispose(){}};e.MarkerDecorationsContribution=I,e.MarkerDecorationsContribution=I=ke([ce(1,d.IMarkerDecorationsService)],I),(0,k.registerEditorContribution)(I.ID,I,0)}),define(ne[726],se([1,0,214,9,16]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewController=void 0;class E{constructor(m,_,b,p){this.configuration=m,this.viewModel=_,this.userInputEvents=b,this.commandDelegate=p}paste(m,_,b,p){this.commandDelegate.paste(m,_,b,p)}type(m){this.commandDelegate.type(m)}compositionType(m,_,b,p){this.commandDelegate.compositionType(m,_,b,p)}compositionStart(){this.commandDelegate.startComposition()}compositionEnd(){this.commandDelegate.endComposition()}cut(){this.commandDelegate.cut()}setSelection(m){d.CoreNavigationCommands.SetSelection.runCoreEditorCommand(this.viewModel,{source:"keyboard",selection:m})}_validateViewColumn(m){const _=this.viewModel.getLineMinColumn(m.lineNumber);return m.column<_?new k.Position(m.lineNumber,_):m}_hasMulticursorModifier(m){switch(this.configuration.options.get(78)){case"altKey":return m.altKey;case"ctrlKey":return m.ctrlKey;case"metaKey":return m.metaKey;default:return!1}}_hasNonMulticursorModifier(m){switch(this.configuration.options.get(78)){case"altKey":return m.ctrlKey||m.metaKey;case"ctrlKey":return m.altKey||m.metaKey;case"metaKey":return m.ctrlKey||m.altKey;default:return!1}}dispatchMouse(m){const _=this.configuration.options,b=I.isLinux&&_.get(108),p=_.get(22);m.middleButton&&!b?this._columnSelect(m.position,m.mouseColumn,m.inSelectionMode):m.startedOnLineNumbers?this._hasMulticursorModifier(m)?m.inSelectionMode?this._lastCursorLineSelect(m.position,m.revealType):this._createCursor(m.position,!0):m.inSelectionMode?this._lineSelectDrag(m.position,m.revealType):this._lineSelect(m.position,m.revealType):m.mouseDownCount>=4?this._selectAll():m.mouseDownCount===3?this._hasMulticursorModifier(m)?m.inSelectionMode?this._lastCursorLineSelectDrag(m.position,m.revealType):this._lastCursorLineSelect(m.position,m.revealType):m.inSelectionMode?this._lineSelectDrag(m.position,m.revealType):this._lineSelect(m.position,m.revealType):m.mouseDownCount===2?m.onInjectedText||(this._hasMulticursorModifier(m)?this._lastCursorWordSelect(m.position,m.revealType):m.inSelectionMode?this._wordSelectDrag(m.position,m.revealType):this._wordSelect(m.position,m.revealType)):this._hasMulticursorModifier(m)?this._hasNonMulticursorModifier(m)||(m.shiftKey?this._columnSelect(m.position,m.mouseColumn,!0):m.inSelectionMode?this._lastCursorMoveToSelect(m.position,m.revealType):this._createCursor(m.position,!1)):m.inSelectionMode?m.altKey?this._columnSelect(m.position,m.mouseColumn,!0):p?this._columnSelect(m.position,m.mouseColumn,!0):this._moveToSelect(m.position,m.revealType):this.moveTo(m.position,m.revealType)}_usualArgs(m,_){return m=this._validateViewColumn(m),{source:"mouse",position:this._convertViewToModelPosition(m),viewPosition:m,revealType:_}}moveTo(m,_){d.CoreNavigationCommands.MoveTo.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_moveToSelect(m,_){d.CoreNavigationCommands.MoveToSelect.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_columnSelect(m,_,b){m=this._validateViewColumn(m),d.CoreNavigationCommands.ColumnSelect.runCoreEditorCommand(this.viewModel,{source:"mouse",position:this._convertViewToModelPosition(m),viewPosition:m,mouseColumn:_,doColumnSelect:b})}_createCursor(m,_){m=this._validateViewColumn(m),d.CoreNavigationCommands.CreateCursor.runCoreEditorCommand(this.viewModel,{source:"mouse",position:this._convertViewToModelPosition(m),viewPosition:m,wholeLine:_})}_lastCursorMoveToSelect(m,_){d.CoreNavigationCommands.LastCursorMoveToSelect.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_wordSelect(m,_){d.CoreNavigationCommands.WordSelect.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_wordSelectDrag(m,_){d.CoreNavigationCommands.WordSelectDrag.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_lastCursorWordSelect(m,_){d.CoreNavigationCommands.LastCursorWordSelect.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_lineSelect(m,_){d.CoreNavigationCommands.LineSelect.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_lineSelectDrag(m,_){d.CoreNavigationCommands.LineSelectDrag.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_lastCursorLineSelect(m,_){d.CoreNavigationCommands.LastCursorLineSelect.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_lastCursorLineSelectDrag(m,_){d.CoreNavigationCommands.LastCursorLineSelectDrag.runCoreEditorCommand(this.viewModel,this._usualArgs(m,_))}_selectAll(){d.CoreNavigationCommands.SelectAll.runCoreEditorCommand(this.viewModel,{source:"mouse"})}_convertViewToModelPosition(m){return this.viewModel.coordinatesConverter.convertViewPositionToModelPosition(m)}emitKeyDown(m){this.userInputEvents.emitKeyDown(m)}emitKeyUp(m){this.userInputEvents.emitKeyUp(m)}emitContextMenu(m){this.userInputEvents.emitContextMenu(m)}emitMouseMove(m){this.userInputEvents.emitMouseMove(m)}emitMouseLeave(m){this.userInputEvents.emitMouseLeave(m)}emitMouseUp(m){this.userInputEvents.emitMouseUp(m)}emitMouseDown(m){this.userInputEvents.emitMouseDown(m)}emitMouseDrag(m){this.userInputEvents.emitMouseDrag(m)}emitMouseDrop(m){this.userInputEvents.emitMouseDrop(m)}emitMouseDropCanceled(){this.userInputEvents.emitMouseDropCanceled()}emitMouseWheel(m){this.userInputEvents.emitMouseWheel(m)}}e.ViewController=E}),define(ne[215],se([1,0,49,7,6,54,55,105,100,63]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";var p;Object.defineProperty(e,"__esModule",{value:!0}),e.WorkerBasedDocumentDiffProvider=e.WorkerBasedDiffProviderFactoryService=e.IDiffProviderFactoryService=void 0,e.IDiffProviderFactoryService=(0,k.createDecorator)("diffProviderFactoryService");let n=class{constructor(i){this.instantiationService=i}createDiffProvider(i){return this.instantiationService.createInstance(o,i)}};e.WorkerBasedDiffProviderFactoryService=n,e.WorkerBasedDiffProviderFactoryService=n=ke([ce(0,k.IInstantiationService)],n),(0,d.registerSingleton)(e.IDiffProviderFactoryService,n,1);let o=class{static{p=this}static{this.diffCache=new Map}constructor(i,s,g){this.editorWorkerService=s,this.telemetryService=g,this.onDidChangeEventEmitter=new I.Emitter,this.onDidChange=this.onDidChangeEventEmitter.event,this.diffAlgorithm="advanced",this.diffAlgorithmOnDidChangeSubscription=void 0,this.setOptions(i)}dispose(){this.diffAlgorithmOnDidChangeSubscription?.dispose()}async computeDiff(i,s,g,c){if(typeof this.diffAlgorithm!="string")return this.diffAlgorithm.computeDiff(i,s,g,c);if(i.isDisposed()||s.isDisposed())return{changes:[],identical:!0,quitEarly:!1,moves:[]};if(i.getLineCount()===1&&i.getLineMaxColumn(1)===1)return s.getLineCount()===1&&s.getLineMaxColumn(1)===1?{changes:[],identical:!0,quitEarly:!1,moves:[]}:{changes:[new m.DetailedLineRangeMapping(new y.LineRange(1,2),new y.LineRange(1,s.getLineCount()+1),[new m.RangeMapping(i.getFullModelRange(),s.getFullModelRange())])],identical:!1,quitEarly:!1,moves:[]};const l=JSON.stringify([i.uri.toString(),s.uri.toString()]),a=JSON.stringify([i.id,s.id,i.getAlternativeVersionId(),s.getAlternativeVersionId(),JSON.stringify(g)]),r=p.diffCache.get(l);if(r&&r.context===a)return r.result;const u=E.StopWatch.create(),C=await this.editorWorkerService.computeDiff(i.uri,s.uri,g,this.diffAlgorithm),f=u.elapsed();if(this.telemetryService.publicLog2("diffEditor.computeDiff",{timeMs:f,timedOut:C?.quitEarly??!0,detectedMoves:g.computeMoves?C?.moves.length??0:-1}),c.isCancellationRequested)return{changes:[],identical:!1,quitEarly:!0,moves:[]};if(!C)throw new Error("no diff result available");return p.diffCache.size>10&&p.diffCache.delete(p.diffCache.keys().next().value),p.diffCache.set(l,{result:C,context:a}),C}setOptions(i){let s=!1;i.diffAlgorithm&&this.diffAlgorithm!==i.diffAlgorithm&&(this.diffAlgorithmOnDidChangeSubscription?.dispose(),this.diffAlgorithmOnDidChangeSubscription=void 0,this.diffAlgorithm=i.diffAlgorithm,typeof i.diffAlgorithm!="string"&&(this.diffAlgorithmOnDidChangeSubscription=i.diffAlgorithm.onDidChange(()=>this.onDidChangeEventEmitter.fire())),s=!0),s&&this.onDidChangeEventEmitter.fire()}};e.WorkerBasedDocumentDiffProvider=o,e.WorkerBasedDocumentDiffProvider=o=p=ke([ce(1,_.IEditorWorkerService),ce(2,b.ITelemetryService)],o)}),define(ne[407],se([1,0,14,18,2,21,215,88,171,55,317,105,200,319,315,19,13,90]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UnchangedRegion=e.DiffMapping=e.DiffState=e.DiffEditorViewModel=void 0;let l=class extends I.Disposable{setActiveMovedText(S){this._activeMovedText.set(S,void 0)}constructor(S,L,D){super(),this.model=S,this._options=L,this._diffProviderFactoryService=D,this._isDiffUpToDate=(0,E.observableValue)(this,!1),this.isDiffUpToDate=this._isDiffUpToDate,this._diff=(0,E.observableValue)(this,void 0),this.diff=this._diff,this._unchangedRegions=(0,E.observableValue)(this,void 0),this.unchangedRegions=(0,E.derived)(this,P=>this._options.hideUnchangedRegions.read(P)?this._unchangedRegions.read(P)?.regions??[]:((0,E.transaction)(N=>{for(const O of this._unchangedRegions.get()?.regions||[])O.collapseAll(N)}),[])),this.movedTextToCompare=(0,E.observableValue)(this,void 0),this._activeMovedText=(0,E.observableValue)(this,void 0),this._hoveredMovedText=(0,E.observableValue)(this,void 0),this.activeMovedText=(0,E.derived)(this,P=>this.movedTextToCompare.read(P)??this._hoveredMovedText.read(P)??this._activeMovedText.read(P)),this._cancellationTokenSource=new k.CancellationTokenSource,this._diffProvider=(0,E.derived)(this,P=>{const N=this._diffProviderFactoryService.createDiffProvider({diffAlgorithm:this._options.diffAlgorithm.read(P)}),O=(0,E.observableSignalFromEvent)("onDidChange",N.onDidChange);return{diffProvider:N,onChangeSignal:O}}),this._register((0,I.toDisposable)(()=>this._cancellationTokenSource.cancel()));const T=(0,E.observableSignal)("contentChangedSignal"),M=this._register(new d.RunOnceScheduler(()=>T.trigger(void 0),200));this._register((0,E.autorun)(P=>{const N=this._unchangedRegions.read(P);if(!N||N.regions.some(q=>q.isDragged.read(P)))return;const O=N.originalDecorationIds.map(q=>S.original.getDecorationRange(q)).map(q=>q?b.LineRange.fromRangeInclusive(q):void 0),F=N.modifiedDecorationIds.map(q=>S.modified.getDecorationRange(q)).map(q=>q?b.LineRange.fromRangeInclusive(q):void 0),x=N.regions.map((q,H)=>!O[H]||!F[H]?void 0:new f(O[H].startLineNumber,F[H].startLineNumber,O[H].length,q.visibleLineCountTop.read(P),q.visibleLineCountBottom.read(P))).filter(s.isDefined),W=[];let V=!1;for(const q of(0,g.groupAdjacentBy)(x,(H,z)=>H.getHiddenModifiedRange(P).endLineNumberExclusive===z.getHiddenModifiedRange(P).startLineNumber))if(q.length>1){V=!0;const H=q.reduce((U,j)=>U+j.lineCount,0),z=new f(q[0].originalLineNumber,q[0].modifiedLineNumber,H,q[0].visibleLineCountTop.get(),q[q.length-1].visibleLineCountBottom.get());W.push(z)}else W.push(q[0]);if(V){const q=S.original.deltaDecorations(N.originalDecorationIds,W.map(z=>({range:z.originalUnchangedRange.toInclusiveRange(),options:{description:"unchanged"}}))),H=S.modified.deltaDecorations(N.modifiedDecorationIds,W.map(z=>({range:z.modifiedUnchangedRange.toInclusiveRange(),options:{description:"unchanged"}})));(0,E.transaction)(z=>{this._unchangedRegions.set({regions:W,originalDecorationIds:q,modifiedDecorationIds:H},z)})}}));const A=(P,N,O)=>{const F=f.fromDiffs(P.changes,S.original.getLineCount(),S.modified.getLineCount(),this._options.hideUnchangedRegionsMinimumLineCount.read(O),this._options.hideUnchangedRegionsContextLineCount.read(O));let x;const W=this._unchangedRegions.get();if(W){const z=W.originalDecorationIds.map(G=>S.original.getDecorationRange(G)).map(G=>G?b.LineRange.fromRangeInclusive(G):void 0),U=W.modifiedDecorationIds.map(G=>S.modified.getDecorationRange(G)).map(G=>G?b.LineRange.fromRangeInclusive(G):void 0);let Y=(0,m.filterWithPrevious)(W.regions.map((G,K)=>{if(!z[K]||!U[K])return;const R=z[K].length;return new f(z[K].startLineNumber,U[K].startLineNumber,R,Math.min(G.visibleLineCountTop.get(),R),Math.min(G.visibleLineCountBottom.get(),R-G.visibleLineCountTop.get()))}).filter(s.isDefined),(G,K)=>!K||G.modifiedLineNumber>=K.modifiedLineNumber+K.lineCount&&G.originalLineNumber>=K.originalLineNumber+K.lineCount).map(G=>new n.LineRangeMapping(G.getHiddenOriginalRange(O),G.getHiddenModifiedRange(O)));Y=n.LineRangeMapping.clip(Y,b.LineRange.ofLength(1,S.original.getLineCount()),b.LineRange.ofLength(1,S.modified.getLineCount())),x=n.LineRangeMapping.inverse(Y,S.original.getLineCount(),S.modified.getLineCount())}const V=[];if(x)for(const z of F){const U=x.filter(j=>j.original.intersectsStrict(z.originalUnchangedRange)&&j.modified.intersectsStrict(z.modifiedUnchangedRange));V.push(...z.setVisibleRanges(U,N))}else V.push(...F);const q=S.original.deltaDecorations(W?.originalDecorationIds||[],V.map(z=>({range:z.originalUnchangedRange.toInclusiveRange(),options:{description:"unchanged"}}))),H=S.modified.deltaDecorations(W?.modifiedDecorationIds||[],V.map(z=>({range:z.modifiedUnchangedRange.toInclusiveRange(),options:{description:"unchanged"}})));this._unchangedRegions.set({regions:V,originalDecorationIds:q,modifiedDecorationIds:H},N)};this._register(S.modified.onDidChangeContent(P=>{if(this._diff.get()){const O=o.TextEditInfo.fromModelContentChanges(P.changes),F=(this._lastDiff,S.original,S.modified,void 0);F&&(this._lastDiff=F,(0,E.transaction)(x=>{this._diff.set(u.fromDiffResult(this._lastDiff),x),A(F,x);const W=this.movedTextToCompare.get();this.movedTextToCompare.set(W?this._lastDiff.moves.find(V=>V.lineRangeMapping.modified.intersect(W.lineRangeMapping.modified)):void 0,x)}))}this._isDiffUpToDate.set(!1,void 0),M.schedule()})),this._register(S.original.onDidChangeContent(P=>{if(this._diff.get()){const O=o.TextEditInfo.fromModelContentChanges(P.changes),F=(this._lastDiff,S.original,S.modified,void 0);F&&(this._lastDiff=F,(0,E.transaction)(x=>{this._diff.set(u.fromDiffResult(this._lastDiff),x),A(F,x);const W=this.movedTextToCompare.get();this.movedTextToCompare.set(W?this._lastDiff.moves.find(V=>V.lineRangeMapping.modified.intersect(W.lineRangeMapping.modified)):void 0,x)}))}this._isDiffUpToDate.set(!1,void 0),M.schedule()})),this._register((0,E.autorunWithStore)(async(P,N)=>{this._options.hideUnchangedRegionsMinimumLineCount.read(P),this._options.hideUnchangedRegionsContextLineCount.read(P),M.cancel(),T.read(P);const O=this._diffProvider.read(P);O.onChangeSignal.read(P),(0,_.readHotReloadableExport)(p.DefaultLinesDiffComputer,P),(0,_.readHotReloadableExport)(i.optimizeSequenceDiffs,P),this._isDiffUpToDate.set(!1,void 0);let F=[];N.add(S.original.onDidChangeContent(V=>{const q=o.TextEditInfo.fromModelContentChanges(V.changes);F=(0,t.combineTextEditInfos)(F,q)}));let x=[];N.add(S.modified.onDidChangeContent(V=>{const q=o.TextEditInfo.fromModelContentChanges(V.changes);x=(0,t.combineTextEditInfos)(x,q)}));let W=await O.diffProvider.computeDiff(S.original,S.modified,{ignoreTrimWhitespace:this._options.ignoreTrimWhitespace.read(P),maxComputationTimeMs:this._options.maxComputationTimeMs.read(P),computeMoves:this._options.showMoves.read(P)},this._cancellationTokenSource.token);this._cancellationTokenSource.token.isCancellationRequested||S.original.isDisposed()||S.modified.isDisposed()||(W=a(W,S.original,S.modified),W=(S.original,S.modified,void 0)??W,W=(S.original,S.modified,void 0)??W,(0,E.transaction)(V=>{A(W,V),this._lastDiff=W;const q=u.fromDiffResult(W);this._diff.set(q,V),this._isDiffUpToDate.set(!0,V);const H=this.movedTextToCompare.get();this.movedTextToCompare.set(H?this._lastDiff.moves.find(z=>z.lineRangeMapping.modified.intersect(H.lineRangeMapping.modified)):void 0,V)}))}))}ensureModifiedLineIsVisible(S,L,D){if(this.diff.get()?.mappings.length===0)return;const T=this._unchangedRegions.get()?.regions||[];for(const M of T)if(M.getHiddenModifiedRange(void 0).contains(S)){M.showModifiedLine(S,L,D);return}}ensureOriginalLineIsVisible(S,L,D){if(this.diff.get()?.mappings.length===0)return;const T=this._unchangedRegions.get()?.regions||[];for(const M of T)if(M.getHiddenOriginalRange(void 0).contains(S)){M.showOriginalLine(S,L,D);return}}async waitForDiff(){await(0,E.waitForState)(this.isDiffUpToDate,S=>S)}serializeState(){return{collapsedRegions:this._unchangedRegions.get()?.regions.map(L=>({range:L.getHiddenModifiedRange(void 0).serialize()}))}}restoreSerializedState(S){const L=S.collapsedRegions?.map(T=>b.LineRange.deserialize(T.range)),D=this._unchangedRegions.get();!D||!L||(0,E.transaction)(T=>{for(const M of D.regions)for(const A of L)if(M.modifiedUnchangedRange.intersect(A)){M.setHiddenModifiedRange(A,T);break}})}};e.DiffEditorViewModel=l,e.DiffEditorViewModel=l=ke([ce(2,y.IDiffProviderFactoryService)],l);function a(w,S,L){return{changes:w.changes.map(D=>new n.DetailedLineRangeMapping(D.original,D.modified,D.innerChanges?D.innerChanges.map(T=>r(T,S,L)):void 0)),moves:w.moves,identical:w.identical,quitEarly:w.quitEarly}}function r(w,S,L){let D=w.originalRange,T=w.modifiedRange;return D.startColumn===1&&T.startColumn===1&&(D.endColumn!==1||T.endColumn!==1)&&D.endColumn===S.getLineMaxColumn(D.endLineNumber)&&T.endColumn===L.getLineMaxColumn(T.endLineNumber)&&D.endLineNumbernew C(L)),S.moves||[],S.identical,S.quitEarly)}constructor(S,L,D,T){this.mappings=S,this.movedTexts=L,this.identical=D,this.quitEarly=T}}e.DiffState=u;class C{constructor(S){this.lineRangeMapping=S}}e.DiffMapping=C;class f{static fromDiffs(S,L,D,T,M){const A=n.DetailedLineRangeMapping.inverse(S,L,D),P=[];for(const N of A){let O=N.original.startLineNumber,F=N.modified.startLineNumber,x=N.original.length;const W=O===1&&F===1,V=O+x===L+1&&F+x===D+1;(W||V)&&x>=M+T?(W&&!V&&(x-=M),V&&!W&&(O+=M,F+=M,x-=M),P.push(new f(O,F,x,0,0))):x>=M*2+T&&(O+=M,F+=M,x-=M*2,P.push(new f(O,F,x,0,0)))}return P}get originalUnchangedRange(){return b.LineRange.ofLength(this.originalLineNumber,this.lineCount)}get modifiedUnchangedRange(){return b.LineRange.ofLength(this.modifiedLineNumber,this.lineCount)}constructor(S,L,D,T,M){this.originalLineNumber=S,this.modifiedLineNumber=L,this.lineCount=D,this._visibleLineCountTop=(0,E.observableValue)(this,0),this.visibleLineCountTop=this._visibleLineCountTop,this._visibleLineCountBottom=(0,E.observableValue)(this,0),this.visibleLineCountBottom=this._visibleLineCountBottom,this._shouldHideControls=(0,E.derived)(this,N=>this.visibleLineCountTop.read(N)+this.visibleLineCountBottom.read(N)===this.lineCount&&!this.isDragged.read(N)),this.isDragged=(0,E.observableValue)(this,void 0);const A=Math.max(Math.min(T,this.lineCount),0),P=Math.max(Math.min(M,this.lineCount-T),0);(0,c.softAssert)(T===A),(0,c.softAssert)(M===P),this._visibleLineCountTop.set(A,void 0),this._visibleLineCountBottom.set(P,void 0)}setVisibleRanges(S,L){const D=[],T=new b.LineRangeSet(S.map(N=>N.modified)).subtractFrom(this.modifiedUnchangedRange);let M=this.originalLineNumber,A=this.modifiedLineNumber;const P=this.modifiedLineNumber+this.lineCount;if(T.ranges.length===0)this.showAll(L),D.push(this);else{let N=0;for(const O of T.ranges){const F=N===T.ranges.length-1;N++;const x=(F?P:O.endLineNumberExclusive)-A,W=new f(M,A,x,0,0);W.setHiddenModifiedRange(O,L),D.push(W),M=W.originalUnchangedRange.endLineNumberExclusive,A=W.modifiedUnchangedRange.endLineNumberExclusive}}return D}shouldHideControls(S){return this._shouldHideControls.read(S)}getHiddenOriginalRange(S){return b.LineRange.ofLength(this.originalLineNumber+this._visibleLineCountTop.read(S),this.lineCount-this._visibleLineCountTop.read(S)-this._visibleLineCountBottom.read(S))}getHiddenModifiedRange(S){return b.LineRange.ofLength(this.modifiedLineNumber+this._visibleLineCountTop.read(S),this.lineCount-this._visibleLineCountTop.read(S)-this._visibleLineCountBottom.read(S))}setHiddenModifiedRange(S,L){const D=S.startLineNumber-this.modifiedLineNumber,T=this.modifiedLineNumber+this.lineCount-S.endLineNumberExclusive;this.setState(D,T,L)}getMaxVisibleLineCountTop(){return this.lineCount-this._visibleLineCountBottom.get()}getMaxVisibleLineCountBottom(){return this.lineCount-this._visibleLineCountTop.get()}showMoreAbove(S=10,L){const D=this.getMaxVisibleLineCountTop();this._visibleLineCountTop.set(Math.min(this._visibleLineCountTop.get()+S,D),L)}showMoreBelow(S=10,L){const D=this.lineCount-this._visibleLineCountTop.get();this._visibleLineCountBottom.set(Math.min(this._visibleLineCountBottom.get()+S,D),L)}showAll(S){this._visibleLineCountBottom.set(this.lineCount-this._visibleLineCountTop.get(),S)}showModifiedLine(S,L,D){const T=S+1-(this.modifiedLineNumber+this._visibleLineCountTop.get()),M=this.modifiedLineNumber-this._visibleLineCountBottom.get()+this.lineCount-S;L===0&&Tthis.selectionAnchorSetContextKey.reset())}setSelectionAnchor(){if(this.editor.hasModel()){const c=this.editor.getPosition();this.editor.changeDecorations(l=>{this.decorationId&&l.removeDecoration(this.decorationId),this.decorationId=l.addDecoration(y.Selection.fromPositions(c,c),{description:"selection-anchor",stickiness:1,hoverMessage:new k.MarkdownString().appendText((0,_.localize)(710,"Selection Anchor")),className:"selection-anchor"})}),this.selectionAnchorSetContextKey.set(!!this.decorationId),(0,d.alert)((0,_.localize)(711,"Anchor set at {0}:{1}",c.lineNumber,c.column))}}goToSelectionAnchor(){if(this.editor.hasModel()&&this.decorationId){const c=this.editor.getModel().getDecorationRange(this.decorationId);c&&this.editor.setPosition(c.getStartPosition())}}selectFromAnchorToCursor(){if(this.editor.hasModel()&&this.decorationId){const c=this.editor.getModel().getDecorationRange(this.decorationId);if(c){const l=this.editor.getPosition();this.editor.setSelection(y.Selection.fromPositions(c.getStartPosition(),l)),this.cancelSelectionAnchor()}}}cancelSelectionAnchor(){if(this.decorationId){const c=this.decorationId;this.editor.changeDecorations(l=>{l.removeDecoration(c),this.decorationId=void 0}),this.selectionAnchorSetContextKey.set(!1)}}dispose(){this.cancelSelectionAnchor(),this.modelChangeListener.dispose()}};n=p=ke([ce(1,b.IContextKeyService)],n);class o extends E.EditorAction{constructor(){super({id:"editor.action.setSelectionAnchor",label:(0,_.localize)(712,"Set Selection Anchor"),alias:"Set Selection Anchor",precondition:void 0,kbOpts:{kbExpr:m.EditorContextKeys.editorTextFocus,primary:(0,I.KeyChord)(2089,2080),weight:100}})}async run(c,l){n.get(l)?.setSelectionAnchor()}}class t extends E.EditorAction{constructor(){super({id:"editor.action.goToSelectionAnchor",label:(0,_.localize)(713,"Go to Selection Anchor"),alias:"Go to Selection Anchor",precondition:e.SelectionAnchorSet})}async run(c,l){n.get(l)?.goToSelectionAnchor()}}class i extends E.EditorAction{constructor(){super({id:"editor.action.selectFromAnchorToCursor",label:(0,_.localize)(714,"Select from Anchor to Cursor"),alias:"Select from Anchor to Cursor",precondition:e.SelectionAnchorSet,kbOpts:{kbExpr:m.EditorContextKeys.editorTextFocus,primary:(0,I.KeyChord)(2089,2089),weight:100}})}async run(c,l){n.get(l)?.selectFromAnchorToCursor()}}class s extends E.EditorAction{constructor(){super({id:"editor.action.cancelSelectionAnchor",label:(0,_.localize)(715,"Cancel Selection Anchor"),alias:"Cancel Selection Anchor",precondition:e.SelectionAnchorSet,kbOpts:{kbExpr:m.EditorContextKeys.editorTextFocus,primary:9,weight:100}})}async run(c,l){n.get(l)?.cancelSelectionAnchor()}}(0,E.registerEditorContribution)(n.ID,n,4),(0,E.registerEditorAction)(o),(0,E.registerEditorAction)(t),(0,E.registerEditorAction)(i),(0,E.registerEditorAction)(s)}),define(ne[728],se([1,0,15,20,607,3]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class y extends d.EditorAction{constructor(p,n){super(n),this.left=p}run(p,n){if(!n.hasModel())return;const o=[],t=n.getSelections();for(const i of t)o.push(new I.MoveCaretCommand(i,this.left));n.pushUndoStop(),n.executeCommands(this.id,o),n.pushUndoStop()}}class m extends y{constructor(){super(!0,{id:"editor.action.moveCarretLeftAction",label:E.localize(722,"Move Selected Text Left"),alias:"Move Selected Text Left",precondition:k.EditorContextKeys.writable})}}class _ extends y{constructor(){super(!1,{id:"editor.action.moveCarretRightAction",label:E.localize(723,"Move Selected Text Right"),alias:"Move Selected Text Right",precondition:k.EditorContextKeys.writable})}}(0,d.registerEditorAction)(m),(0,d.registerEditorAction)(_)}),define(ne[729],se([1,0,15,146,233,4,20,3]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class _ extends d.EditorAction{constructor(){super({id:"editor.action.transposeLetters",label:m.localize(724,"Transpose Letters"),alias:"Transpose Letters",precondition:y.EditorContextKeys.writable,kbOpts:{kbExpr:y.EditorContextKeys.textInputFocus,primary:0,mac:{primary:306},weight:100}})}run(p,n){if(!n.hasModel())return;const o=n.getModel(),t=[],i=n.getSelections();for(const s of i){if(!s.isEmpty())continue;const g=s.startLineNumber,c=s.startColumn,l=o.getLineMaxColumn(g);if(g===1&&(c===1||c===2&&l===2))continue;const a=c===l?s.getPosition():I.MoveOperations.rightPosition(o,s.getPosition().lineNumber,s.getPosition().column),r=I.MoveOperations.leftPosition(o,a),u=I.MoveOperations.leftPosition(o,r),C=o.getValueInRange(E.Range.fromPositions(u,r)),f=o.getValueInRange(E.Range.fromPositions(r,a)),h=E.Range.fromPositions(u,a);t.push(new k.ReplaceCommand(h,f+C))}t.length>0&&(n.pushUndoStop(),n.executeCommands(this.id,t),n.pushUndoStop())}}(0,d.registerEditorAction)(_)}),define(ne[730],se([1,0,72,15,4,20,36,333,609,3,29]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class n extends k.EditorAction{constructor(c,l){super(l),this._type=c}run(c,l){const a=c.get(y.ILanguageConfigurationService);if(!l.hasModel())return;const r=l.getModel(),u=[],C=r.getOptions(),f=l.getOption(23),h=l.getSelections().map((w,S)=>({selection:w,index:S,ignoreFirstLine:!1}));h.sort((w,S)=>I.Range.compareRangesUsingStarts(w.selection,S.selection));let v=h[0];for(let w=1;w{this._undoStack=[],this._redoStack=[]})),this._register(o.onDidChangeModelContent(t=>{this._undoStack=[],this._redoStack=[]})),this._register(o.onDidChangeCursorSelection(t=>{if(this._isCursorUndoRedo||!t.oldSelections||t.oldModelVersionId!==t.modelVersionId)return;const i=new y(t.oldSelections);this._undoStack.length>0&&this._undoStack[this._undoStack.length-1].cursorState.equals(i)||(this._undoStack.push(new m(i,o.getScrollTop(),o.getScrollLeft())),this._redoStack=[],this._undoStack.length>50&&this._undoStack.shift())}))}cursorUndo(){!this._editor.hasModel()||this._undoStack.length===0||(this._redoStack.push(new m(new y(this._editor.getSelections()),this._editor.getScrollTop(),this._editor.getScrollLeft())),this._applyState(this._undoStack.pop()))}cursorRedo(){!this._editor.hasModel()||this._redoStack.length===0||(this._undoStack.push(new m(new y(this._editor.getSelections()),this._editor.getScrollTop(),this._editor.getScrollLeft())),this._applyState(this._redoStack.pop()))}_applyState(o){this._isCursorUndoRedo=!0,this._editor.setSelections(o.cursorState.selections),this._editor.setScrollPosition({scrollTop:o.scrollTop,scrollLeft:o.scrollLeft}),this._isCursorUndoRedo=!1}}e.CursorUndoRedoController=_;class b extends k.EditorAction{constructor(){super({id:"cursorUndo",label:E.localize(821,"Cursor Undo"),alias:"Cursor Undo",precondition:void 0,kbOpts:{kbExpr:I.EditorContextKeys.textInputFocus,primary:2099,weight:100}})}run(o,t,i){_.get(t)?.cursorUndo()}}e.CursorUndo=b;class p extends k.EditorAction{constructor(){super({id:"cursorRedo",label:E.localize(822,"Cursor Redo"),alias:"Cursor Redo",precondition:void 0})}run(o,t,i){_.get(t)?.cursorRedo()}}e.CursorRedo=p,(0,k.registerEditorContribution)(_.ID,_,0),(0,k.registerEditorAction)(b),(0,k.registerEditorAction)(p)}),define(ne[732],se([1,0,15,12,18,73,7,49,3]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorKeybindingCancellationTokenSource=void 0;const b=(0,y.createDecorator)("IEditorCancelService"),p=new k.RawContextKey("cancellableOperation",!1,(0,_.localize)(847,"Whether the editor runs a cancellable operation, e.g. like 'Peek References'"));(0,m.registerSingleton)(b,class{constructor(){this._tokens=new WeakMap}add(o,t){let i=this._tokens.get(o);i||(i=o.invokeWithinContext(g=>{const c=p.bindTo(g.get(k.IContextKeyService)),l=new E.LinkedList;return{key:c,tokens:l}}),this._tokens.set(o,i));let s;return i.key.set(!0),s=i.tokens.push(t),()=>{s&&(s(),i.key.set(!i.tokens.isEmpty()),s=void 0)}}cancel(o){const t=this._tokens.get(o);if(!t)return;const i=t.tokens.pop();i&&(i.cancel(),t.key.set(!t.tokens.isEmpty()))}},1);class n extends I.CancellationTokenSource{constructor(t,i){super(i),this.editor=t,this._unregister=t.invokeWithinContext(s=>s.get(b).add(t,this))}dispose(){this._unregister(),super.dispose()}}e.EditorKeybindingCancellationTokenSource=n,(0,d.registerEditorCommand)(new class extends d.EditorCommand{constructor(){super({id:"editor.cancelOperation",kbOpts:{weight:100,primary:9},precondition:p})}runEditorCommand(o,t){o.get(b).cancel(t)}})}),define(ne[122],se([1,0,11,4,18,2,732]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TextModelCancellationTokenSource=e.EditorStateCancellationTokenSource=e.EditorState=void 0;class m{constructor(n,o){if(this.flags=o,this.flags&1){const t=n.getModel();this.modelVersionId=t?d.format("{0}#{1}",t.uri.toString(),t.getVersionId()):null}else this.modelVersionId=null;this.flags&4?this.position=n.getPosition():this.position=null,this.flags&2?this.selection=n.getSelection():this.selection=null,this.flags&8?(this.scrollLeft=n.getScrollLeft(),this.scrollTop=n.getScrollTop()):(this.scrollLeft=-1,this.scrollTop=-1)}_equals(n){if(!(n instanceof m))return!1;const o=n;return!(this.modelVersionId!==o.modelVersionId||this.scrollLeft!==o.scrollLeft||this.scrollTop!==o.scrollTop||!this.position&&o.position||this.position&&!o.position||this.position&&o.position&&!this.position.equals(o.position)||!this.selection&&o.selection||this.selection&&!o.selection||this.selection&&o.selection&&!this.selection.equalsRange(o.selection))}validate(n){return this._equals(new m(n,this.flags))}}e.EditorState=m;class _ extends y.EditorKeybindingCancellationTokenSource{constructor(n,o,t,i){super(n,i),this._listener=new E.DisposableStore,o&4&&this._listener.add(n.onDidChangeCursorPosition(s=>{(!t||!k.Range.containsPosition(t,s.position))&&this.cancel()})),o&2&&this._listener.add(n.onDidChangeCursorSelection(s=>{(!t||!k.Range.containsRange(t,s.selection))&&this.cancel()})),o&8&&this._listener.add(n.onDidScrollChange(s=>this.cancel())),o&1&&(this._listener.add(n.onDidChangeModel(s=>this.cancel())),this._listener.add(n.onDidChangeModelContent(s=>this.cancel())))}dispose(){this._listener.dispose(),super.dispose()}}e.EditorStateCancellationTokenSource=_;class b extends I.CancellationTokenSource{constructor(n,o){super(o),this._listener=n.onDidChangeContent(()=>this.cancel())}dispose(){this._listener.dispose(),super.dispose()}}e.TextModelCancellationTokenSource=b}),define(ne[157],se([1,0,13,18,8,2,22,152,4,23,17,51,122,3,24,50,96,63,134,91]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ApplyCodeActionReason=e.fixAllCommandId=e.organizeImportsCommandId=e.sourceActionCommandId=e.refactorCommandId=e.autoFixCommandId=e.quickFixCommandId=e.codeActionCommandId=void 0,e.getCodeActions=C,e.applyCodeAction=S,e.codeActionCommandId="editor.action.codeAction",e.quickFixCommandId="editor.action.quickFix",e.autoFixCommandId="editor.action.autoFix",e.refactorCommandId="editor.action.refactor",e.sourceActionCommandId="editor.action.sourceAction",e.organizeImportsCommandId="editor.action.organizeImports",e.fixAllCommandId="editor.action.fixAll";class r extends E.Disposable{static codeActionsPreferredComparator(T,M){return T.isPreferred&&!M.isPreferred?-1:!T.isPreferred&&M.isPreferred?1:0}static codeActionsComparator({action:T},{action:M}){return T.isAI&&!M.isAI?1:!T.isAI&&M.isAI?-1:(0,d.isNonEmptyArray)(T.diagnostics)?(0,d.isNonEmptyArray)(M.diagnostics)?r.codeActionsPreferredComparator(T,M):-1:(0,d.isNonEmptyArray)(M.diagnostics)?1:r.codeActionsPreferredComparator(T,M)}constructor(T,M,A){super(),this.documentation=M,this._register(A),this.allActions=[...T].sort(r.codeActionsComparator),this.validActions=this.allActions.filter(({action:P})=>!P.disabled)}get hasAutoFix(){return this.validActions.some(({action:T})=>!!T.kind&&l.CodeActionKind.QuickFix.contains(new a.HierarchicalKind(T.kind))&&!!T.isPreferred)}get hasAIFix(){return this.validActions.some(({action:T})=>!!T.isAI)}get allAIFixes(){return this.validActions.every(({action:T})=>!!T.isAI)}}const u={actions:[],documentation:void 0};async function C(D,T,M,A,P,N){const O=A.filter||{},F={...O,excludes:[...O.excludes||[],l.CodeActionKind.Notebook]},x={only:O.include?.value,trigger:A.type},W=new o.TextModelCancellationTokenSource(T,N),V=A.type===2,q=f(D,T,V?F:O),H=new E.DisposableStore,z=q.map(async j=>{try{P.report(j);const Y=await j.provideCodeActions(T,M,x,W.token);if(Y&&H.add(Y),W.token.isCancellationRequested)return u;const G=(Y?.actions||[]).filter(R=>R&&(0,l.filtersAction)(O,R)),K=v(j,G,O.include);return{actions:G.map(R=>new l.CodeActionItem(R,j)),documentation:K}}catch(Y){if((0,I.isCancellationError)(Y))throw Y;return(0,I.onUnexpectedExternalError)(Y),u}}),U=D.onDidChange(()=>{const j=D.all(T);(0,d.equals)(j,q)||W.cancel()});try{const j=await Promise.all(z),Y=j.map(K=>K.actions).flat(),G=[...(0,d.coalesce)(j.map(K=>K.documentation)),...h(D,T,A,Y)];return new r(Y,G,H)}finally{U.dispose(),W.dispose()}}function f(D,T,M){return D.all(T).filter(A=>A.providedCodeActionKinds?A.providedCodeActionKinds.some(P=>(0,l.mayIncludeActionsOfKind)(M,new a.HierarchicalKind(P))):!0)}function*h(D,T,M,A){if(T&&A.length)for(const P of D.all(T))P._getAdditionalMenuItems&&(yield*P._getAdditionalMenuItems?.({trigger:M.type,only:M.filter?.include?.value},A.map(N=>N.action)))}function v(D,T,M){if(!D.documentation)return;const A=D.documentation.map(P=>({kind:new a.HierarchicalKind(P.kind),command:P.command}));if(M){let P;for(const N of A)N.kind.contains(M)&&(P?P.kind.contains(N.kind)&&(P=N):P=N);if(P)return P?.command}for(const P of T)if(P.kind){for(const N of A)if(N.kind.contains(new a.HierarchicalKind(P.kind)))return N.command}}var w;(function(D){D.OnSave="onSave",D.FromProblemsView="fromProblemsView",D.FromCodeActions="fromCodeActions",D.FromAILightbulb="fromAILightbulb"})(w||(e.ApplyCodeActionReason=w={}));async function S(D,T,M,A,P=k.CancellationToken.None){const N=D.get(m.IBulkEditService),O=D.get(i.ICommandService),F=D.get(c.ITelemetryService),x=D.get(s.INotificationService);if(F.publicLog2("codeAction.applyCodeAction",{codeActionTitle:T.action.title,codeActionKind:T.action.kind,codeActionIsPreferred:!!T.action.isPreferred,reason:M}),await T.resolve(P),!P.isCancellationRequested&&!(T.action.edit?.edits.length&&!(await N.apply(T.action.edit,{editor:A?.editor,label:T.action.title,quotableLabel:T.action.title,code:"undoredo.codeAction",respectAutoSaveConfig:M!==w.OnSave,showPreview:A?.preview})).isApplied)&&T.action.command)try{await O.executeCommand(T.action.command.id,...T.action.command.arguments||[])}catch(W){const V=L(W);x.error(typeof V=="string"?V:t.localize(742,"An unknown error occurred while applying the code action"))}}function L(D){return typeof D=="string"?D:D instanceof Error&&typeof D.message=="string"?D.message:void 0}i.CommandsRegistry.registerCommand("_executeCodeActionProvider",async function(D,T,M,A,P){if(!(T instanceof y.URI))throw(0,I.illegalArgument)();const{codeActionProvider:N}=D.get(p.ILanguageFeaturesService),O=D.get(n.IModelService).getModel(T);if(!O)throw(0,I.illegalArgument)();const F=b.Selection.isISelection(M)?b.Selection.liftSelection(M):_.Range.isIRange(M)?O.validateRange(M):void 0;if(!F)throw(0,I.illegalArgument)();const x=typeof A=="string"?new a.HierarchicalKind(A):void 0,W=await C(N,O,F,{type:1,triggerAction:l.CodeActionTriggerSource.Default,filter:{includeSourceActions:!0,include:x}},g.Progress.None,k.CancellationToken.None),V=[],q=Math.min(W.validActions.length,typeof P=="number"?P:0);for(let H=0;HH.action)}finally{setTimeout(()=>W.dispose(),100)}})}),define(ne[733],se([1,0,91,98,157,134,31]),function(oe,e,d,k,I,E,y){"use strict";var m;Object.defineProperty(e,"__esModule",{value:!0}),e.CodeActionKeybindingResolver=void 0;let _=class{static{m=this}static{this.codeActionCommands=[I.refactorCommandId,I.codeActionCommandId,I.sourceActionCommandId,I.organizeImportsCommandId,I.fixAllCommandId]}constructor(p){this.keybindingService=p}getResolver(){const p=new k.Lazy(()=>this.keybindingService.getKeybindings().filter(n=>m.codeActionCommands.indexOf(n.command)>=0).filter(n=>n.resolvedKeybinding).map(n=>{let o=n.commandArgs;return n.command===I.organizeImportsCommandId?o={kind:E.CodeActionKind.SourceOrganizeImports.value}:n.command===I.fixAllCommandId&&(o={kind:E.CodeActionKind.SourceFixAll.value}),{resolvedKeybinding:n.resolvedKeybinding,...E.CodeActionCommandArgs.fromUser(o,{kind:d.HierarchicalKind.None,apply:"never"})}}));return n=>{if(n.kind)return this.bestKeybindingForCodeAction(n,p.value)?.resolvedKeybinding}}bestKeybindingForCodeAction(p,n){if(!p.kind)return;const o=new d.HierarchicalKind(p.kind);return n.filter(t=>t.kind.contains(o)).filter(t=>t.preferred?p.isPreferred:!0).reduceRight((t,i)=>t?t.kind.contains(i.kind)?i:t:i,void 0)}};e.CodeActionKeybindingResolver=_,e.CodeActionKeybindingResolver=_=m=ke([ce(0,y.IKeybindingService)],_)}),define(ne[408],se([1,0,14,8,6,2,48,37,9,23,12,96,134,157,91,54]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CodeActionModel=e.CodeActionsState=e.APPLY_FIX_ALL_COMMAND_ID=e.SUPPORTED_CODE_ACTIONS=void 0,e.SUPPORTED_CODE_ACTIONS=new p.RawContextKey("supportedCodeAction",""),e.APPLY_FIX_ALL_COMMAND_ID="_typescript.applyFixAllCodeAction";class g extends E.Disposable{constructor(u,C,f,h=250){super(),this._editor=u,this._markerService=C,this._signalChange=f,this._delay=h,this._autoTriggerTimer=this._register(new d.TimeoutTimer),this._register(this._markerService.onMarkerChanged(v=>this._onMarkerChanges(v))),this._register(this._editor.onDidChangeCursorPosition(()=>this._tryAutoTrigger()))}trigger(u){const C=this._getRangeOfSelectionUnlessWhitespaceEnclosed(u);this._signalChange(C?{trigger:u,selection:C}:void 0)}_onMarkerChanges(u){const C=this._editor.getModel();C&&u.some(f=>(0,y.isEqual)(f,C.uri))&&this._tryAutoTrigger()}_tryAutoTrigger(){this._autoTriggerTimer.cancelAndSet(()=>{this.trigger({type:2,triggerAction:o.CodeActionTriggerSource.Default})},this._delay)}_getRangeOfSelectionUnlessWhitespaceEnclosed(u){if(!this._editor.hasModel())return;const C=this._editor.getSelection();if(u.type===1)return C;const f=this._editor.getOption(65).enabled;if(f!==m.ShowLightbulbIconMode.Off){{if(f===m.ShowLightbulbIconMode.On)return C;if(f===m.ShowLightbulbIconMode.OnCode){if(!C.isEmpty())return C;const v=this._editor.getModel(),{lineNumber:w,column:S}=C.getPosition(),L=v.getLineContent(w);if(L.length===0)return;if(S===1){if(/\s/.test(L[0]))return}else if(S===v.getLineMaxColumn(w)){if(/\s/.test(L[L.length-1]))return}else if(/\s/.test(L[S-2])&&/\s/.test(L[S-1]))return}}return C}}}var c;(function(r){r.Empty={type:0};class u{constructor(f,h,v){this.trigger=f,this.position=h,this._cancellablePromise=v,this.type=1,this.actions=v.catch(w=>{if((0,k.isCancellationError)(w))return l;throw w})}cancel(){this._cancellablePromise.cancel()}}r.Triggered=u})(c||(e.CodeActionsState=c={}));const l=Object.freeze({allActions:[],validActions:[],dispose:()=>{},documentation:[],hasAutoFix:!1,hasAIFix:!1,allAIFixes:!1});class a extends E.Disposable{constructor(u,C,f,h,v,w,S){super(),this._editor=u,this._registry=C,this._markerService=f,this._progressService=v,this._configurationService=w,this._telemetryService=S,this._codeActionOracle=this._register(new E.MutableDisposable),this._state=c.Empty,this._onDidChangeState=this._register(new I.Emitter),this.onDidChangeState=this._onDidChangeState.event,this._disposed=!1,this._supportedCodeActions=e.SUPPORTED_CODE_ACTIONS.bindTo(h),this._register(this._editor.onDidChangeModel(()=>this._update())),this._register(this._editor.onDidChangeModelLanguage(()=>this._update())),this._register(this._registry.onDidChange(()=>this._update())),this._register(this._editor.onDidChangeConfiguration(L=>{L.hasChanged(65)&&this._update()})),this._update()}dispose(){this._disposed||(this._disposed=!0,super.dispose(),this.setState(c.Empty,!0))}_settingEnabledNearbyQuickfixes(){const u=this._editor?.getModel();return this._configurationService?this._configurationService.getValue("editor.codeActionWidget.includeNearbyQuickFixes",{resource:u?.uri}):!1}_update(){if(this._disposed)return;this._codeActionOracle.value=void 0,this.setState(c.Empty);const u=this._editor.getModel();if(u&&this._registry.has(u)&&!this._editor.getOption(92)){const C=this._registry.all(u).flatMap(f=>f.providedCodeActionKinds??[]);this._supportedCodeActions.set(C.join(" ")),this._codeActionOracle.value=new g(this._editor,this._markerService,f=>{if(!f){this.setState(c.Empty);return}const h=f.selection.getStartPosition(),v=(0,d.createCancelablePromise)(async L=>{if(this._settingEnabledNearbyQuickfixes()&&f.trigger.type===1&&(f.trigger.triggerAction===o.CodeActionTriggerSource.QuickFix||f.trigger.filter?.include?.contains(o.CodeActionKind.QuickFix))){const D=await(0,t.getCodeActions)(this._registry,u,f.selection,f.trigger,n.Progress.None,L),T=[...D.allActions];if(L.isCancellationRequested)return l;const M=D.validActions?.some(P=>P.action.kind?o.CodeActionKind.QuickFix.contains(new i.HierarchicalKind(P.action.kind)):!1),A=this._markerService.read({resource:u.uri});if(M){for(const P of D.validActions)P.action.command?.arguments?.some(N=>typeof N=="string"&&N.includes(e.APPLY_FIX_ALL_COMMAND_ID))&&(P.action.diagnostics=[...A.filter(N=>N.relatedInformation)]);return{validActions:D.validActions,allActions:T,documentation:D.documentation,hasAutoFix:D.hasAutoFix,hasAIFix:D.hasAIFix,allAIFixes:D.allAIFixes,dispose:()=>{D.dispose()}}}else if(!M&&A.length>0){const P=f.selection.getPosition();let N=P,O=Number.MAX_VALUE;const F=[...D.validActions];for(const W of A){const V=W.endColumn,q=W.endLineNumber,H=W.startLineNumber;if(q===P.lineNumber||H===P.lineNumber){N=new _.Position(q,V);const z={type:f.trigger.type,triggerAction:f.trigger.triggerAction,filter:{include:f.trigger.filter?.include?f.trigger.filter?.include:o.CodeActionKind.QuickFix},autoApply:f.trigger.autoApply,context:{notAvailableMessage:f.trigger.context?.notAvailableMessage||"",position:N}},U=new b.Selection(N.lineNumber,N.column,N.lineNumber,N.column),j=await(0,t.getCodeActions)(this._registry,u,U,z,n.Progress.None,L);if(j.validActions.length!==0){for(const Y of j.validActions)Y.action.command?.arguments?.some(G=>typeof G=="string"&&G.includes(e.APPLY_FIX_ALL_COMMAND_ID))&&(Y.action.diagnostics=[...A.filter(G=>G.relatedInformation)]);D.allActions.length===0&&T.push(...j.allActions),Math.abs(P.column-V)q.findIndex(H=>H.action.title===W.action.title)===V);return x.sort((W,V)=>W.action.isPreferred&&!V.action.isPreferred?-1:!W.action.isPreferred&&V.action.isPreferred||W.action.isAI&&!V.action.isAI?1:!W.action.isAI&&V.action.isAI?-1:0),{validActions:x,allActions:T,documentation:D.documentation,hasAutoFix:D.hasAutoFix,hasAIFix:D.hasAIFix,allAIFixes:D.allAIFixes,dispose:()=>{D.dispose()}}}}if(f.trigger.type===1){const D=new s.StopWatch,T=await(0,t.getCodeActions)(this._registry,u,f.selection,f.trigger,n.Progress.None,L);return this._telemetryService&&this._telemetryService.publicLog2("codeAction.invokedDurations",{codeActions:T.validActions.length,duration:D.elapsed()}),T}return(0,t.getCodeActions)(this._registry,u,f.selection,f.trigger,n.Progress.None,L)});f.trigger.type===1&&this._progressService?.showWhile(v,250);const w=new c.Triggered(f.trigger,h,v);let S=!1;this._state.type===1&&(S=this._state.trigger.type===1&&w.type===1&&w.trigger.type===2&&this._state.position!==w.position),S?setTimeout(()=>{this.setState(w)},500):this.setState(w)},void 0),this._codeActionOracle.value.trigger({type:2,triggerAction:o.CodeActionTriggerSource.Default})}else this._supportedCodeActions.reset()}trigger(u){this._codeActionOracle.value?.trigger(u)}setState(u,C){u!==this._state&&(this._state.type===1&&this._state.cancel(),this._state=u,!C&&!this._disposed&&this._onDidChangeState.fire(u))}}e.CodeActionModel=a}),define(ne[734],se([1,0,15,165,3]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class E extends d.EditorAction{constructor(){super({id:"editor.action.fontZoomIn",label:I.localize(919,"Increase Editor Font Size"),alias:"Increase Editor Font Size",precondition:void 0})}run(b,p){k.EditorZoom.setZoomLevel(k.EditorZoom.getZoomLevel()+1)}}class y extends d.EditorAction{constructor(){super({id:"editor.action.fontZoomOut",label:I.localize(920,"Decrease Editor Font Size"),alias:"Decrease Editor Font Size",precondition:void 0})}run(b,p){k.EditorZoom.setZoomLevel(k.EditorZoom.getZoomLevel()-1)}}class m extends d.EditorAction{constructor(){super({id:"editor.action.fontZoomReset",label:I.localize(921,"Reset Editor Font Size"),alias:"Reset Editor Font Size",precondition:void 0})}run(b,p){k.EditorZoom.setZoomLevel(0)}}(0,d.registerEditorAction)(E),(0,d.registerEditorAction)(y),(0,d.registerEditorAction)(m)}),define(ne[409],se([1,0,13,18,8,53,73,19,22,122,168,9,4,23,100,78,337,24,674,7,17,62,137]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FormattingConflicts=void 0,e.getRealAndSyntheticDocumentFormattersOrdered=f,e.formatDocumentRangesWithSelectedProvider=v,e.formatDocumentRangesWithProvider=w,e.formatDocumentWithSelectedProvider=S,e.formatDocumentWithProvider=L,e.getDocumentRangeFormattingEditsUntilResult=D,e.getDocumentFormattingEditsUntilResult=T,e.getOnTypeFormattingEdits=M;function f(A,P,N){const O=[],F=new l.ExtensionIdentifierSet,x=A.ordered(N);for(const V of x)O.push(V),V.extensionId&&F.add(V.extensionId);const W=P.ordered(N);for(const V of W){if(V.extensionId){if(F.has(V.extensionId))continue;F.add(V.extensionId)}O.push({displayName:V.displayName,extensionId:V.extensionId,provideDocumentFormattingEdits(q,H,z){return V.provideDocumentRangeFormattingEdits(q,q.getFullModelRange(),H,z)}})}return O}class h{static{this._selectors=new y.LinkedList}static setFormatterSelector(P){return{dispose:h._selectors.unshift(P)}}static async select(P,N,O,F){if(P.length===0)return;const x=E.Iterable.first(h._selectors);if(x)return await x(P,N,O,F)}}e.FormattingConflicts=h;async function v(A,P,N,O,F,x,W){const V=A.get(a.IInstantiationService),{documentRangeFormattingEditProvider:q}=A.get(r.ILanguageFeaturesService),H=(0,p.isCodeEditor)(P)?P.getModel():P,z=q.ordered(H),U=await h.select(z,H,O,2);U&&(F.report(U),await V.invokeFunction(w,U,P,N,x,W))}async function w(A,P,N,O,F,x){const W=A.get(i.IEditorWorkerService),V=A.get(u.ILogService),q=A.get(C.IAccessibilitySignalService);let H,z;(0,p.isCodeEditor)(N)?(H=N.getModel(),z=new b.EditorStateCancellationTokenSource(N,5,void 0,F)):(H=N,z=new b.TextModelCancellationTokenSource(N,F));const U=[];let j=0;for(const J of(0,d.asArray)(O).sort(o.Range.compareRangesUsingStarts))j>0&&o.Range.areIntersectingOrTouching(U[j-1],J)?U[j-1]=o.Range.fromPositions(U[j-1].getStartPosition(),J.getEndPosition()):j=U.push(J);const Y=async J=>{V.trace("[format][provideDocumentRangeFormattingEdits] (request)",P.extensionId?.value,J);const ie=await P.provideDocumentRangeFormattingEdits(H,J,H.getFormattingOptions(),z.token)||[];return V.trace("[format][provideDocumentRangeFormattingEdits] (response)",P.extensionId?.value,ie),ie},G=(J,ie)=>{if(!J.length||!ie.length)return!1;const ue=J.reduce((he,pe)=>o.Range.plusRange(he,pe.range),J[0].range);if(!ie.some(he=>o.Range.intersectRanges(ue,he.range)))return!1;for(const he of J)for(const pe of ie)if(o.Range.intersectRanges(he.range,pe.range))return!0;return!1},K=[],R=[];try{if(typeof P.provideDocumentRangesFormattingEdits=="function"){V.trace("[format][provideDocumentRangeFormattingEdits] (request)",P.extensionId?.value,U);const J=await P.provideDocumentRangesFormattingEdits(H,U,H.getFormattingOptions(),z.token)||[];V.trace("[format][provideDocumentRangeFormattingEdits] (response)",P.extensionId?.value,J),R.push(J)}else{for(const J of U){if(z.token.isCancellationRequested)return!0;R.push(await Y(J))}for(let J=0;J({text:ue.text,range:o.Range.lift(ue.range),forceMoveMarkers:!0})),ue=>{for(const{range:he}of ue)if(o.Range.areIntersectingOrTouching(he,ie))return[new t.Selection(he.startLineNumber,he.startColumn,he.endLineNumber,he.endColumn)];return null})}return q.playSignal(C.AccessibilitySignal.format,{userGesture:x}),!0}async function S(A,P,N,O,F,x){const W=A.get(a.IInstantiationService),V=A.get(r.ILanguageFeaturesService),q=(0,p.isCodeEditor)(P)?P.getModel():P,H=f(V.documentFormattingEditProvider,V.documentRangeFormattingEditProvider,q),z=await h.select(H,q,N,1);z&&(O.report(z),await W.invokeFunction(L,z,P,N,F,x))}async function L(A,P,N,O,F,x){const W=A.get(i.IEditorWorkerService),V=A.get(C.IAccessibilitySignalService);let q,H;(0,p.isCodeEditor)(N)?(q=N.getModel(),H=new b.EditorStateCancellationTokenSource(N,5,void 0,F)):(q=N,H=new b.TextModelCancellationTokenSource(N,F));let z;try{const U=await P.provideDocumentFormattingEdits(q,q.getFormattingOptions(),H.token);if(z=await W.computeMoreMinimalEdits(q.uri,U),H.token.isCancellationRequested)return!0}finally{H.dispose()}if(!z||z.length===0)return!1;if((0,p.isCodeEditor)(N))g.FormattingEdit.execute(N,z,O!==2),O!==2&&N.revealPositionInCenterIfOutsideViewport(N.getPosition(),1);else{const[{range:U}]=z,j=new t.Selection(U.startLineNumber,U.startColumn,U.endLineNumber,U.endColumn);q.pushEditOperations([j],z.map(Y=>({text:Y.text,range:o.Range.lift(Y.range),forceMoveMarkers:!0})),Y=>{for(const{range:G}of Y)if(o.Range.areIntersectingOrTouching(G,j))return[new t.Selection(G.startLineNumber,G.startColumn,G.endLineNumber,G.endColumn)];return null})}return V.playSignal(C.AccessibilitySignal.format,{userGesture:x}),!0}async function D(A,P,N,O,F,x){const W=P.documentRangeFormattingEditProvider.ordered(N);for(const V of W){const q=await Promise.resolve(V.provideDocumentRangeFormattingEdits(N,O,F,x)).catch(I.onUnexpectedExternalError);if((0,d.isNonEmptyArray)(q))return await A.computeMoreMinimalEdits(N.uri,q)}}async function T(A,P,N,O,F){const x=f(P.documentFormattingEditProvider,P.documentRangeFormattingEditProvider,N);for(const W of x){const V=await Promise.resolve(W.provideDocumentFormattingEdits(N,O,F)).catch(I.onUnexpectedExternalError);if((0,d.isNonEmptyArray)(V))return await A.computeMoreMinimalEdits(N.uri,V)}}function M(A,P,N,O,F,x,W){const V=P.onTypeFormattingEditProvider.ordered(N);return V.length===0||V[0].autoFormatTriggerCharacters.indexOf(F)<0?Promise.resolve(void 0):Promise.resolve(V[0].provideOnTypeFormattingEdits(N,O,F,x,W)).catch(I.onUnexpectedExternalError).then(q=>A.computeMoreMinimalEdits(N.uri,q))}c.CommandsRegistry.registerCommand("_executeFormatRangeProvider",async function(A,...P){const[N,O,F]=P;(0,m.assertType)(_.URI.isUri(N)),(0,m.assertType)(o.Range.isIRange(O));const x=A.get(s.ITextModelService),W=A.get(i.IEditorWorkerService),V=A.get(r.ILanguageFeaturesService),q=await x.createModelReference(N);try{return D(W,V,q.object.textEditorModel,o.Range.lift(O),F,k.CancellationToken.None)}finally{q.dispose()}}),c.CommandsRegistry.registerCommand("_executeFormatDocumentProvider",async function(A,...P){const[N,O]=P;(0,m.assertType)(_.URI.isUri(N));const F=A.get(s.ITextModelService),x=A.get(i.IEditorWorkerService),W=A.get(r.ILanguageFeaturesService),V=await F.createModelReference(N);try{return T(x,W,V.object.textEditorModel,O,k.CancellationToken.None)}finally{V.dispose()}}),c.CommandsRegistry.registerCommand("_executeFormatOnTypeProvider",async function(A,...P){const[N,O,F,x]=P;(0,m.assertType)(_.URI.isUri(N)),(0,m.assertType)(n.Position.isIPosition(O)),(0,m.assertType)(typeof F=="string");const W=A.get(s.ITextModelService),V=A.get(i.IEditorWorkerService),q=A.get(r.ILanguageFeaturesService),H=await W.createModelReference(N);try{return M(V,q,H.object.textEditorModel,n.Position.lift(O),F,x,k.CancellationToken.None)}finally{H.dispose()}})}),define(ne[735],se([1,0,13,18,8,72,2,15,34,144,4,20,100,17,409,337,3,137,24,12,7,96]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FormatOnType=void 0;let C=class{static{this.ID="editor.contrib.autoFormat"}constructor(S,L,D,T){this._editor=S,this._languageFeaturesService=L,this._workerService=D,this._accessibilitySignalService=T,this._disposables=new y.DisposableStore,this._sessionDisposables=new y.DisposableStore,this._disposables.add(L.onTypeFormattingEditProvider.onDidChange(this._update,this)),this._disposables.add(S.onDidChangeModel(()=>this._update())),this._disposables.add(S.onDidChangeModelLanguage(()=>this._update())),this._disposables.add(S.onDidChangeConfiguration(M=>{M.hasChanged(56)&&this._update()})),this._update()}dispose(){this._disposables.dispose(),this._sessionDisposables.dispose()}_update(){if(this._sessionDisposables.clear(),!this._editor.getOption(56)||!this._editor.hasModel())return;const S=this._editor.getModel(),[L]=this._languageFeaturesService.onTypeFormattingEditProvider.ordered(S);if(!L||!L.autoFormatTriggerCharacters)return;const D=new b.CharacterSet;for(const T of L.autoFormatTriggerCharacters)D.add(T.charCodeAt(0));this._sessionDisposables.add(this._editor.onDidType(T=>{const M=T.charCodeAt(T.length-1);D.has(M)&&this._trigger(String.fromCharCode(M))}))}_trigger(S){if(!this._editor.hasModel()||this._editor.getSelections().length>1||!this._editor.getSelection().isEmpty())return;const L=this._editor.getModel(),D=this._editor.getPosition(),T=new k.CancellationTokenSource,M=this._editor.onDidChangeModelContent(A=>{if(A.isFlush){T.cancel(),M.dispose();return}for(let P=0,N=A.changes.length;P{T.token.isCancellationRequested||(0,d.isNonEmptyArray)(A)&&(this._accessibilitySignalService.playSignal(c.AccessibilitySignal.format,{userGesture:!1}),s.FormattingEdit.execute(this._editor,A,!0))}).finally(()=>{M.dispose()})}};e.FormatOnType=C,e.FormatOnType=C=ke([ce(1,t.ILanguageFeaturesService),ce(2,o.IEditorWorkerService),ce(3,c.IAccessibilitySignalService)],C);let f=class{static{this.ID="editor.contrib.formatOnPaste"}constructor(S,L,D){this.editor=S,this._languageFeaturesService=L,this._instantiationService=D,this._callOnDispose=new y.DisposableStore,this._callOnModel=new y.DisposableStore,this._callOnDispose.add(S.onDidChangeConfiguration(()=>this._update())),this._callOnDispose.add(S.onDidChangeModel(()=>this._update())),this._callOnDispose.add(S.onDidChangeModelLanguage(()=>this._update())),this._callOnDispose.add(L.documentRangeFormattingEditProvider.onDidChange(this._update,this))}dispose(){this._callOnDispose.dispose(),this._callOnModel.dispose()}_update(){this._callOnModel.clear(),this.editor.getOption(55)&&this.editor.hasModel()&&this._languageFeaturesService.documentRangeFormattingEditProvider.has(this.editor.getModel())&&this._callOnModel.add(this.editor.onDidPaste(({range:S})=>this._trigger(S)))}_trigger(S){this.editor.hasModel()&&(this.editor.getSelections().length>1||this._instantiationService.invokeFunction(i.formatDocumentRangesWithSelectedProvider,this.editor,S,2,u.Progress.None,k.CancellationToken.None,!1).catch(I.onUnexpectedError))}};f=ke([ce(1,t.ILanguageFeaturesService),ce(2,r.IInstantiationService)],f);class h extends m.EditorAction{constructor(){super({id:"editor.action.formatDocument",label:g.localize(922,"Format Document"),alias:"Format Document",precondition:a.ContextKeyExpr.and(n.EditorContextKeys.notInCompositeEditor,n.EditorContextKeys.writable,n.EditorContextKeys.hasDocumentFormattingProvider),kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:1572,linux:{primary:3111},weight:100},contextMenuOpts:{group:"1_modification",order:1.3}})}async run(S,L){if(L.hasModel()){const D=S.get(r.IInstantiationService);await S.get(u.IEditorProgressService).showWhile(D.invokeFunction(i.formatDocumentWithSelectedProvider,L,1,u.Progress.None,k.CancellationToken.None,!0),250)}}}class v extends m.EditorAction{constructor(){super({id:"editor.action.formatSelection",label:g.localize(923,"Format Selection"),alias:"Format Selection",precondition:a.ContextKeyExpr.and(n.EditorContextKeys.writable,n.EditorContextKeys.hasDocumentSelectionFormattingProvider),kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2084),weight:100},contextMenuOpts:{when:n.EditorContextKeys.hasNonEmptySelection,group:"1_modification",order:1.31}})}async run(S,L){if(!L.hasModel())return;const D=S.get(r.IInstantiationService),T=L.getModel(),M=L.getSelections().map(P=>P.isEmpty()?new p.Range(P.startLineNumber,1,P.startLineNumber,T.getLineMaxColumn(P.startLineNumber)):P);await S.get(u.IEditorProgressService).showWhile(D.invokeFunction(i.formatDocumentRangesWithSelectedProvider,L,M,1,u.Progress.None,k.CancellationToken.None,!0),250)}}(0,m.registerEditorContribution)(C.ID,C,2),(0,m.registerEditorContribution)(f.ID,f,2),(0,m.registerEditorAction)(h),(0,m.registerEditorAction)(v),l.CommandsRegistry.registerCommand("editor.action.format",async w=>{const S=w.get(_.ICodeEditorService).getFocusedCodeEditor();if(!S||!S.hasModel())return;const L=w.get(l.ICommandService);S.getSelection().isEmpty()?await L.executeCommand("editor.action.formatDocument"):await L.executeCommand("editor.action.formatSelection")})}),define(ne[277],se([1,0,13,18,8,42,15,17,178]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getDefinitionsAtPosition=n,e.getDeclarationsAtPosition=o,e.getImplementationsAtPosition=t,e.getTypeDefinitionsAtPosition=i,e.getReferencesAtPosition=s;function b(c,l){return l.uri.scheme===c.uri.scheme?!0:!(0,E.matchesSomeScheme)(l.uri,E.Schemas.walkThroughSnippet,E.Schemas.vscodeChatCodeBlock,E.Schemas.vscodeChatCodeCompareBlock)}async function p(c,l,a,r,u){const f=a.ordered(c,r).map(v=>Promise.resolve(u(v,c,l)).then(void 0,w=>{(0,I.onUnexpectedExternalError)(w)})),h=await Promise.all(f);return(0,d.coalesce)(h.flat()).filter(v=>b(c,v))}function n(c,l,a,r,u){return p(l,a,c,r,(C,f,h)=>C.provideDefinition(f,h,u))}function o(c,l,a,r,u){return p(l,a,c,r,(C,f,h)=>C.provideDeclaration(f,h,u))}function t(c,l,a,r,u){return p(l,a,c,r,(C,f,h)=>C.provideImplementation(f,h,u))}function i(c,l,a,r,u){return p(l,a,c,r,(C,f,h)=>C.provideTypeDefinition(f,h,u))}function s(c,l,a,r,u,C){return p(l,a,c,u,async(f,h,v)=>{const w=(await f.provideReferences(h,v,{includeDeclaration:!0},C))?.filter(L=>b(h,L));if(!r||!w||w.length!==2)return w;const S=(await f.provideReferences(h,v,{includeDeclaration:!1},C))?.filter(L=>b(h,L));return S&&S.length===1?S:w})}async function g(c){const l=await c(),a=new _.ReferencesModel(l,""),r=a.references.map(u=>u.link);return a.dispose(),r}(0,y.registerModelAndPositionCommand)("_executeDefinitionProvider",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=n(r.definitionProvider,l,a,!1,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeDefinitionProvider_recursive",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=n(r.definitionProvider,l,a,!0,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeTypeDefinitionProvider",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=i(r.typeDefinitionProvider,l,a,!1,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeTypeDefinitionProvider_recursive",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=i(r.typeDefinitionProvider,l,a,!0,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeDeclarationProvider",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=o(r.declarationProvider,l,a,!1,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeDeclarationProvider_recursive",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=o(r.declarationProvider,l,a,!0,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeReferenceProvider",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=s(r.referenceProvider,l,a,!1,!1,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeReferenceProvider_recursive",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=s(r.referenceProvider,l,a,!1,!0,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeImplementationProvider",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=t(r.implementationProvider,l,a,!1,k.CancellationToken.None);return g(()=>u)}),(0,y.registerModelAndPositionCommand)("_executeImplementationProvider_recursive",(c,l,a)=>{const r=c.get(m.ILanguageFeaturesService),u=t(r.implementationProvider,l,a,!0,k.CancellationToken.None);return g(()=>u)})}),define(ne[736],se([1,0,6,2,48,15,34,4,3,12,49,7,31,121,50]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ISymbolNavigationService=e.ctxHasSymbols=void 0,e.ctxHasSymbols=new b.RawContextKey("hasSymbols",!1,(0,_.localize)(1003,"Whether there are symbol locations that can be navigated via keyboard-only.")),e.ISymbolNavigationService=(0,n.createDecorator)("ISymbolNavigationService");let s=class{constructor(l,a,r,u){this._editorService=a,this._notificationService=r,this._keybindingService=u,this._currentModel=void 0,this._currentIdx=-1,this._ignoreEditorChange=!1,this._ctxHasSymbols=e.ctxHasSymbols.bindTo(l)}reset(){this._ctxHasSymbols.reset(),this._currentState?.dispose(),this._currentMessage?.dispose(),this._currentModel=void 0,this._currentIdx=-1}put(l){const a=l.parent.parent;if(a.references.length<=1){this.reset();return}this._currentModel=a,this._currentIdx=a.references.indexOf(l),this._ctxHasSymbols.set(!0),this._showMessage();const r=new g(this._editorService),u=r.onDidChange(C=>{if(this._ignoreEditorChange)return;const f=this._editorService.getActiveCodeEditor();if(!f)return;const h=f.getModel(),v=f.getPosition();if(!h||!v)return;let w=!1,S=!1;for(const L of a.references)if((0,I.isEqual)(L.uri,h.uri))w=!0,S=S||m.Range.containsPosition(L.range,v);else if(w)break;(!w||!S)&&this.reset()});this._currentState=(0,k.combinedDisposable)(r,u)}revealNext(l){if(!this._currentModel)return Promise.resolve();this._currentIdx+=1,this._currentIdx%=this._currentModel.references.length;const a=this._currentModel.references[this._currentIdx];return this._showMessage(),this._ignoreEditorChange=!0,this._editorService.openCodeEditor({resource:a.uri,options:{selection:m.Range.collapseToStart(a.range),selectionRevealType:3}},l).finally(()=>{this._ignoreEditorChange=!1})}_showMessage(){this._currentMessage?.dispose();const l=this._keybindingService.lookupKeybinding("editor.gotoNextSymbolFromResult"),a=l?(0,_.localize)(1004,"Symbol {0} of {1}, {2} for next",this._currentIdx+1,this._currentModel.references.length,l.getLabel()):(0,_.localize)(1005,"Symbol {0} of {1}",this._currentIdx+1,this._currentModel.references.length);this._currentMessage=this._notificationService.status(a)}};s=ke([ce(0,b.IContextKeyService),ce(1,y.ICodeEditorService),ce(2,i.INotificationService),ce(3,o.IKeybindingService)],s),(0,p.registerSingleton)(e.ISymbolNavigationService,s,1),(0,E.registerEditorCommand)(new class extends E.EditorCommand{constructor(){super({id:"editor.gotoNextSymbolFromResult",precondition:e.ctxHasSymbols,kbOpts:{weight:100,primary:70}})}runEditorCommand(c,l){return c.get(e.ISymbolNavigationService).revealNext(l)}}),t.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"editor.gotoNextSymbolFromResult.cancel",weight:100,when:e.ctxHasSymbols,primary:9,handler(c){c.get(e.ISymbolNavigationService).reset()}});let g=class{constructor(l){this._listener=new Map,this._disposables=new k.DisposableStore,this._onDidChange=new d.Emitter,this.onDidChange=this._onDidChange.event,this._disposables.add(l.onCodeEditorRemove(this._onDidRemoveEditor,this)),this._disposables.add(l.onCodeEditorAdd(this._onDidAddEditor,this)),l.listCodeEditors().forEach(this._onDidAddEditor,this)}dispose(){this._disposables.dispose(),this._onDidChange.dispose(),(0,k.dispose)(this._listener.values())}_onDidAddEditor(l){this._listener.set(l,(0,k.combinedDisposable)(l.onDidChangeCursorPosition(a=>this._onDidChange.fire({editor:l})),l.onDidChangeModelContent(a=>this._onDidChange.fire({editor:l}))))}_onDidRemoveEditor(l){this._listener.get(l)?.dispose(),this._listener.delete(l)}};g=ke([ce(0,y.ICodeEditorService)],g)}),define(ne[410],se([1,0,14,18,8,15,17]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HoverProviderResult=void 0,e.getHoverProviderResultsAsAsyncIterable=b,e.getHoversPromise=p;class m{constructor(t,i,s){this.provider=t,this.hover=i,this.ordinal=s}}e.HoverProviderResult=m;async function _(o,t,i,s,g){const c=await Promise.resolve(o.provideHover(i,s,g)).catch(I.onUnexpectedExternalError);if(!(!c||!n(c)))return new m(o,c,t)}function b(o,t,i,s,g=!1){const l=o.ordered(t,g).map((a,r)=>_(a,r,t,i,s));return d.AsyncIterableObject.fromPromises(l).coalesce()}function p(o,t,i,s,g=!1){return b(o,t,i,s,g).map(c=>c.hover).toPromise()}(0,E.registerModelAndPositionCommand)("_executeHoverProvider",(o,t,i)=>{const s=o.get(y.ILanguageFeaturesService);return p(s.hoverProvider,t,i,k.CancellationToken.None)}),(0,E.registerModelAndPositionCommand)("_executeHoverProvider_recursive",(o,t,i)=>{const s=o.get(y.ILanguageFeaturesService);return p(s.hoverProvider,t,i,k.CancellationToken.None,!0)});function n(o){const t=typeof o.range<"u",i=typeof o.contents<"u"&&o.contents&&o.contents.length>0;return t&&i}}),define(ne[737],se([1,0,2,11,15,183,4,20,36,51,338,3,66,241,714,83]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IndentationToTabsCommand=e.IndentationToSpacesCommand=e.AutoIndentOnPaste=e.AutoIndentOnPasteCommand=e.ReindentSelectedLinesAction=e.ReindentLinesAction=e.DetectIndentation=e.ChangeTabDisplaySize=e.IndentUsingSpaces=e.IndentUsingTabs=e.ChangeIndentationSizeAction=e.IndentationToTabsAction=e.IndentationToSpacesAction=void 0;class g extends I.EditorAction{static{this.ID="editor.action.indentationToSpaces"}constructor(){super({id:g.ID,label:n.localize(1045,"Convert Indentation to Spaces"),alias:"Convert Indentation to Spaces",precondition:m.EditorContextKeys.writable,metadata:{description:n.localize2(1057,"Convert the tab indentation to spaces.")}})}run(A,P){const N=P.getModel();if(!N)return;const O=N.getOptions(),F=P.getSelection();if(!F)return;const x=new D(F,O.tabSize);P.pushUndoStop(),P.executeCommands(this.id,[x]),P.pushUndoStop(),N.updateOptions({insertSpaces:!0})}}e.IndentationToSpacesAction=g;class c extends I.EditorAction{static{this.ID="editor.action.indentationToTabs"}constructor(){super({id:c.ID,label:n.localize(1046,"Convert Indentation to Tabs"),alias:"Convert Indentation to Tabs",precondition:m.EditorContextKeys.writable,metadata:{description:n.localize2(1058,"Convert the spaces indentation to tabs.")}})}run(A,P){const N=P.getModel();if(!N)return;const O=N.getOptions(),F=P.getSelection();if(!F)return;const x=new T(F,O.tabSize);P.pushUndoStop(),P.executeCommands(this.id,[x]),P.pushUndoStop(),N.updateOptions({insertSpaces:!1})}}e.IndentationToTabsAction=c;class l extends I.EditorAction{constructor(A,P,N){super(N),this.insertSpaces=A,this.displaySizeOnly=P}run(A,P){const N=A.get(o.IQuickInputService),O=A.get(b.IModelService),F=P.getModel();if(!F)return;const x=O.getCreationOptions(F.getLanguageId(),F.uri,F.isForSimpleWidget),W=F.getOptions(),V=[1,2,3,4,5,6,7,8].map(H=>({id:H.toString(),label:H.toString(),description:H===x.tabSize&&H===W.tabSize?n.localize(1047,"Configured Tab Size"):H===x.tabSize?n.localize(1048,"Default Tab Size"):H===W.tabSize?n.localize(1049,"Current Tab Size"):void 0})),q=Math.min(F.getOptions().tabSize-1,7);setTimeout(()=>{N.pick(V,{placeHolder:n.localize(1050,"Select Tab Size for Current File"),activeItem:V[q]}).then(H=>{if(H&&F&&!F.isDisposed()){const z=parseInt(H.label,10);this.displaySizeOnly?F.updateOptions({tabSize:z}):F.updateOptions({tabSize:z,indentSize:z,insertSpaces:this.insertSpaces})}})},50)}}e.ChangeIndentationSizeAction=l;class a extends l{static{this.ID="editor.action.indentUsingTabs"}constructor(){super(!1,!1,{id:a.ID,label:n.localize(1051,"Indent Using Tabs"),alias:"Indent Using Tabs",precondition:void 0,metadata:{description:n.localize2(1059,"Use indentation with tabs.")}})}}e.IndentUsingTabs=a;class r extends l{static{this.ID="editor.action.indentUsingSpaces"}constructor(){super(!0,!1,{id:r.ID,label:n.localize(1052,"Indent Using Spaces"),alias:"Indent Using Spaces",precondition:void 0,metadata:{description:n.localize2(1060,"Use indentation with spaces.")}})}}e.IndentUsingSpaces=r;class u extends l{static{this.ID="editor.action.changeTabDisplaySize"}constructor(){super(!0,!0,{id:u.ID,label:n.localize(1053,"Change Tab Display Size"),alias:"Change Tab Display Size",precondition:void 0,metadata:{description:n.localize2(1061,"Change the space size equivalent of the tab.")}})}}e.ChangeTabDisplaySize=u;class C extends I.EditorAction{static{this.ID="editor.action.detectIndentation"}constructor(){super({id:C.ID,label:n.localize(1054,"Detect Indentation from Content"),alias:"Detect Indentation from Content",precondition:void 0,metadata:{description:n.localize2(1062,"Detect the indentation from content.")}})}run(A,P){const N=A.get(b.IModelService),O=P.getModel();if(!O)return;const F=N.getCreationOptions(O.getLanguageId(),O.uri,O.isForSimpleWidget);O.detectIndentation(F.insertSpaces,F.tabSize)}}e.DetectIndentation=C;class f extends I.EditorAction{constructor(){super({id:"editor.action.reindentlines",label:n.localize(1055,"Reindent Lines"),alias:"Reindent Lines",precondition:m.EditorContextKeys.writable,metadata:{description:n.localize2(1063,"Reindent the lines of the editor.")}})}run(A,P){const N=A.get(_.ILanguageConfigurationService),O=P.getModel();if(!O)return;const F=(0,i.getReindentEditOperations)(O,N,1,O.getLineCount());F.length>0&&(P.pushUndoStop(),P.executeEdits(this.id,F),P.pushUndoStop())}}e.ReindentLinesAction=f;class h extends I.EditorAction{constructor(){super({id:"editor.action.reindentselectedlines",label:n.localize(1056,"Reindent Selected Lines"),alias:"Reindent Selected Lines",precondition:m.EditorContextKeys.writable,metadata:{description:n.localize2(1064,"Reindent the selected lines of the editor.")}})}run(A,P){const N=A.get(_.ILanguageConfigurationService),O=P.getModel();if(!O)return;const F=P.getSelections();if(F===null)return;const x=[];for(const W of F){let V=W.startLineNumber,q=W.endLineNumber;if(V!==q&&W.endColumn===1&&q--,V===1){if(V===q)continue}else V--;const H=(0,i.getReindentEditOperations)(O,N,V,q);x.push(...H)}x.length>0&&(P.pushUndoStop(),P.executeEdits(this.id,x),P.pushUndoStop())}}e.ReindentSelectedLinesAction=h;class v{constructor(A,P){this._initialSelection=P,this._edits=[],this._selectionId=null;for(const N of A)N.range&&typeof N.text=="string"&&this._edits.push(N)}getEditOperations(A,P){for(const O of this._edits)P.addEditOperation(y.Range.lift(O.range),O.text);let N=!1;Array.isArray(this._edits)&&this._edits.length===1&&this._initialSelection.isEmpty()&&(this._edits[0].range.startColumn===this._initialSelection.endColumn&&this._edits[0].range.startLineNumber===this._initialSelection.endLineNumber?(N=!0,this._selectionId=P.trackSelection(this._initialSelection,!0)):this._edits[0].range.endColumn===this._initialSelection.startColumn&&this._edits[0].range.endLineNumber===this._initialSelection.startLineNumber&&(N=!0,this._selectionId=P.trackSelection(this._initialSelection,!1))),N||(this._selectionId=P.trackSelection(this._initialSelection))}computeCursorState(A,P){return P.getTrackedSelection(this._selectionId)}}e.AutoIndentOnPasteCommand=v;let w=class{static{this.ID="editor.contrib.autoIndentOnPaste"}constructor(A,P){this.editor=A,this._languageConfigurationService=P,this.callOnDispose=new d.DisposableStore,this.callOnModel=new d.DisposableStore,this.callOnDispose.add(A.onDidChangeConfiguration(()=>this.update())),this.callOnDispose.add(A.onDidChangeModel(()=>this.update())),this.callOnDispose.add(A.onDidChangeModelLanguage(()=>this.update()))}update(){this.callOnModel.clear(),!(this.editor.getOption(12)<4||this.editor.getOption(55))&&this.editor.hasModel()&&this.callOnModel.add(this.editor.onDidPaste(({range:A})=>{this.trigger(A)}))}trigger(A){const P=this.editor.getSelections();if(P===null||P.length>1)return;const N=this.editor.getModel();if(!N||this.rangeContainsOnlyWhitespaceCharacters(N,A)||S(N,A)||!N.tokenization.isCheapToTokenize(A.getStartPosition().lineNumber))return;const F=this.editor.getOption(12),{tabSize:x,indentSize:W,insertSpaces:V}=N.getOptions(),q=[],H={shiftIndent:Y=>E.ShiftCommand.shiftIndent(Y,Y.length+1,x,W,V),unshiftIndent:Y=>E.ShiftCommand.unshiftIndent(Y,Y.length+1,x,W,V)};let z=A.startLineNumber;for(;z<=A.endLineNumber;){if(this.shouldIgnoreLine(N,z)){z++;continue}break}if(z>A.endLineNumber)return;let U=N.getLineContent(z);if(!/\S/.test(U.substring(0,A.startColumn-1))){const Y=(0,t.getGoodIndentForLine)(F,N,N.getLanguageId(),z,H,this._languageConfigurationService);if(Y!==null){const G=k.getLeadingWhitespace(U),K=p.getSpaceCnt(Y,x),R=p.getSpaceCnt(G,x);if(K!==R){const J=p.generateIndent(K,x,V);q.push({range:new y.Range(z,1,z,G.length+1),text:J}),U=J+U.substring(G.length)}else{const J=(0,t.getIndentMetadata)(N,z,this._languageConfigurationService);if(J===0||J===8)return}}}const j=z;for(;zN.tokenization.getLineTokens(K),getLanguageId:()=>N.getLanguageId(),getLanguageIdAtPosition:(K,R)=>N.getLanguageIdAtPosition(K,R)},getLineContent:K=>K===j?U:N.getLineContent(K)},G=(0,t.getGoodIndentForLine)(F,Y,N.getLanguageId(),z+1,H,this._languageConfigurationService);if(G!==null){const K=p.getSpaceCnt(G,x),R=p.getSpaceCnt(k.getLeadingWhitespace(N.getLineContent(z+1)),x);if(K!==R){const J=K-R;for(let ie=z+1;ie<=A.endLineNumber;ie++){const ue=N.getLineContent(ie),he=k.getLeadingWhitespace(ue),ae=p.getSpaceCnt(he,x)+J,ee=p.generateIndent(ae,x,V);ee!==he&&q.push({range:new y.Range(ie,1,ie,he.length+1),text:ee})}}}}if(q.length>0){this.editor.pushUndoStop();const Y=new v(q,this.editor.getSelection());this.editor.executeCommand("autoIndentOnPaste",Y),this.editor.pushUndoStop()}}rangeContainsOnlyWhitespaceCharacters(A,P){const N=F=>F.trim().length===0;let O=!0;if(P.startLineNumber===P.endLineNumber){const x=A.getLineContent(P.startLineNumber).substring(P.startColumn-1,P.endColumn-1);O=N(x)}else for(let F=P.startLineNumber;F<=P.endLineNumber;F++){const x=A.getLineContent(F);if(F===P.startLineNumber){const W=x.substring(P.startColumn-1);O=N(W)}else if(F===P.endLineNumber){const W=x.substring(0,P.endColumn-1);O=N(W)}else O=A.getLineFirstNonWhitespaceColumn(F)===0;if(!O)break}return O}shouldIgnoreLine(A,P){A.tokenization.forceTokenization(P);const N=A.getLineFirstNonWhitespaceColumn(P);if(N===0)return!0;const O=A.tokenization.getLineTokens(P);if(O.getCount()>0){const F=O.findTokenIndexAtOffset(N);if(F>=0&&O.getStandardTokenType(F)===1)return!0}return!1}dispose(){this.callOnDispose.dispose(),this.callOnModel.dispose()}};e.AutoIndentOnPaste=w,e.AutoIndentOnPaste=w=ke([ce(1,_.ILanguageConfigurationService)],w);function S(M,A){const P=N=>(0,s.getStandardTokenTypeAtPosition)(M,N)===2;return P(A.getStartPosition())||P(A.getEndPosition())}function L(M,A,P,N){if(M.getLineCount()===1&&M.getLineMaxColumn(1)===1)return;let O="";for(let x=0;x({selection:X,index:B,ignore:!1}));ee.sort((X,B)=>n.Range.compareRangesUsingStarts(X.selection,B.selection));let de=ee[0];for(let X=1;Xnew p.Position(Z.positionLineNumber,Z.positionColumn)));const ge=ae.getSelection();if(ge===null)return;const X=pe.get(r.IConfigurationService),B=ae.getModel(),$=X.getValue("files.trimTrailingWhitespaceInRegexAndStrings",{overrideIdentifier:B?.getLanguageId(),resource:B?.uri}),Q=new y.TrimTrailingWhitespaceCommand(ge,de,$);ae.pushUndoStop(),ae.executeCommands(this.id,[Q]),ae.pushUndoStop()}}e.TrimTrailingWhitespaceAction=A;class P extends I.EditorAction{constructor(){super({id:"editor.action.deleteLines",label:c.localize(1120,"Delete Line"),alias:"Delete Line",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.textInputFocus,primary:3113,weight:100}})}run(pe,ae){if(!ae.hasModel())return;const ee=this._getLinesToRemove(ae),de=ae.getModel();if(de.getLineCount()===1&&de.getLineMaxColumn(1)===1)return;let ge=0;const X=[],B=[];for(let $=0,Q=ee.length;$1&&(te-=1,le=de.getLineMaxColumn(te)),X.push(b.EditOperation.replace(new o.Selection(te,le,re,me),"")),B.push(new o.Selection(te-ge,Z.positionColumn,te-ge,Z.positionColumn)),ge+=Z.endLineNumber-Z.startLineNumber+1}ae.pushUndoStop(),ae.executeEdits(this.id,X,B),ae.pushUndoStop()}_getLinesToRemove(pe){const ae=pe.getSelections().map(ge=>{let X=ge.endLineNumber;return ge.startLineNumberge.startLineNumber===X.startLineNumber?ge.endLineNumber-X.endLineNumber:ge.startLineNumber-X.startLineNumber);const ee=[];let de=ae[0];for(let ge=1;ge=ae[ge].startLineNumber?de.endLineNumber=ae[ge].endLineNumber:(ee.push(de),de=ae[ge]);return ee.push(de),ee}}e.DeleteLinesAction=P;class N extends I.EditorAction{constructor(){super({id:"editor.action.indentLines",label:c.localize(1121,"Indent Line"),alias:"Indent Line",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.editorTextFocus,primary:2142,weight:100}})}run(pe,ae){const ee=ae._getViewModel();ee&&(ae.pushUndoStop(),ae.executeCommands(this.id,m.TypeOperations.indent(ee.cursorConfig,ae.getModel(),ae.getSelections())),ae.pushUndoStop())}}e.IndentLinesAction=N;class O extends I.EditorAction{constructor(){super({id:"editor.action.outdentLines",label:c.localize(1122,"Outdent Line"),alias:"Outdent Line",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.editorTextFocus,primary:2140,weight:100}})}run(pe,ae){k.CoreEditingCommands.Outdent.runEditorCommand(pe,ae,null)}}class F extends I.EditorAction{constructor(){super({id:"editor.action.insertLineBefore",label:c.localize(1123,"Insert Line Above"),alias:"Insert Line Above",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.editorTextFocus,primary:3075,weight:100}})}run(pe,ae){const ee=ae._getViewModel();ee&&(ae.pushUndoStop(),ae.executeCommands(this.id,_.EnterOperation.lineInsertBefore(ee.cursorConfig,ae.getModel(),ae.getSelections())))}}e.InsertLineBeforeAction=F;class x extends I.EditorAction{constructor(){super({id:"editor.action.insertLineAfter",label:c.localize(1124,"Insert Line Below"),alias:"Insert Line Below",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.editorTextFocus,primary:2051,weight:100}})}run(pe,ae){const ee=ae._getViewModel();ee&&(ae.pushUndoStop(),ae.executeCommands(this.id,_.EnterOperation.lineInsertAfter(ee.cursorConfig,ae.getModel(),ae.getSelections())))}}e.InsertLineAfterAction=x;class W extends I.EditorAction{run(pe,ae){if(!ae.hasModel())return;const ee=ae.getSelection(),de=this._getRangesToDelete(ae),ge=[];for(let $=0,Q=de.length-1;$b.EditOperation.replace($,""));ae.pushUndoStop(),ae.executeEdits(this.id,B,X),ae.pushUndoStop()}}e.AbstractDeleteAllToBoundaryAction=W;class V extends W{constructor(){super({id:"deleteAllLeft",label:c.localize(1125,"Delete All Left"),alias:"Delete All Left",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.textInputFocus,primary:0,mac:{primary:2049},weight:100}})}_getEndCursorState(pe,ae){let ee=null;const de=[];let ge=0;return ae.forEach(X=>{let B;if(X.endColumn===1&&ge>0){const $=X.startLineNumber-ge;B=new o.Selection($,X.startColumn,$,X.startColumn)}else B=new o.Selection(X.startLineNumber,X.startColumn,X.startLineNumber,X.startColumn);ge+=X.endLineNumber-X.startLineNumber,X.intersectRanges(pe)?ee=B:de.push(B)}),ee&&de.unshift(ee),de}_getRangesToDelete(pe){const ae=pe.getSelections();if(ae===null)return[];let ee=ae;const de=pe.getModel();return de===null?[]:(ee.sort(n.Range.compareRangesUsingStarts),ee=ee.map(ge=>{if(ge.isEmpty())if(ge.startColumn===1){const X=Math.max(1,ge.startLineNumber-1),B=ge.startLineNumber===1?1:de.getLineLength(X)+1;return new n.Range(X,B,ge.startLineNumber,1)}else return new n.Range(ge.startLineNumber,1,ge.startLineNumber,ge.startColumn);else return new n.Range(ge.startLineNumber,1,ge.endLineNumber,ge.endColumn)}),ee)}}e.DeleteAllLeftAction=V;class q extends W{constructor(){super({id:"deleteAllRight",label:c.localize(1126,"Delete All Right"),alias:"Delete All Right",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.textInputFocus,primary:0,mac:{primary:297,secondary:[2068]},weight:100}})}_getEndCursorState(pe,ae){let ee=null;const de=[];for(let ge=0,X=ae.length,B=0;ge{if(ge.isEmpty()){const X=ae.getLineMaxColumn(ge.startLineNumber);return ge.startColumn===X?new n.Range(ge.startLineNumber,ge.startColumn,ge.startLineNumber+1,1):new n.Range(ge.startLineNumber,ge.startColumn,ge.startLineNumber,X)}return ge});return de.sort(n.Range.compareRangesUsingStarts),de}}e.DeleteAllRightAction=q;class H extends I.EditorAction{constructor(){super({id:"editor.action.joinLines",label:c.localize(1127,"Join Lines"),alias:"Join Lines",precondition:t.EditorContextKeys.writable,kbOpts:{kbExpr:t.EditorContextKeys.editorTextFocus,primary:0,mac:{primary:296},weight:100}})}run(pe,ae){const ee=ae.getSelections();if(ee===null)return;let de=ae.getSelection();if(de===null)return;ee.sort(n.Range.compareRangesUsingStarts);const ge=[],X=ee.reduce((re,le)=>re.isEmpty()?re.endLineNumber===le.startLineNumber?(de.equalsSelection(re)&&(de=le),le):le.startLineNumber>re.endLineNumber+1?(ge.push(re),le):new o.Selection(re.startLineNumber,re.startColumn,le.endLineNumber,le.endColumn):le.startLineNumber>re.endLineNumber?(ge.push(re),le):new o.Selection(re.startLineNumber,re.startColumn,le.endLineNumber,le.endColumn));ge.push(X);const B=ae.getModel();if(B===null)return;const $=[],Q=[];let Z=de,te=0;for(let re=0,le=ge.length;re=1){let Oe=!0;Ne===""&&(Oe=!1),Oe&&(Ne.charAt(Ne.length-1)===" "||Ne.charAt(Ne.length-1)===" ")&&(Oe=!1,Ne=Ne.replace(/[\s\uFEFF\xA0]+$/g," "));const Fe=Ge.substr(it-1);Ne+=(Oe?" ":"")+Fe,Oe?Le=Fe.length+1:Le=Fe.length}else Le=0}const Ke=new n.Range(Ce,ye,Ee,Me);if(!Ke.isEmpty()){let ze;me.isEmpty()?($.push(b.EditOperation.replace(Ke,Ne)),ze=new o.Selection(Ke.startLineNumber-te,Ne.length-Le+1,Ce-te,Ne.length-Le+1)):me.startLineNumber===me.endLineNumber?($.push(b.EditOperation.replace(Ke,Ne)),ze=new o.Selection(me.startLineNumber-te,me.startColumn,me.endLineNumber-te,me.endColumn)):($.push(b.EditOperation.replace(Ke,Ne)),ze=new o.Selection(me.startLineNumber-te,me.startColumn,me.startLineNumber-te,Ne.length-Ae)),n.Range.intersectRanges(Ke,de)!==null?Z=ze:Q.push(ze)}te+=Ke.endLineNumber-Ke.startLineNumber}Q.unshift(Z),ae.pushUndoStop(),ae.executeEdits(this.id,$,Q),ae.pushUndoStop()}}e.JoinLinesAction=H;class z extends I.EditorAction{constructor(){super({id:"editor.action.transpose",label:c.localize(1128,"Transpose Characters around the Cursor"),alias:"Transpose Characters around the Cursor",precondition:t.EditorContextKeys.writable})}run(pe,ae){const ee=ae.getSelections();if(ee===null)return;const de=ae.getModel();if(de===null)return;const ge=[];for(let X=0,B=ee.length;X=Z){if(Q.lineNumber===de.getLineCount())continue;const te=new n.Range(Q.lineNumber,Math.max(1,Q.column-1),Q.lineNumber+1,1),re=de.getValueInRange(te).split("").reverse().join("");ge.push(new E.ReplaceCommand(new o.Selection(Q.lineNumber,Math.max(1,Q.column-1),Q.lineNumber+1,1),re))}else{const te=new n.Range(Q.lineNumber,Math.max(1,Q.column-1),Q.lineNumber,Q.column+1),re=de.getValueInRange(te).split("").reverse().join("");ge.push(new E.ReplaceCommandThatPreservesSelection(te,re,new o.Selection(Q.lineNumber,Q.column+1,Q.lineNumber,Q.column+1)))}}ae.pushUndoStop(),ae.executeCommands(this.id,ge),ae.pushUndoStop()}}e.TransposeAction=z;class U extends I.EditorAction{run(pe,ae){const ee=ae.getSelections();if(ee===null)return;const de=ae.getModel();if(de===null)return;const ge=ae.getOption(132),X=[];for(const B of ee)if(B.isEmpty()){const $=B.getStartPosition(),Q=ae.getConfiguredWordAtPosition($);if(!Q)continue;const Z=new n.Range($.lineNumber,Q.startColumn,$.lineNumber,Q.endColumn),te=de.getValueInRange(Z);X.push(b.EditOperation.replace(Z,this._modifyText(te,ge)))}else{const $=de.getValueInRange(B);X.push(b.EditOperation.replace(B,this._modifyText($,ge)))}ae.pushUndoStop(),ae.executeEdits(this.id,X),ae.pushUndoStop()}}e.AbstractCaseAction=U;class j extends U{constructor(){super({id:"editor.action.transformToUppercase",label:c.localize(1129,"Transform to Uppercase"),alias:"Transform to Uppercase",precondition:t.EditorContextKeys.writable})}_modifyText(pe,ae){return pe.toLocaleUpperCase()}}e.UpperCaseAction=j;class Y extends U{constructor(){super({id:"editor.action.transformToLowercase",label:c.localize(1130,"Transform to Lowercase"),alias:"Transform to Lowercase",precondition:t.EditorContextKeys.writable})}_modifyText(pe,ae){return pe.toLocaleLowerCase()}}e.LowerCaseAction=Y;class G{constructor(pe,ae){this._pattern=pe,this._flags=ae,this._actual=null,this._evaluated=!1}get(){if(!this._evaluated){this._evaluated=!0;try{this._actual=new RegExp(this._pattern,this._flags)}catch{}}return this._actual}isSupported(){return this.get()!==null}}class K extends U{static{this.titleBoundary=new G("(^|[^\\p{L}\\p{N}']|((^|\\P{L})'))\\p{L}","gmu")}constructor(){super({id:"editor.action.transformToTitlecase",label:c.localize(1131,"Transform to Title Case"),alias:"Transform to Title Case",precondition:t.EditorContextKeys.writable})}_modifyText(pe,ae){const ee=K.titleBoundary.get();return ee?pe.toLocaleLowerCase().replace(ee,de=>de.toLocaleUpperCase()):pe}}e.TitleCaseAction=K;class R extends U{static{this.caseBoundary=new G("(\\p{Ll})(\\p{Lu})","gmu")}static{this.singleLetters=new G("(\\p{Lu}|\\p{N})(\\p{Lu})(\\p{Ll})","gmu")}constructor(){super({id:"editor.action.transformToSnakecase",label:c.localize(1132,"Transform to Snake Case"),alias:"Transform to Snake Case",precondition:t.EditorContextKeys.writable})}_modifyText(pe,ae){const ee=R.caseBoundary.get(),de=R.singleLetters.get();return!ee||!de?pe:pe.replace(ee,"$1_$2").replace(de,"$1_$2$3").toLocaleLowerCase()}}e.SnakeCaseAction=R;class J extends U{static{this.wordBoundary=new G("[_\\s-]","gm")}constructor(){super({id:"editor.action.transformToCamelcase",label:c.localize(1133,"Transform to Camel Case"),alias:"Transform to Camel Case",precondition:t.EditorContextKeys.writable})}_modifyText(pe,ae){const ee=J.wordBoundary.get();if(!ee)return pe;const de=pe.split(ee);return de.shift()+de.map(X=>X.substring(0,1).toLocaleUpperCase()+X.substring(1)).join("")}}e.CamelCaseAction=J;class ie extends U{static{this.wordBoundary=new G("[_\\s-]","gm")}static{this.wordBoundaryToMaintain=new G("(?<=\\.)","gm")}constructor(){super({id:"editor.action.transformToPascalcase",label:c.localize(1134,"Transform to Pascal Case"),alias:"Transform to Pascal Case",precondition:t.EditorContextKeys.writable})}_modifyText(pe,ae){const ee=ie.wordBoundary.get(),de=ie.wordBoundaryToMaintain.get();return!ee||!de?pe:pe.split(de).map(B=>B.split(ee)).flat().map(B=>B.substring(0,1).toLocaleUpperCase()+B.substring(1)).join("")}}e.PascalCaseAction=ie;class ue extends U{static isSupported(){return[this.caseBoundary,this.singleLetters,this.underscoreBoundary].every(ae=>ae.isSupported())}static{this.caseBoundary=new G("(\\p{Ll})(\\p{Lu})","gmu")}static{this.singleLetters=new G("(\\p{Lu}|\\p{N})(\\p{Lu}\\p{Ll})","gmu")}static{this.underscoreBoundary=new G("(\\S)(_)(\\S)","gm")}constructor(){super({id:"editor.action.transformToKebabcase",label:c.localize(1135,"Transform to Kebab Case"),alias:"Transform to Kebab Case",precondition:t.EditorContextKeys.writable})}_modifyText(pe,ae){const ee=ue.caseBoundary.get(),de=ue.singleLetters.get(),ge=ue.underscoreBoundary.get();return!ee||!de||!ge?pe:pe.replace(ge,"$1-$3").replace(ee,"$1-$2").replace(de,"$1-$2").toLocaleLowerCase()}}e.KebabCaseAction=ue,(0,I.registerEditorAction)(C),(0,I.registerEditorAction)(f),(0,I.registerEditorAction)(h),(0,I.registerEditorAction)(w),(0,I.registerEditorAction)(S),(0,I.registerEditorAction)(D),(0,I.registerEditorAction)(T),(0,I.registerEditorAction)(M),(0,I.registerEditorAction)(A),(0,I.registerEditorAction)(P),(0,I.registerEditorAction)(N),(0,I.registerEditorAction)(O),(0,I.registerEditorAction)(F),(0,I.registerEditorAction)(x),(0,I.registerEditorAction)(V),(0,I.registerEditorAction)(q),(0,I.registerEditorAction)(H),(0,I.registerEditorAction)(z),(0,I.registerEditorAction)(j),(0,I.registerEditorAction)(Y),R.caseBoundary.isSupported()&&R.singleLetters.isSupported()&&(0,I.registerEditorAction)(R),J.wordBoundary.isSupported()&&(0,I.registerEditorAction)(J),ie.wordBoundary.isSupported()&&(0,I.registerEditorAction)(ie),K.titleBoundary.isSupported()&&(0,I.registerEditorAction)(K),ue.isSupported()&&(0,I.registerEditorAction)(ue)}),define(ne[740],se([1,0,2,15]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class I extends d.Disposable{static{this.ID="editor.contrib.longLinesHelper"}constructor(y){super(),this._editor=y,this._register(this._editor.onMouseDown(m=>{const _=this._editor.getOption(118);_>=0&&m.target.type===6&&m.target.position.column>=_&&this._editor.updateOptions({stopRenderingLineAfter:-1})}))}}(0,k.registerEditorContribution)(I.ID,I,2)}),define(ne[184],se([1,0,207,46,6,57,2,15,4,120,3,12,59,5,525]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";var i;Object.defineProperty(e,"__esModule",{value:!0}),e.MessageController=void 0;let s=class{static{i=this}static{this.ID="editor.contrib.messageController"}static{this.MESSAGE_VISIBLE=new n.RawContextKey("messageVisible",!1,p.localize(1148,"Whether the editor is currently showing an inline message"))}static get(a){return a.getContribution(i.ID)}constructor(a,r,u){this._openerService=u,this._messageWidget=new y.MutableDisposable,this._messageListeners=new y.DisposableStore,this._mouseOverMessage=!1,this._editor=a,this._visible=i.MESSAGE_VISIBLE.bindTo(r)}dispose(){this._message?.dispose(),this._messageListeners.dispose(),this._messageWidget.dispose(),this._visible.reset()}showMessage(a,r){(0,k.alert)((0,E.isMarkdownString)(a)?a.value:a),this._visible.set(!0),this._messageWidget.clear(),this._messageListeners.clear(),this._message=(0,E.isMarkdownString)(a)?(0,d.renderMarkdown)(a,{actionHandler:{callback:C=>{this.closeMessage(),(0,b.openLinkFromMarkdown)(this._openerService,C,(0,E.isMarkdownString)(a)?a.isTrusted:void 0)},disposables:this._messageListeners}}):void 0,this._messageWidget.value=new c(this._editor,r,typeof a=="string"?a:this._message.element),this._messageListeners.add(I.Event.debounce(this._editor.onDidBlurEditorText,(C,f)=>f,0)(()=>{this._mouseOverMessage||this._messageWidget.value&&t.isAncestor(t.getActiveElement(),this._messageWidget.value.getDomNode())||this.closeMessage()})),this._messageListeners.add(this._editor.onDidChangeCursorPosition(()=>this.closeMessage())),this._messageListeners.add(this._editor.onDidDispose(()=>this.closeMessage())),this._messageListeners.add(this._editor.onDidChangeModel(()=>this.closeMessage())),this._messageListeners.add(t.addDisposableListener(this._messageWidget.value.getDomNode(),t.EventType.MOUSE_ENTER,()=>this._mouseOverMessage=!0,!0)),this._messageListeners.add(t.addDisposableListener(this._messageWidget.value.getDomNode(),t.EventType.MOUSE_LEAVE,()=>this._mouseOverMessage=!1,!0));let u;this._messageListeners.add(this._editor.onMouseMove(C=>{C.target.position&&(u?u.containsPosition(C.target.position)||this.closeMessage():u=new _.Range(r.lineNumber-3,1,C.target.position.lineNumber+3,1))}))}closeMessage(){this._visible.reset(),this._messageListeners.clear(),this._messageWidget.value&&this._messageListeners.add(c.fadeOut(this._messageWidget.value))}};e.MessageController=s,e.MessageController=s=i=ke([ce(1,n.IContextKeyService),ce(2,o.IOpenerService)],s);const g=m.EditorCommand.bindToContribution(s.get);(0,m.registerEditorCommand)(new g({id:"leaveEditorMessage",precondition:s.MESSAGE_VISIBLE,handler:l=>l.closeMessage(),kbOpts:{weight:130,primary:9}}));class c{static fadeOut(a){const r=()=>{a.dispose(),clearTimeout(u),a.getDomNode().removeEventListener("animationend",r)},u=setTimeout(r,110);return a.getDomNode().addEventListener("animationend",r),a.getDomNode().classList.add("fadeOut"),{dispose:r}}constructor(a,{lineNumber:r,column:u},C){this.allowEditorOverflow=!0,this.suppressMouseDown=!1,this._editor=a,this._editor.revealLinesInCenterIfOutsideViewport(r,r,0),this._position={lineNumber:r,column:u},this._domNode=document.createElement("div"),this._domNode.classList.add("monaco-editor-overlaymessage"),this._domNode.style.marginLeft="-6px";const f=document.createElement("div");f.classList.add("anchor","top"),this._domNode.appendChild(f);const h=document.createElement("div");typeof C=="string"?(h.classList.add("message"),h.textContent=C):(C.classList.add("message"),h.appendChild(C)),this._domNode.appendChild(h);const v=document.createElement("div");v.classList.add("anchor","below"),this._domNode.appendChild(v),this._editor.addContentWidget(this),this._domNode.classList.add("fadeIn")}dispose(){this._editor.removeContentWidget(this)}getId(){return"messageoverlay"}getDomNode(){return this._domNode}getPosition(){return{position:this._position,preference:[1,2],positionAffinity:1}}afterRender(a){this._domNode.classList.toggle("below",a===2)}}(0,m.registerEditorContribution)(s.ID,s,4)}),define(ne[741],se([1,0,57,2,15,184,3]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ReadOnlyMessageController=void 0;class m extends k.Disposable{static{this.ID="editor.contrib.readOnlyMessageController"}constructor(b){super(),this.editor=b,this._register(this.editor.onDidAttemptReadOnlyEdit(()=>this._onDidAttemptReadOnlyEdit()))}_onDidAttemptReadOnlyEdit(){const b=E.MessageController.get(this.editor);if(b&&this.editor.hasModel()){let p=this.editor.getOptions().get(93);p||(this.editor.isSimpleWidget?p=new d.MarkdownString(y.localize(1233,"Cannot edit in read-only input")):p=new d.MarkdownString(y.localize(1234,"Cannot edit in read-only editor"))),b.showMessage(p,this.editor.getPosition())}}}e.ReadOnlyMessageController=m,(0,I.registerEditorContribution)(m.ID,m,2)}),define(ne[742],se([1,0,13,18,8,15,9,4,23,20,340,621,3,29,24,17,78,19,22]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";var a;Object.defineProperty(e,"__esModule",{value:!0}),e.SmartSelectController=void 0,e.provideSelectionRanges=v;class r{constructor(S,L){this.index=S,this.ranges=L}mov(S){const L=this.index+(S?1:-1);if(L<0||L>=this.ranges.length)return this;const D=new r(L,this.ranges);return D.ranges[L].equalsRange(this.ranges[this.index])?D.mov(S):D}}let u=class{static{a=this}static{this.ID="editor.contrib.smartSelectController"}static get(S){return S.getContribution(a.ID)}constructor(S,L){this._editor=S,this._languageFeaturesService=L,this._ignoreSelection=!1}dispose(){this._selectionListener?.dispose()}async run(S){if(!this._editor.hasModel())return;const L=this._editor.getSelections(),D=this._editor.getModel();if(this._state||await v(this._languageFeaturesService.selectionRangeProvider,D,L.map(M=>M.getPosition()),this._editor.getOption(114),k.CancellationToken.None).then(M=>{if(!(!d.isNonEmptyArray(M)||M.length!==L.length)&&!(!this._editor.hasModel()||!d.equals(this._editor.getSelections(),L,(A,P)=>A.equalsSelection(P)))){for(let A=0;AP.containsPosition(L[A].getStartPosition())&&P.containsPosition(L[A].getEndPosition())),M[A].unshift(L[A]);this._state=M.map(A=>new r(0,A)),this._selectionListener?.dispose(),this._selectionListener=this._editor.onDidChangeCursorPosition(()=>{this._ignoreSelection||(this._selectionListener?.dispose(),this._state=void 0)})}}),!this._state)return;this._state=this._state.map(M=>M.mov(S));const T=this._state.map(M=>_.Selection.fromPositions(M.ranges[M.index].getStartPosition(),M.ranges[M.index].getEndPosition()));this._ignoreSelection=!0;try{this._editor.setSelections(T)}finally{this._ignoreSelection=!1}}};e.SmartSelectController=u,e.SmartSelectController=u=a=ke([ce(1,s.ILanguageFeaturesService)],u);class C extends E.EditorAction{constructor(S,L){super(L),this._forward=S}async run(S,L){const D=u.get(L);D&&await D.run(this._forward)}}class f extends C{constructor(){super(!0,{id:"editor.action.smartSelect.expand",label:o.localize(1253,"Expand Selection"),alias:"Expand Selection",precondition:void 0,kbOpts:{kbExpr:b.EditorContextKeys.editorTextFocus,primary:1553,mac:{primary:3345,secondary:[1297]},weight:100},menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"1_basic",title:o.localize(1254,"&&Expand Selection"),order:2}})}}i.CommandsRegistry.registerCommandAlias("editor.action.smartSelect.grow","editor.action.smartSelect.expand");class h extends C{constructor(){super(!1,{id:"editor.action.smartSelect.shrink",label:o.localize(1255,"Shrink Selection"),alias:"Shrink Selection",precondition:void 0,kbOpts:{kbExpr:b.EditorContextKeys.editorTextFocus,primary:1551,mac:{primary:3343,secondary:[1295]},weight:100},menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"1_basic",title:o.localize(1256,"&&Shrink Selection"),order:3}})}}(0,E.registerEditorContribution)(u.ID,u,4),(0,E.registerEditorAction)(f),(0,E.registerEditorAction)(h);async function v(w,S,L,D,T){const M=w.all(S).concat(new n.WordSelectionRangeProvider(D.selectSubwords));M.length===1&&M.unshift(new p.BracketSelectionRangeProvider);const A=[],P=[];for(const N of M)A.push(Promise.resolve(N.provideSelectionRanges(S,L,T)).then(O=>{if(d.isNonEmptyArray(O)&&O.length===L.length)for(let F=0;F{if(N.length===0)return[];N.sort((W,V)=>y.Position.isBefore(W.getStartPosition(),V.getStartPosition())?1:y.Position.isBefore(V.getStartPosition(),W.getStartPosition())||y.Position.isBefore(W.getEndPosition(),V.getEndPosition())?-1:y.Position.isBefore(V.getEndPosition(),W.getEndPosition())?1:0);const O=[];let F;for(const W of N)(!F||m.Range.containsRange(W,F)&&!m.Range.equalsRange(W,F))&&(O.push(W),F=W);if(!D.selectLeadingAndTrailingWhitespace)return O;const x=[O[0]];for(let W=1;W{g.hasChanged(127)&&(this._config=this._editor.getOption(127),this._checkForUnusualLineTerminators())})),this._register(this._editor.onDidChangeModel(()=>{this._checkForUnusualLineTerminators()})),this._register(this._editor.onDidChangeModelContent(g=>{g.isUndoing||this._checkForUnusualLineTerminators()})),this._checkForUnusualLineTerminators()}async _checkForUnusualLineTerminators(){if(this._config==="off"||!this._editor.hasModel())return;const t=this._editor.getModel();if(!t.mightContainUnusualLineTerminators()||p(this._codeEditorService,t)===!0||this._editor.getOption(92))return;if(this._config==="auto"){t.removeUnusualLineTerminators(this._editor.getSelections());return}if(this._isPresentingDialog)return;let s;try{this._isPresentingDialog=!0,s=await this._dialogService.confirm({title:y.localize(1410,"Unusual Line Terminators"),message:y.localize(1411,"Detected unusual line terminators"),detail:y.localize(1412,"The file '{0}' contains one or more unusual line terminator characters, like Line Separator (LS) or Paragraph Separator (PS).\n\nIt is recommended to remove them from the file. This can be configured via `editor.unusualLineTerminators`.",(0,k.basename)(t.uri)),primaryButton:y.localize(1413,"&&Remove Unusual Line Terminators"),cancelButton:y.localize(1414,"Ignore")})}finally{this._isPresentingDialog=!1}if(!s.confirmed){b(this._codeEditorService,t,!0);return}t.removeUnusualLineTerminators(this._editor.getSelections())}};e.UnusualLineTerminatorsDetector=n,e.UnusualLineTerminatorsDetector=n=ke([ce(1,m.IDialogService),ce(2,E.ICodeEditorService)],n),(0,I.registerEditorContribution)(n.ID,n,1)}),define(ne[411],se([1,0,15,146,37,76,199,166,9,4,23,20,36,3,61,12,179]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DeleteInsideWord=e.DeleteWordRight=e.DeleteWordEndRight=e.DeleteWordStartRight=e.DeleteWordLeft=e.DeleteWordEndLeft=e.DeleteWordStartLeft=e.DeleteWordRightCommand=e.DeleteWordLeftCommand=e.DeleteWordCommand=e.CursorWordAccessibilityRightSelect=e.CursorWordAccessibilityRight=e.CursorWordRightSelect=e.CursorWordEndRightSelect=e.CursorWordStartRightSelect=e.CursorWordRight=e.CursorWordEndRight=e.CursorWordStartRight=e.CursorWordAccessibilityLeftSelect=e.CursorWordAccessibilityLeft=e.CursorWordLeftSelect=e.CursorWordEndLeftSelect=e.CursorWordStartLeftSelect=e.CursorWordLeft=e.CursorWordEndLeft=e.CursorWordStartLeft=e.WordRightCommand=e.WordLeftCommand=e.MoveWordCommand=void 0;class c extends d.EditorCommand{constructor(K){super(K),this._inSelectionMode=K.inSelectionMode,this._wordNavigationType=K.wordNavigationType}runEditorCommand(K,R,J){if(!R.hasModel())return;const ie=(0,m.getMapForWordSeparators)(R.getOption(132),R.getOption(131)),ue=R.getModel(),he=R.getSelections(),pe=he.length>1,ae=he.map(ee=>{const de=new _.Position(ee.positionLineNumber,ee.positionColumn),ge=this._move(ie,ue,de,this._wordNavigationType,pe);return this._moveTo(ee,ge,this._inSelectionMode)});if(ue.pushStackElement(),R._getViewModel().setCursorStates("moveWordCommand",3,ae.map(ee=>E.CursorState.fromModelSelection(ee))),ae.length===1){const ee=new _.Position(ae[0].positionLineNumber,ae[0].positionColumn);R.revealPosition(ee,0)}}_moveTo(K,R,J){return J?new p.Selection(K.selectionStartLineNumber,K.selectionStartColumn,R.lineNumber,R.column):new p.Selection(R.lineNumber,R.column,R.lineNumber,R.column)}}e.MoveWordCommand=c;class l extends c{_move(K,R,J,ie,ue){return y.WordOperations.moveWordLeft(K,R,J,ie,ue)}}e.WordLeftCommand=l;class a extends c{_move(K,R,J,ie,ue){return y.WordOperations.moveWordRight(K,R,J,ie)}}e.WordRightCommand=a;class r extends l{constructor(){super({inSelectionMode:!1,wordNavigationType:0,id:"cursorWordStartLeft",precondition:void 0})}}e.CursorWordStartLeft=r;class u extends l{constructor(){super({inSelectionMode:!1,wordNavigationType:2,id:"cursorWordEndLeft",precondition:void 0})}}e.CursorWordEndLeft=u;class C extends l{constructor(){super({inSelectionMode:!1,wordNavigationType:1,id:"cursorWordLeft",precondition:void 0,kbOpts:{kbExpr:s.ContextKeyExpr.and(n.EditorContextKeys.textInputFocus,s.ContextKeyExpr.and(i.CONTEXT_ACCESSIBILITY_MODE_ENABLED,g.IsWindowsContext)?.negate()),primary:2063,mac:{primary:527},weight:100}})}}e.CursorWordLeft=C;class f extends l{constructor(){super({inSelectionMode:!0,wordNavigationType:0,id:"cursorWordStartLeftSelect",precondition:void 0})}}e.CursorWordStartLeftSelect=f;class h extends l{constructor(){super({inSelectionMode:!0,wordNavigationType:2,id:"cursorWordEndLeftSelect",precondition:void 0})}}e.CursorWordEndLeftSelect=h;class v extends l{constructor(){super({inSelectionMode:!0,wordNavigationType:1,id:"cursorWordLeftSelect",precondition:void 0,kbOpts:{kbExpr:s.ContextKeyExpr.and(n.EditorContextKeys.textInputFocus,s.ContextKeyExpr.and(i.CONTEXT_ACCESSIBILITY_MODE_ENABLED,g.IsWindowsContext)?.negate()),primary:3087,mac:{primary:1551},weight:100}})}}e.CursorWordLeftSelect=v;class w extends l{constructor(){super({inSelectionMode:!1,wordNavigationType:3,id:"cursorWordAccessibilityLeft",precondition:void 0})}_move(K,R,J,ie,ue){return super._move((0,m.getMapForWordSeparators)(I.EditorOptions.wordSeparators.defaultValue,K.intlSegmenterLocales),R,J,ie,ue)}}e.CursorWordAccessibilityLeft=w;class S extends l{constructor(){super({inSelectionMode:!0,wordNavigationType:3,id:"cursorWordAccessibilityLeftSelect",precondition:void 0})}_move(K,R,J,ie,ue){return super._move((0,m.getMapForWordSeparators)(I.EditorOptions.wordSeparators.defaultValue,K.intlSegmenterLocales),R,J,ie,ue)}}e.CursorWordAccessibilityLeftSelect=S;class L extends a{constructor(){super({inSelectionMode:!1,wordNavigationType:0,id:"cursorWordStartRight",precondition:void 0})}}e.CursorWordStartRight=L;class D extends a{constructor(){super({inSelectionMode:!1,wordNavigationType:2,id:"cursorWordEndRight",precondition:void 0,kbOpts:{kbExpr:s.ContextKeyExpr.and(n.EditorContextKeys.textInputFocus,s.ContextKeyExpr.and(i.CONTEXT_ACCESSIBILITY_MODE_ENABLED,g.IsWindowsContext)?.negate()),primary:2065,mac:{primary:529},weight:100}})}}e.CursorWordEndRight=D;class T extends a{constructor(){super({inSelectionMode:!1,wordNavigationType:2,id:"cursorWordRight",precondition:void 0})}}e.CursorWordRight=T;class M extends a{constructor(){super({inSelectionMode:!0,wordNavigationType:0,id:"cursorWordStartRightSelect",precondition:void 0})}}e.CursorWordStartRightSelect=M;class A extends a{constructor(){super({inSelectionMode:!0,wordNavigationType:2,id:"cursorWordEndRightSelect",precondition:void 0,kbOpts:{kbExpr:s.ContextKeyExpr.and(n.EditorContextKeys.textInputFocus,s.ContextKeyExpr.and(i.CONTEXT_ACCESSIBILITY_MODE_ENABLED,g.IsWindowsContext)?.negate()),primary:3089,mac:{primary:1553},weight:100}})}}e.CursorWordEndRightSelect=A;class P extends a{constructor(){super({inSelectionMode:!0,wordNavigationType:2,id:"cursorWordRightSelect",precondition:void 0})}}e.CursorWordRightSelect=P;class N extends a{constructor(){super({inSelectionMode:!1,wordNavigationType:3,id:"cursorWordAccessibilityRight",precondition:void 0})}_move(K,R,J,ie,ue){return super._move((0,m.getMapForWordSeparators)(I.EditorOptions.wordSeparators.defaultValue,K.intlSegmenterLocales),R,J,ie,ue)}}e.CursorWordAccessibilityRight=N;class O extends a{constructor(){super({inSelectionMode:!0,wordNavigationType:3,id:"cursorWordAccessibilityRightSelect",precondition:void 0})}_move(K,R,J,ie,ue){return super._move((0,m.getMapForWordSeparators)(I.EditorOptions.wordSeparators.defaultValue,K.intlSegmenterLocales),R,J,ie,ue)}}e.CursorWordAccessibilityRightSelect=O;class F extends d.EditorCommand{constructor(K){super(K),this._whitespaceHeuristics=K.whitespaceHeuristics,this._wordNavigationType=K.wordNavigationType}runEditorCommand(K,R,J){const ie=K.get(o.ILanguageConfigurationService);if(!R.hasModel())return;const ue=(0,m.getMapForWordSeparators)(R.getOption(132),R.getOption(131)),he=R.getModel(),pe=R.getSelections(),ae=R.getOption(6),ee=R.getOption(11),de=ie.getLanguageConfiguration(he.getLanguageId()).getAutoClosingPairs(),ge=R._getViewModel(),X=pe.map(B=>{const $=this._delete({wordSeparators:ue,model:he,selection:B,whitespaceHeuristics:this._whitespaceHeuristics,autoClosingDelete:R.getOption(9),autoClosingBrackets:ae,autoClosingQuotes:ee,autoClosingPairs:de,autoClosedCharacters:ge.getCursorAutoClosedCharacters()},this._wordNavigationType);return new k.ReplaceCommand($,"")});R.pushUndoStop(),R.executeCommands(this.id,X),R.pushUndoStop()}}e.DeleteWordCommand=F;class x extends F{_delete(K,R){const J=y.WordOperations.deleteWordLeft(K,R);return J||new b.Range(1,1,1,1)}}e.DeleteWordLeftCommand=x;class W extends F{_delete(K,R){const J=y.WordOperations.deleteWordRight(K,R);if(J)return J;const ie=K.model.getLineCount(),ue=K.model.getLineMaxColumn(ie);return new b.Range(ie,ue,ie,ue)}}e.DeleteWordRightCommand=W;class V extends x{constructor(){super({whitespaceHeuristics:!1,wordNavigationType:0,id:"deleteWordStartLeft",precondition:n.EditorContextKeys.writable})}}e.DeleteWordStartLeft=V;class q extends x{constructor(){super({whitespaceHeuristics:!1,wordNavigationType:2,id:"deleteWordEndLeft",precondition:n.EditorContextKeys.writable})}}e.DeleteWordEndLeft=q;class H extends x{constructor(){super({whitespaceHeuristics:!0,wordNavigationType:0,id:"deleteWordLeft",precondition:n.EditorContextKeys.writable,kbOpts:{kbExpr:n.EditorContextKeys.textInputFocus,primary:2049,mac:{primary:513},weight:100}})}}e.DeleteWordLeft=H;class z extends W{constructor(){super({whitespaceHeuristics:!1,wordNavigationType:0,id:"deleteWordStartRight",precondition:n.EditorContextKeys.writable})}}e.DeleteWordStartRight=z;class U extends W{constructor(){super({whitespaceHeuristics:!1,wordNavigationType:2,id:"deleteWordEndRight",precondition:n.EditorContextKeys.writable})}}e.DeleteWordEndRight=U;class j extends W{constructor(){super({whitespaceHeuristics:!0,wordNavigationType:2,id:"deleteWordRight",precondition:n.EditorContextKeys.writable,kbOpts:{kbExpr:n.EditorContextKeys.textInputFocus,primary:2068,mac:{primary:532},weight:100}})}}e.DeleteWordRight=j;class Y extends d.EditorAction{constructor(){super({id:"deleteInsideWord",precondition:n.EditorContextKeys.writable,label:t.localize(1427,"Delete Word"),alias:"Delete Word"})}run(K,R,J){if(!R.hasModel())return;const ie=(0,m.getMapForWordSeparators)(R.getOption(132),R.getOption(131)),ue=R.getModel(),pe=R.getSelections().map(ae=>{const ee=y.WordOperations.deleteInsideWord(ie,ue,ae);return new k.ReplaceCommand(ee,"")});R.pushUndoStop(),R.executeCommands(this.id,pe),R.pushUndoStop()}}e.DeleteInsideWord=Y,(0,d.registerEditorCommand)(new r),(0,d.registerEditorCommand)(new u),(0,d.registerEditorCommand)(new C),(0,d.registerEditorCommand)(new f),(0,d.registerEditorCommand)(new h),(0,d.registerEditorCommand)(new v),(0,d.registerEditorCommand)(new L),(0,d.registerEditorCommand)(new D),(0,d.registerEditorCommand)(new T),(0,d.registerEditorCommand)(new M),(0,d.registerEditorCommand)(new A),(0,d.registerEditorCommand)(new P),(0,d.registerEditorCommand)(new w),(0,d.registerEditorCommand)(new S),(0,d.registerEditorCommand)(new N),(0,d.registerEditorCommand)(new O),(0,d.registerEditorCommand)(new V),(0,d.registerEditorCommand)(new q),(0,d.registerEditorCommand)(new H),(0,d.registerEditorCommand)(new z),(0,d.registerEditorCommand)(new U),(0,d.registerEditorCommand)(new j),(0,d.registerEditorAction)(Y)}),define(ne[745],se([1,0,15,199,4,20,411,24]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CursorWordPartRightSelect=e.CursorWordPartRight=e.WordPartRightCommand=e.CursorWordPartLeftSelect=e.CursorWordPartLeft=e.WordPartLeftCommand=e.DeleteWordPartRight=e.DeleteWordPartLeft=void 0;class _ extends y.DeleteWordCommand{constructor(){super({whitespaceHeuristics:!0,wordNavigationType:0,id:"deleteWordPartLeft",precondition:E.EditorContextKeys.writable,kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:0,mac:{primary:769},weight:100}})}_delete(c,l){const a=k.WordPartOperations.deleteWordPartLeft(c);return a||new I.Range(1,1,1,1)}}e.DeleteWordPartLeft=_;class b extends y.DeleteWordCommand{constructor(){super({whitespaceHeuristics:!0,wordNavigationType:2,id:"deleteWordPartRight",precondition:E.EditorContextKeys.writable,kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:0,mac:{primary:788},weight:100}})}_delete(c,l){const a=k.WordPartOperations.deleteWordPartRight(c);if(a)return a;const r=c.model.getLineCount(),u=c.model.getLineMaxColumn(r);return new I.Range(r,u,r,u)}}e.DeleteWordPartRight=b;class p extends y.MoveWordCommand{_move(c,l,a,r,u){return k.WordPartOperations.moveWordPartLeft(c,l,a,u)}}e.WordPartLeftCommand=p;class n extends p{constructor(){super({inSelectionMode:!1,wordNavigationType:0,id:"cursorWordPartLeft",precondition:void 0,kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:0,mac:{primary:783},weight:100}})}}e.CursorWordPartLeft=n,m.CommandsRegistry.registerCommandAlias("cursorWordPartStartLeft","cursorWordPartLeft");class o extends p{constructor(){super({inSelectionMode:!0,wordNavigationType:0,id:"cursorWordPartLeftSelect",precondition:void 0,kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:0,mac:{primary:1807},weight:100}})}}e.CursorWordPartLeftSelect=o,m.CommandsRegistry.registerCommandAlias("cursorWordPartStartLeftSelect","cursorWordPartLeftSelect");class t extends y.MoveWordCommand{_move(c,l,a,r,u){return k.WordPartOperations.moveWordPartRight(c,l,a)}}e.WordPartRightCommand=t;class i extends t{constructor(){super({inSelectionMode:!1,wordNavigationType:2,id:"cursorWordPartRight",precondition:void 0,kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:0,mac:{primary:785},weight:100}})}}e.CursorWordPartRight=i;class s extends t{constructor(){super({inSelectionMode:!0,wordNavigationType:2,id:"cursorWordPartRightSelect",precondition:void 0,kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:0,mac:{primary:1809},weight:100}})}}e.CursorWordPartRightSelect=s,(0,d.registerEditorCommand)(new _),(0,d.registerEditorCommand)(new b),(0,d.registerEditorCommand)(new n),(0,d.registerEditorCommand)(new o),(0,d.registerEditorCommand)(new i),(0,d.registerEditorCommand)(new s)}),define(ne[746],se([1,0,5,2,15,16,538]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IPadShowKeyboard=void 0;class y extends k.Disposable{static{this.ID="editor.contrib.iPadShowKeyboard"}constructor(b){super(),this.editor=b,this.widget=null,E.isIOS&&(this._register(b.onDidChangeConfiguration(()=>this.update())),this.update())}update(){const b=!this.editor.getOption(92);!this.widget&&b?this.widget=new m(this.editor):this.widget&&!b&&(this.widget.dispose(),this.widget=null)}dispose(){super.dispose(),this.widget&&(this.widget.dispose(),this.widget=null)}}e.IPadShowKeyboard=y;class m extends k.Disposable{static{this.ID="editor.contrib.ShowKeyboardWidget"}constructor(b){super(),this.editor=b,this._domNode=document.createElement("textarea"),this._domNode.className="iPadShowKeyboard",this._register(d.addDisposableListener(this._domNode,"touchstart",p=>{this.editor.focus()})),this._register(d.addDisposableListener(this._domNode,"focus",p=>{this.editor.focus()})),this.editor.addOverlayWidget(this)}dispose(){this.editor.removeOverlayWidget(this),super.dispose()}getId(){return m.ID}getDomNode(){return this._domNode}getPosition(){return{preference:1}}}(0,I.registerEditorContribution)(y.ID,y,3)}),define(ne[747],se([1,0,5,33,2,15,27,148,177,43,153,107,539]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";var o;Object.defineProperty(e,"__esModule",{value:!0});let t=class extends I.Disposable{static{o=this}static{this.ID="editor.contrib.inspectTokens"}static get(a){return a.getContribution(o.ID)}constructor(a,r,u){super(),this._editor=a,this._languageService=u,this._widget=null,this._register(this._editor.onDidChangeModel(C=>this.stop())),this._register(this._editor.onDidChangeModelLanguage(C=>this.stop())),this._register(y.TokenizationRegistry.onDidChange(C=>this.stop())),this._register(this._editor.onKeyUp(C=>C.keyCode===9&&this.stop()))}dispose(){this.stop(),super.dispose()}launch(){this._widget||this._editor.hasModel()&&(this._widget=new c(this._editor,this._languageService))}stop(){this._widget&&(this._widget.dispose(),this._widget=null)}};t=o=ke([ce(1,p.IStandaloneThemeService),ce(2,b.ILanguageService)],t);class i extends E.EditorAction{constructor(){super({id:"editor.action.inspectTokens",label:n.InspectTokensNLS.inspectTokensAction,alias:"Developer: Inspect Tokens",precondition:void 0})}run(a,r){t.get(r)?.launch()}}function s(l){let a="";for(let r=0,u=l.length;r_.NullState,tokenize:(C,f,h)=>(0,_.nullTokenize)(a,h),tokenizeEncoded:(C,f,h)=>(0,_.nullTokenizeEncoded)(u,h)}}class c extends I.Disposable{static{this._ID="editor.contrib.inspectTokensWidget"}constructor(a,r){super(),this.allowEditorOverflow=!0,this._editor=a,this._languageService=r,this._model=this._editor.getModel(),this._domNode=document.createElement("div"),this._domNode.className="tokens-inspect-widget",this._tokenizationSupport=g(this._languageService.languageIdCodec,this._model.getLanguageId()),this._compute(this._editor.getPosition()),this._register(this._editor.onDidChangeCursorPosition(u=>this._compute(this._editor.getPosition()))),this._editor.addContentWidget(this)}dispose(){this._editor.removeContentWidget(this),super.dispose()}getId(){return c._ID}_compute(a){const r=this._getTokensAtLine(a.lineNumber);let u=0;for(let w=r.tokens1.length-1;w>=0;w--){const S=r.tokens1[w];if(a.column-1>=S.offset){u=w;break}}let C=0;for(let w=r.tokens2.length>>>1;w>=0;w--)if(a.column-1>=r.tokens2[w<<1]){C=w;break}const f=this._model.getLineContent(a.lineNumber);let h="";if(u"}static{this.TFIDF_THRESHOLD=.5}static{this.TFIDF_MAX_RESULTS=5}static{this.WORD_FILTER=(0,I.or)(I.matchesPrefix,I.matchesWords,I.matchesContiguousSubString)}constructor(h,v,w,S,L,D){super(a.PREFIX,h),this.instantiationService=v,this.keybindingService=w,this.commandService=S,this.telemetryService=L,this.dialogService=D,this.commandsHistory=this._register(this.instantiationService.createInstance(C)),this.options=h}async _getPicks(h,v,w,S){const L=await this.getCommandPicks(w);if(w.isCancellationRequested)return[];const D=(0,E.createSingleCallFunction)(()=>{const F=new _.TfIdfCalculator;F.updateDocuments(L.map(W=>({key:W.commandId,textChunks:[this.getTfIdfChunk(W)]})));const x=F.calculateScores(h,w);return(0,_.normalizeTfIdfScores)(x).filter(W=>W.score>a.TFIDF_THRESHOLD).slice(0,a.TFIDF_MAX_RESULTS)}),T=[];for(const F of L){const x=a.WORD_FILTER(h,F.label)??void 0,W=F.commandAlias?a.WORD_FILTER(h,F.commandAlias)??void 0:void 0;if(x||W)F.highlights={label:x,detail:this.options.showAlias?W:void 0},T.push(F);else if(h===F.commandId)T.push(F);else if(h.length>=3){const V=D();if(w.isCancellationRequested)return[];const q=V.find(H=>H.key===F.commandId);q&&(F.tfIdfScore=q.score,T.push(F))}}const M=new Map;for(const F of T){const x=M.get(F.label);x?(F.description=F.commandId,x.description=x.commandId):M.set(F.label,F)}T.sort((F,x)=>{if(F.tfIdfScore&&x.tfIdfScore)return F.tfIdfScore===x.tfIdfScore?F.label.localeCompare(x.label):x.tfIdfScore-F.tfIdfScore;if(F.tfIdfScore)return 1;if(x.tfIdfScore)return-1;const W=this.commandsHistory.peek(F.commandId),V=this.commandsHistory.peek(x.commandId);if(W&&V)return W>V?-1:1;if(W)return-1;if(V)return 1;if(this.options.suggestedCommandIds){const q=this.options.suggestedCommandIds.has(F.commandId),H=this.options.suggestedCommandIds.has(x.commandId);if(q&&H)return 0;if(q)return-1;if(H)return 1}return F.label.localeCompare(x.label)});const A=[];let P=!1,N=!0,O=!!this.options.suggestedCommandIds;for(let F=0;F{const F=await this.getAdditionalCommandPicks(L,T,h,w);if(w.isCancellationRequested)return[];const x=F.map(W=>this.toCommandPick(W,S));return N&&x[0]?.type!=="separator"&&x.unshift({type:"separator",label:(0,b.localize)(1576,"similar commands")}),x})()}:A}toCommandPick(h,v){if(h.type==="separator")return h;const w=this.keybindingService.lookupKeybinding(h.commandId),S=w?(0,b.localize)(1577,"{0}, {1}",h.label,w.getAriaLabel()):h.label;return{...h,ariaLabel:S,detail:this.options.showAlias&&h.commandAlias!==h.label?h.commandAlias:void 0,keybinding:w,accept:async()=>{this.commandsHistory.push(h.commandId),this.telemetryService.publicLog2("workbenchActionExecuted",{id:h.commandId,from:v?.from??"quick open"});try{h.args?.length?await this.commandService.executeCommand(h.commandId,...h.args):await this.commandService.executeCommand(h.commandId)}catch(L){(0,k.isCancellationError)(L)||this.dialogService.error((0,b.localize)(1578,"Command '{0}' resulted in an error",h.label),(0,d.toErrorMessage)(L))}}}}getTfIdfChunk({label:h,commandAlias:v,commandDescription:w}){let S=h;return v&&v!==h&&(S+=` - ${v}`),w&&w.value!==h&&(S+=` - ${w.value===w.original?w.value:`${w.value} (${w.original})`}`),S}};e.AbstractCommandsQuickAccessProvider=u,e.AbstractCommandsQuickAccessProvider=u=a=ke([ce(1,t.IInstantiationService),ce(2,i.IKeybindingService),ce(3,p.ICommandService),ce(4,l.ITelemetryService),ce(5,o.IDialogService)],u);let C=class extends y.Disposable{static{r=this}static{this.DEFAULT_COMMANDS_HISTORY_LENGTH=50}static{this.PREF_KEY_CACHE="commandPalette.mru.cache"}static{this.PREF_KEY_COUNTER="commandPalette.mru.counter"}static{this.counter=1}static{this.hasChanges=!1}constructor(h,v,w){super(),this.storageService=h,this.configurationService=v,this.logService=w,this.configuredCommandsHistoryLength=0,this.updateConfiguration(),this.load(),this.registerListeners()}registerListeners(){this._register(this.configurationService.onDidChangeConfiguration(h=>this.updateConfiguration(h))),this._register(this.storageService.onWillSaveState(h=>{h.reason===c.WillSaveStateReason.SHUTDOWN&&this.saveState()}))}updateConfiguration(h){h&&!h.affectsConfiguration("workbench.commandPalette.history")||(this.configuredCommandsHistoryLength=r.getConfiguredCommandHistoryLength(this.configurationService),r.cache&&r.cache.limit!==this.configuredCommandsHistoryLength&&(r.cache.limit=this.configuredCommandsHistoryLength,r.hasChanges=!0))}load(){const h=this.storageService.get(r.PREF_KEY_CACHE,0);let v;if(h)try{v=JSON.parse(h)}catch(S){this.logService.error(`[CommandsHistory] invalid data: ${S}`)}const w=r.cache=new m.LRUCache(this.configuredCommandsHistoryLength,1);if(v){let S;v.usesLRU?S=v.entries:S=v.entries.sort((L,D)=>L.value-D.value),S.forEach(L=>w.set(L.key,L.value))}r.counter=this.storageService.getNumber(r.PREF_KEY_COUNTER,0,r.counter)}push(h){r.cache&&(r.cache.set(h,r.counter++),r.hasChanges=!0)}peek(h){return r.cache?.peek(h)}saveState(){if(!r.cache||!r.hasChanges)return;const h={usesLRU:!0,entries:[]};r.cache.forEach((v,w)=>h.entries.push({key:w,value:v})),this.storageService.store(r.PREF_KEY_CACHE,JSON.stringify(h),0,0),this.storageService.store(r.PREF_KEY_COUNTER,r.counter,0,0),r.hasChanges=!1}static getConfiguredCommandHistoryLength(h){const w=h.getValue().workbench?.commandPalette?.history;return typeof w=="number"?w:r.DEFAULT_COMMANDS_HISTORY_LENGTH}};e.CommandsHistory=C,e.CommandsHistory=C=r=ke([ce(0,c.IStorageService),ce(1,n.IConfigurationService),ce(2,s.ILogService)],C)}),define(ne[749],se([1,0,142,381,748]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractEditorCommandsQuickAccessProvider=void 0;class E extends I.AbstractCommandsQuickAccessProvider{constructor(m,_,b,p,n,o){super(m,_,b,p,n,o)}getCodeEditorCommandPicks(){const m=this.activeTextEditorControl;if(!m)return[];const _=[];for(const b of m.getSupportedActions()){let p;b.metadata?.description&&((0,k.isLocalizedString)(b.metadata.description)?p=b.metadata.description:p={original:b.metadata.description,value:b.metadata.description}),_.push({commandId:b.id,commandAlias:b.alias,commandDescription:p,label:(0,d.stripIcons)(b.label)||b.id})}return _}}e.AbstractEditorCommandsQuickAccessProvider=E}),define(ne[750],se([1,0,38,156,107,34,749,7,31,24,63,180,15,20,66]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GotoLineAction=e.StandaloneCommandsQuickAccessProvider=void 0;let s=class extends y.AbstractEditorCommandsQuickAccessProvider{get activeTextEditorControl(){return this.codeEditorService.getFocusedCodeEditor()??void 0}constructor(l,a,r,u,C,f){super({showAlias:!1},l,r,u,C,f),this.codeEditorService=a}async getCommandPicks(){return this.getCodeEditorCommandPicks()}hasAdditionalCommandPicks(){return!1}async getAdditionalCommandPicks(){return[]}};e.StandaloneCommandsQuickAccessProvider=s,e.StandaloneCommandsQuickAccessProvider=s=ke([ce(0,m.IInstantiationService),ce(1,E.ICodeEditorService),ce(2,_.IKeybindingService),ce(3,b.ICommandService),ce(4,p.ITelemetryService),ce(5,n.IDialogService)],s);class g extends o.EditorAction{static{this.ID="editor.action.quickCommand"}constructor(){super({id:g.ID,label:I.QuickCommandNLS.quickCommandActionLabel,alias:"Command Palette",precondition:void 0,kbOpts:{kbExpr:t.EditorContextKeys.focus,primary:59,weight:100},contextMenuOpts:{group:"z_commands",order:1}})}run(l){l.get(i.IQuickInputService).quickAccess.show(s.PREFIX)}}e.GotoLineAction=g,(0,o.registerEditorAction)(g),d.Registry.as(k.Extensions.Quickaccess).registerQuickAccessProvider({ctor:s,prefix:s.PREFIX,helpEntries:[{description:I.QuickCommandNLS.quickCommandHelp,commandId:g.ID}]})}),define(ne[89],se([1,0,90,14,33,6,273,38,3]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.workbenchColorsSchemaId=e.DEFAULT_COLOR_CONFIG_VALUE=e.Extensions=void 0,e.asCssVariableName=b,e.asCssVariable=p,e.asCssVariableWithDefault=n,e.isColorDefaults=o,e.registerColor=s,e.executeTransform=g,e.darken=c,e.lighten=l,e.transparent=a,e.oneOf=r,e.ifDefinedThenElse=u,e.lessProminent=C,e.resolveColorValue=f;function b(w){return`--vscode-${w.replace(/\./g,"-")}`}function p(w){return`var(${b(w)})`}function n(w,S){return`var(${b(w)}, ${S})`}function o(w){return w!==null&&typeof w=="object"&&"light"in w&&"dark"in w}e.Extensions={ColorContribution:"base.contributions.colors"},e.DEFAULT_COLOR_CONFIG_VALUE="default";class t{constructor(){this._onDidChangeSchema=new E.Emitter,this.onDidChangeSchema=this._onDidChangeSchema.event,this.colorSchema={type:"object",properties:{}},this.colorReferenceSchema={type:"string",enum:[],enumDescriptions:[]},this.colorsById={}}registerColor(S,L,D,T=!1,M){const A={id:S,description:D,defaults:L,needsTransparency:T,deprecationMessage:M};this.colorsById[S]=A;const P={type:"string",format:"color-hex",defaultSnippets:[{body:"${1:#ff0000}"}]};return M&&(P.deprecationMessage=M),T&&(P.pattern="^#(?:(?[0-9a-fA-f]{3}[0-9a-eA-E])|(?:[0-9a-fA-F]{6}(?:(?![fF]{2})(?:[0-9a-fA-F]{2}))))?$",P.patternErrorMessage=_.localize(1836,"This color must be transparent or it will obscure content")),this.colorSchema.properties[S]={description:D,oneOf:[P,{type:"string",const:e.DEFAULT_COLOR_CONFIG_VALUE,description:_.localize(1837,"Use the default color.")}]},this.colorReferenceSchema.enum.push(S),this.colorReferenceSchema.enumDescriptions.push(D),this._onDidChangeSchema.fire(),S}getColors(){return Object.keys(this.colorsById).map(S=>this.colorsById[S])}resolveDefaultColor(S,L){const D=this.colorsById[S];if(D?.defaults){const T=o(D.defaults)?D.defaults[L.type]:D.defaults;return f(T,L)}}getColorSchema(){return this.colorSchema}toString(){const S=(L,D)=>{const T=L.indexOf(".")===-1?0:1,M=D.indexOf(".")===-1?0:1;return T!==M?T-M:L.localeCompare(D)};return Object.keys(this.colorsById).sort(S).map(L=>`- \`${L}\`: ${this.colorsById[L].description}`).join(` `)}}const i=new t;m.Registry.add(e.Extensions.ColorContribution,i);function s(w,S,L,D,T){return i.registerColor(w,S,L,D,T)}function g(w,S){switch(w.op){case 0:return f(w.value,S)?.darken(w.factor);case 1:return f(w.value,S)?.lighten(w.factor);case 2:return f(w.value,S)?.transparent(w.factor);case 3:{const L=f(w.background,S);return L?f(w.value,S)?.makeOpaque(L):f(w.value,S)}case 4:for(const L of w.values){const D=f(L,S);if(D)return D}return;case 6:return f(S.defines(w.if)?w.then:w.else,S);case 5:{const L=f(w.value,S);if(!L)return;const D=f(w.background,S);return D?L.isDarkerThan(D)?I.Color.getLighterColor(L,D,w.factor).transparent(w.transparency):I.Color.getDarkerColor(L,D,w.factor).transparent(w.transparency):L.transparent(w.factor*w.transparency)}default:throw(0,d.assertNever)(w)}}function c(w,S){return{op:0,value:w,factor:S}}function l(w,S){return{op:1,value:w,factor:S}}function a(w,S){return{op:2,value:w,factor:S}}function r(...w){return{op:4,values:w}}function u(w,S,L){return{op:6,if:w,then:S,else:L}}function C(w,S,L,D){return{op:5,value:w,background:S,factor:L,transparency:D}}function f(w,S){if(w!==null){if(typeof w=="string")return w[0]==="#"?I.Color.fromHex(w):S.getColor(w);if(w instanceof I.Color)return w;if(typeof w=="object")return g(w,S)}}e.workbenchColorsSchemaId="vscode://schemas/workbench-colors";const h=m.Registry.as(y.Extensions.JSONContribution);h.registerSchema(e.workbenchColorsSchemaId,i.getColorSchema());const v=new k.RunOnceScheduler(()=>h.notifySchemaChanged(e.workbenchColorsSchemaId),200);i.onDidChangeSchema(()=>{v.isScheduled()||v.schedule()})}),define(ne[123],se([1,0,3,33,89]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.textCodeBlockBackground=e.textBlockQuoteBorder=e.textBlockQuoteBackground=e.textPreformatBackground=e.textPreformatForeground=e.textSeparatorForeground=e.textLinkActiveForeground=e.textLinkForeground=e.selectionBackground=e.activeContrastBorder=e.contrastBorder=e.focusBorder=e.iconForeground=e.descriptionForeground=e.errorForeground=e.disabledForeground=e.foreground=void 0,e.foreground=(0,I.registerColor)("foreground",{dark:"#CCCCCC",light:"#616161",hcDark:"#FFFFFF",hcLight:"#292929"},d.localize(1599,"Overall foreground color. This color is only used if not overridden by a component.")),e.disabledForeground=(0,I.registerColor)("disabledForeground",{dark:"#CCCCCC80",light:"#61616180",hcDark:"#A5A5A5",hcLight:"#7F7F7F"},d.localize(1600,"Overall foreground for disabled elements. This color is only used if not overridden by a component.")),e.errorForeground=(0,I.registerColor)("errorForeground",{dark:"#F48771",light:"#A1260D",hcDark:"#F48771",hcLight:"#B5200D"},d.localize(1601,"Overall foreground color for error messages. This color is only used if not overridden by a component.")),e.descriptionForeground=(0,I.registerColor)("descriptionForeground",{light:"#717171",dark:(0,I.transparent)(e.foreground,.7),hcDark:(0,I.transparent)(e.foreground,.7),hcLight:(0,I.transparent)(e.foreground,.7)},d.localize(1602,"Foreground color for description text providing additional information, for example for a label.")),e.iconForeground=(0,I.registerColor)("icon.foreground",{dark:"#C5C5C5",light:"#424242",hcDark:"#FFFFFF",hcLight:"#292929"},d.localize(1603,"The default color for icons in the workbench.")),e.focusBorder=(0,I.registerColor)("focusBorder",{dark:"#007FD4",light:"#0090F1",hcDark:"#F38518",hcLight:"#006BBD"},d.localize(1604,"Overall border color for focused elements. This color is only used if not overridden by a component.")),e.contrastBorder=(0,I.registerColor)("contrastBorder",{light:null,dark:null,hcDark:"#6FC3DF",hcLight:"#0F4A85"},d.localize(1605,"An extra border around elements to separate them from others for greater contrast.")),e.activeContrastBorder=(0,I.registerColor)("contrastActiveBorder",{light:null,dark:null,hcDark:e.focusBorder,hcLight:e.focusBorder},d.localize(1606,"An extra border around active elements to separate them from others for greater contrast.")),e.selectionBackground=(0,I.registerColor)("selection.background",null,d.localize(1607,"The background color of text selections in the workbench (e.g. for input fields or text areas). Note that this does not apply to selections within the editor.")),e.textLinkForeground=(0,I.registerColor)("textLink.foreground",{light:"#006AB1",dark:"#3794FF",hcDark:"#21A6FF",hcLight:"#0F4A85"},d.localize(1608,"Foreground color for links in text.")),e.textLinkActiveForeground=(0,I.registerColor)("textLink.activeForeground",{light:"#006AB1",dark:"#3794FF",hcDark:"#21A6FF",hcLight:"#0F4A85"},d.localize(1609,"Foreground color for links in text when clicked on and on mouse hover.")),e.textSeparatorForeground=(0,I.registerColor)("textSeparator.foreground",{light:"#0000002e",dark:"#ffffff2e",hcDark:k.Color.black,hcLight:"#292929"},d.localize(1610,"Color for text separators.")),e.textPreformatForeground=(0,I.registerColor)("textPreformat.foreground",{light:"#A31515",dark:"#D7BA7D",hcDark:"#000000",hcLight:"#FFFFFF"},d.localize(1611,"Foreground color for preformatted text segments.")),e.textPreformatBackground=(0,I.registerColor)("textPreformat.background",{light:"#0000001A",dark:"#FFFFFF1A",hcDark:"#FFFFFF",hcLight:"#09345f"},d.localize(1612,"Background color for preformatted text segments.")),e.textBlockQuoteBackground=(0,I.registerColor)("textBlockQuote.background",{light:"#f2f2f2",dark:"#222222",hcDark:null,hcLight:"#F2F2F2"},d.localize(1613,"Background color for block quotes in text.")),e.textBlockQuoteBorder=(0,I.registerColor)("textBlockQuote.border",{light:"#007acc80",dark:"#007acc80",hcDark:k.Color.white,hcLight:"#292929"},d.localize(1614,"Border color for block quotes in text.")),e.textCodeBlockBackground=(0,I.registerColor)("textCodeBlock.background",{light:"#dcdcdc66",dark:"#0a0a0a66",hcDark:k.Color.black,hcLight:"#F2F2F2"},d.localize(1615,"Background color for code blocks in text."))}),define(ne[278],se([1,0,3,33,89,123]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.progressBarBackground=e.scrollbarSliderActiveBackground=e.scrollbarSliderHoverBackground=e.scrollbarSliderBackground=e.scrollbarShadow=e.badgeForeground=e.badgeBackground=e.sashHoverBorder=void 0,e.sashHoverBorder=(0,I.registerColor)("sash.hoverBorder",E.focusBorder,d.localize(1816,"Border color of active sashes.")),e.badgeBackground=(0,I.registerColor)("badge.background",{dark:"#4D4D4D",light:"#C4C4C4",hcDark:k.Color.black,hcLight:"#0F4A85"},d.localize(1817,"Badge background color. Badges are small information labels, e.g. for search results count.")),e.badgeForeground=(0,I.registerColor)("badge.foreground",{dark:k.Color.white,light:"#333",hcDark:k.Color.white,hcLight:k.Color.white},d.localize(1818,"Badge foreground color. Badges are small information labels, e.g. for search results count.")),e.scrollbarShadow=(0,I.registerColor)("scrollbar.shadow",{dark:"#000000",light:"#DDDDDD",hcDark:null,hcLight:null},d.localize(1819,"Scrollbar shadow to indicate that the view is scrolled.")),e.scrollbarSliderBackground=(0,I.registerColor)("scrollbarSlider.background",{dark:k.Color.fromHex("#797979").transparent(.4),light:k.Color.fromHex("#646464").transparent(.4),hcDark:(0,I.transparent)(E.contrastBorder,.6),hcLight:(0,I.transparent)(E.contrastBorder,.4)},d.localize(1820,"Scrollbar slider background color.")),e.scrollbarSliderHoverBackground=(0,I.registerColor)("scrollbarSlider.hoverBackground",{dark:k.Color.fromHex("#646464").transparent(.7),light:k.Color.fromHex("#646464").transparent(.7),hcDark:(0,I.transparent)(E.contrastBorder,.8),hcLight:(0,I.transparent)(E.contrastBorder,.8)},d.localize(1821,"Scrollbar slider background color when hovering.")),e.scrollbarSliderActiveBackground=(0,I.registerColor)("scrollbarSlider.activeBackground",{dark:k.Color.fromHex("#BFBFBF").transparent(.4),light:k.Color.fromHex("#000000").transparent(.6),hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1822,"Scrollbar slider background color when clicked on.")),e.progressBarBackground=(0,I.registerColor)("progressBar.background",{dark:k.Color.fromHex("#0E70C0"),light:k.Color.fromHex("#0E70C0"),hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1823,"Background color of the progress bar that can show for long running operations."))}),define(ne[138],se([1,0,3,33,89,123,278]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.problemsInfoIconForeground=e.problemsWarningIconForeground=e.problemsErrorIconForeground=e.overviewRulerSelectionHighlightForeground=e.overviewRulerFindMatchForeground=e.overviewRulerCommonContentForeground=e.overviewRulerIncomingContentForeground=e.overviewRulerCurrentContentForeground=e.mergeBorder=e.mergeCommonContentBackground=e.mergeCommonHeaderBackground=e.mergeIncomingContentBackground=e.mergeIncomingHeaderBackground=e.mergeCurrentContentBackground=e.mergeCurrentHeaderBackground=e.breadcrumbsPickerBackground=e.breadcrumbsActiveSelectionForeground=e.breadcrumbsFocusForeground=e.breadcrumbsBackground=e.breadcrumbsForeground=e.toolbarActiveBackground=e.toolbarHoverOutline=e.toolbarHoverBackground=e.widgetBorder=e.widgetShadow=e.diffUnchangedTextBackground=e.diffUnchangedRegionForeground=e.diffUnchangedRegionBackground=e.diffDiagonalFill=e.diffBorder=e.diffRemovedOutline=e.diffInsertedOutline=e.diffOverviewRulerRemoved=e.diffOverviewRulerInserted=e.diffRemovedLineGutter=e.diffInsertedLineGutter=e.diffRemovedLine=e.diffInsertedLine=e.diffRemoved=e.diffInserted=e.defaultRemoveColor=e.defaultInsertColor=e.snippetFinalTabstopHighlightBorder=e.snippetFinalTabstopHighlightBackground=e.snippetTabstopHighlightBorder=e.snippetTabstopHighlightBackground=e.editorLightBulbAiForeground=e.editorLightBulbAutoFixForeground=e.editorLightBulbForeground=e.editorInlayHintParameterBackground=e.editorInlayHintParameterForeground=e.editorInlayHintTypeBackground=e.editorInlayHintTypeForeground=e.editorInlayHintBackground=e.editorInlayHintForeground=e.editorHoverStatusBarBackground=e.editorHoverBorder=e.editorHoverForeground=e.editorHoverBackground=e.editorHoverHighlight=e.editorFindRangeHighlightBorder=e.editorFindMatchHighlightBorder=e.editorFindMatchBorder=e.editorFindRangeHighlight=e.editorFindMatchHighlightForeground=e.editorFindMatchHighlight=e.editorFindMatchForeground=e.editorFindMatch=e.editorSelectionHighlightBorder=e.editorSelectionHighlight=e.editorInactiveSelection=e.editorSelectionForeground=e.editorSelectionBackground=e.editorActiveLinkForeground=e.editorHintBorder=e.editorHintForeground=e.editorInfoBorder=e.editorInfoForeground=e.editorInfoBackground=e.editorWarningBorder=e.editorWarningForeground=e.editorWarningBackground=e.editorErrorBorder=e.editorErrorForeground=e.editorErrorBackground=e.editorWidgetResizeBorder=e.editorWidgetBorder=e.editorWidgetForeground=e.editorWidgetBackground=e.editorStickyScrollShadow=e.editorStickyScrollBorder=e.editorStickyScrollHoverBackground=e.editorStickyScrollBackground=e.editorForeground=e.editorBackground=void 0,e.editorBackground=(0,I.registerColor)("editor.background",{light:"#ffffff",dark:"#1E1E1E",hcDark:k.Color.black,hcLight:k.Color.white},d.localize(1624,"Editor background color.")),e.editorForeground=(0,I.registerColor)("editor.foreground",{light:"#333333",dark:"#BBBBBB",hcDark:k.Color.white,hcLight:E.foreground},d.localize(1625,"Editor default foreground color.")),e.editorStickyScrollBackground=(0,I.registerColor)("editorStickyScroll.background",e.editorBackground,d.localize(1626,"Background color of sticky scroll in the editor")),e.editorStickyScrollHoverBackground=(0,I.registerColor)("editorStickyScrollHover.background",{dark:"#2A2D2E",light:"#F0F0F0",hcDark:null,hcLight:k.Color.fromHex("#0F4A85").transparent(.1)},d.localize(1627,"Background color of sticky scroll on hover in the editor")),e.editorStickyScrollBorder=(0,I.registerColor)("editorStickyScroll.border",{dark:null,light:null,hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1628,"Border color of sticky scroll in the editor")),e.editorStickyScrollShadow=(0,I.registerColor)("editorStickyScroll.shadow",y.scrollbarShadow,d.localize(1629," Shadow color of sticky scroll in the editor")),e.editorWidgetBackground=(0,I.registerColor)("editorWidget.background",{dark:"#252526",light:"#F3F3F3",hcDark:"#0C141F",hcLight:k.Color.white},d.localize(1630,"Background color of editor widgets, such as find/replace.")),e.editorWidgetForeground=(0,I.registerColor)("editorWidget.foreground",E.foreground,d.localize(1631,"Foreground color of editor widgets, such as find/replace.")),e.editorWidgetBorder=(0,I.registerColor)("editorWidget.border",{dark:"#454545",light:"#C8C8C8",hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1632,"Border color of editor widgets. The color is only used if the widget chooses to have a border and if the color is not overridden by a widget.")),e.editorWidgetResizeBorder=(0,I.registerColor)("editorWidget.resizeBorder",null,d.localize(1633,"Border color of the resize bar of editor widgets. The color is only used if the widget chooses to have a resize border and if the color is not overridden by a widget.")),e.editorErrorBackground=(0,I.registerColor)("editorError.background",null,d.localize(1634,"Background color of error text in the editor. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorErrorForeground=(0,I.registerColor)("editorError.foreground",{dark:"#F14C4C",light:"#E51400",hcDark:"#F48771",hcLight:"#B5200D"},d.localize(1635,"Foreground color of error squigglies in the editor.")),e.editorErrorBorder=(0,I.registerColor)("editorError.border",{dark:null,light:null,hcDark:k.Color.fromHex("#E47777").transparent(.8),hcLight:"#B5200D"},d.localize(1636,"If set, color of double underlines for errors in the editor.")),e.editorWarningBackground=(0,I.registerColor)("editorWarning.background",null,d.localize(1637,"Background color of warning text in the editor. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorWarningForeground=(0,I.registerColor)("editorWarning.foreground",{dark:"#CCA700",light:"#BF8803",hcDark:"#FFD370",hcLight:"#895503"},d.localize(1638,"Foreground color of warning squigglies in the editor.")),e.editorWarningBorder=(0,I.registerColor)("editorWarning.border",{dark:null,light:null,hcDark:k.Color.fromHex("#FFCC00").transparent(.8),hcLight:k.Color.fromHex("#FFCC00").transparent(.8)},d.localize(1639,"If set, color of double underlines for warnings in the editor.")),e.editorInfoBackground=(0,I.registerColor)("editorInfo.background",null,d.localize(1640,"Background color of info text in the editor. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorInfoForeground=(0,I.registerColor)("editorInfo.foreground",{dark:"#3794FF",light:"#1a85ff",hcDark:"#3794FF",hcLight:"#1a85ff"},d.localize(1641,"Foreground color of info squigglies in the editor.")),e.editorInfoBorder=(0,I.registerColor)("editorInfo.border",{dark:null,light:null,hcDark:k.Color.fromHex("#3794FF").transparent(.8),hcLight:"#292929"},d.localize(1642,"If set, color of double underlines for infos in the editor.")),e.editorHintForeground=(0,I.registerColor)("editorHint.foreground",{dark:k.Color.fromHex("#eeeeee").transparent(.7),light:"#6c6c6c",hcDark:null,hcLight:null},d.localize(1643,"Foreground color of hint squigglies in the editor.")),e.editorHintBorder=(0,I.registerColor)("editorHint.border",{dark:null,light:null,hcDark:k.Color.fromHex("#eeeeee").transparent(.8),hcLight:"#292929"},d.localize(1644,"If set, color of double underlines for hints in the editor.")),e.editorActiveLinkForeground=(0,I.registerColor)("editorLink.activeForeground",{dark:"#4E94CE",light:k.Color.blue,hcDark:k.Color.cyan,hcLight:"#292929"},d.localize(1645,"Color of active links.")),e.editorSelectionBackground=(0,I.registerColor)("editor.selectionBackground",{light:"#ADD6FF",dark:"#264F78",hcDark:"#f3f518",hcLight:"#0F4A85"},d.localize(1646,"Color of the editor selection.")),e.editorSelectionForeground=(0,I.registerColor)("editor.selectionForeground",{light:null,dark:null,hcDark:"#000000",hcLight:k.Color.white},d.localize(1647,"Color of the selected text for high contrast.")),e.editorInactiveSelection=(0,I.registerColor)("editor.inactiveSelectionBackground",{light:(0,I.transparent)(e.editorSelectionBackground,.5),dark:(0,I.transparent)(e.editorSelectionBackground,.5),hcDark:(0,I.transparent)(e.editorSelectionBackground,.7),hcLight:(0,I.transparent)(e.editorSelectionBackground,.5)},d.localize(1648,"Color of the selection in an inactive editor. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorSelectionHighlight=(0,I.registerColor)("editor.selectionHighlightBackground",{light:(0,I.lessProminent)(e.editorSelectionBackground,e.editorBackground,.3,.6),dark:(0,I.lessProminent)(e.editorSelectionBackground,e.editorBackground,.3,.6),hcDark:null,hcLight:null},d.localize(1649,"Color for regions with the same content as the selection. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorSelectionHighlightBorder=(0,I.registerColor)("editor.selectionHighlightBorder",{light:null,dark:null,hcDark:E.activeContrastBorder,hcLight:E.activeContrastBorder},d.localize(1650,"Border color for regions with the same content as the selection.")),e.editorFindMatch=(0,I.registerColor)("editor.findMatchBackground",{light:"#A8AC94",dark:"#515C6A",hcDark:null,hcLight:null},d.localize(1651,"Color of the current search match.")),e.editorFindMatchForeground=(0,I.registerColor)("editor.findMatchForeground",null,d.localize(1652,"Text color of the current search match.")),e.editorFindMatchHighlight=(0,I.registerColor)("editor.findMatchHighlightBackground",{light:"#EA5C0055",dark:"#EA5C0055",hcDark:null,hcLight:null},d.localize(1653,"Color of the other search matches. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorFindMatchHighlightForeground=(0,I.registerColor)("editor.findMatchHighlightForeground",null,d.localize(1654,"Foreground color of the other search matches."),!0),e.editorFindRangeHighlight=(0,I.registerColor)("editor.findRangeHighlightBackground",{dark:"#3a3d4166",light:"#b4b4b44d",hcDark:null,hcLight:null},d.localize(1655,"Color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorFindMatchBorder=(0,I.registerColor)("editor.findMatchBorder",{light:null,dark:null,hcDark:E.activeContrastBorder,hcLight:E.activeContrastBorder},d.localize(1656,"Border color of the current search match.")),e.editorFindMatchHighlightBorder=(0,I.registerColor)("editor.findMatchHighlightBorder",{light:null,dark:null,hcDark:E.activeContrastBorder,hcLight:E.activeContrastBorder},d.localize(1657,"Border color of the other search matches.")),e.editorFindRangeHighlightBorder=(0,I.registerColor)("editor.findRangeHighlightBorder",{dark:null,light:null,hcDark:(0,I.transparent)(E.activeContrastBorder,.4),hcLight:(0,I.transparent)(E.activeContrastBorder,.4)},d.localize(1658,"Border color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorHoverHighlight=(0,I.registerColor)("editor.hoverHighlightBackground",{light:"#ADD6FF26",dark:"#264f7840",hcDark:"#ADD6FF26",hcLight:null},d.localize(1659,"Highlight below the word for which a hover is shown. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorHoverBackground=(0,I.registerColor)("editorHoverWidget.background",e.editorWidgetBackground,d.localize(1660,"Background color of the editor hover.")),e.editorHoverForeground=(0,I.registerColor)("editorHoverWidget.foreground",e.editorWidgetForeground,d.localize(1661,"Foreground color of the editor hover.")),e.editorHoverBorder=(0,I.registerColor)("editorHoverWidget.border",e.editorWidgetBorder,d.localize(1662,"Border color of the editor hover.")),e.editorHoverStatusBarBackground=(0,I.registerColor)("editorHoverWidget.statusBarBackground",{dark:(0,I.lighten)(e.editorHoverBackground,.2),light:(0,I.darken)(e.editorHoverBackground,.05),hcDark:e.editorWidgetBackground,hcLight:e.editorWidgetBackground},d.localize(1663,"Background color of the editor hover status bar.")),e.editorInlayHintForeground=(0,I.registerColor)("editorInlayHint.foreground",{dark:"#969696",light:"#969696",hcDark:k.Color.white,hcLight:k.Color.black},d.localize(1664,"Foreground color of inline hints")),e.editorInlayHintBackground=(0,I.registerColor)("editorInlayHint.background",{dark:(0,I.transparent)(y.badgeBackground,.1),light:(0,I.transparent)(y.badgeBackground,.1),hcDark:(0,I.transparent)(k.Color.white,.1),hcLight:(0,I.transparent)(y.badgeBackground,.1)},d.localize(1665,"Background color of inline hints")),e.editorInlayHintTypeForeground=(0,I.registerColor)("editorInlayHint.typeForeground",e.editorInlayHintForeground,d.localize(1666,"Foreground color of inline hints for types")),e.editorInlayHintTypeBackground=(0,I.registerColor)("editorInlayHint.typeBackground",e.editorInlayHintBackground,d.localize(1667,"Background color of inline hints for types")),e.editorInlayHintParameterForeground=(0,I.registerColor)("editorInlayHint.parameterForeground",e.editorInlayHintForeground,d.localize(1668,"Foreground color of inline hints for parameters")),e.editorInlayHintParameterBackground=(0,I.registerColor)("editorInlayHint.parameterBackground",e.editorInlayHintBackground,d.localize(1669,"Background color of inline hints for parameters")),e.editorLightBulbForeground=(0,I.registerColor)("editorLightBulb.foreground",{dark:"#FFCC00",light:"#DDB100",hcDark:"#FFCC00",hcLight:"#007ACC"},d.localize(1670,"The color used for the lightbulb actions icon.")),e.editorLightBulbAutoFixForeground=(0,I.registerColor)("editorLightBulbAutoFix.foreground",{dark:"#75BEFF",light:"#007ACC",hcDark:"#75BEFF",hcLight:"#007ACC"},d.localize(1671,"The color used for the lightbulb auto fix actions icon.")),e.editorLightBulbAiForeground=(0,I.registerColor)("editorLightBulbAi.foreground",e.editorLightBulbForeground,d.localize(1672,"The color used for the lightbulb AI icon.")),e.snippetTabstopHighlightBackground=(0,I.registerColor)("editor.snippetTabstopHighlightBackground",{dark:new k.Color(new k.RGBA(124,124,124,.3)),light:new k.Color(new k.RGBA(10,50,100,.2)),hcDark:new k.Color(new k.RGBA(124,124,124,.3)),hcLight:new k.Color(new k.RGBA(10,50,100,.2))},d.localize(1673,"Highlight background color of a snippet tabstop.")),e.snippetTabstopHighlightBorder=(0,I.registerColor)("editor.snippetTabstopHighlightBorder",null,d.localize(1674,"Highlight border color of a snippet tabstop.")),e.snippetFinalTabstopHighlightBackground=(0,I.registerColor)("editor.snippetFinalTabstopHighlightBackground",null,d.localize(1675,"Highlight background color of the final tabstop of a snippet.")),e.snippetFinalTabstopHighlightBorder=(0,I.registerColor)("editor.snippetFinalTabstopHighlightBorder",{dark:"#525252",light:new k.Color(new k.RGBA(10,50,100,.5)),hcDark:"#525252",hcLight:"#292929"},d.localize(1676,"Highlight border color of the final tabstop of a snippet.")),e.defaultInsertColor=new k.Color(new k.RGBA(155,185,85,.2)),e.defaultRemoveColor=new k.Color(new k.RGBA(255,0,0,.2)),e.diffInserted=(0,I.registerColor)("diffEditor.insertedTextBackground",{dark:"#9ccc2c33",light:"#9ccc2c40",hcDark:null,hcLight:null},d.localize(1677,"Background color for text that got inserted. The color must not be opaque so as not to hide underlying decorations."),!0),e.diffRemoved=(0,I.registerColor)("diffEditor.removedTextBackground",{dark:"#ff000033",light:"#ff000033",hcDark:null,hcLight:null},d.localize(1678,"Background color for text that got removed. The color must not be opaque so as not to hide underlying decorations."),!0),e.diffInsertedLine=(0,I.registerColor)("diffEditor.insertedLineBackground",{dark:e.defaultInsertColor,light:e.defaultInsertColor,hcDark:null,hcLight:null},d.localize(1679,"Background color for lines that got inserted. The color must not be opaque so as not to hide underlying decorations."),!0),e.diffRemovedLine=(0,I.registerColor)("diffEditor.removedLineBackground",{dark:e.defaultRemoveColor,light:e.defaultRemoveColor,hcDark:null,hcLight:null},d.localize(1680,"Background color for lines that got removed. The color must not be opaque so as not to hide underlying decorations."),!0),e.diffInsertedLineGutter=(0,I.registerColor)("diffEditorGutter.insertedLineBackground",null,d.localize(1681,"Background color for the margin where lines got inserted.")),e.diffRemovedLineGutter=(0,I.registerColor)("diffEditorGutter.removedLineBackground",null,d.localize(1682,"Background color for the margin where lines got removed.")),e.diffOverviewRulerInserted=(0,I.registerColor)("diffEditorOverview.insertedForeground",null,d.localize(1683,"Diff overview ruler foreground for inserted content.")),e.diffOverviewRulerRemoved=(0,I.registerColor)("diffEditorOverview.removedForeground",null,d.localize(1684,"Diff overview ruler foreground for removed content.")),e.diffInsertedOutline=(0,I.registerColor)("diffEditor.insertedTextBorder",{dark:null,light:null,hcDark:"#33ff2eff",hcLight:"#374E06"},d.localize(1685,"Outline color for the text that got inserted.")),e.diffRemovedOutline=(0,I.registerColor)("diffEditor.removedTextBorder",{dark:null,light:null,hcDark:"#FF008F",hcLight:"#AD0707"},d.localize(1686,"Outline color for text that got removed.")),e.diffBorder=(0,I.registerColor)("diffEditor.border",{dark:null,light:null,hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1687,"Border color between the two text editors.")),e.diffDiagonalFill=(0,I.registerColor)("diffEditor.diagonalFill",{dark:"#cccccc33",light:"#22222233",hcDark:null,hcLight:null},d.localize(1688,"Color of the diff editor's diagonal fill. The diagonal fill is used in side-by-side diff views.")),e.diffUnchangedRegionBackground=(0,I.registerColor)("diffEditor.unchangedRegionBackground","sideBar.background",d.localize(1689,"The background color of unchanged blocks in the diff editor.")),e.diffUnchangedRegionForeground=(0,I.registerColor)("diffEditor.unchangedRegionForeground","foreground",d.localize(1690,"The foreground color of unchanged blocks in the diff editor.")),e.diffUnchangedTextBackground=(0,I.registerColor)("diffEditor.unchangedCodeBackground",{dark:"#74747429",light:"#b8b8b829",hcDark:null,hcLight:null},d.localize(1691,"The background color of unchanged code in the diff editor.")),e.widgetShadow=(0,I.registerColor)("widget.shadow",{dark:(0,I.transparent)(k.Color.black,.36),light:(0,I.transparent)(k.Color.black,.16),hcDark:null,hcLight:null},d.localize(1692,"Shadow color of widgets such as find/replace inside the editor.")),e.widgetBorder=(0,I.registerColor)("widget.border",{dark:null,light:null,hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1693,"Border color of widgets such as find/replace inside the editor.")),e.toolbarHoverBackground=(0,I.registerColor)("toolbar.hoverBackground",{dark:"#5a5d5e50",light:"#b8b8b850",hcDark:null,hcLight:null},d.localize(1694,"Toolbar background when hovering over actions using the mouse")),e.toolbarHoverOutline=(0,I.registerColor)("toolbar.hoverOutline",{dark:null,light:null,hcDark:E.activeContrastBorder,hcLight:E.activeContrastBorder},d.localize(1695,"Toolbar outline when hovering over actions using the mouse")),e.toolbarActiveBackground=(0,I.registerColor)("toolbar.activeBackground",{dark:(0,I.lighten)(e.toolbarHoverBackground,.1),light:(0,I.darken)(e.toolbarHoverBackground,.1),hcDark:null,hcLight:null},d.localize(1696,"Toolbar background when holding the mouse over actions")),e.breadcrumbsForeground=(0,I.registerColor)("breadcrumb.foreground",(0,I.transparent)(E.foreground,.8),d.localize(1697,"Color of focused breadcrumb items.")),e.breadcrumbsBackground=(0,I.registerColor)("breadcrumb.background",e.editorBackground,d.localize(1698,"Background color of breadcrumb items.")),e.breadcrumbsFocusForeground=(0,I.registerColor)("breadcrumb.focusForeground",{light:(0,I.darken)(E.foreground,.2),dark:(0,I.lighten)(E.foreground,.1),hcDark:(0,I.lighten)(E.foreground,.1),hcLight:(0,I.lighten)(E.foreground,.1)},d.localize(1699,"Color of focused breadcrumb items.")),e.breadcrumbsActiveSelectionForeground=(0,I.registerColor)("breadcrumb.activeSelectionForeground",{light:(0,I.darken)(E.foreground,.2),dark:(0,I.lighten)(E.foreground,.1),hcDark:(0,I.lighten)(E.foreground,.1),hcLight:(0,I.lighten)(E.foreground,.1)},d.localize(1700,"Color of selected breadcrumb items.")),e.breadcrumbsPickerBackground=(0,I.registerColor)("breadcrumbPicker.background",e.editorWidgetBackground,d.localize(1701,"Background color of breadcrumb item picker."));const m=.5,_=k.Color.fromHex("#40C8AE").transparent(m),b=k.Color.fromHex("#40A6FF").transparent(m),p=k.Color.fromHex("#606060").transparent(.4),n=.4,o=1;e.mergeCurrentHeaderBackground=(0,I.registerColor)("merge.currentHeaderBackground",{dark:_,light:_,hcDark:null,hcLight:null},d.localize(1702,"Current header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations."),!0),e.mergeCurrentContentBackground=(0,I.registerColor)("merge.currentContentBackground",(0,I.transparent)(e.mergeCurrentHeaderBackground,n),d.localize(1703,"Current content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations."),!0),e.mergeIncomingHeaderBackground=(0,I.registerColor)("merge.incomingHeaderBackground",{dark:b,light:b,hcDark:null,hcLight:null},d.localize(1704,"Incoming header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations."),!0),e.mergeIncomingContentBackground=(0,I.registerColor)("merge.incomingContentBackground",(0,I.transparent)(e.mergeIncomingHeaderBackground,n),d.localize(1705,"Incoming content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations."),!0),e.mergeCommonHeaderBackground=(0,I.registerColor)("merge.commonHeaderBackground",{dark:p,light:p,hcDark:null,hcLight:null},d.localize(1706,"Common ancestor header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations."),!0),e.mergeCommonContentBackground=(0,I.registerColor)("merge.commonContentBackground",(0,I.transparent)(e.mergeCommonHeaderBackground,n),d.localize(1707,"Common ancestor content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations."),!0),e.mergeBorder=(0,I.registerColor)("merge.border",{dark:null,light:null,hcDark:"#C3DF6F",hcLight:"#007ACC"},d.localize(1708,"Border color on headers and the splitter in inline merge-conflicts.")),e.overviewRulerCurrentContentForeground=(0,I.registerColor)("editorOverviewRuler.currentContentForeground",{dark:(0,I.transparent)(e.mergeCurrentHeaderBackground,o),light:(0,I.transparent)(e.mergeCurrentHeaderBackground,o),hcDark:e.mergeBorder,hcLight:e.mergeBorder},d.localize(1709,"Current overview ruler foreground for inline merge-conflicts.")),e.overviewRulerIncomingContentForeground=(0,I.registerColor)("editorOverviewRuler.incomingContentForeground",{dark:(0,I.transparent)(e.mergeIncomingHeaderBackground,o),light:(0,I.transparent)(e.mergeIncomingHeaderBackground,o),hcDark:e.mergeBorder,hcLight:e.mergeBorder},d.localize(1710,"Incoming overview ruler foreground for inline merge-conflicts.")),e.overviewRulerCommonContentForeground=(0,I.registerColor)("editorOverviewRuler.commonContentForeground",{dark:(0,I.transparent)(e.mergeCommonHeaderBackground,o),light:(0,I.transparent)(e.mergeCommonHeaderBackground,o),hcDark:e.mergeBorder,hcLight:e.mergeBorder},d.localize(1711,"Common ancestor overview ruler foreground for inline merge-conflicts.")),e.overviewRulerFindMatchForeground=(0,I.registerColor)("editorOverviewRuler.findMatchForeground",{dark:"#d186167e",light:"#d186167e",hcDark:"#AB5A00",hcLight:"#AB5A00"},d.localize(1712,"Overview ruler marker color for find matches. The color must not be opaque so as not to hide underlying decorations."),!0),e.overviewRulerSelectionHighlightForeground=(0,I.registerColor)("editorOverviewRuler.selectionHighlightForeground","#A0A0A0CC",d.localize(1713,"Overview ruler marker color for selection highlights. The color must not be opaque so as not to hide underlying decorations."),!0),e.problemsErrorIconForeground=(0,I.registerColor)("problemsErrorIcon.foreground",e.editorErrorForeground,d.localize(1714,"The color used for the problems error icon.")),e.problemsWarningIconForeground=(0,I.registerColor)("problemsWarningIcon.foreground",e.editorWarningForeground,d.localize(1715,"The color used for the problems warning icon.")),e.problemsInfoIconForeground=(0,I.registerColor)("problemsInfoIcon.foreground",e.editorInfoForeground,d.localize(1716,"The color used for the problems info icon."))}),define(ne[412],se([1,0,3,33,89,123,138]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.keybindingLabelBottomBorder=e.keybindingLabelBorder=e.keybindingLabelForeground=e.keybindingLabelBackground=e.checkboxSelectBorder=e.checkboxBorder=e.checkboxForeground=e.checkboxSelectBackground=e.checkboxBackground=e.radioInactiveHoverBackground=e.radioInactiveBorder=e.radioInactiveBackground=e.radioInactiveForeground=e.radioActiveBorder=e.radioActiveBackground=e.radioActiveForeground=e.buttonSecondaryHoverBackground=e.buttonSecondaryBackground=e.buttonSecondaryForeground=e.buttonBorder=e.buttonHoverBackground=e.buttonBackground=e.buttonSeparator=e.buttonForeground=e.selectBorder=e.selectForeground=e.selectListBackground=e.selectBackground=e.inputValidationErrorBorder=e.inputValidationErrorForeground=e.inputValidationErrorBackground=e.inputValidationWarningBorder=e.inputValidationWarningForeground=e.inputValidationWarningBackground=e.inputValidationInfoBorder=e.inputValidationInfoForeground=e.inputValidationInfoBackground=e.inputPlaceholderForeground=e.inputActiveOptionForeground=e.inputActiveOptionBackground=e.inputActiveOptionHoverBackground=e.inputActiveOptionBorder=e.inputBorder=e.inputForeground=e.inputBackground=void 0,e.inputBackground=(0,I.registerColor)("input.background",{dark:"#3C3C3C",light:k.Color.white,hcDark:k.Color.black,hcLight:k.Color.white},d.localize(1717,"Input box background.")),e.inputForeground=(0,I.registerColor)("input.foreground",E.foreground,d.localize(1718,"Input box foreground.")),e.inputBorder=(0,I.registerColor)("input.border",{dark:null,light:null,hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1719,"Input box border.")),e.inputActiveOptionBorder=(0,I.registerColor)("inputOption.activeBorder",{dark:"#007ACC",light:"#007ACC",hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1720,"Border color of activated options in input fields.")),e.inputActiveOptionHoverBackground=(0,I.registerColor)("inputOption.hoverBackground",{dark:"#5a5d5e80",light:"#b8b8b850",hcDark:null,hcLight:null},d.localize(1721,"Background color of activated options in input fields.")),e.inputActiveOptionBackground=(0,I.registerColor)("inputOption.activeBackground",{dark:(0,I.transparent)(E.focusBorder,.4),light:(0,I.transparent)(E.focusBorder,.2),hcDark:k.Color.transparent,hcLight:k.Color.transparent},d.localize(1722,"Background hover color of options in input fields.")),e.inputActiveOptionForeground=(0,I.registerColor)("inputOption.activeForeground",{dark:k.Color.white,light:k.Color.black,hcDark:E.foreground,hcLight:E.foreground},d.localize(1723,"Foreground color of activated options in input fields.")),e.inputPlaceholderForeground=(0,I.registerColor)("input.placeholderForeground",{light:(0,I.transparent)(E.foreground,.5),dark:(0,I.transparent)(E.foreground,.5),hcDark:(0,I.transparent)(E.foreground,.7),hcLight:(0,I.transparent)(E.foreground,.7)},d.localize(1724,"Input box foreground color for placeholder text.")),e.inputValidationInfoBackground=(0,I.registerColor)("inputValidation.infoBackground",{dark:"#063B49",light:"#D6ECF2",hcDark:k.Color.black,hcLight:k.Color.white},d.localize(1725,"Input validation background color for information severity.")),e.inputValidationInfoForeground=(0,I.registerColor)("inputValidation.infoForeground",{dark:null,light:null,hcDark:null,hcLight:E.foreground},d.localize(1726,"Input validation foreground color for information severity.")),e.inputValidationInfoBorder=(0,I.registerColor)("inputValidation.infoBorder",{dark:"#007acc",light:"#007acc",hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1727,"Input validation border color for information severity.")),e.inputValidationWarningBackground=(0,I.registerColor)("inputValidation.warningBackground",{dark:"#352A05",light:"#F6F5D2",hcDark:k.Color.black,hcLight:k.Color.white},d.localize(1728,"Input validation background color for warning severity.")),e.inputValidationWarningForeground=(0,I.registerColor)("inputValidation.warningForeground",{dark:null,light:null,hcDark:null,hcLight:E.foreground},d.localize(1729,"Input validation foreground color for warning severity.")),e.inputValidationWarningBorder=(0,I.registerColor)("inputValidation.warningBorder",{dark:"#B89500",light:"#B89500",hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1730,"Input validation border color for warning severity.")),e.inputValidationErrorBackground=(0,I.registerColor)("inputValidation.errorBackground",{dark:"#5A1D1D",light:"#F2DEDE",hcDark:k.Color.black,hcLight:k.Color.white},d.localize(1731,"Input validation background color for error severity.")),e.inputValidationErrorForeground=(0,I.registerColor)("inputValidation.errorForeground",{dark:null,light:null,hcDark:null,hcLight:E.foreground},d.localize(1732,"Input validation foreground color for error severity.")),e.inputValidationErrorBorder=(0,I.registerColor)("inputValidation.errorBorder",{dark:"#BE1100",light:"#BE1100",hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1733,"Input validation border color for error severity.")),e.selectBackground=(0,I.registerColor)("dropdown.background",{dark:"#3C3C3C",light:k.Color.white,hcDark:k.Color.black,hcLight:k.Color.white},d.localize(1734,"Dropdown background.")),e.selectListBackground=(0,I.registerColor)("dropdown.listBackground",{dark:null,light:null,hcDark:k.Color.black,hcLight:k.Color.white},d.localize(1735,"Dropdown list background.")),e.selectForeground=(0,I.registerColor)("dropdown.foreground",{dark:"#F0F0F0",light:E.foreground,hcDark:k.Color.white,hcLight:E.foreground},d.localize(1736,"Dropdown foreground.")),e.selectBorder=(0,I.registerColor)("dropdown.border",{dark:e.selectBackground,light:"#CECECE",hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1737,"Dropdown border.")),e.buttonForeground=(0,I.registerColor)("button.foreground",k.Color.white,d.localize(1738,"Button foreground color.")),e.buttonSeparator=(0,I.registerColor)("button.separator",(0,I.transparent)(e.buttonForeground,.4),d.localize(1739,"Button separator color.")),e.buttonBackground=(0,I.registerColor)("button.background",{dark:"#0E639C",light:"#007ACC",hcDark:null,hcLight:"#0F4A85"},d.localize(1740,"Button background color.")),e.buttonHoverBackground=(0,I.registerColor)("button.hoverBackground",{dark:(0,I.lighten)(e.buttonBackground,.2),light:(0,I.darken)(e.buttonBackground,.2),hcDark:e.buttonBackground,hcLight:e.buttonBackground},d.localize(1741,"Button background color when hovering.")),e.buttonBorder=(0,I.registerColor)("button.border",E.contrastBorder,d.localize(1742,"Button border color.")),e.buttonSecondaryForeground=(0,I.registerColor)("button.secondaryForeground",{dark:k.Color.white,light:k.Color.white,hcDark:k.Color.white,hcLight:E.foreground},d.localize(1743,"Secondary button foreground color.")),e.buttonSecondaryBackground=(0,I.registerColor)("button.secondaryBackground",{dark:"#3A3D41",light:"#5F6A79",hcDark:null,hcLight:k.Color.white},d.localize(1744,"Secondary button background color.")),e.buttonSecondaryHoverBackground=(0,I.registerColor)("button.secondaryHoverBackground",{dark:(0,I.lighten)(e.buttonSecondaryBackground,.2),light:(0,I.darken)(e.buttonSecondaryBackground,.2),hcDark:null,hcLight:null},d.localize(1745,"Secondary button background color when hovering.")),e.radioActiveForeground=(0,I.registerColor)("radio.activeForeground",e.inputActiveOptionForeground,d.localize(1746,"Foreground color of active radio option.")),e.radioActiveBackground=(0,I.registerColor)("radio.activeBackground",e.inputActiveOptionBackground,d.localize(1747,"Background color of active radio option.")),e.radioActiveBorder=(0,I.registerColor)("radio.activeBorder",e.inputActiveOptionBorder,d.localize(1748,"Border color of the active radio option.")),e.radioInactiveForeground=(0,I.registerColor)("radio.inactiveForeground",null,d.localize(1749,"Foreground color of inactive radio option.")),e.radioInactiveBackground=(0,I.registerColor)("radio.inactiveBackground",null,d.localize(1750,"Background color of inactive radio option.")),e.radioInactiveBorder=(0,I.registerColor)("radio.inactiveBorder",{light:(0,I.transparent)(e.radioActiveForeground,.2),dark:(0,I.transparent)(e.radioActiveForeground,.2),hcDark:(0,I.transparent)(e.radioActiveForeground,.4),hcLight:(0,I.transparent)(e.radioActiveForeground,.2)},d.localize(1751,"Border color of the inactive radio option.")),e.radioInactiveHoverBackground=(0,I.registerColor)("radio.inactiveHoverBackground",e.inputActiveOptionHoverBackground,d.localize(1752,"Background color of inactive active radio option when hovering.")),e.checkboxBackground=(0,I.registerColor)("checkbox.background",e.selectBackground,d.localize(1753,"Background color of checkbox widget.")),e.checkboxSelectBackground=(0,I.registerColor)("checkbox.selectBackground",y.editorWidgetBackground,d.localize(1754,"Background color of checkbox widget when the element it's in is selected.")),e.checkboxForeground=(0,I.registerColor)("checkbox.foreground",e.selectForeground,d.localize(1755,"Foreground color of checkbox widget.")),e.checkboxBorder=(0,I.registerColor)("checkbox.border",e.selectBorder,d.localize(1756,"Border color of checkbox widget.")),e.checkboxSelectBorder=(0,I.registerColor)("checkbox.selectBorder",E.iconForeground,d.localize(1757,"Border color of checkbox widget when the element it's in is selected.")),e.keybindingLabelBackground=(0,I.registerColor)("keybindingLabel.background",{dark:new k.Color(new k.RGBA(128,128,128,.17)),light:new k.Color(new k.RGBA(221,221,221,.4)),hcDark:k.Color.transparent,hcLight:k.Color.transparent},d.localize(1758,"Keybinding label background color. The keybinding label is used to represent a keyboard shortcut.")),e.keybindingLabelForeground=(0,I.registerColor)("keybindingLabel.foreground",{dark:k.Color.fromHex("#CCCCCC"),light:k.Color.fromHex("#555555"),hcDark:k.Color.white,hcLight:E.foreground},d.localize(1759,"Keybinding label foreground color. The keybinding label is used to represent a keyboard shortcut.")),e.keybindingLabelBorder=(0,I.registerColor)("keybindingLabel.border",{dark:new k.Color(new k.RGBA(51,51,51,.6)),light:new k.Color(new k.RGBA(204,204,204,.4)),hcDark:new k.Color(new k.RGBA(111,195,223)),hcLight:E.contrastBorder},d.localize(1760,"Keybinding label border color. The keybinding label is used to represent a keyboard shortcut.")),e.keybindingLabelBottomBorder=(0,I.registerColor)("keybindingLabel.bottomBorder",{dark:new k.Color(new k.RGBA(68,68,68,.6)),light:new k.Color(new k.RGBA(187,187,187,.4)),hcDark:new k.Color(new k.RGBA(111,195,223)),hcLight:E.foreground},d.localize(1761,"Keybinding label border bottom color. The keybinding label is used to represent a keyboard shortcut."))}),define(ne[279],se([1,0,3,33,89,123,138]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.editorActionListFocusBackground=e.editorActionListFocusForeground=e.editorActionListForeground=e.editorActionListBackground=e.tableOddRowsBackgroundColor=e.tableColumnsBorder=e.treeInactiveIndentGuidesStroke=e.treeIndentGuidesStroke=e.listDeemphasizedForeground=e.listFilterMatchHighlightBorder=e.listFilterMatchHighlight=e.listFilterWidgetShadow=e.listFilterWidgetNoMatchesOutline=e.listFilterWidgetOutline=e.listFilterWidgetBackground=e.listWarningForeground=e.listErrorForeground=e.listInvalidItemForeground=e.listFocusHighlightForeground=e.listHighlightForeground=e.listDropBetweenBackground=e.listDropOverBackground=e.listHoverForeground=e.listHoverBackground=e.listInactiveFocusOutline=e.listInactiveFocusBackground=e.listInactiveSelectionIconForeground=e.listInactiveSelectionForeground=e.listInactiveSelectionBackground=e.listActiveSelectionIconForeground=e.listActiveSelectionForeground=e.listActiveSelectionBackground=e.listFocusAndSelectionOutline=e.listFocusOutline=e.listFocusForeground=e.listFocusBackground=void 0,e.listFocusBackground=(0,I.registerColor)("list.focusBackground",null,d.localize(1762,"List/Tree background color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")),e.listFocusForeground=(0,I.registerColor)("list.focusForeground",null,d.localize(1763,"List/Tree foreground color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")),e.listFocusOutline=(0,I.registerColor)("list.focusOutline",{dark:E.focusBorder,light:E.focusBorder,hcDark:E.activeContrastBorder,hcLight:E.activeContrastBorder},d.localize(1764,"List/Tree outline color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")),e.listFocusAndSelectionOutline=(0,I.registerColor)("list.focusAndSelectionOutline",null,d.localize(1765,"List/Tree outline color for the focused item when the list/tree is active and selected. An active list/tree has keyboard focus, an inactive does not.")),e.listActiveSelectionBackground=(0,I.registerColor)("list.activeSelectionBackground",{dark:"#04395E",light:"#0060C0",hcDark:null,hcLight:k.Color.fromHex("#0F4A85").transparent(.1)},d.localize(1766,"List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")),e.listActiveSelectionForeground=(0,I.registerColor)("list.activeSelectionForeground",{dark:k.Color.white,light:k.Color.white,hcDark:null,hcLight:null},d.localize(1767,"List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")),e.listActiveSelectionIconForeground=(0,I.registerColor)("list.activeSelectionIconForeground",null,d.localize(1768,"List/Tree icon foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.")),e.listInactiveSelectionBackground=(0,I.registerColor)("list.inactiveSelectionBackground",{dark:"#37373D",light:"#E4E6F1",hcDark:null,hcLight:k.Color.fromHex("#0F4A85").transparent(.1)},d.localize(1769,"List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")),e.listInactiveSelectionForeground=(0,I.registerColor)("list.inactiveSelectionForeground",null,d.localize(1770,"List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")),e.listInactiveSelectionIconForeground=(0,I.registerColor)("list.inactiveSelectionIconForeground",null,d.localize(1771,"List/Tree icon foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")),e.listInactiveFocusBackground=(0,I.registerColor)("list.inactiveFocusBackground",null,d.localize(1772,"List/Tree background color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")),e.listInactiveFocusOutline=(0,I.registerColor)("list.inactiveFocusOutline",null,d.localize(1773,"List/Tree outline color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.")),e.listHoverBackground=(0,I.registerColor)("list.hoverBackground",{dark:"#2A2D2E",light:"#F0F0F0",hcDark:k.Color.white.transparent(.1),hcLight:k.Color.fromHex("#0F4A85").transparent(.1)},d.localize(1774,"List/Tree background when hovering over items using the mouse.")),e.listHoverForeground=(0,I.registerColor)("list.hoverForeground",null,d.localize(1775,"List/Tree foreground when hovering over items using the mouse.")),e.listDropOverBackground=(0,I.registerColor)("list.dropBackground",{dark:"#062F4A",light:"#D6EBFF",hcDark:null,hcLight:null},d.localize(1776,"List/Tree drag and drop background when moving items over other items when using the mouse.")),e.listDropBetweenBackground=(0,I.registerColor)("list.dropBetweenBackground",{dark:E.iconForeground,light:E.iconForeground,hcDark:null,hcLight:null},d.localize(1777,"List/Tree drag and drop border color when moving items between items when using the mouse.")),e.listHighlightForeground=(0,I.registerColor)("list.highlightForeground",{dark:"#2AAAFF",light:"#0066BF",hcDark:E.focusBorder,hcLight:E.focusBorder},d.localize(1778,"List/Tree foreground color of the match highlights when searching inside the list/tree.")),e.listFocusHighlightForeground=(0,I.registerColor)("list.focusHighlightForeground",{dark:e.listHighlightForeground,light:(0,I.ifDefinedThenElse)(e.listActiveSelectionBackground,e.listHighlightForeground,"#BBE7FF"),hcDark:e.listHighlightForeground,hcLight:e.listHighlightForeground},d.localize(1779,"List/Tree foreground color of the match highlights on actively focused items when searching inside the list/tree.")),e.listInvalidItemForeground=(0,I.registerColor)("list.invalidItemForeground",{dark:"#B89500",light:"#B89500",hcDark:"#B89500",hcLight:"#B5200D"},d.localize(1780,"List/Tree foreground color for invalid items, for example an unresolved root in explorer.")),e.listErrorForeground=(0,I.registerColor)("list.errorForeground",{dark:"#F88070",light:"#B01011",hcDark:null,hcLight:null},d.localize(1781,"Foreground color of list items containing errors.")),e.listWarningForeground=(0,I.registerColor)("list.warningForeground",{dark:"#CCA700",light:"#855F00",hcDark:null,hcLight:null},d.localize(1782,"Foreground color of list items containing warnings.")),e.listFilterWidgetBackground=(0,I.registerColor)("listFilterWidget.background",{light:(0,I.darken)(y.editorWidgetBackground,0),dark:(0,I.lighten)(y.editorWidgetBackground,0),hcDark:y.editorWidgetBackground,hcLight:y.editorWidgetBackground},d.localize(1783,"Background color of the type filter widget in lists and trees.")),e.listFilterWidgetOutline=(0,I.registerColor)("listFilterWidget.outline",{dark:k.Color.transparent,light:k.Color.transparent,hcDark:"#f38518",hcLight:"#007ACC"},d.localize(1784,"Outline color of the type filter widget in lists and trees.")),e.listFilterWidgetNoMatchesOutline=(0,I.registerColor)("listFilterWidget.noMatchesOutline",{dark:"#BE1100",light:"#BE1100",hcDark:E.contrastBorder,hcLight:E.contrastBorder},d.localize(1785,"Outline color of the type filter widget in lists and trees, when there are no matches.")),e.listFilterWidgetShadow=(0,I.registerColor)("listFilterWidget.shadow",y.widgetShadow,d.localize(1786,"Shadow color of the type filter widget in lists and trees.")),e.listFilterMatchHighlight=(0,I.registerColor)("list.filterMatchBackground",{dark:y.editorFindMatchHighlight,light:y.editorFindMatchHighlight,hcDark:null,hcLight:null},d.localize(1787,"Background color of the filtered match.")),e.listFilterMatchHighlightBorder=(0,I.registerColor)("list.filterMatchBorder",{dark:y.editorFindMatchHighlightBorder,light:y.editorFindMatchHighlightBorder,hcDark:E.contrastBorder,hcLight:E.activeContrastBorder},d.localize(1788,"Border color of the filtered match.")),e.listDeemphasizedForeground=(0,I.registerColor)("list.deemphasizedForeground",{dark:"#8C8C8C",light:"#8E8E90",hcDark:"#A7A8A9",hcLight:"#666666"},d.localize(1789,"List/Tree foreground color for items that are deemphasized.")),e.treeIndentGuidesStroke=(0,I.registerColor)("tree.indentGuidesStroke",{dark:"#585858",light:"#a9a9a9",hcDark:"#a9a9a9",hcLight:"#a5a5a5"},d.localize(1790,"Tree stroke color for the indentation guides.")),e.treeInactiveIndentGuidesStroke=(0,I.registerColor)("tree.inactiveIndentGuidesStroke",(0,I.transparent)(e.treeIndentGuidesStroke,.4),d.localize(1791,"Tree stroke color for the indentation guides that are not active.")),e.tableColumnsBorder=(0,I.registerColor)("tree.tableColumnsBorder",{dark:"#CCCCCC20",light:"#61616120",hcDark:null,hcLight:null},d.localize(1792,"Table border color between columns.")),e.tableOddRowsBackgroundColor=(0,I.registerColor)("tree.tableOddRowsBackground",{dark:(0,I.transparent)(E.foreground,.04),light:(0,I.transparent)(E.foreground,.04),hcDark:null,hcLight:null},d.localize(1793,"Background color for odd table rows.")),e.editorActionListBackground=(0,I.registerColor)("editorActionList.background",y.editorWidgetBackground,d.localize(1794,"Action List background color.")),e.editorActionListForeground=(0,I.registerColor)("editorActionList.foreground",y.editorWidgetForeground,d.localize(1795,"Action List foreground color.")),e.editorActionListFocusForeground=(0,I.registerColor)("editorActionList.focusForeground",e.listActiveSelectionForeground,d.localize(1796,"Action List foreground color for the focused item.")),e.editorActionListFocusBackground=(0,I.registerColor)("editorActionList.focusBackground",e.listActiveSelectionBackground,d.localize(1797,"Action List background color for the focused item."))}),define(ne[751],se([1,0,3,89,123,412,279]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.menuSeparatorBackground=e.menuSelectionBorder=e.menuSelectionBackground=e.menuSelectionForeground=e.menuBackground=e.menuForeground=e.menuBorder=void 0,e.menuBorder=(0,k.registerColor)("menu.border",{dark:null,light:null,hcDark:I.contrastBorder,hcLight:I.contrastBorder},d.localize(1798,"Border color of menus.")),e.menuForeground=(0,k.registerColor)("menu.foreground",E.selectForeground,d.localize(1799,"Foreground color of menu items.")),e.menuBackground=(0,k.registerColor)("menu.background",E.selectBackground,d.localize(1800,"Background color of menu items.")),e.menuSelectionForeground=(0,k.registerColor)("menu.selectionForeground",y.listActiveSelectionForeground,d.localize(1801,"Foreground color of the selected menu item in menus.")),e.menuSelectionBackground=(0,k.registerColor)("menu.selectionBackground",y.listActiveSelectionBackground,d.localize(1802,"Background color of the selected menu item in menus.")),e.menuSelectionBorder=(0,k.registerColor)("menu.selectionBorder",{dark:null,light:null,hcDark:I.activeContrastBorder,hcLight:I.activeContrastBorder},d.localize(1803,"Border color of the selected menu item in menus.")),e.menuSeparatorBackground=(0,k.registerColor)("menu.separatorBackground",{dark:"#606060",light:"#D4D4D4",hcDark:I.contrastBorder,hcLight:I.contrastBorder},d.localize(1804,"Color of a separator menu item in menus."))}),define(ne[413],se([1,0,3,33,89,138,278]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.minimapSliderActiveBackground=e.minimapSliderHoverBackground=e.minimapSliderBackground=e.minimapForegroundOpacity=e.minimapBackground=e.minimapError=e.minimapWarning=e.minimapInfo=e.minimapSelection=e.minimapSelectionOccurrenceHighlight=e.minimapFindMatch=void 0,e.minimapFindMatch=(0,I.registerColor)("minimap.findMatchHighlight",{light:"#d18616",dark:"#d18616",hcDark:"#AB5A00",hcLight:"#0F4A85"},d.localize(1805,"Minimap marker color for find matches."),!0),e.minimapSelectionOccurrenceHighlight=(0,I.registerColor)("minimap.selectionOccurrenceHighlight",{light:"#c9c9c9",dark:"#676767",hcDark:"#ffffff",hcLight:"#0F4A85"},d.localize(1806,"Minimap marker color for repeating editor selections."),!0),e.minimapSelection=(0,I.registerColor)("minimap.selectionHighlight",{light:"#ADD6FF",dark:"#264F78",hcDark:"#ffffff",hcLight:"#0F4A85"},d.localize(1807,"Minimap marker color for the editor selection."),!0),e.minimapInfo=(0,I.registerColor)("minimap.infoHighlight",{dark:E.editorInfoForeground,light:E.editorInfoForeground,hcDark:E.editorInfoBorder,hcLight:E.editorInfoBorder},d.localize(1808,"Minimap marker color for infos.")),e.minimapWarning=(0,I.registerColor)("minimap.warningHighlight",{dark:E.editorWarningForeground,light:E.editorWarningForeground,hcDark:E.editorWarningBorder,hcLight:E.editorWarningBorder},d.localize(1809,"Minimap marker color for warnings.")),e.minimapError=(0,I.registerColor)("minimap.errorHighlight",{dark:new k.Color(new k.RGBA(255,18,18,.7)),light:new k.Color(new k.RGBA(255,18,18,.7)),hcDark:new k.Color(new k.RGBA(255,50,50,1)),hcLight:"#B5200D"},d.localize(1810,"Minimap marker color for errors.")),e.minimapBackground=(0,I.registerColor)("minimap.background",null,d.localize(1811,"Minimap background color.")),e.minimapForegroundOpacity=(0,I.registerColor)("minimap.foregroundOpacity",k.Color.fromHex("#000f"),d.localize(1812,'Opacity of foreground elements rendered in the minimap. For example, "#000000c0" will render the elements with 75% opacity.')),e.minimapSliderBackground=(0,I.registerColor)("minimapSlider.background",(0,I.transparent)(y.scrollbarSliderBackground,.5),d.localize(1813,"Minimap slider background color.")),e.minimapSliderHoverBackground=(0,I.registerColor)("minimapSlider.hoverBackground",(0,I.transparent)(y.scrollbarSliderHoverBackground,.5),d.localize(1814,"Minimap slider background color when hovering.")),e.minimapSliderActiveBackground=(0,I.registerColor)("minimapSlider.activeBackground",(0,I.transparent)(y.scrollbarSliderActiveBackground,.5),d.localize(1815,"Minimap slider background color when clicked on."))}),define(ne[752],se([1,0,3,89,123,138,413]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.chartsPurple=e.chartsGreen=e.chartsOrange=e.chartsYellow=e.chartsBlue=e.chartsRed=e.chartsLines=e.chartsForeground=void 0,e.chartsForeground=(0,k.registerColor)("charts.foreground",I.foreground,d.localize(1616,"The foreground color used in charts.")),e.chartsLines=(0,k.registerColor)("charts.lines",(0,k.transparent)(I.foreground,.5),d.localize(1617,"The color used for horizontal lines in charts.")),e.chartsRed=(0,k.registerColor)("charts.red",E.editorErrorForeground,d.localize(1618,"The red color used in chart visualizations.")),e.chartsBlue=(0,k.registerColor)("charts.blue",E.editorInfoForeground,d.localize(1619,"The blue color used in chart visualizations.")),e.chartsYellow=(0,k.registerColor)("charts.yellow",E.editorWarningForeground,d.localize(1620,"The yellow color used in chart visualizations.")),e.chartsOrange=(0,k.registerColor)("charts.orange",y.minimapFindMatch,d.localize(1621,"The orange color used in chart visualizations.")),e.chartsGreen=(0,k.registerColor)("charts.green",{dark:"#89D185",light:"#388A34",hcDark:"#89D185",hcLight:"#374e06"},d.localize(1622,"The green color used in chart visualizations.")),e.chartsPurple=(0,k.registerColor)("charts.purple",{dark:"#B180D7",light:"#652D90",hcDark:"#B180D7",hcLight:"#652D90"},d.localize(1623,"The purple color used in chart visualizations."))}),define(ne[753],se([1,0,3,33,89,138,279]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.quickInputListFocusBackground=e.quickInputListFocusIconForeground=e.quickInputListFocusForeground=e._deprecatedQuickInputListFocusBackground=e.pickerGroupBorder=e.pickerGroupForeground=e.quickInputTitleBackground=e.quickInputForeground=e.quickInputBackground=void 0,e.quickInputBackground=(0,I.registerColor)("quickInput.background",E.editorWidgetBackground,d.localize(1824,"Quick picker background color. The quick picker widget is the container for pickers like the command palette.")),e.quickInputForeground=(0,I.registerColor)("quickInput.foreground",E.editorWidgetForeground,d.localize(1825,"Quick picker foreground color. The quick picker widget is the container for pickers like the command palette.")),e.quickInputTitleBackground=(0,I.registerColor)("quickInputTitle.background",{dark:new k.Color(new k.RGBA(255,255,255,.105)),light:new k.Color(new k.RGBA(0,0,0,.06)),hcDark:"#000000",hcLight:k.Color.white},d.localize(1826,"Quick picker title background color. The quick picker widget is the container for pickers like the command palette.")),e.pickerGroupForeground=(0,I.registerColor)("pickerGroup.foreground",{dark:"#3794FF",light:"#0066BF",hcDark:k.Color.white,hcLight:"#0F4A85"},d.localize(1827,"Quick picker color for grouping labels.")),e.pickerGroupBorder=(0,I.registerColor)("pickerGroup.border",{dark:"#3F3F46",light:"#CCCEDB",hcDark:k.Color.white,hcLight:"#0F4A85"},d.localize(1828,"Quick picker color for grouping borders.")),e._deprecatedQuickInputListFocusBackground=(0,I.registerColor)("quickInput.list.focusBackground",null,"",void 0,d.localize(1829,"Please use quickInputList.focusBackground instead")),e.quickInputListFocusForeground=(0,I.registerColor)("quickInputList.focusForeground",y.listActiveSelectionForeground,d.localize(1830,"Quick picker foreground color for the focused item.")),e.quickInputListFocusIconForeground=(0,I.registerColor)("quickInputList.focusIconForeground",y.listActiveSelectionIconForeground,d.localize(1831,"Quick picker icon foreground color for the focused item.")),e.quickInputListFocusBackground=(0,I.registerColor)("quickInputList.focusBackground",{dark:(0,I.oneOf)(e._deprecatedQuickInputListFocusBackground,y.listActiveSelectionBackground),light:(0,I.oneOf)(e._deprecatedQuickInputListFocusBackground,y.listActiveSelectionBackground),hcDark:null,hcLight:null},d.localize(1832,"Quick picker background color for the focused item."))}),define(ne[754],se([1,0,3,89,123,138]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.searchEditorFindMatchBorder=e.searchEditorFindMatch=e.searchResultsInfoForeground=void 0,e.searchResultsInfoForeground=(0,k.registerColor)("search.resultsInfoForeground",{light:I.foreground,dark:(0,k.transparent)(I.foreground,.65),hcDark:I.foreground,hcLight:I.foreground},d.localize(1833,"Color of the text in the search viewlet's completion message.")),e.searchEditorFindMatch=(0,k.registerColor)("searchEditor.findMatchBackground",{light:(0,k.transparent)(E.editorFindMatchHighlight,.66),dark:(0,k.transparent)(E.editorFindMatchHighlight,.66),hcDark:E.editorFindMatchHighlight,hcLight:E.editorFindMatchHighlight},d.localize(1834,"Color of the Search Editor query matches.")),e.searchEditorFindMatchBorder=(0,k.registerColor)("searchEditor.findMatchBorder",{light:(0,k.transparent)(E.editorFindMatchHighlightBorder,.66),dark:(0,k.transparent)(E.editorFindMatchHighlightBorder,.66),hcDark:E.editorFindMatchHighlightBorder,hcLight:E.editorFindMatchHighlightBorder},d.localize(1835,"Border color of the Search Editor query matches."))});var ci=this&&this.__createBinding||(Object.create?function(oe,e,d,k){k===void 0&&(k=d);var I=Object.getOwnPropertyDescriptor(e,d);(!I||("get"in I?!e.__esModule:I.writable||I.configurable))&&(I={enumerable:!0,get:function(){return e[d]}}),Object.defineProperty(oe,k,I)}:function(oe,e,d,k){k===void 0&&(k=d),oe[k]=e[d]}),Lt=this&&this.__exportStar||function(oe,e){for(var d in oe)d!=="default"&&!Object.prototype.hasOwnProperty.call(e,d)&&ci(e,oe,d)};define(ne[32],se([1,0,89,123,752,138,412,279,751,413,278,753,754]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),Lt(d,e),Lt(k,e),Lt(I,e),Lt(E,e),Lt(y,e),Lt(m,e),Lt(_,e),Lt(b,e),Lt(p,e),Lt(n,e),Lt(o,e)}),define(ne[185],se([1,0,5,172,77,14,2,32]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DynamicCssRules=e.GlobalEditorPointerMoveMonitor=e.EditorPointerEventFactory=e.EditorMouseEventFactory=e.EditorMouseEvent=e.CoordinatesRelativeToEditor=e.EditorPagePosition=e.ClientCoordinates=e.PageCoordinates=void 0,e.createEditorPagePosition=o,e.createCoordinatesRelativeToEditor=t;class _{constructor(C,f){this.x=C,this.y=f,this._pageCoordinatesBrand=void 0}toClientCoordinates(C){return new b(this.x-C.scrollX,this.y-C.scrollY)}}e.PageCoordinates=_;class b{constructor(C,f){this.clientX=C,this.clientY=f,this._clientCoordinatesBrand=void 0}toPageCoordinates(C){return new _(this.clientX+C.scrollX,this.clientY+C.scrollY)}}e.ClientCoordinates=b;class p{constructor(C,f,h,v){this.x=C,this.y=f,this.width=h,this.height=v,this._editorPagePositionBrand=void 0}}e.EditorPagePosition=p;class n{constructor(C,f){this.x=C,this.y=f,this._positionRelativeToEditorBrand=void 0}}e.CoordinatesRelativeToEditor=n;function o(u){const C=d.getDomNodePagePosition(u);return new p(C.left,C.top,C.width,C.height)}function t(u,C,f){const h=C.width/u.offsetWidth,v=C.height/u.offsetHeight,w=(f.x-C.x)/h,S=(f.y-C.y)/v;return new n(w,S)}class i extends I.StandardMouseEvent{constructor(C,f,h){super(d.getWindow(h),C),this._editorMouseEventBrand=void 0,this.isFromPointerCapture=f,this.pos=new _(this.posx,this.posy),this.editorPos=o(h),this.relativePos=t(h,this.editorPos,this.pos)}}e.EditorMouseEvent=i;class s{constructor(C){this._editorViewDomNode=C}_create(C){return new i(C,!1,this._editorViewDomNode)}onContextMenu(C,f){return d.addDisposableListener(C,"contextmenu",h=>{f(this._create(h))})}onMouseUp(C,f){return d.addDisposableListener(C,"mouseup",h=>{f(this._create(h))})}onMouseDown(C,f){return d.addDisposableListener(C,d.EventType.MOUSE_DOWN,h=>{f(this._create(h))})}onPointerDown(C,f){return d.addDisposableListener(C,d.EventType.POINTER_DOWN,h=>{f(this._create(h),h.pointerId)})}onMouseLeave(C,f){return d.addDisposableListener(C,d.EventType.MOUSE_LEAVE,h=>{f(this._create(h))})}onMouseMove(C,f){return d.addDisposableListener(C,"mousemove",h=>f(this._create(h)))}}e.EditorMouseEventFactory=s;class g{constructor(C){this._editorViewDomNode=C}_create(C){return new i(C,!1,this._editorViewDomNode)}onPointerUp(C,f){return d.addDisposableListener(C,"pointerup",h=>{f(this._create(h))})}onPointerDown(C,f){return d.addDisposableListener(C,d.EventType.POINTER_DOWN,h=>{f(this._create(h),h.pointerId)})}onPointerLeave(C,f){return d.addDisposableListener(C,d.EventType.POINTER_LEAVE,h=>{f(this._create(h))})}onPointerMove(C,f){return d.addDisposableListener(C,"pointermove",h=>f(this._create(h)))}}e.EditorPointerEventFactory=g;class c extends y.Disposable{constructor(C){super(),this._editorViewDomNode=C,this._globalPointerMoveMonitor=this._register(new k.GlobalPointerMoveMonitor),this._keydownListener=null}startMonitoring(C,f,h,v,w){this._keydownListener=d.addStandardDisposableListener(C.ownerDocument,"keydown",S=>{S.toKeyCodeChord().isModifierKey()||this._globalPointerMoveMonitor.stopMonitoring(!0,S.browserEvent)},!0),this._globalPointerMoveMonitor.startMonitoring(C,f,h,S=>{v(new i(S,!0,this._editorViewDomNode))},S=>{this._keydownListener.dispose(),w(S)})}stopMonitoring(){this._globalPointerMoveMonitor.stopMonitoring(!0)}}e.GlobalEditorPointerMoveMonitor=c;class l{static{this._idPool=0}constructor(C){this._editor=C,this._instanceId=++l._idPool,this._counter=0,this._rules=new Map,this._garbageCollectionScheduler=new E.RunOnceScheduler(()=>this.garbageCollect(),1e3)}createClassNameRef(C){const f=this.getOrCreateRule(C);return f.increaseRefCount(),{className:f.className,dispose:()=>{f.decreaseRefCount(),this._garbageCollectionScheduler.schedule()}}}getOrCreateRule(C){const f=this.computeUniqueKey(C);let h=this._rules.get(f);if(!h){const v=this._counter++;h=new a(f,`dyn-rule-${this._instanceId}-${v}`,d.isInShadowDOM(this._editor.getContainerDomNode())?this._editor.getContainerDomNode():void 0,C),this._rules.set(f,h)}return h}computeUniqueKey(C){return JSON.stringify(C)}garbageCollect(){for(const C of this._rules.values())C.hasReferences()||(this._rules.delete(C.key),C.dispose())}}e.DynamicCssRules=l;class a{constructor(C,f,h,v){this.key=C,this.className=f,this.properties=v,this._referenceCount=0,this._styleElementDisposables=new y.DisposableStore,this._styleElement=d.createStyleSheet(h,void 0,this._styleElementDisposables),this._styleElement.textContent=this.getCssText(this.className,this.properties)}getCssText(C,f){let h=`.${C} {`;for(const v in f){const w=f[v];let S;typeof w=="object"?S=(0,m.asCssVariable)(w.id):S=w;const L=r(v);h+=` ${L}: ${S};`}return h+=` }`,h}dispose(){this._styleElementDisposables.dispose(),this._styleElement=void 0}increaseRefCount(){this._referenceCount++}decreaseRefCount(){this._referenceCount--}hasReferences(){return this._referenceCount>0}}function r(u){return u.replace(/(^[A-Z])/,([C])=>C.toLowerCase()).replace(/([A-Z])/g,([C])=>`-${C.toLowerCase()}`)}}),define(ne[755],se([1,0,5,39,172,2,16,11,262,56,37,4,311,374,95,32,23,69,551,127,45,347,491]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Minimap=void 0;const C=140,f=2;class h{constructor(N,O,F){const x=N.options,W=x.get(144),V=x.get(146),q=V.minimap,H=x.get(50),z=x.get(73);this.renderMinimap=q.renderMinimap,this.size=z.size,this.minimapHeightIsEditorHeight=q.minimapHeightIsEditorHeight,this.scrollBeyondLastLine=x.get(106),this.paddingTop=x.get(84).top,this.paddingBottom=x.get(84).bottom,this.showSlider=z.showSlider,this.autohide=z.autohide,this.pixelRatio=W,this.typicalHalfwidthCharacterWidth=H.typicalHalfwidthCharacterWidth,this.lineHeight=x.get(67),this.minimapLeft=q.minimapLeft,this.minimapWidth=q.minimapWidth,this.minimapHeight=V.height,this.canvasInnerWidth=q.minimapCanvasInnerWidth,this.canvasInnerHeight=q.minimapCanvasInnerHeight,this.canvasOuterWidth=q.minimapCanvasOuterWidth,this.canvasOuterHeight=q.minimapCanvasOuterHeight,this.isSampling=q.minimapIsSampling,this.editorHeight=V.height,this.fontScale=q.minimapScale,this.minimapLineHeight=q.minimapLineHeight,this.minimapCharWidth=1*this.fontScale,this.sectionHeaderFontFamily=u.DEFAULT_FONT_FAMILY,this.sectionHeaderFontSize=z.sectionHeaderFontSize*W,this.sectionHeaderLetterSpacing=z.sectionHeaderLetterSpacing,this.sectionHeaderFontColor=h._getSectionHeaderColor(O,F.getColor(1)),this.charRenderer=(0,a.createSingleCallFunction)(()=>l.MinimapCharRendererFactory.create(this.fontScale,H.fontFamily)),this.defaultBackgroundColor=F.getColor(2),this.backgroundColor=h._getMinimapBackground(O,this.defaultBackgroundColor),this.foregroundAlpha=h._getMinimapForegroundOpacity(O)}static _getMinimapBackground(N,O){const F=N.getColor(s.minimapBackground);return F?new o.RGBA8(F.rgba.r,F.rgba.g,F.rgba.b,Math.round(255*F.rgba.a)):O}static _getMinimapForegroundOpacity(N){const O=N.getColor(s.minimapForegroundOpacity);return O?o.RGBA8._clamp(Math.round(255*O.rgba.a)):255}static _getSectionHeaderColor(N,O){const F=N.getColor(s.editorForeground);return F?new o.RGBA8(F.rgba.r,F.rgba.g,F.rgba.b,Math.round(255*F.rgba.a)):O}equals(N){return this.renderMinimap===N.renderMinimap&&this.size===N.size&&this.minimapHeightIsEditorHeight===N.minimapHeightIsEditorHeight&&this.scrollBeyondLastLine===N.scrollBeyondLastLine&&this.paddingTop===N.paddingTop&&this.paddingBottom===N.paddingBottom&&this.showSlider===N.showSlider&&this.autohide===N.autohide&&this.pixelRatio===N.pixelRatio&&this.typicalHalfwidthCharacterWidth===N.typicalHalfwidthCharacterWidth&&this.lineHeight===N.lineHeight&&this.minimapLeft===N.minimapLeft&&this.minimapWidth===N.minimapWidth&&this.minimapHeight===N.minimapHeight&&this.canvasInnerWidth===N.canvasInnerWidth&&this.canvasInnerHeight===N.canvasInnerHeight&&this.canvasOuterWidth===N.canvasOuterWidth&&this.canvasOuterHeight===N.canvasOuterHeight&&this.isSampling===N.isSampling&&this.editorHeight===N.editorHeight&&this.fontScale===N.fontScale&&this.minimapLineHeight===N.minimapLineHeight&&this.minimapCharWidth===N.minimapCharWidth&&this.sectionHeaderFontSize===N.sectionHeaderFontSize&&this.sectionHeaderLetterSpacing===N.sectionHeaderLetterSpacing&&this.defaultBackgroundColor&&this.defaultBackgroundColor.equals(N.defaultBackgroundColor)&&this.backgroundColor&&this.backgroundColor.equals(N.backgroundColor)&&this.foregroundAlpha===N.foregroundAlpha}}class v{constructor(N,O,F,x,W,V,q,H,z){this.scrollTop=N,this.scrollHeight=O,this.sliderNeeded=F,this._computedSliderRatio=x,this.sliderTop=W,this.sliderHeight=V,this.topPaddingLineCount=q,this.startLineNumber=H,this.endLineNumber=z}getDesiredScrollTopFromDelta(N){return Math.round(this.scrollTop+N/this._computedSliderRatio)}getDesiredScrollTopFromTouchLocation(N){return Math.round((N-this.sliderHeight/2)/this._computedSliderRatio)}intersectWithViewport(N){const O=Math.max(this.startLineNumber,N.startLineNumber),F=Math.min(this.endLineNumber,N.endLineNumber);return O>F?null:[O,F]}getYForLineNumber(N,O){return+(N-this.startLineNumber+this.topPaddingLineCount)*O}static create(N,O,F,x,W,V,q,H,z,U,j){const Y=N.pixelRatio,G=N.minimapLineHeight,K=Math.floor(N.canvasInnerHeight/G),R=N.lineHeight;if(N.minimapHeightIsEditorHeight){let ee=H*N.lineHeight+N.paddingTop+N.paddingBottom;N.scrollBeyondLastLine&&(ee+=Math.max(0,W-N.lineHeight-N.paddingBottom));const de=Math.max(1,Math.floor(W*W/ee)),ge=Math.max(0,N.minimapHeight-de),X=ge/(U-W),B=z*X,$=ge>0,Q=Math.floor(N.canvasInnerHeight/N.minimapLineHeight),Z=Math.floor(N.paddingTop/N.lineHeight);return new v(z,U,$,X,B,de,Z,1,Math.min(q,Q))}let J;if(V&&F!==q){const ee=F-O+1;J=Math.floor(ee*G/Y)}else{const ee=W/R;J=Math.floor(ee*G/Y)}const ie=Math.floor(N.paddingTop/R);let ue=Math.floor(N.paddingBottom/R);if(N.scrollBeyondLastLine){const ee=W/R;ue=Math.max(ue,ee-1)}let he;if(ue>0){const ee=W/R;he=(ie+q+ue-ee-1)*G/Y}else he=Math.max(0,(ie+q)*G/Y-J);he=Math.min(N.minimapHeight-J,he);const pe=he/(U-W),ae=z*pe;if(K>=ie+q+ue){const ee=he>0;return new v(z,U,ee,pe,ae,J,ie,1,q)}else{let ee;O>1?ee=O+ie:ee=Math.max(1,z/R);let de,ge=Math.max(1,Math.floor(ee-ae*Y/G));gez&&(ge=Math.min(ge,j.startLineNumber),de=Math.max(de,j.topPaddingLineCount)),j.scrollTop=N.paddingTop?$=(O-ge+de+B)*G/Y:$=z/N.paddingTop*(de+B)*G/Y,new v(z,U,!0,pe,$,J,de,ge,X)}}}class w{static{this.INVALID=new w(-1)}constructor(N){this.dy=N}onContentChanged(){this.dy=-1}onTokensChanged(){this.dy=-1}}class S{constructor(N,O,F){this.renderedLayout=N,this._imageData=O,this._renderedLines=new _.RenderedLinesCollection({createLine:()=>w.INVALID}),this._renderedLines._set(N.startLineNumber,F)}linesEquals(N){if(!this.scrollEquals(N))return!1;const F=this._renderedLines._get().lines;for(let x=0,W=F.length;x1){for(let ie=0,ue=x-1;ie0&&this.minimapLines[F-1]>=N;)F--;let x=this.modelLineToMinimapLine(O)-1;for(;x+1O)return null}return[F+1,x+1]}decorationLineRangeToMinimapLineRange(N,O){let F=this.modelLineToMinimapLine(N),x=this.modelLineToMinimapLine(O);return N!==O&&x===F&&(x===this.minimapLines.length?F>1&&F--:x++),[F,x]}onLinesDeleted(N){const O=N.toLineNumber-N.fromLineNumber+1;let F=this.minimapLines.length,x=0;for(let W=this.minimapLines.length-1;W>=0&&!(this.minimapLines[W]=0&&!(this.minimapLines[F]0,scrollWidth:N.scrollWidth,scrollHeight:N.scrollHeight,viewportStartLineNumber:O,viewportEndLineNumber:F,viewportStartLineNumberVerticalOffset:N.getVerticalOffsetForLineNumber(O),scrollTop:N.scrollTop,scrollLeft:N.scrollLeft,viewportWidth:N.viewportWidth,viewportHeight:N.viewportHeight};this._actual.render(x)}_recreateLineSampling(){this._minimapSelections=null;const N=!!this._samplingState,[O,F]=D.compute(this.options,this._context.viewModel.getLineCount(),this._samplingState);if(this._samplingState=O,N&&this._samplingState)for(const x of F)switch(x.type){case"deleted":this._actual.onLinesDeleted(x.deleteFromLineNumber,x.deleteToLineNumber);break;case"inserted":this._actual.onLinesInserted(x.insertFromLineNumber,x.insertToLineNumber);break;case"flush":this._actual.onFlushed();break}}getLineCount(){return this._samplingState?this._samplingState.minimapLines.length:this._context.viewModel.getLineCount()}getRealLineCount(){return this._context.viewModel.getLineCount()}getLineContent(N){return this._samplingState?this._context.viewModel.getLineContent(this._samplingState.minimapLines[N-1]):this._context.viewModel.getLineContent(N)}getLineMaxColumn(N){return this._samplingState?this._context.viewModel.getLineMaxColumn(this._samplingState.minimapLines[N-1]):this._context.viewModel.getLineMaxColumn(N)}getMinimapLinesRenderingData(N,O,F){if(this._samplingState){const x=[];for(let W=0,V=O-N+1;W!x.options.minimap?.sectionHeaderStyle);if(this._samplingState){const x=[];for(const W of F){if(!W.options.minimap)continue;const V=W.range,q=this._samplingState.modelLineToMinimapLine(V.startLineNumber),H=this._samplingState.modelLineToMinimapLine(V.endLineNumber);x.push(new i.ViewModelDecoration(new n.Range(q,V.startColumn,H,V.endColumn),W.options))}return x}return F}getSectionHeaderDecorationsInViewport(N,O){const F=this.options.minimapLineHeight,W=this.options.sectionHeaderFontSize/F;return N=Math.floor(Math.max(1,N-W)),this._getMinimapDecorationsInViewport(N,O).filter(V=>!!V.options.minimap?.sectionHeaderStyle)}_getMinimapDecorationsInViewport(N,O){let F;if(this._samplingState){const x=this._samplingState.minimapLines[N-1],W=this._samplingState.minimapLines[O-1];F=new n.Range(x,1,W,this._context.viewModel.getLineMaxColumn(W))}else F=new n.Range(N,1,O,this._context.viewModel.getLineMaxColumn(O));return this._context.viewModel.getMinimapDecorationsInRange(F)}getSectionHeaderText(N,O){const F=N.options.minimap?.sectionHeaderText;if(!F)return null;const x=this._sectionHeaderCache.get(F);if(x)return x;const W=O(F);return this._sectionHeaderCache.set(F,W),W}getOptions(){return this._context.viewModel.model.getOptions()}revealLineNumber(N){this._samplingState&&(N=this._samplingState.minimapLines[N-1]),this._context.viewModel.revealRange("mouse",!1,new n.Range(N,1,N,1),1,0)}setScrollTop(N){this._context.viewModel.viewLayout.setScrollPosition({scrollTop:N},1)}}e.Minimap=T;class M extends E.Disposable{constructor(N,O){super(),this._renderDecorations=!1,this._gestureInProgress=!1,this._theme=N,this._model=O,this._lastRenderData=null,this._buffers=null,this._selectionColor=this._theme.getColor(s.minimapSelection),this._domNode=(0,k.createFastDomNode)(document.createElement("div")),b.PartFingerprints.write(this._domNode,9),this._domNode.setClassName(this._getMinimapDomNodeClassName()),this._domNode.setPosition("absolute"),this._domNode.setAttribute("role","presentation"),this._domNode.setAttribute("aria-hidden","true"),this._shadow=(0,k.createFastDomNode)(document.createElement("div")),this._shadow.setClassName("minimap-shadow-hidden"),this._domNode.appendChild(this._shadow),this._canvas=(0,k.createFastDomNode)(document.createElement("canvas")),this._canvas.setPosition("absolute"),this._canvas.setLeft(0),this._domNode.appendChild(this._canvas),this._decorationsCanvas=(0,k.createFastDomNode)(document.createElement("canvas")),this._decorationsCanvas.setPosition("absolute"),this._decorationsCanvas.setClassName("minimap-decorations-layer"),this._decorationsCanvas.setLeft(0),this._domNode.appendChild(this._decorationsCanvas),this._slider=(0,k.createFastDomNode)(document.createElement("div")),this._slider.setPosition("absolute"),this._slider.setClassName("minimap-slider"),this._slider.setLayerHinting(!0),this._slider.setContain("strict"),this._domNode.appendChild(this._slider),this._sliderHorizontal=(0,k.createFastDomNode)(document.createElement("div")),this._sliderHorizontal.setPosition("absolute"),this._sliderHorizontal.setClassName("minimap-slider-horizontal"),this._slider.appendChild(this._sliderHorizontal),this._applyLayout(),this._pointerDownListener=d.addStandardDisposableListener(this._domNode.domNode,d.EventType.POINTER_DOWN,F=>{if(F.preventDefault(),this._model.options.renderMinimap===0||!this._lastRenderData)return;if(this._model.options.size!=="proportional"){if(F.button===0&&this._lastRenderData){const z=d.getDomNodePagePosition(this._slider.domNode),U=z.top+z.height/2;this._startSliderDragging(F,U,this._lastRenderData.renderedLayout)}return}const W=this._model.options.minimapLineHeight,V=this._model.options.canvasInnerHeight/this._model.options.canvasOuterHeight*F.offsetY;let H=Math.floor(V/W)+this._lastRenderData.renderedLayout.startLineNumber-this._lastRenderData.renderedLayout.topPaddingLineCount;H=Math.min(H,this._model.getLineCount()),this._model.revealLineNumber(H)}),this._sliderPointerMoveMonitor=new I.GlobalPointerMoveMonitor,this._sliderPointerDownListener=d.addStandardDisposableListener(this._slider.domNode,d.EventType.POINTER_DOWN,F=>{F.preventDefault(),F.stopPropagation(),F.button===0&&this._lastRenderData&&this._startSliderDragging(F,F.pageY,this._lastRenderData.renderedLayout)}),this._gestureDisposable=c.Gesture.addTarget(this._domNode.domNode),this._sliderTouchStartListener=d.addDisposableListener(this._domNode.domNode,c.EventType.Start,F=>{F.preventDefault(),F.stopPropagation(),this._lastRenderData&&(this._slider.toggleClassName("active",!0),this._gestureInProgress=!0,this.scrollDueToTouchEvent(F))},{passive:!1}),this._sliderTouchMoveListener=d.addDisposableListener(this._domNode.domNode,c.EventType.Change,F=>{F.preventDefault(),F.stopPropagation(),this._lastRenderData&&this._gestureInProgress&&this.scrollDueToTouchEvent(F)},{passive:!1}),this._sliderTouchEndListener=d.addStandardDisposableListener(this._domNode.domNode,c.EventType.End,F=>{F.preventDefault(),F.stopPropagation(),this._gestureInProgress=!1,this._slider.toggleClassName("active",!1)})}_startSliderDragging(N,O,F){if(!N.target||!(N.target instanceof Element))return;const x=N.pageX;this._slider.toggleClassName("active",!0);const W=(V,q)=>{const H=d.getDomNodePagePosition(this._domNode.domNode),z=Math.min(Math.abs(q-x),Math.abs(q-H.left),Math.abs(q-H.left-H.width));if(y.isWindows&&z>C){this._model.setScrollTop(F.scrollTop);return}const U=V-O;this._model.setScrollTop(F.getDesiredScrollTopFromDelta(U))};N.pageY!==O&&W(N.pageY,x),this._sliderPointerMoveMonitor.startMonitoring(N.target,N.pointerId,N.buttons,V=>W(V.pageY,V.pageX),()=>{this._slider.toggleClassName("active",!1)})}scrollDueToTouchEvent(N){const O=this._domNode.domNode.getBoundingClientRect().top,F=this._lastRenderData.renderedLayout.getDesiredScrollTopFromTouchLocation(N.pageY-O);this._model.setScrollTop(F)}dispose(){this._pointerDownListener.dispose(),this._sliderPointerMoveMonitor.dispose(),this._sliderPointerDownListener.dispose(),this._gestureDisposable.dispose(),this._sliderTouchStartListener.dispose(),this._sliderTouchMoveListener.dispose(),this._sliderTouchEndListener.dispose(),super.dispose()}_getMinimapDomNodeClassName(){const N=["minimap"];return this._model.options.showSlider==="always"?N.push("slider-always"):N.push("slider-mouseover"),this._model.options.autohide&&N.push("autohide"),N.join(" ")}getDomNode(){return this._domNode}_applyLayout(){this._domNode.setLeft(this._model.options.minimapLeft),this._domNode.setWidth(this._model.options.minimapWidth),this._domNode.setHeight(this._model.options.minimapHeight),this._shadow.setHeight(this._model.options.minimapHeight),this._canvas.setWidth(this._model.options.canvasOuterWidth),this._canvas.setHeight(this._model.options.canvasOuterHeight),this._canvas.domNode.width=this._model.options.canvasInnerWidth,this._canvas.domNode.height=this._model.options.canvasInnerHeight,this._decorationsCanvas.setWidth(this._model.options.canvasOuterWidth),this._decorationsCanvas.setHeight(this._model.options.canvasOuterHeight),this._decorationsCanvas.domNode.width=this._model.options.canvasInnerWidth,this._decorationsCanvas.domNode.height=this._model.options.canvasInnerHeight,this._slider.setWidth(this._model.options.minimapWidth)}_getBuffer(){return this._buffers||this._model.options.canvasInnerWidth>0&&this._model.options.canvasInnerHeight>0&&(this._buffers=new L(this._canvas.domNode.getContext("2d"),this._model.options.canvasInnerWidth,this._model.options.canvasInnerHeight,this._model.options.backgroundColor)),this._buffers?this._buffers.getBuffer():null}onDidChangeOptions(){this._lastRenderData=null,this._buffers=null,this._applyLayout(),this._domNode.setClassName(this._getMinimapDomNodeClassName())}onSelectionChanged(){return this._renderDecorations=!0,!0}onDecorationsChanged(){return this._renderDecorations=!0,!0}onFlushed(){return this._lastRenderData=null,!0}onLinesChanged(N,O){return this._lastRenderData?this._lastRenderData.onLinesChanged(N,O):!1}onLinesDeleted(N,O){return this._lastRenderData?.onLinesDeleted(N,O),!0}onLinesInserted(N,O){return this._lastRenderData?.onLinesInserted(N,O),!0}onScrollChanged(){return this._renderDecorations=!0,!0}onThemeChanged(){return this._selectionColor=this._theme.getColor(s.minimapSelection),this._renderDecorations=!0,!0}onTokensChanged(N){return this._lastRenderData?this._lastRenderData.onTokensChanged(N):!1}onTokensColorsChanged(){return this._lastRenderData=null,this._buffers=null,!0}onZonesChanged(){return this._lastRenderData=null,!0}render(N){if(this._model.options.renderMinimap===0){this._shadow.setClassName("minimap-shadow-hidden"),this._sliderHorizontal.setWidth(0),this._sliderHorizontal.setHeight(0);return}N.scrollLeft+N.viewportWidth>=N.scrollWidth?this._shadow.setClassName("minimap-shadow-hidden"):this._shadow.setClassName("minimap-shadow-visible");const F=v.create(this._model.options,N.viewportStartLineNumber,N.viewportEndLineNumber,N.viewportStartLineNumberVerticalOffset,N.viewportHeight,N.viewportContainsWhitespaceGaps,this._model.getLineCount(),this._model.getRealLineCount(),N.scrollTop,N.scrollHeight,this._lastRenderData?this._lastRenderData.renderedLayout:null);this._slider.setDisplay(F.sliderNeeded?"block":"none"),this._slider.setTop(F.sliderTop),this._slider.setHeight(F.sliderHeight),this._sliderHorizontal.setLeft(0),this._sliderHorizontal.setWidth(this._model.options.minimapWidth),this._sliderHorizontal.setTop(0),this._sliderHorizontal.setHeight(F.sliderHeight),this.renderDecorations(F),this._lastRenderData=this.renderLines(F)}renderDecorations(N){if(this._renderDecorations){this._renderDecorations=!1;const O=this._model.getSelections();O.sort(n.Range.compareRangesUsingStarts);const F=this._model.getMinimapDecorationsInViewport(N.startLineNumber,N.endLineNumber);F.sort((Y,G)=>(Y.options.zIndex||0)-(G.options.zIndex||0));const{canvasInnerWidth:x,canvasInnerHeight:W}=this._model.options,V=this._model.options.minimapLineHeight,q=this._model.options.minimapCharWidth,H=this._model.getOptions().tabSize,z=this._decorationsCanvas.domNode.getContext("2d");z.clearRect(0,0,x,W);const U=new A(N.startLineNumber,N.endLineNumber,!1);this._renderSelectionLineHighlights(z,O,U,N,V),this._renderDecorationsLineHighlights(z,F,U,N,V);const j=new A(N.startLineNumber,N.endLineNumber,null);this._renderSelectionsHighlights(z,O,j,N,V,H,q,x),this._renderDecorationsHighlights(z,F,j,N,V,H,q,x),this._renderSectionHeaders(N)}}_renderSelectionLineHighlights(N,O,F,x,W){if(!this._selectionColor||this._selectionColor.isTransparent())return;N.fillStyle=this._selectionColor.transparent(.5).toString();let V=0,q=0;for(const H of O){const z=x.intersectWithViewport(H);if(!z)continue;const[U,j]=z;for(let K=U;K<=j;K++)F.set(K,!0);const Y=x.getYForLineNumber(U,W),G=x.getYForLineNumber(j,W);q>=Y||(q>V&&N.fillRect(p.MINIMAP_GUTTER_WIDTH,V,N.canvas.width,q-V),V=Y),q=G}q>V&&N.fillRect(p.MINIMAP_GUTTER_WIDTH,V,N.canvas.width,q-V)}_renderDecorationsLineHighlights(N,O,F,x,W){const V=new Map;for(let q=O.length-1;q>=0;q--){const H=O[q],z=H.options.minimap;if(!z||z.position!==1)continue;const U=x.intersectWithViewport(H.range);if(!U)continue;const[j,Y]=U,G=z.getColor(this._theme.value);if(!G||G.isTransparent())continue;let K=V.get(G.toString());K||(K=G.transparent(.5).toString(),V.set(G.toString(),K)),N.fillStyle=K;for(let R=j;R<=Y;R++){if(F.has(R))continue;F.set(R,!0);const J=x.getYForLineNumber(j,W);N.fillRect(p.MINIMAP_GUTTER_WIDTH,J,N.canvas.width,W)}}}_renderSelectionsHighlights(N,O,F,x,W,V,q,H){if(!(!this._selectionColor||this._selectionColor.isTransparent()))for(const z of O){const U=x.intersectWithViewport(z);if(!U)continue;const[j,Y]=U;for(let G=j;G<=Y;G++)this.renderDecorationOnLine(N,F,z,this._selectionColor,x,G,W,W,V,q,H)}}_renderDecorationsHighlights(N,O,F,x,W,V,q,H){for(const z of O){const U=z.options.minimap;if(!U)continue;const j=x.intersectWithViewport(z.range);if(!j)continue;const[Y,G]=j,K=U.getColor(this._theme.value);if(!(!K||K.isTransparent()))for(let R=Y;R<=G;R++)switch(U.position){case 1:this.renderDecorationOnLine(N,F,z.range,K,x,R,W,W,V,q,H);continue;case 2:{const J=x.getYForLineNumber(R,W);this.renderDecoration(N,K,2,J,f,W);continue}}}}renderDecorationOnLine(N,O,F,x,W,V,q,H,z,U,j){const Y=W.getYForLineNumber(V,H);if(Y+q<0||Y>this._model.options.canvasInnerHeight)return;const{startLineNumber:G,endLineNumber:K}=F,R=G===V?F.startColumn:1,J=K===V?F.endColumn:this._model.getLineMaxColumn(V),ie=this.getXOffsetForPosition(O,V,R,z,U,j),ue=this.getXOffsetForPosition(O,V,J,z,U,j);this.renderDecoration(N,x,ie,Y,ue-ie,q)}getXOffsetForPosition(N,O,F,x,W,V){if(F===1)return p.MINIMAP_GUTTER_WIDTH;if((F-1)*W>=V)return V;let H=N.get(O);if(!H){const z=this._model.getLineContent(O);H=[p.MINIMAP_GUTTER_WIDTH];let U=p.MINIMAP_GUTTER_WIDTH;for(let j=1;j=V){H[j]=V;break}H[j]=K,U=K}N.set(O,H)}return F-1R.range.startLineNumber-J.range.startLineNumber);const K=M._fitSectionHeader.bind(null,Y,V-p.MINIMAP_GUTTER_WIDTH);for(const R of G){const J=N.getYForLineNumber(R.range.startLineNumber,O)+F,ie=J-F,ue=ie+2,he=this._model.getSectionHeaderText(R,K);M._renderSectionLabel(Y,he,R.options.minimap?.sectionHeaderStyle===2,H,U,V,ie,W,J,ue)}}static _fitSectionHeader(N,O,F){if(!F)return F;const x="\u2026",W=N.measureText(F).width,V=N.measureText(x).width;if(W<=O||W<=V)return F;const q=F.length,H=W/F.length,z=Math.floor((O-V)/H)-1;let U=Math.ceil(z/2);for(;U>0&&/\s/.test(F[U-1]);)--U;return F.substring(0,U)+x+F.substring(q-(z-U))}static _renderSectionLabel(N,O,F,x,W,V,q,H,z,U){O&&(N.fillStyle=x,N.fillRect(0,q,V,H),N.fillStyle=W,N.fillText(O,p.MINIMAP_GUTTER_WIDTH,z)),F&&(N.beginPath(),N.moveTo(0,U),N.lineTo(V,U),N.closePath(),N.stroke())}renderLines(N){const O=N.startLineNumber,F=N.endLineNumber,x=this._model.options.minimapLineHeight;if(this._lastRenderData&&this._lastRenderData.linesEquals(N)){const re=this._lastRenderData._get();return new S(N,re.imageData,re.lines)}const W=this._getBuffer();if(!W)return null;const[V,q,H]=M._renderUntouchedLines(W,N.topPaddingLineCount,O,F,x,this._lastRenderData),z=this._model.getMinimapLinesRenderingData(O,F,H),U=this._model.getOptions().tabSize,j=this._model.options.defaultBackgroundColor,Y=this._model.options.backgroundColor,G=this._model.options.foregroundAlpha,K=this._model.tokensColorTracker,R=K.backgroundIsLight(),J=this._model.options.renderMinimap,ie=this._model.options.charRenderer(),ue=this._model.options.fontScale,he=this._model.options.minimapCharWidth,ae=(J===1?2:3)*ue,ee=x>ae?Math.floor((x-ae)/2):0,de=Y.a/255,ge=new o.RGBA8(Math.round((Y.r-j.r)*de+j.r),Math.round((Y.g-j.g)*de+j.g),Math.round((Y.b-j.b)*de+j.b),255);let X=N.topPaddingLineCount*x;const B=[];for(let re=0,le=F-O+1;re=0&&$ue)return;const Q=J.charCodeAt(ae);if(Q===9){const Z=Y-(ae+ee)%Y;ee+=Z-1,pe+=Z*V}else if(Q===32)pe+=V;else{const Z=m.isFullWidthCharacter(Q)?2:1;for(let te=0;teue)return}}}}}class A{constructor(N,O,F){this._startLineNumber=N,this._endLineNumber=O,this._defaultValue=F,this._values=[];for(let x=0,W=this._endLineNumber-this._startLineNumber+1;xthis._endLineNumber||(this._values[N-this._startLineNumber]=O)}get(N){return Nthis._endLineNumber?this._defaultValue:this._values[N-this._startLineNumber]}}}),define(ne[756],se([1,0,3,32]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.multiDiffEditorBorder=e.multiDiffEditorBackground=e.multiDiffEditorHeaderBackground=void 0,e.multiDiffEditorHeaderBackground=(0,k.registerColor)("multiDiffEditor.headerBackground",{dark:"#262626",light:"tab.inactiveBackground",hcDark:"tab.inactiveBackground",hcLight:"tab.inactiveBackground"},(0,d.localize)(129,"The background color of the diff editor's header")),e.multiDiffEditorBackground=(0,k.registerColor)("multiDiffEditor.background",k.editorBackground,(0,d.localize)(130,"The background color of the multi file diff editor")),e.multiDiffEditorBorder=(0,k.registerColor)("multiDiffEditor.border",{dark:"sideBarSectionHeader.border",light:"#cccccc",hcDark:"sideBarSectionHeader.border",hcLight:"#cccccc"},(0,d.localize)(131,"The border color of the multi file diff editor"))}),define(ne[280],se([1,0,3,32,533]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SYMBOL_ICON_VARIABLE_FOREGROUND=e.SYMBOL_ICON_UNIT_FOREGROUND=e.SYMBOL_ICON_TYPEPARAMETER_FOREGROUND=e.SYMBOL_ICON_TEXT_FOREGROUND=e.SYMBOL_ICON_STRUCT_FOREGROUND=e.SYMBOL_ICON_STRING_FOREGROUND=e.SYMBOL_ICON_SNIPPET_FOREGROUND=e.SYMBOL_ICON_REFERENCE_FOREGROUND=e.SYMBOL_ICON_PROPERTY_FOREGROUND=e.SYMBOL_ICON_PACKAGE_FOREGROUND=e.SYMBOL_ICON_OPERATOR_FOREGROUND=e.SYMBOL_ICON_OBJECT_FOREGROUND=e.SYMBOL_ICON_NUMBER_FOREGROUND=e.SYMBOL_ICON_NULL_FOREGROUND=e.SYMBOL_ICON_NAMESPACE_FOREGROUND=e.SYMBOL_ICON_MODULE_FOREGROUND=e.SYMBOL_ICON_METHOD_FOREGROUND=e.SYMBOL_ICON_KEYWORD_FOREGROUND=e.SYMBOL_ICON_KEY_FOREGROUND=e.SYMBOL_ICON_INTERFACE_FOREGROUND=e.SYMBOL_ICON_FUNCTION_FOREGROUND=e.SYMBOL_ICON_FOLDER_FOREGROUND=e.SYMBOL_ICON_FILE_FOREGROUND=e.SYMBOL_ICON_FIELD_FOREGROUND=e.SYMBOL_ICON_EVENT_FOREGROUND=e.SYMBOL_ICON_ENUMERATOR_MEMBER_FOREGROUND=e.SYMBOL_ICON_ENUMERATOR_FOREGROUND=e.SYMBOL_ICON_CONSTRUCTOR_FOREGROUND=e.SYMBOL_ICON_CONSTANT_FOREGROUND=e.SYMBOL_ICON_COLOR_FOREGROUND=e.SYMBOL_ICON_CLASS_FOREGROUND=e.SYMBOL_ICON_BOOLEAN_FOREGROUND=e.SYMBOL_ICON_ARRAY_FOREGROUND=void 0,e.SYMBOL_ICON_ARRAY_FOREGROUND=(0,k.registerColor)("symbolIcon.arrayForeground",k.foreground,(0,d.localize)(1348,"The foreground color for array symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_BOOLEAN_FOREGROUND=(0,k.registerColor)("symbolIcon.booleanForeground",k.foreground,(0,d.localize)(1349,"The foreground color for boolean symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_CLASS_FOREGROUND=(0,k.registerColor)("symbolIcon.classForeground",{dark:"#EE9D28",light:"#D67E00",hcDark:"#EE9D28",hcLight:"#D67E00"},(0,d.localize)(1350,"The foreground color for class symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_COLOR_FOREGROUND=(0,k.registerColor)("symbolIcon.colorForeground",k.foreground,(0,d.localize)(1351,"The foreground color for color symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_CONSTANT_FOREGROUND=(0,k.registerColor)("symbolIcon.constantForeground",k.foreground,(0,d.localize)(1352,"The foreground color for constant symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_CONSTRUCTOR_FOREGROUND=(0,k.registerColor)("symbolIcon.constructorForeground",{dark:"#B180D7",light:"#652D90",hcDark:"#B180D7",hcLight:"#652D90"},(0,d.localize)(1353,"The foreground color for constructor symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_ENUMERATOR_FOREGROUND=(0,k.registerColor)("symbolIcon.enumeratorForeground",{dark:"#EE9D28",light:"#D67E00",hcDark:"#EE9D28",hcLight:"#D67E00"},(0,d.localize)(1354,"The foreground color for enumerator symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_ENUMERATOR_MEMBER_FOREGROUND=(0,k.registerColor)("symbolIcon.enumeratorMemberForeground",{dark:"#75BEFF",light:"#007ACC",hcDark:"#75BEFF",hcLight:"#007ACC"},(0,d.localize)(1355,"The foreground color for enumerator member symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_EVENT_FOREGROUND=(0,k.registerColor)("symbolIcon.eventForeground",{dark:"#EE9D28",light:"#D67E00",hcDark:"#EE9D28",hcLight:"#D67E00"},(0,d.localize)(1356,"The foreground color for event symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_FIELD_FOREGROUND=(0,k.registerColor)("symbolIcon.fieldForeground",{dark:"#75BEFF",light:"#007ACC",hcDark:"#75BEFF",hcLight:"#007ACC"},(0,d.localize)(1357,"The foreground color for field symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_FILE_FOREGROUND=(0,k.registerColor)("symbolIcon.fileForeground",k.foreground,(0,d.localize)(1358,"The foreground color for file symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_FOLDER_FOREGROUND=(0,k.registerColor)("symbolIcon.folderForeground",k.foreground,(0,d.localize)(1359,"The foreground color for folder symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_FUNCTION_FOREGROUND=(0,k.registerColor)("symbolIcon.functionForeground",{dark:"#B180D7",light:"#652D90",hcDark:"#B180D7",hcLight:"#652D90"},(0,d.localize)(1360,"The foreground color for function symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_INTERFACE_FOREGROUND=(0,k.registerColor)("symbolIcon.interfaceForeground",{dark:"#75BEFF",light:"#007ACC",hcDark:"#75BEFF",hcLight:"#007ACC"},(0,d.localize)(1361,"The foreground color for interface symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_KEY_FOREGROUND=(0,k.registerColor)("symbolIcon.keyForeground",k.foreground,(0,d.localize)(1362,"The foreground color for key symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_KEYWORD_FOREGROUND=(0,k.registerColor)("symbolIcon.keywordForeground",k.foreground,(0,d.localize)(1363,"The foreground color for keyword symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_METHOD_FOREGROUND=(0,k.registerColor)("symbolIcon.methodForeground",{dark:"#B180D7",light:"#652D90",hcDark:"#B180D7",hcLight:"#652D90"},(0,d.localize)(1364,"The foreground color for method symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_MODULE_FOREGROUND=(0,k.registerColor)("symbolIcon.moduleForeground",k.foreground,(0,d.localize)(1365,"The foreground color for module symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_NAMESPACE_FOREGROUND=(0,k.registerColor)("symbolIcon.namespaceForeground",k.foreground,(0,d.localize)(1366,"The foreground color for namespace symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_NULL_FOREGROUND=(0,k.registerColor)("symbolIcon.nullForeground",k.foreground,(0,d.localize)(1367,"The foreground color for null symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_NUMBER_FOREGROUND=(0,k.registerColor)("symbolIcon.numberForeground",k.foreground,(0,d.localize)(1368,"The foreground color for number symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_OBJECT_FOREGROUND=(0,k.registerColor)("symbolIcon.objectForeground",k.foreground,(0,d.localize)(1369,"The foreground color for object symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_OPERATOR_FOREGROUND=(0,k.registerColor)("symbolIcon.operatorForeground",k.foreground,(0,d.localize)(1370,"The foreground color for operator symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_PACKAGE_FOREGROUND=(0,k.registerColor)("symbolIcon.packageForeground",k.foreground,(0,d.localize)(1371,"The foreground color for package symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_PROPERTY_FOREGROUND=(0,k.registerColor)("symbolIcon.propertyForeground",k.foreground,(0,d.localize)(1372,"The foreground color for property symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_REFERENCE_FOREGROUND=(0,k.registerColor)("symbolIcon.referenceForeground",k.foreground,(0,d.localize)(1373,"The foreground color for reference symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_SNIPPET_FOREGROUND=(0,k.registerColor)("symbolIcon.snippetForeground",k.foreground,(0,d.localize)(1374,"The foreground color for snippet symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_STRING_FOREGROUND=(0,k.registerColor)("symbolIcon.stringForeground",k.foreground,(0,d.localize)(1375,"The foreground color for string symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_STRUCT_FOREGROUND=(0,k.registerColor)("symbolIcon.structForeground",k.foreground,(0,d.localize)(1376,"The foreground color for struct symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_TEXT_FOREGROUND=(0,k.registerColor)("symbolIcon.textForeground",k.foreground,(0,d.localize)(1377,"The foreground color for text symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_TYPEPARAMETER_FOREGROUND=(0,k.registerColor)("symbolIcon.typeParameterForeground",k.foreground,(0,d.localize)(1378,"The foreground color for type parameter symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_UNIT_FOREGROUND=(0,k.registerColor)("symbolIcon.unitForeground",k.foreground,(0,d.localize)(1379,"The foreground color for unit symbols. These symbols appear in the outline, breadcrumb, and suggest widget.")),e.SYMBOL_ICON_VARIABLE_FOREGROUND=(0,k.registerColor)("symbolIcon.variableForeground",{dark:"#75BEFF",light:"#007ACC",hcDark:"#75BEFF",hcLight:"#007ACC"},(0,d.localize)(1380,"The foreground color for variable symbols. These symbols appear in the outline, breadcrumb, and suggest widget."))}),define(ne[757],se([1,0,26,134,3,91,195,280]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.toMenuItems=_;const y=Object.freeze({kind:E.HierarchicalKind.Empty,title:(0,I.localize)(777,"More Actions...")}),m=Object.freeze([{kind:k.CodeActionKind.QuickFix,title:(0,I.localize)(778,"Quick Fix")},{kind:k.CodeActionKind.RefactorExtract,title:(0,I.localize)(779,"Extract"),icon:d.Codicon.wrench},{kind:k.CodeActionKind.RefactorInline,title:(0,I.localize)(780,"Inline"),icon:d.Codicon.wrench},{kind:k.CodeActionKind.RefactorRewrite,title:(0,I.localize)(781,"Rewrite"),icon:d.Codicon.wrench},{kind:k.CodeActionKind.RefactorMove,title:(0,I.localize)(782,"Move"),icon:d.Codicon.wrench},{kind:k.CodeActionKind.SurroundWith,title:(0,I.localize)(783,"Surround With"),icon:d.Codicon.surroundWith},{kind:k.CodeActionKind.Source,title:(0,I.localize)(784,"Source Action"),icon:d.Codicon.symbolFile},y]);function _(b,p,n){if(!p)return b.map(i=>({kind:"action",item:i,group:y,disabled:!!i.action.disabled,label:i.action.disabled||i.action.title,canPreview:!!i.action.edit?.edits.length}));const o=m.map(i=>({group:i,actions:[]}));for(const i of b){const s=i.action.kind?new E.HierarchicalKind(i.action.kind):E.HierarchicalKind.None;for(const g of o)if(g.group.kind.contains(s)){g.actions.push(i);break}}const t=[];for(const i of o)if(i.actions.length){t.push({kind:"header",group:i.group});for(const s of i.actions){const g=i.group;t.push({kind:"action",item:s,group:s.action.isAI?{title:g.title,kind:g.kind,icon:d.Codicon.sparkle}:g,label:s.action.title,disabled:!!s.action.disabled,keybinding:n(s.action)})}}return t}}),define(ne[110],se([1,0,32,33]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.defaultMenuStyles=e.defaultSelectBoxStyles=e.defaultListStyles=e.defaultBreadcrumbsWidgetStyles=e.defaultCountBadgeStyles=e.defaultFindWidgetStyles=e.defaultInputBoxStyles=e.defaultDialogStyles=e.defaultCheckboxStyles=e.defaultRadioStyles=e.defaultToggleStyles=e.defaultProgressBarStyles=e.defaultButtonStyles=e.defaultKeybindingLabelStyles=void 0,e.getListStyles=E;function I(y,m){const _={...m};for(const b in y){const p=y[b];_[b]=p!==void 0?(0,d.asCssVariable)(p):void 0}return _}e.defaultKeybindingLabelStyles={keybindingLabelBackground:(0,d.asCssVariable)(d.keybindingLabelBackground),keybindingLabelForeground:(0,d.asCssVariable)(d.keybindingLabelForeground),keybindingLabelBorder:(0,d.asCssVariable)(d.keybindingLabelBorder),keybindingLabelBottomBorder:(0,d.asCssVariable)(d.keybindingLabelBottomBorder),keybindingLabelShadow:(0,d.asCssVariable)(d.widgetShadow)},e.defaultButtonStyles={buttonForeground:(0,d.asCssVariable)(d.buttonForeground),buttonSeparator:(0,d.asCssVariable)(d.buttonSeparator),buttonBackground:(0,d.asCssVariable)(d.buttonBackground),buttonHoverBackground:(0,d.asCssVariable)(d.buttonHoverBackground),buttonSecondaryForeground:(0,d.asCssVariable)(d.buttonSecondaryForeground),buttonSecondaryBackground:(0,d.asCssVariable)(d.buttonSecondaryBackground),buttonSecondaryHoverBackground:(0,d.asCssVariable)(d.buttonSecondaryHoverBackground),buttonBorder:(0,d.asCssVariable)(d.buttonBorder)},e.defaultProgressBarStyles={progressBarBackground:(0,d.asCssVariable)(d.progressBarBackground)},e.defaultToggleStyles={inputActiveOptionBorder:(0,d.asCssVariable)(d.inputActiveOptionBorder),inputActiveOptionForeground:(0,d.asCssVariable)(d.inputActiveOptionForeground),inputActiveOptionBackground:(0,d.asCssVariable)(d.inputActiveOptionBackground)},e.defaultRadioStyles={activeForeground:(0,d.asCssVariable)(d.radioActiveForeground),activeBackground:(0,d.asCssVariable)(d.radioActiveBackground),activeBorder:(0,d.asCssVariable)(d.radioActiveBorder),inactiveForeground:(0,d.asCssVariable)(d.radioInactiveForeground),inactiveBackground:(0,d.asCssVariable)(d.radioInactiveBackground),inactiveBorder:(0,d.asCssVariable)(d.radioInactiveBorder),inactiveHoverBackground:(0,d.asCssVariable)(d.radioInactiveHoverBackground)},e.defaultCheckboxStyles={checkboxBackground:(0,d.asCssVariable)(d.checkboxBackground),checkboxBorder:(0,d.asCssVariable)(d.checkboxBorder),checkboxForeground:(0,d.asCssVariable)(d.checkboxForeground)},e.defaultDialogStyles={dialogBackground:(0,d.asCssVariable)(d.editorWidgetBackground),dialogForeground:(0,d.asCssVariable)(d.editorWidgetForeground),dialogShadow:(0,d.asCssVariable)(d.widgetShadow),dialogBorder:(0,d.asCssVariable)(d.contrastBorder),errorIconForeground:(0,d.asCssVariable)(d.problemsErrorIconForeground),warningIconForeground:(0,d.asCssVariable)(d.problemsWarningIconForeground),infoIconForeground:(0,d.asCssVariable)(d.problemsInfoIconForeground),textLinkForeground:(0,d.asCssVariable)(d.textLinkForeground)},e.defaultInputBoxStyles={inputBackground:(0,d.asCssVariable)(d.inputBackground),inputForeground:(0,d.asCssVariable)(d.inputForeground),inputBorder:(0,d.asCssVariable)(d.inputBorder),inputValidationInfoBorder:(0,d.asCssVariable)(d.inputValidationInfoBorder),inputValidationInfoBackground:(0,d.asCssVariable)(d.inputValidationInfoBackground),inputValidationInfoForeground:(0,d.asCssVariable)(d.inputValidationInfoForeground),inputValidationWarningBorder:(0,d.asCssVariable)(d.inputValidationWarningBorder),inputValidationWarningBackground:(0,d.asCssVariable)(d.inputValidationWarningBackground),inputValidationWarningForeground:(0,d.asCssVariable)(d.inputValidationWarningForeground),inputValidationErrorBorder:(0,d.asCssVariable)(d.inputValidationErrorBorder),inputValidationErrorBackground:(0,d.asCssVariable)(d.inputValidationErrorBackground),inputValidationErrorForeground:(0,d.asCssVariable)(d.inputValidationErrorForeground)},e.defaultFindWidgetStyles={listFilterWidgetBackground:(0,d.asCssVariable)(d.listFilterWidgetBackground),listFilterWidgetOutline:(0,d.asCssVariable)(d.listFilterWidgetOutline),listFilterWidgetNoMatchesOutline:(0,d.asCssVariable)(d.listFilterWidgetNoMatchesOutline),listFilterWidgetShadow:(0,d.asCssVariable)(d.listFilterWidgetShadow),inputBoxStyles:e.defaultInputBoxStyles,toggleStyles:e.defaultToggleStyles},e.defaultCountBadgeStyles={badgeBackground:(0,d.asCssVariable)(d.badgeBackground),badgeForeground:(0,d.asCssVariable)(d.badgeForeground),badgeBorder:(0,d.asCssVariable)(d.contrastBorder)},e.defaultBreadcrumbsWidgetStyles={breadcrumbsBackground:(0,d.asCssVariable)(d.breadcrumbsBackground),breadcrumbsForeground:(0,d.asCssVariable)(d.breadcrumbsForeground),breadcrumbsHoverForeground:(0,d.asCssVariable)(d.breadcrumbsFocusForeground),breadcrumbsFocusForeground:(0,d.asCssVariable)(d.breadcrumbsFocusForeground),breadcrumbsFocusAndSelectionForeground:(0,d.asCssVariable)(d.breadcrumbsActiveSelectionForeground)},e.defaultListStyles={listBackground:void 0,listInactiveFocusForeground:void 0,listFocusBackground:(0,d.asCssVariable)(d.listFocusBackground),listFocusForeground:(0,d.asCssVariable)(d.listFocusForeground),listFocusOutline:(0,d.asCssVariable)(d.listFocusOutline),listActiveSelectionBackground:(0,d.asCssVariable)(d.listActiveSelectionBackground),listActiveSelectionForeground:(0,d.asCssVariable)(d.listActiveSelectionForeground),listActiveSelectionIconForeground:(0,d.asCssVariable)(d.listActiveSelectionIconForeground),listFocusAndSelectionOutline:(0,d.asCssVariable)(d.listFocusAndSelectionOutline),listFocusAndSelectionBackground:(0,d.asCssVariable)(d.listActiveSelectionBackground),listFocusAndSelectionForeground:(0,d.asCssVariable)(d.listActiveSelectionForeground),listInactiveSelectionBackground:(0,d.asCssVariable)(d.listInactiveSelectionBackground),listInactiveSelectionIconForeground:(0,d.asCssVariable)(d.listInactiveSelectionIconForeground),listInactiveSelectionForeground:(0,d.asCssVariable)(d.listInactiveSelectionForeground),listInactiveFocusBackground:(0,d.asCssVariable)(d.listInactiveFocusBackground),listInactiveFocusOutline:(0,d.asCssVariable)(d.listInactiveFocusOutline),listHoverBackground:(0,d.asCssVariable)(d.listHoverBackground),listHoverForeground:(0,d.asCssVariable)(d.listHoverForeground),listDropOverBackground:(0,d.asCssVariable)(d.listDropOverBackground),listDropBetweenBackground:(0,d.asCssVariable)(d.listDropBetweenBackground),listSelectionOutline:(0,d.asCssVariable)(d.activeContrastBorder),listHoverOutline:(0,d.asCssVariable)(d.activeContrastBorder),treeIndentGuidesStroke:(0,d.asCssVariable)(d.treeIndentGuidesStroke),treeInactiveIndentGuidesStroke:(0,d.asCssVariable)(d.treeInactiveIndentGuidesStroke),treeStickyScrollBackground:void 0,treeStickyScrollBorder:void 0,treeStickyScrollShadow:(0,d.asCssVariable)(d.scrollbarShadow),tableColumnsBorder:(0,d.asCssVariable)(d.tableColumnsBorder),tableOddRowsBackgroundColor:(0,d.asCssVariable)(d.tableOddRowsBackgroundColor)};function E(y){return I(y,e.defaultListStyles)}e.defaultSelectBoxStyles={selectBackground:(0,d.asCssVariable)(d.selectBackground),selectListBackground:(0,d.asCssVariable)(d.selectListBackground),selectForeground:(0,d.asCssVariable)(d.selectForeground),decoratorRightForeground:(0,d.asCssVariable)(d.pickerGroupForeground),selectBorder:(0,d.asCssVariable)(d.selectBorder),focusBorder:(0,d.asCssVariable)(d.focusBorder),listFocusBackground:(0,d.asCssVariable)(d.quickInputListFocusBackground),listInactiveSelectionIconForeground:(0,d.asCssVariable)(d.quickInputListFocusIconForeground),listFocusForeground:(0,d.asCssVariable)(d.quickInputListFocusForeground),listFocusOutline:(0,d.asCssVariableWithDefault)(d.activeContrastBorder,k.Color.transparent.toString()),listHoverBackground:(0,d.asCssVariable)(d.listHoverBackground),listHoverForeground:(0,d.asCssVariable)(d.listHoverForeground),listHoverOutline:(0,d.asCssVariable)(d.activeContrastBorder),selectListBorder:(0,d.asCssVariable)(d.editorWidgetBorder),listBackground:void 0,listActiveSelectionBackground:void 0,listActiveSelectionForeground:void 0,listActiveSelectionIconForeground:void 0,listFocusAndSelectionBackground:void 0,listDropOverBackground:void 0,listDropBetweenBackground:void 0,listInactiveSelectionBackground:void 0,listInactiveSelectionForeground:void 0,listInactiveFocusBackground:void 0,listInactiveFocusOutline:void 0,listSelectionOutline:void 0,listFocusAndSelectionForeground:void 0,listFocusAndSelectionOutline:void 0,listInactiveFocusForeground:void 0,tableColumnsBorder:void 0,tableOddRowsBackgroundColor:void 0,treeIndentGuidesStroke:void 0,treeInactiveIndentGuidesStroke:void 0,treeStickyScrollBackground:void 0,treeStickyScrollBorder:void 0,treeStickyScrollShadow:void 0},e.defaultMenuStyles={shadowColor:(0,d.asCssVariable)(d.widgetShadow),borderColor:(0,d.asCssVariable)(d.menuBorder),foregroundColor:(0,d.asCssVariable)(d.menuForeground),backgroundColor:(0,d.asCssVariable)(d.menuBackground),selectionForegroundColor:(0,d.asCssVariable)(d.menuSelectionForeground),selectionBackgroundColor:(0,d.asCssVariable)(d.menuSelectionBackground),selectionBorderColor:(0,d.asCssVariable)(d.menuSelectionBorder),separatorColor:(0,d.asCssVariable)(d.menuSeparatorBackground),scrollbarShadow:(0,d.asCssVariable)(d.scrollbarShadow),scrollbarSliderBackground:(0,d.asCssVariable)(d.scrollbarSliderBackground),scrollbarSliderHoverBackground:(0,d.asCssVariable)(d.scrollbarSliderHoverBackground),scrollbarSliderActiveBackground:(0,d.asCssVariable)(d.scrollbarSliderActiveBackground)}}),define(ne[758],se([1,0,5,354,355,254,82,2,48,78,3,7,31,181,110,178]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";var g;Object.defineProperty(e,"__esModule",{value:!0}),e.AccessibilityProvider=e.OneReferenceRenderer=e.FileReferencesRenderer=e.IdentityProvider=e.StringRepresentationProvider=e.Delegate=e.DataSource=void 0;let c=class{constructor(S){this._resolverService=S}hasChildren(S){return S instanceof s.ReferencesModel||S instanceof s.FileReferences}getChildren(S){if(S instanceof s.ReferencesModel)return S.groups;if(S instanceof s.FileReferences)return S.resolve(this._resolverService).then(L=>L.children);throw new Error("bad tree")}};e.DataSource=c,e.DataSource=c=ke([ce(0,b.ITextModelService)],c);class l{getHeight(){return 23}getTemplateId(S){return S instanceof s.FileReferences?C.id:h.id}}e.Delegate=l;let a=class{constructor(S){this._keybindingService=S}getKeyboardNavigationLabel(S){if(S instanceof s.OneReference){const L=S.parent.getPreview(S)?.preview(S.range);if(L)return L.value}return(0,_.basename)(S.uri)}};e.StringRepresentationProvider=a,e.StringRepresentationProvider=a=ke([ce(0,o.IKeybindingService)],a);class r{getId(S){return S instanceof s.OneReference?S.id:S.uri}}e.IdentityProvider=r;let u=class extends m.Disposable{constructor(S,L){super(),this._labelService=L;const D=document.createElement("div");D.classList.add("reference-file"),this.file=this._register(new E.IconLabel(D,{supportHighlights:!0})),this.badge=new k.CountBadge(d.append(D,d.$(".count")),{},i.defaultCountBadgeStyles),S.appendChild(D)}set(S,L){const D=(0,_.dirname)(S.uri);this.file.setLabel(this._labelService.getUriBasenameLabel(S.uri),this._labelService.getUriLabel(D,{relative:!0}),{title:this._labelService.getUriLabel(S.uri),matches:L});const T=S.children.length;this.badge.setCount(T),T>1?this.badge.setTitleFormat((0,p.localize)(989,"{0} references",T)):this.badge.setTitleFormat((0,p.localize)(990,"{0} reference",T))}};u=ke([ce(1,t.ILabelService)],u);let C=class{static{g=this}static{this.id="FileReferencesRenderer"}constructor(S){this._instantiationService=S,this.templateId=g.id}renderTemplate(S){return this._instantiationService.createInstance(u,S)}renderElement(S,L,D){D.set(S.element,(0,y.createMatches)(S.filterData))}disposeTemplate(S){S.dispose()}};e.FileReferencesRenderer=C,e.FileReferencesRenderer=C=g=ke([ce(0,n.IInstantiationService)],C);class f extends m.Disposable{constructor(S){super(),this.label=this._register(new I.HighlightedLabel(S))}set(S,L){const D=S.parent.getPreview(S)?.preview(S.range);if(!D||!D.value)this.label.set(`${(0,_.basename)(S.uri)}:${S.range.startLineNumber+1}:${S.range.startColumn+1}`);else{const{value:T,highlight:M}=D;L&&!y.FuzzyScore.isDefault(L)?(this.label.element.classList.toggle("referenceMatch",!1),this.label.set(T,(0,y.createMatches)(L))):(this.label.element.classList.toggle("referenceMatch",!0),this.label.set(T,[M]))}}}class h{constructor(){this.templateId=h.id}static{this.id="OneReferenceRenderer"}renderTemplate(S){return new f(S)}renderElement(S,L,D){D.set(S.element,S.filterData)}disposeTemplate(S){S.dispose()}}e.OneReferenceRenderer=h;class v{getWidgetAriaLabel(){return(0,p.localize)(991,"References")}getAriaLabel(S){return S.ariaMessage}}e.AccessibilityProvider=v}),define(ne[759],se([1,0,5,206,115,18,26,2,16,30,3,58,31,110,32,306]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ActionList=e.previewSelectedActionCommand=e.acceptSelectedActionCommand=void 0,e.acceptSelectedActionCommand="acceptSelectedCodeAction",e.previewSelectedActionCommand="previewSelectedCodeAction";class s{get templateId(){return"header"}renderTemplate(f){f.classList.add("group-header");const h=document.createElement("span");return f.append(h),{container:f,text:h}}renderElement(f,h,v){v.text.textContent=f.group?.title??""}disposeTemplate(f){}}let g=class{get templateId(){return"action"}constructor(f,h){this._supportsPreview=f,this._keybindingService=h}renderTemplate(f){f.classList.add(this.templateId);const h=document.createElement("div");h.className="icon",f.append(h);const v=document.createElement("span");v.className="title",f.append(v);const w=new k.KeybindingLabel(f,_.OS);return{container:f,icon:h,text:v,keybinding:w}}renderElement(f,h,v){if(f.group?.icon?(v.icon.className=b.ThemeIcon.asClassName(f.group.icon),f.group.icon.color&&(v.icon.style.color=(0,i.asCssVariable)(f.group.icon.color.id))):(v.icon.className=b.ThemeIcon.asClassName(y.Codicon.lightBulb),v.icon.style.color="var(--vscode-editorLightBulb-foreground)"),!f.item||!f.label)return;v.text.textContent=u(f.label),v.keybinding.set(f.keybinding),d.setVisibility(!!f.keybinding,v.keybinding.element);const w=this._keybindingService.lookupKeybinding(e.acceptSelectedActionCommand)?.getLabel(),S=this._keybindingService.lookupKeybinding(e.previewSelectedActionCommand)?.getLabel();v.container.classList.toggle("option-disabled",f.disabled),f.disabled?v.container.title=f.label:w&&S?this._supportsPreview&&f.canPreview?v.container.title=(0,p.localize)(1492,"{0} to Apply, {1} to Preview",w,S):v.container.title=(0,p.localize)(1493,"{0} to Apply",w):v.container.title=""}disposeTemplate(f){f.keybinding.dispose()}};g=ke([ce(1,o.IKeybindingService)],g);class c extends UIEvent{constructor(){super("acceptSelectedAction")}}class l extends UIEvent{constructor(){super("previewSelectedAction")}}function a(C){if(C.kind==="action")return C.label}let r=class extends m.Disposable{constructor(f,h,v,w,S,L){super(),this._delegate=w,this._contextViewService=S,this._keybindingService=L,this._actionLineHeight=24,this._headerLineHeight=26,this.cts=this._register(new E.CancellationTokenSource),this.domNode=document.createElement("div"),this.domNode.classList.add("actionList");const D={getHeight:T=>T.kind==="header"?this._headerLineHeight:this._actionLineHeight,getTemplateId:T=>T.kind};this._list=this._register(new I.List(f,this.domNode,D,[new g(h,this._keybindingService),new s],{keyboardSupport:!1,typeNavigationEnabled:!0,keyboardNavigationLabelProvider:{getKeyboardNavigationLabel:a},accessibilityProvider:{getAriaLabel:T=>{if(T.kind==="action"){let M=T.label?u(T?.label):"";return T.disabled&&(M=(0,p.localize)(1494,"{0}, Disabled Reason: {1}",M,T.disabled)),M}return null},getWidgetAriaLabel:()=>(0,p.localize)(1495,"Action Widget"),getRole:T=>T.kind==="action"?"option":"separator",getWidgetRole:()=>"listbox"}})),this._list.style(t.defaultListStyles),this._register(this._list.onMouseClick(T=>this.onListClick(T))),this._register(this._list.onMouseOver(T=>this.onListHover(T))),this._register(this._list.onDidChangeFocus(()=>this.onFocus())),this._register(this._list.onDidChangeSelection(T=>this.onListSelection(T))),this._allMenuItems=v,this._list.splice(0,this._list.length,this._allMenuItems),this._list.length&&this.focusNext()}focusCondition(f){return!f.disabled&&f.kind==="action"}hide(f){this._delegate.onHide(f),this.cts.cancel(),this._contextViewService.hideContextView()}layout(f){const h=this._allMenuItems.filter(T=>T.kind==="header").length,w=this._allMenuItems.length*this._actionLineHeight+h*this._headerLineHeight-h*this._actionLineHeight;this._list.layout(w);let S=f;if(this._allMenuItems.length>=50)S=380;else{const T=this._allMenuItems.map((M,A)=>{const P=this.domNode.ownerDocument.getElementById(this._list.getElementID(A));if(P){P.style.width="auto";const N=P.getBoundingClientRect().width;return P.style.width="",N}return 0});S=Math.max(...T,f)}const D=Math.min(w,this.domNode.ownerDocument.body.clientHeight*.7);return this._list.layout(D,S),this.domNode.style.height=`${D}px`,this._list.domFocus(),S}focusPrevious(){this._list.focusPrevious(1,!0,void 0,this.focusCondition)}focusNext(){this._list.focusNext(1,!0,void 0,this.focusCondition)}acceptSelected(f){const h=this._list.getFocus();if(h.length===0)return;const v=h[0],w=this._list.element(v);if(!this.focusCondition(w))return;const S=f?new l:new c;this._list.setSelection([v],S)}onListSelection(f){if(!f.elements.length)return;const h=f.elements[0];h.item&&this.focusCondition(h)?this._delegate.onSelect(h.item,f.browserEvent instanceof l):this._list.setSelection([])}onFocus(){const f=this._list.getFocus();if(f.length===0)return;const h=f[0],v=this._list.element(h);this._delegate.onFocus?.(v.item)}async onListHover(f){const h=f.element;if(h&&h.item&&this.focusCondition(h)){if(this._delegate.onHover&&!h.disabled&&h.kind==="action"){const v=await this._delegate.onHover(h.item,this.cts.token);h.canPreview=v?v.canPreview:void 0}f.index&&this._list.splice(f.index,1,[h])}this._list.setFocus(typeof f.index=="number"?[f.index]:[])}onListClick(f){f.element&&this.focusCondition(f.element)&&this._list.setFocus([])}};e.ActionList=r,e.ActionList=r=ke([ce(4,n.IContextViewService),ce(5,o.IKeybindingService)],r);function u(C){return C.replace(/\r\n|\r|\n/g," ")}}),define(ne[760],se([1,0,5,87,2,3,759,29,12,58,49,7,32,306]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IActionWidgetService=void 0,(0,o.registerColor)("actionBar.toggledBackground",o.inputActiveOptionBackground,(0,E.localize)(1496,"Background color for toggled action items in action bar."));const t={Visible:new _.RawContextKey("codeActionMenuVisible",!1,(0,E.localize)(1497,"Whether the action widget list is visible"))};e.IActionWidgetService=(0,n.createDecorator)("actionWidgetService");let i=class extends I.Disposable{get isVisible(){return t.Visible.getValue(this._contextKeyService)||!1}constructor(c,l,a){super(),this._contextViewService=c,this._contextKeyService=l,this._instantiationService=a,this._list=this._register(new I.MutableDisposable)}show(c,l,a,r,u,C,f){const h=t.Visible.bindTo(this._contextKeyService),v=this._instantiationService.createInstance(y.ActionList,c,l,a,r);this._contextViewService.showContextView({getAnchor:()=>u,render:w=>(h.set(!0),this._renderWidget(w,v,f??[])),onHide:w=>{h.reset(),this._onWidgetClosed(w)}},C,!1)}acceptSelected(c){this._list.value?.acceptSelected(c)}focusPrevious(){this._list?.value?.focusPrevious()}focusNext(){this._list?.value?.focusNext()}hide(c){this._list.value?.hide(c),this._list.clear()}_renderWidget(c,l,a){const r=document.createElement("div");if(r.classList.add("action-widget"),c.appendChild(r),this._list.value=l,this._list.value)r.appendChild(this._list.value.domNode);else throw new Error("List has no value");const u=new I.DisposableStore,C=document.createElement("div"),f=c.appendChild(C);f.classList.add("context-view-block"),u.add(d.addDisposableListener(f,d.EventType.MOUSE_DOWN,D=>D.stopPropagation()));const h=document.createElement("div"),v=c.appendChild(h);v.classList.add("context-view-pointerBlock"),u.add(d.addDisposableListener(v,d.EventType.POINTER_MOVE,()=>v.remove())),u.add(d.addDisposableListener(v,d.EventType.MOUSE_DOWN,()=>v.remove()));let w=0;if(a.length){const D=this._createActionBar(".action-widget-action-bar",a);D&&(r.appendChild(D.getContainer().parentElement),u.add(D),w=D.getContainer().offsetWidth)}const S=this._list.value?.layout(w);r.style.width=`${S}px`;const L=u.add(d.trackFocus(c));return u.add(L.onDidBlur(()=>this.hide(!0))),u}_createActionBar(c,l){if(!l.length)return;const a=d.$(c),r=new k.ActionBar(a);return r.push(l,{icon:!1,label:!0}),r}_onWidgetClosed(c){this._list.value?.hide(c)}};i=ke([ce(0,b.IContextViewService),ce(1,_.IContextKeyService),ce(2,n.IInstantiationService)],i),(0,p.registerSingleton)(e.IActionWidgetService,i,1);const s=1100;(0,m.registerAction2)(class extends m.Action2{constructor(){super({id:"hideCodeActionWidget",title:(0,E.localize2)(1498,"Hide action widget"),precondition:t.Visible,keybinding:{weight:s,primary:9,secondary:[1033]}})}run(g){g.get(e.IActionWidgetService).hide(!0)}}),(0,m.registerAction2)(class extends m.Action2{constructor(){super({id:"selectPrevCodeAction",title:(0,E.localize2)(1499,"Select previous action"),precondition:t.Visible,keybinding:{weight:s,primary:16,secondary:[2064],mac:{primary:16,secondary:[2064,302]}}})}run(g){const c=g.get(e.IActionWidgetService);c instanceof i&&c.focusPrevious()}}),(0,m.registerAction2)(class extends m.Action2{constructor(){super({id:"selectNextCodeAction",title:(0,E.localize2)(1500,"Select next action"),precondition:t.Visible,keybinding:{weight:s,primary:18,secondary:[2066],mac:{primary:18,secondary:[2066,300]}}})}run(g){const c=g.get(e.IActionWidgetService);c instanceof i&&c.focusNext()}}),(0,m.registerAction2)(class extends m.Action2{constructor(){super({id:y.acceptSelectedActionCommand,title:(0,E.localize2)(1501,"Accept selected action"),precondition:t.Visible,keybinding:{weight:s,primary:3,secondary:[2137]}})}run(g){const c=g.get(e.IActionWidgetService);c instanceof i&&c.acceptSelected()}}),(0,m.registerAction2)(class extends m.Action2{constructor(){super({id:y.previewSelectedActionCommand,title:(0,E.localize2)(1502,"Preview selected action"),precondition:t.Visible,keybinding:{weight:s,primary:2051}})}run(g){const c=g.get(e.IActionWidgetService);c instanceof i&&c.acceptSelected(!0)}})}),define(ne[761],se([1,0,5,77,642,41,8,2,110]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContextMenuHandler=void 0;class b{constructor(n,o,t,i){this.contextViewService=n,this.telemetryService=o,this.notificationService=t,this.keybindingService=i,this.focusToReturn=null,this.lastContainer=null,this.block=null,this.blockDisposable=null,this.options={blockMouse:!0}}configure(n){this.options=n}showContextMenu(n){const o=n.getActions();if(!o.length)return;this.focusToReturn=(0,d.getActiveElement)();let t;const i=(0,d.isHTMLElement)(n.domForShadowRoot)?n.domForShadowRoot:void 0;this.contextViewService.showContextView({getAnchor:()=>n.getAnchor(),canRelayout:!1,anchorAlignment:n.anchorAlignment,anchorAxisAlignment:n.anchorAxisAlignment,render:s=>{this.lastContainer=s;const g=n.getMenuClassName?n.getMenuClassName():"";g&&(s.className+=" "+g),this.options.blockMouse&&(this.block=s.appendChild((0,d.$)(".context-view-block")),this.block.style.position="fixed",this.block.style.cursor="initial",this.block.style.left="0",this.block.style.top="0",this.block.style.width="100%",this.block.style.height="100%",this.block.style.zIndex="-1",this.blockDisposable?.dispose(),this.blockDisposable=(0,d.addDisposableListener)(this.block,d.EventType.MOUSE_DOWN,r=>r.stopPropagation()));const c=new m.DisposableStore,l=n.actionRunner||new E.ActionRunner;l.onWillRun(r=>this.onActionRun(r,!n.skipTelemetry),this,c),l.onDidRun(this.onDidActionRun,this,c),t=new I.Menu(s,o,{actionViewItemProvider:n.getActionViewItem,context:n.getActionsContext?n.getActionsContext():null,actionRunner:l,getKeyBinding:n.getKeyBinding?n.getKeyBinding:r=>this.keybindingService.lookupKeybinding(r.id)},_.defaultMenuStyles),t.onDidCancel(()=>this.contextViewService.hideContextView(!0),null,c),t.onDidBlur(()=>this.contextViewService.hideContextView(!0),null,c);const a=(0,d.getWindow)(s);return c.add((0,d.addDisposableListener)(a,d.EventType.BLUR,()=>this.contextViewService.hideContextView(!0))),c.add((0,d.addDisposableListener)(a,d.EventType.MOUSE_DOWN,r=>{if(r.defaultPrevented)return;const u=new k.StandardMouseEvent(a,r);let C=u.target;if(!u.rightButton){for(;C;){if(C===s)return;C=C.parentElement}this.contextViewService.hideContextView(!0)}})),(0,m.combinedDisposable)(c,t)},focus:()=>{t?.focus(!!n.autoSelectFirstItem)},onHide:s=>{n.onHide?.(!!s),this.block&&(this.block.remove(),this.block=null),this.blockDisposable?.dispose(),this.blockDisposable=null,this.lastContainer&&((0,d.getActiveElement)()===this.lastContainer||(0,d.isAncestor)((0,d.getActiveElement)(),this.lastContainer))&&this.focusToReturn?.focus(),this.lastContainer=null}},i,!!i)}onActionRun(n,o){o&&this.telemetryService.publicLog2("workbenchActionExecuted",{id:n.action.id,from:"contextMenu"}),this.contextViewService.hideContextView(!1)}onDidActionRun(n){n.error&&!(0,y.isCancellationError)(n.error)&&this.notificationService.error(n.error)}}e.ContextMenuHandler=b}),define(ne[216],se([1,0,5,637,115,638,176,645,644,360,6,2,3,28,109,12,179,58,7,31,38,110]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.WorkbenchCompressibleAsyncDataTree=e.WorkbenchAsyncDataTree=e.WorkbenchDataTree=e.WorkbenchCompressibleObjectTree=e.WorkbenchObjectTree=e.WorkbenchTable=e.WorkbenchPagedList=e.WorkbenchList=e.WorkbenchTreeFindOpen=e.WorkbenchTreeElementHasChild=e.WorkbenchTreeElementCanExpand=e.WorkbenchTreeElementHasParent=e.WorkbenchTreeElementCanCollapse=e.WorkbenchListSupportsFind=e.WorkbenchListSelectionNavigation=e.WorkbenchListMultiSelection=e.WorkbenchListDoubleSelection=e.WorkbenchListHasSelectionOrFocus=e.WorkbenchListFocusContextKey=e.WorkbenchListSupportsMultiSelectContextKey=e.WorkbenchTreeStickyScrollFocused=e.RawWorkbenchListFocusContextKey=e.WorkbenchListScrollAtBottomContextKey=e.WorkbenchListScrollAtTopContextKey=e.RawWorkbenchListScrollAtBoundaryContextKey=e.ListService=e.IListService=void 0,e.IListService=(0,l.createDecorator)("listService");class C{get lastFocusedList(){return this._lastFocusedWidget}constructor(){this.disposables=new n.DisposableStore,this.lists=[],this._lastFocusedWidget=void 0,this._hasCreatedStyleController=!1}setLastFocusedList(le){le!==this._lastFocusedWidget&&(this._lastFocusedWidget?.getHTMLElement().classList.remove("last-focused"),this._lastFocusedWidget=le,this._lastFocusedWidget?.getHTMLElement().classList.add("last-focused"))}register(le,me){if(this._hasCreatedStyleController||(this._hasCreatedStyleController=!0,new I.DefaultStyleController((0,d.createStyleSheet)(),"").style(u.defaultListStyles)),this.lists.some(ye=>ye.widget===le))throw new Error("Cannot register the same widget multiple times");const Ce={widget:le,extraContextKeys:me};return this.lists.push(Ce),(0,d.isActiveElement)(le.getHTMLElement())&&this.setLastFocusedList(le),(0,n.combinedDisposable)(le.onDidFocus(()=>this.setLastFocusedList(le)),(0,n.toDisposable)(()=>this.lists.splice(this.lists.indexOf(Ce),1)),le.onDidDispose(()=>{this.lists=this.lists.filter(ye=>ye!==Ce),this._lastFocusedWidget===le&&this.setLastFocusedList(void 0)}))}dispose(){this.disposables.dispose()}}e.ListService=C,e.RawWorkbenchListScrollAtBoundaryContextKey=new s.RawContextKey("listScrollAtBoundary","none"),e.WorkbenchListScrollAtTopContextKey=s.ContextKeyExpr.or(e.RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo("top"),e.RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo("both")),e.WorkbenchListScrollAtBottomContextKey=s.ContextKeyExpr.or(e.RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo("bottom"),e.RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo("both")),e.RawWorkbenchListFocusContextKey=new s.RawContextKey("listFocus",!0),e.WorkbenchTreeStickyScrollFocused=new s.RawContextKey("treestickyScrollFocused",!1),e.WorkbenchListSupportsMultiSelectContextKey=new s.RawContextKey("listSupportsMultiselect",!0),e.WorkbenchListFocusContextKey=s.ContextKeyExpr.and(e.RawWorkbenchListFocusContextKey,s.ContextKeyExpr.not(g.InputFocusedContextKey),e.WorkbenchTreeStickyScrollFocused.negate()),e.WorkbenchListHasSelectionOrFocus=new s.RawContextKey("listHasSelectionOrFocus",!1),e.WorkbenchListDoubleSelection=new s.RawContextKey("listDoubleSelection",!1),e.WorkbenchListMultiSelection=new s.RawContextKey("listMultiSelection",!1),e.WorkbenchListSelectionNavigation=new s.RawContextKey("listSelectionNavigation",!1),e.WorkbenchListSupportsFind=new s.RawContextKey("listSupportsFind",!0),e.WorkbenchTreeElementCanCollapse=new s.RawContextKey("treeElementCanCollapse",!1),e.WorkbenchTreeElementHasParent=new s.RawContextKey("treeElementHasParent",!1),e.WorkbenchTreeElementCanExpand=new s.RawContextKey("treeElementCanExpand",!1),e.WorkbenchTreeElementHasChild=new s.RawContextKey("treeElementHasChild",!1),e.WorkbenchTreeFindOpen=new s.RawContextKey("treeFindOpen",!1);const f="listTypeNavigationMode",h="listAutomaticKeyboardNavigation";function v(re,le){const me=re.createScoped(le.getHTMLElement());return e.RawWorkbenchListFocusContextKey.bindTo(me),me}function w(re,le){const me=e.RawWorkbenchListScrollAtBoundaryContextKey.bindTo(re),Ce=()=>{const ye=le.scrollTop===0,Le=le.scrollHeight-le.renderHeight-le.scrollTop<1;ye&&Le?me.set("both"):ye?me.set("top"):Le?me.set("bottom"):me.set("none")};return Ce(),le.onDidScroll(Ce)}const S="workbench.list.multiSelectModifier",L="workbench.list.openMode",D="workbench.list.horizontalScrolling",T="workbench.list.defaultFindMode",M="workbench.list.typeNavigationMode",A="workbench.list.keyboardNavigation",P="workbench.list.scrollByPage",N="workbench.list.defaultFindMatchType",O="workbench.tree.indent",F="workbench.tree.renderIndentGuides",x="workbench.list.smoothScrolling",W="workbench.list.mouseWheelScrollSensitivity",V="workbench.list.fastScrollSensitivity",q="workbench.tree.expandMode",H="workbench.tree.enableStickyScroll",z="workbench.tree.stickyScrollMaxItemCount";function U(re){return re.getValue(S)==="alt"}class j extends n.Disposable{constructor(le){super(),this.configurationService=le,this.useAltAsMultipleSelectionModifier=U(le),this.registerListeners()}registerListeners(){this._register(this.configurationService.onDidChangeConfiguration(le=>{le.affectsConfiguration(S)&&(this.useAltAsMultipleSelectionModifier=U(this.configurationService))}))}isSelectionSingleChangeEvent(le){return this.useAltAsMultipleSelectionModifier?le.browserEvent.altKey:(0,I.isSelectionSingleChangeEvent)(le)}isSelectionRangeChangeEvent(le){return(0,I.isSelectionRangeChangeEvent)(le)}}function Y(re,le){const me=re.get(t.IConfigurationService),Ce=re.get(a.IKeybindingService),ye=new n.DisposableStore;return[{...le,keyboardNavigationDelegate:{mightProducePrintableCharacter(Ee){return Ce.mightProducePrintableCharacter(Ee)}},smoothScrolling:!!me.getValue(x),mouseWheelScrollSensitivity:me.getValue(W),fastScrollSensitivity:me.getValue(V),multipleSelectionController:le.multipleSelectionController??ye.add(new j(me)),keyboardNavigationEventFilter:pe(Ce),scrollByPage:!!me.getValue(P)},ye]}let G=class extends I.List{constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne){const Ke=typeof Le.horizontalScrolling<"u"?Le.horizontalScrolling:!!Ae.getValue(D),[ze,Ge]=Ne.invokeFunction(Y,Le);super(le,me,Ce,ye,{keyboardSupport:!1,...ze,horizontalScrolling:Ke}),this.disposables.add(Ge),this.contextKeyService=v(Ee,this),this.disposables.add(w(this.contextKeyService,this)),this.listSupportsMultiSelect=e.WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService),this.listSupportsMultiSelect.set(Le.multipleSelectionSupport!==!1),e.WorkbenchListSelectionNavigation.bindTo(this.contextKeyService).set(!!Le.selectionNavigation),this.listHasSelectionOrFocus=e.WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService),this.listDoubleSelection=e.WorkbenchListDoubleSelection.bindTo(this.contextKeyService),this.listMultiSelection=e.WorkbenchListMultiSelection.bindTo(this.contextKeyService),this.horizontalScrolling=Le.horizontalScrolling,this._useAltAsMultipleSelectionModifier=U(Ae),this.disposables.add(this.contextKeyService),this.disposables.add(Me.register(this)),this.updateStyles(Le.overrideStyles),this.disposables.add(this.onDidChangeSelection(()=>{const Oe=this.getSelection(),Fe=this.getFocus();this.contextKeyService.bufferChangeEvents(()=>{this.listHasSelectionOrFocus.set(Oe.length>0||Fe.length>0),this.listMultiSelection.set(Oe.length>1),this.listDoubleSelection.set(Oe.length===2)})})),this.disposables.add(this.onDidChangeFocus(()=>{const Oe=this.getSelection(),Fe=this.getFocus();this.listHasSelectionOrFocus.set(Oe.length>0||Fe.length>0)})),this.disposables.add(Ae.onDidChangeConfiguration(Oe=>{Oe.affectsConfiguration(S)&&(this._useAltAsMultipleSelectionModifier=U(Ae));let Fe={};if(Oe.affectsConfiguration(D)&&this.horizontalScrolling===void 0){const fe=!!Ae.getValue(D);Fe={...Fe,horizontalScrolling:fe}}if(Oe.affectsConfiguration(P)){const fe=!!Ae.getValue(P);Fe={...Fe,scrollByPage:fe}}if(Oe.affectsConfiguration(x)){const fe=!!Ae.getValue(x);Fe={...Fe,smoothScrolling:fe}}if(Oe.affectsConfiguration(W)){const fe=Ae.getValue(W);Fe={...Fe,mouseWheelScrollSensitivity:fe}}if(Oe.affectsConfiguration(V)){const fe=Ae.getValue(V);Fe={...Fe,fastScrollSensitivity:fe}}Object.keys(Fe).length>0&&this.updateOptions(Fe)})),this.navigator=new ie(this,{configurationService:Ae,...Le}),this.disposables.add(this.navigator)}updateOptions(le){super.updateOptions(le),le.overrideStyles!==void 0&&this.updateStyles(le.overrideStyles),le.multipleSelectionSupport!==void 0&&this.listSupportsMultiSelect.set(!!le.multipleSelectionSupport)}updateStyles(le){this.style(le?(0,u.getListStyles)(le):u.defaultListStyles)}};e.WorkbenchList=G,e.WorkbenchList=G=ke([ce(5,s.IContextKeyService),ce(6,e.IListService),ce(7,t.IConfigurationService),ce(8,l.IInstantiationService)],G);let K=class extends k.PagedList{constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne){const Ke=typeof Le.horizontalScrolling<"u"?Le.horizontalScrolling:!!Ae.getValue(D),[ze,Ge]=Ne.invokeFunction(Y,Le);super(le,me,Ce,ye,{keyboardSupport:!1,...ze,horizontalScrolling:Ke}),this.disposables=new n.DisposableStore,this.disposables.add(Ge),this.contextKeyService=v(Ee,this),this.disposables.add(w(this.contextKeyService,this.widget)),this.horizontalScrolling=Le.horizontalScrolling,this.listSupportsMultiSelect=e.WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService),this.listSupportsMultiSelect.set(Le.multipleSelectionSupport!==!1),e.WorkbenchListSelectionNavigation.bindTo(this.contextKeyService).set(!!Le.selectionNavigation),this._useAltAsMultipleSelectionModifier=U(Ae),this.disposables.add(this.contextKeyService),this.disposables.add(Me.register(this)),this.updateStyles(Le.overrideStyles),this.disposables.add(Ae.onDidChangeConfiguration(Oe=>{Oe.affectsConfiguration(S)&&(this._useAltAsMultipleSelectionModifier=U(Ae));let Fe={};if(Oe.affectsConfiguration(D)&&this.horizontalScrolling===void 0){const fe=!!Ae.getValue(D);Fe={...Fe,horizontalScrolling:fe}}if(Oe.affectsConfiguration(P)){const fe=!!Ae.getValue(P);Fe={...Fe,scrollByPage:fe}}if(Oe.affectsConfiguration(x)){const fe=!!Ae.getValue(x);Fe={...Fe,smoothScrolling:fe}}if(Oe.affectsConfiguration(W)){const fe=Ae.getValue(W);Fe={...Fe,mouseWheelScrollSensitivity:fe}}if(Oe.affectsConfiguration(V)){const fe=Ae.getValue(V);Fe={...Fe,fastScrollSensitivity:fe}}Object.keys(Fe).length>0&&this.updateOptions(Fe)})),this.navigator=new ie(this,{configurationService:Ae,...Le}),this.disposables.add(this.navigator)}updateOptions(le){super.updateOptions(le),le.overrideStyles!==void 0&&this.updateStyles(le.overrideStyles),le.multipleSelectionSupport!==void 0&&this.listSupportsMultiSelect.set(!!le.multipleSelectionSupport)}updateStyles(le){this.style(le?(0,u.getListStyles)(le):u.defaultListStyles)}dispose(){this.disposables.dispose(),super.dispose()}};e.WorkbenchPagedList=K,e.WorkbenchPagedList=K=ke([ce(5,s.IContextKeyService),ce(6,e.IListService),ce(7,t.IConfigurationService),ce(8,l.IInstantiationService)],K);let R=class extends E.Table{constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne,Ke){const ze=typeof Ee.horizontalScrolling<"u"?Ee.horizontalScrolling:!!Ne.getValue(D),[Ge,it]=Ke.invokeFunction(Y,Ee);super(le,me,Ce,ye,Le,{keyboardSupport:!1,...Ge,horizontalScrolling:ze}),this.disposables.add(it),this.contextKeyService=v(Me,this),this.disposables.add(w(this.contextKeyService,this)),this.listSupportsMultiSelect=e.WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService),this.listSupportsMultiSelect.set(Ee.multipleSelectionSupport!==!1),e.WorkbenchListSelectionNavigation.bindTo(this.contextKeyService).set(!!Ee.selectionNavigation),this.listHasSelectionOrFocus=e.WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService),this.listDoubleSelection=e.WorkbenchListDoubleSelection.bindTo(this.contextKeyService),this.listMultiSelection=e.WorkbenchListMultiSelection.bindTo(this.contextKeyService),this.horizontalScrolling=Ee.horizontalScrolling,this._useAltAsMultipleSelectionModifier=U(Ne),this.disposables.add(this.contextKeyService),this.disposables.add(Ae.register(this)),this.updateStyles(Ee.overrideStyles),this.disposables.add(this.onDidChangeSelection(()=>{const Fe=this.getSelection(),fe=this.getFocus();this.contextKeyService.bufferChangeEvents(()=>{this.listHasSelectionOrFocus.set(Fe.length>0||fe.length>0),this.listMultiSelection.set(Fe.length>1),this.listDoubleSelection.set(Fe.length===2)})})),this.disposables.add(this.onDidChangeFocus(()=>{const Fe=this.getSelection(),fe=this.getFocus();this.listHasSelectionOrFocus.set(Fe.length>0||fe.length>0)})),this.disposables.add(Ne.onDidChangeConfiguration(Fe=>{Fe.affectsConfiguration(S)&&(this._useAltAsMultipleSelectionModifier=U(Ne));let fe={};if(Fe.affectsConfiguration(D)&&this.horizontalScrolling===void 0){const _e=!!Ne.getValue(D);fe={...fe,horizontalScrolling:_e}}if(Fe.affectsConfiguration(P)){const _e=!!Ne.getValue(P);fe={...fe,scrollByPage:_e}}if(Fe.affectsConfiguration(x)){const _e=!!Ne.getValue(x);fe={...fe,smoothScrolling:_e}}if(Fe.affectsConfiguration(W)){const _e=Ne.getValue(W);fe={...fe,mouseWheelScrollSensitivity:_e}}if(Fe.affectsConfiguration(V)){const _e=Ne.getValue(V);fe={...fe,fastScrollSensitivity:_e}}Object.keys(fe).length>0&&this.updateOptions(fe)})),this.navigator=new ue(this,{configurationService:Ne,...Ee}),this.disposables.add(this.navigator)}updateOptions(le){super.updateOptions(le),le.overrideStyles!==void 0&&this.updateStyles(le.overrideStyles),le.multipleSelectionSupport!==void 0&&this.listSupportsMultiSelect.set(!!le.multipleSelectionSupport)}updateStyles(le){this.style(le?(0,u.getListStyles)(le):u.defaultListStyles)}dispose(){this.disposables.dispose(),super.dispose()}};e.WorkbenchTable=R,e.WorkbenchTable=R=ke([ce(6,s.IContextKeyService),ce(7,e.IListService),ce(8,t.IConfigurationService),ce(9,l.IInstantiationService)],R);class J extends n.Disposable{constructor(le,me){super(),this.widget=le,this._onDidOpen=this._register(new p.Emitter),this.onDidOpen=this._onDidOpen.event,this._register(p.Event.filter(this.widget.onDidChangeSelection,Ce=>(0,d.isKeyboardEvent)(Ce.browserEvent))(Ce=>this.onSelectionFromKeyboard(Ce))),this._register(this.widget.onPointer(Ce=>this.onPointer(Ce.element,Ce.browserEvent))),this._register(this.widget.onMouseDblClick(Ce=>this.onMouseDblClick(Ce.element,Ce.browserEvent))),typeof me?.openOnSingleClick!="boolean"&&me?.configurationService?(this.openOnSingleClick=me?.configurationService.getValue(L)!=="doubleClick",this._register(me?.configurationService.onDidChangeConfiguration(Ce=>{Ce.affectsConfiguration(L)&&(this.openOnSingleClick=me?.configurationService.getValue(L)!=="doubleClick")}))):this.openOnSingleClick=me?.openOnSingleClick??!0}onSelectionFromKeyboard(le){if(le.elements.length!==1)return;const me=le.browserEvent,Ce=typeof me.preserveFocus=="boolean"?me.preserveFocus:!0,ye=typeof me.pinned=="boolean"?me.pinned:!Ce;this._open(this.getSelectedElement(),Ce,ye,!1,le.browserEvent)}onPointer(le,me){if(!this.openOnSingleClick||me.detail===2)return;const ye=me.button===1,Le=!0,Ee=ye,Me=me.ctrlKey||me.metaKey||me.altKey;this._open(le,Le,Ee,Me,me)}onMouseDblClick(le,me){if(!me)return;const Ce=me.target;if(Ce.classList.contains("monaco-tl-twistie")||Ce.classList.contains("monaco-icon-label")&&Ce.classList.contains("folder-icon")&&me.offsetX<16)return;const Le=!1,Ee=!0,Me=me.ctrlKey||me.metaKey||me.altKey;this._open(le,Le,Ee,Me,me)}_open(le,me,Ce,ye,Le){le&&this._onDidOpen.fire({editorOptions:{preserveFocus:me,pinned:Ce,revealIfVisible:!0},sideBySide:ye,element:le,browserEvent:Le})}}class ie extends J{constructor(le,me){super(le,me),this.widget=le}getSelectedElement(){return this.widget.getSelectedElements()[0]}}class ue extends J{constructor(le,me){super(le,me)}getSelectedElement(){return this.widget.getSelectedElements()[0]}}class he extends J{constructor(le,me){super(le,me)}getSelectedElement(){return this.widget.getSelection()[0]??void 0}}function pe(re){let le=!1;return me=>{if(me.toKeyCodeChord().isModifierKey())return!1;if(le)return le=!1,!1;const Ce=re.softDispatch(me,me.target);return Ce.kind===1?(le=!0,!1):(le=!1,Ce.kind===0)}}let ae=class extends b.ObjectTree{constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne){const{options:Ke,getTypeNavigationMode:ze,disposable:Ge}=Ee.invokeFunction(Q,Le);super(le,me,Ce,ye,Ke),this.disposables.add(Ge),this.internals=new Z(this,Le,ze,Le.overrideStyles,Me,Ae,Ne),this.disposables.add(this.internals)}updateOptions(le){super.updateOptions(le),this.internals.updateOptions(le)}};e.WorkbenchObjectTree=ae,e.WorkbenchObjectTree=ae=ke([ce(5,l.IInstantiationService),ce(6,s.IContextKeyService),ce(7,e.IListService),ce(8,t.IConfigurationService)],ae);let ee=class extends b.CompressibleObjectTree{constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne){const{options:Ke,getTypeNavigationMode:ze,disposable:Ge}=Ee.invokeFunction(Q,Le);super(le,me,Ce,ye,Ke),this.disposables.add(Ge),this.internals=new Z(this,Le,ze,Le.overrideStyles,Me,Ae,Ne),this.disposables.add(this.internals)}updateOptions(le={}){super.updateOptions(le),le.overrideStyles&&this.internals.updateStyleOverrides(le.overrideStyles),this.internals.updateOptions(le)}};e.WorkbenchCompressibleObjectTree=ee,e.WorkbenchCompressibleObjectTree=ee=ke([ce(5,l.IInstantiationService),ce(6,s.IContextKeyService),ce(7,e.IListService),ce(8,t.IConfigurationService)],ee);let de=class extends _.DataTree{constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne,Ke){const{options:ze,getTypeNavigationMode:Ge,disposable:it}=Me.invokeFunction(Q,Ee);super(le,me,Ce,ye,Le,ze),this.disposables.add(it),this.internals=new Z(this,Ee,Ge,Ee.overrideStyles,Ae,Ne,Ke),this.disposables.add(this.internals)}updateOptions(le={}){super.updateOptions(le),le.overrideStyles!==void 0&&this.internals.updateStyleOverrides(le.overrideStyles),this.internals.updateOptions(le)}};e.WorkbenchDataTree=de,e.WorkbenchDataTree=de=ke([ce(6,l.IInstantiationService),ce(7,s.IContextKeyService),ce(8,e.IListService),ce(9,t.IConfigurationService)],de);let ge=class extends m.AsyncDataTree{get onDidOpen(){return this.internals.onDidOpen}constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne,Ke){const{options:ze,getTypeNavigationMode:Ge,disposable:it}=Me.invokeFunction(Q,Ee);super(le,me,Ce,ye,Le,ze),this.disposables.add(it),this.internals=new Z(this,Ee,Ge,Ee.overrideStyles,Ae,Ne,Ke),this.disposables.add(this.internals)}updateOptions(le={}){super.updateOptions(le),le.overrideStyles&&this.internals.updateStyleOverrides(le.overrideStyles),this.internals.updateOptions(le)}};e.WorkbenchAsyncDataTree=ge,e.WorkbenchAsyncDataTree=ge=ke([ce(6,l.IInstantiationService),ce(7,s.IContextKeyService),ce(8,e.IListService),ce(9,t.IConfigurationService)],ge);let X=class extends m.CompressibleAsyncDataTree{constructor(le,me,Ce,ye,Le,Ee,Me,Ae,Ne,Ke,ze){const{options:Ge,getTypeNavigationMode:it,disposable:Oe}=Ae.invokeFunction(Q,Me);super(le,me,Ce,ye,Le,Ee,Ge),this.disposables.add(Oe),this.internals=new Z(this,Me,it,Me.overrideStyles,Ne,Ke,ze),this.disposables.add(this.internals)}updateOptions(le){super.updateOptions(le),this.internals.updateOptions(le)}};e.WorkbenchCompressibleAsyncDataTree=X,e.WorkbenchCompressibleAsyncDataTree=X=ke([ce(7,l.IInstantiationService),ce(8,s.IContextKeyService),ce(9,e.IListService),ce(10,t.IConfigurationService)],X);function B(re){const le=re.getValue(T);if(le==="highlight")return y.TreeFindMode.Highlight;if(le==="filter")return y.TreeFindMode.Filter;const me=re.getValue(A);if(me==="simple"||me==="highlight")return y.TreeFindMode.Highlight;if(me==="filter")return y.TreeFindMode.Filter}function $(re){const le=re.getValue(N);if(le==="fuzzy")return y.TreeFindMatchType.Fuzzy;if(le==="contiguous")return y.TreeFindMatchType.Contiguous}function Q(re,le){const me=re.get(t.IConfigurationService),Ce=re.get(c.IContextViewService),ye=re.get(s.IContextKeyService),Le=re.get(l.IInstantiationService),Ee=()=>{const Ge=ye.getContextKeyValue(f);if(Ge==="automatic")return I.TypeNavigationMode.Automatic;if(Ge==="trigger"||ye.getContextKeyValue(h)===!1)return I.TypeNavigationMode.Trigger;const Oe=me.getValue(M);if(Oe==="automatic")return I.TypeNavigationMode.Automatic;if(Oe==="trigger")return I.TypeNavigationMode.Trigger},Me=le.horizontalScrolling!==void 0?le.horizontalScrolling:!!me.getValue(D),[Ae,Ne]=Le.invokeFunction(Y,le),Ke=le.paddingBottom,ze=le.renderIndentGuides!==void 0?le.renderIndentGuides:me.getValue(F);return{getTypeNavigationMode:Ee,disposable:Ne,options:{keyboardSupport:!1,...Ae,indent:typeof me.getValue(O)=="number"?me.getValue(O):void 0,renderIndentGuides:ze,smoothScrolling:!!me.getValue(x),defaultFindMode:B(me),defaultFindMatchType:$(me),horizontalScrolling:Me,scrollByPage:!!me.getValue(P),paddingBottom:Ke,hideTwistiesOfChildlessElements:le.hideTwistiesOfChildlessElements,expandOnlyOnTwistieClick:le.expandOnlyOnTwistieClick??me.getValue(q)==="doubleClick",contextViewProvider:Ce,findWidgetStyles:u.defaultFindWidgetStyles,enableStickyScroll:!!me.getValue(H),stickyScrollMaxItemCount:Number(me.getValue(z))}}}let Z=class{get onDidOpen(){return this.navigator.onDidOpen}constructor(le,me,Ce,ye,Le,Ee,Me){this.tree=le,this.disposables=[],this.contextKeyService=v(Le,le),this.disposables.push(w(this.contextKeyService,le)),this.listSupportsMultiSelect=e.WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService),this.listSupportsMultiSelect.set(me.multipleSelectionSupport!==!1),e.WorkbenchListSelectionNavigation.bindTo(this.contextKeyService).set(!!me.selectionNavigation),this.listSupportFindWidget=e.WorkbenchListSupportsFind.bindTo(this.contextKeyService),this.listSupportFindWidget.set(me.findWidgetEnabled??!0),this.hasSelectionOrFocus=e.WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService),this.hasDoubleSelection=e.WorkbenchListDoubleSelection.bindTo(this.contextKeyService),this.hasMultiSelection=e.WorkbenchListMultiSelection.bindTo(this.contextKeyService),this.treeElementCanCollapse=e.WorkbenchTreeElementCanCollapse.bindTo(this.contextKeyService),this.treeElementHasParent=e.WorkbenchTreeElementHasParent.bindTo(this.contextKeyService),this.treeElementCanExpand=e.WorkbenchTreeElementCanExpand.bindTo(this.contextKeyService),this.treeElementHasChild=e.WorkbenchTreeElementHasChild.bindTo(this.contextKeyService),this.treeFindOpen=e.WorkbenchTreeFindOpen.bindTo(this.contextKeyService),this.treeStickyScrollFocused=e.WorkbenchTreeStickyScrollFocused.bindTo(this.contextKeyService),this._useAltAsMultipleSelectionModifier=U(Me),this.updateStyleOverrides(ye);const Ne=()=>{const ze=le.getFocus()[0];if(!ze)return;const Ge=le.getNode(ze);this.treeElementCanCollapse.set(Ge.collapsible&&!Ge.collapsed),this.treeElementHasParent.set(!!le.getParentElement(ze)),this.treeElementCanExpand.set(Ge.collapsible&&Ge.collapsed),this.treeElementHasChild.set(!!le.getFirstElementChild(ze))},Ke=new Set;Ke.add(f),Ke.add(h),this.disposables.push(this.contextKeyService,Ee.register(le),le.onDidChangeSelection(()=>{const ze=le.getSelection(),Ge=le.getFocus();this.contextKeyService.bufferChangeEvents(()=>{this.hasSelectionOrFocus.set(ze.length>0||Ge.length>0),this.hasMultiSelection.set(ze.length>1),this.hasDoubleSelection.set(ze.length===2)})}),le.onDidChangeFocus(()=>{const ze=le.getSelection(),Ge=le.getFocus();this.hasSelectionOrFocus.set(ze.length>0||Ge.length>0),Ne()}),le.onDidChangeCollapseState(Ne),le.onDidChangeModel(Ne),le.onDidChangeFindOpenState(ze=>this.treeFindOpen.set(ze)),le.onDidChangeStickyScrollFocused(ze=>this.treeStickyScrollFocused.set(ze)),Me.onDidChangeConfiguration(ze=>{let Ge={};if(ze.affectsConfiguration(S)&&(this._useAltAsMultipleSelectionModifier=U(Me)),ze.affectsConfiguration(O)){const it=Me.getValue(O);Ge={...Ge,indent:it}}if(ze.affectsConfiguration(F)&&me.renderIndentGuides===void 0){const it=Me.getValue(F);Ge={...Ge,renderIndentGuides:it}}if(ze.affectsConfiguration(x)){const it=!!Me.getValue(x);Ge={...Ge,smoothScrolling:it}}if(ze.affectsConfiguration(T)||ze.affectsConfiguration(A)){const it=B(Me);Ge={...Ge,defaultFindMode:it}}if(ze.affectsConfiguration(M)||ze.affectsConfiguration(A)){const it=Ce();Ge={...Ge,typeNavigationMode:it}}if(ze.affectsConfiguration(N)){const it=$(Me);Ge={...Ge,defaultFindMatchType:it}}if(ze.affectsConfiguration(D)&&me.horizontalScrolling===void 0){const it=!!Me.getValue(D);Ge={...Ge,horizontalScrolling:it}}if(ze.affectsConfiguration(P)){const it=!!Me.getValue(P);Ge={...Ge,scrollByPage:it}}if(ze.affectsConfiguration(q)&&me.expandOnlyOnTwistieClick===void 0&&(Ge={...Ge,expandOnlyOnTwistieClick:Me.getValue(q)==="doubleClick"}),ze.affectsConfiguration(H)){const it=Me.getValue(H);Ge={...Ge,enableStickyScroll:it}}if(ze.affectsConfiguration(z)){const it=Math.max(1,Me.getValue(z));Ge={...Ge,stickyScrollMaxItemCount:it}}if(ze.affectsConfiguration(W)){const it=Me.getValue(W);Ge={...Ge,mouseWheelScrollSensitivity:it}}if(ze.affectsConfiguration(V)){const it=Me.getValue(V);Ge={...Ge,fastScrollSensitivity:it}}Object.keys(Ge).length>0&&le.updateOptions(Ge)}),this.contextKeyService.onDidChangeContext(ze=>{ze.affectsSome(Ke)&&le.updateOptions({typeNavigationMode:Ce()})})),this.navigator=new he(le,{configurationService:Me,...me}),this.disposables.push(this.navigator)}updateOptions(le){le.multipleSelectionSupport!==void 0&&this.listSupportsMultiSelect.set(!!le.multipleSelectionSupport)}updateStyleOverrides(le){this.tree.style(le?(0,u.getListStyles)(le):u.defaultListStyles)}dispose(){this.disposables=(0,n.dispose)(this.disposables)}};Z=ke([ce(4,s.IContextKeyService),ce(5,e.IListService),ce(6,t.IConfigurationService)],Z),r.Registry.as(i.Extensions.Configuration).registerConfiguration({id:"workbench",order:7,title:(0,o.localize)(1542,"Workbench"),type:"object",properties:{[S]:{type:"string",enum:["ctrlCmd","alt"],markdownEnumDescriptions:[(0,o.localize)(1543,"Maps to `Control` on Windows and Linux and to `Command` on macOS."),(0,o.localize)(1544,"Maps to `Alt` on Windows and Linux and to `Option` on macOS.")],default:"ctrlCmd",description:(0,o.localize)(1545,"The modifier to be used to add an item in trees and lists to a multi-selection with the mouse (for example in the explorer, open editors and scm view). The 'Open to Side' mouse gestures - if supported - will adapt such that they do not conflict with the multiselect modifier.")},[L]:{type:"string",enum:["singleClick","doubleClick"],default:"singleClick",description:(0,o.localize)(1546,"Controls how to open items in trees and lists using the mouse (if supported). Note that some trees and lists might choose to ignore this setting if it is not applicable.")},[D]:{type:"boolean",default:!1,description:(0,o.localize)(1547,"Controls whether lists and trees support horizontal scrolling in the workbench. Warning: turning on this setting has a performance implication.")},[P]:{type:"boolean",default:!1,description:(0,o.localize)(1548,"Controls whether clicks in the scrollbar scroll page by page.")},[O]:{type:"number",default:8,minimum:4,maximum:40,description:(0,o.localize)(1549,"Controls tree indentation in pixels.")},[F]:{type:"string",enum:["none","onHover","always"],default:"onHover",description:(0,o.localize)(1550,"Controls whether the tree should render indent guides.")},[x]:{type:"boolean",default:!1,description:(0,o.localize)(1551,"Controls whether lists and trees have smooth scrolling.")},[W]:{type:"number",default:1,markdownDescription:(0,o.localize)(1552,"A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.")},[V]:{type:"number",default:5,markdownDescription:(0,o.localize)(1553,"Scrolling speed multiplier when pressing `Alt`.")},[T]:{type:"string",enum:["highlight","filter"],enumDescriptions:[(0,o.localize)(1554,"Highlight elements when searching. Further up and down navigation will traverse only the highlighted elements."),(0,o.localize)(1555,"Filter elements when searching.")],default:"highlight",description:(0,o.localize)(1556,"Controls the default find mode for lists and trees in the workbench.")},[A]:{type:"string",enum:["simple","highlight","filter"],enumDescriptions:[(0,o.localize)(1557,"Simple keyboard navigation focuses elements which match the keyboard input. Matching is done only on prefixes."),(0,o.localize)(1558,"Highlight keyboard navigation highlights elements which match the keyboard input. Further up and down navigation will traverse only the highlighted elements."),(0,o.localize)(1559,"Filter keyboard navigation will filter out and hide all the elements which do not match the keyboard input.")],default:"highlight",description:(0,o.localize)(1560,"Controls the keyboard navigation style for lists and trees in the workbench. Can be simple, highlight and filter."),deprecated:!0,deprecationMessage:(0,o.localize)(1561,"Please use 'workbench.list.defaultFindMode' and 'workbench.list.typeNavigationMode' instead.")},[N]:{type:"string",enum:["fuzzy","contiguous"],enumDescriptions:[(0,o.localize)(1562,"Use fuzzy matching when searching."),(0,o.localize)(1563,"Use contiguous matching when searching.")],default:"fuzzy",description:(0,o.localize)(1564,"Controls the type of matching used when searching lists and trees in the workbench.")},[q]:{type:"string",enum:["singleClick","doubleClick"],default:"singleClick",description:(0,o.localize)(1565,"Controls how tree folders are expanded when clicking the folder names. Note that some trees and lists might choose to ignore this setting if it is not applicable.")},[H]:{type:"boolean",default:!0,description:(0,o.localize)(1566,"Controls whether sticky scrolling is enabled in trees.")},[z]:{type:"number",minimum:1,default:7,markdownDescription:(0,o.localize)(1567,"Controls the number of sticky elements displayed in the tree when {0} is enabled.","`#workbench.tree.enableStickyScroll#`")},[M]:{type:"string",enum:["automatic","trigger"],default:"automatic",markdownDescription:(0,o.localize)(1568,"Controls how type navigation works in lists and trees in the workbench. When set to `trigger`, type navigation begins once the `list.triggerTypeNavigation` command is run.")}}})}),define(ne[71],se([1,0,14,26,191,30,6,19,22,3,273,38]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.spinningLoading=e.syncing=e.gotoNextLocation=e.gotoPreviousLocation=e.widgetClose=e.iconsSchemaId=e.IconFontDefinition=e.IconContribution=e.Extensions=void 0,e.registerIcon=g,e.getIconRegistry=c,e.Extensions={IconContribution:"base.contributions.icons"};var o;(function(u){function C(f,h){let v=f.defaults;for(;E.ThemeIcon.isThemeIcon(v);){const w=s.getIcon(v.id);if(!w)return;v=w.defaults}return v}u.getDefinition=C})(o||(e.IconContribution=o={}));var t;(function(u){function C(h){return{weight:h.weight,style:h.style,src:h.src.map(v=>({format:v.format,location:v.location.toString()}))}}u.toJSONObject=C;function f(h){const v=w=>(0,m.isString)(w)?w:void 0;if(h&&Array.isArray(h.src)&&h.src.every(w=>(0,m.isString)(w.format)&&(0,m.isString)(w.location)))return{weight:v(h.weight),style:v(h.style),src:h.src.map(w=>({format:w.format,location:_.URI.parse(w.location)}))}}u.fromJSONObject=f})(t||(e.IconFontDefinition=t={}));class i{constructor(){this._onDidChange=new y.Emitter,this.onDidChange=this._onDidChange.event,this.iconSchema={definitions:{icons:{type:"object",properties:{fontId:{type:"string",description:(0,b.localize)(1838,"The id of the font to use. If not set, the font that is defined first is used.")},fontCharacter:{type:"string",description:(0,b.localize)(1839,"The font character associated with the icon definition.")}},additionalProperties:!1,defaultSnippets:[{body:{fontCharacter:"\\\\e030"}}]}},type:"object",properties:{}},this.iconReferenceSchema={type:"string",pattern:`^${E.ThemeIcon.iconNameExpression}$`,enum:[],enumDescriptions:[]},this.iconsById={},this.iconFontsById={}}registerIcon(C,f,h,v){const w=this.iconsById[C];if(w){if(h&&!w.description){w.description=h,this.iconSchema.properties[C].markdownDescription=`${h} $(${C})`;const D=this.iconReferenceSchema.enum.indexOf(C);D!==-1&&(this.iconReferenceSchema.enumDescriptions[D]=h),this._onDidChange.fire()}return w}const S={id:C,description:h,defaults:f,deprecationMessage:v};this.iconsById[C]=S;const L={$ref:"#/definitions/icons"};return v&&(L.deprecationMessage=v),h&&(L.markdownDescription=`${h}: $(${C})`),this.iconSchema.properties[C]=L,this.iconReferenceSchema.enum.push(C),this.iconReferenceSchema.enumDescriptions.push(h||""),this._onDidChange.fire(),{id:C}}getIcons(){return Object.keys(this.iconsById).map(C=>this.iconsById[C])}getIcon(C){return this.iconsById[C]}getIconSchema(){return this.iconSchema}toString(){const C=(w,S)=>w.id.localeCompare(S.id),f=w=>{for(;E.ThemeIcon.isThemeIcon(w.defaults);)w=this.iconsById[w.defaults.id];return`codicon codicon-${w?w.id:""}`},h=[];h.push("| preview | identifier | default codicon ID | description"),h.push("| ----------- | --------------------------------- | --------------------------------- | --------------------------------- |");const v=Object.keys(this.iconsById).map(w=>this.iconsById[w]);for(const w of v.filter(S=>!!S.description).sort(C))h.push(`||${w.id}|${E.ThemeIcon.isThemeIcon(w.defaults)?w.defaults.id:w.id}|${w.description||""}|`);h.push("| preview | identifier "),h.push("| ----------- | --------------------------------- |");for(const w of v.filter(S=>!E.ThemeIcon.isThemeIcon(S.defaults)).sort(C))h.push(`||${w.id}|`);return h.join(` `)}}const s=new i;n.Registry.add(e.Extensions.IconContribution,s);function g(u,C,f,h){return s.registerIcon(u,C,f,h)}function c(){return s}function l(){const u=(0,I.getCodiconFontCharacters)();for(const C in u){const f="\\"+u[C].toString(16);s.registerIcon(C,{fontCharacter:f})}}l(),e.iconsSchemaId="vscode://schemas/icons";const a=n.Registry.as(p.Extensions.JSONContribution);a.registerSchema(e.iconsSchemaId,s.getIconSchema());const r=new d.RunOnceScheduler(()=>a.notifySchemaChanged(e.iconsSchemaId),200);s.onDidChange(()=>{r.isScheduled()||r.schedule()}),e.widgetClose=g("widget-close",k.Codicon.close,(0,b.localize)(1840,"Icon for the close action in widgets.")),e.gotoPreviousLocation=g("goto-previous-location",k.Codicon.arrowUp,(0,b.localize)(1841,"Icon for goto previous editor location.")),e.gotoNextLocation=g("goto-next-location",k.Codicon.arrowDown,(0,b.localize)(1842,"Icon for goto next editor location.")),e.syncing=E.ThemeIcon.modify(k.Codicon.sync,"spin"),e.spinningLoading=E.ThemeIcon.modify(k.Codicon.loading,"spin")}),define(ne[762],se([1,0,5,103,87,86,41,13,26,2,21,30,74,88,37,55,68,9,4,105,43,83,136,95,3,137,7,71,499]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AccessibleDiffViewerModelFromEditors=e.AccessibleDiffViewer=void 0;const L=(0,S.registerIcon)("diff-review-insert",_.Codicon.add,(0,h.localize)(84,"Icon for 'Insert' in accessible diff viewer.")),D=(0,S.registerIcon)("diff-review-remove",_.Codicon.remove,(0,h.localize)(85,"Icon for 'Remove' in accessible diff viewer.")),T=(0,S.registerIcon)("diff-review-close",_.Codicon.close,(0,h.localize)(86,"Icon for 'Close' in accessible diff viewer."));let M=class extends b.Disposable{static{this._ttPolicy=(0,k.createTrustedTypesPolicy)("diffReview",{createHTML:j=>j})}constructor(j,Y,G,K,R,J,ie,ue,he){super(),this._parentNode=j,this._visible=Y,this._setVisible=G,this._canClose=K,this._width=R,this._height=J,this._diffs=ie,this._models=ue,this._instantiationService=he,this._state=(0,p.derivedWithStore)(this,(pe,ae)=>{const ee=this._visible.read(pe);if(this._parentNode.style.visibility=ee?"visible":"hidden",!ee)return null;const de=ae.add(this._instantiationService.createInstance(A,this._diffs,this._models,this._setVisible,this._canClose)),ge=ae.add(this._instantiationService.createInstance(H,this._parentNode,de,this._width,this._height,this._models));return{model:de,view:ge}}).recomputeInitiallyAndOnChange(this._store)}next(){(0,p.transaction)(j=>{const Y=this._visible.get();this._setVisible(!0,j),Y&&this._state.get().model.nextGroup(j)})}prev(){(0,p.transaction)(j=>{this._setVisible(!0,j),this._state.get().model.previousGroup(j)})}close(){(0,p.transaction)(j=>{this._setVisible(!1,j)})}};e.AccessibleDiffViewer=M,e.AccessibleDiffViewer=M=ke([ce(8,w.IInstantiationService)],M);let A=class extends b.Disposable{constructor(j,Y,G,K,R){super(),this._diffs=j,this._models=Y,this._setVisible=G,this.canClose=K,this._accessibilitySignalService=R,this._groups=(0,p.observableValue)(this,[]),this._currentGroupIdx=(0,p.observableValue)(this,0),this._currentElementIdx=(0,p.observableValue)(this,0),this.groups=this._groups,this.currentGroup=this._currentGroupIdx.map((J,ie)=>this._groups.read(ie)[J]),this.currentGroupIndex=this._currentGroupIdx,this.currentElement=this._currentElementIdx.map((J,ie)=>this.currentGroup.read(ie)?.lines[J]),this._register((0,p.autorun)(J=>{const ie=this._diffs.read(J);if(!ie){this._groups.set([],void 0);return}const ue=N(ie,this._models.getOriginalModel().getLineCount(),this._models.getModifiedModel().getLineCount());(0,p.transaction)(he=>{const pe=this._models.getModifiedPosition();if(pe){const ae=ue.findIndex(ee=>pe?.lineNumber{const ie=this.currentElement.read(J);ie?.type===O.Deleted?this._accessibilitySignalService.playSignal(v.AccessibilitySignal.diffLineDeleted,{source:"accessibleDiffViewer.currentElementChanged"}):ie?.type===O.Added&&this._accessibilitySignalService.playSignal(v.AccessibilitySignal.diffLineInserted,{source:"accessibleDiffViewer.currentElementChanged"})})),this._register((0,p.autorun)(J=>{const ie=this.currentElement.read(J);if(ie&&ie.type!==O.Header){const ue=ie.modifiedLineNumber??ie.diff.modified.startLineNumber;this._models.modifiedSetSelection(l.Range.fromPositions(new c.Position(ue,1)))}}))}_goToGroupDelta(j,Y){const G=this.groups.get();!G||G.length<=1||(0,p.subtransaction)(Y,K=>{this._currentGroupIdx.set(g.OffsetRange.ofLength(G.length).clipCyclic(this._currentGroupIdx.get()+j),K),this._currentElementIdx.set(0,K)})}nextGroup(j){this._goToGroupDelta(1,j)}previousGroup(j){this._goToGroupDelta(-1,j)}_goToLineDelta(j){const Y=this.currentGroup.get();!Y||Y.lines.length<=1||(0,p.transaction)(G=>{this._currentElementIdx.set(g.OffsetRange.ofLength(Y.lines.length).clip(this._currentElementIdx.get()+j),G)})}goToNextLine(){this._goToLineDelta(1)}goToPreviousLine(){this._goToLineDelta(-1)}goToLine(j){const Y=this.currentGroup.get();if(!Y)return;const G=Y.lines.indexOf(j);G!==-1&&(0,p.transaction)(K=>{this._currentElementIdx.set(G,K)})}revealCurrentElementInEditor(){if(!this.canClose.get())return;this._setVisible(!1,void 0);const j=this.currentElement.get();j&&(j.type===O.Deleted?this._models.originalReveal(l.Range.fromPositions(new c.Position(j.originalLineNumber,1))):this._models.modifiedReveal(j.type!==O.Header?l.Range.fromPositions(new c.Position(j.modifiedLineNumber,1)):void 0))}close(){this.canClose.get()&&(this._setVisible(!1,void 0),this._models.modifiedFocus())}};A=ke([ce(4,v.IAccessibilitySignalService)],A);const P=3;function N(U,j,Y){const G=[];for(const K of(0,m.groupAdjacentBy)(U,(R,J)=>J.modified.startLineNumber-R.modified.endLineNumberExclusive<2*P)){const R=[];R.push(new x);const J=new s.LineRange(Math.max(1,K[0].original.startLineNumber-P),Math.min(K[K.length-1].original.endLineNumberExclusive+P,j+1)),ie=new s.LineRange(Math.max(1,K[0].modified.startLineNumber-P),Math.min(K[K.length-1].modified.endLineNumberExclusive+P,Y+1));(0,m.forEachAdjacent)(K,(pe,ae)=>{const ee=new s.LineRange(pe?pe.original.endLineNumberExclusive:J.startLineNumber,ae?ae.original.startLineNumber:J.endLineNumberExclusive),de=new s.LineRange(pe?pe.modified.endLineNumberExclusive:ie.startLineNumber,ae?ae.modified.startLineNumber:ie.endLineNumberExclusive);ee.forEach(ge=>{R.push(new q(ge,de.startLineNumber+(ge-ee.startLineNumber)))}),ae&&(ae.original.forEach(ge=>{R.push(new W(ae,ge))}),ae.modified.forEach(ge=>{R.push(new V(ae,ge))}))});const ue=K[0].modified.join(K[K.length-1].modified),he=K[0].original.join(K[K.length-1].original);G.push(new F(new a.LineRangeMapping(ue,he),R))}return G}var O;(function(U){U[U.Header=0]="Header",U[U.Unchanged=1]="Unchanged",U[U.Deleted=2]="Deleted",U[U.Added=3]="Added"})(O||(O={}));class F{constructor(j,Y){this.range=j,this.lines=Y}}class x{constructor(){this.type=O.Header}}class W{constructor(j,Y){this.diff=j,this.originalLineNumber=Y,this.type=O.Deleted,this.modifiedLineNumber=void 0}}class V{constructor(j,Y){this.diff=j,this.modifiedLineNumber=Y,this.type=O.Added,this.originalLineNumber=void 0}}class q{constructor(j,Y){this.originalLineNumber=j,this.modifiedLineNumber=Y,this.type=O.Unchanged}}let H=class extends b.Disposable{constructor(j,Y,G,K,R,J){super(),this._element=j,this._model=Y,this._width=G,this._height=K,this._models=R,this._languageService=J,this.domNode=this._element,this.domNode.className="monaco-component diff-review monaco-editor-background";const ie=document.createElement("div");ie.className="diff-review-actions",this._actionBar=this._register(new I.ActionBar(ie)),this._register((0,p.autorun)(ue=>{this._actionBar.clear(),this._model.canClose.read(ue)&&this._actionBar.push(new y.Action("diffreview.close",(0,h.localize)(87,"Close"),"close-diff-review "+n.ThemeIcon.asClassName(T),!0,async()=>Y.close()),{label:!1,icon:!0})})),this._content=document.createElement("div"),this._content.className="diff-review-content",this._content.setAttribute("role","code"),this._scrollbar=this._register(new E.DomScrollableElement(this._content,{})),(0,d.reset)(this.domNode,this._scrollbar.getDomNode(),ie),this._register((0,p.autorun)(ue=>{this._height.read(ue),this._width.read(ue),this._scrollbar.scanDomNode()})),this._register((0,b.toDisposable)(()=>{(0,d.reset)(this.domNode)})),this._register((0,t.applyStyle)(this.domNode,{width:this._width,height:this._height})),this._register((0,t.applyStyle)(this._content,{width:this._width,height:this._height})),this._register((0,p.autorunWithStore)((ue,he)=>{this._model.currentGroup.read(ue),this._render(he)})),this._register((0,d.addStandardDisposableListener)(this.domNode,"keydown",ue=>{(ue.equals(18)||ue.equals(2066)||ue.equals(530))&&(ue.preventDefault(),this._model.goToNextLine()),(ue.equals(16)||ue.equals(2064)||ue.equals(528))&&(ue.preventDefault(),this._model.goToPreviousLine()),(ue.equals(9)||ue.equals(2057)||ue.equals(521)||ue.equals(1033))&&(ue.preventDefault(),this._model.close()),(ue.equals(10)||ue.equals(3))&&(ue.preventDefault(),this._model.revealCurrentElementInEditor())}))}_render(j){const Y=this._models.getOriginalOptions(),G=this._models.getModifiedOptions(),K=document.createElement("div");K.className="diff-review-table",K.setAttribute("role","list"),K.setAttribute("aria-label",(0,h.localize)(88,"Accessible Diff Viewer. Use arrow up and down to navigate.")),(0,o.applyFontInfo)(K,G.get(50)),(0,d.reset)(this._content,K);const R=this._models.getOriginalModel(),J=this._models.getModifiedModel();if(!R||!J)return;const ie=R.getOptions(),ue=J.getOptions(),he=G.get(67),pe=this._model.currentGroup.get();for(const ae of pe?.lines||[]){if(!pe)break;let ee;if(ae.type===O.Header){const ge=document.createElement("div");ge.className="diff-review-row",ge.setAttribute("role","listitem");const X=pe.range,B=this._model.currentGroupIndex.get(),$=this._model.groups.get().length,Q=le=>le===0?(0,h.localize)(89,"no lines changed"):le===1?(0,h.localize)(90,"1 line changed"):(0,h.localize)(91,"{0} lines changed",le),Z=Q(X.original.length),te=Q(X.modified.length);ge.setAttribute("aria-label",(0,h.localize)(92,"Difference {0} of {1}: original line {2}, {3}, modified line {4}, {5}",B+1,$,X.original.startLineNumber,Z,X.modified.startLineNumber,te));const re=document.createElement("div");re.className="diff-review-cell diff-review-summary",re.appendChild(document.createTextNode(`${B+1}/${$}: @@ -${X.original.startLineNumber},${X.original.length} +${X.modified.startLineNumber},${X.modified.length} @@`)),ge.appendChild(re),ee=ge}else ee=this._createRow(ae,he,this._width.get(),Y,R,ie,G,J,ue);K.appendChild(ee);const de=(0,p.derived)(ge=>this._model.currentElement.read(ge)===ae);j.add((0,p.autorun)(ge=>{const X=de.read(ge);ee.tabIndex=X?0:-1,X&&ee.focus()})),j.add((0,d.addDisposableListener)(ee,"focus",()=>{this._model.goToLine(ae)}))}this._scrollbar.scanDomNode()}_createRow(j,Y,G,K,R,J,ie,ue,he){const pe=K.get(146),ae=pe.glyphMarginWidth+pe.lineNumbersWidth,ee=ie.get(146),de=10+ee.glyphMarginWidth+ee.lineNumbersWidth;let ge="diff-review-row",X="";const B="diff-review-spacer";let $=null;switch(j.type){case O.Added:ge="diff-review-row line-insert",X=" char-insert",$=L;break;case O.Deleted:ge="diff-review-row line-delete",X=" char-delete",$=D;break}const Q=document.createElement("div");Q.style.minWidth=G+"px",Q.className=ge,Q.setAttribute("role","listitem"),Q.ariaLevel="";const Z=document.createElement("div");Z.className="diff-review-cell",Z.style.height=`${Y}px`,Q.appendChild(Z);const te=document.createElement("span");te.style.width=ae+"px",te.style.minWidth=ae+"px",te.className="diff-review-line-number"+X,j.originalLineNumber!==void 0?te.appendChild(document.createTextNode(String(j.originalLineNumber))):te.innerText="\xA0",Z.appendChild(te);const re=document.createElement("span");re.style.width=de+"px",re.style.minWidth=de+"px",re.style.paddingRight="10px",re.className="diff-review-line-number"+X,j.modifiedLineNumber!==void 0?re.appendChild(document.createTextNode(String(j.modifiedLineNumber))):re.innerText="\xA0",Z.appendChild(re);const le=document.createElement("span");if(le.className=B,$){const ye=document.createElement("span");ye.className=n.ThemeIcon.asClassName($),ye.innerText="\xA0\xA0",le.appendChild(ye)}else le.innerText="\xA0\xA0";Z.appendChild(le);let me;if(j.modifiedLineNumber!==void 0){let ye=this._getLineHtml(ue,ie,he.tabSize,j.modifiedLineNumber,this._languageService.languageIdCodec);M._ttPolicy&&(ye=M._ttPolicy.createHTML(ye)),Z.insertAdjacentHTML("beforeend",ye),me=ue.getLineContent(j.modifiedLineNumber)}else{let ye=this._getLineHtml(R,K,J.tabSize,j.originalLineNumber,this._languageService.languageIdCodec);M._ttPolicy&&(ye=M._ttPolicy.createHTML(ye)),Z.insertAdjacentHTML("beforeend",ye),me=R.getLineContent(j.originalLineNumber)}me.length===0&&(me=(0,h.localize)(93,"blank"));let Ce="";switch(j.type){case O.Unchanged:j.originalLineNumber===j.modifiedLineNumber?Ce=(0,h.localize)(94,"{0} unchanged line {1}",me,j.originalLineNumber):Ce=(0,h.localize)(95,"{0} original line {1} modified line {2}",me,j.originalLineNumber,j.modifiedLineNumber);break;case O.Added:Ce=(0,h.localize)(96,"+ {0} modified line {1}",me,j.modifiedLineNumber);break;case O.Deleted:Ce=(0,h.localize)(97,"- {0} original line {1}",me,j.originalLineNumber);break}return Q.setAttribute("aria-label",Ce),Q}_getLineHtml(j,Y,G,K,R){const J=j.getLineContent(K),ie=Y.get(50),ue=u.LineTokens.createEmpty(J,R),he=f.ViewLineRenderingData.isBasicASCII(J,j.mightContainNonBasicASCII()),pe=f.ViewLineRenderingData.containsRTL(J,he,j.mightContainRTL());return(0,C.renderViewLine2)(new C.RenderLineInput(ie.isMonospace&&!Y.get(33),ie.canUseHalfwidthRightwardsArrow,J,!1,he,pe,0,ue,[],G,0,ie.spaceWidth,ie.middotWidth,ie.wsmiddotWidth,Y.get(118),Y.get(100),Y.get(95),Y.get(51)!==i.EditorFontLigatures.OFF,null)).html}};H=ke([ce(5,r.ILanguageService)],H);class z{constructor(j){this.editors=j}getOriginalModel(){return this.editors.original.getModel()}getOriginalOptions(){return this.editors.original.getOptions()}originalReveal(j){this.editors.original.revealRange(j),this.editors.original.setSelection(j),this.editors.original.focus()}getModifiedModel(){return this.editors.modified.getModel()}getModifiedOptions(){return this.editors.modified.getOptions()}modifiedReveal(j){j&&(this.editors.modified.revealRange(j),this.editors.modified.setSelection(j)),this.editors.modified.focus()}modifiedSetSelection(j){this.editors.modified.setSelection(j)}modifiedFocus(){this.editors.modified.focus()}getModifiedPosition(){return this.editors.modified.getPosition()??void 0}}e.AccessibleDiffViewerModelFromEditors=z}),define(ne[763],se([1,0,253,5,172,85,26,33,6,2,30,3,32,71,227]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ColorPickerWidget=e.InsertButton=e.ColorPickerBody=e.ColorPickerHeader=void 0;const i=k.$;class s extends b.Disposable{constructor(v,w,S,L=!1){super(),this.model=w,this.showingStandaloneColorPicker=L,this._closeButton=null,this._domNode=i(".colorpicker-header"),k.append(v,this._domNode),this._pickedColorNode=k.append(this._domNode,i(".picked-color")),k.append(this._pickedColorNode,i("span.codicon.codicon-color-mode")),this._pickedColorPresentation=k.append(this._pickedColorNode,document.createElement("span")),this._pickedColorPresentation.classList.add("picked-color-presentation");const D=(0,n.localize)(796,"Click to toggle color options (rgb/hsl/hex)");this._pickedColorNode.setAttribute("title",D),this._originalColorNode=k.append(this._domNode,i(".original-color")),this._originalColorNode.style.backgroundColor=m.Color.Format.CSS.format(this.model.originalColor)||"",this.backgroundColor=S.getColorTheme().getColor(o.editorHoverBackground)||m.Color.white,this._register(S.onDidColorThemeChange(T=>{this.backgroundColor=T.getColor(o.editorHoverBackground)||m.Color.white})),this._register(k.addDisposableListener(this._pickedColorNode,k.EventType.CLICK,()=>this.model.selectNextColorPresentation())),this._register(k.addDisposableListener(this._originalColorNode,k.EventType.CLICK,()=>{this.model.color=this.model.originalColor,this.model.flushColor()})),this._register(w.onDidChangeColor(this.onDidChangeColor,this)),this._register(w.onDidChangePresentation(this.onDidChangePresentation,this)),this._pickedColorNode.style.backgroundColor=m.Color.Format.CSS.format(w.color)||"",this._pickedColorNode.classList.toggle("light",w.color.rgba.a<.5?this.backgroundColor.isLighter():w.color.isLighter()),this.onDidChangeColor(this.model.color),this.showingStandaloneColorPicker&&(this._domNode.classList.add("standalone-colorpicker"),this._closeButton=this._register(new g(this._domNode)))}get closeButton(){return this._closeButton}get pickedColorNode(){return this._pickedColorNode}get originalColorNode(){return this._originalColorNode}onDidChangeColor(v){this._pickedColorNode.style.backgroundColor=m.Color.Format.CSS.format(v)||"",this._pickedColorNode.classList.toggle("light",v.rgba.a<.5?this.backgroundColor.isLighter():v.isLighter()),this.onDidChangePresentation()}onDidChangePresentation(){this._pickedColorPresentation.textContent=this.model.presentation?this.model.presentation.label:""}}e.ColorPickerHeader=s;class g extends b.Disposable{constructor(v){super(),this._onClicked=this._register(new _.Emitter),this.onClicked=this._onClicked.event,this._button=document.createElement("div"),this._button.classList.add("close-button"),k.append(v,this._button);const w=document.createElement("div");w.classList.add("close-button-inner-div"),k.append(this._button,w),k.append(w,i(".button"+p.ThemeIcon.asCSSSelector((0,t.registerIcon)("color-picker-close",y.Codicon.close,(0,n.localize)(797,"Icon to close the color picker"))))).classList.add("close-icon"),this._register(k.addDisposableListener(this._button,k.EventType.CLICK,()=>{this._onClicked.fire()}))}}class c extends b.Disposable{constructor(v,w,S,L=!1){super(),this.model=w,this.pixelRatio=S,this._insertButton=null,this._domNode=i(".colorpicker-body"),k.append(v,this._domNode),this._saturationBox=new l(this._domNode,this.model,this.pixelRatio),this._register(this._saturationBox),this._register(this._saturationBox.onDidChange(this.onDidSaturationValueChange,this)),this._register(this._saturationBox.onColorFlushed(this.flushColor,this)),this._opacityStrip=new r(this._domNode,this.model,L),this._register(this._opacityStrip),this._register(this._opacityStrip.onDidChange(this.onDidOpacityChange,this)),this._register(this._opacityStrip.onColorFlushed(this.flushColor,this)),this._hueStrip=new u(this._domNode,this.model,L),this._register(this._hueStrip),this._register(this._hueStrip.onDidChange(this.onDidHueChange,this)),this._register(this._hueStrip.onColorFlushed(this.flushColor,this)),L&&(this._insertButton=this._register(new C(this._domNode)),this._domNode.classList.add("standalone-colorpicker"))}flushColor(){this.model.flushColor()}onDidSaturationValueChange({s:v,v:w}){const S=this.model.color.hsva;this.model.color=new m.Color(new m.HSVA(S.h,v,w,S.a))}onDidOpacityChange(v){const w=this.model.color.hsva;this.model.color=new m.Color(new m.HSVA(w.h,w.s,w.v,v))}onDidHueChange(v){const w=this.model.color.hsva,S=(1-v)*360;this.model.color=new m.Color(new m.HSVA(S===360?0:S,w.s,w.v,w.a))}get domNode(){return this._domNode}get saturationBox(){return this._saturationBox}get enterButton(){return this._insertButton}layout(){this._saturationBox.layout(),this._opacityStrip.layout(),this._hueStrip.layout()}}e.ColorPickerBody=c;class l extends b.Disposable{constructor(v,w,S){super(),this.model=w,this.pixelRatio=S,this._onDidChange=new _.Emitter,this.onDidChange=this._onDidChange.event,this._onColorFlushed=new _.Emitter,this.onColorFlushed=this._onColorFlushed.event,this._domNode=i(".saturation-wrap"),k.append(v,this._domNode),this._canvas=document.createElement("canvas"),this._canvas.className="saturation-box",k.append(this._domNode,this._canvas),this.selection=i(".saturation-selection"),k.append(this._domNode,this.selection),this.layout(),this._register(k.addDisposableListener(this._domNode,k.EventType.POINTER_DOWN,L=>this.onPointerDown(L))),this._register(this.model.onDidChangeColor(this.onDidChangeColor,this)),this.monitor=null}get domNode(){return this._domNode}onPointerDown(v){if(!v.target||!(v.target instanceof Element))return;this.monitor=this._register(new I.GlobalPointerMoveMonitor);const w=k.getDomNodePagePosition(this._domNode);v.target!==this.selection&&this.onDidChangePosition(v.offsetX,v.offsetY),this.monitor.startMonitoring(v.target,v.pointerId,v.buttons,L=>this.onDidChangePosition(L.pageX-w.left,L.pageY-w.top),()=>null);const S=k.addDisposableListener(v.target.ownerDocument,k.EventType.POINTER_UP,()=>{this._onColorFlushed.fire(),S.dispose(),this.monitor&&(this.monitor.stopMonitoring(!0),this.monitor=null)},!0)}onDidChangePosition(v,w){const S=Math.max(0,Math.min(1,v/this.width)),L=Math.max(0,Math.min(1,1-w/this.height));this.paintSelection(S,L),this._onDidChange.fire({s:S,v:L})}layout(){this.width=this._domNode.offsetWidth,this.height=this._domNode.offsetHeight,this._canvas.width=this.width*this.pixelRatio,this._canvas.height=this.height*this.pixelRatio,this.paint();const v=this.model.color.hsva;this.paintSelection(v.s,v.v)}paint(){const v=this.model.color.hsva,w=new m.Color(new m.HSVA(v.h,1,1,1)),S=this._canvas.getContext("2d"),L=S.createLinearGradient(0,0,this._canvas.width,0);L.addColorStop(0,"rgba(255, 255, 255, 1)"),L.addColorStop(.5,"rgba(255, 255, 255, 0.5)"),L.addColorStop(1,"rgba(255, 255, 255, 0)");const D=S.createLinearGradient(0,0,0,this._canvas.height);D.addColorStop(0,"rgba(0, 0, 0, 0)"),D.addColorStop(1,"rgba(0, 0, 0, 1)"),S.rect(0,0,this._canvas.width,this._canvas.height),S.fillStyle=m.Color.Format.CSS.format(w),S.fill(),S.fillStyle=L,S.fill(),S.fillStyle=D,S.fill()}paintSelection(v,w){this.selection.style.left=`${v*this.width}px`,this.selection.style.top=`${this.height-w*this.height}px`}onDidChangeColor(v){if(this.monitor&&this.monitor.isMonitoring())return;this.paint();const w=v.hsva;this.paintSelection(w.s,w.v)}}class a extends b.Disposable{constructor(v,w,S=!1){super(),this.model=w,this._onDidChange=new _.Emitter,this.onDidChange=this._onDidChange.event,this._onColorFlushed=new _.Emitter,this.onColorFlushed=this._onColorFlushed.event,S?(this.domNode=k.append(v,i(".standalone-strip")),this.overlay=k.append(this.domNode,i(".standalone-overlay"))):(this.domNode=k.append(v,i(".strip")),this.overlay=k.append(this.domNode,i(".overlay"))),this.slider=k.append(this.domNode,i(".slider")),this.slider.style.top="0px",this._register(k.addDisposableListener(this.domNode,k.EventType.POINTER_DOWN,L=>this.onPointerDown(L))),this._register(w.onDidChangeColor(this.onDidChangeColor,this)),this.layout()}layout(){this.height=this.domNode.offsetHeight-this.slider.offsetHeight;const v=this.getValue(this.model.color);this.updateSliderPosition(v)}onDidChangeColor(v){const w=this.getValue(v);this.updateSliderPosition(w)}onPointerDown(v){if(!v.target||!(v.target instanceof Element))return;const w=this._register(new I.GlobalPointerMoveMonitor),S=k.getDomNodePagePosition(this.domNode);this.domNode.classList.add("grabbing"),v.target!==this.slider&&this.onDidChangeTop(v.offsetY),w.startMonitoring(v.target,v.pointerId,v.buttons,D=>this.onDidChangeTop(D.pageY-S.top),()=>null);const L=k.addDisposableListener(v.target.ownerDocument,k.EventType.POINTER_UP,()=>{this._onColorFlushed.fire(),L.dispose(),w.stopMonitoring(!0),this.domNode.classList.remove("grabbing")},!0)}onDidChangeTop(v){const w=Math.max(0,Math.min(1,1-v/this.height));this.updateSliderPosition(w),this._onDidChange.fire(w)}updateSliderPosition(v){this.slider.style.top=`${(1-v)*this.height}px`}}class r extends a{constructor(v,w,S=!1){super(v,w,S),this.domNode.classList.add("opacity-strip"),this.onDidChangeColor(this.model.color)}onDidChangeColor(v){super.onDidChangeColor(v);const{r:w,g:S,b:L}=v.rgba,D=new m.Color(new m.RGBA(w,S,L,1)),T=new m.Color(new m.RGBA(w,S,L,0));this.overlay.style.background=`linear-gradient(to bottom, ${D} 0%, ${T} 100%)`}getValue(v){return v.hsva.a}}class u extends a{constructor(v,w,S=!1){super(v,w,S),this.domNode.classList.add("hue-strip")}getValue(v){return 1-v.hsva.h/360}}class C extends b.Disposable{constructor(v){super(),this._onClicked=this._register(new _.Emitter),this.onClicked=this._onClicked.event,this._button=k.append(v,document.createElement("button")),this._button.classList.add("insert-button"),this._button.textContent="Insert",this._register(k.addDisposableListener(this._button,k.EventType.CLICK,()=>{this._onClicked.fire()}))}get button(){return this._button}}e.InsertButton=C;class f extends E.Widget{constructor(v,w,S,L,D=!1){super(),this.model=w,this.pixelRatio=S,this._register(d.PixelRatio.getInstance(k.getWindow(v)).onDidChange(()=>this.layout())),this._domNode=i(".colorpicker-widget"),v.appendChild(this._domNode),this.header=this._register(new s(this._domNode,this.model,L,D)),this.body=this._register(new c(this._domNode,this.model,this.pixelRatio,D))}layout(){this.body.layout()}get domNode(){return this._domNode}}e.ColorPickerWidget=f}),define(ne[217],se([1,0,5,13,18,57,2,120,264,4,43,84,3,28,59,17,27,71,26,30,8,31,174,118,14,410,24]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MarkdownHoverParticipant=e.MarkdownHover=void 0,e.renderMarkdownHovers=O,e.labelForHoverVerbosityAction=x;const S=d.$,L=(0,c.registerIcon)("hover-increase-verbosity",l.Codicon.add,o.localize(1031,"Icon for increaseing hover verbosity.")),D=(0,c.registerIcon)("hover-decrease-verbosity",l.Codicon.remove,o.localize(1032,"Icon for decreasing hover verbosity."));class T{constructor(V,q,H,z,U,j=void 0){this.owner=V,this.range=q,this.contents=H,this.isBeforeContent=z,this.ordinal=U,this.source=j}isValidForHoverAnchor(V){return V.type===1&&this.range.startColumn<=V.range.startColumn&&this.range.endColumn>=V.range.endColumn}}e.MarkdownHover=T;class M{constructor(V,q,H){this.hover=V,this.hoverProvider=q,this.hoverPosition=H}supportsVerbosityAction(V){switch(V){case g.HoverVerbosityAction.Increase:return this.hover.canIncreaseVerbosity??!1;case g.HoverVerbosityAction.Decrease:return this.hover.canDecreaseVerbosity??!1}}}let A=class{constructor(V,q,H,z,U,j,Y,G){this._editor=V,this._languageService=q,this._openerService=H,this._configurationService=z,this._languageFeaturesService=U,this._keybindingService=j,this._hoverService=Y,this._commandService=G,this.hoverOrdinal=3}createLoadingMessage(V){return new T(this,V.range,[new E.MarkdownString().appendText(o.localize(1033,"Loading..."))],!1,2e3)}computeSync(V,q){if(!this._editor.hasModel()||V.type!==1)return[];const H=this._editor.getModel(),z=V.range.startLineNumber,U=H.getLineMaxColumn(z),j=[];let Y=1e3;const G=H.getLineLength(z),K=H.getLanguageIdAtPosition(V.range.startLineNumber,V.range.startColumn),R=this._editor.getOption(118),J=this._configurationService.getValue("editor.maxTokenizationLineLength",{overrideIdentifier:K});let ie=!1;R>=0&&G>R&&V.range.startColumn>=R&&(ie=!0,j.push(new T(this,V.range,[{value:o.localize(1034,"Rendering paused for long line for performance reasons. This can be configured via `editor.stopRenderingLineAfter`.")}],!1,Y++))),!ie&&typeof J=="number"&&G>=J&&j.push(new T(this,V.range,[{value:o.localize(1035,"Tokenization is skipped for long lines for performance reasons. This can be configured via `editor.maxTokenizationLineLength`.")}],!1,Y++));let ue=!1;for(const he of q){const pe=he.range.startLineNumber===z?he.range.startColumn:1,ae=he.range.endLineNumber===z?he.range.endColumn:U,ee=he.options.hoverMessage;if(!ee||(0,E.isEmptyMarkdownString)(ee))continue;he.options.beforeContentClassName&&(ue=!0);const de=new b.Range(V.range.startLineNumber,pe,V.range.startLineNumber,ae);j.push(new T(this,de,(0,k.asArray)(ee),ue,Y++))}return j}computeAsync(V,q,H){if(!this._editor.hasModel()||V.type!==1)return h.AsyncIterableObject.EMPTY;const z=this._editor.getModel(),U=this._languageFeaturesService.hoverProvider;return U.has(z)?this._getMarkdownHovers(U,z,V,H):h.AsyncIterableObject.EMPTY}_getMarkdownHovers(V,q,H,z){const U=H.range.getStartPosition();return(0,v.getHoverProviderResultsAsAsyncIterable)(V,q,U,z).filter(G=>!(0,E.isEmptyMarkdownString)(G.hover.contents)).map(G=>{const K=G.hover.range?b.Range.lift(G.hover.range):H.range,R=new M(G.hover,G.provider,U);return new T(this,K,G.hover.contents,!1,G.ordinal,R)})}renderHoverParts(V,q){return this._renderedHoverParts=new N(q,V.fragment,this,this._editor,this._languageService,this._openerService,this._commandService,this._keybindingService,this._hoverService,this._configurationService,V.onContentsChanged),this._renderedHoverParts}updateMarkdownHoverVerbosityLevel(V,q,H){return Promise.resolve(this._renderedHoverParts?.updateMarkdownHoverPartVerbosityLevel(V,q,H))}};e.MarkdownHoverParticipant=A,e.MarkdownHoverParticipant=A=ke([ce(1,p.ILanguageService),ce(2,i.IOpenerService),ce(3,t.IConfigurationService),ce(4,s.ILanguageFeaturesService),ce(5,u.IKeybindingService),ce(6,f.IHoverService),ce(7,w.ICommandService)],A);class P{constructor(V,q,H){this.hoverPart=V,this.hoverElement=q,this.disposables=H}dispose(){this.disposables.dispose()}}class N{constructor(V,q,H,z,U,j,Y,G,K,R,J){this._hoverParticipant=H,this._editor=z,this._languageService=U,this._openerService=j,this._commandService=Y,this._keybindingService=G,this._hoverService=K,this._configurationService=R,this._onFinishedRendering=J,this._ongoingHoverOperations=new Map,this._disposables=new y.DisposableStore,this.renderedHoverParts=this._renderHoverParts(V,q,this._onFinishedRendering),this._disposables.add((0,y.toDisposable)(()=>{this.renderedHoverParts.forEach(ie=>{ie.dispose()}),this._ongoingHoverOperations.forEach(ie=>{ie.tokenSource.dispose(!0)})}))}_renderHoverParts(V,q,H){return V.sort((0,k.compareBy)(z=>z.ordinal,k.numberComparator)),V.map(z=>{const U=this._renderHoverPart(z,H);return q.appendChild(U.hoverElement),U})}_renderHoverPart(V,q){const H=this._renderMarkdownHover(V,q),z=H.hoverElement,U=V.source,j=new y.DisposableStore;if(j.add(H),!U)return new P(V,z,j);const Y=U.supportsVerbosityAction(g.HoverVerbosityAction.Increase),G=U.supportsVerbosityAction(g.HoverVerbosityAction.Decrease);if(!Y&&!G)return new P(V,z,j);const K=S("div.verbosity-actions");return z.prepend(K),j.add(this._renderHoverExpansionAction(K,g.HoverVerbosityAction.Increase,Y)),j.add(this._renderHoverExpansionAction(K,g.HoverVerbosityAction.Decrease,G)),new P(V,z,j)}_renderMarkdownHover(V,q){return F(this._editor,V,this._languageService,this._openerService,q)}_renderHoverExpansionAction(V,q,H){const z=new y.DisposableStore,U=q===g.HoverVerbosityAction.Increase,j=d.append(V,S(a.ThemeIcon.asCSSSelector(U?L:D)));j.tabIndex=0;const Y=new f.WorkbenchHoverDelegate("mouse",!1,{target:V,position:{hoverPosition:0}},this._configurationService,this._hoverService);if(z.add(this._hoverService.setupManagedHover(Y,j,x(this._keybindingService,q))),!H)return j.classList.add("disabled"),z;j.classList.add("enabled");const G=()=>this._commandService.executeCommand(q===g.HoverVerbosityAction.Increase?_.INCREASE_HOVER_VERBOSITY_ACTION_ID:_.DECREASE_HOVER_VERBOSITY_ACTION_ID);return z.add(new C.ClickAction(j,G)),z.add(new C.KeyDownAction(j,G,[3,10])),z}async updateMarkdownHoverPartVerbosityLevel(V,q,H=!0){const z=this._editor.getModel();if(!z)return;const U=this._getRenderedHoverPartAtIndex(q),j=U?.hoverPart.source;if(!U||!j?.supportsVerbosityAction(V))return;const Y=await this._fetchHover(j,z,V);if(!Y)return;const G=new M(Y,j.hoverProvider,j.hoverPosition),K=U.hoverPart,R=new T(this._hoverParticipant,K.range,Y.contents,K.isBeforeContent,K.ordinal,G),J=this._renderHoverPart(R,this._onFinishedRendering);return this._replaceRenderedHoverPartAtIndex(q,J,R),H&&this._focusOnHoverPartWithIndex(q),{hoverPart:R,hoverElement:J.hoverElement}}async _fetchHover(V,q,H){let z=H===g.HoverVerbosityAction.Increase?1:-1;const U=V.hoverProvider,j=this._ongoingHoverOperations.get(U);j&&(j.tokenSource.cancel(),z+=j.verbosityDelta);const Y=new I.CancellationTokenSource;this._ongoingHoverOperations.set(U,{verbosityDelta:z,tokenSource:Y});const G={verbosityRequest:{verbosityDelta:z,previousHover:V.hover}};let K;try{K=await Promise.resolve(U.provideHover(q,V.hoverPosition,Y.token,G))}catch(R){(0,r.onUnexpectedExternalError)(R)}return Y.dispose(),this._ongoingHoverOperations.delete(U),K}_replaceRenderedHoverPartAtIndex(V,q,H){if(V>=this.renderedHoverParts.length||V<0)return;const z=this.renderedHoverParts[V],U=z.hoverElement,j=q.hoverElement,Y=Array.from(j.children);U.replaceChildren(...Y);const G=new P(H,U,q.disposables);U.focus(),z.dispose(),this.renderedHoverParts[V]=G}_focusOnHoverPartWithIndex(V){this.renderedHoverParts[V].hoverElement.focus()}_getRenderedHoverPartAtIndex(V){return this.renderedHoverParts[V]}dispose(){this._disposables.dispose()}}function O(W,V,q,H,z){V.sort((0,k.compareBy)(j=>j.ordinal,k.numberComparator));const U=[];for(const j of V)U.push(F(q,j,H,z,W.onContentsChanged));return new n.RenderedHoverParts(U)}function F(W,V,q,H,z){const U=new y.DisposableStore,j=S("div.hover-row"),Y=S("div.hover-row-contents");j.appendChild(Y);const G=V.contents;for(const R of G){if((0,E.isEmptyMarkdownString)(R))continue;const J=S("div.markdown-hover"),ie=d.append(J,S("div.hover-contents")),ue=U.add(new m.MarkdownRenderer({editor:W},q,H));U.add(ue.onDidRenderAsync(()=>{ie.className="hover-contents code-hover-contents",z()}));const he=U.add(ue.render(R));ie.appendChild(he.element),Y.appendChild(J)}return{hoverPart:V,hoverElement:j,dispose(){U.dispose()}}}function x(W,V){switch(V){case g.HoverVerbosityAction.Increase:{const q=W.lookupKeybinding(_.INCREASE_HOVER_VERBOSITY_ACTION_ID);return q?o.localize(1036,"Increase Hover Verbosity ({0})",q.getLabel()):o.localize(1037,"Increase Hover Verbosity")}case g.HoverVerbosityAction.Decrease:{const q=W.lookupKeybinding(_.DECREASE_HOVER_VERBOSITY_ACTION_ID);return q?o.localize(1038,"Decrease Hover Verbosity ({0})",q.getLabel()):o.localize(1039,"Decrease Hover Verbosity")}}}}),define(ne[764],se([1,0,5,46,86,26,6,2,11,19,37,43,120,270,3,12,59,32,71,30,54,63,526]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u){"use strict";var C;Object.defineProperty(e,"__esModule",{value:!0}),e.ParameterHintsWidget=void 0;const f=d.$,h=(0,l.registerIcon)("parameter-hints-next",E.Codicon.chevronDown,i.localize(1173,"Icon for show next parameter hint.")),v=(0,l.registerIcon)("parameter-hints-previous",E.Codicon.chevronUp,i.localize(1174,"Icon for show previous parameter hint."));let w=class extends m.Disposable{static{C=this}static{this.ID="editor.widget.parameterHintsWidget"}constructor(L,D,T,M,A,P){super(),this.editor=L,this.model=D,this.telemetryService=P,this.renderDisposeables=this._register(new m.DisposableStore),this.visible=!1,this.announcedLabel=null,this.allowEditorOverflow=!0,this.markdownRenderer=this._register(new o.MarkdownRenderer({editor:L},A,M)),this.keyVisible=t.Context.Visible.bindTo(T),this.keyMultipleSignatures=t.Context.MultipleSignatures.bindTo(T)}createParameterHintDOMNodes(){const L=f(".editor-widget.parameter-hints-widget"),D=d.append(L,f(".phwrapper"));D.tabIndex=-1;const T=d.append(D,f(".controls")),M=d.append(T,f(".button"+a.ThemeIcon.asCSSSelector(v))),A=d.append(T,f(".overloads")),P=d.append(T,f(".button"+a.ThemeIcon.asCSSSelector(h)));this._register(d.addDisposableListener(M,"click",V=>{d.EventHelper.stop(V),this.previous()})),this._register(d.addDisposableListener(P,"click",V=>{d.EventHelper.stop(V),this.next()}));const N=f(".body"),O=new I.DomScrollableElement(N,{alwaysConsumeMouseWheel:!0});this._register(O),D.appendChild(O.getDomNode());const F=d.append(N,f(".signature")),x=d.append(N,f(".docs"));L.style.userSelect="text",this.domNodes={element:L,signature:F,overloads:A,docs:x,scrollbar:O},this.editor.addContentWidget(this),this.hide(),this._register(this.editor.onDidChangeCursorSelection(V=>{this.visible&&this.editor.layoutContentWidget(this)}));const W=()=>{if(!this.domNodes)return;const V=this.editor.getOption(50),q=this.domNodes.element;q.style.fontSize=`${V.fontSize}px`,q.style.lineHeight=`${V.lineHeight/V.fontSize}`,q.style.setProperty("--vscode-parameterHintsWidget-editorFontFamily",V.fontFamily),q.style.setProperty("--vscode-parameterHintsWidget-editorFontFamilyDefault",p.EDITOR_FONT_DEFAULTS.fontFamily)};W(),this._register(y.Event.chain(this.editor.onDidChangeConfiguration.bind(this.editor),V=>V.filter(q=>q.hasChanged(50)))(W)),this._register(this.editor.onDidLayoutChange(V=>this.updateMaxHeight())),this.updateMaxHeight()}show(){this.visible||(this.domNodes||this.createParameterHintDOMNodes(),this.keyVisible.set(!0),this.visible=!0,setTimeout(()=>{this.domNodes?.element.classList.add("visible")},100),this.editor.layoutContentWidget(this))}hide(){this.renderDisposeables.clear(),this.visible&&(this.keyVisible.reset(),this.visible=!1,this.announcedLabel=null,this.domNodes?.element.classList.remove("visible"),this.editor.layoutContentWidget(this))}getPosition(){return this.visible?{position:this.editor.getPosition(),preference:[1,2]}:null}render(L){if(this.renderDisposeables.clear(),!this.domNodes)return;const D=L.signatures.length>1;this.domNodes.element.classList.toggle("multiple",D),this.keyMultipleSignatures.set(D),this.domNodes.signature.innerText="",this.domNodes.docs.innerText="";const T=L.signatures[L.activeSignature];if(!T)return;const M=d.append(this.domNodes.signature,f(".code")),A=T.parameters.length>0,P=T.activeParameter??L.activeParameter;if(A)this.renderParameters(M,T,P);else{const F=d.append(M,f("span"));F.textContent=T.label}const N=T.parameters[P];if(N?.documentation){const F=f("span.documentation");if(typeof N.documentation=="string")F.textContent=N.documentation;else{const x=this.renderMarkdownDocs(N.documentation);F.appendChild(x.element)}d.append(this.domNodes.docs,f("p",{},F))}if(T.documentation!==void 0)if(typeof T.documentation=="string")d.append(this.domNodes.docs,f("p",{},T.documentation));else{const F=this.renderMarkdownDocs(T.documentation);d.append(this.domNodes.docs,F.element)}const O=this.hasDocs(T,N);if(this.domNodes.signature.classList.toggle("has-docs",O),this.domNodes.docs.classList.toggle("empty",!O),this.domNodes.overloads.textContent=String(L.activeSignature+1).padStart(L.signatures.length.toString().length,"0")+"/"+L.signatures.length,N){let F="";const x=T.parameters[P];Array.isArray(x.label)?F=T.label.substring(x.label[0],x.label[1]):F=x.label,x.documentation&&(F+=typeof x.documentation=="string"?`, ${x.documentation}`:`, ${x.documentation.value}`),T.documentation&&(F+=typeof T.documentation=="string"?`, ${T.documentation}`:`, ${T.documentation.value}`),this.announcedLabel!==F&&(k.alert(i.localize(1175,"{0}, hint",F)),this.announcedLabel=F)}this.editor.layoutContentWidget(this),this.domNodes.scrollbar.scanDomNode()}renderMarkdownDocs(L){const D=new r.StopWatch,T=this.renderDisposeables.add(this.markdownRenderer.render(L,{asyncRenderCallback:()=>{this.domNodes?.scrollbar.scanDomNode()}}));T.element.classList.add("markdown-docs");const M=D.elapsed();return M>300&&this.telemetryService.publicLog2("parameterHints.parseMarkdown",{renderDuration:M}),T}hasDocs(L,D){return!!(D&&typeof D.documentation=="string"&&(0,b.assertIsDefined)(D.documentation).length>0||D&&typeof D.documentation=="object"&&(0,b.assertIsDefined)(D.documentation).value.length>0||L.documentation&&typeof L.documentation=="string"&&(0,b.assertIsDefined)(L.documentation).length>0||L.documentation&&typeof L.documentation=="object"&&(0,b.assertIsDefined)(L.documentation.value).length>0)}renderParameters(L,D,T){const[M,A]=this.getParameterLabelOffsets(D,T),P=document.createElement("span");P.textContent=D.label.substring(0,M);const N=document.createElement("span");N.textContent=D.label.substring(M,A),N.className="parameter active";const O=document.createElement("span");O.textContent=D.label.substring(A),d.append(L,P,N,O)}getParameterLabelOffsets(L,D){const T=L.parameters[D];if(T){if(Array.isArray(T.label))return T.label;if(T.label.length){const M=new RegExp(`(\\W|^)${(0,_.escapeRegExpCharacters)(T.label)}(?=\\W|$)`,"g");M.test(L.label);const A=M.lastIndex-T.label.length;return A>=0?[A,M.lastIndex]:[0,0]}else return[0,0]}else return[0,0]}next(){this.editor.focus(),this.model.next()}previous(){this.editor.focus(),this.model.previous()}getDomNode(){return this.domNodes||this.createParameterHintDOMNodes(),this.domNodes.element}getId(){return C.ID}updateMaxHeight(){if(!this.domNodes)return;const D=`${Math.max(this.editor.getLayoutInfo().height/4,250)}px`;this.domNodes.element.style.maxHeight=D;const T=this.domNodes.element.getElementsByClassName("phwrapper");T.length&&(T[0].style.maxHeight=D)}};e.ParameterHintsWidget=w,e.ParameterHintsWidget=w=C=ke([ce(2,s.IContextKeyService),ce(3,g.IOpenerService),ce(4,n.ILanguageService),ce(5,u.ITelemetryService)],w),(0,c.registerColor)("editorHoverWidget.highlightForeground",c.listHighlightForeground,i.localize(1176,"Foreground color of the active item in the parameter hint."))}),define(ne[765],se([1,0,98,2,15,20,27,17,683,270,3,12,7,764]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";var i;Object.defineProperty(e,"__esModule",{value:!0}),e.TriggerParameterHintsAction=e.ParameterHintsController=void 0;let s=class extends k.Disposable{static{i=this}static{this.ID="editor.controller.parameterHints"}static get(r){return r.getContribution(i.ID)}constructor(r,u,C){super(),this.editor=r,this.model=this._register(new _.ParameterHintsModel(r,C.signatureHelpProvider)),this._register(this.model.onChangedHints(f=>{f?(this.widget.value.show(),this.widget.value.render(f)):this.widget.rawValue?.hide()})),this.widget=new d.Lazy(()=>this._register(u.createInstance(t.ParameterHintsWidget,this.editor,this.model)))}cancel(){this.model.cancel()}previous(){this.widget.rawValue?.previous()}next(){this.widget.rawValue?.next()}trigger(r){this.model.trigger(r,0)}};e.ParameterHintsController=s,e.ParameterHintsController=s=i=ke([ce(1,o.IInstantiationService),ce(2,m.ILanguageFeaturesService)],s);class g extends I.EditorAction{constructor(){super({id:"editor.action.triggerParameterHints",label:p.localize(1172,"Trigger Parameter Hints"),alias:"Trigger Parameter Hints",precondition:E.EditorContextKeys.hasSignatureHelpProvider,kbOpts:{kbExpr:E.EditorContextKeys.editorTextFocus,primary:3082,weight:100}})}run(r,u){s.get(u)?.trigger({triggerKind:y.SignatureHelpTriggerKind.Invoke})}}e.TriggerParameterHintsAction=g,(0,I.registerEditorContribution)(s.ID,s,2),(0,I.registerEditorAction)(g);const c=175,l=I.EditorCommand.bindToContribution(s.get);(0,I.registerEditorCommand)(new l({id:"closeParameterHints",precondition:b.Context.Visible,handler:a=>a.cancel(),kbOpts:{weight:c,kbExpr:E.EditorContextKeys.focus,primary:9,secondary:[1033]}})),(0,I.registerEditorCommand)(new l({id:"showPrevParameterHint",precondition:n.ContextKeyExpr.and(b.Context.Visible,b.Context.MultipleSignatures),handler:a=>a.previous(),kbOpts:{weight:c,kbExpr:E.EditorContextKeys.focus,primary:16,secondary:[528],mac:{primary:16,secondary:[528,302]}}})),(0,I.registerEditorCommand)(new l({id:"showNextParameterHint",precondition:n.ContextKeyExpr.and(b.Context.Visible,b.Context.MultipleSignatures),handler:a=>a.next(),kbOpts:{weight:c,kbExpr:E.EditorContextKeys.focus,primary:18,secondary:[530],mac:{primary:18,secondary:[530,300]}}}))}),define(ne[766],se([1,0,5,87,41,2,120,7,702,71,30,534]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BannerController=void 0;const n=26;let o=class extends E.Disposable{constructor(s,g){super(),this._editor=s,this.instantiationService=g,this.banner=this._register(this.instantiationService.createInstance(t))}hide(){this._editor.setBanner(null,0),this.banner.clear()}show(s){this.banner.show({...s,onClose:()=>{this.hide(),s.onClose?.()}}),this._editor.setBanner(this.banner.element,n)}};e.BannerController=o,e.BannerController=o=ke([ce(1,m.IInstantiationService)],o);let t=class extends E.Disposable{constructor(s){super(),this.instantiationService=s,this.markdownRenderer=this.instantiationService.createInstance(y.MarkdownRenderer,{}),this.element=(0,d.$)("div.editor-banner"),this.element.tabIndex=0}getAriaLabel(s){if(s.ariaLabel)return s.ariaLabel;if(typeof s.message=="string")return s.message}getBannerMessage(s){if(typeof s=="string"){const g=(0,d.$)("span");return g.innerText=s,g}return this.markdownRenderer.render(s).element}clear(){(0,d.clearNode)(this.element)}show(s){(0,d.clearNode)(this.element);const g=this.getAriaLabel(s);g&&this.element.setAttribute("aria-label",g);const c=(0,d.append)(this.element,(0,d.$)("div.icon-container"));c.setAttribute("aria-hidden","true"),s.icon&&c.appendChild((0,d.$)(`div${p.ThemeIcon.asCSSSelector(s.icon)}`));const l=(0,d.append)(this.element,(0,d.$)("div.message-container"));if(l.setAttribute("aria-hidden","true"),l.appendChild(this.getBannerMessage(s.message)),this.messageActionsContainer=(0,d.append)(this.element,(0,d.$)("div.message-actions-container")),s.actions)for(const r of s.actions)this._register(this.instantiationService.createInstance(_.Link,this.messageActionsContainer,{...r,tabIndex:-1},{}));const a=(0,d.append)(this.element,(0,d.$)("div.action-container"));this.actionBar=this._register(new k.ActionBar(a)),this.actionBar.push(this._register(new I.Action("banner.close","Close Banner",p.ThemeIcon.asClassName(b.widgetClose),!0,()=>{typeof s.onClose=="function"&&s.onClose()})),{icon:!0,label:!1}),this.actionBar.setFocusable(!1)}};t=ke([ce(0,m.IInstantiationService)],t)}),define(ne[767],se([1,0,5,6,2,30,71]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UnthemedProductIconTheme=void 0,e.getIconsStyleSheet=m;function m(b){const p=new I.DisposableStore,n=p.add(new k.Emitter),o=(0,y.getIconRegistry)();return p.add(o.onDidChange(()=>n.fire())),b&&p.add(b.onDidProductIconThemeChange(()=>n.fire())),{dispose:()=>p.dispose(),onDidChange:n.event,getCSS(){const t=b?b.getProductIconTheme():new _,i={},s=[],g=[];for(const c of o.getIcons()){const l=t.getIcon(c);if(!l)continue;const a=l.font,r=`--vscode-icon-${c.id}-font-family`,u=`--vscode-icon-${c.id}-content`;a?(i[a.id]=a.definition,g.push(`${r}: ${(0,d.asCSSPropertyValue)(a.id)};`,`${u}: '${l.fontCharacter}';`),s.push(`.codicon-${c.id}:before { content: '${l.fontCharacter}'; font-family: ${(0,d.asCSSPropertyValue)(a.id)}; }`)):(g.push(`${u}: '${l.fontCharacter}'; ${r}: 'codicon';`),s.push(`.codicon-${c.id}:before { content: '${l.fontCharacter}'; }`))}for(const c in i){const l=i[c],a=l.weight?`font-weight: ${l.weight};`:"",r=l.style?`font-style: ${l.style};`:"",u=l.src.map(C=>`${(0,d.asCSSUrl)(C.location)} format('${C.format}')`).join(", ");s.push(`@font-face { src: ${u}; font-family: ${(0,d.asCSSPropertyValue)(c)};${a}${r} font-display: block; }`)}return s.push(`:root { ${g.join(" ")} }`),s.join(` `)}}}class _{getIcon(p){const n=(0,y.getIconRegistry)();let o=p.defaults;for(;E.ThemeIcon.isThemeIcon(o);){const t=n.getIcon(o.id);if(!t)return;o=t.defaults}return o}}e.UnthemedProductIconTheme=_}),define(ne[97],se([1,0]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ColorScheme=void 0,e.isHighContrast=k,e.isDark=I;var d;(function(E){E.DARK="dark",E.LIGHT="light",E.HIGH_CONTRAST_DARK="hcDark",E.HIGH_CONTRAST_LIGHT="hcLight"})(d||(e.ColorScheme=d={}));function k(E){return E===d.HIGH_CONTRAST_DARK||E===d.HIGH_CONTRAST_LIGHT}function I(E){return E===d.DARK||E===d.HIGH_CONTRAST_DARK}}),define(ne[281],se([1,0,64,39,16,548,164,150,136,97,37]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewLine=e.ViewLineOptions=void 0,e.getColumnOfNodeOffset=u;const n=function(){return I.isNative?!0:!(I.isLinux||d.isFirefox||d.isSafari)}();let o=!0;class t{constructor(f,h){this.themeType=h;const v=f.options,w=v.get(50);v.get(38)==="off"?this.renderWhitespace=v.get(100):this.renderWhitespace="none",this.renderControlCharacters=v.get(95),this.spaceWidth=w.spaceWidth,this.middotWidth=w.middotWidth,this.wsmiddotWidth=w.wsmiddotWidth,this.useMonospaceOptimizations=w.isMonospace&&!v.get(33),this.canUseHalfwidthRightwardsArrow=w.canUseHalfwidthRightwardsArrow,this.lineHeight=v.get(67),this.stopRenderingLineAfter=v.get(118),this.fontLigatures=v.get(51)}equals(f){return this.themeType===f.themeType&&this.renderWhitespace===f.renderWhitespace&&this.renderControlCharacters===f.renderControlCharacters&&this.spaceWidth===f.spaceWidth&&this.middotWidth===f.middotWidth&&this.wsmiddotWidth===f.wsmiddotWidth&&this.useMonospaceOptimizations===f.useMonospaceOptimizations&&this.canUseHalfwidthRightwardsArrow===f.canUseHalfwidthRightwardsArrow&&this.lineHeight===f.lineHeight&&this.stopRenderingLineAfter===f.stopRenderingLineAfter&&this.fontLigatures===f.fontLigatures}}e.ViewLineOptions=t;class i{static{this.CLASS_NAME="view-line"}constructor(f){this._options=f,this._isMaybeInvalid=!0,this._renderedViewLine=null}getDomNode(){return this._renderedViewLine&&this._renderedViewLine.domNode?this._renderedViewLine.domNode.domNode:null}setDomNode(f){if(this._renderedViewLine)this._renderedViewLine.domNode=(0,k.createFastDomNode)(f);else throw new Error("I have no rendered view line to set the dom node to...")}onContentChanged(){this._isMaybeInvalid=!0}onTokensChanged(){this._isMaybeInvalid=!0}onDecorationsChanged(){this._isMaybeInvalid=!0}onOptionsChanged(f){this._isMaybeInvalid=!0,this._options=f}onSelectionChanged(){return(0,b.isHighContrast)(this._options.themeType)||this._options.renderWhitespace==="selection"?(this._isMaybeInvalid=!0,!0):!1}renderLine(f,h,v,w,S){if(this._isMaybeInvalid===!1)return!1;this._isMaybeInvalid=!1;const L=w.getViewLineRenderingData(f),D=this._options,T=m.LineDecoration.filter(L.inlineDecorations,f,L.minColumn,L.maxColumn);let M=null;if((0,b.isHighContrast)(D.themeType)||this._options.renderWhitespace==="selection"){const O=w.selections;for(const F of O){if(F.endLineNumberf)continue;const x=F.startLineNumber===f?F.startColumn:L.minColumn,W=F.endLineNumber===f?F.endColumn:L.maxColumn;x');const P=(0,_.renderViewLine)(A,S);S.appendString("");let N=null;return o&&n&&L.isBasicASCII&&D.useMonospaceOptimizations&&P.containsForeignElements===0&&(N=new s(this._renderedViewLine?this._renderedViewLine.domNode:null,A,P.characterMapping)),N||(N=l(this._renderedViewLine?this._renderedViewLine.domNode:null,A,P.characterMapping,P.containsRTL,P.containsForeignElements)),this._renderedViewLine=N,!0}layoutLine(f,h,v){this._renderedViewLine&&this._renderedViewLine.domNode&&(this._renderedViewLine.domNode.setTop(h),this._renderedViewLine.domNode.setHeight(v))}getWidth(f){return this._renderedViewLine?this._renderedViewLine.getWidth(f):0}getWidthIsFast(){return this._renderedViewLine?this._renderedViewLine.getWidthIsFast():!0}needsMonospaceFontCheck(){return this._renderedViewLine?this._renderedViewLine instanceof s:!1}monospaceAssumptionsAreValid(){return this._renderedViewLine&&this._renderedViewLine instanceof s?this._renderedViewLine.monospaceAssumptionsAreValid():o}onMonospaceAssumptionsInvalidated(){this._renderedViewLine&&this._renderedViewLine instanceof s&&(this._renderedViewLine=this._renderedViewLine.toSlowRenderedLine())}getVisibleRangesForRange(f,h,v,w){if(!this._renderedViewLine)return null;h=Math.min(this._renderedViewLine.input.lineContent.length+1,Math.max(1,h)),v=Math.min(this._renderedViewLine.input.lineContent.length+1,Math.max(1,v));const S=this._renderedViewLine.input.stopRenderingLineAfter;if(S!==-1&&h>S+1&&v>S+1)return new y.VisibleRanges(!0,[new y.FloatHorizontalRange(this.getWidth(w),0)]);S!==-1&&h>S+1&&(h=S+1),S!==-1&&v>S+1&&(v=S+1);const L=this._renderedViewLine.getVisibleRangesForRange(f,h,v,w);return L&&L.length>0?new y.VisibleRanges(!1,L):null}getColumnOfNodeOffset(f,h){return this._renderedViewLine?this._renderedViewLine.getColumnOfNodeOffset(f,h):1}}e.ViewLine=i;class s{constructor(f,h,v){this._cachedWidth=-1,this.domNode=f,this.input=h;const w=Math.floor(h.lineContent.length/300);if(w>0){this._keyColumnPixelOffsetCache=new Float32Array(w);for(let S=0;S=2&&(console.warn("monospace assumptions have been violated, therefore disabling monospace optimizations!"),o=!1)}return o}toSlowRenderedLine(){return l(this.domNode,this.input,this._characterMapping,!1,0)}getVisibleRangesForRange(f,h,v,w){const S=this._getColumnPixelOffset(f,h,w),L=this._getColumnPixelOffset(f,v,w);return[new y.FloatHorizontalRange(S,L-S)]}_getColumnPixelOffset(f,h,v){if(h<=300){const M=this._characterMapping.getHorizontalOffset(h);return this._charWidth*M}const w=Math.floor((h-1)/300)-1,S=(w+1)*300+1;let L=-1;if(this._keyColumnPixelOffsetCache&&(L=this._keyColumnPixelOffsetCache[w],L===-1&&(L=this._actualReadPixelOffset(f,S,v),this._keyColumnPixelOffsetCache[w]=L)),L===-1){const M=this._characterMapping.getHorizontalOffset(h);return this._charWidth*M}const D=this._characterMapping.getHorizontalOffset(S),T=this._characterMapping.getHorizontalOffset(h);return L+this._charWidth*(T-D)}_getReadingTarget(f){return f.domNode.firstChild}_actualReadPixelOffset(f,h,v){if(!this.domNode)return-1;const w=this._characterMapping.getDomPosition(h),S=E.RangeUtil.readHorizontalRanges(this._getReadingTarget(this.domNode),w.partIndex,w.charIndex,w.partIndex,w.charIndex,v);return!S||S.length===0?-1:S[0].left}getColumnOfNodeOffset(f,h){return u(this._characterMapping,f,h)}}class g{constructor(f,h,v,w,S){if(this.domNode=f,this.input=h,this._characterMapping=v,this._isWhitespaceOnly=/^\s*$/.test(h.lineContent),this._containsForeignElements=S,this._cachedWidth=-1,this._pixelOffsetCache=null,!w||this._characterMapping.length===0){this._pixelOffsetCache=new Float32Array(Math.max(2,this._characterMapping.length+1));for(let L=0,D=this._characterMapping.length;L<=D;L++)this._pixelOffsetCache[L]=-1}}_getReadingTarget(f){return f.domNode.firstChild}getWidth(f){return this.domNode?(this._cachedWidth===-1&&(this._cachedWidth=this._getReadingTarget(this.domNode).offsetWidth,f?.markDidDomLayout()),this._cachedWidth):0}getWidthIsFast(){return this._cachedWidth!==-1}getVisibleRangesForRange(f,h,v,w){if(!this.domNode)return null;if(this._pixelOffsetCache!==null){const S=this._readPixelOffset(this.domNode,f,h,w);if(S===-1)return null;const L=this._readPixelOffset(this.domNode,f,v,w);return L===-1?null:[new y.FloatHorizontalRange(S,L-S)]}return this._readVisibleRangesForRange(this.domNode,f,h,v,w)}_readVisibleRangesForRange(f,h,v,w,S){if(v===w){const L=this._readPixelOffset(f,h,v,S);return L===-1?null:[new y.FloatHorizontalRange(L,0)]}else return this._readRawVisibleRangesForRange(f,v,w,S)}_readPixelOffset(f,h,v,w){if(this._characterMapping.length===0){if(this._containsForeignElements===0||this._containsForeignElements===2)return 0;if(this._containsForeignElements===1)return this.getWidth(w);const S=this._getReadingTarget(f);return S.firstChild?(w.markDidDomLayout(),S.firstChild.offsetWidth):0}if(this._pixelOffsetCache!==null){const S=this._pixelOffsetCache[v];if(S!==-1)return S;const L=this._actualReadPixelOffset(f,h,v,w);return this._pixelOffsetCache[v]=L,L}return this._actualReadPixelOffset(f,h,v,w)}_actualReadPixelOffset(f,h,v,w){if(this._characterMapping.length===0){const T=E.RangeUtil.readHorizontalRanges(this._getReadingTarget(f),0,0,0,0,w);return!T||T.length===0?-1:T[0].left}if(v===this._characterMapping.length&&this._isWhitespaceOnly&&this._containsForeignElements===0)return this.getWidth(w);const S=this._characterMapping.getDomPosition(v),L=E.RangeUtil.readHorizontalRanges(this._getReadingTarget(f),S.partIndex,S.charIndex,S.partIndex,S.charIndex,w);if(!L||L.length===0)return-1;const D=L[0].left;if(this.input.isBasicASCII){const T=this._characterMapping.getHorizontalOffset(v),M=Math.round(this.input.spaceWidth*T);if(Math.abs(M-D)<=1)return M}return D}_readRawVisibleRangesForRange(f,h,v,w){if(h===1&&v===this._characterMapping.length)return[new y.FloatHorizontalRange(0,this.getWidth(w))];const S=this._characterMapping.getDomPosition(h),L=this._characterMapping.getDomPosition(v);return E.RangeUtil.readHorizontalRanges(this._getReadingTarget(f),S.partIndex,S.charIndex,L.partIndex,L.charIndex,w)}getColumnOfNodeOffset(f,h){return u(this._characterMapping,f,h)}}class c extends g{_readVisibleRangesForRange(f,h,v,w,S){const L=super._readVisibleRangesForRange(f,h,v,w,S);if(!L||L.length===0||v===w||v===1&&w===this._characterMapping.length)return L;if(!this.input.containsRTL){const D=this._readPixelOffset(f,h,w,S);if(D!==-1){const T=L[L.length-1];T.left=4&&w[0]===3&&w[3]===8}static isStrictChildOfViewLines(w){return w.length>4&&w[0]===3&&w[3]===8}static isChildOfScrollableElement(w){return w.length>=2&&w[0]===3&&w[1]===6}static isChildOfMinimap(w){return w.length>=2&&w[0]===3&&w[1]===9}static isChildOfContentWidgets(w){return w.length>=4&&w[0]===3&&w[3]===1}static isChildOfOverflowGuard(w){return w.length>=1&&w[0]===3}static isChildOfOverflowingContentWidgets(w){return w.length>=1&&w[0]===2}static isChildOfOverlayWidgets(w){return w.length>=2&&w[0]===3&&w[1]===4}static isChildOfOverflowingOverlayWidgets(w){return w.length>=1&&w[0]===5}}class c{constructor(w,S,L){this.viewModel=w.viewModel;const D=w.configuration.options;this.layoutInfo=D.get(146),this.viewDomNode=S.viewDomNode,this.lineHeight=D.get(67),this.stickyTabStops=D.get(117),this.typicalHalfwidthCharacterWidth=D.get(50).typicalHalfwidthCharacterWidth,this.lastRenderData=L,this._context=w,this._viewHelper=S}getZoneAtCoord(w){return c.getZoneAtCoord(this._context,w)}static getZoneAtCoord(w,S){const L=w.viewLayout.getWhitespaceAtVerticalOffset(S);if(L){const D=L.verticalOffset+L.height/2,T=w.viewModel.getLineCount();let M=null,A,P=null;return L.afterLineNumber!==T&&(P=new E.Position(L.afterLineNumber+1,1)),L.afterLineNumber>0&&(M=new E.Position(L.afterLineNumber,w.viewModel.getLineMaxColumn(L.afterLineNumber))),P===null?A=M:M===null?A=P:S=w.layoutInfo.glyphMarginLeft,this.isInContentArea=!this.isInMarginArea,this.mouseColumn=Math.max(0,C._getMouseColumn(this.mouseContentHorizontalOffset,w.typicalHalfwidthCharacterWidth))}}class a extends l{get target(){return this._useHitTestTarget?this.hitTestResult.value.hitTarget:this._eventTarget}get targetPath(){return this._targetPathCacheElement!==this.target&&(this._targetPathCacheElement=this.target,this._targetPathCacheValue=k.PartFingerprints.collect(this.target,this._ctx.viewDomNode)),this._targetPathCacheValue}constructor(w,S,L,D,T){super(w,S,L,D),this.hitTestResult=new p.Lazy(()=>C.doHitTest(this._ctx,this)),this._targetPathCacheElement=null,this._targetPathCacheValue=new Uint8Array(0),this._ctx=w,this._eventTarget=T;const M=!!this._eventTarget;this._useHitTestTarget=!M}toString(){return`pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), relativePos(${this.relativePos.x},${this.relativePos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset} target: ${this.target?this.target.outerHTML:null}`}get wouldBenefitFromHitTestTargetSwitch(){return!this._useHitTestTarget&&this.hitTestResult.value.hitTarget!==null&&this.target!==this.hitTestResult.value.hitTarget}switchToHitTestTarget(){this._useHitTestTarget=!0}_getMouseColumn(w=null){return w&&w.columnM.contentLeft+M.width)continue;const A=w.getVerticalOffsetForLineNumber(M.position.lineNumber);if(A<=T&&T<=A+M.height)return S.fulfillContentText(M.position,null,{mightBeForeignElement:!1,injectedText:null})}}return null}static _hitTestViewZone(w,S){const L=w.getZoneAtCoord(S.mouseVerticalOffset);if(L){const D=S.isInContentArea?8:5;return S.fulfillViewZone(D,L.position,L)}return null}static _hitTestTextArea(w,S){return g.isTextArea(S.targetPath)?w.lastRenderData.lastTextareaPosition?S.fulfillContentText(w.lastRenderData.lastTextareaPosition,null,{mightBeForeignElement:!1,injectedText:null}):S.fulfillTextarea():null}static _hitTestMargin(w,S){if(S.isInMarginArea){const L=w.getFullLineRangeAtCoord(S.mouseVerticalOffset),D=L.range.getStartPosition();let T=Math.abs(S.relativePos.x);const M={isAfterLines:L.isAfterLines,glyphMarginLeft:w.layoutInfo.glyphMarginLeft,glyphMarginWidth:w.layoutInfo.glyphMarginWidth,lineNumbersWidth:w.layoutInfo.lineNumbersWidth,offsetX:T};if(T-=w.layoutInfo.glyphMarginLeft,T<=w.layoutInfo.glyphMarginWidth){const A=w.viewModel.coordinatesConverter.convertViewPositionToModelPosition(L.range.getStartPosition()),P=w.viewModel.glyphLanes.getLanesAtLine(A.lineNumber);return M.glyphMarginLane=P[Math.floor(T/w.lineHeight)],S.fulfillMargin(2,D,L.range,M)}return T-=w.layoutInfo.glyphMarginWidth,T<=w.layoutInfo.lineNumbersWidth?S.fulfillMargin(3,D,L.range,M):(T-=w.layoutInfo.lineNumbersWidth,S.fulfillMargin(4,D,L.range,M))}return null}static _hitTestViewLines(w,S){if(!g.isChildOfViewLines(S.targetPath))return null;if(w.isInTopPadding(S.mouseVerticalOffset))return S.fulfillContentEmpty(new E.Position(1,1),r);if(w.isAfterLines(S.mouseVerticalOffset)||w.isInBottomPadding(S.mouseVerticalOffset)){const D=w.viewModel.getLineCount(),T=w.viewModel.getLineMaxColumn(D);return S.fulfillContentEmpty(new E.Position(D,T),r)}if(g.isStrictChildOfViewLines(S.targetPath)){const D=w.getLineNumberAtVerticalOffset(S.mouseVerticalOffset);if(w.viewModel.getLineLength(D)===0){const M=w.getLineWidth(D),A=u(S.mouseContentHorizontalOffset-M);return S.fulfillContentEmpty(new E.Position(D,1),A)}const T=w.getLineWidth(D);if(S.mouseContentHorizontalOffset>=T){const M=u(S.mouseContentHorizontalOffset-T),A=new E.Position(D,w.viewModel.getLineMaxColumn(D));return S.fulfillContentEmpty(A,M)}}const L=S.hitTestResult.value;return L.type===1?C.createMouseTargetFromHitTestPosition(w,S,L.spanNode,L.position,L.injectedText):S.wouldBenefitFromHitTestTargetSwitch?(S.switchToHitTestTarget(),this._createMouseTarget(w,S)):S.fulfillUnknown()}static _hitTestMinimap(w,S){if(g.isChildOfMinimap(S.targetPath)){const L=w.getLineNumberAtVerticalOffset(S.mouseVerticalOffset),D=w.viewModel.getLineMaxColumn(L);return S.fulfillScrollbar(new E.Position(L,D))}return null}static _hitTestScrollbarSlider(w,S){if(g.isChildOfScrollableElement(S.targetPath)&&S.target&&S.target.nodeType===1){const L=S.target.className;if(L&&/\b(slider|scrollbar)\b/.test(L)){const D=w.getLineNumberAtVerticalOffset(S.mouseVerticalOffset),T=w.viewModel.getLineMaxColumn(D);return S.fulfillScrollbar(new E.Position(D,T))}}return null}static _hitTestScrollbar(w,S){if(g.isChildOfScrollableElement(S.targetPath)){const L=w.getLineNumberAtVerticalOffset(S.mouseVerticalOffset),D=w.viewModel.getLineMaxColumn(L);return S.fulfillScrollbar(new E.Position(L,D))}return null}getMouseColumn(w){const S=this._context.configuration.options,L=S.get(146),D=this._context.viewLayout.getCurrentScrollLeft()+w.x-L.contentLeft;return C._getMouseColumn(D,S.get(50).typicalHalfwidthCharacterWidth)}static _getMouseColumn(w,S){return w<0?1:Math.round(w/S)+1}static createMouseTargetFromHitTestPosition(w,S,L,D,T){const M=D.lineNumber,A=D.column,P=w.getLineWidth(M);if(S.mouseContentHorizontalOffset>P){const z=u(S.mouseContentHorizontalOffset-P);return S.fulfillContentEmpty(D,z)}const N=w.visibleRangeForPosition(M,A);if(!N)return S.fulfillUnknown(D);const O=N.left;if(Math.abs(S.mouseContentHorizontalOffset-O)<1)return S.fulfillContentText(D,null,{mightBeForeignElement:!!T,injectedText:T});const F=[];if(F.push({offset:N.left,column:A}),A>1){const z=w.visibleRangeForPosition(M,A-1);z&&F.push({offset:z.left,column:A-1})}const x=w.viewModel.getLineMaxColumn(M);if(Az.offset-U.offset);const W=S.pos.toClientCoordinates(_.getWindow(w.viewDomNode)),V=L.getBoundingClientRect(),q=V.left<=W.clientX&&W.clientX<=V.right;let H=null;for(let z=1;zT)){const A=Math.floor((D+T)/2);let P=S.pos.y+(A-S.mouseVerticalOffset);P<=S.editorPos.y&&(P=S.editorPos.y+1),P>=S.editorPos.y+S.editorPos.height&&(P=S.editorPos.y+S.editorPos.height-1);const N=new d.PageCoordinates(S.pos.x,P),O=this._actualDoHitTestWithCaretRangeFromPoint(w,N.toClientCoordinates(_.getWindow(w.viewDomNode)));if(O.type===1)return O}return this._actualDoHitTestWithCaretRangeFromPoint(w,S.pos.toClientCoordinates(_.getWindow(w.viewDomNode)))}static _actualDoHitTestWithCaretRangeFromPoint(w,S){const L=_.getShadowRoot(w.viewDomNode);let D;if(L?typeof L.caretRangeFromPoint>"u"?D=f(L,S.clientX,S.clientY):D=L.caretRangeFromPoint(S.clientX,S.clientY):D=w.viewDomNode.ownerDocument.caretRangeFromPoint(S.clientX,S.clientY),!D||!D.startContainer)return new n;const T=D.startContainer;if(T.nodeType===T.TEXT_NODE){const M=T.parentNode,A=M?M.parentNode:null,P=A?A.parentNode:null;return(P&&P.nodeType===P.ELEMENT_NODE?P.className:null)===I.ViewLine.CLASS_NAME?t.createFromDOMInfo(w,M,D.startOffset):new n(T.parentNode)}else if(T.nodeType===T.ELEMENT_NODE){const M=T.parentNode,A=M?M.parentNode:null;return(A&&A.nodeType===A.ELEMENT_NODE?A.className:null)===I.ViewLine.CLASS_NAME?t.createFromDOMInfo(w,T,T.textContent.length):new n(T)}return new n}static _doHitTestWithCaretPositionFromPoint(w,S){const L=w.viewDomNode.ownerDocument.caretPositionFromPoint(S.clientX,S.clientY);if(L.offsetNode.nodeType===L.offsetNode.TEXT_NODE){const D=L.offsetNode.parentNode,T=D?D.parentNode:null,M=T?T.parentNode:null;return(M&&M.nodeType===M.ELEMENT_NODE?M.className:null)===I.ViewLine.CLASS_NAME?t.createFromDOMInfo(w,L.offsetNode.parentNode,L.offset):new n(L.offsetNode.parentNode)}if(L.offsetNode.nodeType===L.offsetNode.ELEMENT_NODE){const D=L.offsetNode.parentNode,T=D&&D.nodeType===D.ELEMENT_NODE?D.className:null,M=D?D.parentNode:null,A=M&&M.nodeType===M.ELEMENT_NODE?M.className:null;if(T===I.ViewLine.CLASS_NAME){const P=L.offsetNode.childNodes[Math.min(L.offset,L.offsetNode.childNodes.length-1)];if(P)return t.createFromDOMInfo(w,P,0)}else if(A===I.ViewLine.CLASS_NAME)return t.createFromDOMInfo(w,L.offsetNode,0)}return new n(L.offsetNode)}static _snapToSoftTabBoundary(w,S){const L=S.getLineContent(w.lineNumber),{tabSize:D}=S.model.getOptions(),T=b.AtomicTabMoveOperations.atomicPosition(L,w.column-1,D,2);return T!==-1?new E.Position(w.lineNumber,T+1):w}static doHitTest(w,S){let L=new n;if(typeof w.viewDomNode.ownerDocument.caretRangeFromPoint=="function"?L=this._doHitTestWithCaretRangeFromPoint(w,S):w.viewDomNode.ownerDocument.caretPositionFromPoint&&(L=this._doHitTestWithCaretPositionFromPoint(w,S.pos.toClientCoordinates(_.getWindow(w.viewDomNode)))),L.type===1){const D=w.viewModel.getInjectedTextAt(L.position),T=w.viewModel.normalizePosition(L.position,2);(D||!T.equals(L.position))&&(L=new o(T,L.spanNode,D))}return L}}e.MouseTargetFactory=C;function f(v,w,S){const L=document.createRange();let D=v.elementFromPoint(w,S);if(D!==null){for(;D&&D.firstChild&&D.firstChild.nodeType!==D.firstChild.TEXT_NODE&&D.lastChild&&D.lastChild.firstChild;)D=D.lastChild;const T=D.getBoundingClientRect(),M=_.getWindow(D),A=M.getComputedStyle(D,null).getPropertyValue("font-style"),P=M.getComputedStyle(D,null).getPropertyValue("font-variant"),N=M.getComputedStyle(D,null).getPropertyValue("font-weight"),O=M.getComputedStyle(D,null).getPropertyValue("font-size"),F=M.getComputedStyle(D,null).getPropertyValue("line-height"),x=M.getComputedStyle(D,null).getPropertyValue("font-family"),W=`${A} ${P} ${N} ${O}/${F} ${x}`,V=D.innerText;let q=T.left,H=0,z;if(w>T.left+T.width)H=V.length;else{const U=h.getInstance();for(let j=0;jthis._createMouseTarget(h,v),h=>this._getMouseColumn(h))),this.lastMouseLeaveTime=-1,this._height=this._context.configuration.options.get(146).height;const C=new m.EditorMouseEventFactory(this.viewHelper.viewDomNode);this._register(C.onContextMenu(this.viewHelper.viewDomNode,h=>this._onContextMenu(h,!0))),this._register(C.onMouseMove(this.viewHelper.viewDomNode,h=>{this._onMouseMove(h),this._mouseLeaveMonitor||(this._mouseLeaveMonitor=d.addDisposableListener(this.viewHelper.viewDomNode.ownerDocument,"mousemove",v=>{this.viewHelper.viewDomNode.contains(v.target)||this._onMouseLeave(new m.EditorMouseEvent(v,!1,this.viewHelper.viewDomNode))}))})),this._register(C.onMouseUp(this.viewHelper.viewDomNode,h=>this._onMouseUp(h))),this._register(C.onMouseLeave(this.viewHelper.viewDomNode,h=>this._onMouseLeave(h)));let f=0;this._register(C.onPointerDown(this.viewHelper.viewDomNode,(h,v)=>{f=v})),this._register(d.addDisposableListener(this.viewHelper.viewDomNode,d.EventType.POINTER_UP,h=>{this._mouseDownOperation.onPointerUp()})),this._register(C.onMouseDown(this.viewHelper.viewDomNode,h=>this._onMouseDown(h,f))),this._setupMouseWheelZoomListener(),this._context.addEventHandler(this)}_setupMouseWheelZoomListener(){const a=o.MouseWheelClassifier.INSTANCE;let r=0,u=_.EditorZoom.getZoomLevel(),C=!1,f=0;const h=w=>{if(this.viewController.emitMouseWheel(w),!this._context.configuration.options.get(76))return;const S=new k.StandardWheelEvent(w);if(a.acceptStandardWheelEvent(S),a.isPhysicalMouseWheel()){if(v(w)){const L=_.EditorZoom.getZoomLevel(),D=S.deltaY>0?1:-1;_.EditorZoom.setZoomLevel(L+D),S.preventDefault(),S.stopPropagation()}}else Date.now()-r>50&&(u=_.EditorZoom.getZoomLevel(),C=v(w),f=0),r=Date.now(),f+=S.deltaY,C&&(_.EditorZoom.setZoomLevel(u+f/5),S.preventDefault(),S.stopPropagation())};this._register(d.addDisposableListener(this.viewHelper.viewDomNode,d.EventType.MOUSE_WHEEL,h,{capture:!0,passive:!1}));function v(w){return E.isMacintosh?(w.metaKey||w.ctrlKey)&&!w.shiftKey&&!w.altKey:w.ctrlKey&&!w.metaKey&&!w.shiftKey&&!w.altKey}}dispose(){this._context.removeEventHandler(this),this._mouseLeaveMonitor&&(this._mouseLeaveMonitor.dispose(),this._mouseLeaveMonitor=null),super.dispose()}onConfigurationChanged(a){if(a.hasChanged(146)){const r=this._context.configuration.options.get(146).height;this._height!==r&&(this._height=r,this._mouseDownOperation.onHeightChanged())}return!1}onCursorStateChanged(a){return this._mouseDownOperation.onCursorStateChanged(a),!1}onFocusChanged(a){return!1}getTargetAtClientPoint(a,r){const C=new m.ClientCoordinates(a,r).toPageCoordinates(d.getWindow(this.viewHelper.viewDomNode)),f=(0,m.createEditorPagePosition)(this.viewHelper.viewDomNode);if(C.yf.y+f.height||C.xf.x+f.width)return null;const h=(0,m.createCoordinatesRelativeToEditor)(this.viewHelper.viewDomNode,f,C);return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(),f,C,h,null)}_createMouseTarget(a,r){let u=a.target;if(!this.viewHelper.viewDomNode.contains(u)){const C=d.getShadowRoot(this.viewHelper.viewDomNode);C&&(u=C.elementsFromPoint(a.posx,a.posy).find(f=>this.viewHelper.viewDomNode.contains(f)))}return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(),a.editorPos,a.pos,a.relativePos,r?u:null)}_getMouseColumn(a){return this.mouseTargetFactory.getMouseColumn(a.relativePos)}_onContextMenu(a,r){this.viewController.emitContextMenu({event:a,target:this._createMouseTarget(a,r)})}_onMouseMove(a){this.mouseTargetFactory.mouseTargetIsWidget(a)||a.preventDefault(),!(this._mouseDownOperation.isActive()||a.timestamp{a.preventDefault(),this.viewHelper.focusTextArea()};if(L&&(C||h&&v))D(),this._mouseDownOperation.start(u.type,a,r);else if(f)a.preventDefault();else if(w){const T=u.detail;L&&this.viewHelper.shouldSuppressMouseDownOnViewZone(T.viewZoneId)&&(D(),this._mouseDownOperation.start(u.type,a,r),a.preventDefault())}else S&&this.viewHelper.shouldSuppressMouseDownOnWidget(u.detail)&&(D(),a.preventDefault());this.viewController.emitMouseDown({event:a,target:u})}}e.MouseHandler=t;class i extends I.Disposable{constructor(a,r,u,C,f,h){super(),this._context=a,this._viewController=r,this._viewHelper=u,this._mouseTargetFactory=C,this._createMouseTarget=f,this._getMouseColumn=h,this._mouseMoveMonitor=this._register(new m.GlobalEditorPointerMoveMonitor(this._viewHelper.viewDomNode)),this._topBottomDragScrolling=this._register(new s(this._context,this._viewHelper,this._mouseTargetFactory,(v,w,S)=>this._dispatchMouse(v,w,S))),this._mouseState=new c,this._currentSelection=new p.Selection(1,1,1,1),this._isActive=!1,this._lastMouseEvent=null}dispose(){super.dispose()}isActive(){return this._isActive}_onMouseDownThenMove(a){this._lastMouseEvent=a,this._mouseState.setModifiers(a);const r=this._findMousePosition(a,!1);r&&(this._mouseState.isDragAndDrop?this._viewController.emitMouseDrag({event:a,target:r}):r.type===13&&(r.outsidePosition==="above"||r.outsidePosition==="below")?this._topBottomDragScrolling.start(r,a):(this._topBottomDragScrolling.stop(),this._dispatchMouse(r,!0,1)))}start(a,r,u){this._lastMouseEvent=r,this._mouseState.setStartedOnLineNumbers(a===3),this._mouseState.setStartButtons(r),this._mouseState.setModifiers(r);const C=this._findMousePosition(r,!0);if(!C||!C.position)return;this._mouseState.trySetCount(r.detail,C.position),r.detail=this._mouseState.count;const f=this._context.configuration.options;if(!f.get(92)&&f.get(35)&&!f.get(22)&&!this._mouseState.altKey&&r.detail<2&&!this._isActive&&!this._currentSelection.isEmpty()&&C.type===6&&C.position&&this._currentSelection.containsPosition(C.position)){this._mouseState.isDragAndDrop=!0,this._isActive=!0,this._mouseMoveMonitor.startMonitoring(this._viewHelper.viewLinesDomNode,u,r.buttons,h=>this._onMouseDownThenMove(h),h=>{const v=this._findMousePosition(this._lastMouseEvent,!1);d.isKeyboardEvent(h)?this._viewController.emitMouseDropCanceled():this._viewController.emitMouseDrop({event:this._lastMouseEvent,target:v?this._createMouseTarget(this._lastMouseEvent,!0):null}),this._stop()});return}this._mouseState.isDragAndDrop=!1,this._dispatchMouse(C,r.shiftKey,1),this._isActive||(this._isActive=!0,this._mouseMoveMonitor.startMonitoring(this._viewHelper.viewLinesDomNode,u,r.buttons,h=>this._onMouseDownThenMove(h),()=>this._stop()))}_stop(){this._isActive=!1,this._topBottomDragScrolling.stop()}onHeightChanged(){this._mouseMoveMonitor.stopMonitoring()}onPointerUp(){this._mouseMoveMonitor.stopMonitoring()}onCursorStateChanged(a){this._currentSelection=a.selections[0]}_getPositionOutsideEditor(a){const r=a.editorPos,u=this._context.viewModel,C=this._context.viewLayout,f=this._getMouseColumn(a);if(a.posyr.y+r.height){const v=a.posy-r.y-r.height,w=C.getCurrentScrollTop()+a.relativePos.y,S=y.HitTestContext.getZoneAtCoord(this._context,w);if(S){const D=this._helpPositionJumpOverViewZone(S);if(D)return y.MouseTarget.createOutsideEditor(f,D,"below",v)}const L=C.getLineNumberAtVerticalOffset(w);return y.MouseTarget.createOutsideEditor(f,new b.Position(L,u.getLineMaxColumn(L)),"below",v)}const h=C.getLineNumberAtVerticalOffset(C.getCurrentScrollTop()+a.relativePos.y);if(a.posxr.x+r.width){const v=a.posx-r.x-r.width;return y.MouseTarget.createOutsideEditor(f,new b.Position(h,u.getLineMaxColumn(h)),"right",v)}return null}_findMousePosition(a,r){const u=this._getPositionOutsideEditor(a);if(u)return u;const C=this._createMouseTarget(a,r);if(!C.position)return null;if(C.type===8||C.type===5){const h=this._helpPositionJumpOverViewZone(C.detail);if(h)return y.MouseTarget.createViewZone(C.type,C.element,C.mouseColumn,h,C.detail)}return C}_helpPositionJumpOverViewZone(a){const r=new b.Position(this._currentSelection.selectionStartLineNumber,this._currentSelection.selectionStartColumn),u=a.positionBefore,C=a.positionAfter;return u&&C?u.isBefore(r)?u:C:null}_dispatchMouse(a,r,u){a.position&&this._viewController.dispatchMouse({position:a.position,mouseColumn:a.mouseColumn,startedOnLineNumbers:this._mouseState.startedOnLineNumbers,revealType:u,inSelectionMode:r,mouseDownCount:this._mouseState.count,altKey:this._mouseState.altKey,ctrlKey:this._mouseState.ctrlKey,metaKey:this._mouseState.metaKey,shiftKey:this._mouseState.shiftKey,leftButton:this._mouseState.leftButton,middleButton:this._mouseState.middleButton,onInjectedText:a.type===6&&a.detail.injectedText!==null})}}class s extends I.Disposable{constructor(a,r,u,C){super(),this._context=a,this._viewHelper=r,this._mouseTargetFactory=u,this._dispatchMouse=C,this._operation=null}dispose(){super.dispose(),this.stop()}start(a,r){this._operation?this._operation.setPosition(a,r):this._operation=new g(this._context,this._viewHelper,this._mouseTargetFactory,this._dispatchMouse,a,r)}stop(){this._operation&&(this._operation.dispose(),this._operation=null)}}class g extends I.Disposable{constructor(a,r,u,C,f,h){super(),this._context=a,this._viewHelper=r,this._mouseTargetFactory=u,this._dispatchMouse=C,this._position=f,this._mouseEvent=h,this._lastTime=Date.now(),this._animationFrameDisposable=d.scheduleAtNextAnimationFrame(d.getWindow(h.browserEvent),()=>this._execute())}dispose(){this._animationFrameDisposable.dispose(),super.dispose()}setPosition(a,r){this._position=a,this._mouseEvent=r}_tick(){const a=Date.now(),r=a-this._lastTime;return this._lastTime=a,r}_getScrollSpeed(){const a=this._context.configuration.options.get(67),r=this._context.configuration.options.get(146).height/a,u=this._position.outsideDistance/a;return u<=1.5?Math.max(30,r*(1+u)):u<=3?Math.max(60,r*(2+u)):Math.max(200,r*(7+u))}_execute(){const a=this._context.configuration.options.get(67),r=this._getScrollSpeed(),u=this._tick(),C=r*(u/1e3)*a,f=this._position.outsidePosition==="above"?-C:C;this._context.viewModel.viewLayout.deltaScrollNow(0,f),this._viewHelper.renderNow();const h=this._context.viewLayout.getLinesViewportData(),v=this._position.outsidePosition==="above"?h.startLineNumber:h.endLineNumber;let w;{const S=(0,m.createEditorPagePosition)(this._viewHelper.viewDomNode),L=this._context.configuration.options.get(146).horizontalScrollbarHeight,D=new m.PageCoordinates(this._mouseEvent.pos.x,S.y+S.height-L-.1),T=(0,m.createCoordinatesRelativeToEditor)(this._viewHelper.viewDomNode,S,D);w=this._mouseTargetFactory.createMouseTarget(this._viewHelper.getLastRenderData(),S,D,T,null)}(!w.position||w.position.lineNumber!==v)&&(this._position.outsidePosition==="above"?w=y.MouseTarget.createOutsideEditor(this._position.mouseColumn,new b.Position(v,1),"above",this._position.outsideDistance):w=y.MouseTarget.createOutsideEditor(this._position.mouseColumn,new b.Position(v,this._context.viewModel.getLineMaxColumn(v)),"below",this._position.outsideDistance)),this._dispatchMouse(w,!0,2),this._animationFrameDisposable=d.scheduleAtNextAnimationFrame(d.getWindow(w.element),()=>this._execute())}}class c{static{this.CLEAR_MOUSE_DOWN_COUNT_TIME=400}get altKey(){return this._altKey}get ctrlKey(){return this._ctrlKey}get metaKey(){return this._metaKey}get shiftKey(){return this._shiftKey}get leftButton(){return this._leftButton}get middleButton(){return this._middleButton}get startedOnLineNumbers(){return this._startedOnLineNumbers}constructor(){this._altKey=!1,this._ctrlKey=!1,this._metaKey=!1,this._shiftKey=!1,this._leftButton=!1,this._middleButton=!1,this._startedOnLineNumbers=!1,this._lastMouseDownPosition=null,this._lastMouseDownPositionEqualCount=0,this._lastMouseDownCount=0,this._lastSetMouseDownCountTime=0,this.isDragAndDrop=!1}get count(){return this._lastMouseDownCount}setModifiers(a){this._altKey=a.altKey,this._ctrlKey=a.ctrlKey,this._metaKey=a.metaKey,this._shiftKey=a.shiftKey}setStartButtons(a){this._leftButton=a.leftButton,this._middleButton=a.middleButton}setStartedOnLineNumbers(a){this._startedOnLineNumbers=a}trySetCount(a,r){const u=new Date().getTime();u-this._lastSetMouseDownCountTime>c.CLEAR_MOUSE_DOWN_COUNT_TIME&&(a=1),this._lastSetMouseDownCountTime=u,a>this._lastMouseDownCount+1&&(a=this._lastMouseDownCount+1),this._lastMouseDownPosition&&this._lastMouseDownPosition.equals(r)?this._lastMouseDownPositionEqualCount++:this._lastMouseDownPositionEqualCount=1,this._lastMouseDownPosition=r,this._lastMouseDownCount=Math.min(a,this._lastMouseDownPositionEqualCount)}}}),define(ne[769],se([1,0,248,5,69,52,2,16,768,212,185]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PointerHandler=e.PointerEventHandler=void 0;class n extends _.MouseHandler{constructor(s,g,c){super(s,g,c),this._register(I.Gesture.addTarget(this.viewHelper.linesContentDomNode)),this._register(k.addDisposableListener(this.viewHelper.linesContentDomNode,I.EventType.Tap,a=>this.onTap(a))),this._register(k.addDisposableListener(this.viewHelper.linesContentDomNode,I.EventType.Change,a=>this.onChange(a))),this._register(k.addDisposableListener(this.viewHelper.linesContentDomNode,I.EventType.Contextmenu,a=>this._onContextMenu(new p.EditorMouseEvent(a,!1,this.viewHelper.viewDomNode),!1))),this._lastPointerType="mouse",this._register(k.addDisposableListener(this.viewHelper.linesContentDomNode,"pointerdown",a=>{const r=a.pointerType;if(r==="mouse"){this._lastPointerType="mouse";return}else r==="touch"?this._lastPointerType="touch":this._lastPointerType="pen"}));const l=new p.EditorPointerEventFactory(this.viewHelper.viewDomNode);this._register(l.onPointerMove(this.viewHelper.viewDomNode,a=>this._onMouseMove(a))),this._register(l.onPointerUp(this.viewHelper.viewDomNode,a=>this._onMouseUp(a))),this._register(l.onPointerLeave(this.viewHelper.viewDomNode,a=>this._onMouseLeave(a))),this._register(l.onPointerDown(this.viewHelper.viewDomNode,(a,r)=>this._onMouseDown(a,r)))}onTap(s){!s.initialTarget||!this.viewHelper.linesContentDomNode.contains(s.initialTarget)||(s.preventDefault(),this.viewHelper.focusTextArea(),this._dispatchGesture(s,!1))}onChange(s){this._lastPointerType==="touch"&&this._context.viewModel.viewLayout.deltaScrollNow(-s.translationX,-s.translationY),this._lastPointerType==="pen"&&this._dispatchGesture(s,!0)}_dispatchGesture(s,g){const c=this._createMouseTarget(new p.EditorMouseEvent(s,!1,this.viewHelper.viewDomNode),!1);c.position&&this.viewController.dispatchMouse({position:c.position,mouseColumn:c.position.column,startedOnLineNumbers:!1,revealType:1,mouseDownCount:s.tapCount,inSelectionMode:g,altKey:!1,ctrlKey:!1,metaKey:!1,shiftKey:!1,leftButton:!1,middleButton:!1,onInjectedText:c.type===6&&c.detail.injectedText!==null})}_onMouseDown(s,g){s.browserEvent.pointerType!=="touch"&&super._onMouseDown(s,g)}}e.PointerEventHandler=n;class o extends _.MouseHandler{constructor(s,g,c){super(s,g,c),this._register(I.Gesture.addTarget(this.viewHelper.linesContentDomNode)),this._register(k.addDisposableListener(this.viewHelper.linesContentDomNode,I.EventType.Tap,l=>this.onTap(l))),this._register(k.addDisposableListener(this.viewHelper.linesContentDomNode,I.EventType.Change,l=>this.onChange(l))),this._register(k.addDisposableListener(this.viewHelper.linesContentDomNode,I.EventType.Contextmenu,l=>this._onContextMenu(new p.EditorMouseEvent(l,!1,this.viewHelper.viewDomNode),!1)))}onTap(s){s.preventDefault(),this.viewHelper.focusTextArea();const g=this._createMouseTarget(new p.EditorMouseEvent(s,!1,this.viewHelper.viewDomNode),!1);if(g.position){const c=document.createEvent("CustomEvent");c.initEvent(b.TextAreaSyntethicEvents.Tap,!1,!0),this.viewHelper.dispatchTextAreaEvent(c),this.viewController.moveTo(g.position,1)}}onChange(s){this._context.viewModel.viewLayout.deltaScrollNow(-s.translationX,-s.translationY)}}class t extends y.Disposable{constructor(s,g,c){super(),(m.isIOS||m.isAndroid&&m.isMobile)&&d.BrowserFeatures.pointerEvents?this.handler=this._register(new n(s,g,c)):E.mainWindow.TouchEvent?this.handler=this._register(new o(s,g,c)):this.handler=this._register(new _.MouseHandler(s,g,c))}getTargetAtClientPoint(s,g){return this.handler.getTargetAtClientPoint(s,g)}}e.PointerHandler=t}),define(ne[770],se([1,0,226,14,16,74,164,262,56,547,281,9,4,487]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewLines=void 0;class t{constructor(){this._currentVisibleRange=new o.Range(1,1,1,1)}getCurrentVisibleRange(){return this._currentVisibleRange}setCurrentVisibleRange(l){this._currentVisibleRange=l}}class i{constructor(l,a,r,u,C,f,h){this.minimalReveal=l,this.lineNumber=a,this.startColumn=r,this.endColumn=u,this.startScrollTop=C,this.stopScrollTop=f,this.scrollType=h,this.type="range",this.minLineNumber=a,this.maxLineNumber=a}}class s{constructor(l,a,r,u,C){this.minimalReveal=l,this.selections=a,this.startScrollTop=r,this.stopScrollTop=u,this.scrollType=C,this.type="selections";let f=a[0].startLineNumber,h=a[0].endLineNumber;for(let v=1,w=a.length;vnew p.ViewLine(this._viewLineOptions)}),this.domNode=this._visibleLines.domNode,_.PartFingerprints.write(this.domNode,8),this.domNode.setClassName(`view-lines ${d.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`),(0,E.applyFontInfo)(this.domNode,C),this._maxLineWidth=0,this._asyncUpdateLineWidths=new k.RunOnceScheduler(()=>{this._updateLineWidthsSlow()},200),this._asyncCheckMonospaceFontAssumptions=new k.RunOnceScheduler(()=>{this._checkMonospaceFontAssumptions()},2e3),this._lastRenderedData=new t,this._horizontalRevealRequest=null,this._stickyScrollEnabled=u.get(116).enabled,this._maxNumberStickyLines=u.get(116).maxLineCount}dispose(){this._asyncUpdateLineWidths.dispose(),this._asyncCheckMonospaceFontAssumptions.dispose(),super.dispose()}getDomNode(){return this.domNode}onConfigurationChanged(l){this._visibleLines.onConfigurationChanged(l),l.hasChanged(147)&&(this._maxLineWidth=0);const a=this._context.configuration.options,r=a.get(50),u=a.get(147);return this._lineHeight=a.get(67),this._typicalHalfwidthCharacterWidth=r.typicalHalfwidthCharacterWidth,this._isViewportWrapping=u.isViewportWrapping,this._revealHorizontalRightPadding=a.get(101),this._cursorSurroundingLines=a.get(29),this._cursorSurroundingLinesStyle=a.get(30),this._canUseLayerHinting=!a.get(32),this._stickyScrollEnabled=a.get(116).enabled,this._maxNumberStickyLines=a.get(116).maxLineCount,(0,E.applyFontInfo)(this.domNode,r),this._onOptionsMaybeChanged(),l.hasChanged(146)&&(this._maxLineWidth=0),!0}_onOptionsMaybeChanged(){const l=this._context.configuration,a=new p.ViewLineOptions(l,this._context.theme.type);if(!this._viewLineOptions.equals(a)){this._viewLineOptions=a;const r=this._visibleLines.getStartLineNumber(),u=this._visibleLines.getEndLineNumber();for(let C=r;C<=u;C++)this._visibleLines.getVisibleLine(C).onOptionsChanged(this._viewLineOptions);return!0}return!1}onCursorStateChanged(l){const a=this._visibleLines.getStartLineNumber(),r=this._visibleLines.getEndLineNumber();let u=!1;for(let C=a;C<=r;C++)u=this._visibleLines.getVisibleLine(C).onSelectionChanged()||u;return u}onDecorationsChanged(l){{const a=this._visibleLines.getStartLineNumber(),r=this._visibleLines.getEndLineNumber();for(let u=a;u<=r;u++)this._visibleLines.getVisibleLine(u).onDecorationsChanged()}return!0}onFlushed(l){const a=this._visibleLines.onFlushed(l);return this._maxLineWidth=0,a}onLinesChanged(l){return this._visibleLines.onLinesChanged(l)}onLinesDeleted(l){return this._visibleLines.onLinesDeleted(l)}onLinesInserted(l){return this._visibleLines.onLinesInserted(l)}onRevealRangeRequest(l){const a=this._computeScrollTopToRevealRange(this._context.viewLayout.getFutureViewport(),l.source,l.minimalReveal,l.range,l.selections,l.verticalType);if(a===-1)return!1;let r=this._context.viewLayout.validateScrollPosition({scrollTop:a});l.revealHorizontal?l.range&&l.range.startLineNumber!==l.range.endLineNumber?r={scrollTop:r.scrollTop,scrollLeft:0}:l.range?this._horizontalRevealRequest=new i(l.minimalReveal,l.range.startLineNumber,l.range.startColumn,l.range.endColumn,this._context.viewLayout.getCurrentScrollTop(),r.scrollTop,l.scrollType):l.selections&&l.selections.length>0&&(this._horizontalRevealRequest=new s(l.minimalReveal,l.selections,this._context.viewLayout.getCurrentScrollTop(),r.scrollTop,l.scrollType)):this._horizontalRevealRequest=null;const C=Math.abs(this._context.viewLayout.getCurrentScrollTop()-r.scrollTop)<=this._lineHeight?1:l.scrollType;return this._context.viewModel.viewLayout.setScrollPosition(r,C),!0}onScrollChanged(l){if(this._horizontalRevealRequest&&l.scrollLeftChanged&&(this._horizontalRevealRequest=null),this._horizontalRevealRequest&&l.scrollTopChanged){const a=Math.min(this._horizontalRevealRequest.startScrollTop,this._horizontalRevealRequest.stopScrollTop),r=Math.max(this._horizontalRevealRequest.startScrollTop,this._horizontalRevealRequest.stopScrollTop);(l.scrollTopr)&&(this._horizontalRevealRequest=null)}return this.domNode.setWidth(l.scrollWidth),this._visibleLines.onScrollChanged(l)||!0}onTokensChanged(l){return this._visibleLines.onTokensChanged(l)}onZonesChanged(l){return this._context.viewModel.viewLayout.setMaxLineWidth(this._maxLineWidth),this._visibleLines.onZonesChanged(l)}onThemeChanged(l){return this._onOptionsMaybeChanged()}getPositionFromDOMInfo(l,a){const r=this._getViewLineDomNode(l);if(r===null)return null;const u=this._getLineNumberFor(r);if(u===-1||u<1||u>this._context.viewModel.getLineCount())return null;if(this._context.viewModel.getLineMaxColumn(u)===1)return new n.Position(u,1);const C=this._visibleLines.getStartLineNumber(),f=this._visibleLines.getEndLineNumber();if(uf)return null;let h=this._visibleLines.getVisibleLine(u).getColumnOfNodeOffset(l,a);const v=this._context.viewModel.getLineMinColumn(u);return hr)return-1;const u=new b.DomReadingContext(this.domNode.domNode,this._textRangeRestingSpot),C=this._visibleLines.getVisibleLine(l).getWidth(u);return this._updateLineWidthsSlowIfDomDidLayout(u),C}linesVisibleRangesForRange(l,a){if(this.shouldRender())return null;const r=l.endLineNumber,u=o.Range.intersectRanges(l,this._lastRenderedData.getCurrentVisibleRange());if(!u)return null;const C=[];let f=0;const h=new b.DomReadingContext(this.domNode.domNode,this._textRangeRestingSpot);let v=0;a&&(v=this._context.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new n.Position(u.startLineNumber,1)).lineNumber);const w=this._visibleLines.getStartLineNumber(),S=this._visibleLines.getEndLineNumber();for(let L=u.startLineNumber;L<=u.endLineNumber;L++){if(LS)continue;const D=L===u.startLineNumber?u.startColumn:1,T=L!==u.endLineNumber,M=T?this._context.viewModel.getLineMaxColumn(L):u.endColumn,A=this._visibleLines.getVisibleLine(L).getVisibleRangesForRange(L,D,M,h);if(A){if(a&&Lthis._visibleLines.getEndLineNumber())return null;const u=new b.DomReadingContext(this.domNode.domNode,this._textRangeRestingSpot),C=this._visibleLines.getVisibleLine(l).getVisibleRangesForRange(l,a,r,u);return this._updateLineWidthsSlowIfDomDidLayout(u),C}visibleRangeForPosition(l){const a=this._visibleRangesForLineRange(l.lineNumber,l.column,l.column);return a?new y.HorizontalPosition(a.outsideRenderedLine,a.ranges[0].left):null}_updateLineWidthsFast(){return this._updateLineWidths(!0)}_updateLineWidthsSlow(){this._updateLineWidths(!1)}_updateLineWidthsSlowIfDomDidLayout(l){l.didDomLayout&&(this._asyncUpdateLineWidths.isScheduled()||(this._asyncUpdateLineWidths.cancel(),this._updateLineWidthsSlow()))}_updateLineWidths(l){const a=this._visibleLines.getStartLineNumber(),r=this._visibleLines.getEndLineNumber();let u=1,C=!0;for(let f=a;f<=r;f++){const h=this._visibleLines.getVisibleLine(f);if(l&&!h.getWidthIsFast()){C=!1;continue}u=Math.max(u,h.getWidth(null))}return C&&a===1&&r===this._context.viewModel.getLineCount()&&(this._maxLineWidth=0),this._ensureMaxLineWidth(u),C}_checkMonospaceFontAssumptions(){let l=-1,a=-1;const r=this._visibleLines.getStartLineNumber(),u=this._visibleLines.getEndLineNumber();for(let C=r;C<=u;C++){const f=this._visibleLines.getVisibleLine(C);if(f.needsMonospaceFontCheck()){const h=f.getWidth(null);h>a&&(a=h,l=C)}}if(l!==-1&&!this._visibleLines.getVisibleLine(l).monospaceAssumptionsAreValid())for(let C=r;C<=u;C++)this._visibleLines.getVisibleLine(C).onMonospaceAssumptionsInvalidated()}prepareRender(){throw new Error("Not supported")}render(){throw new Error("Not supported")}renderText(l){if(this._visibleLines.renderLines(l),this._lastRenderedData.setCurrentVisibleRange(l.visibleRange),this.domNode.setWidth(this._context.viewLayout.getScrollWidth()),this.domNode.setHeight(Math.min(this._context.viewLayout.getScrollHeight(),1e6)),this._horizontalRevealRequest){const r=this._horizontalRevealRequest;if(l.startLineNumber<=r.minLineNumber&&r.maxLineNumber<=l.endLineNumber){this._horizontalRevealRequest=null,this.onDidRender();const u=this._computeScrollLeftToReveal(r);u&&(this._isViewportWrapping||this._ensureMaxLineWidth(u.maxHorizontalOffset),this._context.viewModel.viewLayout.setScrollPosition({scrollLeft:u.scrollLeft},r.scrollType))}}if(this._updateLineWidthsFast()?this._asyncUpdateLineWidths.cancel():this._asyncUpdateLineWidths.schedule(),I.isLinux&&!this._asyncCheckMonospaceFontAssumptions.isScheduled()){const r=this._visibleLines.getStartLineNumber(),u=this._visibleLines.getEndLineNumber();for(let C=r;C<=u;C++)if(this._visibleLines.getVisibleLine(C).needsMonospaceFontCheck()){this._asyncCheckMonospaceFontAssumptions.schedule();break}}this._linesContent.setLayerHinting(this._canUseLayerHinting),this._linesContent.setContain("strict");const a=this._context.viewLayout.getCurrentScrollTop()-l.bigNumbersDelta;this._linesContent.setTop(-a),this._linesContent.setLeft(-this._context.viewLayout.getCurrentScrollLeft())}_ensureMaxLineWidth(l){const a=Math.ceil(l);this._maxLineWidth0){let N=C[0].startLineNumber,O=C[0].endLineNumber;for(let F=1,x=C.length;Fv){if(!S)return-1;P=L}else if(f===5||f===6)if(f===6&&h<=L&&D<=w)P=h;else{const N=Math.max(5*this._lineHeight,v*.2),O=L-N,F=D-v;P=Math.max(F,O)}else if(f===1||f===2)if(f===2&&h<=L&&D<=w)P=h;else{const N=(L+D)/2;P=Math.max(0,N-v/2)}else P=this._computeMinimumScrolling(h,w,L,D,f===3,f===4);return P}_computeScrollLeftToReveal(l){const a=this._context.viewLayout.getCurrentViewport(),r=this._context.configuration.options.get(146),u=a.left,C=u+a.width-r.verticalScrollbarWidth;let f=1073741824,h=0;if(l.type==="range"){const w=this._visibleRangesForLineRange(l.lineNumber,l.startColumn,l.endColumn);if(!w)return null;for(const S of w.ranges)f=Math.min(f,Math.round(S.left)),h=Math.max(h,Math.round(S.left+S.width))}else for(const w of l.selections){if(w.startLineNumber!==w.endLineNumber)return null;const S=this._visibleRangesForLineRange(w.startLineNumber,w.startColumn,w.endColumn);if(!S)return null;for(const L of S.ranges)f=Math.min(f,Math.round(L.left)),h=Math.max(h,Math.round(L.left+L.width))}return l.minimalReveal||(f=Math.max(0,f-g.HORIZONTAL_EXTRA_PX),h+=this._revealHorizontalRightPadding),l.type==="selections"&&h-f>a.width?null:{scrollLeft:this._computeMinimumScrolling(u,C,f,h),maxHorizontalOffset:h}}_computeMinimumScrolling(l,a,r,u,C,f){l=l|0,a=a|0,r=r|0,u=u|0,C=!!C,f=!!f;const h=a-l;if(u-ra)return Math.max(0,u-h)}else return r;return l}}e.ViewLines=g}),define(ne[25],se([1,0,6,2,7,38,97]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Themable=e.Extensions=e.IThemeService=void 0,e.themeColorFromId=m,e.getThemeTypeSelector=_,e.registerThemingParticipant=n,e.IThemeService=(0,I.createDecorator)("themeService");function m(t){return{id:t}}function _(t){switch(t){case y.ColorScheme.DARK:return"vs-dark";case y.ColorScheme.HIGH_CONTRAST_DARK:return"hc-black";case y.ColorScheme.HIGH_CONTRAST_LIGHT:return"hc-light";default:return"vs"}}e.Extensions={ThemingContribution:"base.contributions.theming"};class b{constructor(){this.themingParticipants=[],this.themingParticipants=[],this.onThemingParticipantAddedEmitter=new d.Emitter}onColorThemeChange(i){return this.themingParticipants.push(i),this.onThemingParticipantAddedEmitter.fire(i),(0,k.toDisposable)(()=>{const s=this.themingParticipants.indexOf(i);this.themingParticipants.splice(s,1)})}getThemingParticipants(){return this.themingParticipants}}const p=new b;E.Registry.add(e.Extensions.ThemingContribution,p);function n(t){return p.onColorThemeChange(t)}class o extends k.Disposable{constructor(i){super(),this.themeService=i,this.theme=i.getColorTheme(),this._register(this.themeService.onDidColorThemeChange(s=>this.onThemeChange(s)))}onThemeChange(i){this.theme=i,this.updateStyles()}updateStyles(){}}e.Themable=o}),define(ne[771],se([1,0,6,2,73,25]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GlobalStyleSheet=e.AbstractCodeEditorService=void 0;let y=class extends k.Disposable{constructor(b){super(),this._themeService=b,this._onWillCreateCodeEditor=this._register(new d.Emitter),this._onCodeEditorAdd=this._register(new d.Emitter),this.onCodeEditorAdd=this._onCodeEditorAdd.event,this._onCodeEditorRemove=this._register(new d.Emitter),this.onCodeEditorRemove=this._onCodeEditorRemove.event,this._onWillCreateDiffEditor=this._register(new d.Emitter),this._onDiffEditorAdd=this._register(new d.Emitter),this.onDiffEditorAdd=this._onDiffEditorAdd.event,this._onDiffEditorRemove=this._register(new d.Emitter),this.onDiffEditorRemove=this._onDiffEditorRemove.event,this._decorationOptionProviders=new Map,this._codeEditorOpenHandlers=new I.LinkedList,this._modelProperties=new Map,this._codeEditors=Object.create(null),this._diffEditors=Object.create(null),this._globalStyleSheet=null}willCreateCodeEditor(){this._onWillCreateCodeEditor.fire()}addCodeEditor(b){this._codeEditors[b.getId()]=b,this._onCodeEditorAdd.fire(b)}removeCodeEditor(b){delete this._codeEditors[b.getId()]&&this._onCodeEditorRemove.fire(b)}listCodeEditors(){return Object.keys(this._codeEditors).map(b=>this._codeEditors[b])}willCreateDiffEditor(){this._onWillCreateDiffEditor.fire()}addDiffEditor(b){this._diffEditors[b.getId()]=b,this._onDiffEditorAdd.fire(b)}listDiffEditors(){return Object.keys(this._diffEditors).map(b=>this._diffEditors[b])}getFocusedCodeEditor(){let b=null;const p=this.listCodeEditors();for(const n of p){if(n.hasTextFocus())return n;n.hasWidgetFocus()&&(b=n)}return b}removeDecorationType(b){const p=this._decorationOptionProviders.get(b);p&&(p.refCount--,p.refCount<=0&&(this._decorationOptionProviders.delete(b),p.dispose(),this.listCodeEditors().forEach(n=>n.removeDecorationsByType(b))))}setModelProperty(b,p,n){const o=b.toString();let t;this._modelProperties.has(o)?t=this._modelProperties.get(o):(t=new Map,this._modelProperties.set(o,t)),t.set(p,n)}getModelProperty(b,p){const n=b.toString();if(this._modelProperties.has(n))return this._modelProperties.get(n).get(p)}async openCodeEditor(b,p,n){for(const o of this._codeEditorOpenHandlers){const t=await o(b,p,n);if(t!==null)return t}return null}registerCodeEditorOpenHandler(b){const p=this._codeEditorOpenHandlers.unshift(b);return(0,k.toDisposable)(p)}};e.AbstractCodeEditorService=y,e.AbstractCodeEditorService=y=ke([ce(0,E.IThemeService)],y);class m{constructor(b){this._styleSheet=b}}e.GlobalStyleSheet=m}),define(ne[772],se([1,0,49,25,32,118,58,7,705,2,5,31,47,61,119,52,395,648,14]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HoverService=void 0;let a=class extends b.Disposable{constructor(h,v,w,S,L){super(),this._instantiationService=h,this._keybindingService=w,this._layoutService=S,this._accessibilityService=L,this._managedHovers=new Map,v.onDidShowContextMenu(()=>this.hideHover()),this._contextViewHandler=this._register(new g.ContextViewHandler(this._layoutService))}showHover(h,v,w){if(r(this._currentHoverOptions)===r(h)||this._currentHover&&this._currentHoverOptions?.persistence?.sticky)return;this._currentHoverOptions=h,this._lastHoverOptions=h;const S=h.trapFocus||this._accessibilityService.isScreenReaderOptimized(),L=(0,p.getActiveElement)();w||(S&&L?L.classList.contains("monaco-hover")||(this._lastFocusedElementBeforeOpen=L):this._lastFocusedElementBeforeOpen=void 0);const D=new b.DisposableStore,T=this._instantiationService.createInstance(_.HoverWidget,h);if(h.persistence?.sticky&&(T.isLocked=!0),T.onDispose(()=>{this._currentHover?.domNode&&(0,p.isAncestorOfActiveElement)(this._currentHover.domNode)&&this._lastFocusedElementBeforeOpen?.focus(),this._currentHoverOptions===h&&(this._currentHoverOptions=void 0),D.dispose()},void 0,D),!h.container){const M=(0,p.isHTMLElement)(h.target)?h.target:h.target.targetElements[0];h.container=this._layoutService.getContainer((0,p.getWindow)(M))}if(this._contextViewHandler.showContextView(new u(T,v),h.container),T.onRequestLayout(()=>this._contextViewHandler.layout(),void 0,D),h.persistence?.sticky)D.add((0,p.addDisposableListener)((0,p.getWindow)(h.container).document,p.EventType.MOUSE_DOWN,M=>{(0,p.isAncestor)(M.target,T.domNode)||this.doHideHover()}));else{if("targetElements"in h.target)for(const A of h.target.targetElements)D.add((0,p.addDisposableListener)(A,p.EventType.CLICK,()=>this.hideHover()));else D.add((0,p.addDisposableListener)(h.target,p.EventType.CLICK,()=>this.hideHover()));const M=(0,p.getActiveElement)();if(M){const A=(0,p.getWindow)(M).document;D.add((0,p.addDisposableListener)(M,p.EventType.KEY_DOWN,P=>this._keyDown(P,T,!!h.persistence?.hideOnKeyDown))),D.add((0,p.addDisposableListener)(A,p.EventType.KEY_DOWN,P=>this._keyDown(P,T,!!h.persistence?.hideOnKeyDown))),D.add((0,p.addDisposableListener)(M,p.EventType.KEY_UP,P=>this._keyUp(P,T))),D.add((0,p.addDisposableListener)(A,p.EventType.KEY_UP,P=>this._keyUp(P,T)))}}if("IntersectionObserver"in s.mainWindow){const M=new IntersectionObserver(P=>this._intersectionChange(P,T),{threshold:0}),A="targetElements"in h.target?h.target.targetElements[0]:h.target;M.observe(A),D.add((0,b.toDisposable)(()=>M.disconnect()))}return this._currentHover=T,T}hideHover(){this._currentHover?.isLocked||!this._currentHoverOptions||this.doHideHover()}doHideHover(){this._currentHover=void 0,this._currentHoverOptions=void 0,this._contextViewHandler.hideContextView()}_intersectionChange(h,v){h[h.length-1].isIntersecting||v.dispose()}showAndFocusLastHover(){this._lastHoverOptions&&this.showHover(this._lastHoverOptions,!0,!0)}_keyDown(h,v,w){if(h.key==="Alt"){v.isLocked=!0;return}const S=new o.StandardKeyboardEvent(h);this._keybindingService.resolveKeyboardEvent(S).getSingleModifierDispatchChords().some(D=>!!D)||this._keybindingService.softDispatch(S,S.target).kind!==0||w&&(!this._currentHoverOptions?.trapFocus||h.key!=="Tab")&&(this.hideHover(),this._lastFocusedElementBeforeOpen?.focus())}_keyUp(h,v){h.key==="Alt"&&(v.isLocked=!1,v.isMouseIn||(this.hideHover(),this._lastFocusedElementBeforeOpen?.focus()))}setupManagedHover(h,v,w,S){v.setAttribute("custom-hover","true"),v.title!==""&&(console.warn("HTML element already has a title attribute, which will conflict with the custom hover. Please remove the title attribute."),console.trace("Stack trace:",v.title),v.title="");let L,D;const T=(z,U)=>{const j=D!==void 0;z&&(D?.dispose(),D=void 0),U&&(L?.dispose(),L=void 0),j&&(h.onDidHideHover?.(),D=void 0)},M=(z,U,j,Y)=>new l.TimeoutTimer(async()=>{(!D||D.isDisposed)&&(D=new c.ManagedHoverWidget(h,j||v,z>0),await D.update(typeof w=="function"?w():w,U,{...S,trapFocus:Y}))},z);let A=!1;const P=(0,p.addDisposableListener)(v,p.EventType.MOUSE_DOWN,()=>{A=!0,T(!0,!0)},!0),N=(0,p.addDisposableListener)(v,p.EventType.MOUSE_UP,()=>{A=!1},!0),O=(0,p.addDisposableListener)(v,p.EventType.MOUSE_LEAVE,z=>{A=!1,T(!1,z.fromElement===v)},!0),F=z=>{if(L)return;const U=new b.DisposableStore,j={targetElements:[v],dispose:()=>{}};if(h.placement===void 0||h.placement==="mouse"){const Y=G=>{j.x=G.x+10,(0,p.isHTMLElement)(G.target)&&C(G.target,v)!==v&&T(!0,!0)};U.add((0,p.addDisposableListener)(v,p.EventType.MOUSE_MOVE,Y,!0))}L=U,!((0,p.isHTMLElement)(z.target)&&C(z.target,v)!==v)&&U.add(M(h.delay,!1,j))},x=(0,p.addDisposableListener)(v,p.EventType.MOUSE_OVER,F,!0),W=()=>{if(A||L)return;const z={targetElements:[v],dispose:()=>{}},U=new b.DisposableStore,j=()=>T(!0,!0);U.add((0,p.addDisposableListener)(v,p.EventType.BLUR,j,!0)),U.add(M(h.delay,!1,z)),L=U};let V;const q=v.tagName.toLowerCase();q!=="input"&&q!=="textarea"&&(V=(0,p.addDisposableListener)(v,p.EventType.FOCUS,W,!0));const H={show:z=>{T(!1,!0),M(0,z,void 0,z)},hide:()=>{T(!0,!0)},update:async(z,U)=>{w=z,await D?.update(w,void 0,U)},dispose:()=>{this._managedHovers.delete(v),x.dispose(),O.dispose(),P.dispose(),N.dispose(),V?.dispose(),T(!0,!0)}};return this._managedHovers.set(v,H),H}showManagedHover(h){const v=this._managedHovers.get(h);v&&v.show(!0)}dispose(){this._managedHovers.forEach(h=>h.dispose()),super.dispose()}};e.HoverService=a,e.HoverService=a=ke([ce(0,m.IInstantiationService),ce(1,y.IContextMenuService),ce(2,n.IKeybindingService),ce(3,i.ILayoutService),ce(4,t.IAccessibilityService)],a);function r(f){if(f!==void 0)return f?.id??f}class u{get anchorPosition(){return this._hover.anchor}constructor(h,v=!1){this._hover=h,this._focus=v,this.layer=1}render(h){return this._hover.render(h),this._focus&&this._hover.focus(),this._hover}getAnchor(){return{x:this._hover.x,y:this._hover.y}}layout(){this._hover.layout()}}function C(f,h){for(h=h??(0,p.getWindow)(f).document.body;!f.hasAttribute("custom-hover")&&f!==h;)f=f.parentElement;return f}(0,d.registerSingleton)(E.IHoverService,a,1),(0,k.registerThemingParticipant)((f,h)=>{const v=f.getColor(I.editorHoverBorder);v&&(h.addRule(`.monaco-workbench .workbench-hover .hover-row:not(:first-child):not(:empty) { border-top: 1px solid ${v.transparent(.5)}; }`),h.addRule(`.monaco-workbench .workbench-hover hr { border-top: 1px solid ${v.transparent(.5)}; }`))})}),define(ne[773],se([1,0,5,39,86,56,25]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EditorScrollbar=void 0;class m extends E.ViewPart{constructor(b,p,n,o){super(b);const t=this._context.configuration.options,i=t.get(104),s=t.get(75),g=t.get(40),c=t.get(107),l={listenOnDomNode:n.domNode,className:"editor-scrollable "+(0,y.getThemeTypeSelector)(b.theme.type),useShadows:!1,lazyRender:!0,vertical:i.vertical,horizontal:i.horizontal,verticalHasArrows:i.verticalHasArrows,horizontalHasArrows:i.horizontalHasArrows,verticalScrollbarSize:i.verticalScrollbarSize,verticalSliderSize:i.verticalSliderSize,horizontalScrollbarSize:i.horizontalScrollbarSize,horizontalSliderSize:i.horizontalSliderSize,handleMouseWheel:i.handleMouseWheel,alwaysConsumeMouseWheel:i.alwaysConsumeMouseWheel,arrowSize:i.arrowSize,mouseWheelScrollSensitivity:s,fastScrollSensitivity:g,scrollPredominantAxis:c,scrollByPage:i.scrollByPage};this.scrollbar=this._register(new I.SmoothScrollableElement(p.domNode,l,this._context.viewLayout.getScrollable())),E.PartFingerprints.write(this.scrollbar.getDomNode(),6),this.scrollbarDomNode=(0,k.createFastDomNode)(this.scrollbar.getDomNode()),this.scrollbarDomNode.setPosition("absolute"),this._setLayout();const a=(r,u,C)=>{const f={};if(u){const h=r.scrollTop;h&&(f.scrollTop=this._context.viewLayout.getCurrentScrollTop()+h,r.scrollTop=0)}if(C){const h=r.scrollLeft;h&&(f.scrollLeft=this._context.viewLayout.getCurrentScrollLeft()+h,r.scrollLeft=0)}this._context.viewModel.viewLayout.setScrollPosition(f,1)};this._register(d.addDisposableListener(n.domNode,"scroll",r=>a(n.domNode,!0,!0))),this._register(d.addDisposableListener(p.domNode,"scroll",r=>a(p.domNode,!0,!1))),this._register(d.addDisposableListener(o.domNode,"scroll",r=>a(o.domNode,!0,!1))),this._register(d.addDisposableListener(this.scrollbarDomNode.domNode,"scroll",r=>a(this.scrollbarDomNode.domNode,!0,!1)))}dispose(){super.dispose()}_setLayout(){const b=this._context.configuration.options,p=b.get(146);this.scrollbarDomNode.setLeft(p.contentLeft),b.get(73).side==="right"?this.scrollbarDomNode.setWidth(p.contentWidth+p.minimap.minimapWidth):this.scrollbarDomNode.setWidth(p.contentWidth),this.scrollbarDomNode.setHeight(p.height)}getOverviewRulerLayoutInfo(){return this.scrollbar.getOverviewRulerLayoutInfo()}getDomNode(){return this.scrollbarDomNode}delegateVerticalScrollbarPointerDown(b){this.scrollbar.delegateVerticalScrollbarPointerDown(b)}delegateScrollFromMouseWheelEvent(b){this.scrollbar.delegateScrollFromMouseWheelEvent(b)}onConfigurationChanged(b){if(b.hasChanged(104)||b.hasChanged(75)||b.hasChanged(40)){const p=this._context.configuration.options,n=p.get(104),o=p.get(75),t=p.get(40),i=p.get(107),s={vertical:n.vertical,horizontal:n.horizontal,verticalScrollbarSize:n.verticalScrollbarSize,horizontalScrollbarSize:n.horizontalScrollbarSize,scrollByPage:n.scrollByPage,handleMouseWheel:n.handleMouseWheel,mouseWheelScrollSensitivity:o,fastScrollSensitivity:t,scrollPredominantAxis:i};this.scrollbar.updateOptions(s)}return b.hasChanged(146)&&this._setLayout(),!0}onScrollChanged(b){return!0}onThemeChanged(b){return this.scrollbar.updateClassName("editor-scrollable "+(0,y.getThemeTypeSelector)(this._context.theme.type)),!0}prepareRender(b){}render(b){this.scrollbar.renderNow()}}e.EditorScrollbar=m}),define(ne[774],se([1,0,133,32,25,495]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SelectionsOverlay=void 0;class E{constructor(o){this.left=o.left,this.width=o.width,this.startStyle=null,this.endStyle=null}}class y{constructor(o,t){this.lineNumber=o,this.ranges=t}}function m(n){return new E(n)}function _(n){return new y(n.lineNumber,n.ranges.map(m))}class b extends d.DynamicViewOverlay{static{this.SELECTION_CLASS_NAME="selected-text"}static{this.SELECTION_TOP_LEFT="top-left-radius"}static{this.SELECTION_BOTTOM_LEFT="bottom-left-radius"}static{this.SELECTION_TOP_RIGHT="top-right-radius"}static{this.SELECTION_BOTTOM_RIGHT="bottom-right-radius"}static{this.EDITOR_BACKGROUND_CLASS_NAME="monaco-editor-background"}static{this.ROUNDED_PIECE_WIDTH=10}constructor(o){super(),this._previousFrameVisibleRangesWithStyle=[],this._context=o;const t=this._context.configuration.options;this._roundedSelection=t.get(102),this._typicalHalfwidthCharacterWidth=t.get(50).typicalHalfwidthCharacterWidth,this._selections=[],this._renderResult=null,this._context.addEventHandler(this)}dispose(){this._context.removeEventHandler(this),this._renderResult=null,super.dispose()}onConfigurationChanged(o){const t=this._context.configuration.options;return this._roundedSelection=t.get(102),this._typicalHalfwidthCharacterWidth=t.get(50).typicalHalfwidthCharacterWidth,!0}onCursorStateChanged(o){return this._selections=o.selections.slice(0),!0}onDecorationsChanged(o){return!0}onFlushed(o){return!0}onLinesChanged(o){return!0}onLinesDeleted(o){return!0}onLinesInserted(o){return!0}onScrollChanged(o){return o.scrollTopChanged}onZonesChanged(o){return!0}_visibleRangesHaveGaps(o){for(let t=0,i=o.length;t1)return!0;return!1}_enrichVisibleRangesWithStyle(o,t,i){const s=this._typicalHalfwidthCharacterWidth/4;let g=null,c=null;if(i&&i.length>0&&t.length>0){const l=t[0].lineNumber;if(l===o.startLineNumber)for(let r=0;!g&&r=0;r--)i[r].lineNumber===a&&(c=i[r].ranges[0]);g&&!g.startStyle&&(g=null),c&&!c.startStyle&&(c=null)}for(let l=0,a=t.length;l0){const v=t[l-1].ranges[0].left,w=t[l-1].ranges[0].left+t[l-1].ranges[0].width;p(u-v)v&&(f.top=1),p(C-w)'}_actualRenderOneSelection(o,t,i,s){if(s.length===0)return;const g=!!s[0].ranges[0].startStyle,c=s[0].lineNumber,l=s[s.length-1].lineNumber;for(let a=0,r=s.length;a1,r)}this._previousFrameVisibleRangesWithStyle=g,this._renderResult=t.map(([c,l])=>c+l)}render(o,t){if(!this._renderResult)return"";const i=t-o;return i<0||i>=this._renderResult.length?"":this._renderResult[i]}}e.SelectionsOverlay=b,(0,I.registerThemingParticipant)((n,o)=>{const t=n.getColor(k.editorSelectionForeground);t&&!t.isTransparent()&&o.addRule(`.monaco-editor .view-line span.inline-selected-text { color: ${t}; }`)});function p(n){return n<0?-n:n}}),define(ne[415],se([1,0,5,39,223,2,21,88,9,332,32,25]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";var o;Object.defineProperty(e,"__esModule",{value:!0}),e.OverviewRulerFeature=void 0;let t=class extends E.Disposable{static{o=this}static{this.ONE_OVERVIEW_WIDTH=15}static{this.ENTIRE_DIFF_OVERVIEW_WIDTH=this.ONE_OVERVIEW_WIDTH*2}constructor(s,g,c,l,a,r,u){super(),this._editors=s,this._rootElement=g,this._diffModel=c,this._rootWidth=l,this._rootHeight=a,this._modifiedEditorLayoutInfo=r,this._themeService=u,this.width=o.ENTIRE_DIFF_OVERVIEW_WIDTH;const C=(0,y.observableFromEvent)(this._themeService.onDidColorThemeChange,()=>this._themeService.getColorTheme()),f=(0,y.derived)(w=>{const S=C.read(w),L=S.getColor(p.diffOverviewRulerInserted)||(S.getColor(p.diffInserted)||p.defaultInsertColor).transparent(2),D=S.getColor(p.diffOverviewRulerRemoved)||(S.getColor(p.diffRemoved)||p.defaultRemoveColor).transparent(2);return{insertColor:L,removeColor:D}}),h=(0,k.createFastDomNode)(document.createElement("div"));h.setClassName("diffViewport"),h.setPosition("absolute");const v=(0,d.h)("div.diffOverview",{style:{position:"absolute",top:"0px",width:o.ENTIRE_DIFF_OVERVIEW_WIDTH+"px"}}).root;this._register((0,m.appendRemoveOnDispose)(v,h.domNode)),this._register((0,d.addStandardDisposableListener)(v,d.EventType.POINTER_DOWN,w=>{this._editors.modified.delegateVerticalScrollbarPointerDown(w)})),this._register((0,d.addDisposableListener)(v,d.EventType.MOUSE_WHEEL,w=>{this._editors.modified.delegateScrollFromMouseWheelEvent(w)},{passive:!1})),this._register((0,m.appendRemoveOnDispose)(this._rootElement,v)),this._register((0,y.autorunWithStore)((w,S)=>{const L=this._diffModel.read(w),D=this._editors.original.createOverviewRuler("original diffOverviewRuler");D&&(S.add(D),S.add((0,m.appendRemoveOnDispose)(v,D.getDomNode())));const T=this._editors.modified.createOverviewRuler("modified diffOverviewRuler");if(T&&(S.add(T),S.add((0,m.appendRemoveOnDispose)(v,T.getDomNode()))),!D||!T)return;const M=(0,y.observableSignalFromEvent)("viewZoneChanged",this._editors.original.onDidChangeViewZones),A=(0,y.observableSignalFromEvent)("viewZoneChanged",this._editors.modified.onDidChangeViewZones),P=(0,y.observableSignalFromEvent)("hiddenRangesChanged",this._editors.original.onDidChangeHiddenAreas),N=(0,y.observableSignalFromEvent)("hiddenRangesChanged",this._editors.modified.onDidChangeHiddenAreas);S.add((0,y.autorun)(O=>{M.read(O),A.read(O),P.read(O),N.read(O);const F=f.read(O),x=L?.diff.read(O)?.mappings;function W(H,z,U){const j=U._getViewModel();return j?H.filter(Y=>Y.length>0).map(Y=>{const G=j.coordinatesConverter.convertModelPositionToViewPosition(new _.Position(Y.startLineNumber,1)),K=j.coordinatesConverter.convertModelPositionToViewPosition(new _.Position(Y.endLineNumberExclusive,1)),R=K.lineNumber-G.lineNumber;return new b.OverviewRulerZone(G.lineNumber,K.lineNumber,R,z.toString())}):[]}const V=W((x||[]).map(H=>H.lineRangeMapping.original),F.removeColor,this._editors.original),q=W((x||[]).map(H=>H.lineRangeMapping.modified),F.insertColor,this._editors.modified);D?.setZones(V),T?.setZones(q)})),S.add((0,y.autorun)(O=>{const F=this._rootHeight.read(O),x=this._rootWidth.read(O),W=this._modifiedEditorLayoutInfo.read(O);if(W){const V=o.ENTIRE_DIFF_OVERVIEW_WIDTH-2*o.ONE_OVERVIEW_WIDTH;D.setLayout({top:0,height:F,right:V+o.ONE_OVERVIEW_WIDTH,width:o.ONE_OVERVIEW_WIDTH}),T.setLayout({top:0,height:F,right:0,width:o.ONE_OVERVIEW_WIDTH});const q=this._editors.modifiedScrollTop.read(O),H=this._editors.modifiedScrollHeight.read(O),z=this._editors.modified.getOption(104),U=new I.ScrollbarState(z.verticalHasArrows?z.arrowSize:0,z.verticalScrollbarSize,0,W.height,H,q);h.setTop(U.getSliderPosition()),h.setHeight(U.getSliderSize())}else h.setTop(0),h.setHeight(0);v.style.height=F+"px",v.style.left=x-o.ENTIRE_DIFF_OVERVIEW_WIDTH+"px",h.setWidth(o.ENTIRE_DIFF_OVERVIEW_WIDTH)}))}))}};e.OverviewRulerFeature=t,e.OverviewRulerFeature=t=o=ke([ce(6,n.IThemeService)],t)}),define(ne[775],se([1,0,6,2,21,112,415,37,9,3,7,31]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorEditors=void 0;let o=class extends k.Disposable{get onDidContentSizeChange(){return this._onDidContentSizeChange.event}constructor(i,s,g,c,l,a,r){super(),this.originalEditorElement=i,this.modifiedEditorElement=s,this._options=g,this._argCodeEditorWidgetOptions=c,this._createInnerEditor=l,this._instantiationService=a,this._keybindingService=r,this.original=this._register(this._createLeftHandSideEditor(this._options.editorOptions.get(),this._argCodeEditorWidgetOptions.originalEditor||{})),this.modified=this._register(this._createRightHandSideEditor(this._options.editorOptions.get(),this._argCodeEditorWidgetOptions.modifiedEditor||{})),this._onDidContentSizeChange=this._register(new d.Emitter),this.modifiedScrollTop=(0,I.observableFromEvent)(this,this.modified.onDidScrollChange,()=>this.modified.getScrollTop()),this.modifiedScrollHeight=(0,I.observableFromEvent)(this,this.modified.onDidScrollChange,()=>this.modified.getScrollHeight()),this.modifiedObs=(0,E.observableCodeEditor)(this.modified),this.originalObs=(0,E.observableCodeEditor)(this.original),this.modifiedModel=this.modifiedObs.model,this.modifiedSelections=(0,I.observableFromEvent)(this,this.modified.onDidChangeCursorSelection,()=>this.modified.getSelections()??[]),this.modifiedCursor=(0,I.derivedOpts)({owner:this,equalsFn:_.Position.equals},u=>this.modifiedSelections.read(u)[0]?.getPosition()??new _.Position(1,1)),this.originalCursor=(0,I.observableFromEvent)(this,this.original.onDidChangeCursorPosition,()=>this.original.getPosition()??new _.Position(1,1)),this._argCodeEditorWidgetOptions=null,this._register((0,I.autorunHandleChanges)({createEmptyChangeSummary:()=>({}),handleChange:(u,C)=>(u.didChange(g.editorOptions)&&Object.assign(C,u.change.changedOptions),!0)},(u,C)=>{g.editorOptions.read(u),this._options.renderSideBySide.read(u),this.modified.updateOptions(this._adjustOptionsForRightHandSide(u,C)),this.original.updateOptions(this._adjustOptionsForLeftHandSide(u,C))}))}_createLeftHandSideEditor(i,s){const g=this._adjustOptionsForLeftHandSide(void 0,i),c=this._constructInnerEditor(this._instantiationService,this.originalEditorElement,g,s);return c.setContextValue("isInDiffLeftEditor",!0),c}_createRightHandSideEditor(i,s){const g=this._adjustOptionsForRightHandSide(void 0,i),c=this._constructInnerEditor(this._instantiationService,this.modifiedEditorElement,g,s);return c.setContextValue("isInDiffRightEditor",!0),c}_constructInnerEditor(i,s,g,c){const l=this._createInnerEditor(i,s,g,c);return this._register(l.onDidContentSizeChange(a=>{const r=this.original.getContentWidth()+this.modified.getContentWidth()+y.OverviewRulerFeature.ENTIRE_DIFF_OVERVIEW_WIDTH,u=Math.max(this.modified.getContentHeight(),this.original.getContentHeight());this._onDidContentSizeChange.fire({contentHeight:u,contentWidth:r,contentHeightChanged:a.contentHeightChanged,contentWidthChanged:a.contentWidthChanged})})),l}_adjustOptionsForLeftHandSide(i,s){const g=this._adjustOptionsForSubEditor(s);return this._options.renderSideBySide.get()?(g.unicodeHighlight=this._options.editorOptions.get().unicodeHighlight||{},g.wordWrapOverride1=this._options.diffWordWrap.get()):(g.wordWrapOverride1="off",g.wordWrapOverride2="off",g.stickyScroll={enabled:!1},g.unicodeHighlight={nonBasicASCII:!1,ambiguousCharacters:!1,invisibleCharacters:!1}),g.glyphMargin=this._options.renderSideBySide.get(),s.originalAriaLabel&&(g.ariaLabel=s.originalAriaLabel),g.ariaLabel=this._updateAriaLabel(g.ariaLabel),g.readOnly=!this._options.originalEditable.get(),g.dropIntoEditor={enabled:!g.readOnly},g.extraEditorClassName="original-in-monaco-diff-editor",g}_adjustOptionsForRightHandSide(i,s){const g=this._adjustOptionsForSubEditor(s);return s.modifiedAriaLabel&&(g.ariaLabel=s.modifiedAriaLabel),g.ariaLabel=this._updateAriaLabel(g.ariaLabel),g.wordWrapOverride1=this._options.diffWordWrap.get(),g.revealHorizontalRightPadding=m.EditorOptions.revealHorizontalRightPadding.defaultValue+y.OverviewRulerFeature.ENTIRE_DIFF_OVERVIEW_WIDTH,g.scrollbar.verticalHasArrows=!1,g.extraEditorClassName="modified-in-monaco-diff-editor",g}_adjustOptionsForSubEditor(i){const s={...i,dimension:{height:0,width:0}};return s.inDiffEditor=!0,s.automaticLayout=!1,s.scrollbar={...s.scrollbar||{}},s.folding=!1,s.codeLens=this._options.diffCodeLens.get(),s.fixedOverflowWidgets=!0,s.minimap={...s.minimap||{}},s.minimap.enabled=!1,this._options.hideUnchangedRegions.get()?s.stickyScroll={enabled:!1}:s.stickyScroll=this._options.editorOptions.get().stickyScroll,s}_updateAriaLabel(i){i||(i="");const s=(0,b.localize)(98," use {0} to open the accessibility help.",this._keybindingService.lookupKeybinding("editor.action.accessibilityHelp")?.getAriaLabel());return this._options.accessibilityVerbose.get()?i+s:i?i.replaceAll(s,""):""}};e.DiffEditorEditors=o,e.DiffEditorEditors=o=ke([ce(5,p.IInstantiationService),ce(6,n.IKeybindingService)],o)}),define(ne[80],se([1,0,3,33,32,25]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.editorUnicodeHighlightBackground=e.editorUnicodeHighlightBorder=e.editorBracketPairGuideActiveBackground6=e.editorBracketPairGuideActiveBackground5=e.editorBracketPairGuideActiveBackground4=e.editorBracketPairGuideActiveBackground3=e.editorBracketPairGuideActiveBackground2=e.editorBracketPairGuideActiveBackground1=e.editorBracketPairGuideBackground6=e.editorBracketPairGuideBackground5=e.editorBracketPairGuideBackground4=e.editorBracketPairGuideBackground3=e.editorBracketPairGuideBackground2=e.editorBracketPairGuideBackground1=e.editorBracketHighlightingUnexpectedBracketForeground=e.editorBracketHighlightingForeground6=e.editorBracketHighlightingForeground5=e.editorBracketHighlightingForeground4=e.editorBracketHighlightingForeground3=e.editorBracketHighlightingForeground2=e.editorBracketHighlightingForeground1=e.overviewRulerInfo=e.overviewRulerWarning=e.overviewRulerError=e.overviewRulerRangeHighlight=e.ghostTextBackground=e.ghostTextForeground=e.ghostTextBorder=e.editorUnnecessaryCodeOpacity=e.editorUnnecessaryCodeBorder=e.editorGutter=e.editorOverviewRulerBackground=e.editorOverviewRulerBorder=e.editorBracketMatchBorder=e.editorBracketMatchBackground=e.editorCodeLensForeground=e.editorRuler=e.editorDimmedLineNumber=e.editorActiveLineNumber=e.editorActiveIndentGuide6=e.editorActiveIndentGuide5=e.editorActiveIndentGuide4=e.editorActiveIndentGuide3=e.editorActiveIndentGuide2=e.editorActiveIndentGuide1=e.editorIndentGuide6=e.editorIndentGuide5=e.editorIndentGuide4=e.editorIndentGuide3=e.editorIndentGuide2=e.editorIndentGuide1=e.deprecatedEditorActiveIndentGuides=e.deprecatedEditorIndentGuides=e.editorLineNumbers=e.editorWhitespaces=e.editorMultiCursorSecondaryBackground=e.editorMultiCursorSecondaryForeground=e.editorMultiCursorPrimaryBackground=e.editorMultiCursorPrimaryForeground=e.editorCursorBackground=e.editorCursorForeground=e.editorSymbolHighlightBorder=e.editorSymbolHighlight=e.editorRangeHighlightBorder=e.editorRangeHighlight=e.editorLineHighlightBorder=e.editorLineHighlight=void 0,e.editorLineHighlight=(0,I.registerColor)("editor.lineHighlightBackground",null,d.localize(551,"Background color for the highlight of line at the cursor position.")),e.editorLineHighlightBorder=(0,I.registerColor)("editor.lineHighlightBorder",{dark:"#282828",light:"#eeeeee",hcDark:"#f38518",hcLight:I.contrastBorder},d.localize(552,"Background color for the border around the line at the cursor position.")),e.editorRangeHighlight=(0,I.registerColor)("editor.rangeHighlightBackground",{dark:"#ffffff0b",light:"#fdff0033",hcDark:null,hcLight:null},d.localize(553,"Background color of highlighted ranges, like by quick open and find features. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorRangeHighlightBorder=(0,I.registerColor)("editor.rangeHighlightBorder",{dark:null,light:null,hcDark:I.activeContrastBorder,hcLight:I.activeContrastBorder},d.localize(554,"Background color of the border around highlighted ranges.")),e.editorSymbolHighlight=(0,I.registerColor)("editor.symbolHighlightBackground",{dark:I.editorFindMatchHighlight,light:I.editorFindMatchHighlight,hcDark:null,hcLight:null},d.localize(555,"Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations."),!0),e.editorSymbolHighlightBorder=(0,I.registerColor)("editor.symbolHighlightBorder",{dark:null,light:null,hcDark:I.activeContrastBorder,hcLight:I.activeContrastBorder},d.localize(556,"Background color of the border around highlighted symbols.")),e.editorCursorForeground=(0,I.registerColor)("editorCursor.foreground",{dark:"#AEAFAD",light:k.Color.black,hcDark:k.Color.white,hcLight:"#0F4A85"},d.localize(557,"Color of the editor cursor.")),e.editorCursorBackground=(0,I.registerColor)("editorCursor.background",null,d.localize(558,"The background color of the editor cursor. Allows customizing the color of a character overlapped by a block cursor.")),e.editorMultiCursorPrimaryForeground=(0,I.registerColor)("editorMultiCursor.primary.foreground",e.editorCursorForeground,d.localize(559,"Color of the primary editor cursor when multiple cursors are present.")),e.editorMultiCursorPrimaryBackground=(0,I.registerColor)("editorMultiCursor.primary.background",e.editorCursorBackground,d.localize(560,"The background color of the primary editor cursor when multiple cursors are present. Allows customizing the color of a character overlapped by a block cursor.")),e.editorMultiCursorSecondaryForeground=(0,I.registerColor)("editorMultiCursor.secondary.foreground",e.editorCursorForeground,d.localize(561,"Color of secondary editor cursors when multiple cursors are present.")),e.editorMultiCursorSecondaryBackground=(0,I.registerColor)("editorMultiCursor.secondary.background",e.editorCursorBackground,d.localize(562,"The background color of secondary editor cursors when multiple cursors are present. Allows customizing the color of a character overlapped by a block cursor.")),e.editorWhitespaces=(0,I.registerColor)("editorWhitespace.foreground",{dark:"#e3e4e229",light:"#33333333",hcDark:"#e3e4e229",hcLight:"#CCCCCC"},d.localize(563,"Color of whitespace characters in the editor.")),e.editorLineNumbers=(0,I.registerColor)("editorLineNumber.foreground",{dark:"#858585",light:"#237893",hcDark:k.Color.white,hcLight:"#292929"},d.localize(564,"Color of editor line numbers.")),e.deprecatedEditorIndentGuides=(0,I.registerColor)("editorIndentGuide.background",e.editorWhitespaces,d.localize(565,"Color of the editor indentation guides."),!1,d.localize(566,"'editorIndentGuide.background' is deprecated. Use 'editorIndentGuide.background1' instead.")),e.deprecatedEditorActiveIndentGuides=(0,I.registerColor)("editorIndentGuide.activeBackground",e.editorWhitespaces,d.localize(567,"Color of the active editor indentation guides."),!1,d.localize(568,"'editorIndentGuide.activeBackground' is deprecated. Use 'editorIndentGuide.activeBackground1' instead.")),e.editorIndentGuide1=(0,I.registerColor)("editorIndentGuide.background1",e.deprecatedEditorIndentGuides,d.localize(569,"Color of the editor indentation guides (1).")),e.editorIndentGuide2=(0,I.registerColor)("editorIndentGuide.background2","#00000000",d.localize(570,"Color of the editor indentation guides (2).")),e.editorIndentGuide3=(0,I.registerColor)("editorIndentGuide.background3","#00000000",d.localize(571,"Color of the editor indentation guides (3).")),e.editorIndentGuide4=(0,I.registerColor)("editorIndentGuide.background4","#00000000",d.localize(572,"Color of the editor indentation guides (4).")),e.editorIndentGuide5=(0,I.registerColor)("editorIndentGuide.background5","#00000000",d.localize(573,"Color of the editor indentation guides (5).")),e.editorIndentGuide6=(0,I.registerColor)("editorIndentGuide.background6","#00000000",d.localize(574,"Color of the editor indentation guides (6).")),e.editorActiveIndentGuide1=(0,I.registerColor)("editorIndentGuide.activeBackground1",e.deprecatedEditorActiveIndentGuides,d.localize(575,"Color of the active editor indentation guides (1).")),e.editorActiveIndentGuide2=(0,I.registerColor)("editorIndentGuide.activeBackground2","#00000000",d.localize(576,"Color of the active editor indentation guides (2).")),e.editorActiveIndentGuide3=(0,I.registerColor)("editorIndentGuide.activeBackground3","#00000000",d.localize(577,"Color of the active editor indentation guides (3).")),e.editorActiveIndentGuide4=(0,I.registerColor)("editorIndentGuide.activeBackground4","#00000000",d.localize(578,"Color of the active editor indentation guides (4).")),e.editorActiveIndentGuide5=(0,I.registerColor)("editorIndentGuide.activeBackground5","#00000000",d.localize(579,"Color of the active editor indentation guides (5).")),e.editorActiveIndentGuide6=(0,I.registerColor)("editorIndentGuide.activeBackground6","#00000000",d.localize(580,"Color of the active editor indentation guides (6)."));const y=(0,I.registerColor)("editorActiveLineNumber.foreground",{dark:"#c6c6c6",light:"#0B216F",hcDark:I.activeContrastBorder,hcLight:I.activeContrastBorder},d.localize(581,"Color of editor active line number"),!1,d.localize(582,"Id is deprecated. Use 'editorLineNumber.activeForeground' instead."));e.editorActiveLineNumber=(0,I.registerColor)("editorLineNumber.activeForeground",y,d.localize(583,"Color of editor active line number")),e.editorDimmedLineNumber=(0,I.registerColor)("editorLineNumber.dimmedForeground",null,d.localize(584,"Color of the final editor line when editor.renderFinalNewline is set to dimmed.")),e.editorRuler=(0,I.registerColor)("editorRuler.foreground",{dark:"#5A5A5A",light:k.Color.lightgrey,hcDark:k.Color.white,hcLight:"#292929"},d.localize(585,"Color of the editor rulers.")),e.editorCodeLensForeground=(0,I.registerColor)("editorCodeLens.foreground",{dark:"#999999",light:"#919191",hcDark:"#999999",hcLight:"#292929"},d.localize(586,"Foreground color of editor CodeLens")),e.editorBracketMatchBackground=(0,I.registerColor)("editorBracketMatch.background",{dark:"#0064001a",light:"#0064001a",hcDark:"#0064001a",hcLight:"#0000"},d.localize(587,"Background color behind matching brackets")),e.editorBracketMatchBorder=(0,I.registerColor)("editorBracketMatch.border",{dark:"#888",light:"#B9B9B9",hcDark:I.contrastBorder,hcLight:I.contrastBorder},d.localize(588,"Color for matching brackets boxes")),e.editorOverviewRulerBorder=(0,I.registerColor)("editorOverviewRuler.border",{dark:"#7f7f7f4d",light:"#7f7f7f4d",hcDark:"#7f7f7f4d",hcLight:"#666666"},d.localize(589,"Color of the overview ruler border.")),e.editorOverviewRulerBackground=(0,I.registerColor)("editorOverviewRuler.background",null,d.localize(590,"Background color of the editor overview ruler.")),e.editorGutter=(0,I.registerColor)("editorGutter.background",I.editorBackground,d.localize(591,"Background color of the editor gutter. The gutter contains the glyph margins and the line numbers.")),e.editorUnnecessaryCodeBorder=(0,I.registerColor)("editorUnnecessaryCode.border",{dark:null,light:null,hcDark:k.Color.fromHex("#fff").transparent(.8),hcLight:I.contrastBorder},d.localize(592,"Border color of unnecessary (unused) source code in the editor.")),e.editorUnnecessaryCodeOpacity=(0,I.registerColor)("editorUnnecessaryCode.opacity",{dark:k.Color.fromHex("#000a"),light:k.Color.fromHex("#0007"),hcDark:null,hcLight:null},d.localize(593,`Opacity of unnecessary (unused) source code in the editor. For example, "#000000c0" will render the code with 75% opacity. For high contrast themes, use the 'editorUnnecessaryCode.border' theme color to underline unnecessary code instead of fading it out.`)),e.ghostTextBorder=(0,I.registerColor)("editorGhostText.border",{dark:null,light:null,hcDark:k.Color.fromHex("#fff").transparent(.8),hcLight:k.Color.fromHex("#292929").transparent(.8)},d.localize(594,"Border color of ghost text in the editor.")),e.ghostTextForeground=(0,I.registerColor)("editorGhostText.foreground",{dark:k.Color.fromHex("#ffffff56"),light:k.Color.fromHex("#0007"),hcDark:null,hcLight:null},d.localize(595,"Foreground color of the ghost text in the editor.")),e.ghostTextBackground=(0,I.registerColor)("editorGhostText.background",null,d.localize(596,"Background color of the ghost text in the editor."));const m=new k.Color(new k.RGBA(0,122,204,.6));e.overviewRulerRangeHighlight=(0,I.registerColor)("editorOverviewRuler.rangeHighlightForeground",m,d.localize(597,"Overview ruler marker color for range highlights. The color must not be opaque so as not to hide underlying decorations."),!0),e.overviewRulerError=(0,I.registerColor)("editorOverviewRuler.errorForeground",{dark:new k.Color(new k.RGBA(255,18,18,.7)),light:new k.Color(new k.RGBA(255,18,18,.7)),hcDark:new k.Color(new k.RGBA(255,50,50,1)),hcLight:"#B5200D"},d.localize(598,"Overview ruler marker color for errors.")),e.overviewRulerWarning=(0,I.registerColor)("editorOverviewRuler.warningForeground",{dark:I.editorWarningForeground,light:I.editorWarningForeground,hcDark:I.editorWarningBorder,hcLight:I.editorWarningBorder},d.localize(599,"Overview ruler marker color for warnings.")),e.overviewRulerInfo=(0,I.registerColor)("editorOverviewRuler.infoForeground",{dark:I.editorInfoForeground,light:I.editorInfoForeground,hcDark:I.editorInfoBorder,hcLight:I.editorInfoBorder},d.localize(600,"Overview ruler marker color for infos.")),e.editorBracketHighlightingForeground1=(0,I.registerColor)("editorBracketHighlight.foreground1",{dark:"#FFD700",light:"#0431FAFF",hcDark:"#FFD700",hcLight:"#0431FAFF"},d.localize(601,"Foreground color of brackets (1). Requires enabling bracket pair colorization.")),e.editorBracketHighlightingForeground2=(0,I.registerColor)("editorBracketHighlight.foreground2",{dark:"#DA70D6",light:"#319331FF",hcDark:"#DA70D6",hcLight:"#319331FF"},d.localize(602,"Foreground color of brackets (2). Requires enabling bracket pair colorization.")),e.editorBracketHighlightingForeground3=(0,I.registerColor)("editorBracketHighlight.foreground3",{dark:"#179FFF",light:"#7B3814FF",hcDark:"#87CEFA",hcLight:"#7B3814FF"},d.localize(603,"Foreground color of brackets (3). Requires enabling bracket pair colorization.")),e.editorBracketHighlightingForeground4=(0,I.registerColor)("editorBracketHighlight.foreground4","#00000000",d.localize(604,"Foreground color of brackets (4). Requires enabling bracket pair colorization.")),e.editorBracketHighlightingForeground5=(0,I.registerColor)("editorBracketHighlight.foreground5","#00000000",d.localize(605,"Foreground color of brackets (5). Requires enabling bracket pair colorization.")),e.editorBracketHighlightingForeground6=(0,I.registerColor)("editorBracketHighlight.foreground6","#00000000",d.localize(606,"Foreground color of brackets (6). Requires enabling bracket pair colorization.")),e.editorBracketHighlightingUnexpectedBracketForeground=(0,I.registerColor)("editorBracketHighlight.unexpectedBracket.foreground",{dark:new k.Color(new k.RGBA(255,18,18,.8)),light:new k.Color(new k.RGBA(255,18,18,.8)),hcDark:"new Color(new RGBA(255, 50, 50, 1))",hcLight:"#B5200D"},d.localize(607,"Foreground color of unexpected brackets.")),e.editorBracketPairGuideBackground1=(0,I.registerColor)("editorBracketPairGuide.background1","#00000000",d.localize(608,"Background color of inactive bracket pair guides (1). Requires enabling bracket pair guides.")),e.editorBracketPairGuideBackground2=(0,I.registerColor)("editorBracketPairGuide.background2","#00000000",d.localize(609,"Background color of inactive bracket pair guides (2). Requires enabling bracket pair guides.")),e.editorBracketPairGuideBackground3=(0,I.registerColor)("editorBracketPairGuide.background3","#00000000",d.localize(610,"Background color of inactive bracket pair guides (3). Requires enabling bracket pair guides.")),e.editorBracketPairGuideBackground4=(0,I.registerColor)("editorBracketPairGuide.background4","#00000000",d.localize(611,"Background color of inactive bracket pair guides (4). Requires enabling bracket pair guides.")),e.editorBracketPairGuideBackground5=(0,I.registerColor)("editorBracketPairGuide.background5","#00000000",d.localize(612,"Background color of inactive bracket pair guides (5). Requires enabling bracket pair guides.")),e.editorBracketPairGuideBackground6=(0,I.registerColor)("editorBracketPairGuide.background6","#00000000",d.localize(613,"Background color of inactive bracket pair guides (6). Requires enabling bracket pair guides.")),e.editorBracketPairGuideActiveBackground1=(0,I.registerColor)("editorBracketPairGuide.activeBackground1","#00000000",d.localize(614,"Background color of active bracket pair guides (1). Requires enabling bracket pair guides.")),e.editorBracketPairGuideActiveBackground2=(0,I.registerColor)("editorBracketPairGuide.activeBackground2","#00000000",d.localize(615,"Background color of active bracket pair guides (2). Requires enabling bracket pair guides.")),e.editorBracketPairGuideActiveBackground3=(0,I.registerColor)("editorBracketPairGuide.activeBackground3","#00000000",d.localize(616,"Background color of active bracket pair guides (3). Requires enabling bracket pair guides.")),e.editorBracketPairGuideActiveBackground4=(0,I.registerColor)("editorBracketPairGuide.activeBackground4","#00000000",d.localize(617,"Background color of active bracket pair guides (4). Requires enabling bracket pair guides.")),e.editorBracketPairGuideActiveBackground5=(0,I.registerColor)("editorBracketPairGuide.activeBackground5","#00000000",d.localize(618,"Background color of active bracket pair guides (5). Requires enabling bracket pair guides.")),e.editorBracketPairGuideActiveBackground6=(0,I.registerColor)("editorBracketPairGuide.activeBackground6","#00000000",d.localize(619,"Background color of active bracket pair guides (6). Requires enabling bracket pair guides.")),e.editorUnicodeHighlightBorder=(0,I.registerColor)("editorUnicodeHighlight.border",I.editorWarningForeground,d.localize(620,"Border color used to highlight unicode characters.")),e.editorUnicodeHighlightBackground=(0,I.registerColor)("editorUnicodeHighlight.background",I.editorWarningBackground,d.localize(621,"Background color used to highlight unicode characters.")),(0,E.registerThemingParticipant)((_,b)=>{const p=_.getColor(I.editorBackground),n=_.getColor(e.editorLineHighlight),o=n&&!n.isTransparent()?n:p;o&&b.addRule(`.monaco-editor .inputarea.ime-input { background-color: ${o}; }`)})}),define(ne[776],se([1,0,133,80,13,25,23,97,9,482]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CurrentLineMarginHighlightOverlay=e.CurrentLineHighlightOverlay=e.AbstractLineHighlightOverlay=void 0;class b extends d.DynamicViewOverlay{constructor(t){super(),this._context=t;const i=this._context.configuration.options,s=i.get(146);this._renderLineHighlight=i.get(97),this._renderLineHighlightOnlyWhenFocus=i.get(98),this._wordWrap=s.isViewportWrapping,this._contentLeft=s.contentLeft,this._contentWidth=s.contentWidth,this._selectionIsEmpty=!0,this._focused=!1,this._cursorLineNumbers=[1],this._selections=[new y.Selection(1,1,1,1)],this._renderData=null,this._context.addEventHandler(this)}dispose(){this._context.removeEventHandler(this),super.dispose()}_readFromSelections(){let t=!1;const i=new Set;for(const c of this._selections)i.add(c.positionLineNumber);const s=Array.from(i);s.sort((c,l)=>c-l),I.equals(this._cursorLineNumbers,s)||(this._cursorLineNumbers=s,t=!0);const g=this._selections.every(c=>c.isEmpty());return this._selectionIsEmpty!==g&&(this._selectionIsEmpty=g,t=!0),t}onThemeChanged(t){return this._readFromSelections()}onConfigurationChanged(t){const i=this._context.configuration.options,s=i.get(146);return this._renderLineHighlight=i.get(97),this._renderLineHighlightOnlyWhenFocus=i.get(98),this._wordWrap=s.isViewportWrapping,this._contentLeft=s.contentLeft,this._contentWidth=s.contentWidth,!0}onCursorStateChanged(t){return this._selections=t.selections,this._readFromSelections()}onFlushed(t){return!0}onLinesDeleted(t){return!0}onLinesInserted(t){return!0}onScrollChanged(t){return t.scrollWidthChanged||t.scrollTopChanged}onZonesChanged(t){return!0}onFocusChanged(t){return this._renderLineHighlightOnlyWhenFocus?(this._focused=t.isFocused,!0):!1}prepareRender(t){if(!this._shouldRenderThis()){this._renderData=null;return}const i=t.visibleRange.startLineNumber,s=t.visibleRange.endLineNumber,g=[];for(let l=i;l<=s;l++){const a=l-i;g[a]=""}if(this._wordWrap){const l=this._renderOne(t,!1);for(const a of this._cursorLineNumbers){const r=this._context.viewModel.coordinatesConverter,u=r.convertViewPositionToModelPosition(new _.Position(a,1)).lineNumber,C=r.convertModelPositionToViewPosition(new _.Position(u,1)).lineNumber,f=r.convertModelPositionToViewPosition(new _.Position(u,this._context.viewModel.model.getLineMaxColumn(u))).lineNumber,h=Math.max(C,i),v=Math.min(f,s);for(let w=h;w<=v;w++){const S=w-i;g[S]=l}}}const c=this._renderOne(t,!0);for(const l of this._cursorLineNumbers){if(ls)continue;const a=l-i;g[a]=c}this._renderData=g}render(t,i){if(!this._renderData)return"";const s=i-t;return s>=this._renderData.length?"":this._renderData[s]}_shouldRenderInMargin(){return(this._renderLineHighlight==="gutter"||this._renderLineHighlight==="all")&&(!this._renderLineHighlightOnlyWhenFocus||this._focused)}_shouldRenderInContent(){return(this._renderLineHighlight==="line"||this._renderLineHighlight==="all")&&this._selectionIsEmpty&&(!this._renderLineHighlightOnlyWhenFocus||this._focused)}}e.AbstractLineHighlightOverlay=b;class p extends b{_renderOne(t,i){return`
      `}_shouldRenderThis(){return this._shouldRenderInContent()}_shouldRenderOther(){return this._shouldRenderInMargin()}}e.CurrentLineHighlightOverlay=p;class n extends b{_renderOne(t,i){return`
      `}_shouldRenderThis(){return!0}_shouldRenderOther(){return this._shouldRenderInContent()}}e.CurrentLineMarginHighlightOverlay=n,(0,E.registerThemingParticipant)((o,t)=>{const i=o.getColor(k.editorLineHighlight);if(i&&(t.addRule(`.monaco-editor .view-overlays .current-line { background-color: ${i}; }`),t.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { background-color: ${i}; border: none; }`)),!i||i.isTransparent()||o.defines(k.editorLineHighlightBorder)){const s=o.getColor(k.editorLineHighlightBorder);s&&(t.addRule(`.monaco-editor .view-overlays .current-line-exact { border: 2px solid ${s}; }`),t.addRule(`.monaco-editor .margin-view-overlays .current-line-exact-margin { border: 2px solid ${s}; }`),(0,m.isHighContrast)(o.type)&&(t.addRule(".monaco-editor .view-overlays .current-line-exact { border-width: 1px; }"),t.addRule(".monaco-editor .margin-view-overlays .current-line-exact-margin { border-width: 1px; }")))}})}),define(ne[777],se([1,0,133,80,25,9,13,19,329,239,485]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IndentGuidesOverlay=void 0;class p extends d.DynamicViewOverlay{constructor(t){super(),this._context=t,this._primaryPosition=null;const i=this._context.configuration.options,s=i.get(147),g=i.get(50);this._spaceWidth=g.spaceWidth,this._maxIndentLeft=s.wrappingColumn===-1?-1:s.wrappingColumn*g.typicalHalfwidthCharacterWidth,this._bracketPairGuideOptions=i.get(16),this._renderResult=null,this._context.addEventHandler(this)}dispose(){this._context.removeEventHandler(this),this._renderResult=null,super.dispose()}onConfigurationChanged(t){const i=this._context.configuration.options,s=i.get(147),g=i.get(50);return this._spaceWidth=g.spaceWidth,this._maxIndentLeft=s.wrappingColumn===-1?-1:s.wrappingColumn*g.typicalHalfwidthCharacterWidth,this._bracketPairGuideOptions=i.get(16),!0}onCursorStateChanged(t){const s=t.selections[0].getPosition();return this._primaryPosition?.equals(s)?!1:(this._primaryPosition=s,!0)}onDecorationsChanged(t){return!0}onFlushed(t){return!0}onLinesChanged(t){return!0}onLinesDeleted(t){return!0}onLinesInserted(t){return!0}onScrollChanged(t){return t.scrollTopChanged}onZonesChanged(t){return!0}onLanguageConfigurationChanged(t){return!0}prepareRender(t){if(!this._bracketPairGuideOptions.indentation&&this._bracketPairGuideOptions.bracketPairs===!1){this._renderResult=null;return}const i=t.visibleRange.startLineNumber,s=t.visibleRange.endLineNumber,g=t.scrollWidth,c=this._primaryPosition,l=this.getGuidesByLine(i,Math.min(s+1,this._context.viewModel.getLineCount()),c),a=[];for(let r=i;r<=s;r++){const u=r-i,C=l[u];let f="";const h=t.visibleRangeForPosition(new E.Position(r,1))?.left??0;for(const v of C){const w=v.column===-1?h+(v.visibleColumn-1)*this._spaceWidth:t.visibleRangeForPosition(new E.Position(r,v.column)).left;if(w>g||this._maxIndentLeft>0&&w>this._maxIndentLeft)break;const S=v.horizontalLine?v.horizontalLine.top?"horizontal-top":"horizontal-bottom":"vertical",L=v.horizontalLine?(t.visibleRangeForPosition(new E.Position(r,v.horizontalLine.endColumn))?.left??w+this._spaceWidth)-w:this._spaceWidth;f+=`
      `}a[u]=f}this._renderResult=a}getGuidesByLine(t,i,s){const g=this._bracketPairGuideOptions.bracketPairs!==!1?this._context.viewModel.getBracketGuidesInRangeByLine(t,i,s,{highlightActive:this._bracketPairGuideOptions.highlightActiveBracketPair,horizontalGuides:this._bracketPairGuideOptions.bracketPairsHorizontal===!0?b.HorizontalGuidesState.Enabled:this._bracketPairGuideOptions.bracketPairsHorizontal==="active"?b.HorizontalGuidesState.EnabledForActive:b.HorizontalGuidesState.Disabled,includeInactive:this._bracketPairGuideOptions.bracketPairs===!0}):null,c=this._bracketPairGuideOptions.indentation?this._context.viewModel.getLinesIndentGuides(t,i):null;let l=0,a=0,r=0;if(this._bracketPairGuideOptions.highlightActiveIndentation!==!1&&s){const f=this._context.viewModel.getActiveIndentGuide(s.lineNumber,t,i);l=f.startLineNumber,a=f.endLineNumber,r=f.indent}const{indentSize:u}=this._context.viewModel.model.getOptions(),C=[];for(let f=t;f<=i;f++){const h=new Array;C.push(h);const v=g?g[f-t]:[],w=new y.ArrayQueue(v),S=c?c[f-t]:0;for(let L=1;L<=S;L++){const D=(L-1)*u+1,T=(this._bracketPairGuideOptions.highlightActiveIndentation==="always"||v.length===0)&&l<=f&&f<=a&&L===r;h.push(...w.takeWhile(A=>A.visibleColumn!0)||[])}return C}render(t,i){if(!this._renderResult)return"";const s=i-t;return s<0||s>=this._renderResult.length?"":this._renderResult[s]}}e.IndentGuidesOverlay=p;function n(o){if(!(o&&o.isTransparent()))return o}(0,I.registerThemingParticipant)((o,t)=>{const i=[{bracketColor:k.editorBracketHighlightingForeground1,guideColor:k.editorBracketPairGuideBackground1,guideColorActive:k.editorBracketPairGuideActiveBackground1},{bracketColor:k.editorBracketHighlightingForeground2,guideColor:k.editorBracketPairGuideBackground2,guideColorActive:k.editorBracketPairGuideActiveBackground2},{bracketColor:k.editorBracketHighlightingForeground3,guideColor:k.editorBracketPairGuideBackground3,guideColorActive:k.editorBracketPairGuideActiveBackground3},{bracketColor:k.editorBracketHighlightingForeground4,guideColor:k.editorBracketPairGuideBackground4,guideColorActive:k.editorBracketPairGuideActiveBackground4},{bracketColor:k.editorBracketHighlightingForeground5,guideColor:k.editorBracketPairGuideBackground5,guideColorActive:k.editorBracketPairGuideActiveBackground5},{bracketColor:k.editorBracketHighlightingForeground6,guideColor:k.editorBracketPairGuideBackground6,guideColorActive:k.editorBracketPairGuideActiveBackground6}],s=new _.BracketPairGuidesClassNames,g=[{indentColor:k.editorIndentGuide1,indentColorActive:k.editorActiveIndentGuide1},{indentColor:k.editorIndentGuide2,indentColorActive:k.editorActiveIndentGuide2},{indentColor:k.editorIndentGuide3,indentColorActive:k.editorActiveIndentGuide3},{indentColor:k.editorIndentGuide4,indentColorActive:k.editorActiveIndentGuide4},{indentColor:k.editorIndentGuide5,indentColorActive:k.editorActiveIndentGuide5},{indentColor:k.editorIndentGuide6,indentColorActive:k.editorActiveIndentGuide6}],c=i.map(a=>{const r=o.getColor(a.bracketColor),u=o.getColor(a.guideColor),C=o.getColor(a.guideColorActive),f=n(n(u)??r?.transparent(.3)),h=n(n(C)??r);if(!(!f||!h))return{guideColor:f,guideColorActive:h}}).filter(m.isDefined),l=g.map(a=>{const r=o.getColor(a.indentColor),u=o.getColor(a.indentColorActive),C=n(r),f=n(u);if(!(!C||!f))return{indentColor:C,indentColorActive:f}}).filter(m.isDefined);if(c.length>0){for(let a=0;a<30;a++){const r=c[a%c.length];t.addRule(`.monaco-editor .${s.getInlineClassNameOfLevel(a).replace(/ /g,".")} { --guide-color: ${r.guideColor}; --guide-color-active: ${r.guideColorActive}; }`)}t.addRule(".monaco-editor .vertical { box-shadow: 1px 0 0 0 var(--guide-color) inset; }"),t.addRule(".monaco-editor .horizontal-top { border-top: 1px solid var(--guide-color); }"),t.addRule(".monaco-editor .horizontal-bottom { border-bottom: 1px solid var(--guide-color); }"),t.addRule(`.monaco-editor .vertical.${s.activeClassName} { box-shadow: 1px 0 0 0 var(--guide-color-active) inset; }`),t.addRule(`.monaco-editor .horizontal-top.${s.activeClassName} { border-top: 1px solid var(--guide-color-active); }`),t.addRule(`.monaco-editor .horizontal-bottom.${s.activeClassName} { border-bottom: 1px solid var(--guide-color-active); }`)}if(l.length>0){for(let a=0;a<30;a++){const r=l[a%l.length];t.addRule(`.monaco-editor .lines-content .core-guide-indent.lvl-${a} { --indent-color: ${r.indentColor}; --indent-color-active: ${r.indentColorActive}; }`)}t.addRule(".monaco-editor .lines-content .core-guide-indent { box-shadow: 1px 0 0 0 var(--indent-color) inset; }"),t.addRule(".monaco-editor .lines-content .core-guide-indent.indent-active { box-shadow: 1px 0 0 0 var(--indent-color-active) inset; }")}})}),define(ne[416],se([1,0,16,133,9,4,25,80,486]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.LineNumbersOverlay=void 0;class _ extends k.DynamicViewOverlay{static{this.CLASS_NAME="line-numbers"}constructor(p){super(),this._context=p,this._readConfig(),this._lastCursorModelPosition=new I.Position(1,1),this._renderResult=null,this._activeLineNumber=1,this._context.addEventHandler(this)}_readConfig(){const p=this._context.configuration.options;this._lineHeight=p.get(67);const n=p.get(68);this._renderLineNumbers=n.renderType,this._renderCustomLineNumbers=n.renderFn,this._renderFinalNewline=p.get(96);const o=p.get(146);this._lineNumbersLeft=o.lineNumbersLeft,this._lineNumbersWidth=o.lineNumbersWidth}dispose(){this._context.removeEventHandler(this),this._renderResult=null,super.dispose()}onConfigurationChanged(p){return this._readConfig(),!0}onCursorStateChanged(p){const n=p.selections[0].getPosition();this._lastCursorModelPosition=this._context.viewModel.coordinatesConverter.convertViewPositionToModelPosition(n);let o=!1;return this._activeLineNumber!==n.lineNumber&&(this._activeLineNumber=n.lineNumber,o=!0),(this._renderLineNumbers===2||this._renderLineNumbers===3)&&(o=!0),o}onFlushed(p){return!0}onLinesChanged(p){return!0}onLinesDeleted(p){return!0}onLinesInserted(p){return!0}onScrollChanged(p){return p.scrollTopChanged}onZonesChanged(p){return!0}onDecorationsChanged(p){return p.affectsLineNumber}_getLineRenderLineNumber(p){const n=this._context.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new I.Position(p,1));if(n.column!==1)return"";const o=n.lineNumber;if(this._renderCustomLineNumbers)return this._renderCustomLineNumbers(o);if(this._renderLineNumbers===2){const t=Math.abs(this._lastCursorModelPosition.lineNumber-o);return t===0?''+o+"":String(t)}if(this._renderLineNumbers===3){if(this._lastCursorModelPosition.lineNumber===o||o%10===0)return String(o);const t=this._context.viewModel.getLineCount();return o===t?String(o):""}return String(o)}prepareRender(p){if(this._renderLineNumbers===0){this._renderResult=null;return}const n=d.isLinux?this._lineHeight%2===0?" lh-even":" lh-odd":"",o=p.visibleRange.startLineNumber,t=p.visibleRange.endLineNumber,i=this._context.viewModel.getDecorationsInViewport(p.visibleRange).filter(l=>!!l.options.lineNumberClassName);i.sort((l,a)=>E.Range.compareRangesUsingEnds(l.range,a.range));let s=0;const g=this._context.viewModel.getLineCount(),c=[];for(let l=o;l<=t;l++){const a=l-o;let r=this._getLineRenderLineNumber(l),u="";for(;s${r}`}this._renderResult=c}render(p,n){if(!this._renderResult)return"";const o=n-p;return o<0||o>=this._renderResult.length?"":this._renderResult[o]}}e.LineNumbersOverlay=_,(0,y.registerThemingParticipant)((b,p)=>{const n=b.getColor(m.editorLineNumbers),o=b.getColor(m.editorDimmedLineNumber);o?p.addRule(`.monaco-editor .line-numbers.dimmed-line-number { color: ${o}; }`):n&&p.addRule(`.monaco-editor .line-numbers.dimmed-line-number { color: ${n.transparent(.4)}; }`)})}),define(ne[778],se([1,0,3,64,39,16,11,74,212,310,56,416,331,37,166,9,4,23,226,27,33,300,31,7,479]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TextAreaHandler=void 0;class h{constructor(D,T,M,A,P){this._context=D,this.modelLineNumber=T,this.distanceToModelLineStart=M,this.widthOfHiddenLineTextBefore=A,this.distanceToModelLineEnd=P,this._visibleTextAreaBrand=void 0,this.startPosition=null,this.endPosition=null,this.visibleTextareaStart=null,this.visibleTextareaEnd=null,this._previousPresentation=null}prepareRender(D){const T=new s.Position(this.modelLineNumber,this.distanceToModelLineStart+1),M=new s.Position(this.modelLineNumber,this._context.viewModel.model.getLineMaxColumn(this.modelLineNumber)-this.distanceToModelLineEnd);this.startPosition=this._context.viewModel.coordinatesConverter.convertModelPositionToViewPosition(T),this.endPosition=this._context.viewModel.coordinatesConverter.convertModelPositionToViewPosition(M),this.startPosition.lineNumber===this.endPosition.lineNumber?(this.visibleTextareaStart=D.visibleRangeForPosition(this.startPosition),this.visibleTextareaEnd=D.visibleRangeForPosition(this.endPosition)):(this.visibleTextareaStart=null,this.visibleTextareaEnd=null)}definePresentation(D){return this._previousPresentation||(D?this._previousPresentation=D:this._previousPresentation={foreground:1,italic:!1,bold:!1,underline:!1,strikethrough:!1}),this._previousPresentation}}const v=k.isFirefox;let w=class extends p.ViewPart{constructor(D,T,M,A,P){super(D),this._keybindingService=A,this._instantiationService=P,this._primaryCursorPosition=new s.Position(1,1),this._primaryCursorVisibleRange=null,this._viewController=T,this._visibleRangeProvider=M,this._scrollLeft=0,this._scrollTop=0;const N=this._context.configuration.options,O=N.get(146);this._setAccessibilityOptions(N),this._contentLeft=O.contentLeft,this._contentWidth=O.contentWidth,this._contentHeight=O.height,this._fontInfo=N.get(50),this._lineHeight=N.get(67),this._emptySelectionClipboard=N.get(37),this._copyWithSyntaxHighlighting=N.get(25),this._visibleTextArea=null,this._selections=[new c.Selection(1,1,1,1)],this._modelSelections=[new c.Selection(1,1,1,1)],this._lastRenderPosition=null,this.textArea=(0,I.createFastDomNode)(document.createElement("textarea")),p.PartFingerprints.write(this.textArea,7),this.textArea.setClassName(`inputarea ${l.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`),this.textArea.setAttribute("wrap",this._textAreaWrapping&&!this._visibleTextArea?"on":"off");const{tabSize:F}=this._context.viewModel.model.getOptions();this.textArea.domNode.style.tabSize=`${F*this._fontInfo.spaceWidth}px`,this.textArea.setAttribute("autocorrect","off"),this.textArea.setAttribute("autocapitalize","off"),this.textArea.setAttribute("autocomplete","off"),this.textArea.setAttribute("spellcheck","false"),this.textArea.setAttribute("aria-label",this._getAriaLabel(N)),this.textArea.setAttribute("aria-required",N.get(5)?"true":"false"),this.textArea.setAttribute("tabindex",String(N.get(125))),this.textArea.setAttribute("role","textbox"),this.textArea.setAttribute("aria-roledescription",d.localize(54,"editor")),this.textArea.setAttribute("aria-multiline","true"),this.textArea.setAttribute("aria-autocomplete",N.get(92)?"none":"both"),this._ensureReadOnlyAttribute(),this.textAreaCover=(0,I.createFastDomNode)(document.createElement("div")),this.textAreaCover.setPosition("absolute");const x={getLineCount:()=>this._context.viewModel.getLineCount(),getLineMaxColumn:q=>this._context.viewModel.getLineMaxColumn(q),getValueInRange:(q,H)=>this._context.viewModel.getValueInRange(q,H),getValueLengthInRange:(q,H)=>this._context.viewModel.getValueLengthInRange(q,H),modifyPosition:(q,H)=>this._context.viewModel.modifyPosition(q,H)},W={getDataToCopy:()=>{const q=this._context.viewModel.getPlainTextToCopy(this._modelSelections,this._emptySelectionClipboard,E.isWindows),H=this._context.viewModel.model.getEOL(),z=this._emptySelectionClipboard&&this._modelSelections.length===1&&this._modelSelections[0].isEmpty(),U=Array.isArray(q)?q:null,j=Array.isArray(q)?q.join(H):q;let Y,G=null;if(_.CopyOptions.forceCopyWithSyntaxHighlighting||this._copyWithSyntaxHighlighting&&j.length<65536){const K=this._context.viewModel.getRichTextToCopy(this._modelSelections,this._emptySelectionClipboard);K&&(Y=K.html,G=K.mode)}return{isFromEmptySelection:z,multicursorText:U,text:j,html:Y,mode:G}},getScreenReaderContent:()=>{if(this._accessibilitySupport===1){const q=this._selections[0];if(E.isMacintosh&&q.isEmpty()){const z=q.getStartPosition();let U=this._getWordBeforePosition(z);if(U.length===0&&(U=this._getCharacterBeforePosition(z)),U.length>0)return new b.TextAreaState(U,U.length,U.length,g.Range.fromPositions(z),0)}if(E.isMacintosh&&!q.isEmpty()&&x.getValueLengthInRange(q,0)<500){const z=x.getValueInRange(q,0);return new b.TextAreaState(z,0,z.length,q,0)}if(k.isSafari&&!q.isEmpty()){const z="vscode-placeholder";return new b.TextAreaState(z,0,z.length,null,void 0)}return b.TextAreaState.EMPTY}if(k.isAndroid){const q=this._selections[0];if(q.isEmpty()){const H=q.getStartPosition(),[z,U]=this._getAndroidWordAtPosition(H);if(z.length>0)return new b.TextAreaState(z,U,U,g.Range.fromPositions(H),0)}return b.TextAreaState.EMPTY}return b.PagedScreenReaderStrategy.fromEditorSelection(x,this._selections[0],this._accessibilityPageSize,this._accessibilitySupport===0)},deduceModelPosition:(q,H,z)=>this._context.viewModel.deduceModelPositionRelativeToViewPosition(q,H,z)},V=this._register(new _.TextAreaWrapper(this.textArea.domNode));this._textAreaInput=this._register(this._instantiationService.createInstance(_.TextAreaInput,W,V,E.OS,{isAndroid:k.isAndroid,isChrome:k.isChrome,isFirefox:k.isFirefox,isSafari:k.isSafari})),this._register(this._textAreaInput.onKeyDown(q=>{this._viewController.emitKeyDown(q)})),this._register(this._textAreaInput.onKeyUp(q=>{this._viewController.emitKeyUp(q)})),this._register(this._textAreaInput.onPaste(q=>{let H=!1,z=null,U=null;q.metadata&&(H=this._emptySelectionClipboard&&!!q.metadata.isFromEmptySelection,z=typeof q.metadata.multicursorText<"u"?q.metadata.multicursorText:null,U=q.metadata.mode),this._viewController.paste(q.text,H,z,U)})),this._register(this._textAreaInput.onCut(()=>{this._viewController.cut()})),this._register(this._textAreaInput.onType(q=>{q.replacePrevCharCnt||q.replaceNextCharCnt||q.positionDelta?(b._debugComposition&&console.log(` => compositionType: <<${q.text}>>, ${q.replacePrevCharCnt}, ${q.replaceNextCharCnt}, ${q.positionDelta}`),this._viewController.compositionType(q.text,q.replacePrevCharCnt,q.replaceNextCharCnt,q.positionDelta)):(b._debugComposition&&console.log(` => type: <<${q.text}>>`),this._viewController.type(q.text))})),this._register(this._textAreaInput.onSelectionChangeRequest(q=>{this._viewController.setSelection(q)})),this._register(this._textAreaInput.onCompositionStart(q=>{const H=this.textArea.domNode,z=this._modelSelections[0],{distanceToModelLineStart:U,widthOfHiddenTextBefore:j}=(()=>{const G=H.value.substring(0,Math.min(H.selectionStart,H.selectionEnd)),K=G.lastIndexOf(` `),R=G.substring(K+1),J=R.lastIndexOf(" "),ie=R.length-J-1,ue=z.getStartPosition(),he=Math.min(ue.column-1,ie),pe=ue.column-1-he,ae=R.substring(0,R.length-he),{tabSize:ee}=this._context.viewModel.model.getOptions(),de=S(this.textArea.domNode.ownerDocument,ae,this._fontInfo,ee);return{distanceToModelLineStart:pe,widthOfHiddenTextBefore:de}})(),{distanceToModelLineEnd:Y}=(()=>{const G=H.value.substring(Math.max(H.selectionStart,H.selectionEnd)),K=G.indexOf(` `),R=K===-1?G:G.substring(0,K),J=R.indexOf(" "),ie=J===-1?R.length:R.length-J-1,ue=z.getEndPosition(),he=Math.min(this._context.viewModel.model.getLineMaxColumn(ue.lineNumber)-ue.column,ie);return{distanceToModelLineEnd:this._context.viewModel.model.getLineMaxColumn(ue.lineNumber)-ue.column-he}})();this._context.viewModel.revealRange("keyboard",!0,g.Range.fromPositions(this._selections[0].getStartPosition()),0,1),this._visibleTextArea=new h(this._context,z.startLineNumber,U,j,Y),this.textArea.setAttribute("wrap",this._textAreaWrapping&&!this._visibleTextArea?"on":"off"),this._visibleTextArea.prepareRender(this._visibleRangeProvider),this._render(),this.textArea.setClassName(`inputarea ${l.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME} ime-input`),this._viewController.compositionStart(),this._context.viewModel.onCompositionStart()})),this._register(this._textAreaInput.onCompositionUpdate(q=>{this._visibleTextArea&&(this._visibleTextArea.prepareRender(this._visibleRangeProvider),this._render())})),this._register(this._textAreaInput.onCompositionEnd(()=>{this._visibleTextArea=null,this.textArea.setAttribute("wrap",this._textAreaWrapping&&!this._visibleTextArea?"on":"off"),this._render(),this.textArea.setClassName(`inputarea ${l.MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`),this._viewController.compositionEnd(),this._context.viewModel.onCompositionEnd()})),this._register(this._textAreaInput.onFocus(()=>{this._context.viewModel.setHasFocus(!0)})),this._register(this._textAreaInput.onBlur(()=>{this._context.viewModel.setHasFocus(!1)})),this._register(u.IME.onDidChange(()=>{this._ensureReadOnlyAttribute()}))}writeScreenReaderContent(D){this._textAreaInput.writeNativeTextAreaContent(D)}dispose(){super.dispose()}_getAndroidWordAtPosition(D){const T='`~!@#$%^&*()-=+[{]}\\|;:",.<>/?',M=this._context.viewModel.getLineContent(D.lineNumber),A=(0,i.getMapForWordSeparators)(T,[]);let P=!0,N=D.column,O=!0,F=D.column,x=0;for(;x<50&&(P||O);){if(P&&N<=1&&(P=!1),P){const W=M.charCodeAt(N-2);A.get(W)!==0?P=!1:N--}if(O&&F>M.length&&(O=!1),O){const W=M.charCodeAt(F-1);A.get(W)!==0?O=!1:F++}x++}return[M.substring(N-1,F-1),D.column-N]}_getWordBeforePosition(D){const T=this._context.viewModel.getLineContent(D.lineNumber),M=(0,i.getMapForWordSeparators)(this._context.configuration.options.get(132),[]);let A=D.column,P=0;for(;A>1;){const N=T.charCodeAt(A-2);if(M.get(N)!==0||P>50)return T.substring(A-1,D.column-1);P++,A--}return T.substring(0,D.column-1)}_getCharacterBeforePosition(D){if(D.column>1){const M=this._context.viewModel.getLineContent(D.lineNumber).charAt(D.column-2);if(!y.isHighSurrogate(M.charCodeAt(0)))return M}return""}_getAriaLabel(D){if(D.get(2)===1){const M=this._keybindingService.lookupKeybinding("editor.action.toggleScreenReaderAccessibilityMode")?.getAriaLabel(),A=this._keybindingService.lookupKeybinding("workbench.action.showCommands")?.getAriaLabel(),P=this._keybindingService.lookupKeybinding("workbench.action.openGlobalKeybindings")?.getAriaLabel(),N=d.localize(55,"The editor is not accessible at this time.");return M?d.localize(56,"{0} To enable screen reader optimized mode, use {1}",N,M):A?d.localize(57,"{0} To enable screen reader optimized mode, open the quick pick with {1} and run the command Toggle Screen Reader Accessibility Mode, which is currently not triggerable via keyboard.",N,A):P?d.localize(58,"{0} Please assign a keybinding for the command Toggle Screen Reader Accessibility Mode by accessing the keybindings editor with {1} and run it.",N,P):N}return D.get(4)}_setAccessibilityOptions(D){this._accessibilitySupport=D.get(2);const T=D.get(3);this._accessibilitySupport===2&&T===t.EditorOptions.accessibilityPageSize.defaultValue?this._accessibilityPageSize=500:this._accessibilityPageSize=T;const A=D.get(146).wrappingColumn;if(A!==-1&&this._accessibilitySupport!==1){const P=D.get(50);this._textAreaWrapping=!0,this._textAreaWidth=Math.round(A*P.typicalHalfwidthCharacterWidth)}else this._textAreaWrapping=!1,this._textAreaWidth=v?0:1}onConfigurationChanged(D){const T=this._context.configuration.options,M=T.get(146);this._setAccessibilityOptions(T),this._contentLeft=M.contentLeft,this._contentWidth=M.contentWidth,this._contentHeight=M.height,this._fontInfo=T.get(50),this._lineHeight=T.get(67),this._emptySelectionClipboard=T.get(37),this._copyWithSyntaxHighlighting=T.get(25),this.textArea.setAttribute("wrap",this._textAreaWrapping&&!this._visibleTextArea?"on":"off");const{tabSize:A}=this._context.viewModel.model.getOptions();return this.textArea.domNode.style.tabSize=`${A*this._fontInfo.spaceWidth}px`,this.textArea.setAttribute("aria-label",this._getAriaLabel(T)),this.textArea.setAttribute("aria-required",T.get(5)?"true":"false"),this.textArea.setAttribute("tabindex",String(T.get(125))),(D.hasChanged(34)||D.hasChanged(92))&&this._ensureReadOnlyAttribute(),D.hasChanged(2)&&this._textAreaInput.writeNativeTextAreaContent("strategy changed"),!0}onCursorStateChanged(D){return this._selections=D.selections.slice(0),this._modelSelections=D.modelSelections.slice(0),this._textAreaInput.writeNativeTextAreaContent("selection changed"),!0}onDecorationsChanged(D){return!0}onFlushed(D){return!0}onLinesChanged(D){return!0}onLinesDeleted(D){return!0}onLinesInserted(D){return!0}onScrollChanged(D){return this._scrollLeft=D.scrollLeft,this._scrollTop=D.scrollTop,!0}onZonesChanged(D){return!0}isFocused(){return this._textAreaInput.isFocused()}focusTextArea(){this._textAreaInput.focusTextArea()}getLastRenderData(){return this._lastRenderPosition}setAriaOptions(D){D.activeDescendant?(this.textArea.setAttribute("aria-haspopup","true"),this.textArea.setAttribute("aria-autocomplete","list"),this.textArea.setAttribute("aria-activedescendant",D.activeDescendant)):(this.textArea.setAttribute("aria-haspopup","false"),this.textArea.setAttribute("aria-autocomplete","both"),this.textArea.removeAttribute("aria-activedescendant")),D.role&&this.textArea.setAttribute("role",D.role)}_ensureReadOnlyAttribute(){const D=this._context.configuration.options;!u.IME.enabled||D.get(34)&&D.get(92)?this.textArea.setAttribute("readonly","true"):this.textArea.removeAttribute("readonly")}prepareRender(D){this._primaryCursorPosition=new s.Position(this._selections[0].positionLineNumber,this._selections[0].positionColumn),this._primaryCursorVisibleRange=D.visibleRangeForPosition(this._primaryCursorPosition),this._visibleTextArea?.prepareRender(D)}render(D){this._textAreaInput.writeNativeTextAreaContent("render"),this._render()}_render(){if(this._visibleTextArea){const M=this._visibleTextArea.visibleTextareaStart,A=this._visibleTextArea.visibleTextareaEnd,P=this._visibleTextArea.startPosition,N=this._visibleTextArea.endPosition;if(P&&N&&M&&A&&A.left>=this._scrollLeft&&M.left<=this._scrollLeft+this._contentWidth){const O=this._context.viewLayout.getVerticalOffsetForLineNumber(this._primaryCursorPosition.lineNumber)-this._scrollTop,F=this._newlinecount(this.textArea.domNode.value.substr(0,this.textArea.domNode.selectionStart));let x=this._visibleTextArea.widthOfHiddenLineTextBefore,W=this._contentLeft+M.left-this._scrollLeft,V=A.left-M.left+1;if(Wthis._contentWidth&&(V=this._contentWidth);const q=this._context.viewModel.getViewLineData(P.lineNumber),H=q.tokens.findTokenIndexAtOffset(P.column-1),z=q.tokens.findTokenIndexAtOffset(N.column-1),U=H===z,j=this._visibleTextArea.definePresentation(U?q.tokens.getPresentation(H):null);this.textArea.domNode.scrollTop=F*this._lineHeight,this.textArea.domNode.scrollLeft=x,this._doRender({lastRenderPosition:null,top:O,left:W,width:V,height:this._lineHeight,useCover:!1,color:(a.TokenizationRegistry.getColorMap()||[])[j.foreground],italic:j.italic,bold:j.bold,underline:j.underline,strikethrough:j.strikethrough})}return}if(!this._primaryCursorVisibleRange){this._renderAtTopLeft();return}const D=this._contentLeft+this._primaryCursorVisibleRange.left-this._scrollLeft;if(Dthis._contentLeft+this._contentWidth){this._renderAtTopLeft();return}const T=this._context.viewLayout.getVerticalOffsetForLineNumber(this._selections[0].positionLineNumber)-this._scrollTop;if(T<0||T>this._contentHeight){this._renderAtTopLeft();return}if(E.isMacintosh||this._accessibilitySupport===2){this._doRender({lastRenderPosition:this._primaryCursorPosition,top:T,left:this._textAreaWrapping?this._contentLeft:D,width:this._textAreaWidth,height:this._lineHeight,useCover:!1}),this.textArea.domNode.scrollLeft=this._primaryCursorVisibleRange.left;const M=this._textAreaInput.textAreaState.newlineCountBeforeSelection??this._newlinecount(this.textArea.domNode.value.substr(0,this.textArea.domNode.selectionStart));this.textArea.domNode.scrollTop=M*this._lineHeight;return}this._doRender({lastRenderPosition:this._primaryCursorPosition,top:T,left:this._textAreaWrapping?this._contentLeft:D,width:this._textAreaWidth,height:v?0:1,useCover:!1})}_newlinecount(D){let T=0,M=-1;do{if(M=D.indexOf(` `,M+1),M===-1)break;T++}while(!0);return T}_renderAtTopLeft(){this._doRender({lastRenderPosition:null,top:0,left:0,width:this._textAreaWidth,height:v?0:1,useCover:!0})}_doRender(D){this._lastRenderPosition=D.lastRenderPosition;const T=this.textArea,M=this.textAreaCover;(0,m.applyFontInfo)(T,this._fontInfo),T.setTop(D.top),T.setLeft(D.left),T.setWidth(D.width),T.setHeight(D.height),T.setColor(D.color?r.Color.Format.CSS.formatHex(D.color):""),T.setFontStyle(D.italic?"italic":""),D.bold&&T.setFontWeight("bold"),T.setTextDecoration(`${D.underline?" underline":""}${D.strikethrough?" line-through":""}`),M.setTop(D.useCover?D.top:0),M.setLeft(D.useCover?D.left:0),M.setWidth(D.useCover?D.width:0),M.setHeight(D.useCover?D.height:0);const A=this._context.configuration.options;A.get(57)?M.setClassName("monaco-editor-background textAreaCover "+o.Margin.OUTER_CLASS_NAME):A.get(68).renderType!==0?M.setClassName("monaco-editor-background textAreaCover "+n.LineNumbersOverlay.CLASS_NAME):M.setClassName("monaco-editor-background textAreaCover")}};e.TextAreaHandler=w,e.TextAreaHandler=w=ke([ce(3,C.IKeybindingService),ce(4,f.IInstantiationService)],w);function S(L,D,T,M){if(D.length===0)return 0;const A=L.createElement("div");A.style.position="absolute",A.style.top="-50000px",A.style.width="50000px";const P=L.createElement("span");(0,m.applyFontInfo)(P,T),P.style.whiteSpace="pre",P.style.tabSize=`${M*T.spaceWidth}px`,P.append(D),A.appendChild(P),L.body.appendChild(A);const N=P.offsetWidth;return A.remove(),N}}),define(ne[779],se([1,0,39,33,56,9,27,80,95,13]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DecorationsOverviewRuler=void 0;class p{constructor(t,i){const s=t.options;this.lineHeight=s.get(67),this.pixelRatio=s.get(144),this.overviewRulerLanes=s.get(83),this.renderBorder=s.get(82);const g=i.getColor(m.editorOverviewRulerBorder);this.borderColor=g?g.toString():null,this.hideCursor=s.get(59);const c=i.getColor(m.editorCursorForeground);this.cursorColorSingle=c?c.transparent(.7).toString():null;const l=i.getColor(m.editorMultiCursorPrimaryForeground);this.cursorColorPrimary=l?l.transparent(.7).toString():null;const a=i.getColor(m.editorMultiCursorSecondaryForeground);this.cursorColorSecondary=a?a.transparent(.7).toString():null,this.themeType=i.type;const r=s.get(73),u=r.enabled,C=r.side,f=i.getColor(m.editorOverviewRulerBackground),h=y.TokenizationRegistry.getDefaultBackground();f?this.backgroundColor=f:u&&C==="right"?this.backgroundColor=h:this.backgroundColor=null;const w=s.get(146).overviewRuler;this.top=w.top,this.right=w.right,this.domWidth=w.width,this.domHeight=w.height,this.overviewRulerLanes===0?(this.canvasWidth=0,this.canvasHeight=0):(this.canvasWidth=this.domWidth*this.pixelRatio|0,this.canvasHeight=this.domHeight*this.pixelRatio|0);const[S,L]=this._initLanes(1,this.canvasWidth,this.overviewRulerLanes);this.x=S,this.w=L}_initLanes(t,i,s){const g=i-t;if(s>=3){const c=Math.floor(g/3),l=Math.floor(g/3),a=g-c-l,r=t,u=r+c,C=r+c+a;return[[0,r,u,r,C,r,u,r],[0,c,a,c+a,l,c+a+l,a+l,c+a+l]]}else if(s===2){const c=Math.floor(g/2),l=g-c,a=t,r=a+c;return[[0,a,a,a,r,a,a,a],[0,c,c,c,l,c+l,c+l,c+l]]}else{const c=t,l=g;return[[0,c,c,c,c,c,c,c],[0,l,l,l,l,l,l,l]]}}equals(t){return this.lineHeight===t.lineHeight&&this.pixelRatio===t.pixelRatio&&this.overviewRulerLanes===t.overviewRulerLanes&&this.renderBorder===t.renderBorder&&this.borderColor===t.borderColor&&this.hideCursor===t.hideCursor&&this.cursorColorSingle===t.cursorColorSingle&&this.cursorColorPrimary===t.cursorColorPrimary&&this.cursorColorSecondary===t.cursorColorSecondary&&this.themeType===t.themeType&&k.Color.equals(this.backgroundColor,t.backgroundColor)&&this.top===t.top&&this.right===t.right&&this.domWidth===t.domWidth&&this.domHeight===t.domHeight&&this.canvasWidth===t.canvasWidth&&this.canvasHeight===t.canvasHeight}}class n extends I.ViewPart{constructor(t){super(t),this._actualShouldRender=0,this._renderedDecorations=[],this._renderedCursorPositions=[],this._domNode=(0,d.createFastDomNode)(document.createElement("canvas")),this._domNode.setClassName("decorationsOverviewRuler"),this._domNode.setPosition("absolute"),this._domNode.setLayerHinting(!0),this._domNode.setContain("strict"),this._domNode.setAttribute("aria-hidden","true"),this._updateSettings(!1),this._tokensColorTrackerListener=y.TokenizationRegistry.onDidChange(i=>{i.changedColorMap&&this._updateSettings(!0)}),this._cursorPositions=[{position:new E.Position(1,1),color:this._settings.cursorColorSingle}]}dispose(){super.dispose(),this._tokensColorTrackerListener.dispose()}_updateSettings(t){const i=new p(this._context.configuration,this._context.theme);return this._settings&&this._settings.equals(i)?!1:(this._settings=i,this._domNode.setTop(this._settings.top),this._domNode.setRight(this._settings.right),this._domNode.setWidth(this._settings.domWidth),this._domNode.setHeight(this._settings.domHeight),this._domNode.domNode.width=this._settings.canvasWidth,this._domNode.domNode.height=this._settings.canvasHeight,t&&this._render(),!0)}_markRenderingIsNeeded(){return this._actualShouldRender=2,!0}_markRenderingIsMaybeNeeded(){return this._actualShouldRender=1,!0}onConfigurationChanged(t){return this._updateSettings(!1)?this._markRenderingIsNeeded():!1}onCursorStateChanged(t){this._cursorPositions=[];for(let i=0,s=t.selections.length;i1&&(g=i===0?this._settings.cursorColorPrimary:this._settings.cursorColorSecondary),this._cursorPositions.push({position:t.selections[i].getPosition(),color:g})}return this._cursorPositions.sort((i,s)=>E.Position.compare(i.position,s.position)),this._markRenderingIsMaybeNeeded()}onDecorationsChanged(t){return t.affectsOverviewRuler?this._markRenderingIsMaybeNeeded():!1}onFlushed(t){return this._markRenderingIsNeeded()}onScrollChanged(t){return t.scrollHeightChanged?this._markRenderingIsNeeded():!1}onZonesChanged(t){return this._markRenderingIsNeeded()}onThemeChanged(t){return this._updateSettings(!1)?this._markRenderingIsNeeded():!1}getDomNode(){return this._domNode.domNode}prepareRender(t){}render(t){this._render(),this._actualShouldRender=0}_render(){const t=this._settings.backgroundColor;if(this._settings.overviewRulerLanes===0){this._domNode.setBackgroundColor(t?k.Color.Format.CSS.formatHexA(t):""),this._domNode.setDisplay("none");return}const i=this._context.viewModel.getAllOverviewRulerDecorations(this._context.theme);if(i.sort(_.OverviewRulerDecorationsGroup.compareByRenderingProps),this._actualShouldRender===1&&!_.OverviewRulerDecorationsGroup.equalsArr(this._renderedDecorations,i)&&(this._actualShouldRender=2),this._actualShouldRender===1&&!(0,b.equals)(this._renderedCursorPositions,this._cursorPositions,(w,S)=>w.position.lineNumber===S.position.lineNumber&&w.color===S.color)&&(this._actualShouldRender=2),this._actualShouldRender===1)return;this._renderedDecorations=i,this._renderedCursorPositions=this._cursorPositions,this._domNode.setDisplay("block");const s=this._settings.canvasWidth,g=this._settings.canvasHeight,c=this._settings.lineHeight,l=this._context.viewLayout,a=this._context.viewLayout.getScrollHeight(),r=g/a,u=6*this._settings.pixelRatio|0,C=u/2|0,f=this._domNode.domNode.getContext("2d");t?t.isOpaque()?(f.fillStyle=k.Color.Format.CSS.formatHexA(t),f.fillRect(0,0,s,g)):(f.clearRect(0,0,s,g),f.fillStyle=k.Color.Format.CSS.formatHexA(t),f.fillRect(0,0,s,g)):f.clearRect(0,0,s,g);const h=this._settings.x,v=this._settings.w;for(const w of i){const S=w.color,L=w.data;f.fillStyle=S;let D=0,T=0,M=0;for(let A=0,P=L.length/3;Ag&&(q=g-C),x=q-C,W=q+C}x>M+1||N!==D?(A!==0&&f.fillRect(h[D],T,v[D],M-T),D=N,T=x,M=W):W>M&&(M=W)}f.fillRect(h[D],T,v[D],M-T)}if(!this._settings.hideCursor){const w=2*this._settings.pixelRatio|0,S=w/2|0,L=this._settings.x[7],D=this._settings.w[7];let T=-100,M=-100,A=null;for(let P=0,N=this._cursorPositions.length;Pg&&(x=g-S);const W=x-S,V=W+w;W>M+1||O!==A?(P!==0&&A&&f.fillRect(L,T,D,M-T),T=W,M=V):V>M&&(M=V),A=O,f.fillStyle=O}A&&f.fillRect(L,T,D,M-T)}this._settings.renderBorder&&this._settings.borderColor&&this._settings.overviewRulerLanes>0&&(f.beginPath(),f.lineWidth=1,f.strokeStyle=this._settings.borderColor,f.moveTo(0,0),f.lineTo(0,g),f.moveTo(1,0),f.lineTo(s,0),f.stroke())}}e.DecorationsOverviewRuler=n}),define(ne[780],se([1,0,39,14,56,655,37,80,25,97,5,496]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewCursors=void 0;class n extends I.ViewPart{static{this.BLINK_INTERVAL=500}constructor(t){super(t);const i=this._context.configuration.options;this._readOnly=i.get(92),this._cursorBlinking=i.get(26),this._cursorStyle=i.get(28),this._cursorSmoothCaretAnimation=i.get(27),this._selectionIsEmpty=!0,this._isComposingInput=!1,this._isVisible=!1,this._primaryCursor=new E.ViewCursor(this._context,E.CursorPlurality.Single),this._secondaryCursors=[],this._renderData=[],this._domNode=(0,d.createFastDomNode)(document.createElement("div")),this._domNode.setAttribute("role","presentation"),this._domNode.setAttribute("aria-hidden","true"),this._updateDomClassName(),this._domNode.appendChild(this._primaryCursor.getDomNode()),this._startCursorBlinkAnimation=new k.TimeoutTimer,this._cursorFlatBlinkInterval=new p.WindowIntervalTimer,this._blinkingEnabled=!1,this._editorHasFocus=!1,this._updateBlinking()}dispose(){super.dispose(),this._startCursorBlinkAnimation.dispose(),this._cursorFlatBlinkInterval.dispose()}getDomNode(){return this._domNode}onCompositionStart(t){return this._isComposingInput=!0,this._updateBlinking(),!0}onCompositionEnd(t){return this._isComposingInput=!1,this._updateBlinking(),!0}onConfigurationChanged(t){const i=this._context.configuration.options;this._readOnly=i.get(92),this._cursorBlinking=i.get(26),this._cursorStyle=i.get(28),this._cursorSmoothCaretAnimation=i.get(27),this._updateBlinking(),this._updateDomClassName(),this._primaryCursor.onConfigurationChanged(t);for(let s=0,g=this._secondaryCursors.length;si.length){const c=this._secondaryCursors.length-i.length;for(let l=0;l{for(let g=0,c=t.ranges.length;g{this._isVisible?this._hide():this._show()},n.BLINK_INTERVAL,(0,p.getWindow)(this._domNode.domNode)):this._startCursorBlinkAnimation.setIfNotSet(()=>{this._blinkingEnabled=!0,this._updateDomClassName()},n.BLINK_INTERVAL))}_updateDomClassName(){this._domNode.setClassName(this._getClassName())}_getClassName(){let t="cursors-layer";switch(this._selectionIsEmpty||(t+=" has-selection"),this._cursorStyle){case y.TextEditorCursorStyle.Line:t+=" cursor-line-style";break;case y.TextEditorCursorStyle.Block:t+=" cursor-block-style";break;case y.TextEditorCursorStyle.Underline:t+=" cursor-underline-style";break;case y.TextEditorCursorStyle.LineThin:t+=" cursor-line-thin-style";break;case y.TextEditorCursorStyle.BlockOutline:t+=" cursor-block-outline-style";break;case y.TextEditorCursorStyle.UnderlineThin:t+=" cursor-underline-thin-style";break;default:t+=" cursor-line-style"}if(this._blinkingEnabled)switch(this._getCursorBlinking()){case 1:t+=" cursor-blink";break;case 2:t+=" cursor-smooth";break;case 3:t+=" cursor-phase";break;case 4:t+=" cursor-expand";break;case 5:t+=" cursor-solid";break;default:t+=" cursor-solid"}else t+=" cursor-solid";return(this._cursorSmoothCaretAnimation==="on"||this._cursorSmoothCaretAnimation==="explicit")&&(t+=" cursor-smooth-caret-animation"),t}_show(){this._primaryCursor.show();for(let t=0,i=this._secondaryCursors.length;t{const i=[{class:".cursor",foreground:m.editorCursorForeground,background:m.editorCursorBackground},{class:".cursor-primary",foreground:m.editorMultiCursorPrimaryForeground,background:m.editorMultiCursorPrimaryBackground},{class:".cursor-secondary",foreground:m.editorMultiCursorSecondaryForeground,background:m.editorMultiCursorSecondaryBackground}];for(const s of i){const g=o.getColor(s.foreground);if(g){let c=o.getColor(s.background);c||(c=g.opposite()),t.addRule(`.monaco-editor .cursors-layer ${s.class} { background-color: ${g}; border-color: ${g}; color: ${c}; }`),(0,b.isHighContrast)(o.type)&&t.addRule(`.monaco-editor .cursors-layer.has-selection ${s.class} { border-left: 1px solid ${c}; border-right: 1px solid ${c}; }`)}}})}),define(ne[781],se([1,0,133,11,136,9,80,497]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.WhitespaceOverlay=void 0;class m extends d.DynamicViewOverlay{constructor(p){super(),this._context=p,this._options=new _(this._context.configuration),this._selection=[],this._renderResult=null,this._context.addEventHandler(this)}dispose(){this._context.removeEventHandler(this),this._renderResult=null,super.dispose()}onConfigurationChanged(p){const n=new _(this._context.configuration);return this._options.equals(n)?p.hasChanged(146):(this._options=n,!0)}onCursorStateChanged(p){return this._selection=p.selections,this._options.renderWhitespace==="selection"}onDecorationsChanged(p){return!0}onFlushed(p){return!0}onLinesChanged(p){return!0}onLinesDeleted(p){return!0}onLinesInserted(p){return!0}onScrollChanged(p){return p.scrollTopChanged}onZonesChanged(p){return!0}prepareRender(p){if(this._options.renderWhitespace==="none"){this._renderResult=null;return}const n=p.visibleRange.startLineNumber,t=p.visibleRange.endLineNumber-n+1,i=new Array(t);for(let g=0;gg)continue;const C=u.startLineNumber===g?u.startColumn:l.minColumn,f=u.endLineNumber===g?u.endColumn:l.maxColumn;C=O.endOffset&&(N++,O=o&&o[N]),W!==9&&W!==32||u&&!M&&x<=P)continue;if(r&&x>=A&&x<=P&&W===32){const q=x-1>=0?g.charCodeAt(x-1):0,H=x+1=0?g.charCodeAt(x-1):0;if(W===32&&q!==32&&q!==9)continue}if(o&&(!O||O.startOffset>x||O.endOffset<=x))continue;const V=p.visibleRangeForPosition(new E.Position(n,x+1));V&&(s?(F=Math.max(F,V.left),W===9?T+=this._renderArrow(C,v,V.left):T+=``):W===9?T+=`
      ${D?"\uFFEB":"\u2192"}
      `:T+=`
      ${String.fromCharCode(L)}
      `)}return s?(F=Math.round(F+v),``+T+""):T}_renderArrow(p,n,o){const t=n/7,i=n,s=p/2,g=o,c={x:0,y:t/2},l={x:100/125*i,y:c.y},a={x:l.x-.2*l.x,y:l.y+.2*l.x},r={x:a.x+.1*l.x,y:a.y+.1*l.x},u={x:r.x+.35*l.x,y:r.y-.35*l.x},C={x:u.x,y:-u.y},f={x:r.x,y:-r.y},h={x:a.x,y:-a.y},v={x:l.x,y:-l.y},w={x:c.x,y:-c.y};return``}render(p,n){if(!this._renderResult)return"";const o=n-p;return o<0||o>=this._renderResult.length?"":this._renderResult[o]}}e.WhitespaceOverlay=m;class _{constructor(p){const n=p.options,o=n.get(50),t=n.get(38);t==="off"?(this.renderWhitespace="none",this.renderWithSVG=!1):t==="svg"?(this.renderWhitespace=n.get(100),this.renderWithSVG=!0):(this.renderWhitespace=n.get(100),this.renderWithSVG=!1),this.spaceWidth=o.spaceWidth,this.middotWidth=o.middotWidth,this.wsmiddotWidth=o.wsmiddotWidth,this.canUseHalfwidthRightwardsArrow=o.canUseHalfwidthRightwardsArrow,this.lineHeight=n.get(67),this.stopRenderingLineAfter=n.get(118)}equals(p){return this.renderWhitespace===p.renderWhitespace&&this.renderWithSVG===p.renderWithSVG&&this.spaceWidth===p.spaceWidth&&this.middotWidth===p.middotWidth&&this.wsmiddotWidth===p.wsmiddotWidth&&this.canUseHalfwidthRightwardsArrow===p.canUseHalfwidthRightwardsArrow&&this.lineHeight===p.lineHeight&&this.stopRenderingLineAfter===p.stopRenderingLineAfter}}}),define(ne[782],se([1,0,5,39,296,8,414,769,778,164,726,657,56,309,591,649,776,592,773,242,777,416,770,593,331,594,755,650,779,604,595,596,774,780,597,781,9,4,23,40,170,600,605,7,25]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M,A,P,N,O,F,x,W,V,q,H,z,U,j){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.View=void 0;let Y=class extends q.ViewEventHandler{constructor(J,ie,ue,he,pe,ae,ee){super(),this._instantiationService=ee,this._shouldRecomputeGlyphMarginLanes=!1,this._selections=[new W.Selection(1,1,1,1)],this._renderAnimationFrame=null;const de=new p.ViewController(ie,he,pe,J);this._context=new z.ViewContext(ie,ue,he),this._context.addEventHandler(this),this._viewParts=[],this._textAreaHandler=this._instantiationService.createInstance(_.TextAreaHandler,this._context,de,this._createTextAreaHandlerHelper()),this._viewParts.push(this._textAreaHandler),this._linesContent=(0,k.createFastDomNode)(document.createElement("div")),this._linesContent.setClassName("lines-content monaco-editor-background"),this._linesContent.setPosition("absolute"),this.domNode=(0,k.createFastDomNode)(document.createElement("div")),this.domNode.setClassName(this._getEditorClassName()),this.domNode.setAttribute("role","code"),this._overflowGuardContainer=(0,k.createFastDomNode)(document.createElement("div")),o.PartFingerprints.write(this._overflowGuardContainer,3),this._overflowGuardContainer.setClassName("overflow-guard"),this._scrollbar=new l.EditorScrollbar(this._context,this._linesContent,this.domNode,this._overflowGuardContainer),this._viewParts.push(this._scrollbar),this._viewLines=new C.ViewLines(this._context,this._linesContent),this._viewZones=new N.ViewZones(this._context),this._viewParts.push(this._viewZones);const ge=new L.DecorationsOverviewRuler(this._context);this._viewParts.push(ge);const X=new M.ScrollDecorationViewPart(this._context);this._viewParts.push(X);const B=new n.ContentViewOverlays(this._context);this._viewParts.push(B),B.addDynamicOverlay(new g.CurrentLineHighlightOverlay(this._context)),B.addDynamicOverlay(new A.SelectionsOverlay(this._context)),B.addDynamicOverlay(new r.IndentGuidesOverlay(this._context)),B.addDynamicOverlay(new c.DecorationsOverlay(this._context)),B.addDynamicOverlay(new O.WhitespaceOverlay(this._context));const $=new n.MarginViewOverlays(this._context);this._viewParts.push($),$.addDynamicOverlay(new g.CurrentLineMarginHighlightOverlay(this._context)),$.addDynamicOverlay(new v.MarginViewLineDecorationsOverlay(this._context)),$.addDynamicOverlay(new f.LinesDecorationsOverlay(this._context)),$.addDynamicOverlay(new u.LineNumbersOverlay(this._context)),this._glyphMarginWidgets=new a.GlyphMarginWidgets(this._context),this._viewParts.push(this._glyphMarginWidgets);const Q=new h.Margin(this._context);Q.getDomNode().appendChild(this._viewZones.marginDomNode),Q.getDomNode().appendChild($.getDomNode()),Q.getDomNode().appendChild(this._glyphMarginWidgets.domNode),this._viewParts.push(Q),this._contentWidgets=new s.ViewContentWidgets(this._context,this.domNode),this._viewParts.push(this._contentWidgets),this._viewCursors=new P.ViewCursors(this._context),this._viewParts.push(this._viewCursors),this._overlayWidgets=new S.ViewOverlayWidgets(this._context,this.domNode),this._viewParts.push(this._overlayWidgets);const Z=new T.Rulers(this._context);this._viewParts.push(Z);const te=new i.BlockDecorations(this._context);this._viewParts.push(te);const re=new w.Minimap(this._context);if(this._viewParts.push(re),ge){const le=this._scrollbar.getOverviewRulerLayoutInfo();le.parent.insertBefore(ge.getDomNode(),le.insertBefore)}this._linesContent.appendChild(B.getDomNode()),this._linesContent.appendChild(Z.domNode),this._linesContent.appendChild(this._viewZones.domNode),this._linesContent.appendChild(this._viewLines.getDomNode()),this._linesContent.appendChild(this._contentWidgets.domNode),this._linesContent.appendChild(this._viewCursors.getDomNode()),this._overflowGuardContainer.appendChild(Q.getDomNode()),this._overflowGuardContainer.appendChild(this._scrollbar.getDomNode()),this._overflowGuardContainer.appendChild(X.getDomNode()),this._overflowGuardContainer.appendChild(this._textAreaHandler.textArea),this._overflowGuardContainer.appendChild(this._textAreaHandler.textAreaCover),this._overflowGuardContainer.appendChild(this._overlayWidgets.getDomNode()),this._overflowGuardContainer.appendChild(re.getDomNode()),this._overflowGuardContainer.appendChild(te.domNode),this.domNode.appendChild(this._overflowGuardContainer),ae?(ae.appendChild(this._contentWidgets.overflowingContentWidgetsDomNode.domNode),ae.appendChild(this._overlayWidgets.overflowingOverlayWidgetsDomNode.domNode)):(this.domNode.appendChild(this._contentWidgets.overflowingContentWidgetsDomNode),this.domNode.appendChild(this._overlayWidgets.overflowingOverlayWidgetsDomNode)),this._applyLayout(),this._pointerHandler=this._register(new m.PointerHandler(this._context,de,this._createPointerHandlerHelper()))}_computeGlyphMarginLanes(){const J=this._context.viewModel.model,ie=this._context.viewModel.glyphLanes;let ue=[],he=0;ue=ue.concat(J.getAllMarginDecorations().map(pe=>{const ae=pe.options.glyphMargin?.position??V.GlyphMarginLane.Center;return he=Math.max(he,pe.range.endLineNumber),{range:pe.range,lane:ae,persist:pe.options.glyphMargin?.persistLane}})),ue=ue.concat(this._glyphMarginWidgets.getWidgets().map(pe=>{const ae=J.validateRange(pe.preference.range);return he=Math.max(he,ae.endLineNumber),{range:ae,lane:pe.preference.lane}})),ue.sort((pe,ae)=>x.Range.compareRangesUsingStarts(pe.range,ae.range)),ie.reset(he);for(const pe of ue)ie.push(pe.lane,pe.range,pe.persist);return ie}_createPointerHandlerHelper(){return{viewDomNode:this.domNode.domNode,linesContentDomNode:this._linesContent.domNode,viewLinesDomNode:this._viewLines.getDomNode().domNode,focusTextArea:()=>{this.focus()},dispatchTextAreaEvent:J=>{this._textAreaHandler.textArea.domNode.dispatchEvent(J)},getLastRenderData:()=>{const J=this._viewCursors.getLastRenderData()||[],ie=this._textAreaHandler.getLastRenderData();return new y.PointerHandlerLastRenderData(J,ie)},renderNow:()=>{this.render(!0,!1)},shouldSuppressMouseDownOnViewZone:J=>this._viewZones.shouldSuppressMouseDownOnViewZone(J),shouldSuppressMouseDownOnWidget:J=>this._contentWidgets.shouldSuppressMouseDownOnWidget(J),getPositionFromDOMInfo:(J,ie)=>(this._flushAccumulatedAndRenderNow(),this._viewLines.getPositionFromDOMInfo(J,ie)),visibleRangeForPosition:(J,ie)=>(this._flushAccumulatedAndRenderNow(),this._viewLines.visibleRangeForPosition(new F.Position(J,ie))),getLineWidth:J=>(this._flushAccumulatedAndRenderNow(),this._viewLines.getLineWidth(J))}}_createTextAreaHandlerHelper(){return{visibleRangeForPosition:J=>(this._flushAccumulatedAndRenderNow(),this._viewLines.visibleRangeForPosition(J))}}_applyLayout(){const ie=this._context.configuration.options.get(146);this.domNode.setWidth(ie.width),this.domNode.setHeight(ie.height),this._overflowGuardContainer.setWidth(ie.width),this._overflowGuardContainer.setHeight(ie.height),this._linesContent.setWidth(16777216),this._linesContent.setHeight(16777216)}_getEditorClassName(){const J=this._textAreaHandler.isFocused()?" focused":"";return this._context.configuration.options.get(143)+" "+(0,j.getThemeTypeSelector)(this._context.theme.type)+J}handleEvents(J){super.handleEvents(J),this._scheduleRender()}onConfigurationChanged(J){return this.domNode.setClassName(this._getEditorClassName()),this._applyLayout(),!1}onCursorStateChanged(J){return this._selections=J.selections,!1}onDecorationsChanged(J){return J.affectsGlyphMargin&&(this._shouldRecomputeGlyphMarginLanes=!0),!1}onFocusChanged(J){return this.domNode.setClassName(this._getEditorClassName()),!1}onThemeChanged(J){return this._context.theme.update(J.theme),this.domNode.setClassName(this._getEditorClassName()),!1}dispose(){this._renderAnimationFrame!==null&&(this._renderAnimationFrame.dispose(),this._renderAnimationFrame=null),this._contentWidgets.overflowingContentWidgetsDomNode.domNode.remove(),this._context.removeEventHandler(this),this._viewLines.dispose();for(const J of this._viewParts)J.dispose();super.dispose()}_scheduleRender(){if(this._store.isDisposed)throw new E.BugIndicatingError;if(this._renderAnimationFrame===null){const J=this._createCoordinatedRendering();this._renderAnimationFrame=K.INSTANCE.scheduleCoordinatedRendering({window:d.getWindow(this.domNode?.domNode),prepareRenderText:()=>{if(this._store.isDisposed)throw new E.BugIndicatingError;try{return J.prepareRenderText()}finally{this._renderAnimationFrame=null}},renderText:()=>{if(this._store.isDisposed)throw new E.BugIndicatingError;return J.renderText()},prepareRender:(ie,ue)=>{if(this._store.isDisposed)throw new E.BugIndicatingError;return J.prepareRender(ie,ue)},render:(ie,ue)=>{if(this._store.isDisposed)throw new E.BugIndicatingError;return J.render(ie,ue)}})}}_flushAccumulatedAndRenderNow(){const J=this._createCoordinatedRendering();G(()=>J.prepareRenderText());const ie=G(()=>J.renderText());if(ie){const[ue,he]=ie;G(()=>J.prepareRender(ue,he)),G(()=>J.render(ue,he))}}_getViewPartsToRender(){const J=[];let ie=0;for(const ue of this._viewParts)ue.shouldRender()&&(J[ie++]=ue);return J}_createCoordinatedRendering(){return{prepareRenderText:()=>{if(this._shouldRecomputeGlyphMarginLanes){this._shouldRecomputeGlyphMarginLanes=!1;const J=this._computeGlyphMarginLanes();this._context.configuration.setGlyphMarginDecorationLaneCount(J.requiredLanes)}I.inputLatency.onRenderStart()},renderText:()=>{if(!this.domNode.domNode.isConnected)return null;let J=this._getViewPartsToRender();if(!this._viewLines.shouldRender()&&J.length===0)return null;const ie=this._context.viewLayout.getLinesViewportData();this._context.viewModel.setViewport(ie.startLineNumber,ie.endLineNumber,ie.centeredLineNumber);const ue=new H.ViewportData(this._selections,ie,this._context.viewLayout.getWhitespaceViewportData(),this._context.viewModel);return this._contentWidgets.shouldRender()&&this._contentWidgets.onBeforeRender(ue),this._viewLines.shouldRender()&&(this._viewLines.renderText(ue),this._viewLines.onDidRender(),J=this._getViewPartsToRender()),[J,new b.RenderingContext(this._context.viewLayout,ue,this._viewLines)]},prepareRender:(J,ie)=>{for(const ue of J)ue.prepareRender(ie)},render:(J,ie)=>{for(const ue of J)ue.render(ie),ue.onDidRender()}}}delegateVerticalScrollbarPointerDown(J){this._scrollbar.delegateVerticalScrollbarPointerDown(J)}delegateScrollFromMouseWheelEvent(J){this._scrollbar.delegateScrollFromMouseWheelEvent(J)}restoreState(J){this._context.viewModel.viewLayout.setScrollPosition({scrollTop:J.scrollTop,scrollLeft:J.scrollLeft},1),this._context.viewModel.visibleLinesStabilized()}getOffsetForColumn(J,ie){const ue=this._context.viewModel.model.validatePosition({lineNumber:J,column:ie}),he=this._context.viewModel.coordinatesConverter.convertModelPositionToViewPosition(ue);this._flushAccumulatedAndRenderNow();const pe=this._viewLines.visibleRangeForPosition(new F.Position(he.lineNumber,he.column));return pe?pe.left:-1}getTargetAtClientPoint(J,ie){const ue=this._pointerHandler.getTargetAtClientPoint(J,ie);return ue?t.ViewUserInputEvents.convertViewToModelMouseTarget(ue,this._context.viewModel.coordinatesConverter):null}createOverviewRuler(J){return new D.OverviewRuler(this._context,J)}change(J){this._viewZones.changeViewZones(J),this._scheduleRender()}render(J,ie){if(ie){this._viewLines.forceShouldRender();for(const ue of this._viewParts)ue.forceShouldRender()}J?this._flushAccumulatedAndRenderNow():this._scheduleRender()}writeScreenReaderContent(J){this._textAreaHandler.writeScreenReaderContent(J)}focus(){this._textAreaHandler.focusTextArea()}isFocused(){return this._textAreaHandler.isFocused()}setAriaOptions(J){this._textAreaHandler.setAriaOptions(J)}addContentWidget(J){this._contentWidgets.addWidget(J.widget),this.layoutContentWidget(J),this._scheduleRender()}layoutContentWidget(J){this._contentWidgets.setWidgetPosition(J.widget,J.position?.position??null,J.position?.secondaryPosition??null,J.position?.preference??null,J.position?.positionAffinity??null),this._scheduleRender()}removeContentWidget(J){this._contentWidgets.removeWidget(J.widget),this._scheduleRender()}addOverlayWidget(J){this._overlayWidgets.addWidget(J.widget),this.layoutOverlayWidget(J),this._scheduleRender()}layoutOverlayWidget(J){this._overlayWidgets.setWidgetPosition(J.widget,J.position)&&this._scheduleRender()}removeOverlayWidget(J){this._overlayWidgets.removeWidget(J.widget),this._scheduleRender()}addGlyphMarginWidget(J){this._glyphMarginWidgets.addWidget(J.widget),this._shouldRecomputeGlyphMarginLanes=!0,this._scheduleRender()}layoutGlyphMarginWidget(J){const ie=J.position;this._glyphMarginWidgets.setWidgetPosition(J.widget,ie)&&(this._shouldRecomputeGlyphMarginLanes=!0,this._scheduleRender())}removeGlyphMarginWidget(J){this._glyphMarginWidgets.removeWidget(J.widget),this._shouldRecomputeGlyphMarginLanes=!0,this._scheduleRender()}};e.View=Y,e.View=Y=ke([ce(6,U.IInstantiationService)],Y);function G(R){try{return R()}catch(J){return(0,E.onUnexpectedError)(J),null}}class K{static{this.INSTANCE=new K}constructor(){this._coordinatedRenderings=[],this._animationFrameRunners=new Map}scheduleCoordinatedRendering(J){return this._coordinatedRenderings.push(J),this._scheduleRender(J.window),{dispose:()=>{const ie=this._coordinatedRenderings.indexOf(J);if(ie!==-1&&(this._coordinatedRenderings.splice(ie,1),this._coordinatedRenderings.length===0)){for(const[ue,he]of this._animationFrameRunners)he.dispose();this._animationFrameRunners.clear()}}}}_scheduleRender(J){if(!this._animationFrameRunners.has(J)){const ie=()=>{this._animationFrameRunners.delete(J),this._onRenderScheduled()};this._animationFrameRunners.set(J,d.runAtThisOrScheduleAtNextAnimationFrame(J,ie,100))}}_onRenderScheduled(){const J=this._coordinatedRenderings.slice(0);this._coordinatedRenderings=[];for(const ue of J)G(()=>ue.prepareRenderText());const ie=[];for(let ue=0,he=J.length;uepe.renderText())}for(let ue=0,he=J.length;uepe.prepareRender(ee,de))}for(let ue=0,he=J.length;uepe.render(ee,de))}}}}),define(ne[783],se([1,0,6,2,4,80,25]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ColorizedBracketPairsDecorationProvider=void 0;class m extends k.Disposable{constructor(p){super(),this.textModel=p,this.colorProvider=new _,this.onDidChangeEmitter=new d.Emitter,this.onDidChange=this.onDidChangeEmitter.event,this.colorizationOptions=p.getOptions().bracketPairColorizationOptions,this._register(p.bracketPairs.onDidChange(n=>{this.onDidChangeEmitter.fire()}))}handleDidChangeOptions(p){this.colorizationOptions=this.textModel.getOptions().bracketPairColorizationOptions}getDecorationsInRange(p,n,o,t){return t?[]:n===void 0?[]:this.colorizationOptions.enabled?this.textModel.bracketPairs.getBracketsInRange(p,!0).map(s=>({id:`bracket${s.range.toString()}-${s.nestingLevel}`,options:{description:"BracketPairColorization",inlineClassName:this.colorProvider.getInlineClassName(s,this.colorizationOptions.independentColorPoolPerBracketType)},ownerId:0,range:s.range})).toArray():[]}getAllDecorations(p,n){return p===void 0?[]:this.colorizationOptions.enabled?this.getDecorationsInRange(new I.Range(1,1,this.textModel.getLineCount(),1),p,n):[]}}e.ColorizedBracketPairsDecorationProvider=m;class _{constructor(){this.unexpectedClosingBracketClassName="unexpected-closing-bracket"}getInlineClassName(p,n){return p.isInvalid?this.unexpectedClosingBracketClassName:this.getInlineClassNameOfLevel(n?p.nestingLevelOfEqualBracketType:p.nestingLevel)}getInlineClassNameOfLevel(p){return`bracket-highlighting-${p%30}`}}(0,y.registerThemingParticipant)((b,p)=>{const n=[E.editorBracketHighlightingForeground1,E.editorBracketHighlightingForeground2,E.editorBracketHighlightingForeground3,E.editorBracketHighlightingForeground4,E.editorBracketHighlightingForeground5,E.editorBracketHighlightingForeground6],o=new _;p.addRule(`.monaco-editor .${o.unexpectedClosingBracketClassName} { color: ${b.getColor(E.editorBracketHighlightingUnexpectedBracketForeground)}; }`);const t=n.map(i=>b.getColor(i)).filter(i=>!!i).filter(i=>!i.isTransparent());for(let i=0;i<30;i++){const s=t[i%t.length];p.addRule(`.monaco-editor .${o.getInlineClassNameOfLevel(i)} { color: ${s}; }`)}})}),define(ne[784],se([1,0,108,2,40,25,80,51,4,42,6,32,45,298]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MarkerDecorationsService=void 0;let i=class extends k.Disposable{constructor(c,l){super(),this._markerService=l,this._onDidChangeMarker=this._register(new p.Emitter),this._markerDecorations=new o.ResourceMap,c.getModels().forEach(a=>this._onModelAdded(a)),this._register(c.onModelAdded(this._onModelAdded,this)),this._register(c.onModelRemoved(this._onModelRemoved,this)),this._register(this._markerService.onMarkerChanged(this._handleMarkerChange,this))}dispose(){super.dispose(),this._markerDecorations.forEach(c=>c.dispose()),this._markerDecorations.clear()}getMarker(c,l){const a=this._markerDecorations.get(c);return a&&a.getMarker(l)||null}_handleMarkerChange(c){c.forEach(l=>{const a=this._markerDecorations.get(l);a&&this._updateDecorations(a)})}_onModelAdded(c){const l=new s(c);this._markerDecorations.set(c.uri,l),this._updateDecorations(l)}_onModelRemoved(c){const l=this._markerDecorations.get(c.uri);l&&(l.dispose(),this._markerDecorations.delete(c.uri)),(c.uri.scheme===b.Schemas.inMemory||c.uri.scheme===b.Schemas.internal||c.uri.scheme===b.Schemas.vscode)&&this._markerService?.read({resource:c.uri}).map(a=>a.owner).forEach(a=>this._markerService.remove(a,[c.uri]))}_updateDecorations(c){const l=this._markerService.read({resource:c.model.uri,take:500});c.update(l)&&this._onDidChangeMarker.fire(c.model)}};e.MarkerDecorationsService=i,e.MarkerDecorationsService=i=ke([ce(0,m.IModelService),ce(1,d.IMarkerService)],i);class s extends k.Disposable{constructor(c){super(),this.model=c,this._map=new o.BidirectionalMap,this._register((0,k.toDisposable)(()=>{this.model.deltaDecorations([...this._map.values()],[]),this._map.clear()}))}update(c){const{added:l,removed:a}=(0,t.diffSets)(new Set(this._map.keys()),new Set(c));if(l.length===0&&a.length===0)return!1;const r=a.map(f=>this._map.get(f)),u=l.map(f=>({range:this._createDecorationRange(this.model,f),options:this._createDecorationOption(f)})),C=this.model.deltaDecorations(r,u);for(const f of a)this._map.delete(f);for(let f=0;f=r)return a;const u=c.getWordAtPosition(a.getStartPosition());u&&(a=new _.Range(a.startLineNumber,u.startColumn,a.endLineNumber,u.endColumn))}else if(l.endColumn===Number.MAX_VALUE&&l.startColumn===1&&a.startLineNumber===a.endLineNumber){const r=c.getLineFirstNonWhitespaceColumn(l.startLineNumber);r=0:!1}}}),define(ne[282],se([1,0,148,25,62,589,43]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SemanticTokensProviderStyling=void 0,e.toMultilineTokens2=b;const m=!1;let _=class{constructor(t,i,s,g){this._legend=t,this._themeService=i,this._languageService=s,this._logService=g,this._hasWarnedOverlappingTokens=!1,this._hasWarnedInvalidLengthTokens=!1,this._hasWarnedInvalidEditStart=!1,this._hashTable=new n}getMetadata(t,i,s){const g=this._languageService.languageIdCodec.encodeLanguageId(s),c=this._hashTable.get(t,i,g);let l;if(c)l=c.metadata,m&&this._logService.getLevel()===I.LogLevel.Trace&&this._logService.trace(`SemanticTokensProviderStyling [CACHED] ${t} / ${i}: foreground ${d.TokenMetadata.getForeground(l)}, fontStyle ${d.TokenMetadata.getFontStyle(l).toString(2)}`);else{let a=this._legend.tokenTypes[t];const r=[];if(a){let u=i;for(let f=0;u>0&&f>1;m&&u>0&&this._logService.getLevel()===I.LogLevel.Trace&&(this._logService.trace(`SemanticTokensProviderStyling: unknown token modifier index: ${i.toString(2)} for legend: ${JSON.stringify(this._legend.tokenModifiers)}`),r.push("not-in-legend"));const C=this._themeService.getColorTheme().getTokenStyleMetadata(a,r,s);if(typeof C>"u")l=2147483647;else{if(l=0,typeof C.italic<"u"){const f=(C.italic?1:0)<<11;l|=f|1}if(typeof C.bold<"u"){const f=(C.bold?2:0)<<11;l|=f|2}if(typeof C.underline<"u"){const f=(C.underline?4:0)<<11;l|=f|4}if(typeof C.strikethrough<"u"){const f=(C.strikethrough?8:0)<<11;l|=f|8}if(C.foreground){const f=C.foreground<<15;l|=f|16}l===0&&(l=2147483647)}}else m&&this._logService.getLevel()===I.LogLevel.Trace&&this._logService.trace(`SemanticTokensProviderStyling: unknown token type index: ${t} for legend: ${JSON.stringify(this._legend.tokenTypes)}`),l=2147483647,a="not-in-legend";this._hashTable.add(t,i,g,l),m&&this._logService.getLevel()===I.LogLevel.Trace&&this._logService.trace(`SemanticTokensProviderStyling ${t} (${a}) / ${i} (${r.join(" ")}): foreground ${d.TokenMetadata.getForeground(l)}, fontStyle ${d.TokenMetadata.getFontStyle(l).toString(2)}`)}return l}warnOverlappingSemanticTokens(t,i){this._hasWarnedOverlappingTokens||(this._hasWarnedOverlappingTokens=!0,this._logService.warn(`Overlapping semantic tokens detected at lineNumber ${t}, column ${i}`))}warnInvalidLengthSemanticTokens(t,i){this._hasWarnedInvalidLengthTokens||(this._hasWarnedInvalidLengthTokens=!0,this._logService.warn(`Semantic token with invalid length detected at lineNumber ${t}, column ${i}`))}warnInvalidEditStart(t,i,s,g,c){this._hasWarnedInvalidEditStart||(this._hasWarnedInvalidEditStart=!0,this._logService.warn(`Invalid semantic tokens edit detected (previousResultId: ${t}, resultId: ${i}) at edit #${s}: The provided start offset ${g} is outside the previous data (length ${c}).`))}};e.SemanticTokensProviderStyling=_,e.SemanticTokensProviderStyling=_=ke([ce(1,k.IThemeService),ce(2,y.ILanguageService),ce(3,I.ILogService)],_);function b(o,t,i){const s=o.data,g=o.data.length/5|0,c=Math.max(Math.ceil(g/1024),400),l=[];let a=0,r=1,u=0;for(;aC&&s[5*T]===0;)T--;if(T-1===C){let M=f;for(;M+1N)t.warnOverlappingSemanticTokens(P,N+1);else{const V=t.getMetadata(x,W,i);V!==2147483647&&(w===0&&(w=P),h[v]=P-w,h[v+1]=N,h[v+2]=F,h[v+3]=V,v+=4,S=P,L=F)}r=P,u=N,a++}v!==h.length&&(h=h.subarray(0,v));const D=E.SparseMultilineTokens.create(w,h);l.push(D)}return l}class p{constructor(t,i,s,g){this.tokenTypeIndex=t,this.tokenModifierSet=i,this.languageId=s,this.metadata=g,this.next=null}}class n{static{this._SIZES=[3,7,13,31,61,127,251,509,1021,2039,4093,8191,16381,32749,65521,131071,262139,524287,1048573,2097143]}constructor(){this._elementsCount=0,this._currentLengthIndex=0,this._currentLength=n._SIZES[this._currentLengthIndex],this._growCount=Math.round(this._currentLengthIndex+1=this._growCount){const c=this._elements;this._currentLengthIndex++,this._currentLength=n._SIZES[this._currentLengthIndex],this._growCount=Math.round(this._currentLengthIndex+1{this._caches=new WeakMap}))}getStyling(n){return this._caches.has(n)||this._caches.set(n,new y.SemanticTokensProviderStyling(n.getLegend(),this._themeService,this._languageService,this._logService)),this._caches.get(n)}};e.SemanticTokensStylingService=b,e.SemanticTokensStylingService=b=ke([ce(0,I.IThemeService),ce(1,E.ILogService),ce(2,k.ILanguageService)],b),(0,_.registerSingleton)(m.ISemanticTokensStylingService,b,1)}),define(ne[786],se([1,0,15,80,3,89,379,700,528]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorContribution)(y.PlaceholderTextContribution.ID,(0,m.wrapInReloadableClass1)(()=>y.PlaceholderTextContribution),0),(0,E.registerColor)("editor.placeholder.foreground",k.ghostTextForeground,(0,I.localize)(1194,"Foreground color of the placeholder text in the editor."))}),define(ne[417],se([1,0,127,2,168,40,80,25,46]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractEditorNavigationQuickAccessProvider=void 0;class b{constructor(n){this.options=n,this.rangeHighlightDecorationId=void 0}provide(n,o,t){const i=new k.DisposableStore;n.canAcceptInBackground=!!this.options?.canAcceptInBackground,n.matchOnLabel=n.matchOnDescription=n.matchOnDetail=n.sortByLabel=!1;const s=i.add(new k.MutableDisposable);return s.value=this.doProvide(n,o,t),i.add(this.onDidActiveTextEditorControlChange(()=>{s.value=void 0,s.value=this.doProvide(n,o)})),i}doProvide(n,o,t){const i=new k.DisposableStore,s=this.activeTextEditorControl;if(s&&this.canProvideWithTextEditor(s)){const g={editor:s},c=(0,I.getCodeEditor)(s);if(c){let l=s.saveViewState()??void 0;i.add(c.onDidChangeCursorPosition(()=>{l=s.saveViewState()??void 0})),g.restoreViewState=()=>{l&&s===this.activeTextEditorControl&&s.restoreViewState(l)},i.add((0,d.createSingleCallFunction)(o.onCancellationRequested)(()=>g.restoreViewState?.()))}i.add((0,k.toDisposable)(()=>this.clearDecorations(s))),i.add(this.provideWithTextEditor(g,n,o,t))}else i.add(this.provideWithoutTextEditor(n,o));return i}canProvideWithTextEditor(n){return!0}gotoLocation({editor:n},o){n.setSelection(o.range,"code.jump"),n.revealRangeInCenter(o.range,0),o.preserveFocus||n.focus();const t=n.getModel();t&&"getLineContent"in t&&(0,_.status)(`${t.getLineContent(o.range.startLineNumber)}`)}getModel(n){return(0,I.isDiffEditor)(n)?n.getModel()?.modified:n.getModel()}addDecorations(n,o){n.changeDecorations(t=>{const i=[];this.rangeHighlightDecorationId&&(i.push(this.rangeHighlightDecorationId.overviewRulerDecorationId),i.push(this.rangeHighlightDecorationId.rangeHighlightId),this.rangeHighlightDecorationId=void 0);const s=[{range:o,options:{description:"quick-access-range-highlight",className:"rangeHighlight",isWholeLine:!0}},{range:o,options:{description:"quick-access-range-highlight-overview",overviewRuler:{color:(0,m.themeColorFromId)(y.overviewRulerRangeHighlight),position:E.OverviewRulerLane.Full}}}],[g,c]=t.deltaDecorations(i,s);this.rangeHighlightDecorationId={rangeHighlightId:g,overviewRulerDecorationId:c}})}clearDecorations(n){const o=this.rangeHighlightDecorationId;o&&(n.changeDecorations(t=>{t.deltaDecorations([o.overviewRulerDecorationId,o.rangeHighlightId],[])}),this.rangeHighlightDecorationId=void 0)}}e.AbstractEditorNavigationQuickAccessProvider=b}),define(ne[787],se([1,0,2,168,417,3]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractGotoLineQuickAccessProvider=void 0;class y extends I.AbstractEditorNavigationQuickAccessProvider{static{this.PREFIX=":"}constructor(){super({canAcceptInBackground:!0})}provideWithoutTextEditor(_){const b=(0,E.localize)(1195,"Open a text editor first to go to a line.");return _.items=[{label:b}],_.ariaLabel=b,d.Disposable.None}provideWithTextEditor(_,b,p){const n=_.editor,o=new d.DisposableStore;o.add(b.onDidAccept(s=>{const[g]=b.selectedItems;if(g){if(!this.isValidLineNumber(n,g.lineNumber))return;this.gotoLocation(_,{range:this.toRange(g.lineNumber,g.column),keyMods:b.keyMods,preserveFocus:s.inBackground}),s.inBackground||b.hide()}}));const t=()=>{const s=this.parsePosition(n,b.value.trim().substr(y.PREFIX.length)),g=this.getPickLabel(n,s.lineNumber,s.column);if(b.items=[{lineNumber:s.lineNumber,column:s.column,label:g}],b.ariaLabel=g,!this.isValidLineNumber(n,s.lineNumber)){this.clearDecorations(n);return}const c=this.toRange(s.lineNumber,s.column);n.revealRangeInCenter(c,0),this.addDecorations(n,c)};t(),o.add(b.onDidChangeValue(()=>t()));const i=(0,k.getCodeEditor)(n);return i&&i.getOptions().get(68).renderType===2&&(i.updateOptions({lineNumbers:"on"}),o.add((0,d.toDisposable)(()=>i.updateOptions({lineNumbers:"relative"})))),o}toRange(_=1,b=1){return{startLineNumber:_,startColumn:b,endLineNumber:_,endColumn:b}}parsePosition(_,b){const p=b.split(/,|:|#/).map(o=>parseInt(o,10)).filter(o=>!isNaN(o)),n=this.lineCount(_)+1;return{lineNumber:p[0]>0?p[0]:n+p[0],column:p[1]}}getPickLabel(_,b,p){if(this.isValidLineNumber(_,b))return this.isValidColumn(_,b,p)?(0,E.localize)(1196,"Go to line {0} and character {1}.",b,p):(0,E.localize)(1197,"Go to line {0}.",b);const n=_.getPosition()||{lineNumber:1,column:1},o=this.lineCount(_);return o>1?(0,E.localize)(1198,"Current Line: {0}, Character: {1}. Type a line number between 1 and {2} to navigate to.",n.lineNumber,n.column,o):(0,E.localize)(1199,"Current Line: {0}, Character: {1}. Type a line number to navigate to.",n.lineNumber,n.column)}isValidLineNumber(_,b){return!b||typeof b!="number"?!1:b>0&&b<=this.lineCount(_)}isValidColumn(_,b,p){if(!p||typeof p!="number")return!1;const n=this.getModel(_);if(!n)return!1;const o={lineNumber:b,column:p};return n.validatePosition(o).equals(o)}lineCount(_){return this.getModel(_)?.getLineCount()??0}}e.AbstractGotoLineQuickAccessProvider=y}),define(ne[788],se([1,0,14,18,26,30,628,2,11,4,27,182,417,3,17,67]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";var g;Object.defineProperty(e,"__esModule",{value:!0}),e.AbstractGotoSymbolQuickAccessProvider=void 0;let c=class extends o.AbstractEditorNavigationQuickAccessProvider{static{g=this}static{this.PREFIX="@"}static{this.SCOPE_PREFIX=":"}static{this.PREFIX_BY_CATEGORY=`${this.PREFIX}${this.SCOPE_PREFIX}`}constructor(u,C,f=Object.create(null)){super(f),this._languageFeaturesService=u,this._outlineModelService=C,this.options=f,this.options.canAcceptInBackground=!0}provideWithoutTextEditor(u){return this.provideLabelPick(u,(0,t.localize)(1200,"To go to a symbol, first open a text editor with symbol information.")),m.Disposable.None}provideWithTextEditor(u,C,f,h){const v=u.editor,w=this.getModel(v);return w?this._languageFeaturesService.documentSymbolProvider.has(w)?this.doProvideWithEditorSymbols(u,w,C,f,h):this.doProvideWithoutEditorSymbols(u,w,C,f):m.Disposable.None}doProvideWithoutEditorSymbols(u,C,f,h){const v=new m.DisposableStore;return this.provideLabelPick(f,(0,t.localize)(1201,"The active text editor does not provide symbol information.")),(async()=>!await this.waitForLanguageSymbolRegistry(C,v)||h.isCancellationRequested||v.add(this.doProvideWithEditorSymbols(u,C,f,h)))(),v}provideLabelPick(u,C){u.items=[{label:C,index:0,kind:14}],u.ariaLabel=C}async waitForLanguageSymbolRegistry(u,C){if(this._languageFeaturesService.documentSymbolProvider.has(u))return!0;const f=new d.DeferredPromise,h=C.add(this._languageFeaturesService.documentSymbolProvider.onDidChange(()=>{this._languageFeaturesService.documentSymbolProvider.has(u)&&(h.dispose(),f.complete(!0))}));return C.add((0,m.toDisposable)(()=>f.complete(!1))),f.p}doProvideWithEditorSymbols(u,C,f,h,v){const w=u.editor,S=new m.DisposableStore;S.add(f.onDidAccept(M=>{const[A]=f.selectedItems;A&&A.range&&(this.gotoLocation(u,{range:A.range.selection,keyMods:f.keyMods,preserveFocus:M.inBackground}),v?.handleAccept?.(A),M.inBackground||f.hide())})),S.add(f.onDidTriggerItemButton(({item:M})=>{M&&M.range&&(this.gotoLocation(u,{range:M.range.selection,keyMods:f.keyMods,forceSideBySide:!0}),f.hide())}));const L=this.getDocumentSymbols(C,h);let D;const T=async M=>{D?.dispose(!0),f.busy=!1,D=new k.CancellationTokenSource(h),f.busy=!0;try{const A=(0,y.prepareQuery)(f.value.substr(g.PREFIX.length).trim()),P=await this.doGetSymbolPicks(L,A,void 0,D.token,C);if(h.isCancellationRequested)return;if(P.length>0){if(f.items=P,M&&A.original.length===0){const N=(0,s.findLast)(P,O=>!!(O.type!=="separator"&&O.range&&b.Range.containsPosition(O.range.decoration,M)));N&&(f.activeItems=[N])}}else A.original.length>0?this.provideLabelPick(f,(0,t.localize)(1202,"No matching editor symbols")):this.provideLabelPick(f,(0,t.localize)(1203,"No editor symbols"))}finally{h.isCancellationRequested||(f.busy=!1)}};return S.add(f.onDidChangeValue(()=>T(void 0))),T(w.getSelection()?.getPosition()),S.add(f.onDidChangeActive(()=>{const[M]=f.activeItems;M&&M.range&&(w.revealRangeInCenter(M.range.selection,0),this.addDecorations(w,M.range.decoration))})),S}async doGetSymbolPicks(u,C,f,h,v){const w=await u;if(h.isCancellationRequested)return[];const S=C.original.indexOf(g.SCOPE_PREFIX)===0,L=S?1:0;let D,T;C.values&&C.values.length>1?(D=(0,y.pieceToQuery)(C.values[0]),T=(0,y.pieceToQuery)(C.values.slice(1))):D=C;let M;const A=this.options?.openSideBySideDirection?.();A&&(M=[{iconClass:A==="right"?E.ThemeIcon.asClassName(I.Codicon.splitHorizontal):E.ThemeIcon.asClassName(I.Codicon.splitVertical),tooltip:A==="right"?(0,t.localize)(1204,"Open to the Side"):(0,t.localize)(1205,"Open to the Bottom")}]);const P=[];for(let F=0;FL){let K=!1;if(D!==C&&([z,U]=(0,y.scoreFuzzy2)(V,{...C,values:void 0},L,q),typeof z=="number"&&(K=!0)),typeof z!="number"&&([z,U]=(0,y.scoreFuzzy2)(V,D,L,q),typeof z!="number"))continue;if(!K&&T){if(H&&T.original.length>0&&([j,Y]=(0,y.scoreFuzzy2)(H,T)),typeof j!="number")continue;typeof z=="number"&&(z+=j)}}const G=x.tags&&x.tags.indexOf(1)>=0;P.push({index:F,kind:x.kind,score:z,label:V,ariaLabel:(0,p.getAriaLabelForSymbol)(x.name,x.kind),description:H,highlights:G?void 0:{label:U,description:Y},range:{selection:b.Range.collapseToStart(x.selectionRange),decoration:x.range},uri:v.uri,symbolName:W,strikethrough:G,buttons:M})}const N=P.sort((F,x)=>S?this.compareByKindAndScore(F,x):this.compareByScore(F,x));let O=[];if(S){let V=function(){x&&typeof F=="number"&&W>0&&(x.label=(0,_.format)(a[F]||l,W))},F,x,W=0;for(const q of N)F!==q.kind?(V(),F=q.kind,W=1,x={type:"separator"},O.push(x)):W++,O.push(q);V()}else N.length>0&&(O=[{label:(0,t.localize)(1206,"symbols ({0})",P.length),type:"separator"},...N]);return O}compareByScore(u,C){if(typeof u.score!="number"&&typeof C.score=="number")return 1;if(typeof u.score=="number"&&typeof C.score!="number")return-1;if(typeof u.score=="number"&&typeof C.score=="number"){if(u.score>C.score)return-1;if(u.scoreC.index?1:0}compareByKindAndScore(u,C){const f=a[u.kind]||l,h=a[C.kind]||l,v=f.localeCompare(h);return v===0?this.compareByScore(u,C):v}async getDocumentSymbols(u,C){const f=await this._outlineModelService.getOrCreate(u,C);return C.isCancellationRequested?[]:f.asListOfDocumentSymbols()}};e.AbstractGotoSymbolQuickAccessProvider=c,e.AbstractGotoSymbolQuickAccessProvider=c=g=ke([ce(0,i.ILanguageFeaturesService),ce(1,n.IOutlineModelService)],c);const l=(0,t.localize)(1207,"properties ({0})"),a={5:(0,t.localize)(1208,"methods ({0})"),11:(0,t.localize)(1209,"functions ({0})"),8:(0,t.localize)(1210,"constructors ({0})"),12:(0,t.localize)(1211,"variables ({0})"),4:(0,t.localize)(1212,"classes ({0})"),22:(0,t.localize)(1213,"structs ({0})"),23:(0,t.localize)(1214,"events ({0})"),24:(0,t.localize)(1215,"operators ({0})"),10:(0,t.localize)(1216,"interfaces ({0})"),2:(0,t.localize)(1217,"namespaces ({0})"),3:(0,t.localize)(1218,"packages ({0})"),25:(0,t.localize)(1219,"type parameters ({0})"),1:(0,t.localize)(1220,"modules ({0})"),6:(0,t.localize)(1221,"properties ({0})"),9:(0,t.localize)(1222,"enumerations ({0})"),21:(0,t.localize)(1223,"enumeration members ({0})"),14:(0,t.localize)(1224,"strings ({0})"),0:(0,t.localize)(1225,"files ({0})"),17:(0,t.localize)(1226,"arrays ({0})"),15:(0,t.localize)(1227,"numbers ({0})"),16:(0,t.localize)(1228,"booleans ({0})"),18:(0,t.localize)(1229,"objects ({0})"),19:(0,t.localize)(1230,"keys ({0})"),7:(0,t.localize)(1231,"fields ({0})"),13:(0,t.localize)(1232,"constants ({0})")}}),define(ne[789],se([1,0,5,47,46,81,44,114,115,13,14,18,26,6,2,54,19,74,9,4,27,3,12,31,62,110,32,25,529]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RenameWidget=e.CONTEXT_RENAME_INPUT_FOCUSED=e.CONTEXT_RENAME_INPUT_VISIBLE=void 0;const L=!1;e.CONTEXT_RENAME_INPUT_VISIBLE=new C.RawContextKey("renameInputVisible",!1,u.localize(1246,"Whether the rename input widget is visible")),e.CONTEXT_RENAME_INPUT_FOCUSED=new C.RawContextKey("renameInputFocused",!1,u.localize(1247,"Whether the rename input widget is focused"));let D=class{constructor(N,O,F,x,W,V){this._editor=N,this._acceptKeybindings=O,this._themeService=F,this._keybindingService=x,this._logService=V,this.allowEditorOverflow=!0,this._disposables=new i.DisposableStore,this._visibleContextKey=e.CONTEXT_RENAME_INPUT_VISIBLE.bindTo(W),this._isEditingRenameCandidate=!1,this._nRenameSuggestionsInvocations=0,this._hadAutomaticRenameSuggestionsInvocation=!1,this._candidates=new Set,this._beforeFirstInputFieldEditSW=new s.StopWatch,this._inputWithButton=new M,this._disposables.add(this._inputWithButton),this._editor.addContentWidget(this),this._disposables.add(this._editor.onDidChangeConfiguration(q=>{q.hasChanged(50)&&this._updateFont()})),this._disposables.add(F.onDidColorThemeChange(this._updateStyles,this))}dispose(){this._disposables.dispose(),this._editor.removeContentWidget(this)}getId(){return"__renameInputWidget"}getDomNode(){return this._domNode||(this._domNode=document.createElement("div"),this._domNode.className="monaco-editor rename-box",this._domNode.appendChild(this._inputWithButton.domNode),this._renameCandidateListView=this._disposables.add(new T(this._domNode,{fontInfo:this._editor.getOption(50),onFocusChange:N=>{this._inputWithButton.input.value=N,this._isEditingRenameCandidate=!1},onSelectionChange:()=>{this._isEditingRenameCandidate=!1,this.acceptInput(!1)}})),this._disposables.add(this._inputWithButton.onDidInputChange(()=>{this._renameCandidateListView?.focusedCandidate!==void 0&&(this._isEditingRenameCandidate=!0),this._timeBeforeFirstInputFieldEdit??=this._beforeFirstInputFieldEditSW.elapsed(),this._renameCandidateProvidersCts?.token.isCancellationRequested===!1&&this._renameCandidateProvidersCts.cancel(),this._renameCandidateListView?.clearFocus()})),this._label=document.createElement("div"),this._label.className="rename-label",this._domNode.appendChild(this._label),this._updateFont(),this._updateStyles(this._themeService.getColorTheme())),this._domNode}_updateStyles(N){if(!this._domNode)return;const O=N.getColor(w.widgetShadow),F=N.getColor(w.widgetBorder);this._domNode.style.backgroundColor=String(N.getColor(w.editorWidgetBackground)??""),this._domNode.style.boxShadow=O?` 0 0 8px 2px ${O}`:"",this._domNode.style.border=F?`1px solid ${F}`:"",this._domNode.style.color=String(N.getColor(w.inputForeground)??"");const x=N.getColor(w.inputBorder);this._inputWithButton.domNode.style.backgroundColor=String(N.getColor(w.inputBackground)??""),this._inputWithButton.input.style.backgroundColor=String(N.getColor(w.inputBackground)??""),this._inputWithButton.domNode.style.borderWidth=x?"1px":"0px",this._inputWithButton.domNode.style.borderStyle=x?"solid":"none",this._inputWithButton.domNode.style.borderColor=x?.toString()??"none"}_updateFont(){if(this._domNode===void 0)return;(0,g.assertType)(this._label!==void 0,"RenameWidget#_updateFont: _label must not be undefined given _domNode is defined"),this._editor.applyFontInfo(this._inputWithButton.input);const N=this._editor.getOption(50);this._label.style.fontSize=`${this._computeLabelFontSize(N.fontSize)}px`}_computeLabelFontSize(N){return N*.8}getPosition(){if(!this._visible||!this._editor.hasModel()||!this._editor.getDomNode())return null;const N=d.getClientArea(this.getDomNode().ownerDocument.body),O=d.getDomNodePagePosition(this._editor.getDomNode()),F=this._getTopForPosition();this._nPxAvailableAbove=F+O.top,this._nPxAvailableBelow=N.height-this._nPxAvailableAbove;const x=this._editor.getOption(67),{totalHeight:W}=A.getLayoutInfo({lineHeight:x}),V=this._nPxAvailableBelow>W*6?[2,1]:[1,2];return{position:this._position,preference:V}}beforeRender(){const[N,O]=this._acceptKeybindings;return this._label.innerText=u.localize(1248,"{0} to Rename, {1} to Preview",this._keybindingService.lookupKeybinding(N)?.getLabel(),this._keybindingService.lookupKeybinding(O)?.getLabel()),this._domNode.style.minWidth="200px",null}afterRender(N){if(N===null){this.cancelInput(!0,"afterRender (because position is null)");return}if(!this._editor.hasModel()||!this._editor.getDomNode())return;(0,g.assertType)(this._renameCandidateListView),(0,g.assertType)(this._nPxAvailableAbove!==void 0),(0,g.assertType)(this._nPxAvailableBelow!==void 0);const O=d.getTotalHeight(this._inputWithButton.domNode),F=d.getTotalHeight(this._label);let x;N===2?x=this._nPxAvailableBelow:x=this._nPxAvailableAbove,this._renameCandidateListView.layout({height:x-F-O,width:d.getTotalWidth(this._inputWithButton.domNode)})}acceptInput(N){this._trace("invoking acceptInput"),this._currentAcceptInput?.(N)}cancelInput(N,O){this._currentCancelInput?.(N)}focusNextRenameSuggestion(){this._renameCandidateListView?.focusNext()||(this._inputWithButton.input.value=this._currentName)}focusPreviousRenameSuggestion(){this._renameCandidateListView?.focusPrevious()||(this._inputWithButton.input.value=this._currentName)}getInput(N,O,F,x,W){const{start:V,end:q}=this._getSelection(N,O);this._renameCts=W;const H=new i.DisposableStore;this._nRenameSuggestionsInvocations=0,this._hadAutomaticRenameSuggestionsInvocation=!1,x===void 0?this._inputWithButton.button.style.display="none":(this._inputWithButton.button.style.display="flex",this._requestRenameCandidatesOnce=x,this._requestRenameCandidates(O,!1),H.add(d.addDisposableListener(this._inputWithButton.button,"click",()=>this._requestRenameCandidates(O,!0))),H.add(d.addDisposableListener(this._inputWithButton.button,d.EventType.KEY_DOWN,U=>{const j=new k.StandardKeyboardEvent(U);(j.equals(3)||j.equals(10))&&(j.stopPropagation(),j.preventDefault(),this._requestRenameCandidates(O,!0))}))),this._isEditingRenameCandidate=!1,this._domNode.classList.toggle("preview",F),this._position=new l.Position(N.startLineNumber,N.startColumn),this._currentName=O,this._inputWithButton.input.value=O,this._inputWithButton.input.setAttribute("selectionStart",V.toString()),this._inputWithButton.input.setAttribute("selectionEnd",q.toString()),this._inputWithButton.input.size=Math.max((N.endColumn-N.startColumn)*1.1,20),this._beforeFirstInputFieldEditSW.reset(),H.add((0,i.toDisposable)(()=>{this._renameCts=void 0,W.dispose(!0)})),H.add((0,i.toDisposable)(()=>{this._renameCandidateProvidersCts!==void 0&&(this._renameCandidateProvidersCts.dispose(!0),this._renameCandidateProvidersCts=void 0)})),H.add((0,i.toDisposable)(()=>this._candidates.clear()));const z=new p.DeferredPromise;return z.p.finally(()=>{H.dispose(),this._hide()}),this._currentCancelInput=U=>(this._trace("invoking _currentCancelInput"),this._currentAcceptInput=void 0,this._currentCancelInput=void 0,this._renameCandidateListView?.clearCandidates(),z.complete(U),!0),this._currentAcceptInput=U=>{this._trace("invoking _currentAcceptInput"),(0,g.assertType)(this._renameCandidateListView!==void 0);const j=this._renameCandidateListView.nCandidates;let Y,G;const K=this._renameCandidateListView.focusedCandidate;if(K!==void 0?(this._trace("using new name from renameSuggestion"),Y=K,G={k:"renameSuggestion"}):(this._trace("using new name from inputField"),Y=this._inputWithButton.input.value,G=this._isEditingRenameCandidate?{k:"userEditedRenameSuggestion"}:{k:"inputField"}),Y===O||Y.trim().length===0){this.cancelInput(!0,"_currentAcceptInput (because newName === value || newName.trim().length === 0)");return}this._currentAcceptInput=void 0,this._currentCancelInput=void 0,this._renameCandidateListView.clearCandidates(),z.complete({newName:Y,wantsPreview:F&&U,stats:{source:G,nRenameSuggestions:j,timeBeforeFirstInputFieldEdit:this._timeBeforeFirstInputFieldEdit,nRenameSuggestionsInvocations:this._nRenameSuggestionsInvocations,hadAutomaticRenameSuggestionsInvocation:this._hadAutomaticRenameSuggestionsInvocation}})},H.add(W.token.onCancellationRequested(()=>this.cancelInput(!0,"cts.token.onCancellationRequested"))),L||H.add(this._editor.onDidBlurEditorWidget(()=>this.cancelInput(!this._domNode?.ownerDocument.hasFocus(),"editor.onDidBlurEditorWidget"))),this._show(),z.p}_requestRenameCandidates(N,O){if(this._requestRenameCandidatesOnce!==void 0&&(this._renameCandidateProvidersCts!==void 0&&this._renameCandidateProvidersCts.dispose(!0),(0,g.assertType)(this._renameCts),this._inputWithButton.buttonState!=="stop")){this._renameCandidateProvidersCts=new n.CancellationTokenSource;const F=O?r.NewSymbolNameTriggerKind.Invoke:r.NewSymbolNameTriggerKind.Automatic,x=this._requestRenameCandidatesOnce(F,this._renameCandidateProvidersCts.token);if(x.length===0){this._inputWithButton.setSparkleButton();return}O||(this._hadAutomaticRenameSuggestionsInvocation=!0),this._nRenameSuggestionsInvocations+=1,this._inputWithButton.setStopButton(),this._updateRenameCandidates(x,N,this._renameCts.token)}}_getSelection(N,O){(0,g.assertType)(this._editor.hasModel());const F=this._editor.getSelection();let x=0,W=O.length;return!a.Range.isEmpty(F)&&!a.Range.spansMultipleLines(F)&&a.Range.containsRange(N,F)&&(x=Math.max(0,F.startColumn-N.startColumn),W=Math.min(N.endColumn,F.endColumn)-N.startColumn),{start:x,end:W}}_show(){this._trace("invoking _show"),this._editor.revealLineInCenterIfOutsideViewport(this._position.lineNumber,0),this._visible=!0,this._visibleContextKey.set(!0),this._editor.layoutContentWidget(this),setTimeout(()=>{this._inputWithButton.input.focus(),this._inputWithButton.input.setSelectionRange(parseInt(this._inputWithButton.input.getAttribute("selectionStart")),parseInt(this._inputWithButton.input.getAttribute("selectionEnd")))},100)}async _updateRenameCandidates(N,O,F){const x=(...z)=>this._trace("_updateRenameCandidates",...z);x("start");const W=await(0,p.raceCancellation)(Promise.allSettled(N),F);if(this._inputWithButton.setSparkleButton(),W===void 0){x("returning early - received updateRenameCandidates results - undefined");return}const V=W.flatMap(z=>z.status==="fulfilled"&&(0,g.isDefined)(z.value)?z.value:[]);x(`received updateRenameCandidates results - total (unfiltered) ${V.length} candidates.`);const q=b.distinct(V,z=>z.newSymbolName);x(`distinct candidates - ${q.length} candidates.`);const H=q.filter(({newSymbolName:z})=>z.trim().length>0&&z!==this._inputWithButton.input.value&&z!==O&&!this._candidates.has(z));if(x(`valid distinct candidates - ${V.length} candidates.`),H.forEach(z=>this._candidates.add(z.newSymbolName)),H.length<1){x("returning early - no valid distinct candidates");return}x("setting candidates"),this._renameCandidateListView.setCandidates(H),x("asking editor to re-layout"),this._editor.layoutContentWidget(this)}_hide(){this._trace("invoked _hide"),this._visible=!1,this._visibleContextKey.reset(),this._editor.layoutContentWidget(this)}_getTopForPosition(){const N=this._editor.getVisibleRanges();let O;return N.length>0?O=N[0].startLineNumber:(this._logService.warn("RenameWidget#_getTopForPosition: this should not happen - visibleRanges is empty"),O=Math.max(1,this._position.lineNumber-5)),this._editor.getTopForLineNumber(this._position.lineNumber)-this._editor.getTopForLineNumber(O)}_trace(...N){this._logService.trace("RenameWidget",...N)}};e.RenameWidget=D,e.RenameWidget=D=ke([ce(2,S.IThemeService),ce(3,f.IKeybindingService),ce(4,C.IContextKeyService),ce(5,h.ILogService)],D);class T{constructor(N,O){this._disposables=new i.DisposableStore,this._availableHeight=0,this._minimumWidth=0,this._lineHeight=O.fontInfo.lineHeight,this._typicalHalfwidthCharacterWidth=O.fontInfo.typicalHalfwidthCharacterWidth,this._listContainer=document.createElement("div"),this._listContainer.className="rename-box rename-candidate-list-container",N.appendChild(this._listContainer),this._listWidget=T._createListWidget(this._listContainer,this._candidateViewHeight,O.fontInfo),this._listWidget.onDidChangeFocus(F=>{F.elements.length===1&&O.onFocusChange(F.elements[0].newSymbolName)},this._disposables),this._listWidget.onDidChangeSelection(F=>{F.elements.length===1&&O.onSelectionChange()},this._disposables),this._disposables.add(this._listWidget.onDidBlur(F=>{this._listWidget.setFocus([])})),this._listWidget.style((0,v.getListStyles)({listInactiveFocusForeground:w.quickInputListFocusForeground,listInactiveFocusBackground:w.quickInputListFocusBackground}))}dispose(){this._listWidget.dispose(),this._disposables.dispose()}layout({height:N,width:O}){this._availableHeight=N,this._minimumWidth=O}setCandidates(N){this._listWidget.splice(0,0,N);const O=this._pickListHeight(this._listWidget.length),F=this._pickListWidth(N);this._listWidget.layout(O,F),this._listContainer.style.height=`${O}px`,this._listContainer.style.width=`${F}px`,I.status(u.localize(1249,"Received {0} rename suggestions",N.length))}clearCandidates(){this._listContainer.style.height="0px",this._listContainer.style.width="0px",this._listWidget.splice(0,this._listWidget.length,[])}get nCandidates(){return this._listWidget.length}get focusedCandidate(){if(this._listWidget.length===0)return;const N=this._listWidget.getSelectedElements()[0];if(N!==void 0)return N.newSymbolName;const O=this._listWidget.getFocusedElements()[0];if(O!==void 0)return O.newSymbolName}focusNext(){if(this._listWidget.length===0)return!1;const N=this._listWidget.getFocus();if(N.length===0)return this._listWidget.focusFirst(),this._listWidget.reveal(0),!0;if(N[0]===this._listWidget.length-1)return this._listWidget.setFocus([]),this._listWidget.reveal(0),!1;{this._listWidget.focusNext();const O=this._listWidget.getFocus()[0];return this._listWidget.reveal(O),!0}}focusPrevious(){if(this._listWidget.length===0)return!1;const N=this._listWidget.getFocus();if(N.length===0){this._listWidget.focusLast();const O=this._listWidget.getFocus()[0];return this._listWidget.reveal(O),!0}else{if(N[0]===0)return this._listWidget.setFocus([]),!1;{this._listWidget.focusPrevious();const O=this._listWidget.getFocus()[0];return this._listWidget.reveal(O),!0}}}clearFocus(){this._listWidget.setFocus([])}get _candidateViewHeight(){const{totalHeight:N}=A.getLayoutInfo({lineHeight:this._lineHeight});return N}_pickListHeight(N){const O=this._candidateViewHeight*N;return Math.min(O,this._availableHeight,this._candidateViewHeight*7)}_pickListWidth(N){const O=Math.ceil(Math.max(...N.map(x=>x.newSymbolName.length))*this._typicalHalfwidthCharacterWidth);return Math.max(this._minimumWidth,25+O+10)}static _createListWidget(N,O,F){const x=new class{getTemplateId(V){return"candidate"}getHeight(V){return O}},W=new class{constructor(){this.templateId="candidate"}renderTemplate(V){return new A(V,F)}renderElement(V,q,H){H.populate(V)}disposeTemplate(V){V.dispose()}};return new _.List("NewSymbolNameCandidates",N,x,[W],{keyboardSupport:!1,mouseSupport:!0,multipleSelectionSupport:!1})}}class M{constructor(){this._onDidInputChange=new t.Emitter,this.onDidInputChange=this._onDidInputChange.event,this._disposables=new i.DisposableStore}get domNode(){return this._domNode||(this._domNode=document.createElement("div"),this._domNode.className="rename-input-with-button",this._domNode.style.display="flex",this._domNode.style.flexDirection="row",this._domNode.style.alignItems="center",this._inputNode=document.createElement("input"),this._inputNode.className="rename-input",this._inputNode.type="text",this._inputNode.style.border="none",this._inputNode.setAttribute("aria-label",u.localize(1250,"Rename input. Type new name and press Enter to commit.")),this._domNode.appendChild(this._inputNode),this._buttonNode=document.createElement("div"),this._buttonNode.className="rename-suggestions-button",this._buttonNode.setAttribute("tabindex","0"),this._buttonGenHoverText=u.localize(1251,"Generate new name suggestions"),this._buttonCancelHoverText=u.localize(1252,"Cancel"),this._buttonHover=(0,E.getBaseLayerHoverDelegate)().setupManagedHover((0,y.getDefaultHoverDelegate)("element"),this._buttonNode,this._buttonGenHoverText),this._disposables.add(this._buttonHover),this._domNode.appendChild(this._buttonNode),this._disposables.add(d.addDisposableListener(this.input,d.EventType.INPUT,()=>this._onDidInputChange.fire())),this._disposables.add(d.addDisposableListener(this.input,d.EventType.KEY_DOWN,N=>{const O=new k.StandardKeyboardEvent(N);(O.keyCode===15||O.keyCode===17)&&this._onDidInputChange.fire()})),this._disposables.add(d.addDisposableListener(this.input,d.EventType.CLICK,()=>this._onDidInputChange.fire())),this._disposables.add(d.addDisposableListener(this.input,d.EventType.FOCUS,()=>{this.domNode.style.outlineWidth="1px",this.domNode.style.outlineStyle="solid",this.domNode.style.outlineOffset="-1px",this.domNode.style.outlineColor="var(--vscode-focusBorder)"})),this._disposables.add(d.addDisposableListener(this.input,d.EventType.BLUR,()=>{this.domNode.style.outline="none"}))),this._domNode}get input(){return(0,g.assertType)(this._inputNode),this._inputNode}get button(){return(0,g.assertType)(this._buttonNode),this._buttonNode}get buttonState(){return this._buttonState}setSparkleButton(){this._buttonState="sparkle",this._sparkleIcon??=(0,m.renderIcon)(o.Codicon.sparkle),d.clearNode(this.button),this.button.appendChild(this._sparkleIcon),this.button.setAttribute("aria-label","Generating new name suggestions"),this._buttonHover?.update(this._buttonGenHoverText),this.input.focus()}setStopButton(){this._buttonState="stop",this._stopIcon??=(0,m.renderIcon)(o.Codicon.primitiveSquare),d.clearNode(this.button),this.button.appendChild(this._stopIcon),this.button.setAttribute("aria-label","Cancel generating new name suggestions"),this._buttonHover?.update(this._buttonCancelHoverText),this.input.focus()}dispose(){this._disposables.dispose()}}class A{static{this._PADDING=2}constructor(N,O){this._domNode=document.createElement("div"),this._domNode.className="rename-box rename-candidate",this._domNode.style.display="flex",this._domNode.style.columnGap="5px",this._domNode.style.alignItems="center",this._domNode.style.height=`${O.lineHeight}px`,this._domNode.style.padding=`${A._PADDING}px`;const F=document.createElement("div");F.style.display="flex",F.style.alignItems="center",F.style.width=F.style.height=`${O.lineHeight*.8}px`,this._domNode.appendChild(F),this._icon=(0,m.renderIcon)(o.Codicon.sparkle),this._icon.style.display="none",F.appendChild(this._icon),this._label=document.createElement("div"),c.applyFontInfo(this._label,O),this._domNode.appendChild(this._label),N.appendChild(this._domNode)}populate(N){this._updateIcon(N),this._updateLabel(N)}_updateIcon(N){const O=!!N.tags?.includes(r.NewSymbolNameTag.AIGenerated);this._icon.style.display=O?"inherit":"none"}_updateLabel(N){this._label.innerText=N.newSymbolName}static getLayoutInfo({lineHeight:N}){return{totalHeight:N+A._PADDING*2}}dispose(){}}}),define(ne[790],se([1,0,46,14,18,8,57,2,19,22,15,152,34,9,4,20,27,17,211,122,184,3,29,109,12,7,62,50,96,38,63,789]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M){"use strict";var A;Object.defineProperty(e,"__esModule",{value:!0}),e.RenameAction=void 0,e.rename=N;class P{constructor(V,q,H){this.model=V,this.position=q,this._providerRenameIdx=0,this._providers=H.ordered(V)}hasProvider(){return this._providers.length>0}async resolveRenameLocation(V){const q=[];for(this._providerRenameIdx=0;this._providerRenameIdx0?q.join(` `):void 0}:{range:i.Range.fromPositions(this.position),text:"",rejectReason:q.length>0?q.join(` `):void 0}}async provideRenameEdits(V,q){return this._provideRenameEdits(V,this._providerRenameIdx,[],q)}async _provideRenameEdits(V,q,H,z){const U=this._providers[q];if(!U)return{edits:[],rejectReason:H.join(` `)};const j=await U.provideRenameEdits(this.model,this.position,V,z);if(j){if(j.rejectReason)return this._provideRenameEdits(V,q+1,H.concat(j.rejectReason),z)}else return this._provideRenameEdits(V,q+1,H.concat(u.localize(1235,"No result.")),z);return j}}async function N(W,V,q,H){const z=new P(V,q,W),U=await z.resolveRenameLocation(I.CancellationToken.None);return U?.rejectReason?{edits:[],rejectReason:U.rejectReason}:z.provideRenameEdits(H,I.CancellationToken.None)}let O=class{static{A=this}static{this.ID="editor.contrib.renameController"}static get(V){return V.getContribution(A.ID)}constructor(V,q,H,z,U,j,Y,G,K){this.editor=V,this._instaService=q,this._notificationService=H,this._bulkEditService=z,this._progressService=U,this._logService=j,this._configService=Y,this._languageFeaturesService=G,this._telemetryService=K,this._disposableStore=new m.DisposableStore,this._cts=new I.CancellationTokenSource,this._renameWidget=this._disposableStore.add(this._instaService.createInstance(M.RenameWidget,this.editor,["acceptRenameInput","acceptRenameInputWithPreview"]))}dispose(){this._disposableStore.dispose(),this._cts.dispose(!0)}async run(){const V=this._logService.trace.bind(this._logService,"[rename]");if(this._cts.dispose(!0),this._cts=new I.CancellationTokenSource,!this.editor.hasModel()){V("editor has no model");return}const q=this.editor.getPosition(),H=new P(this.editor.getModel(),q,this._languageFeaturesService.renameProvider);if(!H.hasProvider()){V("skeleton has no provider");return}const z=new a.EditorStateCancellationTokenSource(this.editor,5,void 0,this._cts.token);let U;try{V("resolving rename location");const he=H.resolveRenameLocation(z.token);this._progressService.showWhile(he,250),U=await he,V("resolved rename location")}catch(he){he instanceof E.CancellationError?V("resolve rename location cancelled",JSON.stringify(he,null," ")):(V("resolve rename location failed",he instanceof Error?he:JSON.stringify(he,null," ")),(typeof he=="string"||(0,y.isMarkdownString)(he))&&r.MessageController.get(this.editor)?.showMessage(he||u.localize(1236,"An unknown error occurred while resolving rename location"),q));return}finally{z.dispose()}if(!U){V("returning early - no loc");return}if(U.rejectReason){V(`returning early - rejected with reason: ${U.rejectReason}`,U.rejectReason),r.MessageController.get(this.editor)?.showMessage(U.rejectReason,q);return}if(z.token.isCancellationRequested){V("returning early - cts1 cancelled");return}const j=new a.EditorStateCancellationTokenSource(this.editor,5,U.range,this._cts.token),Y=this.editor.getModel(),G=this._languageFeaturesService.newSymbolNamesProvider.all(Y),K=await Promise.all(G.map(async he=>[he,await he.supportsAutomaticNewSymbolNamesTriggerKind??!1])),R=(he,pe)=>{let ae=K.slice();return he===g.NewSymbolNameTriggerKind.Automatic&&(ae=ae.filter(([ee,de])=>de)),ae.map(([ee])=>ee.provideNewSymbolNames(Y,U.range,he,pe))};V("creating rename input field and awaiting its result");const J=this._bulkEditService.hasPreviewHandler()&&this._configService.getValue(this.editor.getModel().uri,"editor.rename.enablePreview"),ie=await this._renameWidget.getInput(U.range,U.text,J,G.length>0?R:void 0,j);if(V("received response from rename input field"),G.length>0&&this._reportTelemetry(G.length,Y.getLanguageId(),ie),typeof ie=="boolean"){V(`returning early - rename input field response - ${ie}`),ie&&this.editor.focus(),j.dispose();return}this.editor.focus(),V("requesting rename edits");const ue=(0,k.raceCancellation)(H.provideRenameEdits(ie.newName,j.token),j.token).then(async he=>{if(!he){V("returning early - no rename edits result");return}if(!this.editor.hasModel()){V("returning early - no model after rename edits are provided");return}if(he.rejectReason){V(`returning early - rejected with reason: ${he.rejectReason}`),this._notificationService.info(he.rejectReason);return}this.editor.setSelection(i.Range.fromPositions(this.editor.getSelection().getPosition())),V("applying edits"),this._bulkEditService.apply(he,{editor:this.editor,showPreview:ie.wantsPreview,label:u.localize(1237,"Renaming '{0}' to '{1}'",U?.text,ie.newName),code:"undoredo.rename",quotableLabel:u.localize(1238,"Renaming {0} to {1}",U?.text,ie.newName),respectAutoSaveConfig:!0}).then(pe=>{V("edits applied"),pe.ariaSummary&&(0,d.alert)(u.localize(1239,"Successfully renamed '{0}' to '{1}'. Summary: {2}",U.text,ie.newName,pe.ariaSummary))}).catch(pe=>{V(`error when applying edits ${JSON.stringify(pe,null," ")}`),this._notificationService.error(u.localize(1240,"Rename failed to apply edits")),this._logService.error(pe)})},he=>{V("error when providing rename edits",JSON.stringify(he,null," ")),this._notificationService.error(u.localize(1241,"Rename failed to compute edits")),this._logService.error(he)}).finally(()=>{j.dispose()});return V("returning rename operation"),this._progressService.showWhile(ue,250),ue}acceptRenameInput(V){this._renameWidget.acceptInput(V)}cancelRenameInput(){this._renameWidget.cancelInput(!0,"cancelRenameInput command")}focusNextRenameSuggestion(){this._renameWidget.focusNextRenameSuggestion()}focusPreviousRenameSuggestion(){this._renameWidget.focusPreviousRenameSuggestion()}_reportTelemetry(V,q,H){const z=typeof H=="boolean"?{kind:"cancelled",languageId:q,nRenameSuggestionProviders:V}:{kind:"accepted",languageId:q,nRenameSuggestionProviders:V,source:H.stats.source.k,nRenameSuggestions:H.stats.nRenameSuggestions,timeBeforeFirstInputFieldEdit:H.stats.timeBeforeFirstInputFieldEdit,wantsPreview:H.wantsPreview,nRenameSuggestionsInvocations:H.stats.nRenameSuggestionsInvocations,hadAutomaticRenameSuggestionsInvocation:H.stats.hadAutomaticRenameSuggestionsInvocation};this._telemetryService.publicLog2("renameInvokedEvent",z)}};O=A=ke([ce(1,v.IInstantiationService),ce(2,S.INotificationService),ce(3,n.IBulkEditService),ce(4,L.IEditorProgressService),ce(5,w.ILogService),ce(6,l.ITextResourceConfigurationService),ce(7,c.ILanguageFeaturesService),ce(8,T.ITelemetryService)],O);class F extends p.EditorAction{constructor(){super({id:"editor.action.rename",label:u.localize(1242,"Rename Symbol"),alias:"Rename Symbol",precondition:h.ContextKeyExpr.and(s.EditorContextKeys.writable,s.EditorContextKeys.hasRenameProvider),kbOpts:{kbExpr:s.EditorContextKeys.editorTextFocus,primary:60,weight:100},contextMenuOpts:{group:"1_modification",order:1.1}})}runCommand(V,q){const H=V.get(o.ICodeEditorService),[z,U]=Array.isArray(q)&&q||[void 0,void 0];return b.URI.isUri(z)&&t.Position.isIPosition(U)?H.openCodeEditor({resource:z},H.getActiveCodeEditor()).then(j=>{j&&(j.setPosition(U),j.invokeWithinContext(Y=>(this.reportTelemetry(Y,j),this.run(Y,j))))},E.onUnexpectedError):super.runCommand(V,q)}run(V,q){const H=V.get(w.ILogService),z=O.get(q);return z?(H.trace("[RenameAction] got controller, running..."),z.run()):(H.trace("[RenameAction] returning early - controller missing"),Promise.resolve())}}e.RenameAction=F,(0,p.registerEditorContribution)(O.ID,O,4),(0,p.registerEditorAction)(F);const x=p.EditorCommand.bindToContribution(O.get);(0,p.registerEditorCommand)(new x({id:"acceptRenameInput",precondition:M.CONTEXT_RENAME_INPUT_VISIBLE,handler:W=>W.acceptRenameInput(!1),kbOpts:{weight:199,kbExpr:h.ContextKeyExpr.and(s.EditorContextKeys.focus,h.ContextKeyExpr.not("isComposing")),primary:3}})),(0,p.registerEditorCommand)(new x({id:"acceptRenameInputWithPreview",precondition:h.ContextKeyExpr.and(M.CONTEXT_RENAME_INPUT_VISIBLE,h.ContextKeyExpr.has("config.editor.rename.enablePreview")),handler:W=>W.acceptRenameInput(!0),kbOpts:{weight:199,kbExpr:h.ContextKeyExpr.and(s.EditorContextKeys.focus,h.ContextKeyExpr.not("isComposing")),primary:2051}})),(0,p.registerEditorCommand)(new x({id:"cancelRenameInput",precondition:M.CONTEXT_RENAME_INPUT_VISIBLE,handler:W=>W.cancelRenameInput(),kbOpts:{weight:199,kbExpr:s.EditorContextKeys.focus,primary:9,secondary:[1033]}})),(0,C.registerAction2)(class extends C.Action2{constructor(){super({id:"focusNextRenameSuggestion",title:{...u.localize2(1244,"Focus Next Rename Suggestion")},precondition:M.CONTEXT_RENAME_INPUT_VISIBLE,keybinding:[{primary:18,weight:199}]})}run(V){const q=V.get(o.ICodeEditorService).getFocusedCodeEditor();if(!q)return;const H=O.get(q);H&&H.focusNextRenameSuggestion()}}),(0,C.registerAction2)(class extends C.Action2{constructor(){super({id:"focusPreviousRenameSuggestion",title:{...u.localize2(1245,"Focus Previous Rename Suggestion")},precondition:M.CONTEXT_RENAME_INPUT_VISIBLE,keybinding:[{primary:16,weight:199}]})}run(V){const q=V.get(o.ICodeEditorService).getFocusedCodeEditor();if(!q)return;const H=O.get(q);H&&H.focusPreviousRenameSuggestion()}}),(0,p.registerModelAndPositionCommand)("_executeDocumentRenameProvider",function(W,V,q,...H){const[z]=H;(0,_.assertType)(typeof z=="string");const{renameProvider:U}=W.get(c.ILanguageFeaturesService);return N(U,V,q,z)}),(0,p.registerModelAndPositionCommand)("_executePrepareRename",async function(W,V,q){const{renameProvider:H}=W.get(c.ILanguageFeaturesService),U=await new P(V,q,H).resolveRenameLocation(I.CancellationToken.None);if(U?.rejectReason)throw new Error(U.rejectReason);return U}),D.Registry.as(f.Extensions.Configuration).registerConfiguration({id:"editor",properties:{"editor.rename.enablePreview":{scope:5,description:u.localize(1243,"Enable/disable the ability to preview changes before renaming"),default:!0,type:"boolean"}}})}),define(ne[791],se([1,0,2,8,51,28,14,18,25,282,387,79,54,17,267,130,339]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";var c;Object.defineProperty(e,"__esModule",{value:!0}),e.DocumentSemanticTokensFeature=void 0;let l=class extends d.Disposable{constructor(C,f,h,v,w,S){super(),this._watchers=Object.create(null);const L=M=>{this._watchers[M.uri.toString()]=new a(M,C,h,w,S)},D=(M,A)=>{A.dispose(),delete this._watchers[M.uri.toString()]},T=()=>{for(const M of f.getModels()){const A=this._watchers[M.uri.toString()];(0,g.isSemanticColoringEnabled)(M,h,v)?A||L(M):A&&D(M,A)}};f.getModels().forEach(M=>{(0,g.isSemanticColoringEnabled)(M,h,v)&&L(M)}),this._register(f.onModelAdded(M=>{(0,g.isSemanticColoringEnabled)(M,h,v)&&L(M)})),this._register(f.onModelRemoved(M=>{const A=this._watchers[M.uri.toString()];A&&D(M,A)})),this._register(v.onDidChangeConfiguration(M=>{M.affectsConfiguration(g.SEMANTIC_HIGHLIGHTING_SETTING_ID)&&T()})),this._register(h.onDidColorThemeChange(T))}dispose(){for(const C of Object.values(this._watchers))C.dispose();super.dispose()}};e.DocumentSemanticTokensFeature=l,e.DocumentSemanticTokensFeature=l=ke([ce(0,i.ISemanticTokensStylingService),ce(1,I.IModelService),ce(2,_.IThemeService),ce(3,E.IConfigurationService),ce(4,n.ILanguageFeatureDebounceService),ce(5,t.ILanguageFeaturesService)],l);let a=class extends d.Disposable{static{c=this}static{this.REQUEST_MIN_DELAY=300}static{this.REQUEST_MAX_DELAY=2e3}constructor(C,f,h,v,w){super(),this._semanticTokensStylingService=f,this._isDisposed=!1,this._model=C,this._provider=w.documentSemanticTokensProvider,this._debounceInformation=v.for(this._provider,"DocumentSemanticTokens",{min:c.REQUEST_MIN_DELAY,max:c.REQUEST_MAX_DELAY}),this._fetchDocumentSemanticTokens=this._register(new y.RunOnceScheduler(()=>this._fetchDocumentSemanticTokensNow(),c.REQUEST_MIN_DELAY)),this._currentDocumentResponse=null,this._currentDocumentRequestCancellationTokenSource=null,this._documentProvidersChangeListeners=[],this._providersChangedDuringRequest=!1,this._register(this._model.onDidChangeContent(()=>{this._fetchDocumentSemanticTokens.isScheduled()||this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model))})),this._register(this._model.onDidChangeAttached(()=>{this._fetchDocumentSemanticTokens.isScheduled()||this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model))})),this._register(this._model.onDidChangeLanguage(()=>{this._currentDocumentResponse&&(this._currentDocumentResponse.dispose(),this._currentDocumentResponse=null),this._currentDocumentRequestCancellationTokenSource&&(this._currentDocumentRequestCancellationTokenSource.cancel(),this._currentDocumentRequestCancellationTokenSource=null),this._setDocumentSemanticTokens(null,null,null,[]),this._fetchDocumentSemanticTokens.schedule(0)}));const S=()=>{(0,d.dispose)(this._documentProvidersChangeListeners),this._documentProvidersChangeListeners=[];for(const L of this._provider.all(C))typeof L.onDidChange=="function"&&this._documentProvidersChangeListeners.push(L.onDidChange(()=>{if(this._currentDocumentRequestCancellationTokenSource){this._providersChangedDuringRequest=!0;return}this._fetchDocumentSemanticTokens.schedule(0)}))};S(),this._register(this._provider.onDidChange(()=>{S(),this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model))})),this._register(h.onDidColorThemeChange(L=>{this._setDocumentSemanticTokens(null,null,null,[]),this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model))})),this._fetchDocumentSemanticTokens.schedule(0)}dispose(){this._currentDocumentResponse&&(this._currentDocumentResponse.dispose(),this._currentDocumentResponse=null),this._currentDocumentRequestCancellationTokenSource&&(this._currentDocumentRequestCancellationTokenSource.cancel(),this._currentDocumentRequestCancellationTokenSource=null),(0,d.dispose)(this._documentProvidersChangeListeners),this._documentProvidersChangeListeners=[],this._setDocumentSemanticTokens(null,null,null,[]),this._isDisposed=!0,super.dispose()}_fetchDocumentSemanticTokensNow(){if(this._currentDocumentRequestCancellationTokenSource)return;if(!(0,p.hasDocumentSemanticTokensProvider)(this._provider,this._model)){this._currentDocumentResponse&&this._model.tokenization.setSemanticTokens(null,!1);return}if(!this._model.isAttachedToEditor())return;const C=new m.CancellationTokenSource,f=this._currentDocumentResponse?this._currentDocumentResponse.provider:null,h=this._currentDocumentResponse&&this._currentDocumentResponse.resultId||null,v=(0,p.getDocumentSemanticTokens)(this._provider,this._model,f,h,C.token);this._currentDocumentRequestCancellationTokenSource=C,this._providersChangedDuringRequest=!1;const w=[],S=this._model.onDidChangeContent(D=>{w.push(D)}),L=new o.StopWatch(!1);v.then(D=>{if(this._debounceInformation.update(this._model,L.elapsed()),this._currentDocumentRequestCancellationTokenSource=null,S.dispose(),!D)this._setDocumentSemanticTokens(null,null,null,w);else{const{provider:T,tokens:M}=D,A=this._semanticTokensStylingService.getStyling(T);this._setDocumentSemanticTokens(T,M||null,A,w)}},D=>{D&&(k.isCancellationError(D)||typeof D.message=="string"&&D.message.indexOf("busy")!==-1)||k.onUnexpectedError(D),this._currentDocumentRequestCancellationTokenSource=null,S.dispose(),(w.length>0||this._providersChangedDuringRequest)&&(this._fetchDocumentSemanticTokens.isScheduled()||this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model)))})}static _copy(C,f,h,v,w){w=Math.min(w,h.length-v,C.length-f);for(let S=0;S{(v.length>0||this._providersChangedDuringRequest)&&!this._fetchDocumentSemanticTokens.isScheduled()&&this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model))};if(this._currentDocumentResponse&&(this._currentDocumentResponse.dispose(),this._currentDocumentResponse=null),this._isDisposed){C&&f&&C.releaseDocumentSemanticTokens(f.resultId);return}if(!C||!h){this._model.tokenization.setSemanticTokens(null,!1);return}if(!f){this._model.tokenization.setSemanticTokens(null,!0),S();return}if((0,p.isSemanticTokensEdits)(f)){if(!w){this._model.tokenization.setSemanticTokens(null,!0);return}if(f.edits.length===0)f={resultId:f.resultId,data:w.data};else{let L=0;for(const P of f.edits)L+=(P.data?P.data.length:0)-P.deleteCount;const D=w.data,T=new Uint32Array(D.length+L);let M=D.length,A=T.length;for(let P=f.edits.length-1;P>=0;P--){const N=f.edits[P];if(N.start>D.length){h.warnInvalidEditStart(w.resultId,f.resultId,P,N.start,D.length),this._model.tokenization.setSemanticTokens(null,!0);return}const O=M-(N.start+N.deleteCount);O>0&&(c._copy(D,M-O,T,A-O,O),A-=O),N.data&&(c._copy(N.data,0,T,A-N.data.length,N.data.length),A-=N.data.length),M=N.start}M>0&&c._copy(D,0,T,0,M),f={resultId:f.resultId,data:T}}}if((0,p.isSemanticTokens)(f)){this._currentDocumentResponse=new r(C,f.resultId,f.data);const L=(0,b.toMultilineTokens2)(f,h,this._model.getLanguageId());if(v.length>0)for(const D of v)for(const T of L)for(const M of D.changes)T.applyEdit(M.range,M.text);this._model.tokenization.setSemanticTokens(L,!0)}else this._model.tokenization.setSemanticTokens(null,!0);S()}};a=c=ke([ce(1,i.ISemanticTokensStylingService),ce(2,_.IThemeService),ce(3,n.ILanguageFeatureDebounceService),ce(4,t.ILanguageFeaturesService)],a);class r{constructor(C,f,h){this.provider=C,this.resultId=f,this.data=h}dispose(){this.provider.releaseDocumentSemanticTokens(this.resultId)}}(0,s.registerEditorFeature)(l)}),define(ne[792],se([1,0,14,2,15,387,339,282,28,25,79,54,17,267]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewportSemanticTokensContribution=void 0;let i=class extends k.Disposable{static{this.ID="editor.contrib.viewportSemanticTokens"}constructor(g,c,l,a,r,u){super(),this._semanticTokensStylingService=c,this._themeService=l,this._configurationService=a,this._editor=g,this._provider=u.documentRangeSemanticTokensProvider,this._debounceInformation=r.for(this._provider,"DocumentRangeSemanticTokens",{min:100,max:500}),this._tokenizeViewport=this._register(new d.RunOnceScheduler(()=>this._tokenizeViewportNow(),100)),this._outstandingRequests=[];const C=()=>{this._editor.hasModel()&&this._tokenizeViewport.schedule(this._debounceInformation.get(this._editor.getModel()))};this._register(this._editor.onDidScrollChange(()=>{C()})),this._register(this._editor.onDidChangeModel(()=>{this._cancelAll(),C()})),this._register(this._editor.onDidChangeModelContent(f=>{this._cancelAll(),C()})),this._register(this._provider.onDidChange(()=>{this._cancelAll(),C()})),this._register(this._configurationService.onDidChangeConfiguration(f=>{f.affectsConfiguration(y.SEMANTIC_HIGHLIGHTING_SETTING_ID)&&(this._cancelAll(),C())})),this._register(this._themeService.onDidColorThemeChange(()=>{this._cancelAll(),C()})),C()}_cancelAll(){for(const g of this._outstandingRequests)g.cancel();this._outstandingRequests=[]}_removeOutstandingRequest(g){for(let c=0,l=this._outstandingRequests.length;cthis._requestRange(g,l)))}_requestRange(g,c){const l=g.getVersionId(),a=(0,d.createCancelablePromise)(u=>Promise.resolve((0,E.getDocumentRangeSemanticTokens)(this._provider,g,c,u))),r=new n.StopWatch(!1);return a.then(u=>{if(this._debounceInformation.update(g,r.elapsed()),!u||!u.tokens||g.isDisposed()||g.getVersionId()!==l)return;const{provider:C,tokens:f}=u,h=this._semanticTokensStylingService.getStyling(C);g.tokenization.setPartialSemanticTokens(c,(0,m.toMultilineTokens2)(f,h,g.getLanguageId()))}).then(()=>this._removeOutstandingRequest(a),()=>this._removeOutstandingRequest(a)),a}};e.ViewportSemanticTokensContribution=i,e.ViewportSemanticTokensContribution=i=ke([ce(1,t.ISemanticTokensStylingService),ce(2,b.IThemeService),ce(3,_.IConfigurationService),ce(4,p.ILanguageFeatureDebounceService),ce(5,o.ILanguageFeaturesService)],i),(0,I.registerEditorContribution)(i.ID,i,1)}),define(ne[793],se([1,0,5,254,26,30,6,82,2,22,27,708,51,43,3,382,71,25,402]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ItemRenderer=void 0,e.getAriaId=a;function a(h){return`suggest-aria-id:${h}`}const r=(0,g.registerIcon)("suggest-more-info",I.Codicon.chevronRight,i.localize(1346,"Icon for more information in the suggest widget.")),u=new class xt{static{this._regexRelaxed=/(#([\da-fA-F]{3}){1,2}|(rgb|hsl)a\(\s*(\d{1,3}%?\s*,\s*){3}(1|0?\.\d+)\)|(rgb|hsl)\(\s*\d{1,3}%?(\s*,\s*\d{1,3}%?){2}\s*\))/}static{this._regexStrict=new RegExp(`^${xt._regexRelaxed.source}$`,"i")}extract(v,w){if(v.textLabel.match(xt._regexStrict))return w[0]=v.textLabel,!0;if(v.completion.detail&&v.completion.detail.match(xt._regexStrict))return w[0]=v.completion.detail,!0;if(v.completion.documentation){const S=typeof v.completion.documentation=="string"?v.completion.documentation:v.completion.documentation.value,L=xt._regexRelaxed.exec(S);if(L&&(L.index===0||L.index+L[0].length===S.length))return w[0]=L[0],!0}return!1}};let C=class{constructor(v,w,S,L){this._editor=v,this._modelService=w,this._languageService=S,this._themeService=L,this._onDidToggleDetails=new y.Emitter,this.onDidToggleDetails=this._onDidToggleDetails.event,this.templateId="suggestion"}dispose(){this._onDidToggleDetails.dispose()}renderTemplate(v){const w=new _.DisposableStore,S=v;S.classList.add("show-file-icons");const L=(0,d.append)(v,(0,d.$)(".icon")),D=(0,d.append)(L,(0,d.$)("span.colorspan")),T=(0,d.append)(v,(0,d.$)(".contents")),M=(0,d.append)(T,(0,d.$)(".main")),A=(0,d.append)(M,(0,d.$)(".icon-label.codicon")),P=(0,d.append)(M,(0,d.$)("span.left")),N=(0,d.append)(M,(0,d.$)("span.right")),O=new k.IconLabel(P,{supportHighlights:!0,supportIcons:!0});w.add(O);const F=(0,d.append)(P,(0,d.$)("span.signature-label")),x=(0,d.append)(P,(0,d.$)("span.qualifier-label")),W=(0,d.append)(N,(0,d.$)("span.details-label")),V=(0,d.append)(N,(0,d.$)("span.readMore"+E.ThemeIcon.asCSSSelector(r)));return V.title=i.localize(1347,"Read More"),{root:S,left:P,right:N,icon:L,colorspan:D,iconLabel:O,iconContainer:A,parametersLabel:F,qualifierLabel:x,detailsLabel:W,readMore:V,disposables:w,configureFont:()=>{const H=this._editor.getOptions(),z=H.get(50),U=z.getMassagedFontFamily(),j=z.fontFeatureSettings,Y=H.get(120)||z.fontSize,G=H.get(121)||z.lineHeight,K=z.fontWeight,R=z.letterSpacing,J=`${Y}px`,ie=`${G}px`,ue=`${R}px`;S.style.fontSize=J,S.style.fontWeight=K,S.style.letterSpacing=ue,M.style.fontFamily=U,M.style.fontFeatureSettings=j,M.style.lineHeight=ie,L.style.height=ie,L.style.width=ie,V.style.height=ie,V.style.width=ie}}}renderElement(v,w,S){S.configureFont();const{completion:L}=v;S.root.id=a(w),S.colorspan.style.backgroundColor="";const D={labelEscapeNewLines:!0,matches:(0,m.createMatches)(v.score)},T=[];if(L.kind===19&&u.extract(v,T))S.icon.className="icon customcolor",S.iconContainer.className="icon hide",S.colorspan.style.backgroundColor=T[0];else if(L.kind===20&&this._themeService.getFileIconTheme().hasFileIcons){S.icon.className="icon hide",S.iconContainer.className="icon hide";const M=(0,n.getIconClasses)(this._modelService,this._languageService,b.URI.from({scheme:"fake",path:v.textLabel}),s.FileKind.FILE),A=(0,n.getIconClasses)(this._modelService,this._languageService,b.URI.from({scheme:"fake",path:L.detail}),s.FileKind.FILE);D.extraClasses=M.length>A.length?M:A}else L.kind===23&&this._themeService.getFileIconTheme().hasFolderIcons?(S.icon.className="icon hide",S.iconContainer.className="icon hide",D.extraClasses=[(0,n.getIconClasses)(this._modelService,this._languageService,b.URI.from({scheme:"fake",path:v.textLabel}),s.FileKind.FOLDER),(0,n.getIconClasses)(this._modelService,this._languageService,b.URI.from({scheme:"fake",path:L.detail}),s.FileKind.FOLDER)].flat()):(S.icon.className="icon hide",S.iconContainer.className="",S.iconContainer.classList.add("suggest-icon",...E.ThemeIcon.asClassNameArray(p.CompletionItemKinds.toIcon(L.kind))));L.tags&&L.tags.indexOf(1)>=0&&(D.extraClasses=(D.extraClasses||[]).concat(["deprecated"]),D.matches=[]),S.iconLabel.setLabel(v.textLabel,void 0,D),typeof L.label=="string"?(S.parametersLabel.textContent="",S.detailsLabel.textContent=f(L.detail||""),S.root.classList.add("string-label")):(S.parametersLabel.textContent=f(L.label.detail||""),S.detailsLabel.textContent=f(L.label.description||""),S.root.classList.remove("string-label")),this._editor.getOption(119).showInlineDetails?(0,d.show)(S.detailsLabel):(0,d.hide)(S.detailsLabel),(0,l.canExpandCompletionItem)(v)?(S.right.classList.add("can-expand-details"),(0,d.show)(S.readMore),S.readMore.onmousedown=M=>{M.stopPropagation(),M.preventDefault()},S.readMore.onclick=M=>{M.stopPropagation(),M.preventDefault(),this._onDidToggleDetails.fire()}):(S.right.classList.remove("can-expand-details"),(0,d.hide)(S.readMore),S.readMore.onmousedown=null,S.readMore.onclick=null)}disposeTemplate(v){v.disposables.dispose()}};e.ItemRenderer=C,e.ItemRenderer=C=ke([ce(1,o.IModelService),ce(2,t.ILanguageService),ce(3,c.IThemeService)],C);function f(h){return h.replace(/\r\n|\r|\n/g,"")}}),define(ne[794],se([1,0,787,38,156,34,107,6,15,20,66]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GotoLineAction=e.StandaloneGotoLineQuickAccessProvider=void 0;let n=class extends d.AbstractGotoLineQuickAccessProvider{constructor(i){super(),this.editorService=i,this.onDidActiveTextEditorControlChange=m.Event.None}get activeTextEditorControl(){return this.editorService.getFocusedCodeEditor()??void 0}};e.StandaloneGotoLineQuickAccessProvider=n,e.StandaloneGotoLineQuickAccessProvider=n=ke([ce(0,E.ICodeEditorService)],n);class o extends _.EditorAction{static{this.ID="editor.action.gotoLine"}constructor(){super({id:o.ID,label:y.GoToLineNLS.gotoLineActionLabel,alias:"Go to Line/Column...",precondition:void 0,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:2085,mac:{primary:293},weight:100}})}run(i){i.get(p.IQuickInputService).quickAccess.show(n.PREFIX)}}e.GotoLineAction=o,(0,_.registerEditorAction)(o),k.Registry.as(I.Extensions.Quickaccess).registerQuickAccessProvider({ctor:n,prefix:n.PREFIX,helpEntries:[{description:y.GoToLineNLS.gotoLineActionLabel,commandId:o.ID}]})}),define(ne[795],se([1,0,788,38,156,34,107,6,15,20,66,182,17,195,280]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GotoSymbolAction=e.StandaloneGotoSymbolQuickAccessProvider=void 0;let t=class extends d.AbstractGotoSymbolQuickAccessProvider{constructor(g,c,l){super(c,l),this.editorService=g,this.onDidActiveTextEditorControlChange=m.Event.None}get activeTextEditorControl(){return this.editorService.getFocusedCodeEditor()??void 0}};e.StandaloneGotoSymbolQuickAccessProvider=t,e.StandaloneGotoSymbolQuickAccessProvider=t=ke([ce(0,E.ICodeEditorService),ce(1,o.ILanguageFeaturesService),ce(2,n.IOutlineModelService)],t);class i extends _.EditorAction{static{this.ID="editor.action.quickOutline"}constructor(){super({id:i.ID,label:y.QuickOutlineNLS.quickOutlineActionLabel,alias:"Go to Symbol...",precondition:b.EditorContextKeys.hasDocumentSymbolProvider,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:3117,weight:100},contextMenuOpts:{group:"navigation",order:3}})}run(g){g.get(p.IQuickInputService).quickAccess.show(d.AbstractGotoSymbolQuickAccessProvider.PREFIX,{itemActivation:p.ItemActivation.NONE})}}e.GotoSymbolAction=i,(0,_.registerEditorAction)(i),k.Registry.as(I.Extensions.Quickaccess).registerQuickAccessProvider({ctor:t,prefix:d.AbstractGotoSymbolQuickAccessProvider.PREFIX,helpEntries:[{description:y.QuickOutlineNLS.quickOutlineActionLabel,prefix:d.AbstractGotoSymbolQuickAccessProvider.PREFIX,commandId:i.ID},{description:y.QuickOutlineNLS.quickOutlineByCategoryActionLabel,prefix:d.AbstractGotoSymbolQuickAccessProvider.PREFIX_BY_CATEGORY}]})}),define(ne[418],se([1,0,5,42,771,34,12,49,25]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneCodeEditorService=void 0;let b=class extends I.AbstractCodeEditorService{constructor(n,o){super(o),this._register(this.onCodeEditorAdd(()=>this._checkContextKey())),this._register(this.onCodeEditorRemove(()=>this._checkContextKey())),this._editorIsOpen=n.createKey("editorIsOpen",!1),this._activeCodeEditor=null,this._register(this.registerCodeEditorOpenHandler(async(t,i,s)=>i?this.doOpenEditor(i,t):null))}_checkContextKey(){let n=!1;for(const o of this.listCodeEditors())if(!o.isSimpleWidget){n=!0;break}this._editorIsOpen.set(n)}setActiveCodeEditor(n){this._activeCodeEditor=n}getActiveCodeEditor(){return this._activeCodeEditor}doOpenEditor(n,o){if(!this.findModel(n,o.resource)){if(o.resource){const s=o.resource.scheme;if(s===k.Schemas.http||s===k.Schemas.https)return(0,d.windowOpenNoOpener)(o.resource.toString()),n}return null}const i=o.options?o.options.selection:null;if(i)if(typeof i.endLineNumber=="number"&&typeof i.endColumn=="number")n.setSelection(i),n.revealRangeInCenter(i,1);else{const s={lineNumber:i.startLineNumber,column:i.startColumn};n.setPosition(s),n.revealPositionInCenter(s,1)}return n}findModel(n,o){const t=n.getModel();return t&&t.uri.toString()!==o.toString()?null:t}};e.StandaloneCodeEditorService=b,e.StandaloneCodeEditorService=b=ke([ce(0,y.IContextKeyService),ce(1,_.IThemeService)],b),(0,m.registerSingleton)(E.ICodeEditorService,b,0)}),define(ne[796],se([1,0,80,32]),function(oe,e,d,k){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.hc_light=e.hc_black=e.vs_dark=e.vs=void 0,e.vs={base:"vs",inherit:!1,rules:[{token:"",foreground:"000000",background:"fffffe"},{token:"invalid",foreground:"cd3131"},{token:"emphasis",fontStyle:"italic"},{token:"strong",fontStyle:"bold"},{token:"variable",foreground:"001188"},{token:"variable.predefined",foreground:"4864AA"},{token:"constant",foreground:"dd0000"},{token:"comment",foreground:"008000"},{token:"number",foreground:"098658"},{token:"number.hex",foreground:"3030c0"},{token:"regexp",foreground:"800000"},{token:"annotation",foreground:"808080"},{token:"type",foreground:"008080"},{token:"delimiter",foreground:"000000"},{token:"delimiter.html",foreground:"383838"},{token:"delimiter.xml",foreground:"0000FF"},{token:"tag",foreground:"800000"},{token:"tag.id.pug",foreground:"4F76AC"},{token:"tag.class.pug",foreground:"4F76AC"},{token:"meta.scss",foreground:"800000"},{token:"metatag",foreground:"e00000"},{token:"metatag.content.html",foreground:"FF0000"},{token:"metatag.html",foreground:"808080"},{token:"metatag.xml",foreground:"808080"},{token:"metatag.php",fontStyle:"bold"},{token:"key",foreground:"863B00"},{token:"string.key.json",foreground:"A31515"},{token:"string.value.json",foreground:"0451A5"},{token:"attribute.name",foreground:"FF0000"},{token:"attribute.value",foreground:"0451A5"},{token:"attribute.value.number",foreground:"098658"},{token:"attribute.value.unit",foreground:"098658"},{token:"attribute.value.html",foreground:"0000FF"},{token:"attribute.value.xml",foreground:"0000FF"},{token:"string",foreground:"A31515"},{token:"string.html",foreground:"0000FF"},{token:"string.sql",foreground:"FF0000"},{token:"string.yaml",foreground:"0451A5"},{token:"keyword",foreground:"0000FF"},{token:"keyword.json",foreground:"0451A5"},{token:"keyword.flow",foreground:"AF00DB"},{token:"keyword.flow.scss",foreground:"0000FF"},{token:"operator.scss",foreground:"666666"},{token:"operator.sql",foreground:"778899"},{token:"operator.swift",foreground:"666666"},{token:"predefined.sql",foreground:"C700C7"}],colors:{[k.editorBackground]:"#FFFFFE",[k.editorForeground]:"#000000",[k.editorInactiveSelection]:"#E5EBF1",[d.editorIndentGuide1]:"#D3D3D3",[d.editorActiveIndentGuide1]:"#939393",[k.editorSelectionHighlight]:"#ADD6FF4D"}},e.vs_dark={base:"vs-dark",inherit:!1,rules:[{token:"",foreground:"D4D4D4",background:"1E1E1E"},{token:"invalid",foreground:"f44747"},{token:"emphasis",fontStyle:"italic"},{token:"strong",fontStyle:"bold"},{token:"variable",foreground:"74B0DF"},{token:"variable.predefined",foreground:"4864AA"},{token:"variable.parameter",foreground:"9CDCFE"},{token:"constant",foreground:"569CD6"},{token:"comment",foreground:"608B4E"},{token:"number",foreground:"B5CEA8"},{token:"number.hex",foreground:"5BB498"},{token:"regexp",foreground:"B46695"},{token:"annotation",foreground:"cc6666"},{token:"type",foreground:"3DC9B0"},{token:"delimiter",foreground:"DCDCDC"},{token:"delimiter.html",foreground:"808080"},{token:"delimiter.xml",foreground:"808080"},{token:"tag",foreground:"569CD6"},{token:"tag.id.pug",foreground:"4F76AC"},{token:"tag.class.pug",foreground:"4F76AC"},{token:"meta.scss",foreground:"A79873"},{token:"meta.tag",foreground:"CE9178"},{token:"metatag",foreground:"DD6A6F"},{token:"metatag.content.html",foreground:"9CDCFE"},{token:"metatag.html",foreground:"569CD6"},{token:"metatag.xml",foreground:"569CD6"},{token:"metatag.php",fontStyle:"bold"},{token:"key",foreground:"9CDCFE"},{token:"string.key.json",foreground:"9CDCFE"},{token:"string.value.json",foreground:"CE9178"},{token:"attribute.name",foreground:"9CDCFE"},{token:"attribute.value",foreground:"CE9178"},{token:"attribute.value.number.css",foreground:"B5CEA8"},{token:"attribute.value.unit.css",foreground:"B5CEA8"},{token:"attribute.value.hex.css",foreground:"D4D4D4"},{token:"string",foreground:"CE9178"},{token:"string.sql",foreground:"FF0000"},{token:"keyword",foreground:"569CD6"},{token:"keyword.flow",foreground:"C586C0"},{token:"keyword.json",foreground:"CE9178"},{token:"keyword.flow.scss",foreground:"569CD6"},{token:"operator.scss",foreground:"909090"},{token:"operator.sql",foreground:"778899"},{token:"operator.swift",foreground:"909090"},{token:"predefined.sql",foreground:"FF00FF"}],colors:{[k.editorBackground]:"#1E1E1E",[k.editorForeground]:"#D4D4D4",[k.editorInactiveSelection]:"#3A3D41",[d.editorIndentGuide1]:"#404040",[d.editorActiveIndentGuide1]:"#707070",[k.editorSelectionHighlight]:"#ADD6FF26"}},e.hc_black={base:"hc-black",inherit:!1,rules:[{token:"",foreground:"FFFFFF",background:"000000"},{token:"invalid",foreground:"f44747"},{token:"emphasis",fontStyle:"italic"},{token:"strong",fontStyle:"bold"},{token:"variable",foreground:"1AEBFF"},{token:"variable.parameter",foreground:"9CDCFE"},{token:"constant",foreground:"569CD6"},{token:"comment",foreground:"608B4E"},{token:"number",foreground:"FFFFFF"},{token:"regexp",foreground:"C0C0C0"},{token:"annotation",foreground:"569CD6"},{token:"type",foreground:"3DC9B0"},{token:"delimiter",foreground:"FFFF00"},{token:"delimiter.html",foreground:"FFFF00"},{token:"tag",foreground:"569CD6"},{token:"tag.id.pug",foreground:"4F76AC"},{token:"tag.class.pug",foreground:"4F76AC"},{token:"meta",foreground:"D4D4D4"},{token:"meta.tag",foreground:"CE9178"},{token:"metatag",foreground:"569CD6"},{token:"metatag.content.html",foreground:"1AEBFF"},{token:"metatag.html",foreground:"569CD6"},{token:"metatag.xml",foreground:"569CD6"},{token:"metatag.php",fontStyle:"bold"},{token:"key",foreground:"9CDCFE"},{token:"string.key",foreground:"9CDCFE"},{token:"string.value",foreground:"CE9178"},{token:"attribute.name",foreground:"569CD6"},{token:"attribute.value",foreground:"3FF23F"},{token:"string",foreground:"CE9178"},{token:"string.sql",foreground:"FF0000"},{token:"keyword",foreground:"569CD6"},{token:"keyword.flow",foreground:"C586C0"},{token:"operator.sql",foreground:"778899"},{token:"operator.swift",foreground:"909090"},{token:"predefined.sql",foreground:"FF00FF"}],colors:{[k.editorBackground]:"#000000",[k.editorForeground]:"#FFFFFF",[d.editorIndentGuide1]:"#FFFFFF",[d.editorActiveIndentGuide1]:"#FFFFFF"}},e.hc_light={base:"hc-light",inherit:!1,rules:[{token:"",foreground:"292929",background:"FFFFFF"},{token:"invalid",foreground:"B5200D"},{token:"emphasis",fontStyle:"italic"},{token:"strong",fontStyle:"bold"},{token:"variable",foreground:"264F70"},{token:"variable.predefined",foreground:"4864AA"},{token:"constant",foreground:"dd0000"},{token:"comment",foreground:"008000"},{token:"number",foreground:"098658"},{token:"number.hex",foreground:"3030c0"},{token:"regexp",foreground:"800000"},{token:"annotation",foreground:"808080"},{token:"type",foreground:"008080"},{token:"delimiter",foreground:"000000"},{token:"delimiter.html",foreground:"383838"},{token:"tag",foreground:"800000"},{token:"tag.id.pug",foreground:"4F76AC"},{token:"tag.class.pug",foreground:"4F76AC"},{token:"meta.scss",foreground:"800000"},{token:"metatag",foreground:"e00000"},{token:"metatag.content.html",foreground:"B5200D"},{token:"metatag.html",foreground:"808080"},{token:"metatag.xml",foreground:"808080"},{token:"metatag.php",fontStyle:"bold"},{token:"key",foreground:"863B00"},{token:"string.key.json",foreground:"A31515"},{token:"string.value.json",foreground:"0451A5"},{token:"attribute.name",foreground:"264F78"},{token:"attribute.value",foreground:"0451A5"},{token:"string",foreground:"A31515"},{token:"string.sql",foreground:"B5200D"},{token:"keyword",foreground:"0000FF"},{token:"keyword.flow",foreground:"AF00DB"},{token:"operator.sql",foreground:"778899"},{token:"operator.swift",foreground:"666666"},{token:"predefined.sql",foreground:"C700C7"}],colors:{[k.editorBackground]:"#FFFFFF",[k.editorForeground]:"#292929",[d.editorIndentGuide1]:"#292929",[d.editorActiveIndentGuide1]:"#292929"}}}),define(ne[419],se([1,0,5,64,33,6,27,148,572,796,38,32,25,2,97,767,52]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneThemeService=e.HC_LIGHT_THEME_NAME=e.HC_BLACK_THEME_NAME=e.VS_DARK_THEME_NAME=e.VS_LIGHT_THEME_NAME=void 0,e.VS_LIGHT_THEME_NAME="vs",e.VS_DARK_THEME_NAME="vs-dark",e.HC_BLACK_THEME_NAME="hc-black",e.HC_LIGHT_THEME_NAME="hc-light";const c=p.Registry.as(n.Extensions.ColorContribution),l=p.Registry.as(o.Extensions.ThemingContribution);class a{constructor(v,w){this.semanticHighlighting=!1,this.themeData=w;const S=w.base;v.length>0?(r(v)?this.id=v:this.id=S+" "+v,this.themeName=v):(this.id=S,this.themeName=S),this.colors=null,this.defaultColors=Object.create(null),this._tokenTheme=null}get base(){return this.themeData.base}notifyBaseUpdated(){this.themeData.inherit&&(this.colors=null,this._tokenTheme=null)}getColors(){if(!this.colors){const v=new Map;for(const w in this.themeData.colors)v.set(w,I.Color.fromHex(this.themeData.colors[w]));if(this.themeData.inherit){const w=u(this.themeData.base);for(const S in w.colors)v.has(S)||v.set(S,I.Color.fromHex(w.colors[S]))}this.colors=v}return this.colors}getColor(v,w){const S=this.getColors().get(v);if(S)return S;if(w!==!1)return this.getDefault(v)}getDefault(v){let w=this.defaultColors[v];return w||(w=c.resolveDefaultColor(v,this),this.defaultColors[v]=w,w)}defines(v){return this.getColors().has(v)}get type(){switch(this.base){case e.VS_LIGHT_THEME_NAME:return i.ColorScheme.LIGHT;case e.HC_BLACK_THEME_NAME:return i.ColorScheme.HIGH_CONTRAST_DARK;case e.HC_LIGHT_THEME_NAME:return i.ColorScheme.HIGH_CONTRAST_LIGHT;default:return i.ColorScheme.DARK}}get tokenTheme(){if(!this._tokenTheme){let v=[],w=[];if(this.themeData.inherit){const D=u(this.themeData.base);v=D.rules,D.encodedTokensColors&&(w=D.encodedTokensColors)}const S=this.themeData.colors["editor.foreground"],L=this.themeData.colors["editor.background"];if(S||L){const D={token:""};S&&(D.foreground=S),L&&(D.background=L),v.push(D)}v=v.concat(this.themeData.rules),this.themeData.encodedTokensColors&&(w=this.themeData.encodedTokensColors),this._tokenTheme=_.TokenTheme.createFromRawTokenTheme(v,w)}return this._tokenTheme}getTokenStyleMetadata(v,w,S){const D=this.tokenTheme._match([v].concat(w).join(".")).metadata,T=m.TokenMetadata.getForeground(D),M=m.TokenMetadata.getFontStyle(D);return{foreground:T,italic:!!(M&1),bold:!!(M&2),underline:!!(M&4),strikethrough:!!(M&8)}}}function r(h){return h===e.VS_LIGHT_THEME_NAME||h===e.VS_DARK_THEME_NAME||h===e.HC_BLACK_THEME_NAME||h===e.HC_LIGHT_THEME_NAME}function u(h){switch(h){case e.VS_LIGHT_THEME_NAME:return b.vs;case e.VS_DARK_THEME_NAME:return b.vs_dark;case e.HC_BLACK_THEME_NAME:return b.hc_black;case e.HC_LIGHT_THEME_NAME:return b.hc_light}}function C(h){const v=u(h);return new a(h,v)}class f extends t.Disposable{constructor(){super(),this._onColorThemeChange=this._register(new E.Emitter),this.onDidColorThemeChange=this._onColorThemeChange.event,this._onProductIconThemeChange=this._register(new E.Emitter),this.onDidProductIconThemeChange=this._onProductIconThemeChange.event,this._environment=Object.create(null),this._builtInProductIconTheme=new s.UnthemedProductIconTheme,this._autoDetectHighContrast=!0,this._knownThemes=new Map,this._knownThemes.set(e.VS_LIGHT_THEME_NAME,C(e.VS_LIGHT_THEME_NAME)),this._knownThemes.set(e.VS_DARK_THEME_NAME,C(e.VS_DARK_THEME_NAME)),this._knownThemes.set(e.HC_BLACK_THEME_NAME,C(e.HC_BLACK_THEME_NAME)),this._knownThemes.set(e.HC_LIGHT_THEME_NAME,C(e.HC_LIGHT_THEME_NAME));const v=this._register((0,s.getIconsStyleSheet)(this));this._codiconCSS=v.getCSS(),this._themeCSS="",this._allCSS=`${this._codiconCSS} ${this._themeCSS}`,this._globalStyleElement=null,this._styleElements=[],this._colorMapOverride=null,this.setTheme(e.VS_LIGHT_THEME_NAME),this._onOSSchemeChanged(),this._register(v.onDidChange(()=>{this._codiconCSS=v.getCSS(),this._updateCSS()})),(0,k.addMatchMediaChangeListener)(g.mainWindow,"(forced-colors: active)",()=>{this._onOSSchemeChanged()})}registerEditorContainer(v){return d.isInShadowDOM(v)?this._registerShadowDomContainer(v):this._registerRegularEditorContainer()}_registerRegularEditorContainer(){return this._globalStyleElement||(this._globalStyleElement=d.createStyleSheet(void 0,v=>{v.className="monaco-colors",v.textContent=this._allCSS}),this._styleElements.push(this._globalStyleElement)),t.Disposable.None}_registerShadowDomContainer(v){const w=d.createStyleSheet(v,S=>{S.className="monaco-colors",S.textContent=this._allCSS});return this._styleElements.push(w),{dispose:()=>{for(let S=0;S{S.base===v&&S.notifyBaseUpdated()}),this._theme.themeName===v&&this.setTheme(v)}getColorTheme(){return this._theme}setColorMapOverride(v){this._colorMapOverride=v,this._updateThemeOrColorMap()}setTheme(v){let w;this._knownThemes.has(v)?w=this._knownThemes.get(v):w=this._knownThemes.get(e.VS_LIGHT_THEME_NAME),this._updateActualTheme(w)}_updateActualTheme(v){!v||this._theme===v||(this._theme=v,this._updateThemeOrColorMap())}_onOSSchemeChanged(){if(this._autoDetectHighContrast){const v=g.mainWindow.matchMedia("(forced-colors: active)").matches;if(v!==(0,i.isHighContrast)(this._theme.type)){let w;(0,i.isDark)(this._theme.type)?w=v?e.HC_BLACK_THEME_NAME:e.VS_DARK_THEME_NAME:w=v?e.HC_LIGHT_THEME_NAME:e.VS_LIGHT_THEME_NAME,this._updateActualTheme(this._knownThemes.get(w))}}}setAutoDetectHighContrast(v){this._autoDetectHighContrast=v,this._onOSSchemeChanged()}_updateThemeOrColorMap(){const v=[],w={},S={addRule:T=>{w[T]||(v.push(T),w[T]=!0)}};l.getThemingParticipants().forEach(T=>T(this._theme,S,this._environment));const L=[];for(const T of c.getColors()){const M=this._theme.getColor(T.id,!0);M&&L.push(`${(0,n.asCssVariableName)(T.id)}: ${M.toString()};`)}S.addRule(`.monaco-editor, .monaco-diff-editor, .monaco-component { ${L.join(` `)} }`);const D=this._colorMapOverride||this._theme.tokenTheme.getColorMap();S.addRule((0,_.generateTokensCSSForColorMap)(D)),this._themeCSS=v.join(` `),this._updateCSS(),y.TokenizationRegistry.setColorMap(D),this._onColorThemeChange.fire(this._theme)}_updateCSS(){this._allCSS=`${this._codiconCSS} ${this._themeCSS}`,this._styleElements.forEach(v=>v.textContent=this._allCSS)}getFileIconTheme(){return{hasFileIcons:!1,hasFolderIcons:!1,hidesExplorerArrows:!1}}getProductIconTheme(){return this._builtInProductIconTheme}}e.StandaloneThemeService=f}),define(ne[797],se([1,0,15,153,107,97,419]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0});class m extends d.EditorAction{constructor(){super({id:"editor.action.toggleHighContrast",label:I.ToggleHighContrastNLS.toggleHighContrast,alias:"Toggle High Contrast Theme",precondition:void 0}),this._originalThemeName=null}run(b,p){const n=b.get(k.IStandaloneThemeService),o=n.getColorTheme();(0,E.isHighContrast)(o.type)?(n.setTheme(this._originalThemeName||((0,E.isDark)(o.type)?y.VS_DARK_THEME_NAME:y.VS_LIGHT_THEME_NAME)),this._originalThemeName=null):(n.setTheme((0,E.isDark)(o.type)?y.HC_BLACK_THEME_NAME:y.HC_LIGHT_THEME_NAME),this._originalThemeName=o.themeName)}}(0,d.registerEditorAction)(m)}),define(ne[124],se([1,0,5,47,151,359,41,247,2,16,3,29,381,12,58,7,31,50,101,25,30,97,19,32,110,61,542]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DropdownWithDefaultActionViewItem=e.SubmenuEntryActionViewItem=e.TextOnlyMenuEntryActionViewItem=e.MenuEntryActionViewItem=void 0,e.createAndFillInContextMenuActions=w,e.createAndFillInActionBarActions=S,e.createActionViewItem=N;function w(O,F,x,W){let V,q,H;if(Array.isArray(O))H=O,V=F,q=x;else{const j=F;H=O.getActions(j),V=x,q=W}const z=d.ModifierKeyEmitter.getInstance(),U=z.keyStatus.altKey||(b.isWindows||b.isLinux)&&z.keyStatus.shiftKey;L(H,V,U,q?j=>j===q:j=>j==="navigation")}function S(O,F,x,W,V,q){let H,z,U,j,Y;if(Array.isArray(O))Y=O,H=F,z=x,U=W,j=V;else{const K=F;Y=O.getActions(K),H=x,z=W,U=V,j=q}L(Y,H,!1,typeof z=="string"?K=>K===z:z,U,j)}function L(O,F,x,W=H=>H==="navigation",V=()=>!1,q=!1){let H,z;Array.isArray(F)?(H=F,z=F):(H=F.primary,z=F.secondary);const U=new Set;for(const[j,Y]of O){let G;W(j)?(G=H,G.length>0&&q&&G.push(new y.Separator)):(G=z,G.length>0&&G.push(new y.Separator));for(let K of Y){x&&(K=K instanceof n.MenuItemAction&&K.alt?K.alt:K);const R=G.push(K);K instanceof y.SubmenuAction&&U.add({group:j,action:K,index:R-1})}}for(const{group:j,action:Y,index:G}of U){const K=W(j)?H:z,R=Y.actions;V(Y,j,K.length)&&K.splice(G,1,...R)}}let D=class extends I.ActionViewItem{constructor(F,x,W,V,q,H,z,U){super(void 0,F,{icon:!!(F.class||F.item.icon),label:!F.class&&!F.item.icon,draggable:x?.draggable,keybinding:x?.keybinding,hoverDelegate:x?.hoverDelegate}),this._options=x,this._keybindingService=W,this._notificationService=V,this._contextKeyService=q,this._themeService=H,this._contextMenuService=z,this._accessibilityService=U,this._wantsAltCommand=!1,this._itemClassDispose=this._register(new _.MutableDisposable),this._altKey=d.ModifierKeyEmitter.getInstance()}get _menuItemAction(){return this._action}get _commandAction(){return this._wantsAltCommand&&this._menuItemAction.alt||this._menuItemAction}async onClick(F){F.preventDefault(),F.stopPropagation();try{await this.actionRunner.run(this._commandAction,this._context)}catch(x){this._notificationService.error(x)}}render(F){if(super.render(F),F.classList.add("menu-entry"),this.options.icon&&this._updateItemClass(this._menuItemAction.item),this._menuItemAction.alt){let x=!1;const W=()=>{const V=!!this._menuItemAction.alt?.enabled&&(!this._accessibilityService.isMotionReduced()||x)&&(this._altKey.keyStatus.altKey||this._altKey.keyStatus.shiftKey&&x);V!==this._wantsAltCommand&&(this._wantsAltCommand=V,this.updateLabel(),this.updateTooltip(),this.updateClass())};this._register(this._altKey.event(W)),this._register((0,d.addDisposableListener)(F,"mouseleave",V=>{x=!1,W()})),this._register((0,d.addDisposableListener)(F,"mouseenter",V=>{x=!0,W()})),W()}}updateLabel(){this.options.label&&this.label&&(this.label.textContent=this._commandAction.label)}getTooltip(){const F=this._keybindingService.lookupKeybinding(this._commandAction.id,this._contextKeyService),x=F&&F.getLabel(),W=this._commandAction.tooltip||this._commandAction.label;let V=x?(0,p.localize)(1483,"{0} ({1})",W,x):W;if(!this._wantsAltCommand&&this._menuItemAction.alt?.enabled){const q=this._menuItemAction.alt.tooltip||this._menuItemAction.alt.label,H=this._keybindingService.lookupKeybinding(this._menuItemAction.alt.id,this._contextKeyService),z=H&&H.getLabel(),U=z?(0,p.localize)(1484,"{0} ({1})",q,z):q;V=(0,p.localize)(1485,`{0} [{1}] {2}`,V,m.UILabelProvider.modifierLabels[b.OS].altKey,U)}return V}updateClass(){this.options.icon&&(this._commandAction!==this._menuItemAction?this._menuItemAction.alt&&this._updateItemClass(this._menuItemAction.alt.item):this._updateItemClass(this._menuItemAction.item))}_updateItemClass(F){this._itemClassDispose.value=void 0;const{element:x,label:W}=this;if(!x||!W)return;const V=this._commandAction.checked&&(0,o.isICommandActionToggleInfo)(F.toggled)&&F.toggled.icon?F.toggled.icon:F.icon;if(V)if(r.ThemeIcon.isThemeIcon(V)){const q=r.ThemeIcon.asClassNameArray(V);W.classList.add(...q),this._itemClassDispose.value=(0,_.toDisposable)(()=>{W.classList.remove(...q)})}else W.style.backgroundImage=(0,u.isDark)(this._themeService.getColorTheme().type)?(0,d.asCSSUrl)(V.dark):(0,d.asCSSUrl)(V.light),W.classList.add("icon"),this._itemClassDispose.value=(0,_.combinedDisposable)((0,_.toDisposable)(()=>{W.style.backgroundImage="",W.classList.remove("icon")}),this._themeService.onDidColorThemeChange(()=>{this.updateClass()}))}};e.MenuEntryActionViewItem=D,e.MenuEntryActionViewItem=D=ke([ce(2,g.IKeybindingService),ce(3,c.INotificationService),ce(4,t.IContextKeyService),ce(5,a.IThemeService),ce(6,i.IContextMenuService),ce(7,v.IAccessibilityService)],D);class T extends D{render(F){this.options.label=!0,this.options.icon=!1,super.render(F),F.classList.add("text-only"),F.classList.toggle("use-comma",this._options?.useComma??!1)}updateLabel(){const F=this._keybindingService.lookupKeybinding(this._action.id,this._contextKeyService);if(!F)return super.updateLabel();if(this.label){const x=T._symbolPrintEnter(F);this._options?.conversational?this.label.textContent=(0,p.localize)(1486,"{1} to {0}",this._action.label,x):this.label.textContent=(0,p.localize)(1487,"{0} ({1})",this._action.label,x)}}static _symbolPrintEnter(F){return F.getLabel()?.replace(/\benter\b/gi,"\u23CE").replace(/\bEscape\b/gi,"Esc")}}e.TextOnlyMenuEntryActionViewItem=T;let M=class extends E.DropdownMenuActionViewItem{constructor(F,x,W,V,q){const H={...x,menuAsChild:x?.menuAsChild??!1,classNames:x?.classNames??(r.ThemeIcon.isThemeIcon(F.item.icon)?r.ThemeIcon.asClassName(F.item.icon):void 0),keybindingProvider:x?.keybindingProvider??(z=>W.lookupKeybinding(z.id))};super(F,{getActions:()=>F.actions},V,H),this._keybindingService=W,this._contextMenuService=V,this._themeService=q}render(F){super.render(F),(0,C.assertType)(this.element),F.classList.add("menu-entry");const x=this._action,{icon:W}=x.item;if(W&&!r.ThemeIcon.isThemeIcon(W)){this.element.classList.add("icon");const V=()=>{this.element&&(this.element.style.backgroundImage=(0,u.isDark)(this._themeService.getColorTheme().type)?(0,d.asCSSUrl)(W.dark):(0,d.asCSSUrl)(W.light))};V(),this._register(this._themeService.onDidColorThemeChange(()=>{V()}))}}};e.SubmenuEntryActionViewItem=M,e.SubmenuEntryActionViewItem=M=ke([ce(2,g.IKeybindingService),ce(3,i.IContextMenuService),ce(4,a.IThemeService)],M);let A=class extends I.BaseActionViewItem{constructor(F,x,W,V,q,H,z,U){super(null,F),this._keybindingService=W,this._notificationService=V,this._contextMenuService=q,this._menuService=H,this._instaService=z,this._storageService=U,this._container=null,this._options=x,this._storageKey=`${F.item.submenu.id}_lastActionId`;let j;const Y=x?.persistLastActionId?U.get(this._storageKey,1):void 0;Y&&(j=F.actions.find(K=>Y===K.id)),j||(j=F.actions[0]),this._defaultAction=this._instaService.createInstance(D,j,{keybinding:this._getDefaultActionKeybindingLabel(j)});const G={keybindingProvider:K=>this._keybindingService.lookupKeybinding(K.id),...x,menuAsChild:x?.menuAsChild??!0,classNames:x?.classNames??["codicon","codicon-chevron-down"],actionRunner:x?.actionRunner??new y.ActionRunner};this._dropdown=new E.DropdownMenuActionViewItem(F,F.actions,this._contextMenuService,G),this._register(this._dropdown.actionRunner.onDidRun(K=>{K.action instanceof n.MenuItemAction&&this.update(K.action)}))}update(F){this._options?.persistLastActionId&&this._storageService.store(this._storageKey,F.id,1,1),this._defaultAction.dispose(),this._defaultAction=this._instaService.createInstance(D,F,{keybinding:this._getDefaultActionKeybindingLabel(F)}),this._defaultAction.actionRunner=new class extends y.ActionRunner{async runAction(x,W){await x.run(void 0)}},this._container&&this._defaultAction.render((0,d.prepend)(this._container,(0,d.$)(".action-container")))}_getDefaultActionKeybindingLabel(F){let x;if(this._options?.renderKeybindingWithDefaultActionLabel){const W=this._keybindingService.lookupKeybinding(F.id);W&&(x=`(${W.getLabel()})`)}return x}setActionContext(F){super.setActionContext(F),this._defaultAction.setActionContext(F),this._dropdown.setActionContext(F)}render(F){this._container=F,super.render(this._container),this._container.classList.add("monaco-dropdown-with-default");const x=(0,d.$)(".action-container");this._defaultAction.render((0,d.append)(this._container,x)),this._register((0,d.addDisposableListener)(x,d.EventType.KEY_DOWN,V=>{const q=new k.StandardKeyboardEvent(V);q.equals(17)&&(this._defaultAction.element.tabIndex=-1,this._dropdown.focus(),q.stopPropagation())}));const W=(0,d.$)(".dropdown-action-container");this._dropdown.render((0,d.append)(this._container,W)),this._register((0,d.addDisposableListener)(W,d.EventType.KEY_DOWN,V=>{const q=new k.StandardKeyboardEvent(V);q.equals(15)&&(this._defaultAction.element.tabIndex=0,this._dropdown.setFocusable(!1),this._defaultAction.element?.focus(),q.stopPropagation())}))}focus(F){F?this._dropdown.focus():(this._defaultAction.element.tabIndex=0,this._defaultAction.element.focus())}blur(){this._defaultAction.element.tabIndex=-1,this._dropdown.blur(),this._container.blur()}setFocusable(F){F?this._defaultAction.element.tabIndex=0:(this._defaultAction.element.tabIndex=-1,this._dropdown.setFocusable(!1))}dispose(){this._defaultAction.dispose(),this._dropdown.dispose(),super.dispose()}};e.DropdownWithDefaultActionViewItem=A,e.DropdownWithDefaultActionViewItem=A=ke([ce(2,g.IKeybindingService),ce(3,c.INotificationService),ce(4,i.IContextMenuService),ce(5,n.IMenuService),ce(6,s.IInstantiationService),ce(7,l.IStorageService)],A);let P=class extends I.SelectActionViewItem{constructor(F,x){super(null,F,F.actions.map(W=>({text:W.id===y.Separator.ID?"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500":W.label,isDisabled:!W.enabled})),0,x,h.defaultSelectBoxStyles,{ariaLabel:F.tooltip,optionsAsChildren:!0}),this.select(Math.max(0,F.actions.findIndex(W=>W.checked)))}render(F){super.render(F),F.style.borderColor=(0,f.asCssVariable)(f.selectBorder)}runAction(F,x){const W=this.action.actions[x];W&&this.actionRunner.run(W)}};P=ke([ce(1,i.IContextViewService)],P);function N(O,F,x){return F instanceof n.MenuItemAction?O.createInstance(D,F,x):F instanceof n.SubmenuItemAction?F.item.isSelection?O.createInstance(P,F):F.item.rememberDefaultAction?O.createInstance(A,F,{...x,persistLastActionId:!0}):O.createInstance(M,F,x):void 0}}),define(ne[798],se([1,0,5,87,2,124,29,12,7]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SuggestWidgetStatus=void 0;let b=class{constructor(n,o,t,i,s){this._menuId=o,this._menuService=i,this._contextKeyService=s,this._menuDisposables=new I.DisposableStore,this.element=d.append(n,d.$(".suggest-status-bar"));const g=c=>c instanceof y.MenuItemAction?t.createInstance(E.TextOnlyMenuEntryActionViewItem,c,{useComma:!0}):void 0;this._leftActions=new k.ActionBar(this.element,{actionViewItemProvider:g}),this._rightActions=new k.ActionBar(this.element,{actionViewItemProvider:g}),this._leftActions.domNode.classList.add("left"),this._rightActions.domNode.classList.add("right")}dispose(){this._menuDisposables.dispose(),this._leftActions.dispose(),this._rightActions.dispose(),this.element.remove()}show(){const n=this._menuService.createMenu(this._menuId,this._contextKeyService),o=()=>{const t=[],i=[];for(const[s,g]of n.getActions())s==="left"?t.push(...g):i.push(...g);this._leftActions.clear(),this._leftActions.push(t),this._rightActions.clear(),this._rightActions.push(i)};this._menuDisposables.add(n.onDidChange(()=>o())),this._menuDisposables.add(n)}hide(){this._menuDisposables.clear()}};e.SuggestWidgetStatus=b,e.SuggestWidgetStatus=b=ke([ce(2,_.IInstantiationService),ce(3,y.IMenuService),ce(4,m.IContextKeyService)],b)}),define(ne[218],se([1,0,5,77,643,41,13,298,8,6,53,2,3,124,29,406,24,12,58,31,63]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MenuWorkbenchToolBar=e.WorkbenchToolBar=void 0;let u=class extends I.ToolBar{constructor(h,v,w,S,L,D,T,M){super(h,L,{getKeyBinding:P=>D.lookupKeybinding(P.id)??void 0,...v,allowContextMenu:!0,skipTelemetry:typeof v?.telemetrySource=="string"}),this._options=v,this._menuService=w,this._contextKeyService=S,this._contextMenuService=L,this._keybindingService=D,this._commandService=T,this._sessionDisposables=this._store.add(new n.DisposableStore);const A=v?.telemetrySource;A&&this._store.add(this.actionBar.onDidRun(P=>M.publicLog2("workbenchActionExecuted",{id:P.action.id,from:A})))}setActions(h,v=[],w){this._sessionDisposables.clear();const S=h.slice(),L=v.slice(),D=[];let T=0;const M=[];let A=!1;if(this._options?.hiddenItemStrategy!==-1)for(let P=0;PF?.id)),N=this._options.overflowBehavior.maxItems-P.size;let O=0;for(let F=0;F=N&&(S[F]=void 0,M[F]=x))}}(0,y.coalesceInPlace)(S),(0,y.coalesceInPlace)(M),super.setActions(S,E.Separator.join(M,L)),(D.length>0||S.length>0)&&this._sessionDisposables.add((0,d.addDisposableListener)(this.getElement(),"contextmenu",P=>{const N=new k.StandardMouseEvent((0,d.getWindow)(this.getElement()),P),O=this.getItemAction(N.target);if(!O)return;N.preventDefault(),N.stopPropagation();const F=[];if(O instanceof i.MenuItemAction&&O.menuKeybinding)F.push(O.menuKeybinding);else if(!(O instanceof i.SubmenuItemAction||O instanceof I.ToggleMenuAction)){const W=!!this._keybindingService.lookupKeybinding(O.id);F.push((0,s.createConfigureKeybindingAction)(this._commandService,this._keybindingService,O.id,void 0,W))}if(D.length>0){let W=!1;if(T===1&&this._options?.hiddenItemStrategy===0){W=!0;for(let V=0;Vthis._menuService.resetHiddenStates(w)}))),x.length!==0&&this._contextMenuService.showContextMenu({getAnchor:()=>N,getActions:()=>x,menuId:this._options?.contextMenu,menuActionOptions:{renderShortTitle:!0,...this._options?.menuOptions},skipTelemetry:typeof this._options?.telemetrySource=="string",contextKeyService:this._contextKeyService})}))}};e.WorkbenchToolBar=u,e.WorkbenchToolBar=u=ke([ce(2,i.IMenuService),ce(3,c.IContextKeyService),ce(4,l.IContextMenuService),ce(5,a.IKeybindingService),ce(6,g.ICommandService),ce(7,r.ITelemetryService)],u);let C=class extends u{constructor(h,v,w,S,L,D,T,M,A){super(h,{resetMenu:v,...w},S,L,D,T,M,A),this._onDidChangeMenuItems=this._store.add(new b.Emitter),this.onDidChangeMenuItems=this._onDidChangeMenuItems.event;const P=this._store.add(S.createMenu(v,L,{emitEventsForSubmenuChanges:!0})),N=()=>{const O=[],F=[];(0,t.createAndFillInActionBarActions)(P,w?.menuOptions,{primary:O,secondary:F},w?.toolbarOptions?.primaryGroup,w?.toolbarOptions?.shouldInlineSubmenu,w?.toolbarOptions?.useSeparatorsInPrimaryActions),h.classList.toggle("has-no-actions",O.length===0&&F.length===0),super.setActions(O,F)};this._store.add(P.onDidChange(()=>{N(),this._onDidChangeMenuItems.fire(this)})),N()}setActions(){throw new _.BugIndicatingError("This toolbar is populated from a menu.")}};e.MenuWorkbenchToolBar=C,e.MenuWorkbenchToolBar=C=ke([ce(3,i.IMenuService),ce(4,c.IContextKeyService),ce(5,l.IContextMenuService),ce(6,a.IKeybindingService),ce(7,g.ICommandService),ce(8,r.ITelemetryService)],C)}),define(ne[799],se([1,0,5,2,21,65,363,88,654,365,55,68,4,104,105,581,218,29,12,118,7]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorGutter=void 0;const u=[],C=35;let f=class extends k.Disposable{constructor(S,L,D,T,M,A,P,N,O){super(),this._diffModel=L,this._editors=D,this._options=T,this._sashLayout=M,this._boundarySashes=A,this._instantiationService=P,this._contextKeyService=N,this._menuService=O,this._menu=this._register(this._menuService.createMenu(c.MenuId.DiffEditorHunkToolbar,this._contextKeyService)),this._actions=(0,I.observableFromEvent)(this,this._menu.onDidChange,()=>this._menu.getActions()),this._hasActions=this._actions.map(F=>F.length>0),this._showSash=(0,I.derived)(this,F=>this._options.renderSideBySide.read(F)&&this._hasActions.read(F)),this.width=(0,I.derived)(this,F=>this._hasActions.read(F)?C:0),this.elements=(0,d.h)("div.gutter@gutter",{style:{position:"absolute",height:"100%",width:C+"px"}},[]),this._currentDiff=(0,I.derived)(this,F=>{const x=this._diffModel.read(F);if(!x)return;const W=x.diff.read(F)?.mappings,V=this._editors.modifiedCursor.read(F);if(V)return W?.find(q=>q.lineRangeMapping.modified.contains(V.lineNumber))}),this._selectedDiffs=(0,I.derived)(this,F=>{const W=this._diffModel.read(F)?.diff.read(F);if(!W)return u;const V=this._editors.modifiedSelections.read(F);if(V.every(U=>U.isEmpty()))return u;const q=new p.LineRangeSet(V.map(U=>p.LineRange.fromRangeInclusive(U))),z=W.mappings.filter(U=>U.lineRangeMapping.innerChanges&&q.intersects(U.lineRangeMapping.modified)).map(U=>({mapping:U,rangeMappings:U.lineRangeMapping.innerChanges.filter(j=>V.some(Y=>o.Range.areIntersecting(j.modifiedRange,Y)))}));return z.length===0||z.every(U=>U.rangeMappings.length===0)?u:z}),this._register((0,m.prependRemoveOnDispose)(S,this.elements.root)),this._register((0,d.addDisposableListener)(this.elements.root,"click",()=>{this._editors.modified.focus()})),this._register((0,m.applyStyle)(this.elements.root,{display:this._hasActions.map(F=>F?"block":"none")})),(0,E.derivedDisposable)(this,F=>this._showSash.read(F)?new y.DiffEditorSash(S,this._sashLayout.dimensions,this._options.enableSplitViewResizing,this._boundarySashes,(0,E.derivedWithSetter)(this,W=>this._sashLayout.sashLeft.read(W)-C,(W,V)=>this._sashLayout.sashLeft.set(W+C,V)),()=>this._sashLayout.resetSash()):void 0).recomputeInitiallyAndOnChange(this._store),this._register(new _.EditorGutter(this._editors.modified,this.elements.root,{getIntersectingGutterItems:(F,x)=>{const W=this._diffModel.read(x);if(!W)return[];const V=W.diff.read(x);if(!V)return[];const q=this._selectedDiffs.read(x);if(q.length>0){const z=i.DetailedLineRangeMapping.fromRangeMappings(q.flatMap(U=>U.rangeMappings));return[new h(z,!0,c.MenuId.DiffEditorSelectionToolbar,void 0,W.model.original.uri,W.model.modified.uri)]}const H=this._currentDiff.read(x);return V.mappings.map(z=>new h(z.lineRangeMapping.withInnerChangesFromLineRanges(),z.lineRangeMapping===H?.lineRangeMapping,c.MenuId.DiffEditorHunkToolbar,void 0,W.model.original.uri,W.model.modified.uri))},createView:(F,x)=>this._instantiationService.createInstance(v,F,x,this)})),this._register((0,d.addDisposableListener)(this.elements.gutter,d.EventType.MOUSE_WHEEL,F=>{this._editors.modified.getOption(104).handleMouseWheel&&this._editors.modified.delegateScrollFromMouseWheelEvent(F)},{passive:!1}))}computeStagedValue(S){const L=S.innerChanges??[],D=new s.TextModelText(this._editors.modifiedModel.get()),T=new s.TextModelText(this._editors.original.getModel());return new t.TextEdit(L.map(P=>P.toTextEdit(D))).apply(T)}layout(S){this.elements.gutter.style.left=S+"px"}};e.DiffEditorGutter=f,e.DiffEditorGutter=f=ke([ce(6,r.IInstantiationService),ce(7,l.IContextKeyService),ce(8,c.IMenuService)],f);class h{constructor(S,L,D,T,M,A){this.mapping=S,this.showAlways=L,this.menuId=D,this.rangeOverride=T,this.originalUri=M,this.modifiedUri=A}get id(){return this.mapping.modified.toString()}get range(){return this.rangeOverride??this.mapping.modified}}let v=class extends k.Disposable{constructor(S,L,D,T){super(),this._item=S,this._elements=(0,d.h)("div.gutterItem",{style:{height:"20px",width:"34px"}},[(0,d.h)("div.background@background",{},[]),(0,d.h)("div.buttons@buttons",{},[])]),this._showAlways=this._item.map(this,A=>A.showAlways),this._menuId=this._item.map(this,A=>A.menuId),this._isSmall=(0,I.observableValue)(this,!1),this._lastItemRange=void 0,this._lastViewRange=void 0;const M=this._register(T.createInstance(a.WorkbenchHoverDelegate,"element",!0,{position:{hoverPosition:1}}));this._register((0,m.appendRemoveOnDispose)(L,this._elements.root)),this._register((0,I.autorun)(A=>{const P=this._showAlways.read(A);this._elements.root.classList.toggle("noTransition",!0),this._elements.root.classList.toggle("showAlways",P),setTimeout(()=>{this._elements.root.classList.toggle("noTransition",!1)},0)})),this._register((0,I.autorunWithStore)((A,P)=>{this._elements.buttons.replaceChildren();const N=P.add(T.createInstance(g.MenuWorkbenchToolBar,this._elements.buttons,this._menuId.read(A),{orientation:1,hoverDelegate:M,toolbarOptions:{primaryGroup:O=>O.startsWith("primary")},overflowBehavior:{maxItems:this._isSmall.read(A)?1:3},hiddenItemStrategy:0,actionRunner:new b.ActionRunnerWithContext(()=>{const O=this._item.get(),F=O.mapping;return{mapping:F,originalWithModifiedChanges:D.computeStagedValue(F),originalUri:O.originalUri,modifiedUri:O.modifiedUri}}),menuOptions:{shouldForwardArgs:!0}}));P.add(N.onDidChangeMenuItems(()=>{this._lastItemRange&&this.layout(this._lastItemRange,this._lastViewRange)}))}))}layout(S,L){this._lastItemRange=S,this._lastViewRange=L;let D=this._elements.buttons.clientHeight;this._isSmall.set(this._item.get().mapping.original.startLineNumber===1&&S.length<30,void 0),D=this._elements.buttons.clientHeight;const T=S.length/2-D/2,M=D;let A=S.start+T;const P=n.OffsetRange.tryCreate(M,L.endExclusive-M-D),N=n.OffsetRange.tryCreate(S.start+M,S.endExclusive-D-M);N&&P&&N.startthis.editor.getOption(62).showToolbar==="always"),this.sessionPosition=void 0,this.position=(0,p.derived)(this,q=>{const H=this.model.read(q)?.primaryGhostText.read(q);if(!this.alwaysShowToolbar.read(q)||!H||H.parts.length===0)return this.sessionPosition=void 0,null;const z=H.parts[0].column;this.sessionPosition&&this.sessionPosition.lineNumber!==H.lineNumber&&(this.sessionPosition=void 0);const U=new i.Position(H.lineNumber,Math.min(z,this.sessionPosition?.column??Number.MAX_SAFE_INTEGER));return this.sessionPosition=U,U}),this._register((0,p.autorunWithStore)((q,H)=>{const z=this.model.read(q);if(!z||!this.alwaysShowToolbar.read(q))return;const U=(0,n.derivedWithStore)((Y,G)=>{const K=G.add(this.instantiationService.createInstance(A,this.editor,!0,this.position,z.selectedInlineCompletionIndex,z.inlineCompletionsCount,z.activeCommands));return x.addContentWidget(K),G.add((0,b.toDisposable)(()=>x.removeContentWidget(K))),G.add((0,p.autorun)(R=>{this.position.read(R)&&z.lastTriggerKind.read(R)!==s.InlineCompletionTriggerKind.Explicit&&z.triggerExplicitly()})),K}),j=(0,p.derivedObservableWithCache)(this,(Y,G)=>!!this.position.read(Y)||!!G);H.add((0,p.autorun)(Y=>{j.read(Y)&&U.read(Y)}))}))}};e.InlineCompletionsHintsWidget=D,e.InlineCompletionsHintsWidget=D=ke([ce(2,h.IInstantiationService)],D);const T=(0,S.registerIcon)("inline-suggestion-hints-next",_.Codicon.chevronRight,(0,c.localize)(1090,"Icon for show next parameter hint.")),M=(0,S.registerIcon)("inline-suggestion-hints-previous",_.Codicon.chevronLeft,(0,c.localize)(1091,"Icon for show previous parameter hint."));let A=class extends b.Disposable{static{L=this}static{this._dropDownVisible=!1}static get dropDownVisible(){return this._dropDownVisible}static{this.id=0}createCommandAction(x,W,V){const q=new E.Action(x,W,V,!0,()=>this._commandService.executeCommand(x)),H=this.keybindingService.lookupKeybinding(x,this._contextKeyService);let z=W;return H&&(z=(0,c.localize)(1092,"{0} ({1})",W,H.getLabel())),q.tooltip=z,q}constructor(x,W,V,q,H,z,U,j,Y,G,K){super(),this.editor=x,this.withBorder=W,this._position=V,this._currentSuggestionIdx=q,this._suggestionCount=H,this._extraCommands=z,this._commandService=U,this.keybindingService=Y,this._contextKeyService=G,this._menuService=K,this.id=`InlineSuggestionHintsContentWidget${L.id++}`,this.allowEditorOverflow=!0,this.suppressMouseDown=!1,this.nodes=(0,d.h)("div.inlineSuggestionsHints",{className:this.withBorder?".withBorder":""},[(0,d.h)("div@toolBar")]),this.previousAction=this.createCommandAction(g.showPreviousInlineSuggestionActionId,(0,c.localize)(1093,"Previous"),t.ThemeIcon.asClassName(M)),this.availableSuggestionCountAction=new E.Action("inlineSuggestionHints.availableSuggestionCount","",void 0,!1),this.nextAction=this.createCommandAction(g.showNextInlineSuggestionActionId,(0,c.localize)(1094,"Next"),t.ThemeIcon.asClassName(T)),this.inlineCompletionsActionsMenus=this._register(this._menuService.createMenu(r.MenuId.InlineCompletionsActions,this._contextKeyService)),this.clearAvailableSuggestionCountLabelDebounced=this._register(new m.RunOnceScheduler(()=>{this.availableSuggestionCountAction.label=""},100)),this.disableButtonsDebounced=this._register(new m.RunOnceScheduler(()=>{this.previousAction.enabled=this.nextAction.enabled=!1},100)),this.toolBar=this._register(j.createInstance(O,this.nodes.toolBar,r.MenuId.InlineSuggestionToolbar,{menuOptions:{renderShortTitle:!0},toolbarOptions:{primaryGroup:R=>R.startsWith("primary")},actionViewItemProvider:(R,J)=>{if(R instanceof r.MenuItemAction)return j.createInstance(N,R,void 0);if(R===this.availableSuggestionCountAction){const ie=new P(void 0,R,{label:!0,icon:!1});return ie.setClass("availableSuggestionCount"),ie}},telemetrySource:"InlineSuggestionToolbar"})),this.toolBar.setPrependedPrimaryActions([this.previousAction,this.availableSuggestionCountAction,this.nextAction]),this._register(this.toolBar.onDidChangeDropdownVisibility(R=>{L._dropDownVisible=R})),this._register((0,p.autorun)(R=>{this._position.read(R),this.editor.layoutContentWidget(this)})),this._register((0,p.autorun)(R=>{const J=this._suggestionCount.read(R),ie=this._currentSuggestionIdx.read(R);J!==void 0?(this.clearAvailableSuggestionCountLabelDebounced.cancel(),this.availableSuggestionCountAction.label=`${ie+1}/${J}`):this.clearAvailableSuggestionCountLabelDebounced.schedule(),J!==void 0&&J>1?(this.disableButtonsDebounced.cancel(),this.previousAction.enabled=this.nextAction.enabled=!0):this.disableButtonsDebounced.schedule()})),this._register((0,p.autorun)(R=>{const ie=this._extraCommands.read(R).map(ue=>({class:void 0,id:ue.id,enabled:!0,tooltip:ue.tooltip||"",label:ue.title,run:he=>this._commandService.executeCommand(ue.id)}));for(const[ue,he]of this.inlineCompletionsActionsMenus.getActions())for(const pe of he)pe instanceof r.MenuItemAction&&ie.push(pe);ie.length>0&&ie.unshift(new E.Separator),this.toolBar.setAdditionalSecondaryActions(ie)}))}getId(){return this.id}getDomNode(){return this.nodes.root}getPosition(){return{position:this._position.get(),preference:[1,2],positionAffinity:3}}};e.InlineSuggestionHintsContentWidget=A,e.InlineSuggestionHintsContentWidget=A=L=ke([ce(6,u.ICommandService),ce(7,h.IInstantiationService),ce(8,v.IKeybindingService),ce(9,C.IContextKeyService),ce(10,r.IMenuService)],A);class P extends k.ActionViewItem{constructor(){super(...arguments),this._className=void 0}setClass(x){this._className=x}render(x){super.render(x),this._className&&x.classList.add(this._className)}updateTooltip(){}}class N extends l.MenuEntryActionViewItem{updateLabel(){const x=this._keybindingService.lookupKeybinding(this._action.id,this._contextKeyService);if(!x)return super.updateLabel();if(this.label){const W=(0,d.h)("div.keybinding").root;this._register(new I.KeybindingLabel(W,o.OS,{disableTitle:!0,...I.unthemedKeybindingLabelOptions})).set(x),this.label.textContent=this._action.label,this.label.appendChild(W),this.label.classList.add("inlineSuggestionStatusBarItemLabel")}}updateTooltip(){}}let O=class extends a.WorkbenchToolBar{constructor(x,W,V,q,H,z,U,j,Y){super(x,{resetMenu:W,...V},q,H,z,U,j,Y),this.menuId=W,this.options2=V,this.menuService=q,this.contextKeyService=H,this.menu=this._store.add(this.menuService.createMenu(this.menuId,this.contextKeyService,{emitEventsForSubmenuChanges:!0})),this.additionalActions=[],this.prependedPrimaryActions=[],this._store.add(this.menu.onDidChange(()=>this.updateToolbar())),this.updateToolbar()}updateToolbar(){const x=[],W=[];(0,l.createAndFillInActionBarActions)(this.menu,this.options2?.menuOptions,{primary:x,secondary:W},this.options2?.toolbarOptions?.primaryGroup,this.options2?.toolbarOptions?.shouldInlineSubmenu,this.options2?.toolbarOptions?.useSeparatorsInPrimaryActions),W.push(...this.additionalActions),x.unshift(...this.prependedPrimaryActions),this.setActions(x,W)}setPrependedPrimaryActions(x){(0,y.equals)(this.prependedPrimaryActions,x,(W,V)=>W===V)||(this.prependedPrimaryActions=x,this.updateToolbar())}setAdditionalSecondaryActions(x){(0,y.equals)(this.additionalActions,x,(W,V)=>W===V)||(this.additionalActions=x,this.updateToolbar())}};e.CustomizedMenuWorkbenchToolBar=O,e.CustomizedMenuWorkbenchToolBar=O=ke([ce(3,r.IMenuService),ce(4,C.IContextKeyService),ce(5,f.IContextMenuService),ce(6,v.IKeybindingService),ce(7,u.ICommandService),ce(8,w.ITelemetryService)],O)}),define(ne[800],se([1,0,5,206,41,13,2,21,16,9,124,218,29,24,12,58,7,31,63,519]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";var a;Object.defineProperty(e,"__esModule",{value:!0}),e.CustomizedMenuWorkbenchToolBar=e.InlineEditHintsContentWidget=e.InlineEditHintsWidget=void 0;let r=class extends y.Disposable{constructor(v,w,S){super(),this.editor=v,this.model=w,this.instantiationService=S,this.alwaysShowToolbar=(0,m.observableFromEvent)(this,this.editor.onDidChangeConfiguration,()=>this.editor.getOption(63).showToolbar==="always"),this.sessionPosition=void 0,this.position=(0,m.derived)(this,L=>{const D=this.model.read(L)?.model.ghostText.read(L);if(!this.alwaysShowToolbar.read(L)||!D||D.parts.length===0)return this.sessionPosition=void 0,null;const T=D.parts[0].column;this.sessionPosition&&this.sessionPosition.lineNumber!==D.lineNumber&&(this.sessionPosition=void 0);const M=new b.Position(D.lineNumber,Math.min(T,this.sessionPosition?.column??Number.MAX_SAFE_INTEGER));return this.sessionPosition=M,M}),this._register((0,m.autorunWithStore)((L,D)=>{if(!this.model.read(L)||!this.alwaysShowToolbar.read(L))return;const M=D.add(this.instantiationService.createInstance(u,this.editor,!0,this.position));v.addContentWidget(M),D.add((0,y.toDisposable)(()=>v.removeContentWidget(M)))}))}};e.InlineEditHintsWidget=r,e.InlineEditHintsWidget=r=ke([ce(2,g.IInstantiationService)],r);let u=class extends y.Disposable{static{a=this}static{this._dropDownVisible=!1}static{this.id=0}constructor(v,w,S,L,D,T){super(),this.editor=v,this.withBorder=w,this._position=S,this._contextKeyService=D,this._menuService=T,this.id=`InlineEditHintsContentWidget${a.id++}`,this.allowEditorOverflow=!0,this.suppressMouseDown=!1,this.nodes=(0,d.h)("div.inlineEditHints",{className:this.withBorder?".withBorder":""},[(0,d.h)("div@toolBar")]),this.inlineCompletionsActionsMenus=this._register(this._menuService.createMenu(o.MenuId.InlineEditActions,this._contextKeyService)),this.toolBar=this._register(L.createInstance(f,this.nodes.toolBar,this.editor,o.MenuId.InlineEditToolbar,{menuOptions:{renderShortTitle:!0},toolbarOptions:{primaryGroup:M=>M.startsWith("primary")},actionViewItemProvider:(M,A)=>{if(M instanceof o.MenuItemAction)return L.createInstance(C,M,void 0)},telemetrySource:"InlineEditToolbar"})),this._register(this.toolBar.onDidChangeDropdownVisibility(M=>{a._dropDownVisible=M})),this._register((0,m.autorun)(M=>{this._position.read(M),this.editor.layoutContentWidget(this)})),this._register((0,m.autorun)(M=>{const A=[];for(const[P,N]of this.inlineCompletionsActionsMenus.getActions())for(const O of N)O instanceof o.MenuItemAction&&A.push(O);A.length>0&&A.unshift(new I.Separator),this.toolBar.setAdditionalSecondaryActions(A)}))}getId(){return this.id}getDomNode(){return this.nodes.root}getPosition(){return{position:this._position.get(),preference:[1,2],positionAffinity:3}}};e.InlineEditHintsContentWidget=u,e.InlineEditHintsContentWidget=u=a=ke([ce(3,g.IInstantiationService),ce(4,i.IContextKeyService),ce(5,o.IMenuService)],u);class C extends p.MenuEntryActionViewItem{updateLabel(){const v=this._keybindingService.lookupKeybinding(this._action.id,this._contextKeyService);if(!v)return super.updateLabel();if(this.label){const w=(0,d.h)("div.keybinding").root;this._register(new k.KeybindingLabel(w,_.OS,{disableTitle:!0,...k.unthemedKeybindingLabelOptions})).set(v),this.label.textContent=this._action.label,this.label.appendChild(w),this.label.classList.add("inlineEditStatusBarItemLabel")}}updateTooltip(){}}let f=class extends n.WorkbenchToolBar{constructor(v,w,S,L,D,T,M,A,P,N){super(v,{resetMenu:S,...L},D,T,M,A,P,N),this.editor=w,this.menuId=S,this.options2=L,this.menuService=D,this.contextKeyService=T,this.menu=this._store.add(this.menuService.createMenu(this.menuId,this.contextKeyService,{emitEventsForSubmenuChanges:!0})),this.additionalActions=[],this.prependedPrimaryActions=[],this._store.add(this.menu.onDidChange(()=>this.updateToolbar())),this._store.add(this.editor.onDidChangeCursorPosition(()=>this.updateToolbar())),this.updateToolbar()}updateToolbar(){const v=[],w=[];(0,p.createAndFillInActionBarActions)(this.menu,this.options2?.menuOptions,{primary:v,secondary:w},this.options2?.toolbarOptions?.primaryGroup,this.options2?.toolbarOptions?.shouldInlineSubmenu,this.options2?.toolbarOptions?.useSeparatorsInPrimaryActions),w.push(...this.additionalActions),v.unshift(...this.prependedPrimaryActions),this.setActions(v,w)}setAdditionalSecondaryActions(v){(0,E.equals)(this.additionalActions,v,(w,S)=>w===S)||(this.additionalActions=v,this.updateToolbar())}};e.CustomizedMenuWorkbenchToolBar=f,e.CustomizedMenuWorkbenchToolBar=f=ke([ce(4,o.IMenuService),ce(5,i.IContextKeyService),ce(6,s.IContextMenuService),ce(7,c.IKeybindingService),ce(8,t.ICommandService),ce(9,l.ITelemetryService)],f)}),define(ne[801],se([1,0,5,41,6,2,124,29,12,31,50,63,761,58]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContextMenuMenuDelegate=e.ContextMenuService=void 0;let i=class extends E.Disposable{get contextMenuHandler(){return this._contextMenuHandler||(this._contextMenuHandler=new o.ContextMenuHandler(this.contextViewService,this.telemetryService,this.notificationService,this.keybindingService)),this._contextMenuHandler}constructor(c,l,a,r,u,C){super(),this.telemetryService=c,this.notificationService=l,this.contextViewService=a,this.keybindingService=r,this.menuService=u,this.contextKeyService=C,this._contextMenuHandler=void 0,this._onDidShowContextMenu=this._store.add(new I.Emitter),this.onDidShowContextMenu=this._onDidShowContextMenu.event,this._onDidHideContextMenu=this._store.add(new I.Emitter)}configure(c){this.contextMenuHandler.configure(c)}showContextMenu(c){c=s.transform(c,this.menuService,this.contextKeyService),this.contextMenuHandler.showContextMenu({...c,onHide:l=>{c.onHide?.(l),this._onDidHideContextMenu.fire()}}),d.ModifierKeyEmitter.getInstance().resetKeyStatus(),this._onDidShowContextMenu.fire()}};e.ContextMenuService=i,e.ContextMenuService=i=ke([ce(0,n.ITelemetryService),ce(1,p.INotificationService),ce(2,t.IContextViewService),ce(3,b.IKeybindingService),ce(4,m.IMenuService),ce(5,_.IContextKeyService)],i);var s;(function(g){function c(a){return a&&a.menuId instanceof m.MenuId}function l(a,r,u){if(!c(a))return a;const{menuId:C,menuActionOptions:f,contextKeyService:h}=a;return{...a,getActions:()=>{const v=[];if(C){const w=r.getMenuActions(C,h??u,f);(0,y.createAndFillInContextMenuActions)(w,v)}return a.getActions?k.Separator.join(a.getActions(),v):v}}}g.transform=l})(s||(e.ContextMenuMenuDelegate=s={}))}),define(ne[802],se([1,0,5,6,3,7,216,25,2,66,47,16,126,254,206,87,97,22,398,98,142,445,11,176,14,8,61,21,13]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L){"use strict";var D;Object.defineProperty(e,"__esModule",{value:!0}),e.QuickInputTree=void 0;const T=d.$;class M{constructor(Y,G,K){this.index=Y,this.hasCheckbox=G,this._hidden=!1,this._init=new a.Lazy(()=>{const R=K.label??"",J=(0,r.parseLabelWithIcons)(R).text.trim(),ie=K.ariaLabel||[R,this.saneDescription,this.saneDetail].map(ue=>(0,r.getCodiconAriaLabel)(ue)).filter(ue=>!!ue).join(", ");return{saneLabel:R,saneSortLabel:J,saneAriaLabel:ie}}),this._saneDescription=K.description,this._saneTooltip=K.tooltip}get saneLabel(){return this._init.value.saneLabel}get saneSortLabel(){return this._init.value.saneSortLabel}get saneAriaLabel(){return this._init.value.saneAriaLabel}get element(){return this._element}set element(Y){this._element=Y}get hidden(){return this._hidden}set hidden(Y){this._hidden=Y}get saneDescription(){return this._saneDescription}set saneDescription(Y){this._saneDescription=Y}get saneDetail(){return this._saneDetail}set saneDetail(Y){this._saneDetail=Y}get saneTooltip(){return this._saneTooltip}set saneTooltip(Y){this._saneTooltip=Y}get labelHighlights(){return this._labelHighlights}set labelHighlights(Y){this._labelHighlights=Y}get descriptionHighlights(){return this._descriptionHighlights}set descriptionHighlights(Y){this._descriptionHighlights=Y}get detailHighlights(){return this._detailHighlights}set detailHighlights(Y){this._detailHighlights=Y}}class A extends M{constructor(Y,G,K,R,J,ie){super(Y,G,J),this.fireButtonTriggered=K,this._onChecked=R,this.item=J,this._separator=ie,this._checked=!1,this.onChecked=G?k.Event.map(k.Event.filter(this._onChecked.event,ue=>ue.element===this),ue=>ue.checked):k.Event.None,this._saneDetail=J.detail,this._labelHighlights=J.highlights?.label,this._descriptionHighlights=J.highlights?.description,this._detailHighlights=J.highlights?.detail}get separator(){return this._separator}set separator(Y){this._separator=Y}get checked(){return this._checked}set checked(Y){Y!==this._checked&&(this._checked=Y,this._onChecked.fire({element:this,checked:Y}))}get checkboxDisabled(){return!!this.item.disabled}}var P;(function(j){j[j.NONE=0]="NONE",j[j.MOUSE_HOVER=1]="MOUSE_HOVER",j[j.ACTIVE_ITEM=2]="ACTIVE_ITEM"})(P||(P={}));class N extends M{constructor(Y,G,K){super(Y,!1,K),this.fireSeparatorButtonTriggered=G,this.separator=K,this.children=new Array,this.focusInsideSeparator=P.NONE}}class O{getHeight(Y){return Y instanceof N?30:Y.saneDetail?44:22}getTemplateId(Y){return Y instanceof A?W.ID:V.ID}}class F{getWidgetAriaLabel(){return(0,I.localize)(1597,"Quick Input")}getAriaLabel(Y){return Y.separator?.label?`${Y.saneAriaLabel}, ${Y.separator.label}`:Y.saneAriaLabel}getWidgetRole(){return"listbox"}getRole(Y){return Y.hasCheckbox?"checkbox":"option"}isChecked(Y){if(!(!Y.hasCheckbox||!(Y instanceof A)))return{get value(){return Y.checked},onDidChange:G=>Y.onChecked(()=>G())}}}class x{constructor(Y){this.hoverDelegate=Y}renderTemplate(Y){const G=Object.create(null);G.toDisposeElement=new _.DisposableStore,G.toDisposeTemplate=new _.DisposableStore,G.entry=d.append(Y,T(".quick-input-list-entry"));const K=d.append(G.entry,T("label.quick-input-list-label"));G.toDisposeTemplate.add(d.addStandardDisposableListener(K,d.EventType.CLICK,pe=>{G.checkbox.offsetParent||pe.preventDefault()})),G.checkbox=d.append(K,T("input.quick-input-list-checkbox")),G.checkbox.type="checkbox";const R=d.append(K,T(".quick-input-list-rows")),J=d.append(R,T(".quick-input-list-row")),ie=d.append(R,T(".quick-input-list-row"));G.label=new t.IconLabel(J,{supportHighlights:!0,supportDescriptionHighlights:!0,supportIcons:!0,hoverDelegate:this.hoverDelegate}),G.toDisposeTemplate.add(G.label),G.icon=d.prepend(G.label.element,T(".quick-input-list-icon"));const ue=d.append(J,T(".quick-input-list-entry-keybinding"));G.keybinding=new i.KeybindingLabel(ue,n.OS),G.toDisposeTemplate.add(G.keybinding);const he=d.append(ie,T(".quick-input-list-label-meta"));return G.detail=new t.IconLabel(he,{supportHighlights:!0,supportIcons:!0,hoverDelegate:this.hoverDelegate}),G.toDisposeTemplate.add(G.detail),G.separator=d.append(G.entry,T(".quick-input-list-separator")),G.actionBar=new s.ActionBar(G.entry,this.hoverDelegate?{hoverDelegate:this.hoverDelegate}:void 0),G.actionBar.domNode.classList.add("quick-input-list-entry-action-bar"),G.toDisposeTemplate.add(G.actionBar),G}disposeTemplate(Y){Y.toDisposeElement.dispose(),Y.toDisposeTemplate.dispose()}disposeElement(Y,G,K){K.toDisposeElement.clear(),K.actionBar.clear()}}let W=class extends x{static{D=this}static{this.ID="quickpickitem"}constructor(Y,G){super(Y),this.themeService=G,this._itemsWithSeparatorsFrequency=new Map}get templateId(){return D.ID}renderTemplate(Y){const G=super.renderTemplate(Y);return G.toDisposeTemplate.add(d.addStandardDisposableListener(G.checkbox,d.EventType.CHANGE,K=>{G.element.checked=G.checkbox.checked})),G}renderElement(Y,G,K){const R=Y.element;K.element=R,R.element=K.entry??void 0;const J=R.item;K.checkbox.checked=R.checked,K.toDisposeElement.add(R.onChecked(de=>K.checkbox.checked=de)),K.checkbox.disabled=R.checkboxDisabled;const{labelHighlights:ie,descriptionHighlights:ue,detailHighlights:he}=R;if(J.iconPath){const de=(0,g.isDark)(this.themeService.getColorTheme().type)?J.iconPath.dark:J.iconPath.light??J.iconPath.dark,ge=c.URI.revive(de);K.icon.className="quick-input-list-icon",K.icon.style.backgroundImage=d.asCSSUrl(ge)}else K.icon.style.backgroundImage="",K.icon.className=J.iconClass?`quick-input-list-icon ${J.iconClass}`:"";let pe;!R.saneTooltip&&R.saneDescription&&(pe={markdown:{value:R.saneDescription,supportThemeIcons:!0},markdownNotSupportedFallback:R.saneDescription});const ae={matches:ie||[],descriptionTitle:pe,descriptionMatches:ue||[],labelEscapeNewLines:!0};if(ae.extraClasses=J.iconClasses,ae.italic=J.italic,ae.strikethrough=J.strikethrough,K.entry.classList.remove("quick-input-list-separator-as-item"),K.label.setLabel(R.saneLabel,R.saneDescription,ae),K.keybinding.set(J.keybinding),R.saneDetail){let de;R.saneTooltip||(de={markdown:{value:R.saneDetail,supportThemeIcons:!0},markdownNotSupportedFallback:R.saneDetail}),K.detail.element.style.display="",K.detail.setLabel(R.saneDetail,void 0,{matches:he,title:de,labelEscapeNewLines:!0})}else K.detail.element.style.display="none";R.separator?.label?(K.separator.textContent=R.separator.label,K.separator.style.display="",this.addItemWithSeparator(R)):K.separator.style.display="none",K.entry.classList.toggle("quick-input-list-separator-border",!!R.separator);const ee=J.buttons;ee&&ee.length?(K.actionBar.push(ee.map((de,ge)=>(0,l.quickInputButtonToAction)(de,`id-${ge}`,()=>R.fireButtonTriggered({button:de,item:R.item}))),{icon:!0,label:!1}),K.entry.classList.add("has-actions")):K.entry.classList.remove("has-actions")}disposeElement(Y,G,K){this.removeItemWithSeparator(Y.element),super.disposeElement(Y,G,K)}isItemWithSeparatorVisible(Y){return this._itemsWithSeparatorsFrequency.has(Y)}addItemWithSeparator(Y){this._itemsWithSeparatorsFrequency.set(Y,(this._itemsWithSeparatorsFrequency.get(Y)||0)+1)}removeItemWithSeparator(Y){const G=this._itemsWithSeparatorsFrequency.get(Y)||0;G>1?this._itemsWithSeparatorsFrequency.set(Y,G-1):this._itemsWithSeparatorsFrequency.delete(Y)}};W=D=ke([ce(1,m.IThemeService)],W);class V extends x{constructor(){super(...arguments),this._visibleSeparatorsFrequency=new Map}static{this.ID="quickpickseparator"}get templateId(){return V.ID}get visibleSeparators(){return[...this._visibleSeparatorsFrequency.keys()]}isSeparatorVisible(Y){return this._visibleSeparatorsFrequency.has(Y)}renderTemplate(Y){const G=super.renderTemplate(Y);return G.checkbox.style.display="none",G}renderElement(Y,G,K){const R=Y.element;K.element=R,R.element=K.entry??void 0,R.element.classList.toggle("focus-inside",!!R.focusInsideSeparator);const J=R.separator,{labelHighlights:ie,descriptionHighlights:ue,detailHighlights:he}=R;K.icon.style.backgroundImage="",K.icon.className="";let pe;!R.saneTooltip&&R.saneDescription&&(pe={markdown:{value:R.saneDescription,supportThemeIcons:!0},markdownNotSupportedFallback:R.saneDescription});const ae={matches:ie||[],descriptionTitle:pe,descriptionMatches:ue||[],labelEscapeNewLines:!0};if(K.entry.classList.add("quick-input-list-separator-as-item"),K.label.setLabel(R.saneLabel,R.saneDescription,ae),R.saneDetail){let de;R.saneTooltip||(de={markdown:{value:R.saneDetail,supportThemeIcons:!0},markdownNotSupportedFallback:R.saneDetail}),K.detail.element.style.display="",K.detail.setLabel(R.saneDetail,void 0,{matches:he,title:de,labelEscapeNewLines:!0})}else K.detail.element.style.display="none";K.separator.style.display="none",K.entry.classList.add("quick-input-list-separator-border");const ee=J.buttons;ee&&ee.length?(K.actionBar.push(ee.map((de,ge)=>(0,l.quickInputButtonToAction)(de,`id-${ge}`,()=>R.fireSeparatorButtonTriggered({button:de,separator:R.separator}))),{icon:!0,label:!1}),K.entry.classList.add("has-actions")):K.entry.classList.remove("has-actions"),this.addSeparator(R)}disposeElement(Y,G,K){this.removeSeparator(Y.element),this.isSeparatorVisible(Y.element)||Y.element.element?.classList.remove("focus-inside"),super.disposeElement(Y,G,K)}addSeparator(Y){this._visibleSeparatorsFrequency.set(Y,(this._visibleSeparatorsFrequency.get(Y)||0)+1)}removeSeparator(Y){const G=this._visibleSeparatorsFrequency.get(Y)||0;G>1?this._visibleSeparatorsFrequency.set(Y,G-1):this._visibleSeparatorsFrequency.delete(Y)}}let q=class extends _.Disposable{constructor(Y,G,K,R,J,ie){super(),this.parent=Y,this.hoverDelegate=G,this.linkOpenerDelegate=K,this.accessibilityService=ie,this._onKeyDown=new k.Emitter,this._onLeave=new k.Emitter,this.onLeave=this._onLeave.event,this._visibleCountObservable=(0,S.observableValue)("VisibleCount",0),this.onChangedVisibleCount=k.Event.fromObservable(this._visibleCountObservable,this._store),this._allVisibleCheckedObservable=(0,S.observableValue)("AllVisibleChecked",!1),this.onChangedAllVisibleChecked=k.Event.fromObservable(this._allVisibleCheckedObservable,this._store),this._checkedCountObservable=(0,S.observableValue)("CheckedCount",0),this.onChangedCheckedCount=k.Event.fromObservable(this._checkedCountObservable,this._store),this._checkedElementsObservable=(0,S.observableValueOpts)({equalsFn:L.equals},new Array),this.onChangedCheckedElements=k.Event.fromObservable(this._checkedElementsObservable,this._store),this._onButtonTriggered=new k.Emitter,this.onButtonTriggered=this._onButtonTriggered.event,this._onSeparatorButtonTriggered=new k.Emitter,this.onSeparatorButtonTriggered=this._onSeparatorButtonTriggered.event,this._elementChecked=new k.Emitter,this._elementCheckedEventBufferer=new k.EventBufferer,this._hasCheckboxes=!1,this._inputElements=new Array,this._elementTree=new Array,this._itemElements=new Array,this._elementDisposable=this._register(new _.DisposableStore),this._matchOnDescription=!1,this._matchOnDetail=!1,this._matchOnLabel=!0,this._matchOnLabelMode="fuzzy",this._sortByLabel=!0,this._shouldLoop=!0,this._container=d.append(this.parent,T(".quick-input-list")),this._separatorRenderer=new V(G),this._itemRenderer=J.createInstance(W,G),this._tree=this._register(J.createInstance(y.WorkbenchObjectTree,"QuickInput",this._container,new O,[this._itemRenderer,this._separatorRenderer],{filter:{filter(ue){return ue.hidden?0:ue instanceof N?2:1}},sorter:{compare:(ue,he)=>{if(!this.sortByLabel||!this._lastQueryString)return 0;const pe=this._lastQueryString.toLowerCase();return U(ue,he,pe)}},accessibilityProvider:new F,setRowLineHeight:!1,multipleSelectionSupport:!1,hideTwistiesOfChildlessElements:!0,renderIndentGuides:f.RenderIndentGuides.None,findWidgetEnabled:!1,indent:0,horizontalScrolling:!1,allowNonCollapsibleParents:!0,alwaysConsumeMouseWheel:!0})),this._tree.getHTMLElement().id=R,this._registerListeners()}get onDidChangeFocus(){return k.Event.map(this._tree.onDidChangeFocus,Y=>Y.elements.filter(G=>G instanceof A).map(G=>G.item),this._store)}get onDidChangeSelection(){return k.Event.map(this._tree.onDidChangeSelection,Y=>({items:Y.elements.filter(G=>G instanceof A).map(G=>G.item),event:Y.browserEvent}),this._store)}get displayed(){return this._container.style.display!=="none"}set displayed(Y){this._container.style.display=Y?"":"none"}get scrollTop(){return this._tree.scrollTop}set scrollTop(Y){this._tree.scrollTop=Y}get ariaLabel(){return this._tree.ariaLabel}set ariaLabel(Y){this._tree.ariaLabel=Y??""}set enabled(Y){this._tree.getHTMLElement().style.pointerEvents=Y?"":"none"}get matchOnDescription(){return this._matchOnDescription}set matchOnDescription(Y){this._matchOnDescription=Y}get matchOnDetail(){return this._matchOnDetail}set matchOnDetail(Y){this._matchOnDetail=Y}get matchOnLabel(){return this._matchOnLabel}set matchOnLabel(Y){this._matchOnLabel=Y}get matchOnLabelMode(){return this._matchOnLabelMode}set matchOnLabelMode(Y){this._matchOnLabelMode=Y}get sortByLabel(){return this._sortByLabel}set sortByLabel(Y){this._sortByLabel=Y}get shouldLoop(){return this._shouldLoop}set shouldLoop(Y){this._shouldLoop=Y}_registerListeners(){this._registerOnKeyDown(),this._registerOnContainerClick(),this._registerOnMouseMiddleClick(),this._registerOnTreeModelChanged(),this._registerOnElementChecked(),this._registerOnContextMenu(),this._registerHoverListeners(),this._registerSelectionChangeListener(),this._registerSeparatorActionShowingListeners()}_registerOnKeyDown(){this._register(this._tree.onKeyDown(Y=>{const G=new p.StandardKeyboardEvent(Y);switch(G.keyCode){case 10:this.toggleCheckbox();break}this._onKeyDown.fire(G)}))}_registerOnContainerClick(){this._register(d.addDisposableListener(this._container,d.EventType.CLICK,Y=>{(Y.x||Y.y)&&this._onLeave.fire()}))}_registerOnMouseMiddleClick(){this._register(d.addDisposableListener(this._container,d.EventType.AUXCLICK,Y=>{Y.button===1&&this._onLeave.fire()}))}_registerOnTreeModelChanged(){this._register(this._tree.onDidChangeModel(()=>{const Y=this._itemElements.filter(G=>!G.hidden).length;this._visibleCountObservable.set(Y,void 0),this._hasCheckboxes&&this._updateCheckedObservables()}))}_registerOnElementChecked(){this._register(this._elementCheckedEventBufferer.wrapEvent(this._elementChecked.event,(Y,G)=>G)(Y=>this._updateCheckedObservables()))}_registerOnContextMenu(){this._register(this._tree.onContextMenu(Y=>{Y.element&&(Y.browserEvent.preventDefault(),this._tree.setSelection([Y.element]))}))}_registerHoverListeners(){const Y=this._register(new h.ThrottledDelayer(this.hoverDelegate.delay));this._register(this._tree.onMouseOver(async G=>{if(d.isHTMLAnchorElement(G.browserEvent.target)){Y.cancel();return}if(!(!d.isHTMLAnchorElement(G.browserEvent.relatedTarget)&&d.isAncestor(G.browserEvent.relatedTarget,G.element?.element)))try{await Y.trigger(async()=>{G.element instanceof A&&this.showHover(G.element)})}catch(K){if(!(0,v.isCancellationError)(K))throw K}})),this._register(this._tree.onMouseOut(G=>{d.isAncestor(G.browserEvent.relatedTarget,G.element?.element)||Y.cancel()}))}_registerSeparatorActionShowingListeners(){this._register(this._tree.onDidChangeFocus(Y=>{const G=Y.elements[0]?this._tree.getParentElement(Y.elements[0]):null;for(const K of this._separatorRenderer.visibleSeparators){const R=K===G;!!(K.focusInsideSeparator&P.ACTIVE_ITEM)!==R&&(R?K.focusInsideSeparator|=P.ACTIVE_ITEM:K.focusInsideSeparator&=~P.ACTIVE_ITEM,this._tree.rerender(K))}})),this._register(this._tree.onMouseOver(Y=>{const G=Y.element?this._tree.getParentElement(Y.element):null;for(const K of this._separatorRenderer.visibleSeparators){if(K!==G)continue;!!(K.focusInsideSeparator&P.MOUSE_HOVER)||(K.focusInsideSeparator|=P.MOUSE_HOVER,this._tree.rerender(K))}})),this._register(this._tree.onMouseOut(Y=>{const G=Y.element?this._tree.getParentElement(Y.element):null;for(const K of this._separatorRenderer.visibleSeparators){if(K!==G)continue;!!(K.focusInsideSeparator&P.MOUSE_HOVER)&&(K.focusInsideSeparator&=~P.MOUSE_HOVER,this._tree.rerender(K))}}))}_registerSelectionChangeListener(){this._register(this._tree.onDidChangeSelection(Y=>{const G=Y.elements.filter(K=>K instanceof A);G.length!==Y.elements.length&&(Y.elements.length===1&&Y.elements[0]instanceof N&&(this._tree.setFocus([Y.elements[0].children[0]]),this._tree.reveal(Y.elements[0],0)),this._tree.setSelection(G))}))}setAllVisibleChecked(Y){this._elementCheckedEventBufferer.bufferEvents(()=>{this._itemElements.forEach(G=>{!G.hidden&&!G.checkboxDisabled&&(G.checked=Y)})})}setElements(Y){this._elementDisposable.clear(),this._lastQueryString=void 0,this._inputElements=Y,this._hasCheckboxes=this.parent.classList.contains("show-checkboxes");let G;this._itemElements=new Array,this._elementTree=Y.reduce((K,R,J)=>{let ie;if(R.type==="separator"){if(!R.buttons)return K;G=new N(J,ue=>this._onSeparatorButtonTriggered.fire(ue),R),ie=G}else{const ue=J>0?Y[J-1]:void 0;let he;ue&&ue.type==="separator"&&!ue.buttons&&(G=void 0,he=ue);const pe=new A(J,this._hasCheckboxes,ae=>this._onButtonTriggered.fire(ae),this._elementChecked,R,he);if(this._itemElements.push(pe),G)return G.children.push(pe),K;ie=pe}return K.push(ie),K},new Array),this._setElementsToTree(this._elementTree),this.accessibilityService.isScreenReaderOptimized()&&setTimeout(()=>{const K=this._tree.getHTMLElement().querySelector(".monaco-list-row.focused"),R=K?.parentNode;if(K&&R){const J=K.nextSibling;K.remove(),R.insertBefore(K,J)}},0)}setFocusedElements(Y){const G=Y.map(K=>this._itemElements.find(R=>R.item===K)).filter(K=>!!K).filter(K=>!K.hidden);if(this._tree.setFocus(G),Y.length>0){const K=this._tree.getFocus()[0];K&&this._tree.reveal(K)}}getActiveDescendant(){return this._tree.getHTMLElement().getAttribute("aria-activedescendant")}setSelectedElements(Y){const G=Y.map(K=>this._itemElements.find(R=>R.item===K)).filter(K=>!!K);this._tree.setSelection(G)}getCheckedElements(){return this._itemElements.filter(Y=>Y.checked).map(Y=>Y.item)}setCheckedElements(Y){this._elementCheckedEventBufferer.bufferEvents(()=>{const G=new Set;for(const K of Y)G.add(K);for(const K of this._itemElements)K.checked=G.has(K.item)})}focus(Y){if(this._itemElements.length)switch(Y===b.QuickPickFocus.Second&&this._itemElements.length<2&&(Y=b.QuickPickFocus.First),Y){case b.QuickPickFocus.First:this._tree.scrollTop=0,this._tree.focusFirst(void 0,G=>G.element instanceof A);break;case b.QuickPickFocus.Second:{this._tree.scrollTop=0;let G=!1;this._tree.focusFirst(void 0,K=>K.element instanceof A?G?!0:(G=!G,!1):!1);break}case b.QuickPickFocus.Last:this._tree.scrollTop=this._tree.scrollHeight,this._tree.focusLast(void 0,G=>G.element instanceof A);break;case b.QuickPickFocus.Next:{const G=this._tree.getFocus();this._tree.focusNext(void 0,this._shouldLoop,void 0,R=>R.element instanceof A?(this._tree.reveal(R.element),!0):!1);const K=this._tree.getFocus();G.length&&G[0]===K[0]&&G[0]===this._itemElements[this._itemElements.length-1]&&this._onLeave.fire();break}case b.QuickPickFocus.Previous:{const G=this._tree.getFocus();this._tree.focusPrevious(void 0,this._shouldLoop,void 0,R=>{if(!(R.element instanceof A))return!1;const J=this._tree.getParentElement(R.element);return J===null||J.children[0]!==R.element?this._tree.reveal(R.element):this._tree.reveal(J),!0});const K=this._tree.getFocus();G.length&&G[0]===K[0]&&G[0]===this._itemElements[0]&&this._onLeave.fire();break}case b.QuickPickFocus.NextPage:this._tree.focusNextPage(void 0,G=>G.element instanceof A?(this._tree.reveal(G.element),!0):!1);break;case b.QuickPickFocus.PreviousPage:this._tree.focusPreviousPage(void 0,G=>{if(!(G.element instanceof A))return!1;const K=this._tree.getParentElement(G.element);return K===null||K.children[0]!==G.element?this._tree.reveal(G.element):this._tree.reveal(K),!0});break;case b.QuickPickFocus.NextSeparator:{let G=!1;const K=this._tree.getFocus()[0];this._tree.focusNext(void 0,!0,void 0,J=>{if(G)return!0;if(J.element instanceof N)G=!0,this._separatorRenderer.isSeparatorVisible(J.element)?this._tree.reveal(J.element.children[0]):this._tree.reveal(J.element,0);else if(J.element instanceof A){if(J.element.separator)return this._itemRenderer.isItemWithSeparatorVisible(J.element)?this._tree.reveal(J.element):this._tree.reveal(J.element,0),!0;if(J.element===this._elementTree[0])return this._tree.reveal(J.element,0),!0}return!1});const R=this._tree.getFocus()[0];K===R&&(this._tree.scrollTop=this._tree.scrollHeight,this._tree.focusLast(void 0,J=>J.element instanceof A));break}case b.QuickPickFocus.PreviousSeparator:{let G,K=!!this._tree.getFocus()[0]?.separator;this._tree.focusPrevious(void 0,!0,void 0,R=>{if(R.element instanceof N)K?G||(this._separatorRenderer.isSeparatorVisible(R.element)?this._tree.reveal(R.element):this._tree.reveal(R.element,0),G=R.element.children[0]):K=!0;else if(R.element instanceof A&&!G){if(R.element.separator)this._itemRenderer.isItemWithSeparatorVisible(R.element)?this._tree.reveal(R.element):this._tree.reveal(R.element,0),G=R.element;else if(R.element===this._elementTree[0])return this._tree.reveal(R.element,0),!0}return!1}),G&&this._tree.setFocus([G]);break}}}clearFocus(){this._tree.setFocus([])}domFocus(){this._tree.domFocus()}layout(Y){this._tree.getHTMLElement().style.maxHeight=Y?`${Math.floor(Y/44)*44+6}px`:"",this._tree.layout()}filter(Y){if(this._lastQueryString=Y,!(this._sortByLabel||this._matchOnLabel||this._matchOnDescription||this._matchOnDetail))return this._tree.layout(),!1;const G=Y;if(Y=Y.trim(),!Y||!(this.matchOnLabel||this.matchOnDescription||this.matchOnDetail))this._itemElements.forEach(K=>{K.labelHighlights=void 0,K.descriptionHighlights=void 0,K.detailHighlights=void 0,K.hidden=!1;const R=K.index&&this._inputElements[K.index-1];K.item&&(K.separator=R&&R.type==="separator"&&!R.buttons?R:void 0)});else{let K;this._itemElements.forEach(R=>{let J;this.matchOnLabelMode==="fuzzy"?J=this.matchOnLabel?(0,r.matchesFuzzyIconAware)(Y,(0,r.parseLabelWithIcons)(R.saneLabel))??void 0:void 0:J=this.matchOnLabel?H(G,(0,r.parseLabelWithIcons)(R.saneLabel))??void 0:void 0;const ie=this.matchOnDescription?(0,r.matchesFuzzyIconAware)(Y,(0,r.parseLabelWithIcons)(R.saneDescription||""))??void 0:void 0,ue=this.matchOnDetail?(0,r.matchesFuzzyIconAware)(Y,(0,r.parseLabelWithIcons)(R.saneDetail||""))??void 0:void 0;if(J||ie||ue?(R.labelHighlights=J,R.descriptionHighlights=ie,R.detailHighlights=ue,R.hidden=!1):(R.labelHighlights=void 0,R.descriptionHighlights=void 0,R.detailHighlights=void 0,R.hidden=R.item?!R.item.alwaysShow:!0),R.item?R.separator=void 0:R.separator&&(R.hidden=!0),!this.sortByLabel){const he=R.index&&this._inputElements[R.index-1]||void 0;he?.type==="separator"&&!he.buttons&&(K=he),K&&!R.hidden&&(R.separator=K,K=void 0)}})}return this._setElementsToTree(this._sortByLabel&&Y?this._itemElements:this._elementTree),this._tree.layout(),!0}toggleCheckbox(){this._elementCheckedEventBufferer.bufferEvents(()=>{const Y=this._tree.getFocus().filter(K=>K instanceof A),G=this._allVisibleChecked(Y);for(const K of Y)K.checkboxDisabled||(K.checked=!G)})}style(Y){this._tree.style(Y)}toggleHover(){const Y=this._tree.getFocus()[0];if(!Y?.saneTooltip||!(Y instanceof A))return;if(this._lastHover&&!this._lastHover.isDisposed){this._lastHover.dispose();return}this.showHover(Y);const G=new _.DisposableStore;G.add(this._tree.onDidChangeFocus(K=>{K.elements[0]instanceof A&&this.showHover(K.elements[0])})),this._lastHover&&G.add(this._lastHover),this._elementDisposable.add(G)}_setElementsToTree(Y){const G=new Array;for(const K of Y)K instanceof N?G.push({element:K,collapsible:!1,collapsed:!1,children:K.children.map(R=>({element:R,collapsible:!1,collapsed:!1}))}):G.push({element:K,collapsible:!1,collapsed:!1});this._tree.setChildren(null,G)}_allVisibleChecked(Y,G=!0){for(let K=0,R=Y.length;K{this._allVisibleCheckedObservable.set(this._allVisibleChecked(this._itemElements,!1),Y);const G=this._itemElements.filter(K=>K.checked).length;this._checkedCountObservable.set(G,Y),this._checkedElementsObservable.set(this.getCheckedElements(),Y)})}showHover(Y){this._lastHover&&!this._lastHover.isDisposed&&(this.hoverDelegate.onDidHideHover?.(),this._lastHover?.dispose()),!(!Y.element||!Y.saneTooltip)&&(this._lastHover=this.hoverDelegate.showHover({content:Y.saneTooltip,target:Y.element,linkHandler:G=>{this.linkOpenerDelegate(G)},appearance:{showPointer:!0},container:this._container,position:{hoverPosition:1}},!1))}};e.QuickInputTree=q,ke([o.memoize],q.prototype,"onDidChangeFocus",null),ke([o.memoize],q.prototype,"onDidChangeSelection",null),e.QuickInputTree=q=ke([ce(4,E.IInstantiationService),ce(5,w.IAccessibilityService)],q);function H(j,Y){const{text:G,iconOffsets:K}=Y;if(!K||K.length===0)return z(j,G);const R=(0,C.ltrim)(G," "),J=G.length-R.length,ie=z(j,R);if(ie)for(const ue of ie){const he=K[ue.start+J]+J;ue.start+=he,ue.end+=he}return ie}function z(j,Y){const G=Y.toLowerCase().indexOf(j.toLowerCase());return G!==-1?[{start:G,end:G+j.length}]:null}function U(j,Y,G){const K=j.labelHighlights||[],R=Y.labelHighlights||[];return K.length&&!R.length?-1:!K.length&&R.length?1:K.length===0&&R.length===0?0:(0,u.compareAnything)(j.saneSortLabel,Y.saneSortLabel,G)}}),define(ne[803],se([1,0,5,87,258,354,633,18,6,2,111,3,66,704,272,119,52,7,802,12,719]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a){"use strict";var r;Object.defineProperty(e,"__esModule",{value:!0}),e.QuickInputController=void 0;const u=d.$;let C=class extends b.Disposable{static{r=this}static{this.MAX_WIDTH=600}get currentQuickInput(){return this.controller??void 0}get container(){return this._container}constructor(h,v,w,S){super(),this.options=h,this.layoutService=v,this.instantiationService=w,this.contextKeyService=S,this.enabled=!0,this.onDidAcceptEmitter=this._register(new _.Emitter),this.onDidCustomEmitter=this._register(new _.Emitter),this.onDidTriggerButtonEmitter=this._register(new _.Emitter),this.keyMods={ctrlCmd:!1,alt:!1},this.controller=null,this.onShowEmitter=this._register(new _.Emitter),this.onShow=this.onShowEmitter.event,this.onHideEmitter=this._register(new _.Emitter),this.onHide=this.onHideEmitter.event,this.inQuickInputContext=i.InQuickInputContextKey.bindTo(this.contextKeyService),this.quickInputTypeContext=i.QuickInputTypeContextKey.bindTo(this.contextKeyService),this.endOfQuickInputBoxContext=i.EndOfQuickInputBoxContextKey.bindTo(this.contextKeyService),this.idPrefix=h.idPrefix,this._container=h.container,this.styles=h.styles,this._register(_.Event.runAndSubscribe(d.onDidRegisterWindow,({window:L,disposables:D})=>this.registerKeyModsListeners(L,D),{window:g.mainWindow,disposables:this._store})),this._register(d.onWillUnregisterWindow(L=>{this.ui&&d.getWindow(this.ui.container)===L&&(this.reparentUI(this.layoutService.mainContainer),this.layout(this.layoutService.mainContainerDimension,this.layoutService.mainContainerOffset.quickPickTop))}))}registerKeyModsListeners(h,v){const w=S=>{this.keyMods.ctrlCmd=S.ctrlKey||S.metaKey,this.keyMods.alt=S.altKey};for(const S of[d.EventType.KEY_DOWN,d.EventType.KEY_UP,d.EventType.MOUSE_DOWN])v.add(d.addDisposableListener(h,S,w,!0))}getUI(h){if(this.ui)return h&&d.getWindow(this._container)!==d.getWindow(this.layoutService.activeContainer)&&(this.reparentUI(this.layoutService.activeContainer),this.layout(this.layoutService.activeContainerDimension,this.layoutService.activeContainerOffset.quickPickTop)),this.ui;const v=d.append(this._container,u(".quick-input-widget.show-file-icons"));v.tabIndex=-1,v.style.display="none";const w=d.createStyleSheet(v),S=d.append(v,u(".quick-input-titlebar")),L=this._register(new k.ActionBar(S,{hoverDelegate:this.options.hoverDelegate}));L.domNode.classList.add("quick-input-left-action-bar");const D=d.append(S,u(".quick-input-title")),T=this._register(new k.ActionBar(S,{hoverDelegate:this.options.hoverDelegate}));T.domNode.classList.add("quick-input-right-action-bar");const M=d.append(v,u(".quick-input-header")),A=d.append(M,u("input.quick-input-check-all"));A.type="checkbox",A.setAttribute("aria-label",(0,n.localize)(1590,"Toggle all checkboxes")),this._register(d.addStandardDisposableListener(A,d.EventType.CHANGE,pe=>{const ae=A.checked;ue.setAllVisibleChecked(ae)})),this._register(d.addDisposableListener(A,d.EventType.CLICK,pe=>{(pe.x||pe.y)&&F.setFocus()}));const P=d.append(M,u(".quick-input-description")),N=d.append(M,u(".quick-input-and-message")),O=d.append(N,u(".quick-input-filter")),F=this._register(new t.QuickInputBox(O,this.styles.inputBox,this.styles.toggle));F.setAttribute("aria-describedby",`${this.idPrefix}message`);const x=d.append(O,u(".quick-input-visible-count"));x.setAttribute("aria-live","polite"),x.setAttribute("aria-atomic","true");const W=new E.CountBadge(x,{countFormat:(0,n.localize)(1591,"{0} Results")},this.styles.countBadge),V=d.append(O,u(".quick-input-count"));V.setAttribute("aria-live","polite");const q=new E.CountBadge(V,{countFormat:(0,n.localize)(1592,"{0} Selected")},this.styles.countBadge),H=this._register(new k.ActionBar(M,{hoverDelegate:this.options.hoverDelegate}));H.domNode.classList.add("quick-input-inline-action-bar");const z=d.append(M,u(".quick-input-action")),U=this._register(new I.Button(z,this.styles.button));U.label=(0,n.localize)(1593,"OK"),this._register(U.onDidClick(pe=>{this.onDidAcceptEmitter.fire()}));const j=d.append(M,u(".quick-input-action")),Y=this._register(new I.Button(j,{...this.styles.button,supportIcons:!0}));Y.label=(0,n.localize)(1594,"Custom"),this._register(Y.onDidClick(pe=>{this.onDidCustomEmitter.fire()}));const G=d.append(N,u(`#${this.idPrefix}message.quick-input-message`)),K=this._register(new y.ProgressBar(v,this.styles.progressBar));K.getContainer().classList.add("quick-input-progress");const R=d.append(v,u(".quick-input-html-widget"));R.tabIndex=-1;const J=d.append(v,u(".quick-input-description")),ie=this.idPrefix+"list",ue=this._register(this.instantiationService.createInstance(l.QuickInputTree,v,this.options.hoverDelegate,this.options.linkOpenerDelegate,ie));F.setAttribute("aria-controls",ie),this._register(ue.onDidChangeFocus(()=>{F.setAttribute("aria-activedescendant",ue.getActiveDescendant()??"")})),this._register(ue.onChangedAllVisibleChecked(pe=>{A.checked=pe})),this._register(ue.onChangedVisibleCount(pe=>{W.setCount(pe)})),this._register(ue.onChangedCheckedCount(pe=>{q.setCount(pe)})),this._register(ue.onLeave(()=>{setTimeout(()=>{this.controller&&(F.setFocus(),this.controller instanceof i.QuickPick&&this.controller.canSelectMany&&ue.clearFocus())},0)}));const he=d.trackFocus(v);return this._register(he),this._register(d.addDisposableListener(v,d.EventType.FOCUS,pe=>{const ae=this.getUI();if(d.isAncestor(pe.relatedTarget,ae.inputContainer)){const ee=ae.inputBox.isSelectionAtEnd();this.endOfQuickInputBoxContext.get()!==ee&&this.endOfQuickInputBoxContext.set(ee)}d.isAncestor(pe.relatedTarget,ae.container)||(this.inQuickInputContext.set(!0),this.previousFocusElement=d.isHTMLElement(pe.relatedTarget)?pe.relatedTarget:void 0)},!0)),this._register(he.onDidBlur(()=>{!this.getUI().ignoreFocusOut&&!this.options.ignoreFocusOut()&&this.hide(o.QuickInputHideReason.Blur),this.inQuickInputContext.set(!1),this.endOfQuickInputBoxContext.set(!1),this.previousFocusElement=void 0})),this._register(F.onKeyDown(pe=>{const ae=this.getUI().inputBox.isSelectionAtEnd();this.endOfQuickInputBoxContext.get()!==ae&&this.endOfQuickInputBoxContext.set(ae)})),this._register(d.addDisposableListener(v,d.EventType.FOCUS,pe=>{F.setFocus()})),this._register(d.addStandardDisposableListener(v,d.EventType.KEY_DOWN,pe=>{if(!d.isAncestor(pe.target,R))switch(pe.keyCode){case 3:d.EventHelper.stop(pe,!0),this.enabled&&this.onDidAcceptEmitter.fire();break;case 9:d.EventHelper.stop(pe,!0),this.hide(o.QuickInputHideReason.Gesture);break;case 2:if(!pe.altKey&&!pe.ctrlKey&&!pe.metaKey){const ae=[".quick-input-list .monaco-action-bar .always-visible",".quick-input-list-entry:hover .monaco-action-bar",".monaco-list-row.focused .monaco-action-bar"];if(v.classList.contains("show-checkboxes")?ae.push("input"):ae.push("input[type=text]"),this.getUI().list.displayed&&ae.push(".monaco-list"),this.getUI().message&&ae.push(".quick-input-message a"),this.getUI().widget){if(d.isAncestor(pe.target,this.getUI().widget))break;ae.push(".quick-input-html-widget")}const ee=v.querySelectorAll(ae.join(", "));pe.shiftKey&&pe.target===ee[0]?(d.EventHelper.stop(pe,!0),ue.clearFocus()):!pe.shiftKey&&d.isAncestor(pe.target,ee[ee.length-1])&&(d.EventHelper.stop(pe,!0),ee[0].focus())}break;case 10:pe.ctrlKey&&(d.EventHelper.stop(pe,!0),this.getUI().list.toggleHover());break}})),this.ui={container:v,styleSheet:w,leftActionBar:L,titleBar:S,title:D,description1:J,description2:P,widget:R,rightActionBar:T,inlineActionBar:H,checkAll:A,inputContainer:N,filterContainer:O,inputBox:F,visibleCountContainer:x,visibleCount:W,countContainer:V,count:q,okContainer:z,ok:U,message:G,customButtonContainer:j,customButton:Y,list:ue,progressBar:K,onDidAccept:this.onDidAcceptEmitter.event,onDidCustom:this.onDidCustomEmitter.event,onDidTriggerButton:this.onDidTriggerButtonEmitter.event,ignoreFocusOut:!1,keyMods:this.keyMods,show:pe=>this.show(pe),hide:()=>this.hide(),setVisibilities:pe=>this.setVisibilities(pe),setEnabled:pe=>this.setEnabled(pe),setContextKey:pe=>this.options.setContextKey(pe),linkOpenerDelegate:pe=>this.options.linkOpenerDelegate(pe)},this.updateStyles(),this.ui}reparentUI(h){this.ui&&(this._container=h,d.append(this._container,this.ui.container))}pick(h,v={},w=m.CancellationToken.None){return new Promise((S,L)=>{let D=P=>{D=S,v.onKeyMods?.(T.keyMods),S(P)};if(w.isCancellationRequested){D(void 0);return}const T=this.createQuickPick({useSeparators:!0});let M;const A=[T,T.onDidAccept(()=>{if(T.canSelectMany)D(T.selectedItems.slice()),T.hide();else{const P=T.activeItems[0];P&&(D(P),T.hide())}}),T.onDidChangeActive(P=>{const N=P[0];N&&v.onDidFocus&&v.onDidFocus(N)}),T.onDidChangeSelection(P=>{if(!T.canSelectMany){const N=P[0];N&&(D(N),T.hide())}}),T.onDidTriggerItemButton(P=>v.onDidTriggerItemButton&&v.onDidTriggerItemButton({...P,removeItem:()=>{const N=T.items.indexOf(P.item);if(N!==-1){const O=T.items.slice(),F=O.splice(N,1),x=T.activeItems.filter(V=>V!==F[0]),W=T.keepScrollPosition;T.keepScrollPosition=!0,T.items=O,x&&(T.activeItems=x),T.keepScrollPosition=W}}})),T.onDidTriggerSeparatorButton(P=>v.onDidTriggerSeparatorButton?.(P)),T.onDidChangeValue(P=>{M&&!P&&(T.activeItems.length!==1||T.activeItems[0]!==M)&&(T.activeItems=[M])}),w.onCancellationRequested(()=>{T.hide()}),T.onDidHide(()=>{(0,b.dispose)(A),D(void 0)})];T.title=v.title,v.value&&(T.value=v.value),T.canSelectMany=!!v.canPickMany,T.placeholder=v.placeHolder,T.ignoreFocusOut=!!v.ignoreFocusLost,T.matchOnDescription=!!v.matchOnDescription,T.matchOnDetail=!!v.matchOnDetail,T.matchOnLabel=v.matchOnLabel===void 0||v.matchOnLabel,T.quickNavigate=v.quickNavigate,T.hideInput=!!v.hideInput,T.contextKey=v.contextKey,T.busy=!0,Promise.all([h,v.activeItem]).then(([P,N])=>{M=N,T.busy=!1,T.items=P,T.canSelectMany&&(T.selectedItems=P.filter(O=>O.type!=="separator"&&O.picked)),M&&(T.activeItems=[M])}),T.show(),Promise.resolve(h).then(void 0,P=>{L(P),T.hide()})})}createQuickPick(h={useSeparators:!1}){const v=this.getUI(!0);return new i.QuickPick(v)}createInputBox(){const h=this.getUI(!0);return new i.InputBox(h)}show(h){const v=this.getUI(!0);this.onShowEmitter.fire();const w=this.controller;this.controller=h,w?.didHide(),this.setEnabled(!0),v.leftActionBar.clear(),v.title.textContent="",v.description1.textContent="",v.description2.textContent="",d.reset(v.widget),v.rightActionBar.clear(),v.inlineActionBar.clear(),v.checkAll.checked=!1,v.inputBox.placeholder="",v.inputBox.password=!1,v.inputBox.showDecoration(p.default.Ignore),v.visibleCount.setCount(0),v.count.setCount(0),d.reset(v.message),v.progressBar.stop(),v.list.setElements([]),v.list.matchOnDescription=!1,v.list.matchOnDetail=!1,v.list.matchOnLabel=!0,v.list.sortByLabel=!0,v.ignoreFocusOut=!1,v.inputBox.toggles=void 0;const S=this.options.backKeybindingLabel();i.backButton.tooltip=S?(0,n.localize)(1595,"Back ({0})",S):(0,n.localize)(1596,"Back"),v.container.style.display="",this.updateLayout(),v.inputBox.setFocus(),this.quickInputTypeContext.set(h.type)}isVisible(){return!!this.ui&&this.ui.container.style.display!=="none"}setVisibilities(h){const v=this.getUI();v.title.style.display=h.title?"":"none",v.description1.style.display=h.description&&(h.inputBox||h.checkAll)?"":"none",v.description2.style.display=h.description&&!(h.inputBox||h.checkAll)?"":"none",v.checkAll.style.display=h.checkAll?"":"none",v.inputContainer.style.display=h.inputBox?"":"none",v.filterContainer.style.display=h.inputBox?"":"none",v.visibleCountContainer.style.display=h.visibleCount?"":"none",v.countContainer.style.display=h.count?"":"none",v.okContainer.style.display=h.ok?"":"none",v.customButtonContainer.style.display=h.customButton?"":"none",v.message.style.display=h.message?"":"none",v.progressBar.getContainer().style.display=h.progressBar?"":"none",v.list.displayed=!!h.list,v.container.classList.toggle("show-checkboxes",!!h.checkBox),v.container.classList.toggle("hidden-input",!h.inputBox&&!h.description),this.updateLayout()}setEnabled(h){if(h!==this.enabled){this.enabled=h;for(const v of this.getUI().leftActionBar.viewItems)v.action.enabled=h;for(const v of this.getUI().rightActionBar.viewItems)v.action.enabled=h;this.getUI().checkAll.disabled=!h,this.getUI().inputBox.enabled=h,this.getUI().ok.enabled=h,this.getUI().list.enabled=h}}hide(h){const v=this.controller;if(!v)return;v.willHide(h);const w=this.ui?.container,S=w&&!d.isAncestorOfActiveElement(w);if(this.controller=null,this.onHideEmitter.fire(),w&&(w.style.display="none"),!S){let L=this.previousFocusElement;for(;L&&!L.offsetParent;)L=L.parentElement??void 0;L?.offsetParent?(L.focus(),this.previousFocusElement=void 0):this.options.returnFocus()}v.didHide(h)}layout(h,v){this.dimension=h,this.titleBarOffset=v,this.updateLayout()}updateLayout(){if(this.ui&&this.isVisible()){this.ui.container.style.top=`${this.titleBarOffset}px`;const h=this.ui.container.style,v=Math.min(this.dimension.width*.62,r.MAX_WIDTH);h.width=v+"px",h.marginLeft="-"+v/2+"px",this.ui.inputBox.layout(),this.ui.list.layout(this.dimension&&this.dimension.height*.4)}}applyStyles(h){this.styles=h,this.updateStyles()}updateStyles(){if(this.ui){const{quickInputTitleBackground:h,quickInputBackground:v,quickInputForeground:w,widgetBorder:S,widgetShadow:L}=this.styles.widget;this.ui.titleBar.style.backgroundColor=h??"",this.ui.container.style.backgroundColor=v??"",this.ui.container.style.color=w??"",this.ui.container.style.border=S?`1px solid ${S}`:"",this.ui.container.style.boxShadow=L?`0 0 8px 2px ${L}`:"",this.ui.list.style(this.styles.list);const D=[];this.styles.pickerGroup.pickerGroupBorder&&D.push(`.quick-input-list .quick-input-list-entry { border-top-color: ${this.styles.pickerGroup.pickerGroupBorder}; }`),this.styles.pickerGroup.pickerGroupForeground&&D.push(`.quick-input-list .quick-input-list-separator { color: ${this.styles.pickerGroup.pickerGroupForeground}; }`),this.styles.pickerGroup.pickerGroupForeground&&D.push(".quick-input-list .quick-input-list-separator-as-item { color: var(--vscode-descriptionForeground); }"),(this.styles.keybindingLabel.keybindingLabelBackground||this.styles.keybindingLabel.keybindingLabelBorder||this.styles.keybindingLabel.keybindingLabelBottomBorder||this.styles.keybindingLabel.keybindingLabelShadow||this.styles.keybindingLabel.keybindingLabelForeground)&&(D.push(".quick-input-list .monaco-keybinding > .monaco-keybinding-key {"),this.styles.keybindingLabel.keybindingLabelBackground&&D.push(`background-color: ${this.styles.keybindingLabel.keybindingLabelBackground};`),this.styles.keybindingLabel.keybindingLabelBorder&&D.push(`border-color: ${this.styles.keybindingLabel.keybindingLabelBorder};`),this.styles.keybindingLabel.keybindingLabelBottomBorder&&D.push(`border-bottom-color: ${this.styles.keybindingLabel.keybindingLabelBottomBorder};`),this.styles.keybindingLabel.keybindingLabelShadow&&D.push(`box-shadow: inset 0 -1px 0 ${this.styles.keybindingLabel.keybindingLabelShadow};`),this.styles.keybindingLabel.keybindingLabelForeground&&D.push(`color: ${this.styles.keybindingLabel.keybindingLabelForeground};`),D.push("}"));const T=D.join(` `);T!==this.ui.styleSheet.textContent&&(this.ui.styleSheet.textContent=T)}}};e.QuickInputController=C,e.QuickInputController=C=r=ke([ce(1,s.ILayoutService),ce(2,c.IInstantiationService),ce(3,a.IContextKeyService)],C)}),define(ne[804],se([1,0,18,6,12,7,119,59,722,110,32,25,272,803,28,5]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QuickInputService=void 0;let g=class extends n.Themable{get controller(){return this._controller||(this._controller=this._register(this.createController())),this._controller}get hasController(){return!!this._controller}get currentQuickInput(){return this.controller.currentQuickInput}get quickAccess(){return this._quickAccess||(this._quickAccess=this._register(this.instantiationService.createInstance(_.QuickAccessController))),this._quickAccess}constructor(l,a,r,u,C){super(r),this.instantiationService=l,this.contextKeyService=a,this.layoutService=u,this.configurationService=C,this._onShow=this._register(new k.Emitter),this._onHide=this._register(new k.Emitter),this.contexts=new Map}createController(l=this.layoutService,a){const r={idPrefix:"quickInput_",container:l.activeContainer,ignoreFocusOut:()=>!1,backKeybindingLabel:()=>{},setContextKey:C=>this.setContextKey(C),linkOpenerDelegate:C=>{this.instantiationService.invokeFunction(f=>{f.get(m.IOpenerService).open(C,{allowCommands:!0,fromUserGesture:!0})})},returnFocus:()=>l.focus(),styles:this.computeStyles(),hoverDelegate:this._register(this.instantiationService.createInstance(o.QuickInputHoverDelegate))},u=this._register(this.instantiationService.createInstance(t.QuickInputController,{...r,...a}));return u.layout(l.activeContainerDimension,l.activeContainerOffset.quickPickTop),this._register(l.onDidLayoutActiveContainer(C=>{(0,s.getWindow)(l.activeContainer)===(0,s.getWindow)(u.container)&&u.layout(C,l.activeContainerOffset.quickPickTop)})),this._register(l.onDidChangeActiveContainer(()=>{u.isVisible()||u.layout(l.activeContainerDimension,l.activeContainerOffset.quickPickTop)})),this._register(u.onShow(()=>{this.resetContextKeys(),this._onShow.fire()})),this._register(u.onHide(()=>{this.resetContextKeys(),this._onHide.fire()})),u}setContextKey(l){let a;l&&(a=this.contexts.get(l),a||(a=new I.RawContextKey(l,!1).bindTo(this.contextKeyService),this.contexts.set(l,a))),!(a&&a.get())&&(this.resetContextKeys(),a?.set(!0))}resetContextKeys(){this.contexts.forEach(l=>{l.get()&&l.reset()})}pick(l,a,r=d.CancellationToken.None){return this.controller.pick(l,a,r)}createQuickPick(l={useSeparators:!1}){return this.controller.createQuickPick(l)}createInputBox(){return this.controller.createInputBox()}updateStyles(){this.hasController&&this.controller.applyStyles(this.computeStyles())}computeStyles(){return{widget:{quickInputBackground:(0,p.asCssVariable)(p.quickInputBackground),quickInputForeground:(0,p.asCssVariable)(p.quickInputForeground),quickInputTitleBackground:(0,p.asCssVariable)(p.quickInputTitleBackground),widgetBorder:(0,p.asCssVariable)(p.widgetBorder),widgetShadow:(0,p.asCssVariable)(p.widgetShadow)},inputBox:b.defaultInputBoxStyles,toggle:b.defaultToggleStyles,countBadge:b.defaultCountBadgeStyles,button:b.defaultButtonStyles,progressBar:b.defaultProgressBarStyles,keybindingLabel:b.defaultKeybindingLabelStyles,list:(0,b.getListStyles)({listBackground:p.quickInputBackground,listFocusBackground:p.quickInputListFocusBackground,listFocusForeground:p.quickInputListFocusForeground,listInactiveFocusForeground:p.quickInputListFocusForeground,listInactiveSelectionIconForeground:p.quickInputListFocusIconForeground,listInactiveFocusBackground:p.quickInputListFocusBackground,listFocusOutline:p.activeContrastBorder,listInactiveFocusOutline:p.activeContrastBorder}),pickerGroup:{pickerGroupBorder:(0,p.asCssVariable)(p.pickerGroupBorder),pickerGroupForeground:(0,p.asCssVariable)(p.pickerGroupForeground)}}}};e.QuickInputService=g,e.QuickInputService=g=ke([ce(0,E.IInstantiationService),ce(1,I.IContextKeyService),ce(2,n.IThemeService),ce(3,y.ILayoutService),ce(4,i.IConfigurationService)],g)}),define(ne[805],se([1,0,6,15,25,18,7,12,394,34,804,127,28,540]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QuickInputEditorWidget=e.QuickInputEditorContribution=e.StandaloneQuickInputService=void 0;let t=class extends p.QuickInputService{constructor(l,a,r,u,C,f){super(a,r,u,new _.EditorScopedLayoutService(l.getContainerDomNode(),C),f),this.host=void 0;const h=s.get(l);if(h){const v=h.widget;this.host={_serviceBrand:void 0,get mainContainer(){return v.getDomNode()},getContainer(){return v.getDomNode()},whenContainerStylesLoaded(){},get containers(){return[v.getDomNode()]},get activeContainer(){return v.getDomNode()},get mainContainerDimension(){return l.getLayoutInfo()},get activeContainerDimension(){return l.getLayoutInfo()},get onDidLayoutMainContainer(){return l.onDidLayoutChange},get onDidLayoutActiveContainer(){return l.onDidLayoutChange},get onDidLayoutContainer(){return d.Event.map(l.onDidLayoutChange,w=>({container:v.getDomNode(),dimension:w}))},get onDidChangeActiveContainer(){return d.Event.None},get onDidAddContainer(){return d.Event.None},get mainContainerOffset(){return{top:0,quickPickTop:0}},get activeContainerOffset(){return{top:0,quickPickTop:0}},focus:()=>l.focus()}}else this.host=void 0}createController(){return super.createController(this.host)}};t=ke([ce(1,y.IInstantiationService),ce(2,m.IContextKeyService),ce(3,I.IThemeService),ce(4,b.ICodeEditorService),ce(5,o.IConfigurationService)],t);let i=class{get activeService(){const l=this.codeEditorService.getFocusedCodeEditor();if(!l)throw new Error("Quick input service needs a focused editor to work.");let a=this.mapEditorToService.get(l);if(!a){const r=a=this.instantiationService.createInstance(t,l);this.mapEditorToService.set(l,a),(0,n.createSingleCallFunction)(l.onDidDispose)(()=>{r.dispose(),this.mapEditorToService.delete(l)})}return a}get currentQuickInput(){return this.activeService.currentQuickInput}get quickAccess(){return this.activeService.quickAccess}constructor(l,a){this.instantiationService=l,this.codeEditorService=a,this.mapEditorToService=new Map}pick(l,a,r=E.CancellationToken.None){return this.activeService.pick(l,a,r)}createQuickPick(l={useSeparators:!1}){return this.activeService.createQuickPick(l)}createInputBox(){return this.activeService.createInputBox()}};e.StandaloneQuickInputService=i,e.StandaloneQuickInputService=i=ke([ce(0,y.IInstantiationService),ce(1,b.ICodeEditorService)],i);class s{static{this.ID="editor.controller.quickInput"}static get(l){return l.getContribution(s.ID)}constructor(l){this.editor=l,this.widget=new g(this.editor)}dispose(){this.widget.dispose()}}e.QuickInputEditorContribution=s;class g{static{this.ID="editor.contrib.quickInputWidget"}constructor(l){this.codeEditor=l,this.domNode=document.createElement("div"),this.codeEditor.addOverlayWidget(this)}getId(){return g.ID}getDomNode(){return this.domNode}getPosition(){return{preference:2}}dispose(){this.codeEditor.removeOverlayWidget(this)}}e.QuickInputEditorWidget=g,(0,k.registerEditorContribution)(s.ID,s,4)}),define(ne[284],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UndoRedoSource=e.UndoRedoGroup=e.ResourceEditStackSnapshot=e.IUndoRedoService=void 0,e.IUndoRedoService=(0,d.createDecorator)("undoRedoService");class k{constructor(m,_){this.resource=m,this.elements=_}}e.ResourceEditStackSnapshot=k;class I{static{this._ID=0}constructor(){this.id=I._ID++,this.order=1}nextOrder(){return this.id===0?0:this.order++}static{this.None=new I}}e.UndoRedoGroup=I;class E{static{this._ID=0}constructor(){this.id=E._ID++,this.order=1}nextOrder(){return this.id===0?0:this.order++}static{this.None=new E}}e.UndoRedoSource=E}),define(ne[35],se([1,0,13,33,8,6,2,11,22,145,230,9,4,23,197,43,36,40,661,783,370,329,577,578,371,662,202,707,263,132,7,284]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M){"use strict";var A;Object.defineProperty(e,"__esModule",{value:!0}),e.ModelDecorationOptions=e.ModelDecorationInjectedTextOptions=e.ModelDecorationMinimapOptions=e.ModelDecorationGlyphMarginOptions=e.ModelDecorationOverviewRulerOptions=e.TextModel=void 0,e.createTextBufferFactory=P,e.createTextBufferFactoryFromSnapshot=N,e.createTextBuffer=O,e.indentOfLine=z;function P(X){const B=new v.PieceTreeTextBufferBuilder;return B.acceptChunk(X),B.finish()}function N(X){const B=new v.PieceTreeTextBufferBuilder;let $;for(;typeof($=X.read())=="string";)B.acceptChunk($);return B.finish()}function O(X,B){let $;return typeof X=="string"?$=P(X):c.isITextSnapshot(X)?$=N(X):$=X,$.create(B)}let F=0;const x=999,W=1e4;class V{constructor(B){this._source=B,this._eos=!1}read(){if(this._eos)return null;const B=[];let $=0,Q=0;do{const Z=this._source.read();if(Z===null)return this._eos=!0,$===0?null:B.join("");if(Z.length>0&&(B[$++]=Z,Q+=Z.length),Q>=64*1024)return B.join("")}while(!0)}}const q=()=>{throw new Error("Invalid change accessor")};let H=class extends y.Disposable{static{A=this}static{this._MODEL_SYNC_LIMIT=50*1024*1024}static{this.LARGE_FILE_SIZE_THRESHOLD=20*1024*1024}static{this.LARGE_FILE_LINE_COUNT_THRESHOLD=300*1e3}static{this.LARGE_FILE_HEAP_OPERATION_THRESHOLD=256*1024*1024}static{this.DEFAULT_CREATION_OPTIONS={isForSimpleWidget:!1,tabSize:i.EDITOR_MODEL_DEFAULTS.tabSize,indentSize:i.EDITOR_MODEL_DEFAULTS.indentSize,insertSpaces:i.EDITOR_MODEL_DEFAULTS.insertSpaces,detectIndentation:!1,defaultEOL:1,trimAutoWhitespace:i.EDITOR_MODEL_DEFAULTS.trimAutoWhitespace,largeFileOptimizations:i.EDITOR_MODEL_DEFAULTS.largeFileOptimizations,bracketPairColorizationOptions:i.EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions}}static resolveOptions(B,$){if($.detectIndentation){const Q=(0,C.guessIndentation)(B,$.tabSize,$.insertSpaces);return new c.TextModelResolvedOptions({tabSize:Q.tabSize,indentSize:"tabSize",insertSpaces:Q.insertSpaces,trimAutoWhitespace:$.trimAutoWhitespace,defaultEOL:$.defaultEOL,bracketPairColorizationOptions:$.bracketPairColorizationOptions})}return new c.TextModelResolvedOptions($)}get onDidChangeLanguage(){return this._tokenizationTextModelPart.onDidChangeLanguage}get onDidChangeLanguageConfiguration(){return this._tokenizationTextModelPart.onDidChangeLanguageConfiguration}get onDidChangeTokens(){return this._tokenizationTextModelPart.onDidChangeTokens}onDidChangeContent(B){return this._eventEmitter.slowEvent($=>B($.contentChangedEvent))}onDidChangeContentOrInjectedText(B){return(0,y.combinedDisposable)(this._eventEmitter.fastEvent($=>B($)),this._onDidChangeInjectedText.event($=>B($)))}_isDisposing(){return this.__isDisposing}get tokenization(){return this._tokenizationTextModelPart}get bracketPairs(){return this._bracketPairs}get guides(){return this._guidesTextModelPart}constructor(B,$,Q,Z=null,te,re,le,me){super(),this._undoRedoService=te,this._languageService=re,this._languageConfigurationService=le,this.instantiationService=me,this._onWillDispose=this._register(new E.Emitter),this.onWillDispose=this._onWillDispose.event,this._onDidChangeDecorations=this._register(new de(Ae=>this.handleBeforeFireDecorationsChangedEvent(Ae))),this.onDidChangeDecorations=this._onDidChangeDecorations.event,this._onDidChangeOptions=this._register(new E.Emitter),this.onDidChangeOptions=this._onDidChangeOptions.event,this._onDidChangeAttached=this._register(new E.Emitter),this.onDidChangeAttached=this._onDidChangeAttached.event,this._onDidChangeInjectedText=this._register(new E.Emitter),this._eventEmitter=this._register(new ge),this._languageSelectionListener=this._register(new y.MutableDisposable),this._deltaDecorationCallCnt=0,this._attachedViews=new L.AttachedViews,F++,this.id="$model"+F,this.isForSimpleWidget=Q.isForSimpleWidget,typeof Z>"u"||Z===null?this._associatedResource=_.URI.parse("inmemory://model/"+F):this._associatedResource=Z,this._attachedEditorCount=0;const{textBuffer:Ce,disposable:ye}=O(B,Q.defaultEOL);this._buffer=Ce,this._bufferDisposable=ye,this._options=A.resolveOptions(this._buffer,Q);const Le=typeof $=="string"?$:$.languageId;typeof $!="string"&&(this._languageSelectionListener.value=$.onDidChange(()=>this._setLanguage($.languageId))),this._bracketPairs=this._register(new l.BracketPairsTextModelPart(this,this._languageConfigurationService)),this._guidesTextModelPart=this._register(new u.GuidesTextModelPart(this,this._languageConfigurationService)),this._decorationProvider=this._register(new a.ColorizedBracketPairsDecorationProvider(this)),this._tokenizationTextModelPart=this.instantiationService.createInstance(S.TokenizationTextModelPart,this,this._bracketPairs,Le,this._attachedViews);const Ee=this._buffer.getLineCount(),Me=this._buffer.getValueLengthInRange(new o.Range(1,1,Ee,this._buffer.getLineLength(Ee)+1),0);Q.largeFileOptimizations?(this._isTooLargeForTokenization=Me>A.LARGE_FILE_SIZE_THRESHOLD||Ee>A.LARGE_FILE_LINE_COUNT_THRESHOLD,this._isTooLargeForHeapOperation=Me>A.LARGE_FILE_HEAP_OPERATION_THRESHOLD):(this._isTooLargeForTokenization=!1,this._isTooLargeForHeapOperation=!1),this._isTooLargeForSyncing=Me>A._MODEL_SYNC_LIMIT,this._versionId=1,this._alternativeVersionId=1,this._initialUndoRedoSnapshot=null,this._isDisposed=!1,this.__isDisposing=!1,this._instanceId=m.singleLetterHash(F),this._lastDecorationId=0,this._decorations=Object.create(null),this._decorationsTree=new G,this._commandManager=new r.EditStack(this,this._undoRedoService),this._isUndoing=!1,this._isRedoing=!1,this._trimAutoWhitespaceLines=null,this._register(this._decorationProvider.onDidChange(()=>{this._onDidChangeDecorations.beginDeferredEmit(),this._onDidChangeDecorations.fire(),this._onDidChangeDecorations.endDeferredEmit()})),this._languageService.requestRichLanguageFeatures(Le),this._register(this._languageConfigurationService.onDidChange(Ae=>{this._bracketPairs.handleLanguageConfigurationServiceChange(Ae),this._tokenizationTextModelPart.handleLanguageConfigurationServiceChange(Ae)}))}dispose(){this.__isDisposing=!0,this._onWillDispose.fire(),this._tokenizationTextModelPart.dispose(),this._isDisposed=!0,super.dispose(),this._bufferDisposable.dispose(),this.__isDisposing=!1;const B=new h.PieceTreeTextBuffer([],"",` `,!1,!1,!0,!0);B.dispose(),this._buffer=B,this._bufferDisposable=y.Disposable.None}_assertNotDisposed(){if(this._isDisposed)throw new I.BugIndicatingError("Model is disposed!")}_emitContentChangedEvent(B,$){this.__isDisposing||(this._tokenizationTextModelPart.handleDidChangeContent($),this._bracketPairs.handleDidChangeContent($),this._eventEmitter.fire(new D.InternalModelContentChangeEvent(B,$)))}setValue(B){if(this._assertNotDisposed(),B==null)throw(0,I.illegalArgument)();const{textBuffer:$,disposable:Q}=O(B,this._options.defaultEOL);this._setValueFromTextBuffer($,Q)}_createContentChanged2(B,$,Q,Z,te,re,le,me){return{changes:[{range:B,rangeOffset:$,rangeLength:Q,text:Z}],eol:this._buffer.getEOL(),isEolChange:me,versionId:this.getVersionId(),isUndoing:te,isRedoing:re,isFlush:le}}_setValueFromTextBuffer(B,$){this._assertNotDisposed();const Q=this.getFullModelRange(),Z=this.getValueLengthInRange(Q),te=this.getLineCount(),re=this.getLineMaxColumn(te);this._buffer=B,this._bufferDisposable.dispose(),this._bufferDisposable=$,this._increaseVersionId(),this._decorations=Object.create(null),this._decorationsTree=new G,this._commandManager.clear(),this._trimAutoWhitespaceLines=null,this._emitContentChangedEvent(new D.ModelRawContentChangedEvent([new D.ModelRawFlush],this._versionId,!1,!1),this._createContentChanged2(new o.Range(1,1,te,re),0,Z,this.getValue(),!1,!1,!0,!1))}setEOL(B){this._assertNotDisposed();const $=B===1?`\r `:` `;if(this._buffer.getEOL()===$)return;const Q=this.getFullModelRange(),Z=this.getValueLengthInRange(Q),te=this.getLineCount(),re=this.getLineMaxColumn(te);this._onBeforeEOLChange(),this._buffer.setEOL($),this._increaseVersionId(),this._onAfterEOLChange(),this._emitContentChangedEvent(new D.ModelRawContentChangedEvent([new D.ModelRawEOLChanged],this._versionId,!1,!1),this._createContentChanged2(new o.Range(1,1,te,re),0,Z,this.getValue(),!1,!1,!1,!0))}_onBeforeEOLChange(){this._decorationsTree.ensureAllNodesHaveRanges(this)}_onAfterEOLChange(){const B=this.getVersionId(),$=this._decorationsTree.collectNodesPostOrder();for(let Q=0,Z=$.length;Q0}getAttachedEditorCount(){return this._attachedEditorCount}isTooLargeForSyncing(){return this._isTooLargeForSyncing}isTooLargeForTokenization(){return this._isTooLargeForTokenization}isTooLargeForHeapOperation(){return this._isTooLargeForHeapOperation}isDisposed(){return this._isDisposed}isDominatedByLongLines(){if(this._assertNotDisposed(),this.isTooLargeForTokenization())return!1;let B=0,$=0;const Q=this._buffer.getLineCount();for(let Z=1;Z<=Q;Z++){const te=this._buffer.getLineLength(Z);te>=W?$+=te:B+=te}return $>B}get uri(){return this._associatedResource}getOptions(){return this._assertNotDisposed(),this._options}getFormattingOptions(){return{tabSize:this._options.indentSize,insertSpaces:this._options.insertSpaces}}updateOptions(B){this._assertNotDisposed();const $=typeof B.tabSize<"u"?B.tabSize:this._options.tabSize,Q=typeof B.indentSize<"u"?B.indentSize:this._options.originalIndentSize,Z=typeof B.insertSpaces<"u"?B.insertSpaces:this._options.insertSpaces,te=typeof B.trimAutoWhitespace<"u"?B.trimAutoWhitespace:this._options.trimAutoWhitespace,re=typeof B.bracketColorizationOptions<"u"?B.bracketColorizationOptions:this._options.bracketPairColorizationOptions,le=new c.TextModelResolvedOptions({tabSize:$,indentSize:Q,insertSpaces:Z,defaultEOL:this._options.defaultEOL,trimAutoWhitespace:te,bracketPairColorizationOptions:re});if(this._options.equals(le))return;const me=this._options.createChangeEvent(le);this._options=le,this._bracketPairs.handleDidChangeOptions(me),this._decorationProvider.handleDidChangeOptions(me),this._onDidChangeOptions.fire(me)}detectIndentation(B,$){this._assertNotDisposed();const Q=(0,C.guessIndentation)(this._buffer,$,B);this.updateOptions({insertSpaces:Q.insertSpaces,tabSize:Q.tabSize,indentSize:Q.tabSize})}normalizeIndentation(B){return this._assertNotDisposed(),(0,p.normalizeIndentation)(B,this._options.indentSize,this._options.insertSpaces)}getVersionId(){return this._assertNotDisposed(),this._versionId}mightContainRTL(){return this._buffer.mightContainRTL()}mightContainUnusualLineTerminators(){return this._buffer.mightContainUnusualLineTerminators()}removeUnusualLineTerminators(B=null){const $=this.findMatches(m.UNUSUAL_LINE_TERMINATORS.source,!1,!0,!1,null,!1,1073741824);this._buffer.resetMightContainUnusualLineTerminators(),this.pushEditOperations(B,$.map(Q=>({range:Q.range,text:null})),()=>null)}mightContainNonBasicASCII(){return this._buffer.mightContainNonBasicASCII()}getAlternativeVersionId(){return this._assertNotDisposed(),this._alternativeVersionId}getInitialUndoRedoSnapshot(){return this._assertNotDisposed(),this._initialUndoRedoSnapshot}getOffsetAt(B){this._assertNotDisposed();const $=this._validatePosition(B.lineNumber,B.column,0);return this._buffer.getOffsetAt($.lineNumber,$.column)}getPositionAt(B){this._assertNotDisposed();const $=Math.min(this._buffer.getLength(),Math.max(0,B));return this._buffer.getPositionAt($)}_increaseVersionId(){this._versionId=this._versionId+1,this._alternativeVersionId=this._versionId}_overwriteVersionId(B){this._versionId=B}_overwriteAlternativeVersionId(B){this._alternativeVersionId=B}_overwriteInitialUndoRedoSnapshot(B){this._initialUndoRedoSnapshot=B}getValue(B,$=!1){if(this._assertNotDisposed(),this.isTooLargeForHeapOperation())throw new I.BugIndicatingError("Operation would exceed heap memory limits");const Q=this.getFullModelRange(),Z=this.getValueInRange(Q,B);return $?this._buffer.getBOM()+Z:Z}createSnapshot(B=!1){return new V(this._buffer.createSnapshot(B))}getValueLength(B,$=!1){this._assertNotDisposed();const Q=this.getFullModelRange(),Z=this.getValueLengthInRange(Q,B);return $?this._buffer.getBOM().length+Z:Z}getValueInRange(B,$=0){return this._assertNotDisposed(),this._buffer.getValueInRange(this.validateRange(B),$)}getValueLengthInRange(B,$=0){return this._assertNotDisposed(),this._buffer.getValueLengthInRange(this.validateRange(B),$)}getCharacterCountInRange(B,$=0){return this._assertNotDisposed(),this._buffer.getCharacterCountInRange(this.validateRange(B),$)}getLineCount(){return this._assertNotDisposed(),this._buffer.getLineCount()}getLineContent(B){if(this._assertNotDisposed(),B<1||B>this.getLineCount())throw new I.BugIndicatingError("Illegal value for lineNumber");return this._buffer.getLineContent(B)}getLineLength(B){if(this._assertNotDisposed(),B<1||B>this.getLineCount())throw new I.BugIndicatingError("Illegal value for lineNumber");return this._buffer.getLineLength(B)}getLinesContent(){if(this._assertNotDisposed(),this.isTooLargeForHeapOperation())throw new I.BugIndicatingError("Operation would exceed heap memory limits");return this._buffer.getLinesContent()}getEOL(){return this._assertNotDisposed(),this._buffer.getEOL()}getEndOfLineSequence(){return this._assertNotDisposed(),this._buffer.getEOL()===` `?0:1}getLineMinColumn(B){return this._assertNotDisposed(),1}getLineMaxColumn(B){if(this._assertNotDisposed(),B<1||B>this.getLineCount())throw new I.BugIndicatingError("Illegal value for lineNumber");return this._buffer.getLineLength(B)+1}getLineFirstNonWhitespaceColumn(B){if(this._assertNotDisposed(),B<1||B>this.getLineCount())throw new I.BugIndicatingError("Illegal value for lineNumber");return this._buffer.getLineFirstNonWhitespaceColumn(B)}getLineLastNonWhitespaceColumn(B){if(this._assertNotDisposed(),B<1||B>this.getLineCount())throw new I.BugIndicatingError("Illegal value for lineNumber");return this._buffer.getLineLastNonWhitespaceColumn(B)}_validateRangeRelaxedNoAllocations(B){const $=this._buffer.getLineCount(),Q=B.startLineNumber,Z=B.startColumn;let te=Math.floor(typeof Q=="number"&&!isNaN(Q)?Q:1),re=Math.floor(typeof Z=="number"&&!isNaN(Z)?Z:1);if(te<1)te=1,re=1;else if(te>$)te=$,re=this.getLineMaxColumn(te);else if(re<=1)re=1;else{const Le=this.getLineMaxColumn(te);re>=Le&&(re=Le)}const le=B.endLineNumber,me=B.endColumn;let Ce=Math.floor(typeof le=="number"&&!isNaN(le)?le:1),ye=Math.floor(typeof me=="number"&&!isNaN(me)?me:1);if(Ce<1)Ce=1,ye=1;else if(Ce>$)Ce=$,ye=this.getLineMaxColumn(Ce);else if(ye<=1)ye=1;else{const Le=this.getLineMaxColumn(Ce);ye>=Le&&(ye=Le)}return Q===te&&Z===re&&le===Ce&&me===ye&&B instanceof o.Range&&!(B instanceof t.Selection)?B:new o.Range(te,re,Ce,ye)}_isValidPosition(B,$,Q){if(typeof B!="number"||typeof $!="number"||isNaN(B)||isNaN($)||B<1||$<1||(B|0)!==B||($|0)!==$)return!1;const Z=this._buffer.getLineCount();if(B>Z)return!1;if($===1)return!0;const te=this.getLineMaxColumn(B);if($>te)return!1;if(Q===1){const re=this._buffer.getLineCharCode(B,$-2);if(m.isHighSurrogate(re))return!1}return!0}_validatePosition(B,$,Q){const Z=Math.floor(typeof B=="number"&&!isNaN(B)?B:1),te=Math.floor(typeof $=="number"&&!isNaN($)?$:1),re=this._buffer.getLineCount();if(Z<1)return new n.Position(1,1);if(Z>re)return new n.Position(re,this.getLineMaxColumn(re));if(te<=1)return new n.Position(Z,1);const le=this.getLineMaxColumn(Z);if(te>=le)return new n.Position(Z,le);if(Q===1){const me=this._buffer.getLineCharCode(Z,te-2);if(m.isHighSurrogate(me))return new n.Position(Z,te-1)}return new n.Position(Z,te)}validatePosition(B){return this._assertNotDisposed(),B instanceof n.Position&&this._isValidPosition(B.lineNumber,B.column,1)?B:this._validatePosition(B.lineNumber,B.column,1)}_isValidRange(B,$){const Q=B.startLineNumber,Z=B.startColumn,te=B.endLineNumber,re=B.endColumn;if(!this._isValidPosition(Q,Z,0)||!this._isValidPosition(te,re,0))return!1;if($===1){const le=Z>1?this._buffer.getLineCharCode(Q,Z-2):0,me=re>1&&re<=this._buffer.getLineLength(te)?this._buffer.getLineCharCode(te,re-2):0,Ce=m.isHighSurrogate(le),ye=m.isHighSurrogate(me);return!Ce&&!ye}return!0}validateRange(B){if(this._assertNotDisposed(),B instanceof o.Range&&!(B instanceof t.Selection)&&this._isValidRange(B,1))return B;const Q=this._validatePosition(B.startLineNumber,B.startColumn,0),Z=this._validatePosition(B.endLineNumber,B.endColumn,0),te=Q.lineNumber,re=Q.column,le=Z.lineNumber,me=Z.column;{const Ce=re>1?this._buffer.getLineCharCode(te,re-2):0,ye=me>1&&me<=this._buffer.getLineLength(le)?this._buffer.getLineCharCode(le,me-2):0,Le=m.isHighSurrogate(Ce),Ee=m.isHighSurrogate(ye);return!Le&&!Ee?new o.Range(te,re,le,me):te===le&&re===me?new o.Range(te,re-1,le,me-1):Le&&Ee?new o.Range(te,re-1,le,me+1):Le?new o.Range(te,re-1,le,me):new o.Range(te,re,le,me+1)}return new o.Range(te,re,le,me)}modifyPosition(B,$){this._assertNotDisposed();const Q=this.getOffsetAt(B)+$;return this.getPositionAt(Math.min(this._buffer.getLength(),Math.max(0,Q)))}getFullModelRange(){this._assertNotDisposed();const B=this.getLineCount();return new o.Range(1,1,B,this.getLineMaxColumn(B))}findMatchesLineByLine(B,$,Q,Z){return this._buffer.findMatchesLineByLine(B,$,Q,Z)}findMatches(B,$,Q,Z,te,re,le=x){this._assertNotDisposed();let me=null;$!==null&&(Array.isArray($)||($=[$]),$.every(Le=>o.Range.isIRange(Le))&&(me=$.map(Le=>this.validateRange(Le)))),me===null&&(me=[this.getFullModelRange()]),me=me.sort((Le,Ee)=>Le.startLineNumber-Ee.startLineNumber||Le.startColumn-Ee.startColumn);const Ce=[];Ce.push(me.reduce((Le,Ee)=>o.Range.areIntersecting(Le,Ee)?Le.plusRange(Ee):(Ce.push(Le),Ee)));let ye;if(!Q&&B.indexOf(` `)<0){const Ee=new w.SearchParams(B,Q,Z,te).parseSearchRequest();if(!Ee)return[];ye=Me=>this.findMatchesLineByLine(Me,Ee,re,le)}else ye=Le=>w.TextModelSearch.findMatches(this,new w.SearchParams(B,Q,Z,te),Le,re,le);return Ce.map(ye).reduce((Le,Ee)=>Le.concat(Ee),[])}findNextMatch(B,$,Q,Z,te,re){this._assertNotDisposed();const le=this.validatePosition($);if(!Q&&B.indexOf(` `)<0){const Ce=new w.SearchParams(B,Q,Z,te).parseSearchRequest();if(!Ce)return null;const ye=this.getLineCount();let Le=new o.Range(le.lineNumber,le.column,ye,this.getLineMaxColumn(ye)),Ee=this.findMatchesLineByLine(Le,Ce,re,1);return w.TextModelSearch.findNextMatch(this,new w.SearchParams(B,Q,Z,te),le,re),Ee.length>0||(Le=new o.Range(1,1,le.lineNumber,this.getLineMaxColumn(le.lineNumber)),Ee=this.findMatchesLineByLine(Le,Ce,re,1),Ee.length>0)?Ee[0]:null}return w.TextModelSearch.findNextMatch(this,new w.SearchParams(B,Q,Z,te),le,re)}findPreviousMatch(B,$,Q,Z,te,re){this._assertNotDisposed();const le=this.validatePosition($);return w.TextModelSearch.findPreviousMatch(this,new w.SearchParams(B,Q,Z,te),le,re)}pushStackElement(){this._commandManager.pushStackElement()}popStackElement(){this._commandManager.popStackElement()}pushEOL(B){if((this.getEOL()===` `?0:1)!==B)try{this._onDidChangeDecorations.beginDeferredEmit(),this._eventEmitter.beginDeferredEmit(),this._initialUndoRedoSnapshot===null&&(this._initialUndoRedoSnapshot=this._undoRedoService.createSnapshot(this.uri)),this._commandManager.pushEOL(B)}finally{this._eventEmitter.endDeferredEmit(),this._onDidChangeDecorations.endDeferredEmit()}}_validateEditOperation(B){return B instanceof c.ValidAnnotatedEditOperation?B:new c.ValidAnnotatedEditOperation(B.identifier||null,this.validateRange(B.range),B.text,B.forceMoveMarkers||!1,B.isAutoWhitespaceEdit||!1,B._isTracked||!1)}_validateEditOperations(B){const $=[];for(let Q=0,Z=B.length;Q({range:this.validateRange(le.range),text:le.text}));let re=!0;if(B)for(let le=0,me=B.length;leCe.endLineNumber,Ne=Ce.startLineNumber>Me.endLineNumber;if(!Ae&&!Ne){ye=!0;break}}if(!ye){re=!1;break}}if(re)for(let le=0,me=this._trimAutoWhitespaceLines.length;leAe.endLineNumber)&&!(Ce===Ae.startLineNumber&&Ae.startColumn===ye&&Ae.isEmpty()&&Ne&&Ne.length>0&&Ne.charAt(0)===` `)&&!(Ce===Ae.startLineNumber&&Ae.startColumn===1&&Ae.isEmpty()&&Ne&&Ne.length>0&&Ne.charAt(Ne.length-1)===` `)){Le=!1;break}}if(Le){const Ee=new o.Range(Ce,1,Ce,ye);$.push(new c.ValidAnnotatedEditOperation(null,Ee,null,!1,!1,!1))}}this._trimAutoWhitespaceLines=null}return this._initialUndoRedoSnapshot===null&&(this._initialUndoRedoSnapshot=this._undoRedoService.createSnapshot(this.uri)),this._commandManager.pushEditOperation(B,$,Q,Z)}_applyUndo(B,$,Q,Z){const te=B.map(re=>{const le=this.getPositionAt(re.newPosition),me=this.getPositionAt(re.newEnd);return{range:new o.Range(le.lineNumber,le.column,me.lineNumber,me.column),text:re.oldText}});this._applyUndoRedoEdits(te,$,!0,!1,Q,Z)}_applyRedo(B,$,Q,Z){const te=B.map(re=>{const le=this.getPositionAt(re.oldPosition),me=this.getPositionAt(re.oldEnd);return{range:new o.Range(le.lineNumber,le.column,me.lineNumber,me.column),text:re.newText}});this._applyUndoRedoEdits(te,$,!1,!0,Q,Z)}_applyUndoRedoEdits(B,$,Q,Z,te,re){try{this._onDidChangeDecorations.beginDeferredEmit(),this._eventEmitter.beginDeferredEmit(),this._isUndoing=Q,this._isRedoing=Z,this.applyEdits(B,!1),this.setEOL($),this._overwriteAlternativeVersionId(te)}finally{this._isUndoing=!1,this._isRedoing=!1,this._eventEmitter.endDeferredEmit(re),this._onDidChangeDecorations.endDeferredEmit()}}applyEdits(B,$=!1){try{this._onDidChangeDecorations.beginDeferredEmit(),this._eventEmitter.beginDeferredEmit();const Q=this._validateEditOperations(B);return this._doApplyEdits(Q,$)}finally{this._eventEmitter.endDeferredEmit(),this._onDidChangeDecorations.endDeferredEmit()}}_doApplyEdits(B,$){const Q=this._buffer.getLineCount(),Z=this._buffer.applyEdits(B,this._options.trimAutoWhitespace,$),te=this._buffer.getLineCount(),re=Z.changes;if(this._trimAutoWhitespaceLines=Z.trimAutoWhitespaceLineNumbers,re.length!==0){for(let Ce=0,ye=re.length;Ce=0;be--){const ve=Me+be,we=it+be;xe.takeFromEndWhile(Pe=>Pe.lineNumber>we);const Te=xe.takeFromEndWhile(Pe=>Pe.lineNumber===we);le.push(new D.ModelRawLineChanged(ve,this.getLineContent(we),Te))}if(zeje.lineNumber<$e),Pe[He]=be.takeWhile(je=>je.lineNumber===$e)}le.push(new D.ModelRawLinesInserted(ve+1,Me+Ke,Be,Pe))}me+=Ge}this._emitContentChangedEvent(new D.ModelRawContentChangedEvent(le,this.getVersionId(),this._isUndoing,this._isRedoing),{changes:re,eol:this._buffer.getEOL(),isEolChange:!1,versionId:this.getVersionId(),isUndoing:this._isUndoing,isRedoing:this._isRedoing,isFlush:!1})}return Z.reverseEdits===null?void 0:Z.reverseEdits}undo(){return this._undoRedoService.undo(this.uri)}canUndo(){return this._undoRedoService.canUndo(this.uri)}redo(){return this._undoRedoService.redo(this.uri)}canRedo(){return this._undoRedoService.canRedo(this.uri)}handleBeforeFireDecorationsChangedEvent(B){if(B===null||B.size===0)return;const Q=Array.from(B).map(Z=>new D.ModelRawLineChanged(Z,this.getLineContent(Z),this._getInjectedTextInLine(Z)));this._onDidChangeInjectedText.fire(new D.ModelInjectedTextChangedEvent(Q))}changeDecorations(B,$=0){this._assertNotDisposed();try{return this._onDidChangeDecorations.beginDeferredEmit(),this._changeDecorations($,B)}finally{this._onDidChangeDecorations.endDeferredEmit()}}_changeDecorations(B,$){const Q={addDecoration:(te,re)=>this._deltaDecorationsImpl(B,[],[{range:te,options:re}])[0],changeDecoration:(te,re)=>{this._changeDecorationImpl(te,re)},changeDecorationOptions:(te,re)=>{this._changeDecorationOptionsImpl(te,ee(re))},removeDecoration:te=>{this._deltaDecorationsImpl(B,[te],[])},deltaDecorations:(te,re)=>te.length===0&&re.length===0?[]:this._deltaDecorationsImpl(B,te,re)};let Z=null;try{Z=$(Q)}catch(te){(0,I.onUnexpectedError)(te)}return Q.addDecoration=q,Q.changeDecoration=q,Q.changeDecorationOptions=q,Q.removeDecoration=q,Q.deltaDecorations=q,Z}deltaDecorations(B,$,Q=0){if(this._assertNotDisposed(),B||(B=[]),B.length===0&&$.length===0)return[];try{return this._deltaDecorationCallCnt++,this._deltaDecorationCallCnt>1&&(console.warn("Invoking deltaDecorations recursively could lead to leaking decorations."),(0,I.onUnexpectedError)(new Error("Invoking deltaDecorations recursively could lead to leaking decorations."))),this._onDidChangeDecorations.beginDeferredEmit(),this._deltaDecorationsImpl(Q,B,$)}finally{this._onDidChangeDecorations.endDeferredEmit(),this._deltaDecorationCallCnt--}}_getTrackedRange(B){return this.getDecorationRange(B)}_setTrackedRange(B,$,Q){const Z=B?this._decorations[B]:null;if(!Z)return $?this._deltaDecorationsImpl(0,[],[{range:$,options:ae[Q]}],!0)[0]:null;if(!$)return this._decorationsTree.delete(Z),delete this._decorations[Z.id],null;const te=this._validateRangeRelaxedNoAllocations($),re=this._buffer.getOffsetAt(te.startLineNumber,te.startColumn),le=this._buffer.getOffsetAt(te.endLineNumber,te.endColumn);return this._decorationsTree.delete(Z),Z.reset(this.getVersionId(),re,le,te),Z.setOptions(ae[Q]),this._decorationsTree.insert(Z),Z.id}removeAllDecorationsWithOwnerId(B){if(this._isDisposed)return;const $=this._decorationsTree.collectNodesFromOwner(B);for(let Q=0,Z=$.length;Qthis.getLineCount()?[]:this.getLinesDecorations(B,B,$,Q)}getLinesDecorations(B,$,Q=0,Z=!1,te=!1){const re=this.getLineCount(),le=Math.min(re,Math.max(1,B)),me=Math.min(re,Math.max(1,$)),Ce=this.getLineMaxColumn(me),ye=new o.Range(le,1,me,Ce),Le=this._getDecorationsInRange(ye,Q,Z,te);return(0,d.pushMany)(Le,this._decorationProvider.getDecorationsInRange(ye,Q,Z)),Le}getDecorationsInRange(B,$=0,Q=!1,Z=!1,te=!1){const re=this.validateRange(B),le=this._getDecorationsInRange(re,$,Q,te);return(0,d.pushMany)(le,this._decorationProvider.getDecorationsInRange(re,$,Q,Z)),le}getOverviewRulerDecorations(B=0,$=!1){return this._decorationsTree.getAll(this,B,$,!0,!1)}getInjectedTextDecorations(B=0){return this._decorationsTree.getAllInjectedText(this,B)}_getInjectedTextInLine(B){const $=this._buffer.getOffsetAt(B,1),Q=$+this._buffer.getLineLength(B),Z=this._decorationsTree.getInjectedTextInInterval(this,$,Q,0);return D.LineInjectedText.fromDecorations(Z).filter(te=>te.lineNumber===B)}getAllDecorations(B=0,$=!1){let Q=this._decorationsTree.getAll(this,B,$,!1,!1);return Q=Q.concat(this._decorationProvider.getAllDecorations(B,$)),Q}getAllMarginDecorations(B=0){return this._decorationsTree.getAll(this,B,!1,!1,!0)}_getDecorationsInRange(B,$,Q,Z){const te=this._buffer.getOffsetAt(B.startLineNumber,B.startColumn),re=this._buffer.getOffsetAt(B.endLineNumber,B.endColumn);return this._decorationsTree.getAllInInterval(this,te,re,$,Q,Z)}getRangeAt(B,$){return this._buffer.getRangeAt(B,$-B)}_changeDecorationImpl(B,$){const Q=this._decorations[B];if(!Q)return;if(Q.options.after){const le=this.getDecorationRange(B);this._onDidChangeDecorations.recordLineAffectedByInjectedText(le.endLineNumber)}if(Q.options.before){const le=this.getDecorationRange(B);this._onDidChangeDecorations.recordLineAffectedByInjectedText(le.startLineNumber)}const Z=this._validateRangeRelaxedNoAllocations($),te=this._buffer.getOffsetAt(Z.startLineNumber,Z.startColumn),re=this._buffer.getOffsetAt(Z.endLineNumber,Z.endColumn);this._decorationsTree.delete(Q),Q.reset(this.getVersionId(),te,re,Z),this._decorationsTree.insert(Q),this._onDidChangeDecorations.checkAffectedAndFire(Q.options),Q.options.after&&this._onDidChangeDecorations.recordLineAffectedByInjectedText(Z.endLineNumber),Q.options.before&&this._onDidChangeDecorations.recordLineAffectedByInjectedText(Z.startLineNumber)}_changeDecorationOptionsImpl(B,$){const Q=this._decorations[B];if(!Q)return;const Z=!!(Q.options.overviewRuler&&Q.options.overviewRuler.color),te=!!($.overviewRuler&&$.overviewRuler.color);if(this._onDidChangeDecorations.checkAffectedAndFire(Q.options),this._onDidChangeDecorations.checkAffectedAndFire($),Q.options.after||$.after){const me=this._decorationsTree.getNodeRange(this,Q);this._onDidChangeDecorations.recordLineAffectedByInjectedText(me.endLineNumber)}if(Q.options.before||$.before){const me=this._decorationsTree.getNodeRange(this,Q);this._onDidChangeDecorations.recordLineAffectedByInjectedText(me.startLineNumber)}const re=Z!==te,le=j($)!==Y(Q);re||le?(this._decorationsTree.delete(Q),Q.setOptions($),this._decorationsTree.insert(Q)):Q.setOptions($)}_deltaDecorationsImpl(B,$,Q,Z=!1){const te=this.getVersionId(),re=$.length;let le=0;const me=Q.length;let Ce=0;this._onDidChangeDecorations.beginDeferredEmit();try{const ye=new Array(me);for(;lethis._setLanguage(B.languageId,$)),this._setLanguage(B.languageId,$))}_setLanguage(B,$){this.tokenization.setLanguageId(B,$),this._languageService.requestRichLanguageFeatures(B)}getLanguageIdAtPosition(B,$){return this.tokenization.getLanguageIdAtPosition(B,$)}getWordAtPosition(B){return this._tokenizationTextModelPart.getWordAtPosition(B)}getWordUntilPosition(B){return this._tokenizationTextModelPart.getWordUntilPosition(B)}normalizePosition(B,$){return B}getLineIndentColumn(B){return z(this.getLineContent(B))+1}};e.TextModel=H,e.TextModel=H=A=ke([ce(4,M.IUndoRedoService),ce(5,s.ILanguageService),ce(6,g.ILanguageConfigurationService),ce(7,T.IInstantiationService)],H);function z(X){let B=0;for(const $ of X)if($===" "||$===" ")B++;else break;return B}function U(X){return!!(X.options.overviewRuler&&X.options.overviewRuler.color)}function j(X){return!!X.after||!!X.before}function Y(X){return!!X.options.after||!!X.options.before}class G{constructor(){this._decorationsTree0=new f.IntervalTree,this._decorationsTree1=new f.IntervalTree,this._injectedTextDecorationsTree=new f.IntervalTree}ensureAllNodesHaveRanges(B){this.getAll(B,0,!1,!1,!1)}_ensureNodesHaveRanges(B,$){for(const Q of $)Q.range===null&&(Q.range=B.getRangeAt(Q.cachedAbsoluteStart,Q.cachedAbsoluteEnd));return $}getAllInInterval(B,$,Q,Z,te,re){const le=B.getVersionId(),me=this._intervalSearch($,Q,Z,te,le,re);return this._ensureNodesHaveRanges(B,me)}_intervalSearch(B,$,Q,Z,te,re){const le=this._decorationsTree0.intervalSearch(B,$,Q,Z,te,re),me=this._decorationsTree1.intervalSearch(B,$,Q,Z,te,re),Ce=this._injectedTextDecorationsTree.intervalSearch(B,$,Q,Z,te,re);return le.concat(me).concat(Ce)}getInjectedTextInInterval(B,$,Q,Z){const te=B.getVersionId(),re=this._injectedTextDecorationsTree.intervalSearch($,Q,Z,!1,te,!1);return this._ensureNodesHaveRanges(B,re).filter(le=>le.options.showIfCollapsed||!le.range.isEmpty())}getAllInjectedText(B,$){const Q=B.getVersionId(),Z=this._injectedTextDecorationsTree.search($,!1,Q,!1);return this._ensureNodesHaveRanges(B,Z).filter(te=>te.options.showIfCollapsed||!te.range.isEmpty())}getAll(B,$,Q,Z,te){const re=B.getVersionId(),le=this._search($,Q,Z,re,te);return this._ensureNodesHaveRanges(B,le)}_search(B,$,Q,Z,te){if(Q)return this._decorationsTree1.search(B,$,Z,te);{const re=this._decorationsTree0.search(B,$,Z,te),le=this._decorationsTree1.search(B,$,Z,te),me=this._injectedTextDecorationsTree.search(B,$,Z,te);return re.concat(le).concat(me)}}collectNodesFromOwner(B){const $=this._decorationsTree0.collectNodesFromOwner(B),Q=this._decorationsTree1.collectNodesFromOwner(B),Z=this._injectedTextDecorationsTree.collectNodesFromOwner(B);return $.concat(Q).concat(Z)}collectNodesPostOrder(){const B=this._decorationsTree0.collectNodesPostOrder(),$=this._decorationsTree1.collectNodesPostOrder(),Q=this._injectedTextDecorationsTree.collectNodesPostOrder();return B.concat($).concat(Q)}insert(B){Y(B)?this._injectedTextDecorationsTree.insert(B):U(B)?this._decorationsTree1.insert(B):this._decorationsTree0.insert(B)}delete(B){Y(B)?this._injectedTextDecorationsTree.delete(B):U(B)?this._decorationsTree1.delete(B):this._decorationsTree0.delete(B)}getNodeRange(B,$){const Q=B.getVersionId();return $.cachedVersionId!==Q&&this._resolveNode($,Q),$.range===null&&($.range=B.getRangeAt($.cachedAbsoluteStart,$.cachedAbsoluteEnd)),$.range}_resolveNode(B,$){Y(B)?this._injectedTextDecorationsTree.resolveNode(B,$):U(B)?this._decorationsTree1.resolveNode(B,$):this._decorationsTree0.resolveNode(B,$)}acceptReplace(B,$,Q,Z){this._decorationsTree0.acceptReplace(B,$,Q,Z),this._decorationsTree1.acceptReplace(B,$,Q,Z),this._injectedTextDecorationsTree.acceptReplace(B,$,Q,Z)}}function K(X){return X.replace(/[^a-z0-9\-_]/gi," ")}class R{constructor(B){this.color=B.color||"",this.darkColor=B.darkColor||""}}class J extends R{constructor(B){super(B),this._resolvedColor=null,this.position=typeof B.position=="number"?B.position:c.OverviewRulerLane.Center}getColor(B){return this._resolvedColor||(B.type!=="light"&&this.darkColor?this._resolvedColor=this._resolveColor(this.darkColor,B):this._resolvedColor=this._resolveColor(this.color,B)),this._resolvedColor}invalidateCachedColor(){this._resolvedColor=null}_resolveColor(B,$){if(typeof B=="string")return B;const Q=B?$.getColor(B.id):null;return Q?Q.toString():""}}e.ModelDecorationOverviewRulerOptions=J;class ie{constructor(B){this.position=B?.position??c.GlyphMarginLane.Center,this.persistLane=B?.persistLane}}e.ModelDecorationGlyphMarginOptions=ie;class ue extends R{constructor(B){super(B),this.position=B.position,this.sectionHeaderStyle=B.sectionHeaderStyle??null,this.sectionHeaderText=B.sectionHeaderText??null}getColor(B){return this._resolvedColor||(B.type!=="light"&&this.darkColor?this._resolvedColor=this._resolveColor(this.darkColor,B):this._resolvedColor=this._resolveColor(this.color,B)),this._resolvedColor}invalidateCachedColor(){this._resolvedColor=void 0}_resolveColor(B,$){return typeof B=="string"?k.Color.fromHex(B):$.getColor(B.id)}}e.ModelDecorationMinimapOptions=ue;class he{static from(B){return B instanceof he?B:new he(B)}constructor(B){this.content=B.content||"",this.inlineClassName=B.inlineClassName||null,this.inlineClassNameAffectsLetterSpacing=B.inlineClassNameAffectsLetterSpacing||!1,this.attachedData=B.attachedData||null,this.cursorStops=B.cursorStops||null}}e.ModelDecorationInjectedTextOptions=he;class pe{static register(B){return new pe(B)}static createDynamic(B){return new pe(B)}constructor(B){this.description=B.description,this.blockClassName=B.blockClassName?K(B.blockClassName):null,this.blockDoesNotCollapse=B.blockDoesNotCollapse??null,this.blockIsAfterEnd=B.blockIsAfterEnd??null,this.blockPadding=B.blockPadding??null,this.stickiness=B.stickiness||0,this.zIndex=B.zIndex||0,this.className=B.className?K(B.className):null,this.shouldFillLineOnLineBreak=B.shouldFillLineOnLineBreak??null,this.hoverMessage=B.hoverMessage||null,this.glyphMarginHoverMessage=B.glyphMarginHoverMessage||null,this.lineNumberHoverMessage=B.lineNumberHoverMessage||null,this.isWholeLine=B.isWholeLine||!1,this.showIfCollapsed=B.showIfCollapsed||!1,this.collapseOnReplaceEdit=B.collapseOnReplaceEdit||!1,this.overviewRuler=B.overviewRuler?new J(B.overviewRuler):null,this.minimap=B.minimap?new ue(B.minimap):null,this.glyphMargin=B.glyphMarginClassName?new ie(B.glyphMargin):null,this.glyphMarginClassName=B.glyphMarginClassName?K(B.glyphMarginClassName):null,this.linesDecorationsClassName=B.linesDecorationsClassName?K(B.linesDecorationsClassName):null,this.lineNumberClassName=B.lineNumberClassName?K(B.lineNumberClassName):null,this.linesDecorationsTooltip=B.linesDecorationsTooltip?m.htmlAttributeEncodeValue(B.linesDecorationsTooltip):null,this.firstLineDecorationClassName=B.firstLineDecorationClassName?K(B.firstLineDecorationClassName):null,this.marginClassName=B.marginClassName?K(B.marginClassName):null,this.inlineClassName=B.inlineClassName?K(B.inlineClassName):null,this.inlineClassNameAffectsLetterSpacing=B.inlineClassNameAffectsLetterSpacing||!1,this.beforeContentClassName=B.beforeContentClassName?K(B.beforeContentClassName):null,this.afterContentClassName=B.afterContentClassName?K(B.afterContentClassName):null,this.after=B.after?he.from(B.after):null,this.before=B.before?he.from(B.before):null,this.hideInCommentTokens=B.hideInCommentTokens??!1,this.hideInStringTokens=B.hideInStringTokens??!1}}e.ModelDecorationOptions=pe,pe.EMPTY=pe.register({description:"empty"});const ae=[pe.register({description:"tracked-range-always-grows-when-typing-at-edges",stickiness:0}),pe.register({description:"tracked-range-never-grows-when-typing-at-edges",stickiness:1}),pe.register({description:"tracked-range-grows-only-when-typing-before",stickiness:2}),pe.register({description:"tracked-range-grows-only-when-typing-after",stickiness:3})];function ee(X){return X instanceof pe?X:pe.createDynamic(X)}class de extends y.Disposable{constructor(B){super(),this.handleBeforeFire=B,this._actual=this._register(new E.Emitter),this.event=this._actual.event,this._affectedInjectedTextLines=null,this._deferredCnt=0,this._shouldFireDeferred=!1,this._affectsMinimap=!1,this._affectsOverviewRuler=!1,this._affectsGlyphMargin=!1,this._affectsLineNumber=!1}beginDeferredEmit(){this._deferredCnt++}endDeferredEmit(){this._deferredCnt--,this._deferredCnt===0&&(this._shouldFireDeferred&&this.doFire(),this._affectedInjectedTextLines?.clear(),this._affectedInjectedTextLines=null)}recordLineAffectedByInjectedText(B){this._affectedInjectedTextLines||(this._affectedInjectedTextLines=new Set),this._affectedInjectedTextLines.add(B)}checkAffectedAndFire(B){this._affectsMinimap||=!!B.minimap?.position,this._affectsOverviewRuler||=!!B.overviewRuler?.color,this._affectsGlyphMargin||=!!B.glyphMarginClassName,this._affectsLineNumber||=!!B.lineNumberClassName,this.tryFire()}fire(){this._affectsMinimap=!0,this._affectsOverviewRuler=!0,this._affectsGlyphMargin=!0,this.tryFire()}tryFire(){this._deferredCnt===0?this.doFire():this._shouldFireDeferred=!0}doFire(){this.handleBeforeFire(this._affectedInjectedTextLines);const B={affectsMinimap:this._affectsMinimap,affectsOverviewRuler:this._affectsOverviewRuler,affectsGlyphMargin:this._affectsGlyphMargin,affectsLineNumber:this._affectsLineNumber};this._shouldFireDeferred=!1,this._affectsMinimap=!1,this._affectsOverviewRuler=!1,this._affectsGlyphMargin=!1,this._actual.fire(B)}}class ge extends y.Disposable{constructor(){super(),this._fastEmitter=this._register(new E.Emitter),this.fastEvent=this._fastEmitter.event,this._slowEmitter=this._register(new E.Emitter),this.slowEvent=this._slowEmitter.event,this._deferredCnt=0,this._deferredEvent=null}beginDeferredEmit(){this._deferredCnt++}endDeferredEmit(B=null){if(this._deferredCnt--,this._deferredCnt===0&&this._deferredEvent!==null){this._deferredEvent.rawContentChangedEvent.resultingSelection=B;const $=this._deferredEvent;this._deferredEvent=null,this._fastEmitter.fire($),this._slowEmitter.fire($)}}fire(B){if(this._deferredCnt>0){this._deferredEvent?this._deferredEvent=this._deferredEvent.merge(B):this._deferredEvent=B;return}this._fastEmitter.fire(B),this._slowEmitter.fire(B)}}}),define(ne[139],se([1,0,26,30,35,3,32,71]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.diffDeleteDecorationEmpty=e.diffWholeLineDeleteDecoration=e.diffDeleteDecoration=e.diffAddDecorationEmpty=e.diffWholeLineAddDecoration=e.diffAddDecoration=e.diffLineDeleteDecorationBackground=e.diffLineAddDecorationBackground=e.diffLineDeleteDecorationBackgroundWithIndicator=e.diffLineAddDecorationBackgroundWithIndicator=e.diffRemoveIcon=e.diffInsertIcon=e.diffEditorUnchangedRegionShadow=e.diffMoveBorderActive=e.diffMoveBorder=void 0,e.diffMoveBorder=(0,y.registerColor)("diffEditor.move.border","#8b8b8b9c",(0,E.localize)(124,"The border color for text that got moved in the diff editor.")),e.diffMoveBorderActive=(0,y.registerColor)("diffEditor.moveActive.border","#FFA500",(0,E.localize)(125,"The active border color for text that got moved in the diff editor.")),e.diffEditorUnchangedRegionShadow=(0,y.registerColor)("diffEditor.unchangedRegionShadow",{dark:"#000000",light:"#737373BF",hcDark:"#000000",hcLight:"#737373BF"},(0,E.localize)(126,"The color of the shadow around unchanged region widgets.")),e.diffInsertIcon=(0,m.registerIcon)("diff-insert",d.Codicon.add,(0,E.localize)(127,"Line decoration for inserts in the diff editor.")),e.diffRemoveIcon=(0,m.registerIcon)("diff-remove",d.Codicon.remove,(0,E.localize)(128,"Line decoration for removals in the diff editor.")),e.diffLineAddDecorationBackgroundWithIndicator=I.ModelDecorationOptions.register({className:"line-insert",description:"line-insert",isWholeLine:!0,linesDecorationsClassName:"insert-sign "+k.ThemeIcon.asClassName(e.diffInsertIcon),marginClassName:"gutter-insert"}),e.diffLineDeleteDecorationBackgroundWithIndicator=I.ModelDecorationOptions.register({className:"line-delete",description:"line-delete",isWholeLine:!0,linesDecorationsClassName:"delete-sign "+k.ThemeIcon.asClassName(e.diffRemoveIcon),marginClassName:"gutter-delete"}),e.diffLineAddDecorationBackground=I.ModelDecorationOptions.register({className:"line-insert",description:"line-insert",isWholeLine:!0,marginClassName:"gutter-insert"}),e.diffLineDeleteDecorationBackground=I.ModelDecorationOptions.register({className:"line-delete",description:"line-delete",isWholeLine:!0,marginClassName:"gutter-delete"}),e.diffAddDecoration=I.ModelDecorationOptions.register({className:"char-insert",description:"char-insert",shouldFillLineOnLineBreak:!0}),e.diffWholeLineAddDecoration=I.ModelDecorationOptions.register({className:"char-insert",description:"char-insert",isWholeLine:!0}),e.diffAddDecorationEmpty=I.ModelDecorationOptions.register({className:"char-insert diff-range-empty",description:"char-insert diff-range-empty"}),e.diffDeleteDecoration=I.ModelDecorationOptions.register({className:"char-delete",description:"char-delete",shouldFillLineOnLineBreak:!0}),e.diffWholeLineDeleteDecoration=I.ModelDecorationOptions.register({className:"char-delete",description:"char-delete",isWholeLine:!0}),e.diffDeleteDecorationEmpty=I.ModelDecorationOptions.register({className:"char-delete diff-range-empty",description:"char-delete diff-range-empty"})}),define(ne[285],se([1,0,5,13,14,26,2,21,30,19,74,139,407,652,667,88,55,9,95,117,58,4]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorViewZones=void 0,e.allowsTrueInlineDiffRendering=v;let C=class extends y.Disposable{constructor(L,D,T,M,A,P,N,O,F,x){super(),this._targetWindow=L,this._editors=D,this._diffModel=T,this._options=M,this._diffEditorWidget=A,this._canIgnoreViewZoneUpdateEvent=P,this._origViewZonesToIgnore=N,this._modViewZonesToIgnore=O,this._clipboardService=F,this._contextMenuService=x,this._originalTopPadding=(0,m.observableValue)(this,0),this._originalScrollOffset=(0,m.observableValue)(this,0),this._originalScrollOffsetAnimated=(0,s.animatedObservable)(this._targetWindow,this._originalScrollOffset,this._store),this._modifiedTopPadding=(0,m.observableValue)(this,0),this._modifiedScrollOffset=(0,m.observableValue)(this,0),this._modifiedScrollOffsetAnimated=(0,s.animatedObservable)(this._targetWindow,this._modifiedScrollOffset,this._store);const W=(0,m.observableValue)("invalidateAlignmentsState",0),V=this._register(new I.RunOnceScheduler(()=>{W.set(W.get()+1,void 0)},0));this._register(this._editors.original.onDidChangeViewZones(G=>{this._canIgnoreViewZoneUpdateEvent()||V.schedule()})),this._register(this._editors.modified.onDidChangeViewZones(G=>{this._canIgnoreViewZoneUpdateEvent()||V.schedule()})),this._register(this._editors.original.onDidChangeConfiguration(G=>{(G.hasChanged(147)||G.hasChanged(67))&&V.schedule()})),this._register(this._editors.modified.onDidChangeConfiguration(G=>{(G.hasChanged(147)||G.hasChanged(67))&&V.schedule()}));const q=this._diffModel.map(G=>G?(0,m.observableFromEvent)(this,G.model.original.onDidChangeTokens,()=>G.model.original.tokenization.backgroundTokenizationState===2):void 0).map((G,K)=>G?.read(K)),H=(0,m.derived)(G=>{const K=this._diffModel.read(G),R=K?.diff.read(G);if(!K||!R)return null;W.read(G);const ie=this._options.renderSideBySide.read(G);return f(this._editors.original,this._editors.modified,R.mappings,this._origViewZonesToIgnore,this._modViewZonesToIgnore,ie)}),z=(0,m.derived)(G=>{const K=this._diffModel.read(G)?.movedTextToCompare.read(G);if(!K)return null;W.read(G);const R=K.changes.map(J=>new o.DiffMapping(J));return f(this._editors.original,this._editors.modified,R,this._origViewZonesToIgnore,this._modViewZonesToIgnore,!0)});function U(){const G=document.createElement("div");return G.className="diagonal-fill",G}const j=this._register(new y.DisposableStore);this.viewZones=(0,m.derivedWithStore)(this,(G,K)=>{j.clear();const R=H.read(G)||[],J=[],ie=[],ue=this._modifiedTopPadding.read(G);ue>0&&ie.push({afterLineNumber:0,domNode:document.createElement("div"),heightInPx:ue,showInHiddenAreas:!0,suppressMouseDown:!0});const he=this._originalTopPadding.read(G);he>0&&J.push({afterLineNumber:0,domNode:document.createElement("div"),heightInPx:he,showInHiddenAreas:!0,suppressMouseDown:!0});const pe=this._options.renderSideBySide.read(G),ae=pe?void 0:this._editors.modified._getViewModel()?.createLineBreaksComputer();if(ae){const Z=this._editors.original.getModel();for(const te of R)if(te.diff)for(let re=te.originalRange.startLineNumber;reZ.getLineCount())return{orig:J,mod:ie};ae?.addRequest(Z.getLineContent(re),null,null)}}const ee=ae?.finalize()??[];let de=0;const ge=this._editors.modified.getOption(67),X=this._diffModel.read(G)?.movedTextToCompare.read(G),B=this._editors.original.getModel()?.mightContainNonBasicASCII()??!1,$=this._editors.original.getModel()?.mightContainRTL()??!1,Q=i.RenderOptions.fromEditor(this._editors.modified);for(const Z of R)if(Z.diff&&!pe&&(!this._options.useTrueInlineDiffRendering.read(G)||!v(Z.diff))){if(!Z.originalRange.isEmpty){q.read(G);const re=document.createElement("div");re.classList.add("view-lines","line-delete","monaco-mouse-cursor-text");const le=this._editors.original.getModel();if(Z.originalRange.endLineNumberExclusive-1>le.getLineCount())return{orig:J,mod:ie};const me=new i.LineSource(Z.originalRange.mapToLineArray(Me=>le.tokenization.getLineTokens(Me)),Z.originalRange.mapToLineArray(Me=>ee[de++]),B,$),Ce=[];for(const Me of Z.diff.innerChanges||[])Ce.push(new l.InlineDecoration(Me.originalRange.delta(-(Z.diff.original.startLineNumber-1)),n.diffDeleteDecoration.className,0));const ye=(0,i.renderLines)(me,Q,Ce,re),Le=document.createElement("div");if(Le.className="inline-deleted-margin-view-zone",(0,p.applyFontInfo)(Le,Q.fontInfo),this._options.renderIndicators.read(G))for(let Me=0;Me(0,b.assertIsDefined)(Ee),Le,this._editors.modified,Z.diff,this._diffEditorWidget,ye.viewLineCounts,this._editors.original.getModel(),this._contextMenuService,this._clipboardService));for(let Me=0;Me1&&J.push({afterLineNumber:Z.originalRange.startLineNumber+Me,domNode:U(),heightInPx:(Ae-1)*ge,showInHiddenAreas:!0,suppressMouseDown:!0})}ie.push({afterLineNumber:Z.modifiedRange.startLineNumber-1,domNode:re,heightInPx:ye.heightInLines*ge,minWidthInPx:ye.minWidthInPx,marginDomNode:Le,setZoneId(Me){Ee=Me},showInHiddenAreas:!0,suppressMouseDown:!0})}const te=document.createElement("div");te.className="gutter-delete",J.push({afterLineNumber:Z.originalRange.endLineNumberExclusive-1,domNode:U(),heightInPx:Z.modifiedHeightInPx,marginDomNode:te,showInHiddenAreas:!0,suppressMouseDown:!0})}else{const te=Z.modifiedHeightInPx-Z.originalHeightInPx;if(te>0){if(X?.lineRangeMapping.original.delta(-1).deltaLength(2).contains(Z.originalRange.endLineNumberExclusive-1))continue;J.push({afterLineNumber:Z.originalRange.endLineNumberExclusive-1,domNode:U(),heightInPx:te,showInHiddenAreas:!0,suppressMouseDown:!0})}else{let re=function(){const me=document.createElement("div");return me.className="arrow-revert-change "+_.ThemeIcon.asClassName(E.Codicon.arrowRight),K.add((0,d.addDisposableListener)(me,"mousedown",Ce=>Ce.stopPropagation())),K.add((0,d.addDisposableListener)(me,"click",Ce=>{Ce.stopPropagation(),A.revert(Z.diff)})),(0,d.$)("div",{},me)};if(X?.lineRangeMapping.modified.delta(-1).deltaLength(2).contains(Z.modifiedRange.endLineNumberExclusive-1))continue;let le;Z.diff&&Z.diff.modified.isEmpty&&this._options.shouldRenderOldRevertArrows.read(G)&&(le=re()),ie.push({afterLineNumber:Z.modifiedRange.endLineNumberExclusive-1,domNode:U(),heightInPx:-te,marginDomNode:le,showInHiddenAreas:!0,suppressMouseDown:!0})}}for(const Z of z.read(G)??[]){if(!X?.lineRangeMapping.original.intersect(Z.originalRange)||!X?.lineRangeMapping.modified.intersect(Z.modifiedRange))continue;const te=Z.modifiedHeightInPx-Z.originalHeightInPx;te>0?J.push({afterLineNumber:Z.originalRange.endLineNumberExclusive-1,domNode:U(),heightInPx:te,showInHiddenAreas:!0,suppressMouseDown:!0}):ie.push({afterLineNumber:Z.modifiedRange.endLineNumberExclusive-1,domNode:U(),heightInPx:-te,showInHiddenAreas:!0,suppressMouseDown:!0})}return{orig:J,mod:ie}});let Y=!1;this._register(this._editors.original.onDidScrollChange(G=>{G.scrollLeftChanged&&!Y&&(Y=!0,this._editors.modified.setScrollLeft(G.scrollLeft),Y=!1)})),this._register(this._editors.modified.onDidScrollChange(G=>{G.scrollLeftChanged&&!Y&&(Y=!0,this._editors.original.setScrollLeft(G.scrollLeft),Y=!1)})),this._originalScrollTop=(0,m.observableFromEvent)(this._editors.original.onDidScrollChange,()=>this._editors.original.getScrollTop()),this._modifiedScrollTop=(0,m.observableFromEvent)(this._editors.modified.onDidScrollChange,()=>this._editors.modified.getScrollTop()),this._register((0,m.autorun)(G=>{const K=this._originalScrollTop.read(G)-(this._originalScrollOffsetAnimated.get()-this._modifiedScrollOffsetAnimated.read(G))-(this._originalTopPadding.get()-this._modifiedTopPadding.read(G));K!==this._editors.modified.getScrollTop()&&this._editors.modified.setScrollTop(K,1)})),this._register((0,m.autorun)(G=>{const K=this._modifiedScrollTop.read(G)-(this._modifiedScrollOffsetAnimated.get()-this._originalScrollOffsetAnimated.read(G))-(this._modifiedTopPadding.get()-this._originalTopPadding.read(G));K!==this._editors.original.getScrollTop()&&this._editors.original.setScrollTop(K,1)})),this._register((0,m.autorun)(G=>{const K=this._diffModel.read(G)?.movedTextToCompare.read(G);let R=0;if(K){const J=this._editors.original.getTopForLineNumber(K.lineRangeMapping.original.startLineNumber,!0)-this._originalTopPadding.get();R=this._editors.modified.getTopForLineNumber(K.lineRangeMapping.modified.startLineNumber,!0)-this._modifiedTopPadding.get()-J}R>0?(this._modifiedTopPadding.set(0,void 0),this._originalTopPadding.set(R,void 0)):R<0?(this._modifiedTopPadding.set(-R,void 0),this._originalTopPadding.set(0,void 0)):setTimeout(()=>{this._modifiedTopPadding.set(0,void 0),this._originalTopPadding.set(0,void 0)},400),this._editors.modified.hasTextFocus()?this._originalScrollOffset.set(this._modifiedScrollOffset.get()-R,void 0,!0):this._modifiedScrollOffset.set(this._originalScrollOffset.get()+R,void 0,!0)}))}};e.DiffEditorViewZones=C,e.DiffEditorViewZones=C=ke([ce(8,a.IClipboardService),ce(9,r.IContextMenuService)],C);function f(S,L,D,T,M,A){const P=new k.ArrayQueue(h(S,T)),N=new k.ArrayQueue(h(L,M)),O=S.getOption(67),F=L.getOption(67),x=[];let W=0,V=0;function q(H,z){for(;;){let U=P.peek(),j=N.peek();if(U&&U.lineNumber>=H&&(U=void 0),j&&j.lineNumber>=z&&(j=void 0),!U&&!j)break;const Y=U?U.lineNumber-W:Number.MAX_VALUE,G=j?j.lineNumber-V:Number.MAX_VALUE;YG?(N.dequeue(),U={lineNumber:j.lineNumber-V+W,heightInPx:0}):(P.dequeue(),N.dequeue()),x.push({originalRange:g.LineRange.ofLength(U.lineNumber,1),modifiedRange:g.LineRange.ofLength(j.lineNumber,1),originalHeightInPx:O+U.heightInPx,modifiedHeightInPx:F+j.heightInPx,diff:void 0})}}for(const H of D){let G=function(K,R,J=!1){if(Kae.lineNumberae+ee.heightInPx,0)??0,pe=N.takeWhile(ae=>ae.lineNumberae+ee.heightInPx,0)??0;x.push({originalRange:ie,modifiedRange:ue,originalHeightInPx:ie.length*O+he,modifiedHeightInPx:ue.length*F+pe,diff:H.lineRangeMapping}),Y=K,j=R};const z=H.lineRangeMapping;q(z.original.startLineNumber,z.modified.startLineNumber);let U=!0,j=z.modified.startLineNumber,Y=z.original.startLineNumber;if(A)for(const K of z.innerChanges||[]){K.originalRange.startColumn>1&&K.modifiedRange.startColumn>1&&G(K.originalRange.startLineNumber,K.modifiedRange.startLineNumber);const R=S.getModel(),J=K.originalRange.endLineNumber<=R.getLineCount()?R.getLineMaxColumn(K.originalRange.endLineNumber):Number.MAX_SAFE_INTEGER;K.originalRange.endColumn1&&T.push({lineNumber:O,heightInPx:P*(F-1)})}for(const O of S.getWhitespaces()){if(L.has(O.id))continue;const F=O.afterLineNumber===0?0:A.convertViewPositionToModelPosition(new c.Position(O.afterLineNumber,1)).lineNumber;D.push({lineNumber:F,heightInPx:O.height})}return(0,s.joinCombine)(D,T,O=>O.lineNumber,(O,F)=>({lineNumber:O.lineNumber,heightInPx:O.heightInPx+F.heightInPx}))}function v(S){return S.innerChanges?S.innerChanges.every(L=>w(L.modifiedRange)&&w(L.originalRange)||L.originalRange.equalsRange(new u.Range(1,1,1,1))):!1}function w(S){return S.startLineNumber===S.endLineNumber}}),define(ne[806],se([1,0,2,21,285,364,139,88]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorDecorations=void 0;class _ extends d.Disposable{constructor(p,n,o,t){super(),this._editors=p,this._diffModel=n,this._options=o,this._decorations=(0,k.derived)(this,i=>{const s=this._diffModel.read(i),g=s?.diff.read(i);if(!g)return null;const c=this._diffModel.read(i).movedTextToCompare.read(i),l=this._options.renderIndicators.read(i),a=this._options.showEmptyDecorations.read(i),r=[],u=[];if(!c)for(const f of g.mappings)if(f.lineRangeMapping.original.isEmpty||r.push({range:f.lineRangeMapping.original.toInclusiveRange(),options:l?y.diffLineDeleteDecorationBackgroundWithIndicator:y.diffLineDeleteDecorationBackground}),f.lineRangeMapping.modified.isEmpty||u.push({range:f.lineRangeMapping.modified.toInclusiveRange(),options:l?y.diffLineAddDecorationBackgroundWithIndicator:y.diffLineAddDecorationBackground}),f.lineRangeMapping.modified.isEmpty||f.lineRangeMapping.original.isEmpty)f.lineRangeMapping.original.isEmpty||r.push({range:f.lineRangeMapping.original.toInclusiveRange(),options:y.diffWholeLineDeleteDecoration}),f.lineRangeMapping.modified.isEmpty||u.push({range:f.lineRangeMapping.modified.toInclusiveRange(),options:y.diffWholeLineAddDecoration});else{const h=this._options.useTrueInlineDiffRendering.read(i)&&(0,I.allowsTrueInlineDiffRendering)(f.lineRangeMapping);for(const v of f.lineRangeMapping.innerChanges||[])if(f.lineRangeMapping.original.contains(v.originalRange.startLineNumber)&&r.push({range:v.originalRange,options:v.originalRange.isEmpty()&&a?y.diffDeleteDecorationEmpty:y.diffDeleteDecoration}),f.lineRangeMapping.modified.contains(v.modifiedRange.startLineNumber)&&u.push({range:v.modifiedRange,options:v.modifiedRange.isEmpty()&&a&&!h?y.diffAddDecorationEmpty:y.diffAddDecoration}),h){const w=s.model.original.getValueInRange(v.originalRange);u.push({range:v.modifiedRange,options:{description:"deleted-text",before:{content:w,inlineClassName:"inline-deleted-text"},zIndex:1e5,showIfCollapsed:!0}})}}if(c)for(const f of c.changes){const h=f.original.toInclusiveRange();h&&r.push({range:h,options:l?y.diffLineDeleteDecorationBackgroundWithIndicator:y.diffLineDeleteDecorationBackground});const v=f.modified.toInclusiveRange();v&&u.push({range:v,options:l?y.diffLineAddDecorationBackgroundWithIndicator:y.diffLineAddDecorationBackground});for(const w of f.innerChanges||[])r.push({range:w.originalRange,options:y.diffDeleteDecoration}),u.push({range:w.modifiedRange,options:y.diffAddDecoration})}const C=this._diffModel.read(i).activeMovedText.read(i);for(const f of g.movedTexts)r.push({range:f.lineRangeMapping.original.toInclusiveRange(),options:{description:"moved",blockClassName:"movedOriginal"+(f===C?" currentMove":""),blockPadding:[E.MovedBlocksLinesFeature.movedCodeBlockPadding,0,E.MovedBlocksLinesFeature.movedCodeBlockPadding,E.MovedBlocksLinesFeature.movedCodeBlockPadding]}}),u.push({range:f.lineRangeMapping.modified.toInclusiveRange(),options:{description:"moved",blockClassName:"movedModified"+(f===C?" currentMove":""),blockPadding:[4,0,4,4]}});return{originalDecorations:r,modifiedDecorations:u}}),this._register((0,m.applyObservableDecorations)(this._editors.original,this._decorations.map(i=>i?.originalDecorations||[]))),this._register((0,m.applyObservableDecorations)(this._editors.modified,this._decorations.map(i=>i?.modifiedDecorations||[])))}}e.DiffEditorDecorations=_}),define(ne[807],se([1,0,21,189,285,308,37,61]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorOptions=void 0;let _=class{get editorOptions(){return this._options}constructor(i,s){this._accessibilityService=s,this._diffEditorWidth=(0,d.observableValue)(this,0),this._screenReaderMode=(0,d.observableFromEvent)(this,this._accessibilityService.onDidChangeScreenReaderOptimized,()=>this._accessibilityService.isScreenReaderOptimized()),this.couldShowInlineViewBecauseOfSize=(0,d.derived)(this,c=>this._options.read(c).renderSideBySide&&this._diffEditorWidth.read(c)<=this._options.read(c).renderSideBySideInlineBreakpoint),this.renderOverviewRuler=(0,d.derived)(this,c=>this._options.read(c).renderOverviewRuler),this.renderSideBySide=(0,d.derived)(this,c=>this.compactMode.read(c)&&this.shouldRenderInlineViewInSmartMode.read(c)?!1:this._options.read(c).renderSideBySide&&!(this._options.read(c).useInlineViewWhenSpaceIsLimited&&this.couldShowInlineViewBecauseOfSize.read(c)&&!this._screenReaderMode.read(c))),this.readOnly=(0,d.derived)(this,c=>this._options.read(c).readOnly),this.shouldRenderOldRevertArrows=(0,d.derived)(this,c=>!(!this._options.read(c).renderMarginRevertIcon||!this.renderSideBySide.read(c)||this.readOnly.read(c)||this.shouldRenderGutterMenu.read(c))),this.shouldRenderGutterMenu=(0,d.derived)(this,c=>this._options.read(c).renderGutterMenu),this.renderIndicators=(0,d.derived)(this,c=>this._options.read(c).renderIndicators),this.enableSplitViewResizing=(0,d.derived)(this,c=>this._options.read(c).enableSplitViewResizing),this.splitViewDefaultRatio=(0,d.derived)(this,c=>this._options.read(c).splitViewDefaultRatio),this.ignoreTrimWhitespace=(0,d.derived)(this,c=>this._options.read(c).ignoreTrimWhitespace),this.maxComputationTimeMs=(0,d.derived)(this,c=>this._options.read(c).maxComputationTime),this.showMoves=(0,d.derived)(this,c=>this._options.read(c).experimental.showMoves&&this.renderSideBySide.read(c)),this.isInEmbeddedEditor=(0,d.derived)(this,c=>this._options.read(c).isInEmbeddedEditor),this.diffWordWrap=(0,d.derived)(this,c=>this._options.read(c).diffWordWrap),this.originalEditable=(0,d.derived)(this,c=>this._options.read(c).originalEditable),this.diffCodeLens=(0,d.derived)(this,c=>this._options.read(c).diffCodeLens),this.accessibilityVerbose=(0,d.derived)(this,c=>this._options.read(c).accessibilityVerbose),this.diffAlgorithm=(0,d.derived)(this,c=>this._options.read(c).diffAlgorithm),this.showEmptyDecorations=(0,d.derived)(this,c=>this._options.read(c).experimental.showEmptyDecorations),this.onlyShowAccessibleDiffViewer=(0,d.derived)(this,c=>this._options.read(c).onlyShowAccessibleDiffViewer),this.compactMode=(0,d.derived)(this,c=>this._options.read(c).compactMode),this.trueInlineDiffRenderingEnabled=(0,d.derived)(this,c=>this._options.read(c).experimental.useTrueInlineView),this.useTrueInlineDiffRendering=(0,d.derived)(this,c=>!this.renderSideBySide.read(c)&&this.trueInlineDiffRenderingEnabled.read(c)),this.hideUnchangedRegions=(0,d.derived)(this,c=>this._options.read(c).hideUnchangedRegions.enabled),this.hideUnchangedRegionsRevealLineCount=(0,d.derived)(this,c=>this._options.read(c).hideUnchangedRegions.revealLineCount),this.hideUnchangedRegionsContextLineCount=(0,d.derived)(this,c=>this._options.read(c).hideUnchangedRegions.contextLineCount),this.hideUnchangedRegionsMinimumLineCount=(0,d.derived)(this,c=>this._options.read(c).hideUnchangedRegions.minimumLineCount),this._model=(0,d.observableValue)(this,void 0),this.shouldRenderInlineViewInSmartMode=this._model.map(this,c=>(0,k.derivedConstOnceDefined)(this,l=>{const a=c?.diff.read(l);return a?b(a,this.trueInlineDiffRenderingEnabled.read(l)):void 0})).flatten().map(this,c=>!!c),this.inlineViewHideOriginalLineNumbers=this.compactMode;const g={...i,...o(i,E.diffEditorDefaultOptions)};this._options=(0,d.observableValue)(this,g)}updateOptions(i){const s=o(i,this._options.get()),g={...this._options.get(),...i,...s};this._options.set(g,void 0,{changedOptions:i})}setWidth(i){this._diffEditorWidth.set(i,void 0)}setModel(i){this._model.set(i,void 0)}};e.DiffEditorOptions=_,e.DiffEditorOptions=_=ke([ce(1,m.IAccessibilityService)],_);function b(t,i){return t.mappings.every(s=>p(s.lineRangeMapping)||n(s.lineRangeMapping)||i&&(0,I.allowsTrueInlineDiffRendering)(s.lineRangeMapping))}function p(t){return t.original.length===0}function n(t){return t.modified.length===0}function o(t,i){return{enableSplitViewResizing:(0,y.boolean)(t.enableSplitViewResizing,i.enableSplitViewResizing),splitViewDefaultRatio:(0,y.clampedFloat)(t.splitViewDefaultRatio,.5,.1,.9),renderSideBySide:(0,y.boolean)(t.renderSideBySide,i.renderSideBySide),renderMarginRevertIcon:(0,y.boolean)(t.renderMarginRevertIcon,i.renderMarginRevertIcon),maxComputationTime:(0,y.clampedInt)(t.maxComputationTime,i.maxComputationTime,0,1073741824),maxFileSize:(0,y.clampedInt)(t.maxFileSize,i.maxFileSize,0,1073741824),ignoreTrimWhitespace:(0,y.boolean)(t.ignoreTrimWhitespace,i.ignoreTrimWhitespace),renderIndicators:(0,y.boolean)(t.renderIndicators,i.renderIndicators),originalEditable:(0,y.boolean)(t.originalEditable,i.originalEditable),diffCodeLens:(0,y.boolean)(t.diffCodeLens,i.diffCodeLens),renderOverviewRuler:(0,y.boolean)(t.renderOverviewRuler,i.renderOverviewRuler),diffWordWrap:(0,y.stringSet)(t.diffWordWrap,i.diffWordWrap,["off","on","inherit"]),diffAlgorithm:(0,y.stringSet)(t.diffAlgorithm,i.diffAlgorithm,["legacy","advanced"],{smart:"legacy",experimental:"advanced"}),accessibilityVerbose:(0,y.boolean)(t.accessibilityVerbose,i.accessibilityVerbose),experimental:{showMoves:(0,y.boolean)(t.experimental?.showMoves,i.experimental.showMoves),showEmptyDecorations:(0,y.boolean)(t.experimental?.showEmptyDecorations,i.experimental.showEmptyDecorations),useTrueInlineView:(0,y.boolean)(t.experimental?.useTrueInlineView,i.experimental.useTrueInlineView)},hideUnchangedRegions:{enabled:(0,y.boolean)(t.hideUnchangedRegions?.enabled??t.experimental?.collapseUnchangedRegions,i.hideUnchangedRegions.enabled),contextLineCount:(0,y.clampedInt)(t.hideUnchangedRegions?.contextLineCount,i.hideUnchangedRegions.contextLineCount,0,1073741824),minimumLineCount:(0,y.clampedInt)(t.hideUnchangedRegions?.minimumLineCount,i.hideUnchangedRegions.minimumLineCount,0,1073741824),revealLineCount:(0,y.clampedInt)(t.hideUnchangedRegions?.revealLineCount,i.hideUnchangedRegions.revealLineCount,0,1073741824)},isInEmbeddedEditor:(0,y.boolean)(t.isInEmbeddedEditor,i.isInEmbeddedEditor),onlyShowAccessibleDiffViewer:(0,y.boolean)(t.onlyShowAccessibleDiffViewer,i.onlyShowAccessibleDiffViewer),renderSideBySideInlineBreakpoint:(0,y.clampedInt)(t.renderSideBySideInlineBreakpoint,i.renderSideBySideInlineBreakpoint,0,1073741824),useInlineViewWhenSpaceIsLimited:(0,y.boolean)(t.useInlineViewWhenSpaceIsLimited,i.useInlineViewWhenSpaceIsLimited),renderGutterMenu:(0,y.boolean)(t.renderGutterMenu,i.renderGutterMenu),compactMode:(0,y.boolean)(t.compactMode,i.compactMode)}}}),define(ne[808],se([1,0,6,2,16,35,197,70,211,28,284,129,370,42,60,7]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";var g;Object.defineProperty(e,"__esModule",{value:!0}),e.DefaultModelSHA1Computer=e.ModelService=void 0;function c(f){return f.toString()}class l{constructor(h,v,w){this.model=h,this._modelEventListeners=new k.DisposableStore,this.model=h,this._modelEventListeners.add(h.onWillDispose(()=>v(h))),this._modelEventListeners.add(h.onDidChangeLanguage(S=>w(h,S)))}dispose(){this._modelEventListeners.dispose()}}const a=I.isLinux||I.isMacintosh?1:2;class r{constructor(h,v,w,S,L,D,T,M){this.uri=h,this.initialUndoRedoSnapshot=v,this.time=w,this.sharesUndoRedoStack=S,this.heapSize=L,this.sha1=D,this.versionId=T,this.alternativeVersionId=M}}let u=class extends k.Disposable{static{g=this}static{this.MAX_MEMORY_FOR_CLOSED_FILES_UNDO_STACK=20*1024*1024}constructor(h,v,w,S){super(),this._configurationService=h,this._resourcePropertiesService=v,this._undoRedoService=w,this._instantiationService=S,this._onModelAdded=this._register(new d.Emitter),this.onModelAdded=this._onModelAdded.event,this._onModelRemoved=this._register(new d.Emitter),this.onModelRemoved=this._onModelRemoved.event,this._onModelModeChanged=this._register(new d.Emitter),this.onModelLanguageChanged=this._onModelModeChanged.event,this._modelCreationOptionsByLanguageAndResource=Object.create(null),this._models={},this._disposedModels=new Map,this._disposedModelsHeapSize=0,this._register(this._configurationService.onDidChangeConfiguration(L=>this._updateModelOptions(L))),this._updateModelOptions(void 0)}static _readModelOptions(h,v){let w=y.EDITOR_MODEL_DEFAULTS.tabSize;if(h.editor&&typeof h.editor.tabSize<"u"){const O=parseInt(h.editor.tabSize,10);isNaN(O)||(w=O),w<1&&(w=1)}let S="tabSize";if(h.editor&&typeof h.editor.indentSize<"u"&&h.editor.indentSize!=="tabSize"){const O=parseInt(h.editor.indentSize,10);isNaN(O)||(S=Math.max(O,1))}let L=y.EDITOR_MODEL_DEFAULTS.insertSpaces;h.editor&&typeof h.editor.insertSpaces<"u"&&(L=h.editor.insertSpaces==="false"?!1:!!h.editor.insertSpaces);let D=a;const T=h.eol;T===`\r `?D=2:T===` `&&(D=1);let M=y.EDITOR_MODEL_DEFAULTS.trimAutoWhitespace;h.editor&&typeof h.editor.trimAutoWhitespace<"u"&&(M=h.editor.trimAutoWhitespace==="false"?!1:!!h.editor.trimAutoWhitespace);let A=y.EDITOR_MODEL_DEFAULTS.detectIndentation;h.editor&&typeof h.editor.detectIndentation<"u"&&(A=h.editor.detectIndentation==="false"?!1:!!h.editor.detectIndentation);let P=y.EDITOR_MODEL_DEFAULTS.largeFileOptimizations;h.editor&&typeof h.editor.largeFileOptimizations<"u"&&(P=h.editor.largeFileOptimizations==="false"?!1:!!h.editor.largeFileOptimizations);let N=y.EDITOR_MODEL_DEFAULTS.bracketPairColorizationOptions;return h.editor?.bracketPairColorization&&typeof h.editor.bracketPairColorization=="object"&&(N={enabled:!!h.editor.bracketPairColorization.enabled,independentColorPoolPerBracketType:!!h.editor.bracketPairColorization.independentColorPoolPerBracketType}),{isForSimpleWidget:v,tabSize:w,indentSize:S,insertSpaces:L,detectIndentation:A,defaultEOL:D,trimAutoWhitespace:M,largeFileOptimizations:P,bracketPairColorizationOptions:N}}_getEOL(h,v){if(h)return this._resourcePropertiesService.getEOL(h,v);const w=this._configurationService.getValue("files.eol",{overrideIdentifier:v});return w&&typeof w=="string"&&w!=="auto"?w:I.OS===3||I.OS===2?` `:`\r `}_shouldRestoreUndoStack(){const h=this._configurationService.getValue("files.restoreUndoStack");return typeof h=="boolean"?h:!0}getCreationOptions(h,v,w){const S=typeof h=="string"?h:h.languageId;let L=this._modelCreationOptionsByLanguageAndResource[S+v];if(!L){const D=this._configurationService.getValue("editor",{overrideIdentifier:S,resource:v}),T=this._getEOL(v,S);L=g._readModelOptions({editor:D,eol:T},w),this._modelCreationOptionsByLanguageAndResource[S+v]=L}return L}_updateModelOptions(h){const v=this._modelCreationOptionsByLanguageAndResource;this._modelCreationOptionsByLanguageAndResource=Object.create(null);const w=Object.keys(this._models);for(let S=0,L=w.length;Sh){const v=[];for(this._disposedModels.forEach(w=>{w.sharesUndoRedoStack||v.push(w)}),v.sort((w,S)=>w.time-S.time);v.length>0&&this._disposedModelsHeapSize>h;){const w=v.shift();this._removeDisposedModel(w.uri),w.initialUndoRedoSnapshot!==null&&this._undoRedoService.restoreSnapshot(w.initialUndoRedoSnapshot)}}}_createModelData(h,v,w,S){const L=this.getCreationOptions(v,w,S),D=this._instantiationService.createInstance(E.TextModel,h,v,L,w);if(w&&this._disposedModels.has(c(w))){const A=this._removeDisposedModel(w),P=this._undoRedoService.getElements(w),N=this._getSHA1Computer(),O=N.canComputeSHA1(D)?N.computeSHA1(D)===A.sha1:!1;if(O||A.sharesUndoRedoStack){for(const F of P.past)(0,o.isEditStackElement)(F)&&F.matchesResource(w)&&F.setModel(D);for(const F of P.future)(0,o.isEditStackElement)(F)&&F.matchesResource(w)&&F.setModel(D);this._undoRedoService.setElementsValidFlag(w,!0,F=>(0,o.isEditStackElement)(F)&&F.matchesResource(w)),O&&(D._overwriteVersionId(A.versionId),D._overwriteAlternativeVersionId(A.alternativeVersionId),D._overwriteInitialUndoRedoSnapshot(A.initialUndoRedoSnapshot))}else A.initialUndoRedoSnapshot!==null&&this._undoRedoService.restoreSnapshot(A.initialUndoRedoSnapshot)}const T=c(D.uri);if(this._models[T])throw new Error("ModelService: Cannot add model because it already exists!");const M=new l(D,A=>this._onWillDispose(A),(A,P)=>this._onDidChangeLanguage(A,P));return this._models[T]=M,M}createModel(h,v,w,S=!1){let L;return v?L=this._createModelData(h,v,w,S):L=this._createModelData(h,m.PLAINTEXT_LANGUAGE_ID,w,S),this._onModelAdded.fire(L.model),L.model}getModels(){const h=[],v=Object.keys(this._models);for(let w=0,S=v.length;w0||A.future.length>0){for(const P of A.past)(0,o.isEditStackElement)(P)&&P.matchesResource(h.uri)&&(L=!0,D+=P.heapSize(h.uri),P.setModel(h.uri));for(const P of A.future)(0,o.isEditStackElement)(P)&&P.matchesResource(h.uri)&&(L=!0,D+=P.heapSize(h.uri),P.setModel(h.uri))}}const T=g.MAX_MEMORY_FOR_CLOSED_FILES_UNDO_STACK,M=this._getSHA1Computer();if(L)if(!S&&(D>T||!M.canComputeSHA1(h))){const A=w.model.getInitialUndoRedoSnapshot();A!==null&&this._undoRedoService.restoreSnapshot(A)}else this._ensureDisposedModelsHeapSize(T-D),this._undoRedoService.setElementsValidFlag(h.uri,!1,A=>(0,o.isEditStackElement)(A)&&A.matchesResource(h.uri)),this._insertDisposedModel(new r(h.uri,w.model.getInitialUndoRedoSnapshot(),Date.now(),S,D,M.computeSHA1(h),h.getVersionId(),h.getAlternativeVersionId()));else if(!S){const A=w.model.getInitialUndoRedoSnapshot();A!==null&&this._undoRedoService.restoreSnapshot(A)}delete this._models[v],w.dispose(),delete this._modelCreationOptionsByLanguageAndResource[h.getLanguageId()+h.uri],this._onModelRemoved.fire(h)}_onDidChangeLanguage(h,v){const w=v.oldLanguage,S=h.getLanguageId(),L=this.getCreationOptions(w,h.uri,h.isForSimpleWidget),D=this.getCreationOptions(S,h.uri,h.isForSimpleWidget);g._setModelOptionsForModel(h,D,L),this._onModelModeChanged.fire({model:h,oldLanguageId:w})}_getSHA1Computer(){return new C}};e.ModelService=u,e.ModelService=u=g=ke([ce(0,b.IConfigurationService),ce(1,_.ITextResourcePropertiesService),ce(2,p.IUndoRedoService),ce(3,s.IInstantiationService)],u);class C{static{this.MAX_MODEL_SIZE=10*1024*1024}canComputeSHA1(h){return h.getValueLength()<=C.MAX_MODEL_SIZE}computeSHA1(h){const v=new n.StringSHA1,w=h.createSnapshot();let S;for(;S=w.read();)v.update(S);return v.digest()}}e.DefaultModelSHA1Computer=C}),define(ne[809],se([1,0,13,9,4,239,35,132,243,602,322,95]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewModelLinesFromModelAsIs=e.ViewModelLinesFromProjectedModel=void 0;class o{constructor(r,u,C,f,h,v,w,S,L,D){this._editorId=r,this.model=u,this._validModelVersionId=-1,this._domLineBreaksComputerFactory=C,this._monospaceLineBreaksComputerFactory=f,this.fontInfo=h,this.tabSize=v,this.wrappingStrategy=w,this.wrappingColumn=S,this.wrappingIndent=L,this.wordBreak=D,this._constructLines(!0,null)}dispose(){this.hiddenAreasDecorationIds=this.model.deltaDecorations(this.hiddenAreasDecorationIds,[])}createCoordinatesConverter(){return new g(this)}_constructLines(r,u){this.modelLineProjections=[],r&&(this.hiddenAreasDecorationIds=this.model.deltaDecorations(this.hiddenAreasDecorationIds,[]));const C=this.model.getLinesContent(),f=this.model.getInjectedTextDecorations(this._editorId),h=C.length,v=this.createLineBreaksComputer(),w=new d.ArrayQueue(m.LineInjectedText.fromDecorations(f));for(let N=0;NF.lineNumber===N+1);v.addRequest(C[N],O,u?u[N]:null)}const S=v.finalize(),L=[],D=this.hiddenAreasDecorationIds.map(N=>this.model.getDecorationRange(N)).sort(I.Range.compareRangesUsingStarts);let T=1,M=0,A=-1,P=A+1=T&&O<=M,x=(0,b.createModelLineProjection)(S[N],!F);L[N]=x.getViewLineCount(),this.modelLineProjections[N]=x}this._validModelVersionId=this.model.getVersionId(),this.projectedModelLineLineCounts=new p.ConstantTimePrefixSumComputer(L)}getHiddenAreas(){return this.hiddenAreasDecorationIds.map(r=>this.model.getDecorationRange(r))}setHiddenAreas(r){const u=r.map(M=>this.model.validateRange(M)),C=t(u),f=this.hiddenAreasDecorationIds.map(M=>this.model.getDecorationRange(M)).sort(I.Range.compareRangesUsingStarts);if(C.length===f.length){let M=!1;for(let A=0;A({range:M,options:y.ModelDecorationOptions.EMPTY}));this.hiddenAreasDecorationIds=this.model.deltaDecorations(this.hiddenAreasDecorationIds,h);const v=C;let w=1,S=0,L=-1,D=L+1=w&&A<=S?this.modelLineProjections[M].isVisible()&&(this.modelLineProjections[M]=this.modelLineProjections[M].setVisible(!1),P=!0):(T=!0,this.modelLineProjections[M].isVisible()||(this.modelLineProjections[M]=this.modelLineProjections[M].setVisible(!0),P=!0)),P){const N=this.modelLineProjections[M].getViewLineCount();this.projectedModelLineLineCounts.setValue(M,N)}}return T||this.setHiddenAreas([]),!0}modelPositionIsVisible(r,u){return r<1||r>this.modelLineProjections.length?!1:this.modelLineProjections[r-1].isVisible()}getModelLineViewLineCount(r){return r<1||r>this.modelLineProjections.length?1:this.modelLineProjections[r-1].getViewLineCount()}setTabSize(r){return this.tabSize===r?!1:(this.tabSize=r,this._constructLines(!1,null),!0)}setWrappingSettings(r,u,C,f,h){const v=this.fontInfo.equals(r),w=this.wrappingStrategy===u,S=this.wrappingColumn===C,L=this.wrappingIndent===f,D=this.wordBreak===h;if(v&&w&&S&&L&&D)return!1;const T=v&&w&&!S&&L&&D;this.fontInfo=r,this.wrappingStrategy=u,this.wrappingColumn=C,this.wrappingIndent=f,this.wordBreak=h;let M=null;if(T){M=[];for(let A=0,P=this.modelLineProjections.length;A2&&!this.modelLineProjections[u-2].isVisible(),v=u===1?1:this.projectedModelLineLineCounts.getPrefixSum(u-1)+1;let w=0;const S=[],L=[];for(let D=0,T=f.length;DS?(D=this.projectedModelLineLineCounts.getPrefixSum(u-1)+1,T=D+S-1,P=T+1,N=P+(h-S)-1,L=!0):hu?u:r|0}getActiveIndentGuide(r,u,C){r=this._toValidViewLineNumber(r),u=this._toValidViewLineNumber(u),C=this._toValidViewLineNumber(C);const f=this.convertViewPositionToModelPosition(r,this.getViewLineMinColumn(r)),h=this.convertViewPositionToModelPosition(u,this.getViewLineMinColumn(u)),v=this.convertViewPositionToModelPosition(C,this.getViewLineMinColumn(C)),w=this.model.guides.getActiveIndentGuide(f.lineNumber,h.lineNumber,v.lineNumber),S=this.convertModelPositionToViewPosition(w.startLineNumber,1),L=this.convertModelPositionToViewPosition(w.endLineNumber,this.model.getLineMaxColumn(w.endLineNumber));return{startLineNumber:S.lineNumber,endLineNumber:L.lineNumber,indent:w.indent}}getViewLineInfo(r){r=this._toValidViewLineNumber(r);const u=this.projectedModelLineLineCounts.getIndexOf(r-1),C=u.index,f=u.remainder;return new i(C+1,f)}getMinColumnOfViewLine(r){return this.modelLineProjections[r.modelLineNumber-1].getViewLineMinColumn(this.model,r.modelLineNumber,r.modelLineWrappedLineIdx)}getMaxColumnOfViewLine(r){return this.modelLineProjections[r.modelLineNumber-1].getViewLineMaxColumn(this.model,r.modelLineNumber,r.modelLineWrappedLineIdx)}getModelStartPositionOfViewLine(r){const u=this.modelLineProjections[r.modelLineNumber-1],C=u.getViewLineMinColumn(this.model,r.modelLineNumber,r.modelLineWrappedLineIdx),f=u.getModelColumnOfViewPosition(r.modelLineWrappedLineIdx,C);return new k.Position(r.modelLineNumber,f)}getModelEndPositionOfViewLine(r){const u=this.modelLineProjections[r.modelLineNumber-1],C=u.getViewLineMaxColumn(this.model,r.modelLineNumber,r.modelLineWrappedLineIdx),f=u.getModelColumnOfViewPosition(r.modelLineWrappedLineIdx,C);return new k.Position(r.modelLineNumber,f)}getViewLineInfosGroupedByModelRanges(r,u){const C=this.getViewLineInfo(r),f=this.getViewLineInfo(u),h=new Array;let v=this.getModelStartPositionOfViewLine(C),w=new Array;for(let S=C.modelLineNumber;S<=f.modelLineNumber;S++){const L=this.modelLineProjections[S-1];if(L.isVisible()){const D=S===C.modelLineNumber?C.modelLineWrappedLineIdx:0,T=S===f.modelLineNumber?f.modelLineWrappedLineIdx+1:L.getViewLineCount();for(let M=D;M{if(A.forWrappedLinesAfterColumn!==-1&&this.modelLineProjections[D.modelLineNumber-1].getViewPositionOfModelPosition(0,A.forWrappedLinesAfterColumn).lineNumber>=D.modelLineWrappedLineIdx||A.forWrappedLinesBeforeOrAtColumn!==-1&&this.modelLineProjections[D.modelLineNumber-1].getViewPositionOfModelPosition(0,A.forWrappedLinesBeforeOrAtColumn).lineNumberD.modelLineWrappedLineIdx)return}const N=this.convertModelPositionToViewPosition(D.modelLineNumber,A.horizontalLine.endColumn),O=this.modelLineProjections[D.modelLineNumber-1].getViewPositionOfModelPosition(0,A.horizontalLine.endColumn);return O.lineNumber===D.modelLineWrappedLineIdx?new E.IndentGuide(A.visibleColumn,P,A.className,new E.IndentGuideHorizontalLine(A.horizontalLine.top,N.column),-1,-1):O.lineNumber!!A))}}return v}getViewLinesIndentGuides(r,u){r=this._toValidViewLineNumber(r),u=this._toValidViewLineNumber(u);const C=this.convertViewPositionToModelPosition(r,this.getViewLineMinColumn(r)),f=this.convertViewPositionToModelPosition(u,this.getViewLineMaxColumn(u));let h=[];const v=[],w=[],S=C.lineNumber-1,L=f.lineNumber-1;let D=null;for(let P=S;P<=L;P++){const N=this.modelLineProjections[P];if(N.isVisible()){const O=N.getViewLineNumberOfModelPosition(0,P===S?C.column:1),F=N.getViewLineNumberOfModelPosition(0,this.model.getLineMaxColumn(P+1)),x=F-O+1;let W=0;x>1&&N.getViewLineMinColumn(this.model,P+1,F)===1&&(W=O===0?1:2),v.push(x),w.push(W),D===null&&(D=new k.Position(P+1,0))}else D!==null&&(h=h.concat(this.model.guides.getLinesIndentGuides(D.lineNumber,P)),D=null)}D!==null&&(h=h.concat(this.model.guides.getLinesIndentGuides(D.lineNumber,f.lineNumber)),D=null);const T=u-r+1,M=new Array(T);let A=0;for(let P=0,N=h.length;Pu&&(P=!0,A=u-h+1),T.getViewLinesData(this.model,L+1,M,A,h-r,C,S),h+=A,P)break}return S}validateViewPosition(r,u,C){r=this._toValidViewLineNumber(r);const f=this.projectedModelLineLineCounts.getIndexOf(r-1),h=f.index,v=f.remainder,w=this.modelLineProjections[h],S=w.getViewLineMinColumn(this.model,h+1,v),L=w.getViewLineMaxColumn(this.model,h+1,v);uL&&(u=L);const D=w.getModelColumnOfViewPosition(v,u);return this.model.validatePosition(new k.Position(h+1,D)).equals(C)?new k.Position(r,u):this.convertModelPositionToViewPosition(C.lineNumber,C.column)}validateViewRange(r,u){const C=this.validateViewPosition(r.startLineNumber,r.startColumn,u.getStartPosition()),f=this.validateViewPosition(r.endLineNumber,r.endColumn,u.getEndPosition());return new I.Range(C.lineNumber,C.column,f.lineNumber,f.column)}convertViewPositionToModelPosition(r,u){const C=this.getViewLineInfo(r),f=this.modelLineProjections[C.modelLineNumber-1].getModelColumnOfViewPosition(C.modelLineWrappedLineIdx,u);return this.model.validatePosition(new k.Position(C.modelLineNumber,f))}convertViewRangeToModelRange(r){const u=this.convertViewPositionToModelPosition(r.startLineNumber,r.startColumn),C=this.convertViewPositionToModelPosition(r.endLineNumber,r.endColumn);return new I.Range(u.lineNumber,u.column,C.lineNumber,C.column)}convertModelPositionToViewPosition(r,u,C=2,f=!1,h=!1){const v=this.model.validatePosition(new k.Position(r,u)),w=v.lineNumber,S=v.column;let L=w-1,D=!1;if(h)for(;L0&&!this.modelLineProjections[L].isVisible();)L--,D=!0;if(L===0&&!this.modelLineProjections[L].isVisible())return new k.Position(f?0:1,1);const T=1+this.projectedModelLineLineCounts.getPrefixSum(L);let M;return D?h?M=this.modelLineProjections[L].getViewPositionOfModelPosition(T,1,C):M=this.modelLineProjections[L].getViewPositionOfModelPosition(T,this.model.getLineMaxColumn(L+1),C):M=this.modelLineProjections[w-1].getViewPositionOfModelPosition(T,S,C),M}convertModelRangeToViewRange(r,u=0){if(r.isEmpty()){const C=this.convertModelPositionToViewPosition(r.startLineNumber,r.startColumn,u);return I.Range.fromPositions(C)}else{const C=this.convertModelPositionToViewPosition(r.startLineNumber,r.startColumn,1),f=this.convertModelPositionToViewPosition(r.endLineNumber,r.endColumn,0);return new I.Range(C.lineNumber,C.column,f.lineNumber,f.column)}}getViewLineNumberOfModelPosition(r,u){let C=r-1;if(this.modelLineProjections[C].isVisible()){const h=1+this.projectedModelLineLineCounts.getPrefixSum(C);return this.modelLineProjections[C].getViewLineNumberOfModelPosition(h,u)}for(;C>0&&!this.modelLineProjections[C].isVisible();)C--;if(C===0&&!this.modelLineProjections[C].isVisible())return 1;const f=1+this.projectedModelLineLineCounts.getPrefixSum(C);return this.modelLineProjections[C].getViewLineNumberOfModelPosition(f,this.model.getLineMaxColumn(C+1))}getDecorationsInRange(r,u,C,f,h){const v=this.convertViewPositionToModelPosition(r.startLineNumber,r.startColumn),w=this.convertViewPositionToModelPosition(r.endLineNumber,r.endColumn);if(w.lineNumber-v.lineNumber<=r.endLineNumber-r.startLineNumber)return this.model.getDecorationsInRange(new I.Range(v.lineNumber,1,w.lineNumber,w.column),u,C,f,h);let S=[];const L=v.lineNumber-1,D=w.lineNumber-1;let T=null;for(let N=L;N<=D;N++)if(this.modelLineProjections[N].isVisible())T===null&&(T=new k.Position(N+1,N===L?v.column:1));else if(T!==null){const F=this.model.getLineMaxColumn(N);S=S.concat(this.model.getDecorationsInRange(new I.Range(T.lineNumber,T.column,N,F),u,C,f)),T=null}T!==null&&(S=S.concat(this.model.getDecorationsInRange(new I.Range(T.lineNumber,T.column,w.lineNumber,w.column),u,C,f)),T=null),S.sort((N,O)=>{const F=I.Range.compareRangesUsingStarts(N.range,O.range);return F===0?N.idO.id?1:0:F});const M=[];let A=0,P=null;for(const N of S){const O=N.id;P!==O&&(P=O,M[A++]=N)}return M}getInjectedTextAt(r){const u=this.getViewLineInfo(r.lineNumber);return this.modelLineProjections[u.modelLineNumber-1].getInjectedTextAt(u.modelLineWrappedLineIdx,r.column)}normalizePosition(r,u){const C=this.getViewLineInfo(r.lineNumber);return this.modelLineProjections[C.modelLineNumber-1].normalizePosition(C.modelLineWrappedLineIdx,r,u)}getLineIndentColumn(r){const u=this.getViewLineInfo(r);return u.modelLineWrappedLineIdx===0?this.model.getLineIndentColumn(u.modelLineNumber):0}}e.ViewModelLinesFromProjectedModel=o;function t(a){if(a.length===0)return[];const r=a.slice();r.sort(I.Range.compareRangesUsingStarts);const u=[];let C=r[0].startLineNumber,f=r[0].endLineNumber;for(let h=1,v=r.length;hf+1?(u.push(new I.Range(C,1,f,1)),C=w.startLineNumber,f=w.endLineNumber):w.endLineNumber>f&&(f=w.endLineNumber)}return u.push(new I.Range(C,1,f,1)),u}class i{constructor(r,u){this.modelLineNumber=r,this.modelLineWrappedLineIdx=u}}class s{constructor(r,u){this.modelRange=r,this.viewLines=u}}class g{constructor(r){this._lines=r}convertViewPositionToModelPosition(r){return this._lines.convertViewPositionToModelPosition(r.lineNumber,r.column)}convertViewRangeToModelRange(r){return this._lines.convertViewRangeToModelRange(r)}validateViewPosition(r,u){return this._lines.validateViewPosition(r.lineNumber,r.column,u)}validateViewRange(r,u){return this._lines.validateViewRange(r,u)}convertModelPositionToViewPosition(r,u,C,f){return this._lines.convertModelPositionToViewPosition(r.lineNumber,r.column,u,C,f)}convertModelRangeToViewRange(r,u){return this._lines.convertModelRangeToViewRange(r,u)}modelPositionIsVisible(r){return this._lines.modelPositionIsVisible(r.lineNumber,r.column)}getModelLineViewLineCount(r){return this._lines.getModelLineViewLineCount(r)}getViewLineNumberOfModelPosition(r,u){return this._lines.getViewLineNumberOfModelPosition(r,u)}}class c{constructor(r){this.model=r}dispose(){}createCoordinatesConverter(){return new l(this)}getHiddenAreas(){return[]}setHiddenAreas(r){return!1}setTabSize(r){return!1}setWrappingSettings(r,u,C,f){return!1}createLineBreaksComputer(){const r=[];return{addRequest:(u,C,f)=>{r.push(null)},finalize:()=>r}}onModelFlushed(){}onModelLinesDeleted(r,u,C){return new _.ViewLinesDeletedEvent(u,C)}onModelLinesInserted(r,u,C,f){return new _.ViewLinesInsertedEvent(u,C)}onModelLineChanged(r,u,C){return[!1,new _.ViewLinesChangedEvent(u,1),null,null]}acceptVersionId(r){}getViewLineCount(){return this.model.getLineCount()}getActiveIndentGuide(r,u,C){return{startLineNumber:r,endLineNumber:r,indent:0}}getViewLinesBracketGuides(r,u,C){return new Array(u-r+1).fill([])}getViewLinesIndentGuides(r,u){const C=u-r+1,f=new Array(C);for(let h=0;hu)}getModelLineViewLineCount(r){return 1}getViewLineNumberOfModelPosition(r,u){return r}}}),define(ne[810],se([1,0,13,14,33,2,16,11,37,706,76,9,4,132,27,70,369,243,606,374,95,375,244,809,601]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ViewModel=void 0;const v=!0;class w extends E.Disposable{constructor(N,O,F,x,W,V,q,H,z,U){if(super(),this.languageConfigurationService=q,this._themeService=H,this._attachedView=z,this._transactionalTarget=U,this.hiddenAreasModel=new D,this.previousHiddenAreas=[],this._editorId=N,this._configuration=O,this.model=F,this._eventDispatcher=new C.ViewModelEventDispatcher,this.onEvent=this._eventDispatcher.onEvent,this.cursorConfig=new p.CursorConfiguration(this.model.getLanguageId(),this.model.getOptions(),this._configuration,this.languageConfigurationService),this._updateConfigurationViewLineCount=this._register(new k.RunOnceScheduler(()=>this._updateConfigurationViewLineCountNow(),0)),this._hasFocus=!1,this._viewportStart=S.create(this.model),this.glyphLanes=new h.GlyphMarginLanesModel(0),v&&this.model.isTooLargeForTokenization())this._lines=new f.ViewModelLinesFromModelAsIs(this.model);else{const j=this._configuration.options,Y=j.get(50),G=j.get(140),K=j.get(147),R=j.get(139),J=j.get(130);this._lines=new f.ViewModelLinesFromProjectedModel(this._editorId,this.model,x,W,Y,this.model.getOptions().tabSize,G,K.wrappingColumn,R,J)}this.coordinatesConverter=this._lines.createCoordinatesConverter(),this._cursor=this._register(new b.CursorsController(F,this,this.coordinatesConverter,this.cursorConfig)),this.viewLayout=this._register(new l.ViewLayout(this._configuration,this.getLineCount(),V)),this._register(this.viewLayout.onDidScroll(j=>{j.scrollTopChanged&&this._handleVisibleLinesChanged(),j.scrollTopChanged&&this._viewportStart.invalidate(),this._eventDispatcher.emitSingleViewEvent(new c.ViewScrollChangedEvent(j)),this._eventDispatcher.emitOutgoingEvent(new C.ScrollChangedEvent(j.oldScrollWidth,j.oldScrollLeft,j.oldScrollHeight,j.oldScrollTop,j.scrollWidth,j.scrollLeft,j.scrollHeight,j.scrollTop))})),this._register(this.viewLayout.onDidContentSizeChange(j=>{this._eventDispatcher.emitOutgoingEvent(j)})),this._decorations=new u.ViewModelDecorations(this._editorId,this.model,this._configuration,this._lines,this.coordinatesConverter),this._registerModelEvents(),this._register(this._configuration.onDidChangeFast(j=>{try{const Y=this._eventDispatcher.beginEmitViewEvents();this._onConfigurationChanged(Y,j)}finally{this._eventDispatcher.endEmitViewEvents()}})),this._register(a.MinimapTokensColorTracker.getInstance().onDidChange(()=>{this._eventDispatcher.emitSingleViewEvent(new c.ViewTokensColorsChangedEvent)})),this._register(this._themeService.onDidColorThemeChange(j=>{this._invalidateDecorationsColorCache(),this._eventDispatcher.emitSingleViewEvent(new c.ViewThemeChangedEvent(j))})),this._updateConfigurationViewLineCountNow()}dispose(){super.dispose(),this._decorations.dispose(),this._lines.dispose(),this._viewportStart.dispose(),this._eventDispatcher.dispose()}createLineBreaksComputer(){return this._lines.createLineBreaksComputer()}addViewEventHandler(N){this._eventDispatcher.addViewEventHandler(N)}removeViewEventHandler(N){this._eventDispatcher.removeViewEventHandler(N)}_updateConfigurationViewLineCountNow(){this._configuration.setViewLineCount(this._lines.getViewLineCount())}getModelVisibleRanges(){const N=this.viewLayout.getLinesViewportData(),O=new o.Range(N.startLineNumber,this.getLineMinColumn(N.startLineNumber),N.endLineNumber,this.getLineMaxColumn(N.endLineNumber));return this._toModelVisibleRanges(O)}visibleLinesStabilized(){const N=this.getModelVisibleRanges();this._attachedView.setVisibleLines(N,!0)}_handleVisibleLinesChanged(){const N=this.getModelVisibleRanges();this._attachedView.setVisibleLines(N,!1)}setHasFocus(N){this._hasFocus=N,this._cursor.setHasFocus(N),this._eventDispatcher.emitSingleViewEvent(new c.ViewFocusChangedEvent(N)),this._eventDispatcher.emitOutgoingEvent(new C.FocusChangedEvent(!N,N))}onCompositionStart(){this._eventDispatcher.emitSingleViewEvent(new c.ViewCompositionStartEvent)}onCompositionEnd(){this._eventDispatcher.emitSingleViewEvent(new c.ViewCompositionEndEvent)}_captureStableViewport(){if(this._viewportStart.isValid&&this.viewLayout.getCurrentScrollTop()>0){const N=new n.Position(this._viewportStart.viewLineNumber,this.getLineMinColumn(this._viewportStart.viewLineNumber)),O=this.coordinatesConverter.convertViewPositionToModelPosition(N);return new A(O,this._viewportStart.startLineDelta)}return new A(null,0)}_onConfigurationChanged(N,O){const F=this._captureStableViewport(),x=this._configuration.options,W=x.get(50),V=x.get(140),q=x.get(147),H=x.get(139),z=x.get(130);this._lines.setWrappingSettings(W,V,q.wrappingColumn,H,z)&&(N.emitViewEvent(new c.ViewFlushedEvent),N.emitViewEvent(new c.ViewLineMappingChangedEvent),N.emitViewEvent(new c.ViewDecorationsChangedEvent(null)),this._cursor.onLineMappingChanged(N),this._decorations.onLineMappingChanged(),this.viewLayout.onFlushed(this.getLineCount()),this._updateConfigurationViewLineCount.schedule()),O.hasChanged(92)&&(this._decorations.reset(),N.emitViewEvent(new c.ViewDecorationsChangedEvent(null))),O.hasChanged(99)&&(this._decorations.reset(),N.emitViewEvent(new c.ViewDecorationsChangedEvent(null))),N.emitViewEvent(new c.ViewConfigurationChangedEvent(O)),this.viewLayout.onConfigurationChanged(O),F.recoverViewportStart(this.coordinatesConverter,this.viewLayout),p.CursorConfiguration.shouldRecreate(O)&&(this.cursorConfig=new p.CursorConfiguration(this.model.getLanguageId(),this.model.getOptions(),this._configuration,this.languageConfigurationService),this._cursor.updateConfiguration(this.cursorConfig))}_registerModelEvents(){this._register(this.model.onDidChangeContentOrInjectedText(N=>{try{const F=this._eventDispatcher.beginEmitViewEvents();let x=!1,W=!1;const V=N instanceof t.InternalModelContentChangeEvent?N.rawContentChangedEvent.changes:N.changes,q=N instanceof t.InternalModelContentChangeEvent?N.rawContentChangedEvent.versionId:null,H=this._lines.createLineBreaksComputer();for(const j of V)switch(j.changeType){case 4:{for(let Y=0;Y!R.ownerId||R.ownerId===this._editorId)),H.addRequest(G,K,null)}break}case 2:{let Y=null;j.injectedText&&(Y=j.injectedText.filter(G=>!G.ownerId||G.ownerId===this._editorId)),H.addRequest(j.detail,Y,null);break}}const z=H.finalize(),U=new d.ArrayQueue(z);for(const j of V)switch(j.changeType){case 1:{this._lines.onModelFlushed(),F.emitViewEvent(new c.ViewFlushedEvent),this._decorations.reset(),this.viewLayout.onFlushed(this.getLineCount()),x=!0;break}case 3:{const Y=this._lines.onModelLinesDeleted(q,j.fromLineNumber,j.toLineNumber);Y!==null&&(F.emitViewEvent(Y),this.viewLayout.onLinesDeleted(Y.fromLineNumber,Y.toLineNumber)),x=!0;break}case 4:{const Y=U.takeCount(j.detail.length),G=this._lines.onModelLinesInserted(q,j.fromLineNumber,j.toLineNumber,Y);G!==null&&(F.emitViewEvent(G),this.viewLayout.onLinesInserted(G.fromLineNumber,G.toLineNumber)),x=!0;break}case 2:{const Y=U.dequeue(),[G,K,R,J]=this._lines.onModelLineChanged(q,j.lineNumber,Y);W=G,K&&F.emitViewEvent(K),R&&(F.emitViewEvent(R),this.viewLayout.onLinesInserted(R.fromLineNumber,R.toLineNumber)),J&&(F.emitViewEvent(J),this.viewLayout.onLinesDeleted(J.fromLineNumber,J.toLineNumber));break}case 5:break}q!==null&&this._lines.acceptVersionId(q),this.viewLayout.onHeightMaybeChanged(),!x&&W&&(F.emitViewEvent(new c.ViewLineMappingChangedEvent),F.emitViewEvent(new c.ViewDecorationsChangedEvent(null)),this._cursor.onLineMappingChanged(F),this._decorations.onLineMappingChanged())}finally{this._eventDispatcher.endEmitViewEvents()}const O=this._viewportStart.isValid;if(this._viewportStart.invalidate(),this._configuration.setModelLineCount(this.model.getLineCount()),this._updateConfigurationViewLineCountNow(),!this._hasFocus&&this.model.getAttachedEditorCount()>=2&&O){const F=this.model._getTrackedRange(this._viewportStart.modelTrackedRange);if(F){const x=this.coordinatesConverter.convertModelPositionToViewPosition(F.getStartPosition()),W=this.viewLayout.getVerticalOffsetForLineNumber(x.lineNumber);this.viewLayout.setScrollPosition({scrollTop:W+this._viewportStart.startLineDelta},1)}}try{const F=this._eventDispatcher.beginEmitViewEvents();N instanceof t.InternalModelContentChangeEvent&&F.emitOutgoingEvent(new C.ModelContentChangedEvent(N.contentChangedEvent)),this._cursor.onModelContentChanged(F,N)}finally{this._eventDispatcher.endEmitViewEvents()}this._handleVisibleLinesChanged()})),this._register(this.model.onDidChangeTokens(N=>{const O=[];for(let F=0,x=N.ranges.length;F{this._eventDispatcher.emitSingleViewEvent(new c.ViewLanguageConfigurationEvent),this.cursorConfig=new p.CursorConfiguration(this.model.getLanguageId(),this.model.getOptions(),this._configuration,this.languageConfigurationService),this._cursor.updateConfiguration(this.cursorConfig),this._eventDispatcher.emitOutgoingEvent(new C.ModelLanguageConfigurationChangedEvent(N))})),this._register(this.model.onDidChangeLanguage(N=>{this.cursorConfig=new p.CursorConfiguration(this.model.getLanguageId(),this.model.getOptions(),this._configuration,this.languageConfigurationService),this._cursor.updateConfiguration(this.cursorConfig),this._eventDispatcher.emitOutgoingEvent(new C.ModelLanguageChangedEvent(N))})),this._register(this.model.onDidChangeOptions(N=>{if(this._lines.setTabSize(this.model.getOptions().tabSize)){try{const O=this._eventDispatcher.beginEmitViewEvents();O.emitViewEvent(new c.ViewFlushedEvent),O.emitViewEvent(new c.ViewLineMappingChangedEvent),O.emitViewEvent(new c.ViewDecorationsChangedEvent(null)),this._cursor.onLineMappingChanged(O),this._decorations.onLineMappingChanged(),this.viewLayout.onFlushed(this.getLineCount())}finally{this._eventDispatcher.endEmitViewEvents()}this._updateConfigurationViewLineCount.schedule()}this.cursorConfig=new p.CursorConfiguration(this.model.getLanguageId(),this.model.getOptions(),this._configuration,this.languageConfigurationService),this._cursor.updateConfiguration(this.cursorConfig),this._eventDispatcher.emitOutgoingEvent(new C.ModelOptionsChangedEvent(N))})),this._register(this.model.onDidChangeDecorations(N=>{this._decorations.onModelDecorationsChanged(),this._eventDispatcher.emitSingleViewEvent(new c.ViewDecorationsChangedEvent(N)),this._eventDispatcher.emitOutgoingEvent(new C.ModelDecorationsChangedEvent(N))}))}setHiddenAreas(N,O){this.hiddenAreasModel.setHiddenAreas(O,N);const F=this.hiddenAreasModel.getMergedRanges();if(F===this.previousHiddenAreas)return;this.previousHiddenAreas=F;const x=this._captureStableViewport();let W=!1;try{const V=this._eventDispatcher.beginEmitViewEvents();W=this._lines.setHiddenAreas(F),W&&(V.emitViewEvent(new c.ViewFlushedEvent),V.emitViewEvent(new c.ViewLineMappingChangedEvent),V.emitViewEvent(new c.ViewDecorationsChangedEvent(null)),this._cursor.onLineMappingChanged(V),this._decorations.onLineMappingChanged(),this.viewLayout.onFlushed(this.getLineCount()),this.viewLayout.onHeightMaybeChanged());const q=x.viewportStartModelPosition?.lineNumber;q&&F.some(z=>z.startLineNumber<=q&&q<=z.endLineNumber)||x.recoverViewportStart(this.coordinatesConverter,this.viewLayout)}finally{this._eventDispatcher.endEmitViewEvents()}this._updateConfigurationViewLineCount.schedule(),W&&this._eventDispatcher.emitOutgoingEvent(new C.HiddenAreasChangedEvent)}getVisibleRangesPlusViewportAboveBelow(){const N=this._configuration.options.get(146),O=this._configuration.options.get(67),F=Math.max(20,Math.round(N.height/O)),x=this.viewLayout.getLinesViewportData(),W=Math.max(1,x.completelyVisibleStartLineNumber-F),V=Math.min(this.getLineCount(),x.completelyVisibleEndLineNumber+F);return this._toModelVisibleRanges(new o.Range(W,this.getLineMinColumn(W),V,this.getLineMaxColumn(V)))}getVisibleRanges(){const N=this.getCompletelyVisibleViewRange();return this._toModelVisibleRanges(N)}getHiddenAreas(){return this._lines.getHiddenAreas()}_toModelVisibleRanges(N){const O=this.coordinatesConverter.convertViewRangeToModelRange(N),F=this._lines.getHiddenAreas();if(F.length===0)return[O];const x=[];let W=0,V=O.startLineNumber,q=O.startColumn;const H=O.endLineNumber,z=O.endColumn;for(let U=0,j=F.length;UH||(V"u")return this._reduceRestoreStateCompatibility(N);const O=this.model.validatePosition(N.firstPosition),F=this.coordinatesConverter.convertModelPositionToViewPosition(O),x=this.viewLayout.getVerticalOffsetForLineNumber(F.lineNumber)-N.firstPositionDeltaTop;return{scrollLeft:N.scrollLeft,scrollTop:x}}_reduceRestoreStateCompatibility(N){return{scrollLeft:N.scrollLeft,scrollTop:N.scrollTopWithoutViewZones}}getTabSize(){return this.model.getOptions().tabSize}getLineCount(){return this._lines.getViewLineCount()}setViewport(N,O,F){this._viewportStart.update(this,N)}getActiveIndentGuide(N,O,F){return this._lines.getActiveIndentGuide(N,O,F)}getLinesIndentGuides(N,O){return this._lines.getViewLinesIndentGuides(N,O)}getBracketGuidesInRangeByLine(N,O,F,x){return this._lines.getViewLinesBracketGuides(N,O,F,x)}getLineContent(N){return this._lines.getViewLineContent(N)}getLineLength(N){return this._lines.getViewLineLength(N)}getLineMinColumn(N){return this._lines.getViewLineMinColumn(N)}getLineMaxColumn(N){return this._lines.getViewLineMaxColumn(N)}getLineFirstNonWhitespaceColumn(N){const O=m.firstNonWhitespaceIndex(this.getLineContent(N));return O===-1?0:O+1}getLineLastNonWhitespaceColumn(N){const O=m.lastNonWhitespaceIndex(this.getLineContent(N));return O===-1?0:O+2}getMinimapDecorationsInRange(N){return this._decorations.getMinimapDecorationsInRange(N)}getDecorationsInViewport(N){return this._decorations.getDecorationsViewportData(N).decorations}getInjectedTextAt(N){return this._lines.getInjectedTextAt(N)}getViewportViewLineRenderingData(N,O){const x=this._decorations.getDecorationsViewportData(N).inlineDecorations[O-N.startLineNumber];return this._getViewLineRenderingData(O,x)}getViewLineRenderingData(N){const O=this._decorations.getInlineDecorationsOnLine(N);return this._getViewLineRenderingData(N,O)}_getViewLineRenderingData(N,O){const F=this.model.mightContainRTL(),x=this.model.mightContainNonBasicASCII(),W=this.getTabSize(),V=this._lines.getViewLineData(N);return V.inlineDecorations&&(O=[...O,...V.inlineDecorations.map(q=>q.toInlineDecoration(N))]),new r.ViewLineRenderingData(V.minColumn,V.maxColumn,V.content,V.continuesWithWrappedLine,F,x,V.tokens,O,W,V.startVisibleColumn)}getViewLineData(N){return this._lines.getViewLineData(N)}getMinimapLinesRenderingData(N,O,F){const x=this._lines.getViewLinesData(N,O,F);return new r.MinimapLinesRenderingData(this.getTabSize(),x)}getAllOverviewRulerDecorations(N){const O=this.model.getOverviewRulerDecorations(this._editorId,(0,_.filterValidationDecorations)(this._configuration.options)),F=new L;for(const x of O){const W=x.options,V=W.overviewRuler;if(!V)continue;const q=V.position;if(q===0)continue;const H=V.getColor(N.value),z=this.coordinatesConverter.getViewLineNumberOfModelPosition(x.range.startLineNumber,x.range.startColumn),U=this.coordinatesConverter.getViewLineNumberOfModelPosition(x.range.endLineNumber,x.range.endColumn);F.accept(H,W.zIndex,z,U,q)}return F.asArray}_invalidateDecorationsColorCache(){const N=this.model.getOverviewRulerDecorations();for(const O of N)O.options.overviewRuler?.invalidateCachedColor(),O.options.minimap?.invalidateCachedColor()}getValueInRange(N,O){const F=this.coordinatesConverter.convertViewRangeToModelRange(N);return this.model.getValueInRange(F,O)}getValueLengthInRange(N,O){const F=this.coordinatesConverter.convertViewRangeToModelRange(N);return this.model.getValueLengthInRange(F,O)}modifyPosition(N,O){const F=this.coordinatesConverter.convertViewPositionToModelPosition(N),x=this.model.modifyPosition(F,O);return this.coordinatesConverter.convertModelPositionToViewPosition(x)}deduceModelPositionRelativeToViewPosition(N,O,F){const x=this.coordinatesConverter.convertViewPositionToModelPosition(N);this.model.getEOL().length===2&&(O<0?O-=F:O+=F);const V=this.model.getOffsetAt(x)+O;return this.model.getPositionAt(V)}getPlainTextToCopy(N,O,F){const x=F?`\r `:this.model.getEOL();N=N.slice(0),N.sort(o.Range.compareRangesUsingStarts);let W=!1,V=!1;for(const H of N)H.isEmpty()?W=!0:V=!0;if(!V){if(!O)return"";const H=N.map(U=>U.startLineNumber);let z="";for(let U=0;U0&&H[U-1]===H[U]||(z+=this.model.getLineContent(H[U])+x);return z}if(W&&O){const H=[];let z=0;for(const U of N){const j=U.startLineNumber;U.isEmpty()?j!==z&&H.push(this.model.getLineContent(j)):H.push(this.model.getValueInRange(U,F?2:0)),z=j}return H.length===1?H[0]:H}const q=[];for(const H of N)H.isEmpty()||q.push(this.model.getValueInRange(H,F?2:0));return q.length===1?q[0]:q}getRichTextToCopy(N,O){const F=this.model.getLanguageId();if(F===s.PLAINTEXT_LANGUAGE_ID||N.length!==1)return null;let x=N[0];if(x.isEmpty()){if(!O)return null;const U=x.startLineNumber;x=new o.Range(U,this.model.getLineMinColumn(U),U,this.model.getLineMaxColumn(U))}const W=this._configuration.options.get(50),V=this._getColorMap(),H=/[:;\\\/<>]/.test(W.fontFamily)||W.fontFamily===_.EDITOR_FONT_DEFAULTS.fontFamily;let z;return H?z=_.EDITOR_FONT_DEFAULTS.fontFamily:(z=W.fontFamily,z=z.replace(/"/g,"'"),/[,']/.test(z)||/[+ ]/.test(z)&&(z=`'${z}'`),z=`${z}, ${_.EDITOR_FONT_DEFAULTS.fontFamily}`),{mode:F,html:`
      `+this._getHTMLToCopy(x,V)+"
      "}}_getHTMLToCopy(N,O){const F=N.startLineNumber,x=N.startColumn,W=N.endLineNumber,V=N.endColumn,q=this.getTabSize();let H="";for(let z=F;z<=W;z++){const U=this.model.tokenization.getLineTokens(z),j=U.getLineContent(),Y=z===F?x-1:0,G=z===W?V-1:j.length;j===""?H+="
      ":H+=(0,g.tokenizeLineToHTML)(j,U.inflate(),O,Y,G,q,y.isWindows)}return H}_getColorMap(){const N=i.TokenizationRegistry.getColorMap(),O=["#000000"];if(N)for(let F=1,x=N.length;Fthis._cursor.setStates(x,N,O,F))}getCursorColumnSelectData(){return this._cursor.getCursorColumnSelectData()}getCursorAutoClosedCharacters(){return this._cursor.getAutoClosedCharacters()}setCursorColumnSelectData(N){this._cursor.setCursorColumnSelectData(N)}getPrevEditOperationType(){return this._cursor.getPrevEditOperationType()}setPrevEditOperationType(N){this._cursor.setPrevEditOperationType(N)}getSelection(){return this._cursor.getSelection()}getSelections(){return this._cursor.getSelections()}getPosition(){return this._cursor.getPrimaryCursorState().modelState.position}setSelections(N,O,F=0){this._withViewEventsCollector(x=>this._cursor.setSelections(x,N,O,F))}saveCursorState(){return this._cursor.saveState()}restoreCursorState(N){this._withViewEventsCollector(O=>this._cursor.restoreState(O,N))}_executeCursorEdit(N){if(this._cursor.context.cursorConfig.readOnly){this._eventDispatcher.emitOutgoingEvent(new C.ReadOnlyEditAttemptEvent);return}this._withViewEventsCollector(N)}executeEdits(N,O,F){this._executeCursorEdit(x=>this._cursor.executeEdits(x,N,O,F))}startComposition(){this._executeCursorEdit(N=>this._cursor.startComposition(N))}endComposition(N){this._executeCursorEdit(O=>this._cursor.endComposition(O,N))}type(N,O){this._executeCursorEdit(F=>this._cursor.type(F,N,O))}compositionType(N,O,F,x,W){this._executeCursorEdit(V=>this._cursor.compositionType(V,N,O,F,x,W))}paste(N,O,F,x){this._executeCursorEdit(W=>this._cursor.paste(W,N,O,F,x))}cut(N){this._executeCursorEdit(O=>this._cursor.cut(O,N))}executeCommand(N,O){this._executeCursorEdit(F=>this._cursor.executeCommand(F,N,O))}executeCommands(N,O){this._executeCursorEdit(F=>this._cursor.executeCommands(F,N,O))}revealAllCursors(N,O,F=!1){this._withViewEventsCollector(x=>this._cursor.revealAll(x,N,F,0,O,0))}revealPrimaryCursor(N,O,F=!1){this._withViewEventsCollector(x=>this._cursor.revealPrimary(x,N,F,0,O,0))}revealTopMostCursor(N){const O=this._cursor.getTopMostViewPosition(),F=new o.Range(O.lineNumber,O.column,O.lineNumber,O.column);this._withViewEventsCollector(x=>x.emitViewEvent(new c.ViewRevealRangeRequestEvent(N,!1,F,null,0,!0,0)))}revealBottomMostCursor(N){const O=this._cursor.getBottomMostViewPosition(),F=new o.Range(O.lineNumber,O.column,O.lineNumber,O.column);this._withViewEventsCollector(x=>x.emitViewEvent(new c.ViewRevealRangeRequestEvent(N,!1,F,null,0,!0,0)))}revealRange(N,O,F,x,W){this._withViewEventsCollector(V=>V.emitViewEvent(new c.ViewRevealRangeRequestEvent(N,!1,F,null,x,O,W)))}changeWhitespace(N){this.viewLayout.changeWhitespace(N)&&(this._eventDispatcher.emitSingleViewEvent(new c.ViewZonesChangedEvent),this._eventDispatcher.emitOutgoingEvent(new C.ViewZonesChangedEvent))}_withViewEventsCollector(N){return this._transactionalTarget.batchChanges(()=>{try{const O=this._eventDispatcher.beginEmitViewEvents();return N(O)}finally{this._eventDispatcher.endEmitViewEvents()}})}batchEvents(N){this._withViewEventsCollector(()=>{N()})}normalizePosition(N,O){return this._lines.normalizePosition(N,O)}getLineIndentColumn(N){return this._lines.getLineIndentColumn(N)}}e.ViewModel=w;class S{static create(N){const O=N._setTrackedRange(null,new o.Range(1,1,1,1),1);return new S(N,1,!1,O,0)}get viewLineNumber(){return this._viewLineNumber}get isValid(){return this._isValid}get modelTrackedRange(){return this._modelTrackedRange}get startLineDelta(){return this._startLineDelta}constructor(N,O,F,x,W){this._model=N,this._viewLineNumber=O,this._isValid=F,this._modelTrackedRange=x,this._startLineDelta=W}dispose(){this._model._setTrackedRange(this._modelTrackedRange,null,1)}update(N,O){const F=N.coordinatesConverter.convertViewPositionToModelPosition(new n.Position(O,N.getLineMinColumn(O))),x=N.model._setTrackedRange(this._modelTrackedRange,new o.Range(F.lineNumber,F.column,F.lineNumber,F.column),1),W=N.viewLayout.getVerticalOffsetForLineNumber(O),V=N.viewLayout.getCurrentScrollTop();this._viewLineNumber=O,this._isValid=!0,this._modelTrackedRange=x,this._startLineDelta=V-W}invalidate(){this._isValid=!1}}class L{constructor(){this._asMap=Object.create(null),this.asArray=[]}accept(N,O,F,x,W){const V=this._asMap[N];if(V){const q=V.data,H=q[q.length-3],z=q[q.length-1];if(H===W&&z+1>=F){x>z&&(q[q.length-1]=x);return}q.push(W,F,x)}else{const q=new r.OverviewRulerDecorationsGroup(N,O,[W,F,x]);this._asMap[N]=q,this.asArray.push(q)}}}class D{constructor(){this.hiddenAreas=new Map,this.shouldRecompute=!1,this.ranges=[]}setHiddenAreas(N,O){const F=this.hiddenAreas.get(N);F&&M(F,O)||(this.hiddenAreas.set(N,O),this.shouldRecompute=!0)}getMergedRanges(){if(!this.shouldRecompute)return this.ranges;this.shouldRecompute=!1;const N=Array.from(this.hiddenAreas.values()).reduce((O,F)=>T(O,F),[]);return M(this.ranges,N)?this.ranges:(this.ranges=N,this.ranges)}}function T(P,N){const O=[];let F=0,x=0;for(;F{this._onDidChangeConfiguration.fire(Ne);const Ke=this._configuration.options;if(Ne.hasChanged(146)){const ze=Ke.get(146);this._onDidLayoutChange.fire(ze)}})),this._contextKeyService=this._register(re.createScoped(this._domElement)),this._notificationService=me,this._codeEditorService=Z,this._commandService=te,this._themeService=le,this._register(new K(this,this._contextKeyService)),this._register(new R(this,this._contextKeyService,Le)),this._instantiationService=this._register(Q.createChild(new F.ServiceCollection([N.IContextKeyService,this._contextKeyService]))),this._modelData=null,this._focusTracker=new J(X,this._overflowWidgetsDomNode),this._register(this._focusTracker.onChange(()=>{this._editorWidgetFocus.setValue(this._focusTracker.hasFocus())})),this._contentWidgets={},this._overlayWidgets={},this._glyphMarginWidgets={};let Me;Array.isArray($.contributions)?Me=$.contributions:Me=p.EditorExtensionsRegistry.getEditorContributions(),this._contributions.initialize(this,Me,this._instantiationService);for(const Ne of p.EditorExtensionsRegistry.getEditorActions()){if(this._actions.has(Ne.id)){(0,k.onUnexpectedError)(new Error(`Cannot have two actions with the same id ${Ne.id}`));continue}const Ke=new f.InternalEditorAction(Ne.id,Ne.label,Ne.alias,Ne.metadata,Ne.precondition??void 0,ze=>this._instantiationService.invokeFunction(Ge=>Promise.resolve(Ne.runEditorCommand(Ge,this,ze))),this._contextKeyService);this._actions.set(Ke.id,Ke)}const Ae=()=>!this._configuration.options.get(92)&&this._configuration.options.get(36).enabled;this._register(new d.DragAndDropObserver(this._domElement,{onDragOver:Ne=>{if(!Ae())return;const Ke=this.getTargetAtClientPoint(Ne.clientX,Ne.clientY);Ke?.position&&this.showDropIndicatorAt(Ke.position)},onDrop:async Ne=>{if(!Ae()||(this.removeDropIndicator(),!Ne.dataTransfer))return;const Ke=this.getTargetAtClientPoint(Ne.clientX,Ne.clientY);Ke?.position&&this._onDropIntoEditor.fire({position:Ke.position,event:Ne})},onDragLeave:()=>{this.removeDropIndicator()},onDragEnd:()=>{this.removeDropIndicator()}})),this._codeEditorService.addCodeEditor(this)}writeScreenReaderContent(X){this._modelData?.view.writeScreenReaderContent(X)}_createConfiguration(X,B,$,Q){return new _.EditorConfiguration(X,B,$,this._domElement,Q)}getId(){return this.getEditorType()+":"+this._id}getEditorType(){return h.EditorType.ICodeEditor}dispose(){this._codeEditorService.removeCodeEditor(this),this._focusTracker.dispose(),this._actions.clear(),this._contentWidgets={},this._overlayWidgets={},this._removeDecorationTypes(),this._postDetachModelCleanup(this._detachModel()),this._onDidDispose.fire(),super.dispose()}invokeWithinContext(X){return this._instantiationService.invokeFunction(X)}updateOptions(X){this._configuration.updateOptions(X||{})}getOptions(){return this._configuration.options}getOption(X){return this._configuration.options.get(X)}getRawOptions(){return this._configuration.getRawOptions()}getOverflowWidgetsDomNode(){return this._overflowWidgetsDomNode}getConfiguredWordAtPosition(X){return this._modelData?C.WordOperations.getWordAtPosition(this._modelData.model,this._configuration.options.get(132),this._configuration.options.get(131),X):null}getValue(X=null){if(!this._modelData)return"";const B=!!(X&&X.preserveBOM);let $=0;return X&&X.lineEnding&&X.lineEnding===` `?$=1:X&&X.lineEnding&&X.lineEnding===`\r `&&($=2),this._modelData.model.getValue($,B)}setValue(X){try{if(this._beginUpdate(),!this._modelData)return;this._modelData.model.setValue(X)}finally{this._endUpdate()}}getModel(){return this._modelData?this._modelData.model:null}setModel(X=null){try{this._beginUpdate();const B=X;if(this._modelData===null&&B===null||this._modelData&&this._modelData.model===B)return;const $={oldModelUrl:this._modelData?.model.uri||null,newModelUrl:B?.uri||null};this._onWillChangeModel.fire($);const Q=this.hasTextFocus(),Z=this._detachModel();this._attachModel(B),Q&&this.hasModel()&&this.focus(),this._removeDecorationTypes(),this._onDidChangeModel.fire($),this._postDetachModelCleanup(Z),this._contributionsDisposable=this._contributions.onAfterModelAttached()}finally{this._endUpdate()}}_removeDecorationTypes(){if(this._decorationTypeKeysToIds={},this._decorationTypeSubtypes){for(const X in this._decorationTypeSubtypes){const B=this._decorationTypeSubtypes[X];for(const $ in B)this._removeDecorationType(X+"-"+$)}this._decorationTypeSubtypes={}}}getVisibleRanges(){return this._modelData?this._modelData.viewModel.getVisibleRanges():[]}getVisibleRangesPlusViewportAboveBelow(){return this._modelData?this._modelData.viewModel.getVisibleRangesPlusViewportAboveBelow():[]}getWhitespaces(){return this._modelData?this._modelData.viewModel.viewLayout.getWhitespaces():[]}static _getVerticalOffsetAfterPosition(X,B,$,Q){const Z=X.model.validatePosition({lineNumber:B,column:$}),te=X.viewModel.coordinatesConverter.convertModelPositionToViewPosition(Z);return X.viewModel.viewLayout.getVerticalOffsetAfterLineNumber(te.lineNumber,Q)}getTopForLineNumber(X,B=!1){return this._modelData?H._getVerticalOffsetForPosition(this._modelData,X,1,B):-1}getTopForPosition(X,B){return this._modelData?H._getVerticalOffsetForPosition(this._modelData,X,B,!1):-1}static _getVerticalOffsetForPosition(X,B,$,Q=!1){const Z=X.model.validatePosition({lineNumber:B,column:$}),te=X.viewModel.coordinatesConverter.convertModelPositionToViewPosition(Z);return X.viewModel.viewLayout.getVerticalOffsetForLineNumber(te.lineNumber,Q)}getBottomForLineNumber(X,B=!1){if(!this._modelData)return-1;const $=this._modelData.model.getLineMaxColumn(X);return H._getVerticalOffsetAfterPosition(this._modelData,X,$,B)}setHiddenAreas(X,B){this._modelData?.viewModel.setHiddenAreas(X.map($=>r.Range.lift($)),B)}getVisibleColumnFromPosition(X){if(!this._modelData)return X.column;const B=this._modelData.model.validatePosition(X),$=this._modelData.model.getOptions().tabSize;return c.CursorColumns.visibleColumnFromColumn(this._modelData.model.getLineContent(B.lineNumber),B.column,$)+1}getPosition(){return this._modelData?this._modelData.viewModel.getPosition():null}setPosition(X,B="api"){if(this._modelData){if(!a.Position.isIPosition(X))throw new Error("Invalid arguments");this._modelData.viewModel.setSelections(B,[{selectionStartLineNumber:X.lineNumber,selectionStartColumn:X.column,positionLineNumber:X.lineNumber,positionColumn:X.column}])}}_sendRevealRange(X,B,$,Q){if(!this._modelData)return;if(!r.Range.isIRange(X))throw new Error("Invalid arguments");const Z=this._modelData.model.validateRange(X),te=this._modelData.viewModel.coordinatesConverter.convertModelRangeToViewRange(Z);this._modelData.viewModel.revealRange("api",$,te,B,Q)}revealLine(X,B=0){this._revealLine(X,0,B)}revealLineInCenter(X,B=0){this._revealLine(X,1,B)}revealLineInCenterIfOutsideViewport(X,B=0){this._revealLine(X,2,B)}revealLineNearTop(X,B=0){this._revealLine(X,5,B)}_revealLine(X,B,$){if(typeof X!="number")throw new Error("Invalid arguments");this._sendRevealRange(new r.Range(X,1,X,1),B,!1,$)}revealPosition(X,B=0){this._revealPosition(X,0,!0,B)}revealPositionInCenter(X,B=0){this._revealPosition(X,1,!0,B)}revealPositionInCenterIfOutsideViewport(X,B=0){this._revealPosition(X,2,!0,B)}revealPositionNearTop(X,B=0){this._revealPosition(X,5,!0,B)}_revealPosition(X,B,$,Q){if(!a.Position.isIPosition(X))throw new Error("Invalid arguments");this._sendRevealRange(new r.Range(X.lineNumber,X.column,X.lineNumber,X.column),B,$,Q)}getSelection(){return this._modelData?this._modelData.viewModel.getSelection():null}getSelections(){return this._modelData?this._modelData.viewModel.getSelections():null}setSelection(X,B="api"){const $=u.Selection.isISelection(X),Q=r.Range.isIRange(X);if(!$&&!Q)throw new Error("Invalid arguments");if($)this._setSelectionImpl(X,B);else if(Q){const Z={selectionStartLineNumber:X.startLineNumber,selectionStartColumn:X.startColumn,positionLineNumber:X.endLineNumber,positionColumn:X.endColumn};this._setSelectionImpl(Z,B)}}_setSelectionImpl(X,B){if(!this._modelData)return;const $=new u.Selection(X.selectionStartLineNumber,X.selectionStartColumn,X.positionLineNumber,X.positionColumn);this._modelData.viewModel.setSelections(B,[$])}revealLines(X,B,$=0){this._revealLines(X,B,0,$)}revealLinesInCenter(X,B,$=0){this._revealLines(X,B,1,$)}revealLinesInCenterIfOutsideViewport(X,B,$=0){this._revealLines(X,B,2,$)}revealLinesNearTop(X,B,$=0){this._revealLines(X,B,5,$)}_revealLines(X,B,$,Q){if(typeof X!="number"||typeof B!="number")throw new Error("Invalid arguments");this._sendRevealRange(new r.Range(X,1,B,1),$,!1,Q)}revealRange(X,B=0,$=!1,Q=!0){this._revealRange(X,$?1:0,Q,B)}revealRangeInCenter(X,B=0){this._revealRange(X,1,!0,B)}revealRangeInCenterIfOutsideViewport(X,B=0){this._revealRange(X,2,!0,B)}revealRangeNearTop(X,B=0){this._revealRange(X,5,!0,B)}revealRangeNearTopIfOutsideViewport(X,B=0){this._revealRange(X,6,!0,B)}revealRangeAtTop(X,B=0){this._revealRange(X,3,!0,B)}_revealRange(X,B,$,Q){if(!r.Range.isIRange(X))throw new Error("Invalid arguments");this._sendRevealRange(r.Range.lift(X),B,$,Q)}setSelections(X,B="api",$=0){if(this._modelData){if(!X||X.length===0)throw new Error("Invalid arguments");for(let Q=0,Z=X.length;Q0&&this._modelData.viewModel.restoreCursorState($):this._modelData.viewModel.restoreCursorState([$]),this._contributions.restoreViewState(B.contributionsState||{});const Q=this._modelData.viewModel.reduceRestoreState(B.viewState);this._modelData.view.restoreState(Q)}}handleInitialized(){this._getViewModel()?.visibleLinesStabilized()}getContribution(X){return this._contributions.get(X)}getActions(){return Array.from(this._actions.values())}getSupportedActions(){let X=this.getActions();return X=X.filter(B=>B.isSupported()),X}getAction(X){return this._actions.get(X)||null}trigger(X,B,$){$=$||{};try{switch(this._beginUpdate(),B){case"compositionStart":this._startComposition();return;case"compositionEnd":this._endComposition(X);return;case"type":{const Z=$;this._type(X,Z.text||"");return}case"replacePreviousChar":{const Z=$;this._compositionType(X,Z.text||"",Z.replaceCharCnt||0,0,0);return}case"compositionType":{const Z=$;this._compositionType(X,Z.text||"",Z.replacePrevCharCnt||0,Z.replaceNextCharCnt||0,Z.positionDelta||0);return}case"paste":{const Z=$;this._paste(X,Z.text||"",Z.pasteOnNewLine||!1,Z.multicursorText||null,Z.mode||null,Z.clipboardEvent);return}case"cut":this._cut(X);return}const Q=this.getAction(B);if(Q){Promise.resolve(Q.run($)).then(void 0,k.onUnexpectedError);return}if(!this._modelData||this._triggerEditorCommand(X,B,$))return;this._triggerCommand(B,$)}finally{this._endUpdate()}}_triggerCommand(X,B){this._commandService.executeCommand(X,B)}_startComposition(){this._modelData&&(this._modelData.viewModel.startComposition(),this._onDidCompositionStart.fire())}_endComposition(X){this._modelData&&(this._modelData.viewModel.endComposition(X),this._onDidCompositionEnd.fire())}_type(X,B){!this._modelData||B.length===0||(X==="keyboard"&&this._onWillType.fire(B),this._modelData.viewModel.type(B,X),X==="keyboard"&&this._onDidType.fire(B))}_compositionType(X,B,$,Q,Z){this._modelData&&this._modelData.viewModel.compositionType(B,$,Q,Z,X)}_paste(X,B,$,Q,Z,te){if(!this._modelData)return;const re=this._modelData.viewModel,le=re.getSelection().getStartPosition();re.paste(B,$,Q,X);const me=re.getSelection().getStartPosition();X==="keyboard"&&this._onDidPaste.fire({clipboardEvent:te,range:new r.Range(le.lineNumber,le.column,me.lineNumber,me.column),languageId:Z})}_cut(X){this._modelData&&this._modelData.viewModel.cut(X)}_triggerEditorCommand(X,B,$){const Q=p.EditorExtensionsRegistry.getEditorCommand(B);return Q?($=$||{},$.source=X,this._instantiationService.invokeFunction(Z=>{Promise.resolve(Q.runEditorCommand(Z,this,$)).then(void 0,k.onUnexpectedError)}),!0):!1}_getViewModel(){return this._modelData?this._modelData.viewModel:null}pushUndoStop(){return!this._modelData||this._configuration.options.get(92)?!1:(this._modelData.model.pushStackElement(),!0)}popUndoStop(){return!this._modelData||this._configuration.options.get(92)?!1:(this._modelData.model.popStackElement(),!0)}executeEdits(X,B,$){if(!this._modelData||this._configuration.options.get(92))return!1;let Q;return $?Array.isArray($)?Q=()=>$:Q=$:Q=()=>null,this._modelData.viewModel.executeEdits(X,B,Q),!0}executeCommand(X,B){this._modelData&&this._modelData.viewModel.executeCommand(B,X)}executeCommands(X,B){this._modelData&&this._modelData.viewModel.executeCommands(B,X)}createDecorationsCollection(X){return new ie(this,X)}changeDecorations(X){return this._modelData?this._modelData.model.changeDecorations(X,this._id):null}getLineDecorations(X){return this._modelData?this._modelData.model.getLineDecorations(X,this._id,(0,g.filterValidationDecorations)(this._configuration.options)):null}getDecorationsInRange(X){return this._modelData?this._modelData.model.getDecorationsInRange(X,this._id,(0,g.filterValidationDecorations)(this._configuration.options)):null}deltaDecorations(X,B){return this._modelData?X.length===0&&B.length===0?X:this._modelData.model.deltaDecorations(X,B,this._id):[]}removeDecorations(X){!this._modelData||X.length===0||this._modelData.model.changeDecorations(B=>{B.deltaDecorations(X,[])})}removeDecorationsByType(X){const B=this._decorationTypeKeysToIds[X];B&&this.changeDecorations($=>$.deltaDecorations(B,[])),this._decorationTypeKeysToIds.hasOwnProperty(X)&&delete this._decorationTypeKeysToIds[X],this._decorationTypeSubtypes.hasOwnProperty(X)&&delete this._decorationTypeSubtypes[X]}getLayoutInfo(){return this._configuration.options.get(146)}createOverviewRuler(X){return!this._modelData||!this._modelData.hasRealView?null:this._modelData.view.createOverviewRuler(X)}getContainerDomNode(){return this._domElement}getDomNode(){return!this._modelData||!this._modelData.hasRealView?null:this._modelData.view.domNode.domNode}delegateVerticalScrollbarPointerDown(X){!this._modelData||!this._modelData.hasRealView||this._modelData.view.delegateVerticalScrollbarPointerDown(X)}delegateScrollFromMouseWheelEvent(X){!this._modelData||!this._modelData.hasRealView||this._modelData.view.delegateScrollFromMouseWheelEvent(X)}layout(X,B=!1){this._configuration.observeContainer(X),B||this.render()}focus(){!this._modelData||!this._modelData.hasRealView||this._modelData.view.focus()}hasTextFocus(){return!this._modelData||!this._modelData.hasRealView?!1:this._modelData.view.isFocused()}hasWidgetFocus(){return this._focusTracker&&this._focusTracker.hasFocus()}addContentWidget(X){const B={widget:X,position:X.getPosition()};this._contentWidgets.hasOwnProperty(X.getId())&&console.warn("Overwriting a content widget with the same id:"+X.getId()),this._contentWidgets[X.getId()]=B,this._modelData&&this._modelData.hasRealView&&this._modelData.view.addContentWidget(B)}layoutContentWidget(X){const B=X.getId();if(this._contentWidgets.hasOwnProperty(B)){const $=this._contentWidgets[B];$.position=X.getPosition(),this._modelData&&this._modelData.hasRealView&&this._modelData.view.layoutContentWidget($)}}removeContentWidget(X){const B=X.getId();if(this._contentWidgets.hasOwnProperty(B)){const $=this._contentWidgets[B];delete this._contentWidgets[B],this._modelData&&this._modelData.hasRealView&&this._modelData.view.removeContentWidget($)}}addOverlayWidget(X){const B={widget:X,position:X.getPosition()};this._overlayWidgets.hasOwnProperty(X.getId())&&console.warn("Overwriting an overlay widget with the same id."),this._overlayWidgets[X.getId()]=B,this._modelData&&this._modelData.hasRealView&&this._modelData.view.addOverlayWidget(B)}layoutOverlayWidget(X){const B=X.getId();if(this._overlayWidgets.hasOwnProperty(B)){const $=this._overlayWidgets[B];$.position=X.getPosition(),this._modelData&&this._modelData.hasRealView&&this._modelData.view.layoutOverlayWidget($)}}removeOverlayWidget(X){const B=X.getId();if(this._overlayWidgets.hasOwnProperty(B)){const $=this._overlayWidgets[B];delete this._overlayWidgets[B],this._modelData&&this._modelData.hasRealView&&this._modelData.view.removeOverlayWidget($)}}addGlyphMarginWidget(X){const B={widget:X,position:X.getPosition()};this._glyphMarginWidgets.hasOwnProperty(X.getId())&&console.warn("Overwriting a glyph margin widget with the same id."),this._glyphMarginWidgets[X.getId()]=B,this._modelData&&this._modelData.hasRealView&&this._modelData.view.addGlyphMarginWidget(B)}layoutGlyphMarginWidget(X){const B=X.getId();if(this._glyphMarginWidgets.hasOwnProperty(B)){const $=this._glyphMarginWidgets[B];$.position=X.getPosition(),this._modelData&&this._modelData.hasRealView&&this._modelData.view.layoutGlyphMarginWidget($)}}removeGlyphMarginWidget(X){const B=X.getId();if(this._glyphMarginWidgets.hasOwnProperty(B)){const $=this._glyphMarginWidgets[B];delete this._glyphMarginWidgets[B],this._modelData&&this._modelData.hasRealView&&this._modelData.view.removeGlyphMarginWidget($)}}changeViewZones(X){!this._modelData||!this._modelData.hasRealView||this._modelData.view.change(X)}getTargetAtClientPoint(X,B){return!this._modelData||!this._modelData.hasRealView?null:this._modelData.view.getTargetAtClientPoint(X,B)}getScrolledVisiblePosition(X){if(!this._modelData||!this._modelData.hasRealView)return null;const B=this._modelData.model.validatePosition(X),$=this._configuration.options,Q=$.get(146),Z=H._getVerticalOffsetForPosition(this._modelData,B.lineNumber,B.column)-this.getScrollTop(),te=this._modelData.view.getOffsetForColumn(B.lineNumber,B.column)+Q.glyphMarginWidth+Q.lineNumbersWidth+Q.decorationsWidth-this.getScrollLeft();return{top:Z,left:te,height:$.get(67)}}getOffsetForColumn(X,B){return!this._modelData||!this._modelData.hasRealView?-1:this._modelData.view.getOffsetForColumn(X,B)}render(X=!1){!this._modelData||!this._modelData.hasRealView||this._modelData.viewModel.batchEvents(()=>{this._modelData.view.render(!0,X)})}setAriaOptions(X){!this._modelData||!this._modelData.hasRealView||this._modelData.view.setAriaOptions(X)}applyFontInfo(X){(0,m.applyFontInfo)(X,this._configuration.options.get(50))}setBanner(X,B){this._bannerDomNode&&this._domElement.contains(this._bannerDomNode)&&this._bannerDomNode.remove(),this._bannerDomNode=X,this._configuration.setReservedHeight(X?B:0),this._bannerDomNode&&this._domElement.prepend(this._bannerDomNode)}_attachModel(X){if(!X){this._modelData=null;return}const B=[];this._domElement.setAttribute("data-mode-id",X.getLanguageId()),this._configuration.setIsDominatedByLongLines(X.isDominatedByLongLines()),this._configuration.setModelLineCount(X.getLineCount());const $=X.onBeforeAttached(),Q=new T.ViewModel(this._id,this._configuration,X,t.DOMLineBreaksComputerFactory.create(d.getWindow(this._domElement)),D.MonospaceLineBreaksComputerFactory.create(this._configuration.options),re=>d.scheduleAtNextAnimationFrame(d.getWindow(this._domElement),re),this.languageConfigurationService,this._themeService,$,{batchChanges:re=>{try{return this._beginUpdate(),re()}finally{this._endUpdate()}}});B.push(X.onWillDispose(()=>this.setModel(null))),B.push(Q.onEvent(re=>{switch(re.kind){case 0:this._onDidContentSizeChange.fire(re);break;case 1:this._editorTextFocus.setValue(re.hasFocus);break;case 2:this._onDidScrollChange.fire(re);break;case 3:this._onDidChangeViewZones.fire();break;case 4:this._onDidChangeHiddenAreas.fire();break;case 5:this._onDidAttemptReadOnlyEdit.fire();break;case 6:{if(re.reachedMaxCursorCount){const ye=this.getOption(80),Le=M.localize(70,"The number of cursors has been limited to {0}. Consider using [find and replace](https://code.visualstudio.com/docs/editor/codebasics#_find-and-replace) for larger changes or increase the editor multi cursor limit setting.",ye);this._notificationService.prompt(x.Severity.Warning,Le,[{label:"Find and Replace",run:()=>{this._commandService.executeCommand("editor.action.startFindReplaceAction")}},{label:M.localize(71,"Increase Multi Cursor Limit"),run:()=>{this._commandService.executeCommand("workbench.action.openSettings2",{query:"editor.multiCursorLimit"})}}])}const le=[];for(let ye=0,Le=re.selections.length;ye{this._paste("keyboard",Z,te,re,le)},type:Z=>{this._type("keyboard",Z)},compositionType:(Z,te,re,le)=>{this._compositionType("keyboard",Z,te,re,le)},startComposition:()=>{this._startComposition()},endComposition:()=>{this._endComposition("keyboard")},cut:()=>{this._cut("keyboard")}}:B={paste:(Z,te,re,le)=>{const me={text:Z,pasteOnNewLine:te,multicursorText:re,mode:le};this._commandService.executeCommand("paste",me)},type:Z=>{const te={text:Z};this._commandService.executeCommand("type",te)},compositionType:(Z,te,re,le)=>{if(re||le){const me={text:Z,replacePrevCharCnt:te,replaceNextCharCnt:re,positionDelta:le};this._commandService.executeCommand("compositionType",me)}else{const me={text:Z,replaceCharCnt:te};this._commandService.executeCommand("replacePreviousChar",me)}},startComposition:()=>{this._commandService.executeCommand("compositionStart",{})},endComposition:()=>{this._commandService.executeCommand("compositionEnd",{})},cut:()=>{this._commandService.executeCommand("cut",{})}};const $=new i.ViewUserInputEvents(X.coordinatesConverter);return $.onKeyDown=Z=>this._onKeyDown.fire(Z),$.onKeyUp=Z=>this._onKeyUp.fire(Z),$.onContextMenu=Z=>this._onContextMenu.fire(Z),$.onMouseMove=Z=>this._onMouseMove.fire(Z),$.onMouseLeave=Z=>this._onMouseLeave.fire(Z),$.onMouseDown=Z=>this._onMouseDown.fire(Z),$.onMouseUp=Z=>this._onMouseUp.fire(Z),$.onMouseDrag=Z=>this._onMouseDrag.fire(Z),$.onMouseDrop=Z=>this._onMouseDrop.fire(Z),$.onMouseDropCanceled=Z=>this._onMouseDropCanceled.fire(Z),$.onMouseWheel=Z=>this._onMouseWheel.fire(Z),[new o.View(B,this._configuration,this._themeService.getColorTheme(),X,$,this._overflowWidgetsDomNode,this._instantiationService),!0]}_postDetachModelCleanup(X){X?.removeAllDecorationsWithOwnerId(this._id)}_detachModel(){if(this._contributionsDisposable?.dispose(),this._contributionsDisposable=void 0,!this._modelData)return null;const X=this._modelData.model,B=this._modelData.hasRealView?this._modelData.view.domNode.domNode:null;return this._modelData.dispose(),this._modelData=null,this._domElement.removeAttribute("data-mode-id"),B&&this._domElement.contains(B)&&B.remove(),this._bannerDomNode&&this._domElement.contains(this._bannerDomNode)&&this._bannerDomNode.remove(),X}_removeDecorationType(X){this._codeEditorService.removeDecorationType(X)}hasModel(){return this._modelData!==null}showDropIndicatorAt(X){const B=[{range:new r.Range(X.lineNumber,X.column,X.lineNumber,X.column),options:H.dropIntoEditorDecorationOptions}];this._dropIntoEditorDecorations.set(B),this.revealPosition(X,1)}removeDropIndicator(){this._dropIntoEditorDecorations.clear()}setContextValue(X,B){this._contextKeyService.createKey(X,B)}_beginUpdate(){this._updateCounter++,this._updateCounter===1&&this._onBeginUpdate.fire()}_endUpdate(){this._updateCounter--,this._updateCounter===0&&this._onEndUpdate.fire()}};e.CodeEditorWidget=z,e.CodeEditorWidget=z=H=ke([ce(3,O.IInstantiationService),ce(4,n.ICodeEditorService),ce(5,P.ICommandService),ce(6,N.IContextKeyService),ce(7,V.IThemeService),ce(8,x.INotificationService),ce(9,A.IAccessibilityService),ce(10,w.ILanguageConfigurationService),ce(11,L.ILanguageFeaturesService)],z);let U=0;class j{constructor(X,B,$,Q,Z,te){this.model=X,this.viewModel=B,this.view=$,this.hasRealView=Q,this.listenersToRemove=Z,this.attachedView=te}dispose(){(0,E.dispose)(this.listenersToRemove),this.model.onBeforeDetached(this.attachedView),this.hasRealView&&this.view.dispose(),this.viewModel.dispose()}}class Y extends E.Disposable{constructor(X){super(),this._emitterOptions=X,this._onDidChangeToTrue=this._register(new I.Emitter(this._emitterOptions)),this.onDidChangeToTrue=this._onDidChangeToTrue.event,this._onDidChangeToFalse=this._register(new I.Emitter(this._emitterOptions)),this.onDidChangeToFalse=this._onDidChangeToFalse.event,this._value=0}setValue(X){const B=X?2:1;this._value!==B&&(this._value=B,this._value===2?this._onDidChangeToTrue.fire():this._value===1&&this._onDidChangeToFalse.fire())}}e.BooleanEventEmitter=Y;class G extends I.Emitter{constructor(X,B){super({deliveryQueue:B}),this._contributions=X}fire(X){this._contributions.onBeforeInteractionEvent(),super.fire(X)}}class K extends E.Disposable{constructor(X,B){super(),this._editor=X,B.createKey("editorId",X.getId()),this._editorSimpleInput=v.EditorContextKeys.editorSimpleInput.bindTo(B),this._editorFocus=v.EditorContextKeys.focus.bindTo(B),this._textInputFocus=v.EditorContextKeys.textInputFocus.bindTo(B),this._editorTextFocus=v.EditorContextKeys.editorTextFocus.bindTo(B),this._tabMovesFocus=v.EditorContextKeys.tabMovesFocus.bindTo(B),this._editorReadonly=v.EditorContextKeys.readOnly.bindTo(B),this._inDiffEditor=v.EditorContextKeys.inDiffEditor.bindTo(B),this._editorColumnSelection=v.EditorContextKeys.columnSelection.bindTo(B),this._hasMultipleSelections=v.EditorContextKeys.hasMultipleSelections.bindTo(B),this._hasNonEmptySelection=v.EditorContextKeys.hasNonEmptySelection.bindTo(B),this._canUndo=v.EditorContextKeys.canUndo.bindTo(B),this._canRedo=v.EditorContextKeys.canRedo.bindTo(B),this._register(this._editor.onDidChangeConfiguration(()=>this._updateFromConfig())),this._register(this._editor.onDidChangeCursorSelection(()=>this._updateFromSelection())),this._register(this._editor.onDidFocusEditorWidget(()=>this._updateFromFocus())),this._register(this._editor.onDidBlurEditorWidget(()=>this._updateFromFocus())),this._register(this._editor.onDidFocusEditorText(()=>this._updateFromFocus())),this._register(this._editor.onDidBlurEditorText(()=>this._updateFromFocus())),this._register(this._editor.onDidChangeModel(()=>this._updateFromModel())),this._register(this._editor.onDidChangeConfiguration(()=>this._updateFromModel())),this._register(b.TabFocus.onDidChangeTabFocus($=>this._tabMovesFocus.set($))),this._updateFromConfig(),this._updateFromSelection(),this._updateFromFocus(),this._updateFromModel(),this._editorSimpleInput.set(this._editor.isSimpleWidget)}_updateFromConfig(){const X=this._editor.getOptions();this._tabMovesFocus.set(b.TabFocus.getTabFocusMode()),this._editorReadonly.set(X.get(92)),this._inDiffEditor.set(X.get(61)),this._editorColumnSelection.set(X.get(22))}_updateFromSelection(){const X=this._editor.getSelections();X?(this._hasMultipleSelections.set(X.length>1),this._hasNonEmptySelection.set(X.some(B=>!B.isEmpty()))):(this._hasMultipleSelections.reset(),this._hasNonEmptySelection.reset())}_updateFromFocus(){this._editorFocus.set(this._editor.hasWidgetFocus()&&!this._editor.isSimpleWidget),this._editorTextFocus.set(this._editor.hasTextFocus()&&!this._editor.isSimpleWidget),this._textInputFocus.set(this._editor.hasTextFocus())}_updateFromModel(){const X=this._editor.getModel();this._canUndo.set(!!(X&&X.canUndo())),this._canRedo.set(!!(X&&X.canRedo()))}}class R extends E.Disposable{constructor(X,B,$){super(),this._editor=X,this._contextKeyService=B,this._languageFeaturesService=$,this._langId=v.EditorContextKeys.languageId.bindTo(B),this._hasCompletionItemProvider=v.EditorContextKeys.hasCompletionItemProvider.bindTo(B),this._hasCodeActionsProvider=v.EditorContextKeys.hasCodeActionsProvider.bindTo(B),this._hasCodeLensProvider=v.EditorContextKeys.hasCodeLensProvider.bindTo(B),this._hasDefinitionProvider=v.EditorContextKeys.hasDefinitionProvider.bindTo(B),this._hasDeclarationProvider=v.EditorContextKeys.hasDeclarationProvider.bindTo(B),this._hasImplementationProvider=v.EditorContextKeys.hasImplementationProvider.bindTo(B),this._hasTypeDefinitionProvider=v.EditorContextKeys.hasTypeDefinitionProvider.bindTo(B),this._hasHoverProvider=v.EditorContextKeys.hasHoverProvider.bindTo(B),this._hasDocumentHighlightProvider=v.EditorContextKeys.hasDocumentHighlightProvider.bindTo(B),this._hasDocumentSymbolProvider=v.EditorContextKeys.hasDocumentSymbolProvider.bindTo(B),this._hasReferenceProvider=v.EditorContextKeys.hasReferenceProvider.bindTo(B),this._hasRenameProvider=v.EditorContextKeys.hasRenameProvider.bindTo(B),this._hasSignatureHelpProvider=v.EditorContextKeys.hasSignatureHelpProvider.bindTo(B),this._hasInlayHintsProvider=v.EditorContextKeys.hasInlayHintsProvider.bindTo(B),this._hasDocumentFormattingProvider=v.EditorContextKeys.hasDocumentFormattingProvider.bindTo(B),this._hasDocumentSelectionFormattingProvider=v.EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(B),this._hasMultipleDocumentFormattingProvider=v.EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(B),this._hasMultipleDocumentSelectionFormattingProvider=v.EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(B),this._isInEmbeddedEditor=v.EditorContextKeys.isInEmbeddedEditor.bindTo(B);const Q=()=>this._update();this._register(X.onDidChangeModel(Q)),this._register(X.onDidChangeModelLanguage(Q)),this._register($.completionProvider.onDidChange(Q)),this._register($.codeActionProvider.onDidChange(Q)),this._register($.codeLensProvider.onDidChange(Q)),this._register($.definitionProvider.onDidChange(Q)),this._register($.declarationProvider.onDidChange(Q)),this._register($.implementationProvider.onDidChange(Q)),this._register($.typeDefinitionProvider.onDidChange(Q)),this._register($.hoverProvider.onDidChange(Q)),this._register($.documentHighlightProvider.onDidChange(Q)),this._register($.documentSymbolProvider.onDidChange(Q)),this._register($.referenceProvider.onDidChange(Q)),this._register($.renameProvider.onDidChange(Q)),this._register($.documentFormattingEditProvider.onDidChange(Q)),this._register($.documentRangeFormattingEditProvider.onDidChange(Q)),this._register($.signatureHelpProvider.onDidChange(Q)),this._register($.inlayHintsProvider.onDidChange(Q)),Q()}dispose(){super.dispose()}reset(){this._contextKeyService.bufferChangeEvents(()=>{this._langId.reset(),this._hasCompletionItemProvider.reset(),this._hasCodeActionsProvider.reset(),this._hasCodeLensProvider.reset(),this._hasDefinitionProvider.reset(),this._hasDeclarationProvider.reset(),this._hasImplementationProvider.reset(),this._hasTypeDefinitionProvider.reset(),this._hasHoverProvider.reset(),this._hasDocumentHighlightProvider.reset(),this._hasDocumentSymbolProvider.reset(),this._hasReferenceProvider.reset(),this._hasRenameProvider.reset(),this._hasDocumentFormattingProvider.reset(),this._hasDocumentSelectionFormattingProvider.reset(),this._hasSignatureHelpProvider.reset(),this._isInEmbeddedEditor.reset()})}_update(){const X=this._editor.getModel();if(!X){this.reset();return}this._contextKeyService.bufferChangeEvents(()=>{this._langId.set(X.getLanguageId()),this._hasCompletionItemProvider.set(this._languageFeaturesService.completionProvider.has(X)),this._hasCodeActionsProvider.set(this._languageFeaturesService.codeActionProvider.has(X)),this._hasCodeLensProvider.set(this._languageFeaturesService.codeLensProvider.has(X)),this._hasDefinitionProvider.set(this._languageFeaturesService.definitionProvider.has(X)),this._hasDeclarationProvider.set(this._languageFeaturesService.declarationProvider.has(X)),this._hasImplementationProvider.set(this._languageFeaturesService.implementationProvider.has(X)),this._hasTypeDefinitionProvider.set(this._languageFeaturesService.typeDefinitionProvider.has(X)),this._hasHoverProvider.set(this._languageFeaturesService.hoverProvider.has(X)),this._hasDocumentHighlightProvider.set(this._languageFeaturesService.documentHighlightProvider.has(X)),this._hasDocumentSymbolProvider.set(this._languageFeaturesService.documentSymbolProvider.has(X)),this._hasReferenceProvider.set(this._languageFeaturesService.referenceProvider.has(X)),this._hasRenameProvider.set(this._languageFeaturesService.renameProvider.has(X)),this._hasSignatureHelpProvider.set(this._languageFeaturesService.signatureHelpProvider.has(X)),this._hasInlayHintsProvider.set(this._languageFeaturesService.inlayHintsProvider.has(X)),this._hasDocumentFormattingProvider.set(this._languageFeaturesService.documentFormattingEditProvider.has(X)||this._languageFeaturesService.documentRangeFormattingEditProvider.has(X)),this._hasDocumentSelectionFormattingProvider.set(this._languageFeaturesService.documentRangeFormattingEditProvider.has(X)),this._hasMultipleDocumentFormattingProvider.set(this._languageFeaturesService.documentFormattingEditProvider.all(X).length+this._languageFeaturesService.documentRangeFormattingEditProvider.all(X).length>1),this._hasMultipleDocumentSelectionFormattingProvider.set(this._languageFeaturesService.documentRangeFormattingEditProvider.all(X).length>1),this._isInEmbeddedEditor.set(X.uri.scheme===y.Schemas.walkThroughSnippet||X.uri.scheme===y.Schemas.vscodeChatCodeBlock)})}}e.EditorModeContext=R;class J extends E.Disposable{constructor(X,B){super(),this._onChange=this._register(new I.Emitter),this.onChange=this._onChange.event,this._hadFocus=void 0,this._hasDomElementFocus=!1,this._domFocusTracker=this._register(d.trackFocus(X)),this._overflowWidgetsDomNodeHasFocus=!1,this._register(this._domFocusTracker.onDidFocus(()=>{this._hasDomElementFocus=!0,this._update()})),this._register(this._domFocusTracker.onDidBlur(()=>{this._hasDomElementFocus=!1,this._update()})),B&&(this._overflowWidgetsDomNode=this._register(d.trackFocus(B)),this._register(this._overflowWidgetsDomNode.onDidFocus(()=>{this._overflowWidgetsDomNodeHasFocus=!0,this._update()})),this._register(this._overflowWidgetsDomNode.onDidBlur(()=>{this._overflowWidgetsDomNodeHasFocus=!1,this._update()})))}_update(){const X=this._hasDomElementFocus||this._overflowWidgetsDomNodeHasFocus;this._hadFocus!==X&&(this._hadFocus=X,this._onChange.fire(void 0))}hasFocus(){return this._hadFocus??!1}}class ie{get length(){return this._decorationIds.length}constructor(X,B){this._editor=X,this._decorationIds=[],this._isChangingDecorations=!1,Array.isArray(B)&&B.length>0&&this.set(B)}onDidChange(X,B,$){return this._editor.onDidChangeModelDecorations(Q=>{this._isChangingDecorations||X.call(B,Q)},$)}getRange(X){return!this._editor.hasModel()||X>=this._decorationIds.length?null:this._editor.getModel().getDecorationRange(this._decorationIds[X])}getRanges(){if(!this._editor.hasModel())return[];const X=this._editor.getModel(),B=[];for(const $ of this._decorationIds){const Q=X.getDecorationRange($);Q&&B.push(Q)}return B}has(X){return this._decorationIds.includes(X.id)}clear(){this._decorationIds.length!==0&&this.set([])}set(X){try{this._isChangingDecorations=!0,this._editor.changeDecorations(B=>{this._decorationIds=B.deltaDecorations(this._decorationIds,X)})}finally{this._isChangingDecorations=!1}return this._decorationIds}append(X){let B=[];try{this._isChangingDecorations=!0,this._editor.changeDecorations($=>{B=$.deltaDecorations([],X),this._decorationIds=this._decorationIds.concat(B)})}finally{this._isChangingDecorations=!1}return B}}const ue=encodeURIComponent("");function pe(ge){return ue+encodeURIComponent(ge.toString())+he}const ae=encodeURIComponent('');function de(ge){return ae+encodeURIComponent(ge.toString())+ee}(0,V.registerThemingParticipant)((ge,X)=>{const B=ge.getColor(W.editorErrorForeground);B&&X.addRule(`.monaco-editor .squiggly-error { background: url("data:image/svg+xml,${pe(B)}") repeat-x bottom left; }`);const $=ge.getColor(W.editorWarningForeground);$&&X.addRule(`.monaco-editor .squiggly-warning { background: url("data:image/svg+xml,${pe($)}") repeat-x bottom left; }`);const Q=ge.getColor(W.editorInfoForeground);Q&&X.addRule(`.monaco-editor .squiggly-info { background: url("data:image/svg+xml,${pe(Q)}") repeat-x bottom left; }`);const Z=ge.getColor(W.editorHintForeground);Z&&X.addRule(`.monaco-editor .squiggly-hint { background: url("data:image/svg+xml,${de(Z)}") no-repeat bottom left; }`);const te=ge.getColor(l.editorUnnecessaryCodeOpacity);te&&X.addRule(`.monaco-editor.showUnused .squiggly-inline-unnecessary { opacity: ${te.rgba.a}; }`)})}),define(ne[125],se([1,0,60,34,219,36,17,61,24,12,7,50,25]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.EmbeddedCodeEditorWidget=void 0;let t=class extends I.CodeEditorWidget{constructor(s,g,c,l,a,r,u,C,f,h,v,w,S){super(s,{...l.getRawOptions(),overflowWidgetsDomNode:l.getOverflowWidgetsDomNode()},c,a,r,u,C,f,h,v,w,S),this._parentEditor=l,this._overwriteOptions=g,super.updateOptions(this._overwriteOptions),this._register(l.onDidChangeConfiguration(L=>this._onParentConfigurationChanged(L)))}getParentEditor(){return this._parentEditor}_onParentConfigurationChanged(s){super.updateOptions(this._parentEditor.getRawOptions()),super.updateOptions(this._overwriteOptions)}updateOptions(s){d.mixin(this._overwriteOptions,s,!0),super.updateOptions(this._overwriteOptions)}};e.EmbeddedCodeEditorWidget=t,e.EmbeddedCodeEditorWidget=t=ke([ce(4,p.IInstantiationService),ce(5,k.ICodeEditorService),ce(6,_.ICommandService),ce(7,b.IContextKeyService),ce(8,o.IThemeService),ce(9,n.INotificationService),ce(10,m.IAccessibilityService),ce(11,E.ILanguageConfigurationService),ce(12,y.ILanguageFeaturesService)],t)}),define(ne[286],se([1,0,5,67,8,6,2,21,65,15,34,143,219,762,806,363,285,799,383,364,415,653,88,171,397,9,4,198,20,137,12,7,154,96,775,552,807,407,500]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M,A,P,N,O,F,x){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorWidget=void 0;let W=class extends O.DelegatingEditor{get onDidContentSizeChange(){return this._editors.onDidContentSizeChange}constructor(H,z,U,j,Y,G,K,R){super(),this._domElement=H,this._parentContextKeyService=j,this._parentInstantiationService=Y,this._accessibilitySignalService=K,this._editorProgressService=R,this.elements=(0,d.h)("div.monaco-diff-editor.side-by-side",{style:{position:"relative",height:"100%"}},[(0,d.h)("div.editor.original@original",{style:{position:"absolute",height:"100%"}}),(0,d.h)("div.editor.modified@modified",{style:{position:"absolute",height:"100%"}}),(0,d.h)("div.accessibleDiffViewer@accessibleDiffViewer",{style:{position:"absolute",height:"100%"}})]),this._diffModelSrc=this._register((0,m.disposableObservableValue)(this,void 0)),this._diffModel=(0,m.derived)(this,$=>this._diffModelSrc.read($)?.object),this.onDidChangeModel=E.Event.fromObservableLight(this._diffModel),this._contextKeyService=this._register(this._parentContextKeyService.createScoped(this._domElement)),this._instantiationService=this._register(this._parentInstantiationService.createChild(new A.ServiceCollection([T.IContextKeyService,this._contextKeyService]))),this._boundarySashes=(0,m.observableValue)(this,void 0),this._accessibleDiffViewerShouldBeVisible=(0,m.observableValue)(this,!1),this._accessibleDiffViewerVisible=(0,m.derived)(this,$=>this._options.onlyShowAccessibleDiffViewer.read($)?!0:this._accessibleDiffViewerShouldBeVisible.read($)),this._movedBlocksLinesPart=(0,m.observableValue)(this,void 0),this._layoutInfo=(0,m.derived)(this,$=>{const Q=this._rootSizeObserver.width.read($),Z=this._rootSizeObserver.height.read($);this._rootSizeObserver.automaticLayout?this.elements.root.style.height="100%":this.elements.root.style.height=Z+"px";const te=this._sash.read($),re=this._gutter.read($),le=re?.width.read($)??0,me=this._overviewRulerPart.read($)?.width??0;let Ce,ye,Le,Ee,Me;if(!!te){const Ne=te.sashLeft.read($),Ke=this._movedBlocksLinesPart.read($)?.width.read($)??0;Ce=0,ye=Ne-le-Ke,Me=Ne-le,Le=Ne,Ee=Q-Le-me}else{Me=0;const Ne=this._options.inlineViewHideOriginalLineNumbers.read($);Ce=le,Ne?ye=0:ye=Math.max(5,this._editors.originalObs.layoutInfoDecorationsLeft.read($)),Le=le+ye,Ee=Q-Le-me}return this.elements.original.style.left=Ce+"px",this.elements.original.style.width=ye+"px",this._editors.original.layout({width:ye,height:Z},!0),re?.layout(Me),this.elements.modified.style.left=Le+"px",this.elements.modified.style.width=Ee+"px",this._editors.modified.layout({width:Ee,height:Z},!0),{modifiedEditor:this._editors.modified.getLayoutInfo(),originalEditor:this._editors.original.getLayoutInfo()}}),this._diffValue=this._diffModel.map(($,Q)=>$?.diff.read(Q)),this.onDidUpdateDiff=E.Event.fromObservableLight(this._diffValue),G.willCreateDiffEditor(),this._contextKeyService.createKey("isInDiffEditor",!0),this._domElement.appendChild(this.elements.root),this._register((0,y.toDisposable)(()=>this.elements.root.remove())),this._rootSizeObserver=this._register(new C.ObservableElementSizeObserver(this.elements.root,z.dimension)),this._rootSizeObserver.setAutomaticLayout(z.automaticLayout??!1),this._options=this._instantiationService.createInstance(F.DiffEditorOptions,z),this._register((0,m.autorun)($=>{this._options.setWidth(this._rootSizeObserver.width.read($))})),this._contextKeyService.createKey(L.EditorContextKeys.isEmbeddedDiffEditor.key,!1),this._register((0,h.bindContextKey)(L.EditorContextKeys.isEmbeddedDiffEditor,this._contextKeyService,$=>this._options.isInEmbeddedEditor.read($))),this._register((0,h.bindContextKey)(L.EditorContextKeys.comparingMovedCode,this._contextKeyService,$=>!!this._diffModel.read($)?.movedTextToCompare.read($))),this._register((0,h.bindContextKey)(L.EditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached,this._contextKeyService,$=>this._options.couldShowInlineViewBecauseOfSize.read($))),this._register((0,h.bindContextKey)(L.EditorContextKeys.diffEditorInlineMode,this._contextKeyService,$=>!this._options.renderSideBySide.read($))),this._register((0,h.bindContextKey)(L.EditorContextKeys.hasChanges,this._contextKeyService,$=>(this._diffModel.read($)?.diff.read($)?.mappings.length??0)>0)),this._editors=this._register(this._instantiationService.createInstance(N.DiffEditorEditors,this.elements.original,this.elements.modified,this._options,U,($,Q,Z,te)=>this._createInnerEditor($,Q,Z,te))),this._register((0,h.bindContextKey)(L.EditorContextKeys.diffEditorOriginalWritable,this._contextKeyService,$=>this._options.originalEditable.read($))),this._register((0,h.bindContextKey)(L.EditorContextKeys.diffEditorModifiedWritable,this._contextKeyService,$=>!this._options.readOnly.read($))),this._register((0,h.bindContextKey)(L.EditorContextKeys.diffEditorOriginalUri,this._contextKeyService,$=>this._diffModel.read($)?.model.original.uri.toString()??"")),this._register((0,h.bindContextKey)(L.EditorContextKeys.diffEditorModifiedUri,this._contextKeyService,$=>this._diffModel.read($)?.model.modified.uri.toString()??"")),this._overviewRulerPart=(0,_.derivedDisposable)(this,$=>this._options.renderOverviewRuler.read($)?this._instantiationService.createInstance((0,f.readHotReloadableExport)(r.OverviewRulerFeature,$),this._editors,this.elements.root,this._diffModel,this._rootSizeObserver.width,this._rootSizeObserver.height,this._layoutInfo.map(Q=>Q.modifiedEditor)):void 0).recomputeInitiallyAndOnChange(this._store);const J={height:this._rootSizeObserver.height,width:this._rootSizeObserver.width.map(($,Q)=>$-(this._overviewRulerPart.read(Q)?.width??0))};this._sashLayout=new s.SashLayout(this._options,J),this._sash=(0,_.derivedDisposable)(this,$=>{const Q=this._options.renderSideBySide.read($);return this.elements.root.classList.toggle("side-by-side",Q),Q?new s.DiffEditorSash(this.elements.root,J,this._options.enableSplitViewResizing,this._boundarySashes,this._sashLayout.sashLeft,()=>this._sashLayout.resetSash()):void 0}).recomputeInitiallyAndOnChange(this._store);const ie=(0,_.derivedDisposable)(this,$=>this._instantiationService.createInstance((0,f.readHotReloadableExport)(l.HideUnchangedRegionsFeature,$),this._editors,this._diffModel,this._options)).recomputeInitiallyAndOnChange(this._store);(0,_.derivedDisposable)(this,$=>this._instantiationService.createInstance((0,f.readHotReloadableExport)(i.DiffEditorDecorations,$),this._editors,this._diffModel,this._options,this)).recomputeInitiallyAndOnChange(this._store);const ue=new Set,he=new Set;let pe=!1;const ae=(0,_.derivedDisposable)(this,$=>this._instantiationService.createInstance((0,f.readHotReloadableExport)(g.DiffEditorViewZones,$),(0,d.getWindow)(this._domElement),this._editors,this._diffModel,this._options,this,()=>pe||ie.get().isUpdatingHiddenAreas,ue,he)).recomputeInitiallyAndOnChange(this._store),ee=(0,m.derived)(this,$=>{const Q=ae.read($).viewZones.read($).orig,Z=ie.read($).viewZones.read($).origViewZones;return Q.concat(Z)}),de=(0,m.derived)(this,$=>{const Q=ae.read($).viewZones.read($).mod,Z=ie.read($).viewZones.read($).modViewZones;return Q.concat(Z)});this._register((0,C.applyViewZones)(this._editors.original,ee,$=>{pe=$},ue));let ge;this._register((0,C.applyViewZones)(this._editors.modified,de,$=>{pe=$,pe?ge=n.StableEditorScrollState.capture(this._editors.modified):(ge?.restore(this._editors.modified),ge=void 0)},he)),this._accessibleDiffViewer=(0,_.derivedDisposable)(this,$=>this._instantiationService.createInstance((0,f.readHotReloadableExport)(t.AccessibleDiffViewer,$),this.elements.accessibleDiffViewer,this._accessibleDiffViewerVisible,(Q,Z)=>this._accessibleDiffViewerShouldBeVisible.set(Q,Z),this._options.onlyShowAccessibleDiffViewer.map(Q=>!Q),this._rootSizeObserver.width,this._rootSizeObserver.height,this._diffModel.map((Q,Z)=>Q?.diff.read(Z)?.mappings.map(te=>te.lineRangeMapping)),new t.AccessibleDiffViewerModelFromEditors(this._editors))).recomputeInitiallyAndOnChange(this._store);const X=this._accessibleDiffViewerVisible.map($=>$?"hidden":"visible");this._register((0,C.applyStyle)(this.elements.modified,{visibility:X})),this._register((0,C.applyStyle)(this.elements.original,{visibility:X})),this._createDiffEditorContributions(),G.addDiffEditor(this),this._gutter=(0,_.derivedDisposable)(this,$=>this._options.shouldRenderGutterMenu.read($)?this._instantiationService.createInstance((0,f.readHotReloadableExport)(c.DiffEditorGutter,$),this.elements.root,this._diffModel,this._editors,this._options,this._sashLayout,this._boundarySashes):void 0),this._register((0,m.recomputeInitiallyAndOnChange)(this._layoutInfo)),(0,_.derivedDisposable)(this,$=>new((0,f.readHotReloadableExport)(a.MovedBlocksLinesFeature,$))(this.elements.root,this._diffModel,this._layoutInfo.map(Q=>Q.originalEditor),this._layoutInfo.map(Q=>Q.modifiedEditor),this._editors)).recomputeInitiallyAndOnChange(this._store,$=>{this._movedBlocksLinesPart.set($,void 0)}),this._register(E.Event.runAndSubscribe(this._editors.modified.onDidChangeCursorPosition,$=>this._handleCursorPositionChange($,!0))),this._register(E.Event.runAndSubscribe(this._editors.original.onDidChangeCursorPosition,$=>this._handleCursorPositionChange($,!1)));const B=this._diffModel.map(this,($,Q)=>{if($)return $.diff.read(Q)===void 0&&!$.isDiffUpToDate.read(Q)});this._register((0,m.autorunWithStore)(($,Q)=>{if(B.read($)===!0){const Z=this._editorProgressService.show(!0,1e3);Q.add((0,y.toDisposable)(()=>Z.done()))}})),this._register((0,m.autorunWithStore)(($,Q)=>{Q.add(new((0,f.readHotReloadableExport)(u.RevertButtonsFeature,$))(this._editors,this._diffModel,this._options,this))})),this._register((0,m.autorunWithStore)(($,Q)=>{const Z=this._diffModel.read($);if(Z)for(const te of[Z.model.original,Z.model.modified])Q.add(te.onWillDispose(re=>{(0,I.onUnexpectedError)(new I.BugIndicatingError("TextModel got disposed before DiffEditorWidget model got reset")),this.setModel(null)}))})),this._register((0,m.autorun)($=>{this._options.setModel(this._diffModel.read($))}))}_createInnerEditor(H,z,U,j){return H.createInstance(o.CodeEditorWidget,z,U,j)}_createDiffEditorContributions(){const H=b.EditorExtensionsRegistry.getDiffEditorContributions();for(const z of H)try{this._register(this._instantiationService.createInstance(z.ctor,this))}catch(U){(0,I.onUnexpectedError)(U)}}get _targetEditor(){return this._editors.modified}getEditorType(){return S.EditorType.IDiffEditor}layout(H){this._rootSizeObserver.observe(H)}hasTextFocus(){return this._editors.original.hasTextFocus()||this._editors.modified.hasTextFocus()}saveViewState(){const H=this._editors.original.saveViewState(),z=this._editors.modified.saveViewState();return{original:H,modified:z,modelState:this._diffModel.get()?.serializeState()}}restoreViewState(H){if(H&&H.original&&H.modified){const z=H;this._editors.original.restoreViewState(z.original),this._editors.modified.restoreViewState(z.modified),z.modelState&&this._diffModel.get()?.restoreSerializedState(z.modelState)}}handleInitialized(){this._editors.original.handleInitialized(),this._editors.modified.handleInitialized()}createViewModel(H){return this._instantiationService.createInstance(x.DiffEditorViewModel,H,this._options)}getModel(){return this._diffModel.get()?.model??null}setModel(H){const z=H?"model"in H?C.RefCounted.create(H).createNewRef(this):C.RefCounted.create(this.createViewModel(H),this):null;this.setDiffModel(z)}setDiffModel(H,z){const U=this._diffModel.get();!H&&U&&this._accessibleDiffViewer.get().close(),this._diffModel.get()!==H?.object&&(0,m.subtransaction)(z,j=>{const Y=H?.object;m.observableFromEvent.batchEventsGlobally(j,()=>{this._editors.original.setModel(Y?Y.model.original:null),this._editors.modified.setModel(Y?Y.model.modified:null)});const G=this._diffModelSrc.get()?.createNewRef(this);this._diffModelSrc.set(H?.createNewRef(this),j),setTimeout(()=>{G?.dispose()},0)})}updateOptions(H){this._options.updateOptions(H)}getContainerDomNode(){return this._domElement}getOriginalEditor(){return this._editors.original}getModifiedEditor(){return this._editors.modified}getLineChanges(){const H=this._diffModel.get()?.diff.get();return H?V(H):null}revert(H){const z=this._diffModel.get();!z||!z.isDiffUpToDate.get()||this._editors.modified.executeEdits("diffEditor",[{range:H.modified.toExclusiveRange(),text:z.model.original.getValueInRange(H.original.toExclusiveRange())}])}revertRangeMappings(H){const z=this._diffModel.get();if(!z||!z.isDiffUpToDate.get())return;const U=H.map(j=>({range:j.modifiedRange,text:z.model.original.getValueInRange(j.originalRange)}));this._editors.modified.executeEdits("diffEditor",U)}_goTo(H){this._editors.modified.setPosition(new v.Position(H.lineRangeMapping.modified.startLineNumber,1)),this._editors.modified.revealRangeInCenter(H.lineRangeMapping.modified.toExclusiveRange())}goToDiff(H){const z=this._diffModel.get()?.diff.get()?.mappings;if(!z||z.length===0)return;const U=this._editors.modified.getPosition().lineNumber;let j;H==="next"?j=z.find(Y=>Y.lineRangeMapping.modified.startLineNumber>U)??z[0]:j=(0,k.findLast)(z,Y=>Y.lineRangeMapping.modified.startLineNumber{const z=H.diff.get()?.mappings;!z||z.length===0||this._goTo(z[0])})}accessibleDiffViewerNext(){this._accessibleDiffViewer.get().next()}accessibleDiffViewerPrev(){this._accessibleDiffViewer.get().prev()}async waitForDiff(){const H=this._diffModel.get();H&&await H.waitForDiff()}mapToOtherSide(){const H=this._editors.modified.hasWidgetFocus(),z=H?this._editors.modified:this._editors.original,U=H?this._editors.original:this._editors.modified;let j;const Y=z.getSelection();if(Y){const G=this._diffModel.get()?.diff.get()?.mappings.map(K=>H?K.lineRangeMapping.flip():K.lineRangeMapping);if(G){const K=(0,C.translatePosition)(Y.getStartPosition(),G),R=(0,C.translatePosition)(Y.getEndPosition(),G);j=w.Range.plusRange(K,R)}}return{destination:U,destinationSelection:j}}switchSide(){const{destination:H,destinationSelection:z}=this.mapToOtherSide();H.focus(),z&&H.setSelection(z)}exitCompareMove(){const H=this._diffModel.get();H&&H.movedTextToCompare.set(void 0,void 0)}collapseAllUnchangedRegions(){const H=this._diffModel.get()?.unchangedRegions.get();H&&(0,m.transaction)(z=>{for(const U of H)U.collapseAll(z)})}showAllUnchangedRegions(){const H=this._diffModel.get()?.unchangedRegions.get();H&&(0,m.transaction)(z=>{for(const U of H)U.showAll(z)})}_handleCursorPositionChange(H,z){if(H?.reason===3){const U=this._diffModel.get()?.diff.get()?.mappings.find(j=>z?j.lineRangeMapping.modified.contains(H.position.lineNumber):j.lineRangeMapping.original.contains(H.position.lineNumber));U?.lineRangeMapping.modified.isEmpty?this._accessibilitySignalService.playSignal(D.AccessibilitySignal.diffLineDeleted,{source:"diffEditor.cursorPositionChanged"}):U?.lineRangeMapping.original.isEmpty?this._accessibilitySignalService.playSignal(D.AccessibilitySignal.diffLineInserted,{source:"diffEditor.cursorPositionChanged"}):U&&this._accessibilitySignalService.playSignal(D.AccessibilitySignal.diffLineModified,{source:"diffEditor.cursorPositionChanged"})}}};e.DiffEditorWidget=W,e.DiffEditorWidget=W=ke([ce(3,T.IContextKeyService),ce(4,M.IInstantiationService),ce(5,p.ICodeEditorService),ce(6,D.IAccessibilitySignalService),ce(7,P.IEditorProgressService)],W);function V(q){return q.mappings.map(H=>{const z=H.lineRangeMapping;let U,j,Y,G,K=z.innerChanges;return z.original.isEmpty?(U=z.original.startLineNumber-1,j=0,K=void 0):(U=z.original.startLineNumber,j=z.original.endLineNumberExclusive-1),z.modified.isEmpty?(Y=z.modified.startLineNumber-1,G=0,K=void 0):(Y=z.modified.startLineNumber,G=z.modified.endLineNumberExclusive-1),{originalStartLineNumber:U,originalEndLineNumber:j,modifiedStartLineNumber:Y,modifiedEndLineNumber:G,charChanges:K?.map(R=>({originalStartLineNumber:R.originalRange.startLineNumber,originalStartColumn:R.originalRange.startColumn,originalEndLineNumber:R.originalRange.endLineNumber,originalEndColumn:R.originalRange.endColumn,modifiedStartLineNumber:R.modifiedRange.startLineNumber,modifiedStartColumn:R.modifiedRange.startColumn,modifiedEndLineNumber:R.modifiedRange.endLineNumber,modifiedEndColumn:R.modifiedRange.endColumn}))}})}}),define(ne[811],se([1,0,5,26,15,34,286,20,3,29,28,12,139]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AccessibleDiffViewerPrev=e.AccessibleDiffViewerNext=e.RevertHunkOrSelection=e.ShowAllUnchangedRegions=e.CollapseAllUnchangedRegions=e.ExitCompareMove=e.SwitchSide=e.ToggleUseInlineViewWhenSpaceIsLimited=e.ToggleShowMovedCodeBlocks=e.ToggleCollapseUnchangedRegions=void 0,e.findDiffEditor=h,e.findFocusedDiffEditor=v;class o extends b.Action2{constructor(){super({id:"diffEditor.toggleCollapseUnchangedRegions",title:(0,_.localize2)(72,"Toggle Collapse Unchanged Regions"),icon:k.Codicon.map,toggled:n.ContextKeyExpr.has("config.diffEditor.hideUnchangedRegions.enabled"),precondition:n.ContextKeyExpr.has("isInDiffEditor"),menu:{when:n.ContextKeyExpr.has("isInDiffEditor"),id:b.MenuId.EditorTitle,order:22,group:"navigation"}})}run(L,...D){const T=L.get(p.IConfigurationService),M=!T.getValue("diffEditor.hideUnchangedRegions.enabled");T.updateValue("diffEditor.hideUnchangedRegions.enabled",M)}}e.ToggleCollapseUnchangedRegions=o;class t extends b.Action2{constructor(){super({id:"diffEditor.toggleShowMovedCodeBlocks",title:(0,_.localize2)(73,"Toggle Show Moved Code Blocks"),precondition:n.ContextKeyExpr.has("isInDiffEditor")})}run(L,...D){const T=L.get(p.IConfigurationService),M=!T.getValue("diffEditor.experimental.showMoves");T.updateValue("diffEditor.experimental.showMoves",M)}}e.ToggleShowMovedCodeBlocks=t;class i extends b.Action2{constructor(){super({id:"diffEditor.toggleUseInlineViewWhenSpaceIsLimited",title:(0,_.localize2)(74,"Toggle Use Inline View When Space Is Limited"),precondition:n.ContextKeyExpr.has("isInDiffEditor")})}run(L,...D){const T=L.get(p.IConfigurationService),M=!T.getValue("diffEditor.useInlineViewWhenSpaceIsLimited");T.updateValue("diffEditor.useInlineViewWhenSpaceIsLimited",M)}}e.ToggleUseInlineViewWhenSpaceIsLimited=i;const s=(0,_.localize2)(75,"Diff Editor");class g extends I.EditorAction2{constructor(){super({id:"diffEditor.switchSide",title:(0,_.localize2)(76,"Switch Side"),icon:k.Codicon.arrowSwap,precondition:n.ContextKeyExpr.has("isInDiffEditor"),f1:!0,category:s})}runEditorCommand(L,D,T){const M=v(L);if(M instanceof y.DiffEditorWidget){if(T&&T.dryRun)return{destinationSelection:M.mapToOtherSide().destinationSelection};M.switchSide()}}}e.SwitchSide=g;class c extends I.EditorAction2{constructor(){super({id:"diffEditor.exitCompareMove",title:(0,_.localize2)(77,"Exit Compare Move"),icon:k.Codicon.close,precondition:m.EditorContextKeys.comparingMovedCode,f1:!1,category:s,keybinding:{weight:1e4,primary:9}})}runEditorCommand(L,D,...T){const M=v(L);M instanceof y.DiffEditorWidget&&M.exitCompareMove()}}e.ExitCompareMove=c;class l extends I.EditorAction2{constructor(){super({id:"diffEditor.collapseAllUnchangedRegions",title:(0,_.localize2)(78,"Collapse All Unchanged Regions"),icon:k.Codicon.fold,precondition:n.ContextKeyExpr.has("isInDiffEditor"),f1:!0,category:s})}runEditorCommand(L,D,...T){const M=v(L);M instanceof y.DiffEditorWidget&&M.collapseAllUnchangedRegions()}}e.CollapseAllUnchangedRegions=l;class a extends I.EditorAction2{constructor(){super({id:"diffEditor.showAllUnchangedRegions",title:(0,_.localize2)(79,"Show All Unchanged Regions"),icon:k.Codicon.unfold,precondition:n.ContextKeyExpr.has("isInDiffEditor"),f1:!0,category:s})}runEditorCommand(L,D,...T){const M=v(L);M instanceof y.DiffEditorWidget&&M.showAllUnchangedRegions()}}e.ShowAllUnchangedRegions=a;class r extends b.Action2{constructor(){super({id:"diffEditor.revert",title:(0,_.localize2)(80,"Revert"),f1:!1,category:s})}run(L,D){const T=h(L,D.originalUri,D.modifiedUri);T instanceof y.DiffEditorWidget&&T.revertRangeMappings(D.mapping.innerChanges??[])}}e.RevertHunkOrSelection=r;const u=(0,_.localize2)(81,"Accessible Diff Viewer");class C extends b.Action2{static{this.id="editor.action.accessibleDiffViewer.next"}constructor(){super({id:C.id,title:(0,_.localize2)(82,"Go to Next Difference"),category:u,precondition:n.ContextKeyExpr.has("isInDiffEditor"),keybinding:{primary:65,weight:100},f1:!0})}run(L){v(L)?.accessibleDiffViewerNext()}}e.AccessibleDiffViewerNext=C;class f extends b.Action2{static{this.id="editor.action.accessibleDiffViewer.prev"}constructor(){super({id:f.id,title:(0,_.localize2)(83,"Go to Previous Difference"),category:u,precondition:n.ContextKeyExpr.has("isInDiffEditor"),keybinding:{primary:1089,weight:100},f1:!0})}run(L){v(L)?.accessibleDiffViewerPrev()}}e.AccessibleDiffViewerPrev=f;function h(S,L,D){return S.get(E.ICodeEditorService).listDiffEditors().find(A=>{const P=A.getModifiedEditor(),N=A.getOriginalEditor();return P&&P.getModel()?.uri.toString()===D.toString()&&N&&N.getModel()?.uri.toString()===L.toString()})||null}function v(S){const D=S.get(E.ICodeEditorService).listDiffEditors(),T=(0,d.getActiveElement)();if(T)for(const M of D){const A=M.getContainerDomNode();if(w(A,T))return M}return null}function w(S,L){let D=L;for(;D;){if(D===S)return!0;D=D.parentElement}return!1}}),define(ne[812],se([1,0,26,811,20,3,29,24,12,139]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,y.registerAction2)(k.ToggleCollapseUnchangedRegions),(0,y.registerAction2)(k.ToggleShowMovedCodeBlocks),(0,y.registerAction2)(k.ToggleUseInlineViewWhenSpaceIsLimited),y.MenuRegistry.appendMenuItem(y.MenuId.EditorTitle,{command:{id:new k.ToggleUseInlineViewWhenSpaceIsLimited().desc.id,title:(0,E.localize)(106,"Use Inline View When Space Is Limited"),toggled:_.ContextKeyExpr.has("config.diffEditor.useInlineViewWhenSpaceIsLimited"),precondition:_.ContextKeyExpr.has("isInDiffEditor")},order:11,group:"1_diff",when:_.ContextKeyExpr.and(I.EditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached,_.ContextKeyExpr.has("isInDiffEditor"))}),y.MenuRegistry.appendMenuItem(y.MenuId.EditorTitle,{command:{id:new k.ToggleShowMovedCodeBlocks().desc.id,title:(0,E.localize)(107,"Show Moved Code Blocks"),icon:d.Codicon.move,toggled:_.ContextKeyEqualsExpr.create("config.diffEditor.experimental.showMoves",!0),precondition:_.ContextKeyExpr.has("isInDiffEditor")},order:10,group:"1_diff",when:_.ContextKeyExpr.has("isInDiffEditor")}),(0,y.registerAction2)(k.RevertHunkOrSelection);for(const b of[{icon:d.Codicon.arrowRight,key:I.EditorContextKeys.diffEditorInlineMode.toNegated()},{icon:d.Codicon.discard,key:I.EditorContextKeys.diffEditorInlineMode}])y.MenuRegistry.appendMenuItem(y.MenuId.DiffEditorHunkToolbar,{command:{id:new k.RevertHunkOrSelection().desc.id,title:(0,E.localize)(108,"Revert Block"),icon:b.icon},when:_.ContextKeyExpr.and(I.EditorContextKeys.diffEditorModifiedWritable,b.key),order:5,group:"primary"}),y.MenuRegistry.appendMenuItem(y.MenuId.DiffEditorSelectionToolbar,{command:{id:new k.RevertHunkOrSelection().desc.id,title:(0,E.localize)(109,"Revert Selection"),icon:b.icon},when:_.ContextKeyExpr.and(I.EditorContextKeys.diffEditorModifiedWritable,b.key),order:5,group:"primary"});(0,y.registerAction2)(k.SwitchSide),(0,y.registerAction2)(k.ExitCompareMove),(0,y.registerAction2)(k.CollapseAllUnchangedRegions),(0,y.registerAction2)(k.ShowAllUnchangedRegions),y.MenuRegistry.appendMenuItem(y.MenuId.EditorTitle,{command:{id:k.AccessibleDiffViewerNext.id,title:(0,E.localize)(110,"Open Accessible Diff Viewer"),precondition:_.ContextKeyExpr.has("isInDiffEditor")},order:10,group:"2_diff",when:_.ContextKeyExpr.and(I.EditorContextKeys.accessibleDiffViewerVisible.negate(),_.ContextKeyExpr.has("isInDiffEditor"))}),m.CommandsRegistry.registerCommandAlias("editor.action.diffReview.next",k.AccessibleDiffViewerNext.id),(0,y.registerAction2)(k.AccessibleDiffViewerNext),m.CommandsRegistry.registerCommandAlias("editor.action.diffReview.prev",k.AccessibleDiffViewerPrev.id),(0,y.registerAction2)(k.AccessibleDiffViewerPrev)}),define(ne[420],se([1,0,5,258,26,2,21,92,112,286,124,218,29,7,365,12,154]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DiffEditorItemTemplate=e.TemplateData=void 0;class c{constructor(r,u){this.viewModel=r,this.deltaScrollVertical=u}getId(){return this.viewModel}}e.TemplateData=c;let l=class extends E.Disposable{constructor(r,u,C,f,h){super(),this._container=r,this._overflowWidgetsDomNode=u,this._workbenchUIElementFactory=C,this._instantiationService=f,this._viewModel=(0,m.observableValue)(this,void 0),this._collapsed=(0,y.derived)(this,S=>this._viewModel.read(S)?.collapsed.read(S)),this._editorContentHeight=(0,m.observableValue)(this,500),this.contentHeight=(0,y.derived)(this,S=>(this._collapsed.read(S)?0:this._editorContentHeight.read(S))+this._outerEditorHeight),this._modifiedContentWidth=(0,m.observableValue)(this,0),this._modifiedWidth=(0,m.observableValue)(this,0),this._originalContentWidth=(0,m.observableValue)(this,0),this._originalWidth=(0,m.observableValue)(this,0),this.maxScroll=(0,y.derived)(this,S=>{const L=this._modifiedContentWidth.read(S)-this._modifiedWidth.read(S),D=this._originalContentWidth.read(S)-this._originalWidth.read(S);return L>D?{maxScroll:L,width:this._modifiedWidth.read(S)}:{maxScroll:D,width:this._originalWidth.read(S)}}),this._elements=(0,d.h)("div.multiDiffEntry",[(0,d.h)("div.header@header",[(0,d.h)("div.header-content",[(0,d.h)("div.collapse-button@collapseButton"),(0,d.h)("div.file-path",[(0,d.h)("div.title.modified.show-file-icons@primaryPath",[]),(0,d.h)("div.status.deleted@status",["R"]),(0,d.h)("div.title.original.show-file-icons@secondaryPath",[])]),(0,d.h)("div.actions@actions")])]),(0,d.h)("div.editorParent",[(0,d.h)("div.editorContainer@editor")])]),this.editor=this._register(this._instantiationService.createInstance(b.DiffEditorWidget,this._elements.editor,{overflowWidgetsDomNode:this._overflowWidgetsDomNode},{})),this.isModifedFocused=(0,_.observableCodeEditor)(this.editor.getModifiedEditor()).isFocused,this.isOriginalFocused=(0,_.observableCodeEditor)(this.editor.getOriginalEditor()).isFocused,this.isFocused=(0,y.derived)(this,S=>this.isModifedFocused.read(S)||this.isOriginalFocused.read(S)),this._resourceLabel=this._workbenchUIElementFactory.createResourceLabel?this._register(this._workbenchUIElementFactory.createResourceLabel(this._elements.primaryPath)):void 0,this._resourceLabel2=this._workbenchUIElementFactory.createResourceLabel?this._register(this._workbenchUIElementFactory.createResourceLabel(this._elements.secondaryPath)):void 0,this._dataStore=this._register(new E.DisposableStore),this._headerHeight=40,this._lastScrollTop=-1,this._isSettingScrollTop=!1;const v=new k.Button(this._elements.collapseButton,{});this._register((0,y.autorun)(S=>{v.element.className="",v.icon=this._collapsed.read(S)?I.Codicon.chevronRight:I.Codicon.chevronDown})),this._register(v.onDidClick(()=>{this._viewModel.get()?.collapsed.set(!this._collapsed.get(),void 0)})),this._register((0,y.autorun)(S=>{this._elements.editor.style.display=this._collapsed.read(S)?"none":"block"})),this._register(this.editor.getModifiedEditor().onDidLayoutChange(S=>{const L=this.editor.getModifiedEditor().getLayoutInfo().contentWidth;this._modifiedWidth.set(L,void 0)})),this._register(this.editor.getOriginalEditor().onDidLayoutChange(S=>{const L=this.editor.getOriginalEditor().getLayoutInfo().contentWidth;this._originalWidth.set(L,void 0)})),this._register(this.editor.onDidContentSizeChange(S=>{(0,m.globalTransaction)(L=>{this._editorContentHeight.set(S.contentHeight,L),this._modifiedContentWidth.set(this.editor.getModifiedEditor().getContentWidth(),L),this._originalContentWidth.set(this.editor.getOriginalEditor().getContentWidth(),L)})})),this._register(this.editor.getOriginalEditor().onDidScrollChange(S=>{if(this._isSettingScrollTop||!S.scrollTopChanged||!this._data)return;const L=S.scrollTop-this._lastScrollTop;this._data.deltaScrollVertical(L)})),this._register((0,y.autorun)(S=>{const L=this._viewModel.read(S)?.isActive.read(S);this._elements.root.classList.toggle("active",L)})),this._container.appendChild(this._elements.root),this._outerEditorHeight=this._headerHeight,this._contextKeyService=this._register(h.createScoped(this._elements.actions));const w=this._register(this._instantiationService.createChild(new g.ServiceCollection([s.IContextKeyService,this._contextKeyService])));this._register(w.createInstance(n.MenuWorkbenchToolBar,this._elements.actions,o.MenuId.MultiDiffEditorFileToolbar,{actionRunner:this._register(new i.ActionRunnerWithContext(()=>this._viewModel.get()?.modifiedUri)),menuOptions:{shouldForwardArgs:!0},toolbarOptions:{primaryGroup:S=>S.startsWith("navigation")},actionViewItemProvider:(S,L)=>(0,p.createActionViewItem)(w,S,L)}))}setScrollLeft(r){this._modifiedContentWidth.get()-this._modifiedWidth.get()>this._originalContentWidth.get()-this._originalWidth.get()?this.editor.getModifiedEditor().setScrollLeft(r):this.editor.getOriginalEditor().setScrollLeft(r)}setData(r){this._data=r;function u(f){return{...f,scrollBeyondLastLine:!1,hideUnchangedRegions:{enabled:!0},scrollbar:{vertical:"hidden",horizontal:"hidden",handleMouseWheel:!1,useShadows:!1},renderOverviewRuler:!1,fixedOverflowWidgets:!0,overviewRulerBorder:!1}}if(!r){(0,m.globalTransaction)(f=>{this._viewModel.set(void 0,f),this.editor.setDiffModel(null,f),this._dataStore.clear()});return}const C=r.viewModel.documentDiffItem;if((0,m.globalTransaction)(f=>{this._resourceLabel?.setUri(r.viewModel.modifiedUri??r.viewModel.originalUri,{strikethrough:r.viewModel.modifiedUri===void 0});let h=!1,v=!1,w=!1,S="";r.viewModel.modifiedUri&&r.viewModel.originalUri&&r.viewModel.modifiedUri.path!==r.viewModel.originalUri.path?(S="R",h=!0):r.viewModel.modifiedUri?r.viewModel.originalUri||(S="A",w=!0):(S="D",v=!0),this._elements.status.classList.toggle("renamed",h),this._elements.status.classList.toggle("deleted",v),this._elements.status.classList.toggle("added",w),this._elements.status.innerText=S,this._resourceLabel2?.setUri(h?r.viewModel.originalUri:void 0,{strikethrough:!0}),this._dataStore.clear(),this._viewModel.set(r.viewModel,f),this.editor.setDiffModel(r.viewModel.diffEditorViewModelRef,f),this.editor.updateOptions(u(C.options??{}))}),C.onOptionsDidChange&&this._dataStore.add(C.onOptionsDidChange(()=>{this.editor.updateOptions(u(C.options??{}))})),r.viewModel.isAlive.recomputeInitiallyAndOnChange(this._dataStore,f=>{f||this.setData(void 0)}),r.viewModel.documentDiffItem.contextKeys)for(const[f,h]of Object.entries(r.viewModel.documentDiffItem.contextKeys))this._contextKeyService.createKey(f,h)}render(r,u,C,f){this._elements.root.style.visibility="visible",this._elements.root.style.top=`${r.start}px`,this._elements.root.style.height=`${r.length}px`,this._elements.root.style.width=`${u}px`,this._elements.root.style.position="absolute";const h=r.length-this._headerHeight,v=Math.max(0,Math.min(f.start-r.start,h));this._elements.header.style.transform=`translateY(${v}px)`,(0,m.globalTransaction)(w=>{this.editor.layout({width:u-2*8-2*1,height:r.length-this._outerEditorHeight})});try{this._isSettingScrollTop=!0,this._lastScrollTop=C,this.editor.getOriginalEditor().setScrollTop(C)}finally{this._isSettingScrollTop=!1}this._elements.header.classList.toggle("shadow",v>0||C>0),this._elements.header.classList.toggle("collapsed",v===h)}hide(){this._elements.root.style.top="-100000px",this._elements.root.style.visibility="hidden"}};e.DiffEditorItemTemplate=l,e.DiffEditorItemTemplate=l=ke([ce(3,t.IInstantiationService),ce(4,s.IContextKeyService)],l)}),define(ne[813],se([1,0,5,86,13,67,8,2,21,92,163,88,68,23,20,12,7,154,420,553,3,502]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MultiDiffEditorWidgetImpl=void 0;let u=class extends m.Disposable{constructor(h,v,w,S,L,D){super(),this._element=h,this._dimension=v,this._viewModel=w,this._workbenchUIElementFactory=S,this._parentContextKeyService=L,this._parentInstantiationService=D,this._scrollableElements=(0,d.h)("div.scrollContent",[(0,d.h)("div@content",{style:{overflow:"hidden"}}),(0,d.h)("div.monaco-editor@overflowWidgetsDomNode",{})]),this._scrollable=this._register(new p.Scrollable({forceIntegerValues:!1,scheduleAtNextAnimationFrame:M=>(0,d.scheduleAtNextAnimationFrame)((0,d.getWindow)(this._element),M),smoothScrollDuration:100})),this._scrollableElement=this._register(new k.SmoothScrollableElement(this._scrollableElements.root,{vertical:1,horizontal:1,useShadows:!1},this._scrollable)),this._elements=(0,d.h)("div.monaco-component.multiDiffEditor",{},[(0,d.h)("div",{},[this._scrollableElement.getDomNode()]),(0,d.h)("div.placeholder@placeholder",{},[(0,d.h)("div",[(0,r.localize)(132,"No Changed Files")])])]),this._sizeObserver=this._register(new n.ObservableElementSizeObserver(this._element,void 0)),this._objectPool=this._register(new a.ObjectPool(M=>{const A=this._instantiationService.createInstance(l.DiffEditorItemTemplate,this._scrollableElements.content,this._scrollableElements.overflowWidgetsDomNode,this._workbenchUIElementFactory);return A.setData(M),A})),this.scrollTop=(0,_.observableFromEvent)(this,this._scrollableElement.onScroll,()=>this._scrollableElement.getScrollPosition().scrollTop),this.scrollLeft=(0,_.observableFromEvent)(this,this._scrollableElement.onScroll,()=>this._scrollableElement.getScrollPosition().scrollLeft),this._viewItemsInfo=(0,_.derivedWithStore)(this,(M,A)=>{const P=this._viewModel.read(M);if(!P)return{items:[],getItem:x=>{throw new y.BugIndicatingError}};const N=P.items.read(M),O=new Map;return{items:N.map(x=>{const W=A.add(new C(x,this._objectPool,this.scrollLeft,q=>{this._scrollableElement.setScrollPosition({scrollTop:this._scrollableElement.getScrollPosition().scrollTop+q})})),V=this._lastDocStates?.[W.getKey()];return V&&(0,b.transaction)(q=>{W.setViewState(V,q)}),O.set(x,W),W}),getItem:x=>O.get(x)}}),this._viewItems=this._viewItemsInfo.map(this,M=>M.items),this._spaceBetweenPx=0,this._totalHeight=this._viewItems.map(this,(M,A)=>M.reduce((P,N)=>P+N.contentHeight.read(A)+this._spaceBetweenPx,0)),this._contextKeyService=this._register(this._parentContextKeyService.createScoped(this._element)),this._instantiationService=this._register(this._parentInstantiationService.createChild(new c.ServiceCollection([s.IContextKeyService,this._contextKeyService]))),this._lastDocStates={},this._contextKeyService.createKey(i.EditorContextKeys.inMultiDiffEditor.key,!0),this._register((0,_.autorunWithStore)((M,A)=>{const P=this._viewModel.read(M);if(P&&P.contextKeys)for(const[N,O]of Object.entries(P.contextKeys)){const F=this._contextKeyService.createKey(N,void 0);F.set(O),A.add((0,m.toDisposable)(()=>F.reset()))}}));const T=this._parentContextKeyService.createKey(i.EditorContextKeys.multiDiffEditorAllCollapsed.key,!1);this._register((0,_.autorun)(M=>{const A=this._viewModel.read(M);if(A){const P=A.items.read(M).every(N=>N.collapsed.read(M));T.set(P)}})),this._register((0,_.autorun)(M=>{const A=this._dimension.read(M);this._sizeObserver.observe(A)})),this._register((0,_.autorun)(M=>{const A=this._viewItems.read(M);this._elements.placeholder.classList.toggle("visible",A.length===0)})),this._scrollableElements.content.style.position="relative",this._register((0,_.autorun)(M=>{const A=this._sizeObserver.height.read(M);this._scrollableElements.root.style.height=`${A}px`;const P=this._totalHeight.read(M);this._scrollableElements.content.style.height=`${P}px`;const N=this._sizeObserver.width.read(M);let O=N;const F=this._viewItems.read(M),x=(0,E.findFirstMax)(F,(0,I.compareBy)(W=>W.maxScroll.read(M).maxScroll,I.numberComparator));if(x){const W=x.maxScroll.read(M);O=N+W.maxScroll}this._scrollableElement.setScrollDimensions({width:N,height:A,scrollHeight:P,scrollWidth:O})})),h.replaceChildren(this._elements.root),this._register((0,m.toDisposable)(()=>{h.replaceChildren()})),this._register(this._register((0,_.autorun)(M=>{(0,b.globalTransaction)(A=>{this.render(M)})})))}render(h){const v=this.scrollTop.read(h);let w=0,S=0,L=0;const D=this._sizeObserver.height.read(h),T=o.OffsetRange.ofStartAndLength(v,D),M=this._sizeObserver.width.read(h);for(const A of this._viewItems.read(h)){const P=A.contentHeight.read(h),N=Math.min(P,D),O=o.OffsetRange.ofStartAndLength(S,N),F=o.OffsetRange.ofStartAndLength(L,P);if(F.isBefore(T))w-=P-N,A.hide();else if(F.isAfter(T))A.hide();else{const x=Math.max(0,Math.min(T.start-F.start,P-N));w-=x;const W=o.OffsetRange.ofStartAndLength(v+w,D);A.render(O,x,M,W)}S+=N+this._spaceBetweenPx,L+=P+this._spaceBetweenPx}this._scrollableElements.content.style.transform=`translateY(${-(v+w)}px)`}};e.MultiDiffEditorWidgetImpl=u,e.MultiDiffEditorWidgetImpl=u=ke([ce(4,s.IContextKeyService),ce(5,g.IInstantiationService)],u);class C extends m.Disposable{constructor(h,v,w,S){super(),this.viewModel=h,this._objectPool=v,this._scrollLeft=w,this._deltaScrollVertical=S,this._templateRef=this._register((0,b.disposableObservableValue)(this,void 0)),this.contentHeight=(0,_.derived)(this,L=>this._templateRef.read(L)?.object.contentHeight?.read(L)??this.viewModel.lastTemplateData.read(L).contentHeight),this.maxScroll=(0,_.derived)(this,L=>this._templateRef.read(L)?.object.maxScroll.read(L)??{maxScroll:0,scrollWidth:0}),this.template=(0,_.derived)(this,L=>this._templateRef.read(L)?.object),this._isHidden=(0,_.observableValue)(this,!1),this._isFocused=(0,_.derived)(this,L=>this.template.read(L)?.isFocused.read(L)??!1),this.viewModel.setIsFocused(this._isFocused,void 0),this._register((0,_.autorun)(L=>{const D=this._scrollLeft.read(L);this._templateRef.read(L)?.object.setScrollLeft(D)})),this._register((0,_.autorun)(L=>{const D=this._templateRef.read(L);!D||!this._isHidden.read(L)||D.object.isFocused.read(L)||this._clear()}))}dispose(){this._clear(),super.dispose()}toString(){return`VirtualViewItem(${this.viewModel.documentDiffItem.modified?.uri.toString()})`}getKey(){return this.viewModel.getKey()}setViewState(h,v){this.viewModel.collapsed.set(h.collapsed,v),this._updateTemplateData(v);const w=this.viewModel.lastTemplateData.get(),S=h.selections?.map(t.Selection.liftSelection);this.viewModel.lastTemplateData.set({...w,selections:S},v);const L=this._templateRef.get();L&&S&&L.object.editor.setSelections(S)}_updateTemplateData(h){const v=this._templateRef.get();v&&this.viewModel.lastTemplateData.set({contentHeight:v.object.contentHeight.get(),selections:v.object.editor.getSelections()??void 0},h)}_clear(){const h=this._templateRef.get();h&&(0,b.transaction)(v=>{this._updateTemplateData(v),h.object.hide(),this._templateRef.set(void 0,v)})}hide(){this._isHidden.set(!0,void 0)}render(h,v,w,S){this._isHidden.set(!1,void 0);let L=this._templateRef.get();if(!L){L=this._objectPool.getUnusedObj(new l.TemplateData(this.viewModel,this._deltaScrollVertical)),this._templateRef.set(L,void 0);const D=this.viewModel.lastTemplateData.get().selections;D&&L.object.editor.setSelections(D)}L.object.render(h,w,v,S)}}}),define(ne[814],se([1,0,2,21,171,813,7,420,756]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MultiDiffEditorWidget=void 0;let _=class extends d.Disposable{constructor(p,n,o){super(),this._element=p,this._workbenchUIElementFactory=n,this._instantiationService=o,this._dimension=(0,k.observableValue)(this,void 0),this._viewModel=(0,k.observableValue)(this,void 0),this._widgetImpl=(0,k.derivedWithStore)(this,(t,i)=>((0,I.readHotReloadableExport)(m.DiffEditorItemTemplate,t),i.add(this._instantiationService.createInstance((0,I.readHotReloadableExport)(E.MultiDiffEditorWidgetImpl,t),this._element,this._dimension,this._viewModel,this._workbenchUIElementFactory)))),this._register((0,k.recomputeInitiallyAndOnChange)(this._widgetImpl))}};e.MultiDiffEditorWidget=_,e.MultiDiffEditorWidget=_=ke([ce(2,y.IInstantiationService)],_)}),define(ne[815],se([1,0,14,2,15,9,4,23,20,40,35,3,29,32,25,504]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BracketMatchingController=void 0;const s=(0,t.registerColor)("editorOverviewRuler.bracketMatchForeground","#A0A0A0",n.localize(716,"Overview ruler marker color for matching brackets."));class g extends I.EditorAction{constructor(){super({id:"editor.action.jumpToBracket",label:n.localize(717,"Go to Bracket"),alias:"Go to Bracket",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.editorTextFocus,primary:3165,weight:100}})}run(C,f){r.get(f)?.jumpToBracket()}}class c extends I.EditorAction{constructor(){super({id:"editor.action.selectToBracket",label:n.localize(718,"Select to Bracket"),alias:"Select to Bracket",precondition:void 0,metadata:{description:n.localize2(721,"Select the text inside and including the brackets or curly braces"),args:[{name:"args",schema:{type:"object",properties:{selectBrackets:{type:"boolean",default:!0}}}}]}})}run(C,f,h){let v=!0;h&&h.selectBrackets===!1&&(v=!1),r.get(f)?.selectToBracket(v)}}class l extends I.EditorAction{constructor(){super({id:"editor.action.removeBrackets",label:n.localize(719,"Remove Brackets"),alias:"Remove Brackets",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.editorTextFocus,primary:2561,weight:100}})}run(C,f){r.get(f)?.removeBrackets(this.id)}}class a{constructor(C,f,h){this.position=C,this.brackets=f,this.options=h}}class r extends k.Disposable{static{this.ID="editor.contrib.bracketMatchingController"}static get(C){return C.getContribution(r.ID)}constructor(C){super(),this._editor=C,this._lastBracketsData=[],this._lastVersionId=0,this._decorations=this._editor.createDecorationsCollection(),this._updateBracketsSoon=this._register(new d.RunOnceScheduler(()=>this._updateBrackets(),50)),this._matchBrackets=this._editor.getOption(72),this._updateBracketsSoon.schedule(),this._register(C.onDidChangeCursorPosition(f=>{this._matchBrackets!=="never"&&this._updateBracketsSoon.schedule()})),this._register(C.onDidChangeModelContent(f=>{this._updateBracketsSoon.schedule()})),this._register(C.onDidChangeModel(f=>{this._lastBracketsData=[],this._updateBracketsSoon.schedule()})),this._register(C.onDidChangeModelLanguageConfiguration(f=>{this._lastBracketsData=[],this._updateBracketsSoon.schedule()})),this._register(C.onDidChangeConfiguration(f=>{f.hasChanged(72)&&(this._matchBrackets=this._editor.getOption(72),this._decorations.clear(),this._lastBracketsData=[],this._lastVersionId=0,this._updateBracketsSoon.schedule())})),this._register(C.onDidBlurEditorWidget(()=>{this._updateBracketsSoon.schedule()})),this._register(C.onDidFocusEditorWidget(()=>{this._updateBracketsSoon.schedule()}))}jumpToBracket(){if(!this._editor.hasModel())return;const C=this._editor.getModel(),f=this._editor.getSelections().map(h=>{const v=h.getStartPosition(),w=C.bracketPairs.matchBracket(v);let S=null;if(w)w[0].containsPosition(v)&&!w[1].containsPosition(v)?S=w[1].getStartPosition():w[1].containsPosition(v)&&(S=w[0].getStartPosition());else{const L=C.bracketPairs.findEnclosingBrackets(v);if(L)S=L[1].getStartPosition();else{const D=C.bracketPairs.findNextBracket(v);D&&D.range&&(S=D.range.getStartPosition())}}return S?new m.Selection(S.lineNumber,S.column,S.lineNumber,S.column):new m.Selection(v.lineNumber,v.column,v.lineNumber,v.column)});this._editor.setSelections(f),this._editor.revealRange(f[0])}selectToBracket(C){if(!this._editor.hasModel())return;const f=this._editor.getModel(),h=[];this._editor.getSelections().forEach(v=>{const w=v.getStartPosition();let S=f.bracketPairs.matchBracket(w);if(!S&&(S=f.bracketPairs.findEnclosingBrackets(w),!S)){const T=f.bracketPairs.findNextBracket(w);T&&T.range&&(S=f.bracketPairs.matchBracket(T.range.getStartPosition()))}let L=null,D=null;if(S){S.sort(y.Range.compareRangesUsingStarts);const[T,M]=S;if(L=C?T.getStartPosition():T.getEndPosition(),D=C?M.getEndPosition():M.getStartPosition(),M.containsPosition(w)){const A=L;L=D,D=A}}L&&D&&h.push(new m.Selection(L.lineNumber,L.column,D.lineNumber,D.column))}),h.length>0&&(this._editor.setSelections(h),this._editor.revealRange(h[0]))}removeBrackets(C){if(!this._editor.hasModel())return;const f=this._editor.getModel();this._editor.getSelections().forEach(h=>{const v=h.getPosition();let w=f.bracketPairs.matchBracket(v);w||(w=f.bracketPairs.findEnclosingBrackets(v)),w&&(this._editor.pushUndoStop(),this._editor.executeEdits(C,[{range:w[0],text:""},{range:w[1],text:""}]),this._editor.pushUndoStop())})}static{this._DECORATION_OPTIONS_WITH_OVERVIEW_RULER=p.ModelDecorationOptions.register({description:"bracket-match-overview",stickiness:1,className:"bracket-match",overviewRuler:{color:(0,i.themeColorFromId)(s),position:b.OverviewRulerLane.Center}})}static{this._DECORATION_OPTIONS_WITHOUT_OVERVIEW_RULER=p.ModelDecorationOptions.register({description:"bracket-match-no-overview",stickiness:1,className:"bracket-match"})}_updateBrackets(){if(this._matchBrackets==="never")return;this._recomputeBrackets();const C=[];let f=0;for(const h of this._lastBracketsData){const v=h.brackets;v&&(C[f++]={range:v[0],options:h.options},C[f++]={range:v[1],options:h.options})}this._decorations.set(C)}_recomputeBrackets(){if(!this._editor.hasModel()||!this._editor.hasWidgetFocus()){this._lastBracketsData=[],this._lastVersionId=0;return}const C=this._editor.getSelections();if(C.length>100){this._lastBracketsData=[],this._lastVersionId=0;return}const f=this._editor.getModel(),h=f.getVersionId();let v=[];this._lastVersionId===h&&(v=this._lastBracketsData);const w=[];let S=0;for(let A=0,P=C.length;A1&&w.sort(E.Position.compare);const L=[];let D=0,T=0;const M=v.length;for(let A=0,P=w.length;A{const L=this._editor.getModel();(this.state.type!==1||!L||this.state.editorPosition.lineNumber>=L.getLineCount())&&this.hide(),(this.gutterState.type!==1||!L||this.gutterState.editorPosition.lineNumber>=L.getLineCount())&&this.gutterHide()})),this._register(d.addStandardDisposableGenericMouseDownListener(this._domNode,S=>{if(this.state.type!==1)return;this._editor.focus(),S.preventDefault();const{top:L,height:D}=d.getDomNodePagePosition(this._domNode),T=this._editor.getOption(67);let M=Math.floor(T/3);this.state.widgetPosition.position!==null&&this.state.widgetPosition.position.lineNumber{(S.buttons&1)===1&&this.hide()})),this._register(E.Event.runAndSubscribe(this._keybindingService.onDidUpdateKeybindings,()=>{this._preferredKbLabel=this._keybindingService.lookupKeybinding(n.autoFixCommandId)?.getLabel()??void 0,this._quickFixKbLabel=this._keybindingService.lookupKeybinding(n.quickFixCommandId)?.getLabel()??void 0,this._updateLightBulbTitleAndIcon()})),this._register(this._editor.onMouseDown(async S=>{if(!S.target.element||!this.lightbulbClasses.some(A=>S.target.element&&S.target.element.classList.contains(A))||this.gutterState.type!==1)return;this._editor.focus();const{top:L,height:D}=d.getDomNodePagePosition(S.target.element),T=this._editor.getOption(67);let M=Math.floor(T/3);this.gutterState.widgetPosition.position!==null&&this.gutterState.widgetPosition.position.lineNumber22,W=Y=>Y>2&&this._editor.getTopForLineNumber(Y)===this._editor.getTopForLineNumber(Y-1),V=this._editor.getLineDecorations(M);let q=!1;if(V)for(const Y of V){const G=Y.options.glyphMarginClassName;if(G&&!this.lightbulbClasses.some(K=>G.includes(K))){q=!0;break}}let H=M,z=1;if(!x){const Y=G=>{const K=T.getLineContent(G);return/^\s*$|^\s+/.test(K)||K.length<=z};if(M>1&&!W(M-1)){const G=T.getLineCount(),K=M===G,R=M>1&&Y(M-1),J=!K&&Y(M+1),ie=Y(M),ue=!J&&!R;if(!J&&!R&&!q)return this.gutterState=new C.Showing(v,w,S,{position:{lineNumber:H,column:z},preference:g._posPref}),this.renderGutterLightbub(),this.hide();R||K||R&&!ie?H-=1:(J||ue&&ie)&&(H+=1)}else if(M===1&&(M===T.getLineCount()||!Y(M+1)&&!Y(M)))if(this.gutterState=new C.Showing(v,w,S,{position:{lineNumber:H,column:z},preference:g._posPref}),q)this.gutterHide();else return this.renderGutterLightbub(),this.hide();else if(M{this._gutterDecorationID=w.addDecoration(new s.Range(v,0,v,0),this.gutterDecoration)})}_removeGutterDecoration(v){this._editor.changeDecorations(w=>{w.removeDecoration(v),this._gutterDecorationID=void 0})}_updateGutterDecoration(v,w){this._editor.changeDecorations(S=>{S.changeDecoration(v,new s.Range(w,0,w,0)),S.changeDecorationOptions(v,this.gutterDecoration)})}_updateLightbulbTitle(v,w){this.state.type===1&&(w?this.title=o.localize(790,"Run: {0}",this.state.actions.validActions[0].action.title):v&&this._preferredKbLabel?this.title=o.localize(791,"Show Code Actions. Preferred Quick Fix Available ({0})",this._preferredKbLabel):!v&&this._quickFixKbLabel?this.title=o.localize(792,"Show Code Actions ({0})",this._quickFixKbLabel):v||(this.title=o.localize(793,"Show Code Actions")))}set title(v){this._domNode.title=v}};e.LightBulbWidget=f,e.LightBulbWidget=f=g=ke([ce(1,t.IKeybindingService)],f)}),define(ne[287],se([1,0,5,46,8,98,2,9,35,17,157,733,757,421,184,3,760,24,28,12,7,108,96,32,97,25,134,408,91,63]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D){"use strict";var T;Object.defineProperty(e,"__esModule",{value:!0}),e.CodeActionController=void 0;const M="quickfix-edit-highlight";let A=class extends y.Disposable{static{T=this}static{this.ID="editor.contrib.codeActionController"}static get(N){return N.getContribution(T.ID)}constructor(N,O,F,x,W,V,q,H,z,U,j){super(),this._commandService=q,this._configurationService=H,this._actionWidgetService=z,this._instantiationService=U,this._telemetryService=j,this._activeCodeActions=this._register(new y.MutableDisposable),this._showDisabled=!1,this._disposed=!1,this._editor=N,this._model=this._register(new S.CodeActionModel(this._editor,W.codeActionProvider,O,F,V,H,this._telemetryService)),this._register(this._model.onDidChangeState(Y=>this.update(Y))),this._lightBulbWidget=new E.Lazy(()=>{const Y=this._editor.getContribution(t.LightBulbWidget.ID);return Y&&this._register(Y.onClick(G=>this.showCodeActionsFromLightbulb(G.actions,G))),Y}),this._resolver=x.createInstance(n.CodeActionKeybindingResolver),this._register(this._editor.onDidLayoutChange(()=>this._actionWidgetService.hide()))}dispose(){this._disposed=!0,super.dispose()}async showCodeActionsFromLightbulb(N,O){if(N.allAIFixes&&N.validActions.length===1){const F=N.validActions[0],x=F.action.command;x&&x.id==="inlineChat.start"&&x.arguments&&x.arguments.length>=1&&(x.arguments[0]={...x.arguments[0],autoSend:!1}),await this._applyCodeAction(F,!1,!1,p.ApplyCodeActionReason.FromAILightbulb);return}await this.showCodeActionList(N,O,{includeDisabledActions:!1,fromLightbulb:!0})}showCodeActions(N,O,F){return this.showCodeActionList(O,F,{includeDisabledActions:!1,fromLightbulb:!1})}manualTriggerAtCurrentPosition(N,O,F,x){if(!this._editor.hasModel())return;i.MessageController.get(this._editor)?.closeMessage();const W=this._editor.getPosition();this._trigger({type:1,triggerAction:O,filter:F,autoApply:x,context:{notAvailableMessage:N,position:W}})}_trigger(N){return this._model.trigger(N)}async _applyCodeAction(N,O,F,x){try{await this._instantiationService.invokeFunction(p.applyCodeAction,N,x,{preview:F,editor:this._editor})}finally{O&&this._trigger({type:2,triggerAction:w.CodeActionTriggerSource.QuickFix,filter:{}})}}hideLightBulbWidget(){this._lightBulbWidget.rawValue?.hide(),this._lightBulbWidget.rawValue?.gutterHide()}async update(N){if(N.type!==1){this.hideLightBulbWidget();return}let O;try{O=await N.actions}catch(x){(0,I.onUnexpectedError)(x);return}if(!(this._disposed||this._editor.getSelection()?.startLineNumber!==N.position.lineNumber))if(this._lightBulbWidget.value?.update(O,N.trigger,N.position),N.trigger.type===1){if(N.trigger.filter?.include){const W=this.tryGetValidActionToApply(N.trigger,O);if(W){try{this.hideLightBulbWidget(),await this._applyCodeAction(W,!1,!1,p.ApplyCodeActionReason.FromCodeActions)}finally{O.dispose()}return}if(N.trigger.context){const V=this.getInvalidActionThatWouldHaveBeenApplied(N.trigger,O);if(V&&V.action.disabled){i.MessageController.get(this._editor)?.showMessage(V.action.disabled,N.trigger.context.position),O.dispose();return}}}const x=!!N.trigger.filter?.include;if(N.trigger.context&&(!O.allActions.length||!x&&!O.validActions.length)){i.MessageController.get(this._editor)?.showMessage(N.trigger.context.notAvailableMessage,N.trigger.context.position),this._activeCodeActions.value=O,O.dispose();return}this._activeCodeActions.value=O,this.showCodeActionList(O,this.toCoords(N.position),{includeDisabledActions:x,fromLightbulb:!1})}else this._actionWidgetService.isVisible?O.dispose():this._activeCodeActions.value=O}getInvalidActionThatWouldHaveBeenApplied(N,O){if(O.allActions.length&&(N.autoApply==="first"&&O.validActions.length===0||N.autoApply==="ifSingle"&&O.allActions.length===1))return O.allActions.find(({action:F})=>F.disabled)}tryGetValidActionToApply(N,O){if(O.validActions.length&&(N.autoApply==="first"&&O.validActions.length>0||N.autoApply==="ifSingle"&&O.validActions.length===1))return O.validActions[0]}static{this.DECORATION=_.ModelDecorationOptions.register({description:"quickfix-highlight",className:M})}async showCodeActionList(N,O,F){const x=this._editor.createDecorationsCollection(),W=this._editor.getDomNode();if(!W)return;const V=F.includeDisabledActions&&(this._showDisabled||N.validActions.length===0)?N.allActions:N.validActions;if(!V.length)return;const q=m.Position.isIPosition(O)?this.toCoords(O):O,H={onSelect:async(z,U)=>{this._applyCodeAction(z,!0,!!U,F.fromLightbulb?p.ApplyCodeActionReason.FromAILightbulb:p.ApplyCodeActionReason.FromCodeActions),this._actionWidgetService.hide(!1),x.clear()},onHide:z=>{this._editor?.focus(),x.clear()},onHover:async(z,U)=>{if(U.isCancellationRequested)return;let j=!1;const Y=z.action.kind;if(Y){const G=new L.HierarchicalKind(Y);j=[w.CodeActionKind.RefactorExtract,w.CodeActionKind.RefactorInline,w.CodeActionKind.RefactorRewrite,w.CodeActionKind.RefactorMove,w.CodeActionKind.Source].some(R=>R.contains(G))}return{canPreview:j||!!z.action.edit?.edits.length}},onFocus:z=>{if(z&&z.action){const U=z.action.ranges,j=z.action.diagnostics;if(x.clear(),U&&U.length>0){const Y=j&&j?.length>1?j.map(G=>({range:G,options:T.DECORATION})):U.map(G=>({range:G,options:T.DECORATION}));x.set(Y)}else if(j&&j.length>0){const Y=j.map(K=>({range:K,options:T.DECORATION}));x.set(Y);const G=j[0];if(G.startLineNumber&&G.startColumn){const K=this._editor.getModel()?.getWordAtPosition({lineNumber:G.startLineNumber,column:G.startColumn})?.word;k.status((0,s.localize)(774,"Context: {0} at line {1} and column {2}.",K,G.startLineNumber,G.startColumn))}}}else x.clear()}};this._actionWidgetService.show("codeActionWidget",!0,(0,o.toMenuItems)(V,this._shouldShowHeaders(),this._resolver.getResolver()),H,q,W,this._getActionBarActions(N,O,F))}toCoords(N){if(!this._editor.hasModel())return{x:0,y:0};this._editor.revealPosition(N,1),this._editor.render();const O=this._editor.getScrolledVisiblePosition(N),F=(0,d.getDomNodePagePosition)(this._editor.getDomNode()),x=F.left+O.left,W=F.top+O.top+O.height;return{x,y:W}}_shouldShowHeaders(){const N=this._editor?.getModel();return this._configurationService.getValue("editor.codeActionWidget.showHeaders",{resource:N?.uri})}_getActionBarActions(N,O,F){if(F.fromLightbulb)return[];const x=N.documentation.map(W=>({id:W.id,label:W.title,tooltip:W.tooltip??"",class:void 0,enabled:!0,run:()=>this._commandService.executeCommand(W.id,...W.arguments??[])}));return F.includeDisabledActions&&N.validActions.length>0&&N.allActions.length!==N.validActions.length&&x.push(this._showDisabled?{id:"hideMoreActions",label:(0,s.localize)(775,"Hide Disabled"),enabled:!0,tooltip:"",class:void 0,run:()=>(this._showDisabled=!1,this.showCodeActionList(N,O,F))}:{id:"showMoreActions",label:(0,s.localize)(776,"Show Disabled"),enabled:!0,tooltip:"",class:void 0,run:()=>(this._showDisabled=!0,this.showCodeActionList(N,O,F))}),x}};e.CodeActionController=A,e.CodeActionController=A=T=ke([ce(1,u.IMarkerService),ce(2,a.IContextKeyService),ce(3,r.IInstantiationService),ce(4,b.ILanguageFeaturesService),ce(5,C.IEditorProgressService),ce(6,c.ICommandService),ce(7,l.IConfigurationService),ce(8,g.IActionWidgetService),ce(9,r.IInstantiationService),ce(10,D.ITelemetryService)],A),(0,v.registerThemingParticipant)((P,N)=>{((x,W)=>{W&&N.addRule(`.monaco-editor ${x} { background-color: ${W}; }`)})(".quickfix-edit-highlight",P.getColor(f.editorFindMatchHighlight));const F=P.getColor(f.editorFindMatchHighlightBorder);F&&N.addRule(`.monaco-editor .quickfix-edit-highlight { border: 1px ${(0,h.isHighContrast)(P.type)?"dotted":"solid"} ${F}; box-sizing: border-box; }`)})}),define(ne[816],se([1,0,91,11,15,20,157,3,12,134,287,408]),function(oe,e,d,k,I,E,y,m,_,b,p,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.AutoFixAction=e.FixAllAction=e.OrganizeImportsAction=e.SourceAction=e.RefactorAction=e.CodeActionCommand=e.QuickFixAction=void 0;function o(C){return _.ContextKeyExpr.regex(n.SUPPORTED_CODE_ACTIONS.keys()[0],new RegExp("(\\s|^)"+(0,k.escapeRegExpCharacters)(C.value)+"\\b"))}const t={type:"object",defaultSnippets:[{body:{kind:""}}],properties:{kind:{type:"string",description:m.localize(743,"Kind of the code action to run.")},apply:{type:"string",description:m.localize(744,"Controls when the returned actions are applied."),default:"ifSingle",enum:["first","ifSingle","never"],enumDescriptions:[m.localize(745,"Always apply the first returned code action."),m.localize(746,"Apply the first returned code action if it is the only one."),m.localize(747,"Do not apply the returned code actions.")]},preferred:{type:"boolean",default:!1,description:m.localize(748,"Controls if only preferred code actions should be returned.")}}};function i(C,f,h,v,w=b.CodeActionTriggerSource.Default){C.hasModel()&&p.CodeActionController.get(C)?.manualTriggerAtCurrentPosition(f,w,h,v)}class s extends I.EditorAction{constructor(){super({id:y.quickFixCommandId,label:m.localize(749,"Quick Fix..."),alias:"Quick Fix...",precondition:_.ContextKeyExpr.and(E.EditorContextKeys.writable,E.EditorContextKeys.hasCodeActionsProvider),kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:2137,weight:100}})}run(f,h){return i(h,m.localize(750,"No code actions available"),void 0,void 0,b.CodeActionTriggerSource.QuickFix)}}e.QuickFixAction=s;class g extends I.EditorCommand{constructor(){super({id:y.codeActionCommandId,precondition:_.ContextKeyExpr.and(E.EditorContextKeys.writable,E.EditorContextKeys.hasCodeActionsProvider),metadata:{description:"Trigger a code action",args:[{name:"args",schema:t}]}})}runEditorCommand(f,h,v){const w=b.CodeActionCommandArgs.fromUser(v,{kind:d.HierarchicalKind.Empty,apply:"ifSingle"});return i(h,typeof v?.kind=="string"?w.preferred?m.localize(751,"No preferred code actions for '{0}' available",v.kind):m.localize(752,"No code actions for '{0}' available",v.kind):w.preferred?m.localize(753,"No preferred code actions available"):m.localize(754,"No code actions available"),{include:w.kind,includeSourceActions:!0,onlyIncludePreferredActions:w.preferred},w.apply)}}e.CodeActionCommand=g;class c extends I.EditorAction{constructor(){super({id:y.refactorCommandId,label:m.localize(755,"Refactor..."),alias:"Refactor...",precondition:_.ContextKeyExpr.and(E.EditorContextKeys.writable,E.EditorContextKeys.hasCodeActionsProvider),kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:3120,mac:{primary:1328},weight:100},contextMenuOpts:{group:"1_modification",order:2,when:_.ContextKeyExpr.and(E.EditorContextKeys.writable,o(b.CodeActionKind.Refactor))},metadata:{description:"Refactor...",args:[{name:"args",schema:t}]}})}run(f,h,v){const w=b.CodeActionCommandArgs.fromUser(v,{kind:b.CodeActionKind.Refactor,apply:"never"});return i(h,typeof v?.kind=="string"?w.preferred?m.localize(756,"No preferred refactorings for '{0}' available",v.kind):m.localize(757,"No refactorings for '{0}' available",v.kind):w.preferred?m.localize(758,"No preferred refactorings available"):m.localize(759,"No refactorings available"),{include:b.CodeActionKind.Refactor.contains(w.kind)?w.kind:d.HierarchicalKind.None,onlyIncludePreferredActions:w.preferred},w.apply,b.CodeActionTriggerSource.Refactor)}}e.RefactorAction=c;class l extends I.EditorAction{constructor(){super({id:y.sourceActionCommandId,label:m.localize(760,"Source Action..."),alias:"Source Action...",precondition:_.ContextKeyExpr.and(E.EditorContextKeys.writable,E.EditorContextKeys.hasCodeActionsProvider),contextMenuOpts:{group:"1_modification",order:2.1,when:_.ContextKeyExpr.and(E.EditorContextKeys.writable,o(b.CodeActionKind.Source))},metadata:{description:"Source Action...",args:[{name:"args",schema:t}]}})}run(f,h,v){const w=b.CodeActionCommandArgs.fromUser(v,{kind:b.CodeActionKind.Source,apply:"never"});return i(h,typeof v?.kind=="string"?w.preferred?m.localize(761,"No preferred source actions for '{0}' available",v.kind):m.localize(762,"No source actions for '{0}' available",v.kind):w.preferred?m.localize(763,"No preferred source actions available"):m.localize(764,"No source actions available"),{include:b.CodeActionKind.Source.contains(w.kind)?w.kind:d.HierarchicalKind.None,includeSourceActions:!0,onlyIncludePreferredActions:w.preferred},w.apply,b.CodeActionTriggerSource.SourceAction)}}e.SourceAction=l;class a extends I.EditorAction{constructor(){super({id:y.organizeImportsCommandId,label:m.localize(765,"Organize Imports"),alias:"Organize Imports",precondition:_.ContextKeyExpr.and(E.EditorContextKeys.writable,o(b.CodeActionKind.SourceOrganizeImports)),kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:1581,weight:100}})}run(f,h){return i(h,m.localize(766,"No organize imports action available"),{include:b.CodeActionKind.SourceOrganizeImports,includeSourceActions:!0},"ifSingle",b.CodeActionTriggerSource.OrganizeImports)}}e.OrganizeImportsAction=a;class r extends I.EditorAction{constructor(){super({id:y.fixAllCommandId,label:m.localize(767,"Fix All"),alias:"Fix All",precondition:_.ContextKeyExpr.and(E.EditorContextKeys.writable,o(b.CodeActionKind.SourceFixAll))})}run(f,h){return i(h,m.localize(768,"No fix all action available"),{include:b.CodeActionKind.SourceFixAll,includeSourceActions:!0},"ifSingle",b.CodeActionTriggerSource.FixAll)}}e.FixAllAction=r;class u extends I.EditorAction{constructor(){super({id:y.autoFixCommandId,label:m.localize(769,"Auto Fix..."),alias:"Auto Fix...",precondition:_.ContextKeyExpr.and(E.EditorContextKeys.writable,o(b.CodeActionKind.QuickFix)),kbOpts:{kbExpr:E.EditorContextKeys.textInputFocus,primary:1625,mac:{primary:2649},weight:100}})}run(f,h){return i(h,m.localize(770,"No auto fixes available"),{include:b.CodeActionKind.QuickFix,onlyIncludePreferredActions:!0},"ifSingle",b.CodeActionTriggerSource.AutoFix)}}e.AutoFixAction=u}),define(ne[817],se([1,0,15,274,816,287,421,3,109,38]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorContribution)(E.CodeActionController.ID,E.CodeActionController,3),(0,d.registerEditorContribution)(y.LightBulbWidget.ID,y.LightBulbWidget,4),(0,d.registerEditorAction)(I.QuickFixAction),(0,d.registerEditorAction)(I.RefactorAction),(0,d.registerEditorAction)(I.SourceAction),(0,d.registerEditorAction)(I.OrganizeImportsAction),(0,d.registerEditorAction)(I.AutoFixAction),(0,d.registerEditorAction)(I.FixAllAction),(0,d.registerEditorCommand)(new I.CodeActionCommand),b.Registry.as(_.Extensions.Configuration).registerConfiguration({...k.editorConfigurationBaseNode,properties:{"editor.codeActionWidget.showHeaders":{type:"boolean",scope:5,description:m.localize(771,"Enable/disable showing group headers in the Code Action menu."),default:!0}}}),b.Registry.as(_.Extensions.Configuration).registerConfiguration({...k.editorConfigurationBaseNode,properties:{"editor.codeActionWidget.includeNearbyQuickFixes":{type:"boolean",scope:5,description:m.localize(772,"Enable/disable showing nearest Quick Fix within a line when not currently on a diagnostic."),default:!0}}}),b.Registry.as(_.Extensions.Configuration).registerConfiguration({...k.editorConfigurationBaseNode,properties:{"editor.codeActions.triggerOnFocusChange":{type:"boolean",scope:5,markdownDescription:m.localize(773,"Enable triggering {0} when {1} is set to {2}. Code Actions must be set to {3} to be triggered for window and focus changes.","`#editor.codeActionsOnSave#`","`#files.autoSave#`","`afterDelay`","`always`"),default:!1}}})}),define(ne[818],se([1,0,5,114,4,35,506]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.CodeLensWidget=e.CodeLensHelper=void 0;class y{constructor(o,t,i){this.afterColumn=1073741824,this.afterLineNumber=o,this.heightInPx=t,this._onHeight=i,this.suppressMouseDown=!0,this.domNode=document.createElement("div")}onComputedHeight(o){this._lastHeight===void 0?this._lastHeight=o:this._lastHeight!==o&&(this._lastHeight=o,this._onHeight())}isVisible(){return this._lastHeight!==0&&this.domNode.hasAttribute("monaco-visible-view-zone")}}class m{static{this._idPool=0}constructor(o,t){this.allowEditorOverflow=!1,this.suppressMouseDown=!0,this._commands=new Map,this._isEmpty=!0,this._editor=o,this._id=`codelens.widget-${m._idPool++}`,this.updatePosition(t),this._domNode=document.createElement("span"),this._domNode.className="codelens-decoration"}withCommands(o,t){this._commands.clear();const i=[];let s=!1;for(let g=0;g{r.symbol.command&&a.push(r.symbol),i.addDecoration({range:r.symbol.range,options:b},C=>this._decorationIds[u]=C),l?l=I.Range.plusRange(l,r.symbol.range):l=I.Range.lift(r.symbol.range)}),this._viewZone=new y(l.startLineNumber-1,g,c),this._viewZoneId=s.addZone(this._viewZone),a.length>0&&(this._createContentWidgetIfNecessary(),this._contentWidget.withCommands(a,!1))}_createContentWidgetIfNecessary(){this._contentWidget?this._editor.layoutContentWidget(this._contentWidget):(this._contentWidget=new m(this._editor,this._viewZone.afterLineNumber+1),this._editor.addContentWidget(this._contentWidget))}dispose(o,t){this._decorationIds.forEach(o.removeDecoration,o),this._decorationIds=[],t?.removeZone(this._viewZoneId),this._contentWidget&&(this._editor.removeContentWidget(this._contentWidget),this._contentWidget=void 0),this._isDisposed=!0}isDisposed(){return this._isDisposed}isValid(){return this._decorationIds.some((o,t)=>{const i=this._editor.getModel().getDecorationRange(o),s=this._data[t].symbol;return!!(i&&I.Range.isEmpty(s.range)===i.isEmpty())})}updateCodeLensSymbols(o,t){this._decorationIds.forEach(t.removeDecoration,t),this._decorationIds=[],this._data=o,this._data.forEach((i,s)=>{t.addDecoration({range:i.symbol.range,options:b},g=>this._decorationIds[s]=g)})}updateHeight(o,t){this._viewZone.heightInPx=o,t.layoutZone(this._viewZoneId),this._contentWidget&&this._editor.layoutContentWidget(this._contentWidget)}computeIfNecessary(o){if(!this._viewZone.isVisible())return null;for(let t=0;tthis._resolveCodeLensesInViewport(),this._resolveCodeLensesDebounce.default()),this._disposables.add(this._editor.onDidChangeModel(()=>this._onModelChange())),this._disposables.add(this._editor.onDidChangeModelLanguage(()=>this._onModelChange())),this._disposables.add(this._editor.onDidChangeConfiguration(w=>{(w.hasChanged(50)||w.hasChanged(19)||w.hasChanged(18))&&this._updateLensStyle(),w.hasChanged(17)&&this._onModelChange()})),this._disposables.add(u.codeLensProvider.onDidChange(this._onModelChange,this)),this._onModelChange(),this._updateLensStyle()}dispose(){this._localDispose(),this._disposables.dispose(),this._oldCodeLensModels.dispose(),this._currentCodeLensModel?.dispose()}_getLayoutInfo(){const r=Math.max(1.3,this._editor.getOption(67)/this._editor.getOption(52));let u=this._editor.getOption(19);return(!u||u<5)&&(u=this._editor.getOption(52)*.9|0),{fontSize:u,codeLensHeight:u*r|0}}_updateLensStyle(){const{codeLensHeight:r,fontSize:u}=this._getLayoutInfo(),C=this._editor.getOption(18),f=this._editor.getOption(50),{style:h}=this._editor.getContainerDomNode();h.setProperty("--vscode-editorCodeLens-lineHeight",`${r}px`),h.setProperty("--vscode-editorCodeLens-fontSize",`${u}px`),h.setProperty("--vscode-editorCodeLens-fontFeatureSettings",f.fontFeatureSettings),C&&(h.setProperty("--vscode-editorCodeLens-fontFamily",C),h.setProperty("--vscode-editorCodeLens-fontFamilyDefault",m.EDITOR_FONT_DEFAULTS.fontFamily)),this._editor.changeViewZones(v=>{for(const w of this._lenses)w.updateHeight(r,v)})}_localDispose(){this._getCodeLensModelPromise?.cancel(),this._getCodeLensModelPromise=void 0,this._resolveCodeLensesPromise?.cancel(),this._resolveCodeLensesPromise=void 0,this._localToDispose.clear(),this._oldCodeLensModels.clear(),this._currentCodeLensModel?.dispose()}_onModelChange(){this._localDispose();const r=this._editor.getModel();if(!r||!this._editor.getOption(17)||r.isTooLargeForTokenization())return;const u=this._codeLensCache.get(r);if(u&&this._renderCodeLensSymbols(u),!this._languageFeaturesService.codeLensProvider.has(r)){u&&(0,d.disposableTimeout)(()=>{const f=this._codeLensCache.get(r);u===f&&(this._codeLensCache.delete(r),this._onModelChange())},30*1e3,this._localToDispose);return}for(const f of this._languageFeaturesService.codeLensProvider.all(r))if(typeof f.onDidChange=="function"){const h=f.onDidChange(()=>C.schedule());this._localToDispose.add(h)}const C=new d.RunOnceScheduler(()=>{const f=Date.now();this._getCodeLensModelPromise?.cancel(),this._getCodeLensModelPromise=(0,d.createCancelablePromise)(h=>(0,b.getCodeLensModel)(this._languageFeaturesService.codeLensProvider,r,h)),this._getCodeLensModelPromise.then(h=>{this._currentCodeLensModel&&this._oldCodeLensModels.add(this._currentCodeLensModel),this._currentCodeLensModel=h,this._codeLensCache.put(r,h);const v=this._provideCodeLensDebounce.update(r,Date.now()-f);C.delay=v,this._renderCodeLensSymbols(h),this._resolveCodeLensesInViewportSoon()},k.onUnexpectedError)},this._provideCodeLensDebounce.get(r));this._localToDispose.add(C),this._localToDispose.add((0,I.toDisposable)(()=>this._resolveCodeLensesScheduler.cancel())),this._localToDispose.add(this._editor.onDidChangeModelContent(()=>{this._editor.changeDecorations(f=>{this._editor.changeViewZones(h=>{const v=[];let w=-1;this._lenses.forEach(L=>{!L.isValid()||w===L.getLineNumber()?v.push(L):(L.update(h),w=L.getLineNumber())});const S=new n.CodeLensHelper;v.forEach(L=>{L.dispose(S,h),this._lenses.splice(this._lenses.indexOf(L),1)}),S.commit(f)})}),C.schedule(),this._resolveCodeLensesScheduler.cancel(),this._resolveCodeLensesPromise?.cancel(),this._resolveCodeLensesPromise=void 0})),this._localToDispose.add(this._editor.onDidFocusEditorText(()=>{C.schedule()})),this._localToDispose.add(this._editor.onDidBlurEditorText(()=>{C.cancel()})),this._localToDispose.add(this._editor.onDidScrollChange(f=>{f.scrollTopChanged&&this._lenses.length>0&&this._resolveCodeLensesInViewportSoon()})),this._localToDispose.add(this._editor.onDidLayoutChange(()=>{this._resolveCodeLensesInViewportSoon()})),this._localToDispose.add((0,I.toDisposable)(()=>{if(this._editor.getModel()){const f=E.StableEditorScrollState.capture(this._editor);this._editor.changeDecorations(h=>{this._editor.changeViewZones(v=>{this._disposeAllLenses(h,v)})}),f.restore(this._editor)}else this._disposeAllLenses(void 0,void 0)})),this._localToDispose.add(this._editor.onMouseDown(f=>{if(f.target.type!==9)return;let h=f.target.element;if(h?.tagName==="SPAN"&&(h=h.parentElement),h?.tagName==="A")for(const v of this._lenses){const w=v.getCommand(h);if(w){this._commandService.executeCommand(w.id,...w.arguments||[]).catch(S=>this._notificationService.error(S));break}}})),C.schedule()}_disposeAllLenses(r,u){const C=new n.CodeLensHelper;for(const f of this._lenses)f.dispose(C,u);r&&C.commit(r),this._lenses.length=0}_renderCodeLensSymbols(r){if(!this._editor.hasModel())return;const u=this._editor.getModel().getLineCount(),C=[];let f;for(const w of r.lenses){const S=w.symbol.range.startLineNumber;S<1||S>u||(f&&f[f.length-1].symbol.range.startLineNumber===S?f.push(w):(f=[w],C.push(f)))}if(!C.length&&!this._lenses.length)return;const h=E.StableEditorScrollState.capture(this._editor),v=this._getLayoutInfo();this._editor.changeDecorations(w=>{this._editor.changeViewZones(S=>{const L=new n.CodeLensHelper;let D=0,T=0;for(;Tthis._resolveCodeLensesInViewportSoon())),D++,T++)}for(;Dthis._resolveCodeLensesInViewportSoon())),T++;L.commit(w)})}),h.restore(this._editor)}_resolveCodeLensesInViewportSoon(){this._editor.getModel()&&this._resolveCodeLensesScheduler.schedule()}_resolveCodeLensesInViewport(){this._resolveCodeLensesPromise?.cancel(),this._resolveCodeLensesPromise=void 0;const r=this._editor.getModel();if(!r)return;const u=[],C=[];if(this._lenses.forEach(v=>{const w=v.computeIfNecessary(r);w&&(u.push(w),C.push(v))}),u.length===0)return;const f=Date.now(),h=(0,d.createCancelablePromise)(v=>{const w=u.map((S,L)=>{const D=new Array(S.length),T=S.map((M,A)=>!M.symbol.command&&typeof M.provider.resolveCodeLens=="function"?Promise.resolve(M.provider.resolveCodeLens(r,M.symbol,v)).then(P=>{D[A]=P},k.onUnexpectedExternalError):(D[A]=M.symbol,Promise.resolve(void 0)));return Promise.all(T).then(()=>{!v.isCancellationRequested&&!C[L].isDisposed()&&C[L].updateCommands(D)})});return Promise.all(w)});this._resolveCodeLensesPromise=h,this._resolveCodeLensesPromise.then(()=>{const v=this._resolveCodeLensesDebounce.update(r,Date.now()-f);this._resolveCodeLensesScheduler.delay=v,this._currentCodeLensModel&&this._codeLensCache.put(r,this._currentCodeLensModel),this._oldCodeLensModels.clear(),h===this._resolveCodeLensesPromise&&(this._resolveCodeLensesPromise=void 0)},v=>{(0,k.onUnexpectedError)(v),h===this._resolveCodeLensesPromise&&(this._resolveCodeLensesPromise=void 0)})}async getModel(){return await this._getCodeLensModelPromise,await this._resolveCodeLensesPromise,this._currentCodeLensModel?.isDisposed?void 0:this._currentCodeLensModel}};e.CodeLensContribution=l,e.CodeLensContribution=l=ke([ce(1,c.ILanguageFeaturesService),ce(2,g.ILanguageFeatureDebounceService),ce(3,t.ICommandService),ce(4,i.INotificationService),ce(5,p.ICodeLensCache)],l),(0,y.registerEditorContribution)(l.ID,l,1),(0,y.registerEditorAction)(class extends y.EditorAction{constructor(){super({id:"codelens.showLensesInCurrentLine",precondition:_.EditorContextKeys.hasCodeLensProvider,label:(0,o.localize)(794,"Show CodeLens Commands For Current Line"),alias:"Show CodeLens Commands For Current Line"})}async run(r,u){if(!u.hasModel())return;const C=r.get(s.IQuickInputService),f=r.get(t.ICommandService),h=r.get(i.INotificationService),v=u.getSelection().positionLineNumber,w=u.getContribution(l.ID);if(!w)return;const S=await w.getModel();if(!S)return;const L=[];for(const M of S.lenses)M.symbol.command&&M.symbol.range.startLineNumber===v&&L.push({label:M.symbol.command.title,command:M.symbol.command});if(L.length===0)return;const D=await C.pick(L,{canPickMany:!1,placeHolder:(0,o.localize)(795,"Select a command")});if(!D)return;let T=D.command;if(S.isDisposed){const A=(await w.getModel())?.lenses.find(P=>P.symbol.range.startLineNumber===v&&P.symbol.command?.title===T.title);if(!A||!A.symbol.command)return;T=A.symbol.command}try{await f.executeCommand(T.id,...T.arguments||[])}catch(M){h.error(M)}}})}),define(ne[422],se([1,0,14,33,8,6,2,54,11,185,15,4,35,79,17,388,28]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";var c;Object.defineProperty(e,"__esModule",{value:!0}),e.DecoratorLimitReporter=e.ColorDetector=e.ColorDecorationInjectedTextMarker=void 0,e.ColorDecorationInjectedTextMarker=Object.create({});let l=class extends y.Disposable{static{c=this}static{this.ID="editor.contrib.colorDetector"}static{this.RECOMPUTE_TIME=1e3}constructor(u,C,f,h){super(),this._editor=u,this._configurationService=C,this._languageFeaturesService=f,this._localToDispose=this._register(new y.DisposableStore),this._decorationsIds=[],this._colorDatas=new Map,this._colorDecoratorIds=this._editor.createDecorationsCollection(),this._ruleFactory=new b.DynamicCssRules(this._editor),this._decoratorLimitReporter=new a,this._colorDecorationClassRefs=this._register(new y.DisposableStore),this._debounceInformation=h.for(f.colorProvider,"Document Colors",{min:c.RECOMPUTE_TIME}),this._register(u.onDidChangeModel(()=>{this._isColorDecoratorsEnabled=this.isEnabled(),this.updateColors()})),this._register(u.onDidChangeModelLanguage(()=>this.updateColors())),this._register(f.colorProvider.onDidChange(()=>this.updateColors())),this._register(u.onDidChangeConfiguration(v=>{const w=this._isColorDecoratorsEnabled;this._isColorDecoratorsEnabled=this.isEnabled(),this._isDefaultColorDecoratorsEnabled=this._editor.getOption(148);const S=w!==this._isColorDecoratorsEnabled||v.hasChanged(21),L=v.hasChanged(148);(S||L)&&(this._isColorDecoratorsEnabled?this.updateColors():this.removeAllDecorations())})),this._timeoutTimer=null,this._computePromise=null,this._isColorDecoratorsEnabled=this.isEnabled(),this._isDefaultColorDecoratorsEnabled=this._editor.getOption(148),this.updateColors()}isEnabled(){const u=this._editor.getModel();if(!u)return!1;const C=u.getLanguageId(),f=this._configurationService.getValue(C);if(f&&typeof f=="object"){const h=f.colorDecorators;if(h&&h.enable!==void 0&&!h.enable)return h.enable}return this._editor.getOption(20)}static get(u){return u.getContribution(this.ID)}dispose(){this.stop(),this.removeAllDecorations(),super.dispose()}updateColors(){if(this.stop(),!this._isColorDecoratorsEnabled)return;const u=this._editor.getModel();!u||!this._languageFeaturesService.colorProvider.has(u)||(this._localToDispose.add(this._editor.onDidChangeModelContent(()=>{this._timeoutTimer||(this._timeoutTimer=new d.TimeoutTimer,this._timeoutTimer.cancelAndSet(()=>{this._timeoutTimer=null,this.beginCompute()},this._debounceInformation.get(u)))})),this.beginCompute())}async beginCompute(){this._computePromise=(0,d.createCancelablePromise)(async u=>{const C=this._editor.getModel();if(!C)return[];const f=new m.StopWatch(!1),h=await(0,s.getColors)(this._languageFeaturesService.colorProvider,C,u,this._isDefaultColorDecoratorsEnabled);return this._debounceInformation.update(C,f.elapsed()),h});try{const u=await this._computePromise;this.updateDecorations(u),this.updateColorDecorators(u),this._computePromise=null}catch(u){(0,I.onUnexpectedError)(u)}}stop(){this._timeoutTimer&&(this._timeoutTimer.cancel(),this._timeoutTimer=null),this._computePromise&&(this._computePromise.cancel(),this._computePromise=null),this._localToDispose.clear()}updateDecorations(u){const C=u.map(f=>({range:{startLineNumber:f.colorInfo.range.startLineNumber,startColumn:f.colorInfo.range.startColumn,endLineNumber:f.colorInfo.range.endLineNumber,endColumn:f.colorInfo.range.endColumn},options:o.ModelDecorationOptions.EMPTY}));this._editor.changeDecorations(f=>{this._decorationsIds=f.deltaDecorations(this._decorationsIds,C),this._colorDatas=new Map,this._decorationsIds.forEach((h,v)=>this._colorDatas.set(h,u[v]))})}updateColorDecorators(u){this._colorDecorationClassRefs.clear();const C=[],f=this._editor.getOption(21);for(let v=0;vthis._colorDatas.has(h.id));return f.length===0?null:this._colorDatas.get(f[0].id)}isColorDecoration(u){return this._colorDecoratorIds.has(u)}};e.ColorDetector=l,e.ColorDetector=l=c=ke([ce(1,g.IConfigurationService),ce(2,i.ILanguageFeaturesService),ce(3,t.ILanguageFeatureDebounceService)],l);class a{constructor(){this._onDidChange=new E.Emitter,this._computed=0,this._limited=!1}update(u,C){(u!==this._computed||C!==this._limited)&&(this._computed=u,this._limited=C,this._onDidChange.fire())}}e.DecoratorLimitReporter=a,(0,p.registerEditorContribution)(l.ID,l,1)}),define(ne[288],se([1,0,14,18,33,2,4,388,422,608,763,84,25,5]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneColorPickerParticipant=e.StandaloneColorPickerHover=e.ColorHoverParticipant=e.ColorHover=void 0;class i{constructor(f,h,v,w){this.owner=f,this.range=h,this.model=v,this.provider=w,this.forceShowAtRange=!0}isValidForHoverAnchor(f){return f.type===1&&this.range.startColumn<=f.range.startColumn&&this.range.endColumn>=f.range.endColumn}}e.ColorHover=i;let s=class{constructor(f,h){this._editor=f,this._themeService=h,this.hoverOrdinal=2}computeSync(f,h){return[]}computeAsync(f,h,v){return d.AsyncIterableObject.fromPromise(this._computeAsync(f,h,v))}async _computeAsync(f,h,v){if(!this._editor.hasModel())return[];const w=_.ColorDetector.get(this._editor);if(!w)return[];for(const S of h){if(!w.isColorDecoration(S))continue;const L=w.getColorData(S.range.getStartPosition());if(L)return[await l(this,this._editor.getModel(),L.colorInfo,L.provider)]}return[]}renderHoverParts(f,h){const v=a(this,this._editor,this._themeService,h,f);if(!v)return new n.RenderedHoverParts([]);this._colorPicker=v.colorPicker;const w={hoverPart:v.hoverPart,hoverElement:this._colorPicker.domNode,dispose(){v.disposables.dispose()}};return new n.RenderedHoverParts([w])}handleResize(){this._colorPicker?.layout()}isColorPickerVisible(){return!!this._colorPicker}};e.ColorHoverParticipant=s,e.ColorHoverParticipant=s=ke([ce(1,o.IThemeService)],s);class g{constructor(f,h,v,w){this.owner=f,this.range=h,this.model=v,this.provider=w}}e.StandaloneColorPickerHover=g;let c=class{constructor(f,h){this._editor=f,this._themeService=h,this._color=null}async createColorHover(f,h,v){if(!this._editor.hasModel()||!_.ColorDetector.get(this._editor))return null;const S=await(0,m.getColors)(v,this._editor.getModel(),k.CancellationToken.None);let L=null,D=null;for(const P of S){const N=P.colorInfo;y.Range.containsRange(N.range,f.range)&&(L=N,D=P.provider)}const T=L??f,M=D??h,A=!!L;return{colorHover:await l(this,this._editor.getModel(),T,M),foundInEditor:A}}async updateEditorModel(f){if(!this._editor.hasModel())return;const h=f.model;let v=new y.Range(f.range.startLineNumber,f.range.startColumn,f.range.endLineNumber,f.range.endColumn);this._color&&(await u(this._editor.getModel(),h,this._color,v,f),v=r(this._editor,v,h))}renderHoverParts(f,h){return a(this,this._editor,this._themeService,h,f)}set color(f){this._color=f}get color(){return this._color}};e.StandaloneColorPickerParticipant=c,e.StandaloneColorPickerParticipant=c=ke([ce(1,o.IThemeService)],c);async function l(C,f,h,v){const w=f.getValueInRange(h.range),{red:S,green:L,blue:D,alpha:T}=h.color,M=new I.RGBA(Math.round(S*255),Math.round(L*255),Math.round(D*255),T),A=new I.Color(M),P=await(0,m.getColorPresentations)(f,h,v,k.CancellationToken.None),N=new b.ColorPickerModel(A,[],0);return N.colorPresentations=P||[],N.guessColorPresentation(A,w),C instanceof s?new i(C,y.Range.lift(h.range),N,v):new g(C,y.Range.lift(h.range),N,v)}function a(C,f,h,v,w){if(v.length===0||!f.hasModel())return;if(w.setMinimumDimensions){const N=f.getOption(67)+8;w.setMinimumDimensions(new t.Dimension(302,N))}const S=new E.DisposableStore,L=v[0],D=f.getModel(),T=L.model,M=S.add(new p.ColorPickerWidget(w.fragment,T,f.getOption(144),h,C instanceof c));let A=!1,P=new y.Range(L.range.startLineNumber,L.range.startColumn,L.range.endLineNumber,L.range.endColumn);if(C instanceof c){const N=L.model.color;C.color=N,u(D,T,N,P,L),S.add(T.onColorFlushed(O=>{C.color=O}))}else S.add(T.onColorFlushed(async N=>{await u(D,T,N,P,L),A=!0,P=r(f,P,T)}));return S.add(T.onDidChangeColor(N=>{u(D,T,N,P,L)})),S.add(f.onDidChangeModelContent(N=>{A?A=!1:(w.hide(),f.focus())})),{hoverPart:L,colorPicker:M,disposables:S}}function r(C,f,h){const v=[],w=h.presentation.textEdit??{range:f,text:h.presentation.label,forceMoveMarkers:!1};v.push(w),h.presentation.additionalTextEdits&&v.push(...h.presentation.additionalTextEdits);const S=y.Range.lift(w.range),L=C.getModel()._setTrackedRange(null,S,3);return C.executeEdits("colorpicker",v),C.pushUndoStop(),C.getModel()._getTrackedRange(L)??S}async function u(C,f,h,v,w){const S=await(0,m.getColorPresentations)(C,{range:v,color:{red:h.rgba.r/255,green:h.rgba.g/255,blue:h.rgba.b/255,alpha:h.rgba.a}},w.provider,k.CancellationToken.None);f.colorPresentations=S||[]}}),define(ne[820],se([1,0,2,288,7,391,31,6,17,15,20,12,385,5,100,227]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";var s,g;Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneColorPickerWidget=e.StandaloneColorPickerController=void 0;let c=class extends d.Disposable{static{s=this}static{this.ID="editor.contrib.standaloneColorPickerController"}constructor(f,h,v){super(),this._editor=f,this._instantiationService=v,this._standaloneColorPickerWidget=null,this._standaloneColorPickerVisible=p.EditorContextKeys.standaloneColorPickerVisible.bindTo(h),this._standaloneColorPickerFocused=p.EditorContextKeys.standaloneColorPickerFocused.bindTo(h)}showOrFocus(){this._editor.hasModel()&&(this._standaloneColorPickerVisible.get()?this._standaloneColorPickerFocused.get()||this._standaloneColorPickerWidget?.focus():this._standaloneColorPickerWidget=this._instantiationService.createInstance(r,this._editor,this._standaloneColorPickerVisible,this._standaloneColorPickerFocused))}hide(){this._standaloneColorPickerFocused.set(!1),this._standaloneColorPickerVisible.set(!1),this._standaloneColorPickerWidget?.hide(),this._editor.focus()}insertColor(){this._standaloneColorPickerWidget?.updateEditor(),this.hide()}static get(f){return f.getContribution(s.ID)}};e.StandaloneColorPickerController=c,e.StandaloneColorPickerController=c=s=ke([ce(1,n.IContextKeyService),ce(2,I.IInstantiationService)],c),(0,b.registerEditorContribution)(c.ID,c,1);const l=8,a=22;let r=class extends d.Disposable{static{g=this}static{this.ID="editor.contrib.standaloneColorPickerWidget"}constructor(f,h,v,w,S,L,D){super(),this._editor=f,this._standaloneColorPickerVisible=h,this._standaloneColorPickerFocused=v,this._keybindingService=S,this._languageFeaturesService=L,this._editorWorkerService=D,this.allowEditorOverflow=!0,this._position=void 0,this._body=document.createElement("div"),this._colorHover=null,this._selectionSetInEditor=!1,this._onResult=this._register(new m.Emitter),this.onResult=this._onResult.event,this._standaloneColorPickerVisible.set(!0),this._standaloneColorPickerParticipant=w.createInstance(k.StandaloneColorPickerParticipant,this._editor),this._position=this._editor._getViewModel()?.getPrimaryCursorState().modelState.position;const T=this._editor.getSelection(),M=T?{startLineNumber:T.startLineNumber,startColumn:T.startColumn,endLineNumber:T.endLineNumber,endColumn:T.endColumn}:{startLineNumber:0,endLineNumber:0,endColumn:0,startColumn:0},A=this._register(t.trackFocus(this._body));this._register(A.onDidBlur(P=>{this.hide()})),this._register(A.onDidFocus(P=>{this.focus()})),this._register(this._editor.onDidChangeCursorPosition(()=>{this._selectionSetInEditor?this._selectionSetInEditor=!1:this.hide()})),this._register(this._editor.onMouseMove(P=>{const N=P.target.element?.classList;N&&N.contains("colorpicker-color-decoration")&&this.hide()})),this._register(this.onResult(P=>{this._render(P.value,P.foundInEditor)})),this._start(M),this._body.style.zIndex="50",this._editor.addContentWidget(this)}updateEditor(){this._colorHover&&this._standaloneColorPickerParticipant.updateEditorModel(this._colorHover)}getId(){return g.ID}getDomNode(){return this._body}getPosition(){if(!this._position)return null;const f=this._editor.getOption(60).above;return{position:this._position,secondaryPosition:this._position,preference:f?[1,2]:[2,1],positionAffinity:2}}hide(){this.dispose(),this._standaloneColorPickerVisible.set(!1),this._standaloneColorPickerFocused.set(!1),this._editor.removeContentWidget(this),this._editor.focus()}focus(){this._standaloneColorPickerFocused.set(!0),this._body.focus()}async _start(f){const h=await this._computeAsync(f);h&&this._onResult.fire(new u(h.result,h.foundInEditor))}async _computeAsync(f){if(!this._editor.hasModel())return null;const h={range:f,color:{red:0,green:0,blue:0,alpha:1}},v=await this._standaloneColorPickerParticipant.createColorHover(h,new o.DefaultDocumentColorProvider(this._editorWorkerService),this._languageFeaturesService.colorProvider);return v?{result:v.colorHover,foundInEditor:v.foundInEditor}:null}_render(f,h){const v=document.createDocumentFragment(),w=this._register(new E.EditorHoverStatusBar(this._keybindingService)),S={fragment:v,statusBar:w,onContentsChanged:()=>{},hide:()=>this.hide()};this._colorHover=f;const L=this._standaloneColorPickerParticipant.renderHoverParts(S,[f]);if(!L)return;this._register(L.disposables);const D=L.colorPicker;this._body.classList.add("standalone-colorpicker-body"),this._body.style.maxHeight=Math.max(this._editor.getLayoutInfo().height/4,250)+"px",this._body.style.maxWidth=Math.max(this._editor.getLayoutInfo().width*.66,500)+"px",this._body.tabIndex=0,this._body.appendChild(v),D.layout();const T=D.body,M=T.saturationBox.domNode.clientWidth,A=T.domNode.clientWidth-M-a-l,P=D.body.enterButton;P?.onClicked(()=>{this.updateEditor(),this.hide()});const N=D.header,O=N.pickedColorNode;O.style.width=M+l+"px";const F=N.originalColorNode;F.style.width=A+"px",D.header.closeButton?.onClicked(()=>{this.hide()}),h&&(P&&(P.button.textContent="Replace"),this._selectionSetInEditor=!0,this._editor.setSelection(f.range)),this._editor.layoutContentWidget(this)}};e.StandaloneColorPickerWidget=r,e.StandaloneColorPickerWidget=r=g=ke([ce(3,I.IInstantiationService),ce(4,y.IKeybindingService),ce(5,_.ILanguageFeaturesService),ce(6,i.IEditorWorkerService)],r);class u{constructor(f,h){this.value=f,this.foundInEditor=h}}}),define(ne[821],se([1,0,15,3,820,20,29,227]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ShowOrFocusStandaloneColorPicker=void 0;class m extends d.EditorAction2{constructor(){super({id:"editor.action.showOrFocusStandaloneColorPicker",title:{...(0,k.localize2)(801,"Show or Focus Standalone Color Picker"),mnemonicTitle:(0,k.localize)(798,"&&Show or Focus Standalone Color Picker")},precondition:void 0,menu:[{id:y.MenuId.CommandPalette}],metadata:{description:(0,k.localize2)(802,"Show or focus a standalone color picker which uses the default color provider. It displays hex/rgb/hsl colors.")}})}runEditorCommand(n,o){I.StandaloneColorPickerController.get(o)?.showOrFocus()}}e.ShowOrFocusStandaloneColorPicker=m;class _ extends d.EditorAction{constructor(){super({id:"editor.action.hideColorPicker",label:(0,k.localize)(799,"Hide the Color Picker"),alias:"Hide the Color Picker",precondition:E.EditorContextKeys.standaloneColorPickerVisible.isEqualTo(!0),kbOpts:{primary:9,weight:100},metadata:{description:(0,k.localize2)(803,"Hide the standalone color picker.")}})}run(n,o){I.StandaloneColorPickerController.get(o)?.hide()}}class b extends d.EditorAction{constructor(){super({id:"editor.action.insertColorWithStandaloneColorPicker",label:(0,k.localize)(800,"Insert Color with Standalone Color Picker"),alias:"Insert Color with Standalone Color Picker",precondition:E.EditorContextKeys.standaloneColorPickerFocused.isEqualTo(!0),kbOpts:{primary:3,weight:100},metadata:{description:(0,k.localize2)(804,"Insert hex/rgb/hsl colors with the focused standalone color picker.")}})}run(n,o){I.StandaloneColorPickerController.get(o)?.insertColor()}}(0,d.registerEditorAction)(_),(0,d.registerEditorAction)(b),(0,y.registerAction2)(m)}),define(ne[822],se([1,0,2,16,15,9,4,23,35,610,507]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DragAndDropController=void 0;function p(o){return k.isMacintosh?o.altKey:o.ctrlKey}class n extends d.Disposable{static{this.ID="editor.contrib.dragAndDrop"}static{this.TRIGGER_KEY_VALUE=k.isMacintosh?6:5}constructor(t){super(),this._editor=t,this._dndDecorationIds=this._editor.createDecorationsCollection(),this._register(this._editor.onMouseDown(i=>this._onEditorMouseDown(i))),this._register(this._editor.onMouseUp(i=>this._onEditorMouseUp(i))),this._register(this._editor.onMouseDrag(i=>this._onEditorMouseDrag(i))),this._register(this._editor.onMouseDrop(i=>this._onEditorMouseDrop(i))),this._register(this._editor.onMouseDropCanceled(()=>this._onEditorMouseDropCanceled())),this._register(this._editor.onKeyDown(i=>this.onEditorKeyDown(i))),this._register(this._editor.onKeyUp(i=>this.onEditorKeyUp(i))),this._register(this._editor.onDidBlurEditorWidget(()=>this.onEditorBlur())),this._register(this._editor.onDidBlurEditorText(()=>this.onEditorBlur())),this._mouseDown=!1,this._modifierPressed=!1,this._dragSelection=null}onEditorBlur(){this._removeDecoration(),this._dragSelection=null,this._mouseDown=!1,this._modifierPressed=!1}onEditorKeyDown(t){!this._editor.getOption(35)||this._editor.getOption(22)||(p(t)&&(this._modifierPressed=!0),this._mouseDown&&p(t)&&this._editor.updateOptions({mouseStyle:"copy"}))}onEditorKeyUp(t){!this._editor.getOption(35)||this._editor.getOption(22)||(p(t)&&(this._modifierPressed=!1),this._mouseDown&&t.keyCode===n.TRIGGER_KEY_VALUE&&this._editor.updateOptions({mouseStyle:"default"}))}_onEditorMouseDown(t){this._mouseDown=!0}_onEditorMouseUp(t){this._mouseDown=!1,this._editor.updateOptions({mouseStyle:"text"})}_onEditorMouseDrag(t){const i=t.target;if(this._dragSelection===null){const g=(this._editor.getSelections()||[]).filter(c=>i.position&&c.containsPosition(i.position));if(g.length===1)this._dragSelection=g[0];else return}p(t.event)?this._editor.updateOptions({mouseStyle:"copy"}):this._editor.updateOptions({mouseStyle:"default"}),i.position&&(this._dragSelection.containsPosition(i.position)?this._removeDecoration():this.showAt(i.position))}_onEditorMouseDropCanceled(){this._editor.updateOptions({mouseStyle:"text"}),this._removeDecoration(),this._dragSelection=null,this._mouseDown=!1}_onEditorMouseDrop(t){if(t.target&&(this._hitContent(t.target)||this._hitMargin(t.target))&&t.target.position){const i=new E.Position(t.target.position.lineNumber,t.target.position.column);if(this._dragSelection===null){let s=null;if(t.event.shiftKey){const g=this._editor.getSelection();if(g){const{selectionStartLineNumber:c,selectionStartColumn:l}=g;s=[new m.Selection(c,l,i.lineNumber,i.column)]}}else s=(this._editor.getSelections()||[]).map(g=>g.containsPosition(i)?new m.Selection(i.lineNumber,i.column,i.lineNumber,i.column):g);this._editor.setSelections(s||[],"mouse",3)}else(!this._dragSelection.containsPosition(i)||(p(t.event)||this._modifierPressed)&&(this._dragSelection.getEndPosition().equals(i)||this._dragSelection.getStartPosition().equals(i)))&&(this._editor.pushUndoStop(),this._editor.executeCommand(n.ID,new b.DragAndDropCommand(this._dragSelection,i,p(t.event)||this._modifierPressed)),this._editor.pushUndoStop())}this._editor.updateOptions({mouseStyle:"text"}),this._removeDecoration(),this._dragSelection=null,this._mouseDown=!1}static{this._DECORATION_OPTIONS=_.ModelDecorationOptions.register({description:"dnd-target",className:"dnd-target"})}showAt(t){this._dndDecorationIds.set([{range:new y.Range(t.lineNumber,t.column,t.lineNumber,t.column),options:n._DECORATION_OPTIONS}]),this._editor.revealPosition(t,1)}_removeDecoration(){this._dndDecorationIds.clear()}_hitContent(t){return t.type===6||t.type===7}_hitMargin(t){return t.type===2||t.type===3||t.type===4}dispose(){this._removeDecoration(),this._dragSelection=null,this._mouseDown=!1,this._modifierPressed=!1,super.dispose()}}e.DragAndDropController=n,(0,I.registerEditorContribution)(n.ID,n,2)}),define(ne[823],se([1,0,4,40,35,32,25]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FindDecorations=void 0;class m{constructor(b){this._editor=b,this._decorations=[],this._overviewRulerApproximateDecorations=[],this._findScopeDecorationIds=[],this._rangeHighlightDecorationId=null,this._highlightedDecorationId=null,this._startPosition=this._editor.getPosition()}dispose(){this._editor.removeDecorations(this._allDecorations()),this._decorations=[],this._overviewRulerApproximateDecorations=[],this._findScopeDecorationIds=[],this._rangeHighlightDecorationId=null,this._highlightedDecorationId=null}reset(){this._decorations=[],this._overviewRulerApproximateDecorations=[],this._findScopeDecorationIds=[],this._rangeHighlightDecorationId=null,this._highlightedDecorationId=null}getCount(){return this._decorations.length}getFindScope(){return this._findScopeDecorationIds[0]?this._editor.getModel().getDecorationRange(this._findScopeDecorationIds[0]):null}getFindScopes(){if(this._findScopeDecorationIds.length){const b=this._findScopeDecorationIds.map(p=>this._editor.getModel().getDecorationRange(p)).filter(p=>!!p);if(b.length)return b}return null}getStartPosition(){return this._startPosition}setStartPosition(b){this._startPosition=b,this.setCurrentFindMatch(null)}_getDecorationIndex(b){const p=this._decorations.indexOf(b);return p>=0?p+1:1}getDecorationRangeAt(b){const p=b{if(this._highlightedDecorationId!==null&&(o.changeDecorationOptions(this._highlightedDecorationId,m._FIND_MATCH_DECORATION),this._highlightedDecorationId=null),p!==null&&(this._highlightedDecorationId=p,o.changeDecorationOptions(this._highlightedDecorationId,m._CURRENT_FIND_MATCH_DECORATION)),this._rangeHighlightDecorationId!==null&&(o.removeDecoration(this._rangeHighlightDecorationId),this._rangeHighlightDecorationId=null),p!==null){let t=this._editor.getModel().getDecorationRange(p);if(t.startLineNumber!==t.endLineNumber&&t.endColumn===1){const i=t.endLineNumber-1,s=this._editor.getModel().getLineMaxColumn(i);t=new d.Range(t.startLineNumber,t.startColumn,i,s)}this._rangeHighlightDecorationId=o.addDecoration(t,m._RANGE_HIGHLIGHT_DECORATION)}}),n}set(b,p){this._editor.changeDecorations(n=>{let o=m._FIND_MATCH_DECORATION;const t=[];if(b.length>1e3){o=m._FIND_MATCH_NO_OVERVIEW_DECORATION;const s=this._editor.getModel().getLineCount(),c=this._editor.getLayoutInfo().height/s,l=Math.max(2,Math.ceil(3/c));let a=b[0].range.startLineNumber,r=b[0].range.endLineNumber;for(let u=1,C=b.length;u=f.startLineNumber?f.endLineNumber>r&&(r=f.endLineNumber):(t.push({range:new d.Range(a,1,r,1),options:m._FIND_MATCH_ONLY_OVERVIEW_DECORATION}),a=f.startLineNumber,r=f.endLineNumber)}t.push({range:new d.Range(a,1,r,1),options:m._FIND_MATCH_ONLY_OVERVIEW_DECORATION})}const i=new Array(b.length);for(let s=0,g=b.length;sn.removeDecoration(s)),this._findScopeDecorationIds=[]),p?.length&&(this._findScopeDecorationIds=p.map(s=>n.addDecoration(s,m._FIND_SCOPE_DECORATION)))})}matchBeforePosition(b){if(this._decorations.length===0)return null;for(let p=this._decorations.length-1;p>=0;p--){const n=this._decorations[p],o=this._editor.getModel().getDecorationRange(n);if(!(!o||o.endLineNumber>b.lineNumber)){if(o.endLineNumberb.column))return o}}return this._editor.getModel().getDecorationRange(this._decorations[this._decorations.length-1])}matchAfterPosition(b){if(this._decorations.length===0)return null;for(let p=0,n=this._decorations.length;pb.lineNumber)return t;if(!(t.startColumn{if(this._editor.hasModel())return this.research(!1)},100),this._toDispose.add(this._updateDecorationsScheduler),this._toDispose.add(this._editor.onDidChangeCursorPosition(a=>{(a.reason===3||a.reason===5||a.reason===6)&&this._decorations.setStartPosition(this._editor.getPosition())})),this._ignoreModelContentChanged=!1,this._toDispose.add(this._editor.onDidChangeModelContent(a=>{this._ignoreModelContentChanged||(a.isFlush&&this._decorations.reset(),this._decorations.setStartPosition(this._editor.getPosition()),this._updateDecorationsScheduler.schedule())})),this._toDispose.add(this._state.onFindReplaceStateChange(a=>this._onStateChanged(a))),this.research(!1,this._state.searchScope)}dispose(){this._isDisposed=!0,(0,I.dispose)(this._startSearchingTimer),this._toDispose.dispose()}_onStateChanged(c){this._isDisposed||this._editor.hasModel()&&(c.searchString||c.isReplaceRevealed||c.isRegex||c.wholeWord||c.matchCase||c.searchScope)&&(this._editor.getModel().isTooLargeForSyncing()?(this._startSearchingTimer.cancel(),this._startSearchingTimer.setIfNotSet(()=>{c.searchScope?this.research(c.moveCursor,this._state.searchScope):this.research(c.moveCursor)},i)):c.searchScope?this.research(c.moveCursor,this._state.searchScope):this.research(c.moveCursor))}static _getSearchRange(c,l){return l||c.getFullModelRange()}research(c,l){let a=null;typeof l<"u"?l!==null&&(Array.isArray(l)?a=l:a=[l]):a=this._decorations.getFindScopes(),a!==null&&(a=a.map(f=>{if(f.startLineNumber!==f.endLineNumber){let h=f.endLineNumber;return f.endColumn===1&&(h=h-1),new m.Range(f.startLineNumber,1,h,this._editor.getModel().getLineMaxColumn(h))}return f}));const r=this._findMatches(a,!1,e.MATCHES_LIMIT);this._decorations.set(r,a);const u=this._editor.getSelection();let C=this._decorations.getCurrentMatchesPosition(u);if(C===0&&r.length>0){const f=(0,d.findFirstIdxMonotonousOrArrLen)(r.map(h=>h.range),h=>m.Range.compareRangesUsingStarts(h,u)>=0);C=f>0?f-1+1:C}this._state.changeMatchInfo(C,this._decorations.getCount(),void 0),c&&this._editor.getOption(41).cursorMoveOnType&&this._moveToNextMatch(this._decorations.getStartPosition())}_hasMatches(){return this._state.matchesCount>0}_cannotFind(){if(!this._hasMatches()){const c=this._decorations.getFindScope();return c&&this._editor.revealRangeInCenterIfOutsideViewport(c,0),!0}return!1}_setCurrentFindMatch(c){const l=this._decorations.setCurrentFindMatch(c);this._state.changeMatchInfo(l,this._decorations.getCount(),c),this._editor.setSelection(c),this._editor.revealRangeInCenterIfOutsideViewport(c,0)}_prevSearchPosition(c){const l=this._state.isRegex&&(this._state.searchString.indexOf("^")>=0||this._state.searchString.indexOf("$")>=0);let{lineNumber:a,column:r}=c;const u=this._editor.getModel();return l||r===1?(a===1?a=u.getLineCount():a--,r=u.getLineMaxColumn(a)):r--,new y.Position(a,r)}_moveToPrevMatch(c,l=!1){if(!this._state.canNavigateBack()){const w=this._decorations.matchAfterPosition(c);w&&this._setCurrentFindMatch(w);return}if(this._decorations.getCount()=0||this._state.searchString.indexOf("$")>=0);let{lineNumber:a,column:r}=c;const u=this._editor.getModel();return l||r===u.getLineMaxColumn(a)?(a===u.getLineCount()?a=1:a++,r=1):r++,new y.Position(a,r)}_moveToNextMatch(c){if(!this._state.canNavigateForward()){const a=this._decorations.matchBeforePosition(c);a&&this._setCurrentFindMatch(a);return}if(this._decorations.getCount()s._getSearchRange(this._editor.getModel(),u));return this._editor.getModel().findMatches(this._state.searchString,r,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getOption(132):null,l,a)}replaceAll(){if(!this._hasMatches())return;const c=this._decorations.getFindScopes();c===null&&this._state.matchesCount>=e.MATCHES_LIMIT?this._largeReplaceAll():this._regularReplaceAll(c),this.research(!1)}_largeReplaceAll(){const l=new b.SearchParams(this._state.searchString,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getOption(132):null).parseSearchRequest();if(!l)return;let a=l.regex;if(!a.multiline){let S="mu";a.ignoreCase&&(S+="i"),a.global&&(S+="g"),a=new RegExp(a.source,S)}const r=this._editor.getModel(),u=r.getValue(1),C=r.getFullModelRange(),f=this._getReplacePattern();let h;const v=this._state.preserveCase;f.hasReplacementPatterns||v?h=u.replace(a,function(){return f.buildReplaceString(arguments,v)}):h=u.replace(a,f.buildReplaceString(null,v));const w=new E.ReplaceCommandThatPreservesSelection(C,h,this._editor.getSelection());this._executeEditorCommand("replaceAll",w)}_regularReplaceAll(c){const l=this._getReplacePattern(),a=this._findMatches(c,l.hasReplacementPatterns||this._state.preserveCase,1073741824),r=[];for(let C=0,f=a.length;CC.range),r);this._executeEditorCommand("replaceAll",u)}selectAllMatches(){if(!this._hasMatches())return;const c=this._decorations.getFindScopes();let a=this._findMatches(c,!1,1073741824).map(u=>new _.Selection(u.range.startLineNumber,u.range.startColumn,u.range.endLineNumber,u.range.endColumn));const r=this._editor.getSelection();for(let u=0,C=a.length;uthis._hide(),2e3)),this._isVisible=!1,this._editor=n,this._state=o,this._keybindingService=t,this._domNode=document.createElement("div"),this._domNode.className="findOptionsWidget",this._domNode.style.display="none",this._domNode.style.top="10px",this._domNode.style.zIndex="12",this._domNode.setAttribute("role","presentation"),this._domNode.setAttribute("aria-hidden","true");const i={inputActiveOptionBorder:(0,m.asCssVariable)(m.inputActiveOptionBorder),inputActiveOptionForeground:(0,m.asCssVariable)(m.inputActiveOptionForeground),inputActiveOptionBackground:(0,m.asCssVariable)(m.inputActiveOptionBackground)},s=this._register((0,_.createInstantHoverDelegate)());this.caseSensitive=this._register(new k.CaseSensitiveToggle({appendTitle:this._keybindingLabelFor(y.FIND_IDS.ToggleCaseSensitiveCommand),isChecked:this._state.matchCase,hoverDelegate:s,...i})),this._domNode.appendChild(this.caseSensitive.domNode),this._register(this.caseSensitive.onChange(()=>{this._state.change({matchCase:this.caseSensitive.checked},!1)})),this.wholeWords=this._register(new k.WholeWordsToggle({appendTitle:this._keybindingLabelFor(y.FIND_IDS.ToggleWholeWordCommand),isChecked:this._state.wholeWord,hoverDelegate:s,...i})),this._domNode.appendChild(this.wholeWords.domNode),this._register(this.wholeWords.onChange(()=>{this._state.change({wholeWord:this.wholeWords.checked},!1)})),this.regex=this._register(new k.RegexToggle({appendTitle:this._keybindingLabelFor(y.FIND_IDS.ToggleRegexCommand),isChecked:this._state.isRegex,hoverDelegate:s,...i})),this._domNode.appendChild(this.regex.domNode),this._register(this.regex.onChange(()=>{this._state.change({isRegex:this.regex.checked},!1)})),this._editor.addOverlayWidget(this),this._register(this._state.onFindReplaceStateChange(g=>{let c=!1;g.isRegex&&(this.regex.checked=this._state.isRegex,c=!0),g.wholeWord&&(this.wholeWords.checked=this._state.wholeWord,c=!0),g.matchCase&&(this.caseSensitive.checked=this._state.matchCase,c=!0),!this._state.isRevealed&&c&&this._revealTemporarily()})),this._register(d.addDisposableListener(this._domNode,d.EventType.MOUSE_LEAVE,g=>this._onMouseLeave())),this._register(d.addDisposableListener(this._domNode,"mouseover",g=>this._onMouseOver()))}_keybindingLabelFor(n){const o=this._keybindingService.lookupKeybinding(n);return o?` (${o.getLabel()})`:""}dispose(){this._editor.removeOverlayWidget(this),super.dispose()}getId(){return b.ID}getDomNode(){return this._domNode}getPosition(){return{preference:0}}highlightFindOptions(){this._revealTemporarily()}_revealTemporarily(){this._show(),this._hideSoon.schedule()}_onMouseLeave(){this._hideSoon.schedule()}_onMouseOver(){this._hideSoon.cancel()}_show(){this._isVisible||(this._isVisible=!0,this._domNode.style.display="block")}_hide(){this._isVisible&&(this._isVisible=!1,this._domNode.style.display="none")}}e.FindOptionsWidget=b}),define(ne[825],se([1,0,6,2,4,220]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FindReplaceState=void 0;function y(_,b){return _===1?!0:_===2?!1:b}class m extends k.Disposable{get searchString(){return this._searchString}get replaceString(){return this._replaceString}get isRevealed(){return this._isRevealed}get isReplaceRevealed(){return this._isReplaceRevealed}get isRegex(){return y(this._isRegexOverride,this._isRegex)}get wholeWord(){return y(this._wholeWordOverride,this._wholeWord)}get matchCase(){return y(this._matchCaseOverride,this._matchCase)}get preserveCase(){return y(this._preserveCaseOverride,this._preserveCase)}get actualIsRegex(){return this._isRegex}get actualWholeWord(){return this._wholeWord}get actualMatchCase(){return this._matchCase}get actualPreserveCase(){return this._preserveCase}get searchScope(){return this._searchScope}get matchesPosition(){return this._matchesPosition}get matchesCount(){return this._matchesCount}get currentMatch(){return this._currentMatch}constructor(){super(),this._onFindReplaceStateChange=this._register(new d.Emitter),this.onFindReplaceStateChange=this._onFindReplaceStateChange.event,this._searchString="",this._replaceString="",this._isRevealed=!1,this._isReplaceRevealed=!1,this._isRegex=!1,this._isRegexOverride=0,this._wholeWord=!1,this._wholeWordOverride=0,this._matchCase=!1,this._matchCaseOverride=0,this._preserveCase=!1,this._preserveCaseOverride=0,this._searchScope=null,this._matchesPosition=0,this._matchesCount=0,this._currentMatch=null,this._loop=!0,this._isSearching=!1,this._filters=null}changeMatchInfo(b,p,n){const o={moveCursor:!1,updateHistory:!1,searchString:!1,replaceString:!1,isRevealed:!1,isReplaceRevealed:!1,isRegex:!1,wholeWord:!1,matchCase:!1,preserveCase:!1,searchScope:!1,matchesPosition:!1,matchesCount:!1,currentMatch:!1,loop:!1,isSearching:!1,filters:!1};let t=!1;p===0&&(b=0),b>p&&(b=p),this._matchesPosition!==b&&(this._matchesPosition=b,o.matchesPosition=!0,t=!0),this._matchesCount!==p&&(this._matchesCount=p,o.matchesCount=!0,t=!0),typeof n<"u"&&(I.Range.equalsRange(this._currentMatch,n)||(this._currentMatch=n,o.currentMatch=!0,t=!0)),t&&this._onFindReplaceStateChange.fire(o)}change(b,p,n=!0){const o={moveCursor:p,updateHistory:n,searchString:!1,replaceString:!1,isRevealed:!1,isReplaceRevealed:!1,isRegex:!1,wholeWord:!1,matchCase:!1,preserveCase:!1,searchScope:!1,matchesPosition:!1,matchesCount:!1,currentMatch:!1,loop:!1,isSearching:!1,filters:!1};let t=!1;const i=this.isRegex,s=this.wholeWord,g=this.matchCase,c=this.preserveCase;typeof b.searchString<"u"&&this._searchString!==b.searchString&&(this._searchString=b.searchString,o.searchString=!0,t=!0),typeof b.replaceString<"u"&&this._replaceString!==b.replaceString&&(this._replaceString=b.replaceString,o.replaceString=!0,t=!0),typeof b.isRevealed<"u"&&this._isRevealed!==b.isRevealed&&(this._isRevealed=b.isRevealed,o.isRevealed=!0,t=!0),typeof b.isReplaceRevealed<"u"&&this._isReplaceRevealed!==b.isReplaceRevealed&&(this._isReplaceRevealed=b.isReplaceRevealed,o.isReplaceRevealed=!0,t=!0),typeof b.isRegex<"u"&&(this._isRegex=b.isRegex),typeof b.wholeWord<"u"&&(this._wholeWord=b.wholeWord),typeof b.matchCase<"u"&&(this._matchCase=b.matchCase),typeof b.preserveCase<"u"&&(this._preserveCase=b.preserveCase),typeof b.searchScope<"u"&&(b.searchScope?.every(l=>this._searchScope?.some(a=>!I.Range.equalsRange(a,l)))||(this._searchScope=b.searchScope,o.searchScope=!0,t=!0)),typeof b.loop<"u"&&this._loop!==b.loop&&(this._loop=b.loop,o.loop=!0,t=!0),typeof b.isSearching<"u"&&this._isSearching!==b.isSearching&&(this._isSearching=b.isSearching,o.isSearching=!0,t=!0),typeof b.filters<"u"&&(this._filters?this._filters.update(b.filters):this._filters=b.filters,o.filters=!0,t=!0),this._isRegexOverride=typeof b.isRegexOverride<"u"?b.isRegexOverride:0,this._wholeWordOverride=typeof b.wholeWordOverride<"u"?b.wholeWordOverride:0,this._matchCaseOverride=typeof b.matchCaseOverride<"u"?b.matchCaseOverride:0,this._preserveCaseOverride=typeof b.preserveCaseOverride<"u"?b.preserveCaseOverride:0,i!==this.isRegex&&(t=!0,o.isRegex=!0),s!==this.wholeWord&&(t=!0,o.wholeWord=!0),g!==this.matchCase&&(t=!0,o.matchCase=!0),c!==this.preserveCase&&(t=!0,o.preserveCase=!0),t&&this._onFindReplaceStateChange.fire(o)}canNavigateBack(){return this.canNavigateInLoop()||this.matchesPosition!==1}canNavigateForward(){return this.canNavigateInLoop()||this.matchesPosition=E.MATCHES_LIMIT}}e.FindReplaceState=m}),define(ne[826],se([1,0,5,46,175,173,85,14,26,8,2,16,11,4,220,3,404,675,32,71,25,30,97,19,110,44,510]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SimpleButton=e.FindWidget=e.FindWidgetViewZone=e.NLS_NO_RESULTS=e.NLS_MATCHES_LOCATION=e.findNextMatchIcon=e.findPreviousMatchIcon=e.findReplaceAllIcon=e.findReplaceIcon=e.findSelectionIcon=void 0;const w=(0,a.registerIcon)("find-collapsed",_.Codicon.chevronRight,s.localize(864,"Icon to indicate that the editor find widget is collapsed.")),S=(0,a.registerIcon)("find-expanded",_.Codicon.chevronDown,s.localize(865,"Icon to indicate that the editor find widget is expanded."));e.findSelectionIcon=(0,a.registerIcon)("find-selection",_.Codicon.selection,s.localize(866,"Icon for 'Find in Selection' in the editor find widget.")),e.findReplaceIcon=(0,a.registerIcon)("find-replace",_.Codicon.replace,s.localize(867,"Icon for 'Replace' in the editor find widget.")),e.findReplaceAllIcon=(0,a.registerIcon)("find-replace-all",_.Codicon.replaceAll,s.localize(868,"Icon for 'Replace All' in the editor find widget.")),e.findPreviousMatchIcon=(0,a.registerIcon)("find-previous-match",_.Codicon.arrowUp,s.localize(869,"Icon for 'Find Previous' in the editor find widget.")),e.findNextMatchIcon=(0,a.registerIcon)("find-next-match",_.Codicon.arrowDown,s.localize(870,"Icon for 'Find Next' in the editor find widget."));const L=s.localize(871,"Find / Replace"),D=s.localize(872,"Find"),T=s.localize(873,"Find"),M=s.localize(874,"Previous Match"),A=s.localize(875,"Next Match"),P=s.localize(876,"Find in Selection"),N=s.localize(877,"Close"),O=s.localize(878,"Replace"),F=s.localize(879,"Replace"),x=s.localize(880,"Replace"),W=s.localize(881,"Replace All"),V=s.localize(882,"Toggle Replace"),q=s.localize(883,"Only the first {0} results are highlighted, but all find operations work on the entire text.",i.MATCHES_LIMIT);e.NLS_MATCHES_LOCATION=s.localize(884,"{0} of {1}"),e.NLS_NO_RESULTS=s.localize(885,"No results");const H=419,U=275-54;let j=69;const Y=33,G="ctrlEnterReplaceAll.windows.donotask",K=n.isMacintosh?256:2048;class R{constructor(ae){this.afterLineNumber=ae,this.heightInPx=Y,this.suppressMouseDown=!1,this.domNode=document.createElement("div"),this.domNode.className="dock-find-viewzone"}}e.FindWidgetViewZone=R;function J(pe,ae,ee){const de=!!ae.match(/\n/);if(ee&&de&&ee.selectionStart>0){pe.stopPropagation();return}}function ie(pe,ae,ee){const de=!!ae.match(/\n/);if(ee&&de&&ee.selectionEndthis._updateHistoryDelayer.cancel())),this._register(this._state.onFindReplaceStateChange(re=>this._onStateChanged(re))),this._buildDomNode(),this._updateButtons(),this._tryUpdateWidgetWidth(),this._findInput.inputBox.layout(),this._register(this._codeEditor.onDidChangeConfiguration(re=>{if(re.hasChanged(92)&&(this._codeEditor.getOption(92)&&this._state.change({isReplaceRevealed:!1},!1),this._updateButtons()),re.hasChanged(146)&&this._tryUpdateWidgetWidth(),re.hasChanged(2)&&this.updateAccessibilitySupport(),re.hasChanged(41)){const le=this._codeEditor.getOption(41).loop;this._state.change({loop:le},!1);const me=this._codeEditor.getOption(41).addExtraSpaceOnTop;me&&!this._viewZone&&(this._viewZone=new R(0),this._showViewZone()),!me&&this._viewZone&&this._removeViewZone()}})),this.updateAccessibilitySupport(),this._register(this._codeEditor.onDidChangeCursorSelection(()=>{this._isVisible&&this._updateToggleSelectionFindButton()})),this._register(this._codeEditor.onDidFocusEditorWidget(async()=>{if(this._isVisible){const re=await this._controller.getGlobalBufferTerm();re&&re!==this._state.searchString&&(this._state.change({searchString:re},!1),this._findInput.select())}})),this._findInputFocused=i.CONTEXT_FIND_INPUT_FOCUSED.bindTo(B),this._findFocusTracker=this._register(d.trackFocus(this._findInput.inputBox.inputElement)),this._register(this._findFocusTracker.onDidFocus(()=>{this._findInputFocused.set(!0),this._updateSearchScope()})),this._register(this._findFocusTracker.onDidBlur(()=>{this._findInputFocused.set(!1)})),this._replaceInputFocused=i.CONTEXT_REPLACE_INPUT_FOCUSED.bindTo(B),this._replaceFocusTracker=this._register(d.trackFocus(this._replaceInput.inputBox.inputElement)),this._register(this._replaceFocusTracker.onDidFocus(()=>{this._replaceInputFocused.set(!0),this._updateSearchScope()})),this._register(this._replaceFocusTracker.onDidBlur(()=>{this._replaceInputFocused.set(!1)})),this._codeEditor.addOverlayWidget(this),this._codeEditor.getOption(41).addExtraSpaceOnTop&&(this._viewZone=new R(0)),this._register(this._codeEditor.onDidChangeModel(()=>{this._isVisible&&(this._viewZoneId=void 0)})),this._register(this._codeEditor.onDidScrollChange(re=>{if(re.scrollTopChanged){this._layoutViewZone();return}setTimeout(()=>{this._layoutViewZone()},0)}))}getId(){return ue.ID}getDomNode(){return this._domNode}getPosition(){return this._isVisible?{preference:0}:null}_onStateChanged(ae){if(ae.searchString){try{this._ignoreChangeEvent=!0,this._findInput.setValue(this._state.searchString)}finally{this._ignoreChangeEvent=!1}this._updateButtons()}if(ae.replaceString&&(this._replaceInput.inputBox.value=this._state.replaceString),ae.isRevealed&&(this._state.isRevealed?this._reveal():this._hide(!0)),ae.isReplaceRevealed&&(this._state.isReplaceRevealed?!this._codeEditor.getOption(92)&&!this._isReplaceVisible&&(this._isReplaceVisible=!0,this._replaceInput.width=d.getTotalWidth(this._findInput.domNode),this._updateButtons(),this._replaceInput.inputBox.layout()):this._isReplaceVisible&&(this._isReplaceVisible=!1,this._updateButtons())),(ae.isRevealed||ae.isReplaceRevealed)&&(this._state.isRevealed||this._state.isReplaceRevealed)&&this._tryUpdateHeight()&&this._showViewZone(),ae.isRegex&&this._findInput.setRegex(this._state.isRegex),ae.wholeWord&&this._findInput.setWholeWords(this._state.wholeWord),ae.matchCase&&this._findInput.setCaseSensitive(this._state.matchCase),ae.preserveCase&&this._replaceInput.setPreserveCase(this._state.preserveCase),ae.searchScope&&(this._state.searchScope?this._toggleSelectionFind.checked=!0:this._toggleSelectionFind.checked=!1,this._updateToggleSelectionFindButton()),ae.searchString||ae.matchesCount||ae.matchesPosition){const ee=this._state.searchString.length>0&&this._state.matchesCount===0;this._domNode.classList.toggle("no-results",ee),this._updateMatchesCount(),this._updateButtons()}(ae.searchString||ae.currentMatch)&&this._layoutViewZone(),ae.updateHistory&&this._delayedUpdateHistory(),ae.loop&&this._updateButtons()}_delayedUpdateHistory(){this._updateHistoryDelayer.trigger(this._updateHistory.bind(this)).then(void 0,b.onUnexpectedError)}_updateHistory(){this._state.searchString&&this._findInput.inputBox.addToHistory(),this._state.replaceString&&this._replaceInput.inputBox.addToHistory()}_updateMatchesCount(){this._matchesCount.style.minWidth=j+"px",this._state.matchesCount>=i.MATCHES_LIMIT?this._matchesCount.title=q:this._matchesCount.title="",this._matchesCount.firstChild?.remove();let ae;if(this._state.matchesCount>0){let ee=String(this._state.matchesCount);this._state.matchesCount>=i.MATCHES_LIMIT&&(ee+="+");let de=String(this._state.matchesPosition);de==="0"&&(de="?"),ae=o.format(e.NLS_MATCHES_LOCATION,de,ee)}else ae=e.NLS_NO_RESULTS;this._matchesCount.appendChild(document.createTextNode(ae)),(0,k.alert)(this._getAriaLabel(ae,this._state.currentMatch,this._state.searchString)),j=Math.max(j,this._matchesCount.clientWidth)}_getAriaLabel(ae,ee,de){if(ae===e.NLS_NO_RESULTS)return de===""?s.localize(886,"{0} found",ae):s.localize(887,"{0} found for '{1}'",ae,de);if(ee){const ge=s.localize(888,"{0} found for '{1}', at {2}",ae,de,ee.startLineNumber+":"+ee.startColumn),X=this._codeEditor.getModel();return X&&ee.startLineNumber<=X.getLineCount()&&ee.startLineNumber>=1?`${X.getLineContent(ee.startLineNumber)}, ${ge}`:ge}return s.localize(889,"{0} found for '{1}'",ae,de)}_updateToggleSelectionFindButton(){const ae=this._codeEditor.getSelection(),ee=ae?ae.startLineNumber!==ae.endLineNumber||ae.startColumn!==ae.endColumn:!1,de=this._toggleSelectionFind.checked;this._isVisible&&(de||ee)?this._toggleSelectionFind.enable():this._toggleSelectionFind.disable()}_updateButtons(){this._findInput.setEnabled(this._isVisible),this._replaceInput.setEnabled(this._isVisible&&this._isReplaceVisible),this._updateToggleSelectionFindButton(),this._closeBtn.setEnabled(this._isVisible);const ae=this._state.searchString.length>0,ee=!!this._state.matchesCount;this._prevBtn.setEnabled(this._isVisible&&ae&&ee&&this._state.canNavigateBack()),this._nextBtn.setEnabled(this._isVisible&&ae&&ee&&this._state.canNavigateForward()),this._replaceBtn.setEnabled(this._isVisible&&this._isReplaceVisible&&ae),this._replaceAllBtn.setEnabled(this._isVisible&&this._isReplaceVisible&&ae),this._domNode.classList.toggle("replaceToggled",this._isReplaceVisible),this._toggleReplaceBtn.setExpanded(this._isReplaceVisible);const de=!this._codeEditor.getOption(92);this._toggleReplaceBtn.setEnabled(this._isVisible&&de)}_reveal(){if(this._revealTimeouts.forEach(ae=>{clearTimeout(ae)}),this._revealTimeouts=[],!this._isVisible){this._isVisible=!0;const ae=this._codeEditor.getSelection();switch(this._codeEditor.getOption(41).autoFindInSelection){case"always":this._toggleSelectionFind.checked=!0;break;case"never":this._toggleSelectionFind.checked=!1;break;case"multiline":{const de=!!ae&&ae.startLineNumber!==ae.endLineNumber;this._toggleSelectionFind.checked=de;break}default:break}this._tryUpdateWidgetWidth(),this._updateButtons(),this._revealTimeouts.push(setTimeout(()=>{this._domNode.classList.add("visible"),this._domNode.setAttribute("aria-hidden","false")},0)),this._revealTimeouts.push(setTimeout(()=>{this._findInput.validate()},200)),this._codeEditor.layoutOverlayWidget(this);let ee=!0;if(this._codeEditor.getOption(41).seedSearchStringFromSelection&&ae){const de=this._codeEditor.getDomNode();if(de){const ge=d.getDomNodePagePosition(de),X=this._codeEditor.getScrolledVisiblePosition(ae.getStartPosition()),B=ge.left+(X?X.left:0),$=X?X.top:0;if(this._viewZone&&$ae.startLineNumber&&(ee=!1);const Q=d.getTopLeftOffset(this._domNode).left;B>Q&&(ee=!1);const Z=this._codeEditor.getScrolledVisiblePosition(ae.getEndPosition());ge.left+(Z?Z.left:0)>Q&&(ee=!1)}}}this._showViewZone(ee)}}_hide(ae){this._revealTimeouts.forEach(ee=>{clearTimeout(ee)}),this._revealTimeouts=[],this._isVisible&&(this._isVisible=!1,this._updateButtons(),this._domNode.classList.remove("visible"),this._domNode.setAttribute("aria-hidden","true"),this._findInput.clearMessage(),ae&&this._codeEditor.focus(),this._codeEditor.layoutOverlayWidget(this),this._removeViewZone())}_layoutViewZone(ae){if(!this._codeEditor.getOption(41).addExtraSpaceOnTop){this._removeViewZone();return}if(!this._isVisible)return;const de=this._viewZone;this._viewZoneId!==void 0||!de||this._codeEditor.changeViewZones(ge=>{de.heightInPx=this._getHeight(),this._viewZoneId=ge.addZone(de),this._codeEditor.setScrollTop(ae||this._codeEditor.getScrollTop()+de.heightInPx)})}_showViewZone(ae=!0){if(!this._isVisible||!this._codeEditor.getOption(41).addExtraSpaceOnTop)return;this._viewZone===void 0&&(this._viewZone=new R(0));const de=this._viewZone;this._codeEditor.changeViewZones(ge=>{if(this._viewZoneId!==void 0){const X=this._getHeight();if(X===de.heightInPx)return;const B=X-de.heightInPx;de.heightInPx=X,ge.layoutZone(this._viewZoneId),ae&&this._codeEditor.setScrollTop(this._codeEditor.getScrollTop()+B);return}else{let X=this._getHeight();if(X-=this._codeEditor.getOption(84).top,X<=0)return;de.heightInPx=X,this._viewZoneId=ge.addZone(de),ae&&this._codeEditor.setScrollTop(this._codeEditor.getScrollTop()+X)}})}_removeViewZone(){this._codeEditor.changeViewZones(ae=>{this._viewZoneId!==void 0&&(ae.removeZone(this._viewZoneId),this._viewZoneId=void 0,this._viewZone&&(this._codeEditor.setScrollTop(this._codeEditor.getScrollTop()-this._viewZone.heightInPx),this._viewZone=void 0))})}_tryUpdateWidgetWidth(){if(!this._isVisible||!this._domNode.isConnected)return;const ae=this._codeEditor.getLayoutInfo();if(ae.contentWidth<=0){this._domNode.classList.add("hiddenEditor");return}else this._domNode.classList.contains("hiddenEditor")&&this._domNode.classList.remove("hiddenEditor");const de=ae.width,ge=ae.minimap.minimapWidth;let X=!1,B=!1,$=!1;if(this._resized&&d.getTotalWidth(this._domNode)>H){this._domNode.style.maxWidth=`${de-28-ge-15}px`,this._replaceInput.width=d.getTotalWidth(this._findInput.domNode);return}if(H+28+ge>=de&&(B=!0),H+28+ge-j>=de&&($=!0),H+28+ge-j>=de+50&&(X=!0),this._domNode.classList.toggle("collapsed-find-widget",X),this._domNode.classList.toggle("narrow-find-widget",$),this._domNode.classList.toggle("reduced-find-widget",B),!$&&!X&&(this._domNode.style.maxWidth=`${de-28-ge-15}px`),this._findInput.layout({collapsedFindWidget:X,narrowFindWidget:$,reducedFindWidget:B}),this._resized){const Q=this._findInput.inputBox.element.clientWidth;Q>0&&(this._replaceInput.width=Q)}else this._isReplaceVisible&&(this._replaceInput.width=d.getTotalWidth(this._findInput.domNode))}_getHeight(){let ae=0;return ae+=4,ae+=this._findInput.inputBox.height+2,this._isReplaceVisible&&(ae+=4,ae+=this._replaceInput.inputBox.height+2),ae+=4,ae}_tryUpdateHeight(){const ae=this._getHeight();return this._cachedHeight!==null&&this._cachedHeight===ae?!1:(this._cachedHeight=ae,this._domNode.style.height=`${ae}px`,!0)}focusFindInput(){this._findInput.select(),this._findInput.focus()}focusReplaceInput(){this._replaceInput.select(),this._replaceInput.focus()}highlightFindOptions(){this._findInput.highlightFindOptions()}_updateSearchScope(){if(this._codeEditor.hasModel()&&this._toggleSelectionFind.checked){const ae=this._codeEditor.getSelections();ae.map(ee=>{ee.endColumn===1&&ee.endLineNumber>ee.startLineNumber&&(ee=ee.setEndPosition(ee.endLineNumber-1,this._codeEditor.getModel().getLineMaxColumn(ee.endLineNumber-1)));const de=this._state.currentMatch;return ee.startLineNumber!==ee.endLineNumber&&!t.Range.equalsRange(ee,de)?ee:null}).filter(ee=>!!ee),ae.length&&this._state.change({searchScope:ae},!0)}}_onFindInputMouseDown(ae){ae.middleButton&&ae.stopPropagation()}_onFindInputKeyDown(ae){if(ae.equals(K|3))if(this._keybindingService.dispatchEvent(ae,ae.target)){ae.preventDefault();return}else{this._findInput.inputBox.insertAtCursor(` `),ae.preventDefault();return}if(ae.equals(2)){this._isReplaceVisible?this._replaceInput.focus():this._findInput.focusOnCaseSensitive(),ae.preventDefault();return}if(ae.equals(2066)){this._codeEditor.focus(),ae.preventDefault();return}if(ae.equals(16))return J(ae,this._findInput.getValue(),this._findInput.domNode.querySelector("textarea"));if(ae.equals(18))return ie(ae,this._findInput.getValue(),this._findInput.domNode.querySelector("textarea"))}_onReplaceInputKeyDown(ae){if(ae.equals(K|3))if(this._keybindingService.dispatchEvent(ae,ae.target)){ae.preventDefault();return}else{n.isWindows&&n.isNative&&!this._ctrlEnterReplaceAllWarningPrompted&&(this._notificationService.info(s.localize(890,"Ctrl+Enter now inserts line break instead of replacing all. You can modify the keybinding for editor.action.replaceAll to override this behavior.")),this._ctrlEnterReplaceAllWarningPrompted=!0,this._storageService.store(G,!0,0,0)),this._replaceInput.inputBox.insertAtCursor(` `),ae.preventDefault();return}if(ae.equals(2)){this._findInput.focusOnCaseSensitive(),ae.preventDefault();return}if(ae.equals(1026)){this._findInput.focus(),ae.preventDefault();return}if(ae.equals(2066)){this._codeEditor.focus(),ae.preventDefault();return}if(ae.equals(16))return J(ae,this._replaceInput.inputBox.value,this._replaceInput.inputBox.element.querySelector("textarea"));if(ae.equals(18))return ie(ae,this._replaceInput.inputBox.value,this._replaceInput.inputBox.element.querySelector("textarea"))}getVerticalSashLeft(ae){return 0}_keybindingLabelFor(ae){const ee=this._keybindingService.lookupKeybinding(ae);return ee?` (${ee.getLabel()})`:""}_buildDomNode(){this._findInput=this._register(new g.ContextScopedFindInput(null,this._contextViewProvider,{width:U,label:D,placeholder:T,appendCaseSensitiveLabel:this._keybindingLabelFor(i.FIND_IDS.ToggleCaseSensitiveCommand),appendWholeWordsLabel:this._keybindingLabelFor(i.FIND_IDS.ToggleWholeWordCommand),appendRegexLabel:this._keybindingLabelFor(i.FIND_IDS.ToggleRegexCommand),validation:te=>{if(te.length===0||!this._findInput.getRegex())return null;try{return new RegExp(te,"gu"),null}catch(re){return{content:re.message}}},flexibleHeight:!0,flexibleWidth:!0,flexibleMaxHeight:118,showCommonFindToggles:!0,showHistoryHint:()=>(0,c.showHistoryKeybindingHint)(this._keybindingService),inputBoxStyles:h.defaultInputBoxStyles,toggleStyles:h.defaultToggleStyles},this._contextKeyService)),this._findInput.setRegex(!!this._state.isRegex),this._findInput.setCaseSensitive(!!this._state.matchCase),this._findInput.setWholeWords(!!this._state.wholeWord),this._register(this._findInput.onKeyDown(te=>this._onFindInputKeyDown(te))),this._register(this._findInput.inputBox.onDidChange(()=>{this._ignoreChangeEvent||this._state.change({searchString:this._findInput.getValue()},!0)})),this._register(this._findInput.onDidOptionChange(()=>{this._state.change({isRegex:this._findInput.getRegex(),wholeWord:this._findInput.getWholeWords(),matchCase:this._findInput.getCaseSensitive()},!0)})),this._register(this._findInput.onCaseSensitiveKeyDown(te=>{te.equals(1026)&&this._isReplaceVisible&&(this._replaceInput.focus(),te.preventDefault())})),this._register(this._findInput.onRegexKeyDown(te=>{te.equals(2)&&this._isReplaceVisible&&(this._replaceInput.focusOnPreserve(),te.preventDefault())})),this._register(this._findInput.inputBox.onDidHeightChange(te=>{this._tryUpdateHeight()&&this._showViewZone()})),n.isLinux&&this._register(this._findInput.onMouseDown(te=>this._onFindInputMouseDown(te))),this._matchesCount=document.createElement("div"),this._matchesCount.className="matchesCount",this._updateMatchesCount();const de=this._register((0,v.createInstantHoverDelegate)());this._prevBtn=this._register(new he({label:M+this._keybindingLabelFor(i.FIND_IDS.PreviousMatchFindAction),icon:e.findPreviousMatchIcon,hoverDelegate:de,onTrigger:()=>{(0,f.assertIsDefined)(this._codeEditor.getAction(i.FIND_IDS.PreviousMatchFindAction)).run().then(void 0,b.onUnexpectedError)}},this._hoverService)),this._nextBtn=this._register(new he({label:A+this._keybindingLabelFor(i.FIND_IDS.NextMatchFindAction),icon:e.findNextMatchIcon,hoverDelegate:de,onTrigger:()=>{(0,f.assertIsDefined)(this._codeEditor.getAction(i.FIND_IDS.NextMatchFindAction)).run().then(void 0,b.onUnexpectedError)}},this._hoverService));const ge=document.createElement("div");ge.className="find-part",ge.appendChild(this._findInput.domNode);const X=document.createElement("div");X.className="find-actions",ge.appendChild(X),X.appendChild(this._matchesCount),X.appendChild(this._prevBtn.domNode),X.appendChild(this._nextBtn.domNode),this._toggleSelectionFind=this._register(new I.Toggle({icon:e.findSelectionIcon,title:P+this._keybindingLabelFor(i.FIND_IDS.ToggleSearchScopeCommand),isChecked:!1,hoverDelegate:de,inputActiveOptionBackground:(0,l.asCssVariable)(l.inputActiveOptionBackground),inputActiveOptionBorder:(0,l.asCssVariable)(l.inputActiveOptionBorder),inputActiveOptionForeground:(0,l.asCssVariable)(l.inputActiveOptionForeground)})),this._register(this._toggleSelectionFind.onChange(()=>{if(this._toggleSelectionFind.checked){if(this._codeEditor.hasModel()){let te=this._codeEditor.getSelections();te=te.map(re=>(re.endColumn===1&&re.endLineNumber>re.startLineNumber&&(re=re.setEndPosition(re.endLineNumber-1,this._codeEditor.getModel().getLineMaxColumn(re.endLineNumber-1))),re.isEmpty()?null:re)).filter(re=>!!re),te.length&&this._state.change({searchScope:te},!0)}}else this._state.change({searchScope:null},!0)})),X.appendChild(this._toggleSelectionFind.domNode),this._closeBtn=this._register(new he({label:N+this._keybindingLabelFor(i.FIND_IDS.CloseFindWidgetCommand),icon:a.widgetClose,hoverDelegate:de,onTrigger:()=>{this._state.change({isRevealed:!1,searchScope:null},!1)},onKeyDown:te=>{te.equals(2)&&this._isReplaceVisible&&(this._replaceBtn.isEnabled()?this._replaceBtn.focus():this._codeEditor.focus(),te.preventDefault())}},this._hoverService)),this._replaceInput=this._register(new g.ContextScopedReplaceInput(null,void 0,{label:O,placeholder:F,appendPreserveCaseLabel:this._keybindingLabelFor(i.FIND_IDS.TogglePreserveCaseCommand),history:[],flexibleHeight:!0,flexibleWidth:!0,flexibleMaxHeight:118,showHistoryHint:()=>(0,c.showHistoryKeybindingHint)(this._keybindingService),inputBoxStyles:h.defaultInputBoxStyles,toggleStyles:h.defaultToggleStyles},this._contextKeyService,!0)),this._replaceInput.setPreserveCase(!!this._state.preserveCase),this._register(this._replaceInput.onKeyDown(te=>this._onReplaceInputKeyDown(te))),this._register(this._replaceInput.inputBox.onDidChange(()=>{this._state.change({replaceString:this._replaceInput.inputBox.value},!1)})),this._register(this._replaceInput.inputBox.onDidHeightChange(te=>{this._isReplaceVisible&&this._tryUpdateHeight()&&this._showViewZone()})),this._register(this._replaceInput.onDidOptionChange(()=>{this._state.change({preserveCase:this._replaceInput.getPreserveCase()},!0)})),this._register(this._replaceInput.onPreserveCaseKeyDown(te=>{te.equals(2)&&(this._prevBtn.isEnabled()?this._prevBtn.focus():this._nextBtn.isEnabled()?this._nextBtn.focus():this._toggleSelectionFind.enabled?this._toggleSelectionFind.focus():this._closeBtn.isEnabled()&&this._closeBtn.focus(),te.preventDefault())}));const B=this._register((0,v.createInstantHoverDelegate)());this._replaceBtn=this._register(new he({label:x+this._keybindingLabelFor(i.FIND_IDS.ReplaceOneAction),icon:e.findReplaceIcon,hoverDelegate:B,onTrigger:()=>{this._controller.replace()},onKeyDown:te=>{te.equals(1026)&&(this._closeBtn.focus(),te.preventDefault())}},this._hoverService)),this._replaceAllBtn=this._register(new he({label:W+this._keybindingLabelFor(i.FIND_IDS.ReplaceAllAction),icon:e.findReplaceAllIcon,hoverDelegate:B,onTrigger:()=>{this._controller.replaceAll()}},this._hoverService));const $=document.createElement("div");$.className="replace-part",$.appendChild(this._replaceInput.domNode);const Q=document.createElement("div");Q.className="replace-actions",$.appendChild(Q),Q.appendChild(this._replaceBtn.domNode),Q.appendChild(this._replaceAllBtn.domNode),this._toggleReplaceBtn=this._register(new he({label:V,className:"codicon toggle left",onTrigger:()=>{this._state.change({isReplaceRevealed:!this._isReplaceVisible},!1),this._isReplaceVisible&&(this._replaceInput.width=d.getTotalWidth(this._findInput.domNode),this._replaceInput.inputBox.layout()),this._showViewZone()}},this._hoverService)),this._toggleReplaceBtn.setExpanded(this._isReplaceVisible),this._domNode=document.createElement("div"),this._domNode.className="editor-widget find-widget",this._domNode.setAttribute("aria-hidden","true"),this._domNode.ariaLabel=L,this._domNode.role="dialog",this._domNode.style.width=`${H}px`,this._domNode.appendChild(this._toggleReplaceBtn.domNode),this._domNode.appendChild(ge),this._domNode.appendChild(this._closeBtn.domNode),this._domNode.appendChild($),this._resizeSash=this._register(new E.Sash(this._domNode,this,{orientation:0,size:2})),this._resized=!1;let Z=H;this._register(this._resizeSash.onDidStart(()=>{Z=d.getTotalWidth(this._domNode)})),this._register(this._resizeSash.onDidChange(te=>{this._resized=!0;const re=Z+te.startX-te.currentX;if(rele||(this._domNode.style.width=`${re}px`,this._isReplaceVisible&&(this._replaceInput.width=d.getTotalWidth(this._findInput.domNode)),this._findInput.inputBox.layout(),this._tryUpdateHeight())})),this._register(this._resizeSash.onDidReset(()=>{const te=d.getTotalWidth(this._domNode);if(te{this._opts.onTrigger(),ge.preventDefault()}),this.onkeydown(this._domNode,ge=>{if(ge.equals(10)||ge.equals(3)){this._opts.onTrigger(),ge.preventDefault();return}this._opts.onKeyDown?.(ge)})}get domNode(){return this._domNode}isEnabled(){return this._domNode.tabIndex>=0}focus(){this._domNode.focus()}setEnabled(ae){this._domNode.classList.toggle("disabled",!ae),this._domNode.setAttribute("aria-disabled",String(!ae)),this._domNode.tabIndex=ae?0:-1}setExpanded(ae){this._domNode.setAttribute("aria-expanded",String(!!ae)),ae?(this._domNode.classList.remove(...u.ThemeIcon.asClassNameArray(w)),this._domNode.classList.add(...u.ThemeIcon.asClassNameArray(S))):(this._domNode.classList.remove(...u.ThemeIcon.asClassNameArray(S)),this._domNode.classList.add(...u.ThemeIcon.asClassNameArray(w)))}}e.SimpleButton=he,(0,r.registerThemingParticipant)((pe,ae)=>{const ee=pe.getColor(l.editorFindMatchHighlightBorder);ee&&ae.addRule(`.monaco-editor .findMatch { border: 1px ${(0,C.isHighContrast)(pe.type)?"dotted":"solid"} ${ee}; box-sizing: border-box; }`);const de=pe.getColor(l.editorFindRangeHighlightBorder);de&&ae.addRule(`.monaco-editor .findScope { border: 1px ${(0,C.isHighContrast)(pe.type)?"dashed":"solid"} ${de}; }`);const ge=pe.getColor(l.contrastBorder);ge&&ae.addRule(`.monaco-editor .find-widget { border: 1px solid ${ge}; }`);const X=pe.getColor(l.editorFindMatchForeground);X&&ae.addRule(`.monaco-editor .findMatchInline { color: ${X}; }`);const B=pe.getColor(l.editorFindMatchHighlightForeground);B&&ae.addRule(`.monaco-editor .currentFindMatchInline { color: ${B}; }`)})}),define(ne[423],se([1,0,14,2,11,15,80,20,40,220,824,825,826,3,29,117,12,58,31,50,66,101,25,118]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f){"use strict";var h;Object.defineProperty(e,"__esModule",{value:!0}),e.StartFindReplaceAction=e.PreviousSelectionMatchFindAction=e.NextSelectionMatchFindAction=e.SelectionMatchFindAction=e.MoveToMatchFindAction=e.PreviousMatchFindAction=e.NextMatchFindAction=e.MatchFindAction=e.StartFindWithSelectionAction=e.StartFindWithArgsAction=e.StartFindAction=e.FindController=e.CommonFindController=void 0,e.getSelectionSearchString=w;const v=524288;function w(q,H="single",z=!1){if(!q.hasModel())return null;const U=q.getSelection();if(H==="single"&&U.startLineNumber===U.endLineNumber||H==="multiple"){if(U.isEmpty()){const j=q.getConfiguredWordAtPosition(U.getStartPosition());if(j&&z===!1)return j.word}else if(q.getModel().getValueLengthInRange(U)this._onStateChanged(K))),this._model=null,this._register(this._editor.onDidChangeModel(()=>{const K=this._editor.getModel()&&this._state.isRevealed;this.disposeModel(),this._state.change({searchScope:null,matchCase:this._storageService.getBoolean("editor.matchCase",1,!1),wholeWord:this._storageService.getBoolean("editor.wholeWord",1,!1),isRegex:this._storageService.getBoolean("editor.isRegex",1,!1),preserveCase:this._storageService.getBoolean("editor.preserveCase",1,!1)},!1),K&&this._start({forceRevealReplace:!1,seedSearchStringFromSelection:"none",seedSearchStringFromNonEmptySelection:!1,seedSearchStringFromGlobalClipboard:!1,shouldFocus:0,shouldAnimate:!1,updateSearchScope:!1,loop:this._editor.getOption(41).loop})}))}dispose(){this.disposeModel(),super.dispose()}disposeModel(){this._model&&(this._model.dispose(),this._model=null)}_onStateChanged(H){this.saveQueryState(H),H.isRevealed&&(this._state.isRevealed?this._findWidgetVisible.set(!0):(this._findWidgetVisible.reset(),this.disposeModel())),H.searchString&&this.setGlobalBufferTerm(this._state.searchString)}saveQueryState(H){H.isRegex&&this._storageService.store("editor.isRegex",this._state.actualIsRegex,1,1),H.wholeWord&&this._storageService.store("editor.wholeWord",this._state.actualWholeWord,1,1),H.matchCase&&this._storageService.store("editor.matchCase",this._state.actualMatchCase,1,1),H.preserveCase&&this._storageService.store("editor.preserveCase",this._state.actualPreserveCase,1,1)}loadQueryState(){this._state.change({matchCase:this._storageService.getBoolean("editor.matchCase",1,this._state.matchCase),wholeWord:this._storageService.getBoolean("editor.wholeWord",1,this._state.wholeWord),isRegex:this._storageService.getBoolean("editor.isRegex",1,this._state.isRegex),preserveCase:this._storageService.getBoolean("editor.preserveCase",1,this._state.preserveCase)},!1)}isFindInputFocused(){return!!b.CONTEXT_FIND_INPUT_FOCUSED.getValue(this._contextKeyService)}getState(){return this._state}closeFindWidget(){this._state.change({isRevealed:!1,searchScope:null},!1),this._editor.focus()}toggleCaseSensitive(){this._state.change({matchCase:!this._state.matchCase},!1),this._state.isRevealed||this.highlightFindOptions()}toggleWholeWords(){this._state.change({wholeWord:!this._state.wholeWord},!1),this._state.isRevealed||this.highlightFindOptions()}toggleRegex(){this._state.change({isRegex:!this._state.isRegex},!1),this._state.isRevealed||this.highlightFindOptions()}togglePreserveCase(){this._state.change({preserveCase:!this._state.preserveCase},!1),this._state.isRevealed||this.highlightFindOptions()}toggleSearchScope(){if(this._state.searchScope)this._state.change({searchScope:null},!0);else if(this._editor.hasModel()){let H=this._editor.getSelections();H=H.map(z=>(z.endColumn===1&&z.endLineNumber>z.startLineNumber&&(z=z.setEndPosition(z.endLineNumber-1,this._editor.getModel().getLineMaxColumn(z.endLineNumber-1))),z.isEmpty()?null:z)).filter(z=>!!z),H.length&&this._state.change({searchScope:H},!0)}}setSearchString(H){this._state.isRegex&&(H=I.escapeRegExpCharacters(H)),this._state.change({searchString:H},!1)}highlightFindOptions(H=!1){}async _start(H,z){if(this.disposeModel(),!this._editor.hasModel())return;const U={...z,isRevealed:!0};if(H.seedSearchStringFromSelection==="single"){const j=w(this._editor,H.seedSearchStringFromSelection,H.seedSearchStringFromNonEmptySelection);j&&(this._state.isRegex?U.searchString=I.escapeRegExpCharacters(j):U.searchString=j)}else if(H.seedSearchStringFromSelection==="multiple"&&!H.updateSearchScope){const j=w(this._editor,H.seedSearchStringFromSelection);j&&(U.searchString=j)}if(!U.searchString&&H.seedSearchStringFromGlobalClipboard){const j=await this.getGlobalBufferTerm();if(!this._editor.hasModel())return;j&&(U.searchString=j)}if(H.forceRevealReplace||U.isReplaceRevealed?U.isReplaceRevealed=!0:this._findWidgetVisible.get()||(U.isReplaceRevealed=!1),H.updateSearchScope){const j=this._editor.getSelections();j.some(Y=>!Y.isEmpty())&&(U.searchScope=j)}U.loop=H.loop,this._state.change(U,!1),this._model||(this._model=new b.FindModelBoundToEditorModel(this._editor,this._state))}start(H,z){return this._start(H,z)}moveToNextMatch(){return this._model?(this._model.moveToNextMatch(),!0):!1}moveToPrevMatch(){return this._model?(this._model.moveToPrevMatch(),!0):!1}goToMatch(H){return this._model?(this._model.moveToMatch(H),!0):!1}replace(){return this._model?(this._model.replace(),!0):!1}replaceAll(){return this._model?this._editor.getModel()?.isTooLargeForHeapOperation()?(this._notificationService.warn(t.localize(848,"The file is too large to perform a replace all operation.")),!1):(this._model.replaceAll(),!0):!1}selectAllMatches(){return this._model?(this._model.selectAllMatches(),this._editor.focus(),!0):!1}async getGlobalBufferTerm(){return this._editor.getOption(41).globalFindClipboard&&this._editor.hasModel()&&!this._editor.getModel().isTooLargeForSyncing()?this._clipboardService.readFindText():""}setGlobalBufferTerm(H){this._editor.getOption(41).globalFindClipboard&&this._editor.hasModel()&&!this._editor.getModel().isTooLargeForSyncing()&&this._clipboardService.writeFindText(H)}};e.CommonFindController=S,e.CommonFindController=S=h=ke([ce(1,g.IContextKeyService),ce(2,u.IStorageService),ce(3,s.IClipboardService),ce(4,a.INotificationService),ce(5,f.IHoverService)],S);let L=class extends S{constructor(H,z,U,j,Y,G,K,R,J){super(H,U,K,R,G,J),this._contextViewService=z,this._keybindingService=j,this._themeService=Y,this._widget=null,this._findOptionsWidget=null}async _start(H,z){this._widget||this._createFindWidget();const U=this._editor.getSelection();let j=!1;switch(this._editor.getOption(41).autoFindInSelection){case"always":j=!0;break;case"never":j=!1;break;case"multiline":{j=!!U&&U.startLineNumber!==U.endLineNumber;break}default:break}H.updateSearchScope=H.updateSearchScope||j,await super._start(H,z),this._widget&&(H.shouldFocus===2?this._widget.focusReplaceInput():H.shouldFocus===1&&this._widget.focusFindInput())}highlightFindOptions(H=!1){this._widget||this._createFindWidget(),this._state.isRevealed&&!H?this._widget.highlightFindOptions():this._findOptionsWidget.highlightFindOptions()}_createFindWidget(){this._widget=this._register(new o.FindWidget(this._editor,this,this._state,this._contextViewService,this._keybindingService,this._contextKeyService,this._themeService,this._storageService,this._notificationService,this._hoverService)),this._findOptionsWidget=this._register(new p.FindOptionsWidget(this._editor,this._state,this._keybindingService))}};e.FindController=L,e.FindController=L=ke([ce(1,c.IContextViewService),ce(2,g.IContextKeyService),ce(3,l.IKeybindingService),ce(4,C.IThemeService),ce(5,a.INotificationService),ce(6,u.IStorageService),ce(7,s.IClipboardService),ce(8,f.IHoverService)],L),e.StartFindAction=(0,E.registerMultiEditorAction)(new E.MultiEditorAction({id:b.FIND_IDS.StartFindAction,label:t.localize(849,"Find"),alias:"Find",precondition:g.ContextKeyExpr.or(m.EditorContextKeys.focus,g.ContextKeyExpr.has("editorIsOpen")),kbOpts:{kbExpr:null,primary:2084,weight:100},menuOpts:{menuId:i.MenuId.MenubarEditMenu,group:"3_find",title:t.localize(850,"&&Find"),order:1}})),e.StartFindAction.addImplementation(0,(q,H,z)=>{const U=S.get(H);return U?U.start({forceRevealReplace:!1,seedSearchStringFromSelection:H.getOption(41).seedSearchStringFromSelection!=="never"?"single":"none",seedSearchStringFromNonEmptySelection:H.getOption(41).seedSearchStringFromSelection==="selection",seedSearchStringFromGlobalClipboard:H.getOption(41).globalFindClipboard,shouldFocus:1,shouldAnimate:!0,updateSearchScope:!1,loop:H.getOption(41).loop}):!1});const D={description:"Open a new In-Editor Find Widget.",args:[{name:"Open a new In-Editor Find Widget args",schema:{properties:{searchString:{type:"string"},replaceString:{type:"string"},isRegex:{type:"boolean"},matchWholeWord:{type:"boolean"},isCaseSensitive:{type:"boolean"},preserveCase:{type:"boolean"},findInSelection:{type:"boolean"}}}}]};class T extends E.EditorAction{constructor(){super({id:b.FIND_IDS.StartFindWithArgs,label:t.localize(851,"Find With Arguments"),alias:"Find With Arguments",precondition:void 0,kbOpts:{kbExpr:null,primary:0,weight:100},metadata:D})}async run(H,z,U){const j=S.get(z);if(j){const Y=U?{searchString:U.searchString,replaceString:U.replaceString,isReplaceRevealed:U.replaceString!==void 0,isRegex:U.isRegex,wholeWord:U.matchWholeWord,matchCase:U.isCaseSensitive,preserveCase:U.preserveCase}:{};await j.start({forceRevealReplace:!1,seedSearchStringFromSelection:j.getState().searchString.length===0&&z.getOption(41).seedSearchStringFromSelection!=="never"?"single":"none",seedSearchStringFromNonEmptySelection:z.getOption(41).seedSearchStringFromSelection==="selection",seedSearchStringFromGlobalClipboard:!0,shouldFocus:1,shouldAnimate:!0,updateSearchScope:U?.findInSelection||!1,loop:z.getOption(41).loop},Y),j.setGlobalBufferTerm(j.getState().searchString)}}}e.StartFindWithArgsAction=T;class M extends E.EditorAction{constructor(){super({id:b.FIND_IDS.StartFindWithSelection,label:t.localize(852,"Find With Selection"),alias:"Find With Selection",precondition:void 0,kbOpts:{kbExpr:null,primary:0,mac:{primary:2083},weight:100}})}async run(H,z){const U=S.get(z);U&&(await U.start({forceRevealReplace:!1,seedSearchStringFromSelection:"multiple",seedSearchStringFromNonEmptySelection:!1,seedSearchStringFromGlobalClipboard:!1,shouldFocus:0,shouldAnimate:!0,updateSearchScope:!1,loop:z.getOption(41).loop}),U.setGlobalBufferTerm(U.getState().searchString))}}e.StartFindWithSelectionAction=M;class A extends E.EditorAction{async run(H,z){const U=S.get(z);U&&!this._run(U)&&(await U.start({forceRevealReplace:!1,seedSearchStringFromSelection:U.getState().searchString.length===0&&z.getOption(41).seedSearchStringFromSelection!=="never"?"single":"none",seedSearchStringFromNonEmptySelection:z.getOption(41).seedSearchStringFromSelection==="selection",seedSearchStringFromGlobalClipboard:!0,shouldFocus:0,shouldAnimate:!0,updateSearchScope:!1,loop:z.getOption(41).loop}),this._run(U))}}e.MatchFindAction=A;class P extends A{constructor(){super({id:b.FIND_IDS.NextMatchFindAction,label:t.localize(853,"Find Next"),alias:"Find Next",precondition:void 0,kbOpts:[{kbExpr:m.EditorContextKeys.focus,primary:61,mac:{primary:2085,secondary:[61]},weight:100},{kbExpr:g.ContextKeyExpr.and(m.EditorContextKeys.focus,b.CONTEXT_FIND_INPUT_FOCUSED),primary:3,weight:100}]})}_run(H){return H.moveToNextMatch()?(H.editor.pushUndoStop(),!0):!1}}e.NextMatchFindAction=P;class N extends A{constructor(){super({id:b.FIND_IDS.PreviousMatchFindAction,label:t.localize(854,"Find Previous"),alias:"Find Previous",precondition:void 0,kbOpts:[{kbExpr:m.EditorContextKeys.focus,primary:1085,mac:{primary:3109,secondary:[1085]},weight:100},{kbExpr:g.ContextKeyExpr.and(m.EditorContextKeys.focus,b.CONTEXT_FIND_INPUT_FOCUSED),primary:1027,weight:100}]})}_run(H){return H.moveToPrevMatch()}}e.PreviousMatchFindAction=N;class O extends E.EditorAction{constructor(){super({id:b.FIND_IDS.GoToMatchFindAction,label:t.localize(855,"Go to Match..."),alias:"Go to Match...",precondition:b.CONTEXT_FIND_WIDGET_VISIBLE}),this._highlightDecorations=[]}run(H,z,U){const j=S.get(z);if(!j)return;const Y=j.getState().matchesCount;if(Y<1){H.get(a.INotificationService).notify({severity:a.Severity.Warning,message:t.localize(856,"No matches. Try searching for something else.")});return}const G=H.get(r.IQuickInputService),K=new k.DisposableStore,R=K.add(G.createInputBox());R.placeholder=t.localize(857,"Type a number to go to a specific match (between 1 and {0})",Y);const J=ue=>{const he=parseInt(ue);if(isNaN(he))return;const pe=j.getState().matchesCount;if(he>0&&he<=pe)return he-1;if(he<0&&he>=-pe)return pe+he},ie=ue=>{const he=J(ue);if(typeof he=="number"){R.validationMessage=void 0,j.goToMatch(he);const pe=j.getState().currentMatch;pe&&this.addDecorations(z,pe)}else R.validationMessage=t.localize(858,"Please type a number between 1 and {0}",j.getState().matchesCount),this.clearDecorations(z)};K.add(R.onDidChangeValue(ue=>{ie(ue)})),K.add(R.onDidAccept(()=>{const ue=J(R.value);typeof ue=="number"?(j.goToMatch(ue),R.hide()):R.validationMessage=t.localize(859,"Please type a number between 1 and {0}",j.getState().matchesCount)})),K.add(R.onDidHide(()=>{this.clearDecorations(z),K.dispose()})),R.show()}clearDecorations(H){H.changeDecorations(z=>{this._highlightDecorations=z.deltaDecorations(this._highlightDecorations,[])})}addDecorations(H,z){H.changeDecorations(U=>{this._highlightDecorations=U.deltaDecorations(this._highlightDecorations,[{range:z,options:{description:"find-match-quick-access-range-highlight",className:"rangeHighlight",isWholeLine:!0}},{range:z,options:{description:"find-match-quick-access-range-highlight-overview",overviewRuler:{color:(0,C.themeColorFromId)(y.overviewRulerRangeHighlight),position:_.OverviewRulerLane.Full}}}])})}}e.MoveToMatchFindAction=O;class F extends E.EditorAction{async run(H,z){const U=S.get(z);if(!U)return;const j=w(z,"single",!1);j&&U.setSearchString(j),this._run(U)||(await U.start({forceRevealReplace:!1,seedSearchStringFromSelection:"none",seedSearchStringFromNonEmptySelection:!1,seedSearchStringFromGlobalClipboard:!1,shouldFocus:0,shouldAnimate:!0,updateSearchScope:!1,loop:z.getOption(41).loop}),this._run(U))}}e.SelectionMatchFindAction=F;class x extends F{constructor(){super({id:b.FIND_IDS.NextSelectionMatchFindAction,label:t.localize(860,"Find Next Selection"),alias:"Find Next Selection",precondition:void 0,kbOpts:{kbExpr:m.EditorContextKeys.focus,primary:2109,weight:100}})}_run(H){return H.moveToNextMatch()}}e.NextSelectionMatchFindAction=x;class W extends F{constructor(){super({id:b.FIND_IDS.PreviousSelectionMatchFindAction,label:t.localize(861,"Find Previous Selection"),alias:"Find Previous Selection",precondition:void 0,kbOpts:{kbExpr:m.EditorContextKeys.focus,primary:3133,weight:100}})}_run(H){return H.moveToPrevMatch()}}e.PreviousSelectionMatchFindAction=W,e.StartFindReplaceAction=(0,E.registerMultiEditorAction)(new E.MultiEditorAction({id:b.FIND_IDS.StartFindReplaceAction,label:t.localize(862,"Replace"),alias:"Replace",precondition:g.ContextKeyExpr.or(m.EditorContextKeys.focus,g.ContextKeyExpr.has("editorIsOpen")),kbOpts:{kbExpr:null,primary:2086,mac:{primary:2596},weight:100},menuOpts:{menuId:i.MenuId.MenubarEditMenu,group:"3_find",title:t.localize(863,"&&Replace"),order:2}})),e.StartFindReplaceAction.addImplementation(0,(q,H,z)=>{if(!H.hasModel()||H.getOption(92))return!1;const U=S.get(H);if(!U)return!1;const j=H.getSelection(),Y=U.isFindInputFocused(),G=!j.isEmpty()&&j.startLineNumber===j.endLineNumber&&H.getOption(41).seedSearchStringFromSelection!=="never"&&!Y,K=Y||G?2:1;return U.start({forceRevealReplace:!0,seedSearchStringFromSelection:G?"single":"none",seedSearchStringFromNonEmptySelection:H.getOption(41).seedSearchStringFromSelection==="selection",seedSearchStringFromGlobalClipboard:H.getOption(41).seedSearchStringFromSelection!=="never",shouldFocus:K,shouldAnimate:!0,updateSearchScope:!1,loop:H.getOption(41).loop})}),(0,E.registerEditorContribution)(S.ID,L,0),(0,E.registerEditorAction)(T),(0,E.registerEditorAction)(M),(0,E.registerEditorAction)(P),(0,E.registerEditorAction)(N),(0,E.registerEditorAction)(O),(0,E.registerEditorAction)(x),(0,E.registerEditorAction)(W);const V=E.EditorCommand.bindToContribution(S.get);(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.CloseFindWidgetCommand,precondition:b.CONTEXT_FIND_WIDGET_VISIBLE,handler:q=>q.closeFindWidget(),kbOpts:{weight:105,kbExpr:g.ContextKeyExpr.and(m.EditorContextKeys.focus,g.ContextKeyExpr.not("isComposing")),primary:9,secondary:[1033]}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ToggleCaseSensitiveCommand,precondition:void 0,handler:q=>q.toggleCaseSensitive(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:b.ToggleCaseSensitiveKeybinding.primary,mac:b.ToggleCaseSensitiveKeybinding.mac,win:b.ToggleCaseSensitiveKeybinding.win,linux:b.ToggleCaseSensitiveKeybinding.linux}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ToggleWholeWordCommand,precondition:void 0,handler:q=>q.toggleWholeWords(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:b.ToggleWholeWordKeybinding.primary,mac:b.ToggleWholeWordKeybinding.mac,win:b.ToggleWholeWordKeybinding.win,linux:b.ToggleWholeWordKeybinding.linux}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ToggleRegexCommand,precondition:void 0,handler:q=>q.toggleRegex(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:b.ToggleRegexKeybinding.primary,mac:b.ToggleRegexKeybinding.mac,win:b.ToggleRegexKeybinding.win,linux:b.ToggleRegexKeybinding.linux}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ToggleSearchScopeCommand,precondition:void 0,handler:q=>q.toggleSearchScope(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:b.ToggleSearchScopeKeybinding.primary,mac:b.ToggleSearchScopeKeybinding.mac,win:b.ToggleSearchScopeKeybinding.win,linux:b.ToggleSearchScopeKeybinding.linux}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.TogglePreserveCaseCommand,precondition:void 0,handler:q=>q.togglePreserveCase(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:b.TogglePreserveCaseKeybinding.primary,mac:b.TogglePreserveCaseKeybinding.mac,win:b.TogglePreserveCaseKeybinding.win,linux:b.TogglePreserveCaseKeybinding.linux}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ReplaceOneAction,precondition:b.CONTEXT_FIND_WIDGET_VISIBLE,handler:q=>q.replace(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:3094}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ReplaceOneAction,precondition:b.CONTEXT_FIND_WIDGET_VISIBLE,handler:q=>q.replace(),kbOpts:{weight:105,kbExpr:g.ContextKeyExpr.and(m.EditorContextKeys.focus,b.CONTEXT_REPLACE_INPUT_FOCUSED),primary:3}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ReplaceAllAction,precondition:b.CONTEXT_FIND_WIDGET_VISIBLE,handler:q=>q.replaceAll(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:2563}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.ReplaceAllAction,precondition:b.CONTEXT_FIND_WIDGET_VISIBLE,handler:q=>q.replaceAll(),kbOpts:{weight:105,kbExpr:g.ContextKeyExpr.and(m.EditorContextKeys.focus,b.CONTEXT_REPLACE_INPUT_FOCUSED),primary:void 0,mac:{primary:2051}}})),(0,E.registerEditorCommand)(new V({id:b.FIND_IDS.SelectAllMatchesAction,precondition:b.CONTEXT_FIND_WIDGET_VISIBLE,handler:q=>q.selectAllMatches(),kbOpts:{weight:105,kbExpr:m.EditorContextKeys.focus,primary:515}}))}),define(ne[424],se([1,0,26,35,3,32,71,25,30]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.FoldingDecorationProvider=e.foldingManualExpandedIcon=e.foldingManualCollapsedIcon=e.foldingCollapsedIcon=e.foldingExpandedIcon=void 0;const b=(0,E.registerColor)("editor.foldBackground",{light:(0,E.transparent)(E.editorSelectionBackground,.3),dark:(0,E.transparent)(E.editorSelectionBackground,.3),hcDark:null,hcLight:null},(0,I.localize)(910,"Background color behind folded ranges. The color must not be opaque so as not to hide underlying decorations."),!0);(0,E.registerColor)("editor.foldPlaceholderForeground",{light:"#808080",dark:"#808080",hcDark:null,hcLight:null},(0,I.localize)(911,"Color of the collapsed text after the first line of a folded range.")),(0,E.registerColor)("editorGutter.foldingControlForeground",E.iconForeground,(0,I.localize)(912,"Color of the folding control in the editor gutter.")),e.foldingExpandedIcon=(0,y.registerIcon)("folding-expanded",d.Codicon.chevronDown,(0,I.localize)(913,"Icon for expanded ranges in the editor glyph margin.")),e.foldingCollapsedIcon=(0,y.registerIcon)("folding-collapsed",d.Codicon.chevronRight,(0,I.localize)(914,"Icon for collapsed ranges in the editor glyph margin.")),e.foldingManualCollapsedIcon=(0,y.registerIcon)("folding-manual-collapsed",e.foldingCollapsedIcon,(0,I.localize)(915,"Icon for manually collapsed ranges in the editor glyph margin.")),e.foldingManualExpandedIcon=(0,y.registerIcon)("folding-manual-expanded",e.foldingExpandedIcon,(0,I.localize)(916,"Icon for manually expanded ranges in the editor glyph margin."));const p={color:(0,m.themeColorFromId)(b),position:1},n=(0,I.localize)(917,"Click to expand the range."),o=(0,I.localize)(918,"Click to collapse the range.");class t{static{this.COLLAPSED_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-collapsed-visual-decoration",stickiness:0,afterContentClassName:"inline-folded",isWholeLine:!0,linesDecorationsTooltip:n,firstLineDecorationClassName:_.ThemeIcon.asClassName(e.foldingCollapsedIcon)})}static{this.COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-collapsed-highlighted-visual-decoration",stickiness:0,afterContentClassName:"inline-folded",className:"folded-background",minimap:p,isWholeLine:!0,linesDecorationsTooltip:n,firstLineDecorationClassName:_.ThemeIcon.asClassName(e.foldingCollapsedIcon)})}static{this.MANUALLY_COLLAPSED_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-manually-collapsed-visual-decoration",stickiness:0,afterContentClassName:"inline-folded",isWholeLine:!0,linesDecorationsTooltip:n,firstLineDecorationClassName:_.ThemeIcon.asClassName(e.foldingManualCollapsedIcon)})}static{this.MANUALLY_COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-manually-collapsed-highlighted-visual-decoration",stickiness:0,afterContentClassName:"inline-folded",className:"folded-background",minimap:p,isWholeLine:!0,linesDecorationsTooltip:n,firstLineDecorationClassName:_.ThemeIcon.asClassName(e.foldingManualCollapsedIcon)})}static{this.NO_CONTROLS_COLLAPSED_RANGE_DECORATION=k.ModelDecorationOptions.register({description:"folding-no-controls-range-decoration",stickiness:0,afterContentClassName:"inline-folded",isWholeLine:!0,linesDecorationsTooltip:n})}static{this.NO_CONTROLS_COLLAPSED_HIGHLIGHTED_RANGE_DECORATION=k.ModelDecorationOptions.register({description:"folding-no-controls-range-decoration",stickiness:0,afterContentClassName:"inline-folded",className:"folded-background",minimap:p,isWholeLine:!0,linesDecorationsTooltip:n})}static{this.EXPANDED_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-expanded-visual-decoration",stickiness:1,isWholeLine:!0,firstLineDecorationClassName:"alwaysShowFoldIcons "+_.ThemeIcon.asClassName(e.foldingExpandedIcon),linesDecorationsTooltip:o})}static{this.EXPANDED_AUTO_HIDE_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-expanded-auto-hide-visual-decoration",stickiness:1,isWholeLine:!0,firstLineDecorationClassName:_.ThemeIcon.asClassName(e.foldingExpandedIcon),linesDecorationsTooltip:o})}static{this.MANUALLY_EXPANDED_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-manually-expanded-visual-decoration",stickiness:0,isWholeLine:!0,firstLineDecorationClassName:"alwaysShowFoldIcons "+_.ThemeIcon.asClassName(e.foldingManualExpandedIcon),linesDecorationsTooltip:o})}static{this.MANUALLY_EXPANDED_AUTO_HIDE_VISUAL_DECORATION=k.ModelDecorationOptions.register({description:"folding-manually-expanded-auto-hide-visual-decoration",stickiness:0,isWholeLine:!0,firstLineDecorationClassName:_.ThemeIcon.asClassName(e.foldingManualExpandedIcon),linesDecorationsTooltip:o})}static{this.NO_CONTROLS_EXPANDED_RANGE_DECORATION=k.ModelDecorationOptions.register({description:"folding-no-controls-range-decoration",stickiness:0,isWholeLine:!0})}static{this.HIDDEN_RANGE_DECORATION=k.ModelDecorationOptions.register({description:"folding-hidden-range-decoration",stickiness:1})}constructor(s){this.editor=s,this.showFoldingControls="mouseover",this.showFoldingHighlights=!0}getDecorationOption(s,g,c){return g?t.HIDDEN_RANGE_DECORATION:this.showFoldingControls==="never"?s?this.showFoldingHighlights?t.NO_CONTROLS_COLLAPSED_HIGHLIGHTED_RANGE_DECORATION:t.NO_CONTROLS_COLLAPSED_RANGE_DECORATION:t.NO_CONTROLS_EXPANDED_RANGE_DECORATION:s?c?this.showFoldingHighlights?t.MANUALLY_COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION:t.MANUALLY_COLLAPSED_VISUAL_DECORATION:this.showFoldingHighlights?t.COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION:t.COLLAPSED_VISUAL_DECORATION:this.showFoldingControls==="mouseover"?c?t.MANUALLY_EXPANDED_AUTO_HIDE_VISUAL_DECORATION:t.EXPANDED_AUTO_HIDE_VISUAL_DECORATION:c?t.MANUALLY_EXPANDED_VISUAL_DECORATION:t.EXPANDED_VISUAL_DECORATION}changeDecorations(s){return this.editor.changeDecorations(s)}removeDecorations(s){this.editor.removeDecorations(s)}}e.FoldingDecorationProvider=t}),define(ne[289],se([1,0,14,18,8,72,2,11,19,143,15,20,27,36,334,613,335,3,12,424,203,336,50,79,54,17,6,24,22,51,28,511]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T){"use strict";var M;Object.defineProperty(e,"__esModule",{value:!0}),e.RangesLimitReporter=e.FoldingController=void 0,e.toSelectedLines=F;const A=new l.RawContextKey("foldingEnabled",!1);let P=class extends y.Disposable{static{M=this}static{this.ID="editor.contrib.folding"}static get(X){return X.getContribution(M.ID)}static getFoldingRangeProviders(X,B){const $=X.foldingRangeProvider.ordered(B);return M._foldingRangeSelector?.($,B)??$}constructor(X,B,$,Q,Z,te){super(),this.contextKeyService=B,this.languageConfigurationService=$,this.languageFeaturesService=te,this.localToDispose=this._register(new y.DisposableStore),this.editor=X,this._foldingLimitReporter=new N(X);const re=this.editor.getOptions();this._isEnabled=re.get(43),this._useFoldingProviders=re.get(44)!=="indentation",this._unfoldOnClickAfterEndOfLine=re.get(48),this._restoringViewState=!1,this._currentModelHasFoldedImports=!1,this._foldingImportsByDefault=re.get(46),this.updateDebounceInfo=Z.for(te.foldingRangeProvider,"Folding",{min:200}),this.foldingModel=null,this.hiddenRangeModel=null,this.rangeProvider=null,this.foldingRegionPromise=null,this.foldingModelPromise=null,this.updateScheduler=null,this.cursorChangedScheduler=null,this.mouseDownInfo=null,this.foldingDecorationProvider=new a.FoldingDecorationProvider(X),this.foldingDecorationProvider.showFoldingControls=re.get(111),this.foldingDecorationProvider.showFoldingHighlights=re.get(45),this.foldingEnabled=A.bindTo(this.contextKeyService),this.foldingEnabled.set(this._isEnabled),this._register(this.editor.onDidChangeModel(()=>this.onModelChanged())),this._register(this.editor.onDidChangeConfiguration(le=>{if(le.hasChanged(43)&&(this._isEnabled=this.editor.getOptions().get(43),this.foldingEnabled.set(this._isEnabled),this.onModelChanged()),le.hasChanged(47)&&this.onModelChanged(),le.hasChanged(111)||le.hasChanged(45)){const me=this.editor.getOptions();this.foldingDecorationProvider.showFoldingControls=me.get(111),this.foldingDecorationProvider.showFoldingHighlights=me.get(45),this.triggerFoldingModelChanged()}le.hasChanged(44)&&(this._useFoldingProviders=this.editor.getOptions().get(44)!=="indentation",this.onFoldingStrategyChanged()),le.hasChanged(48)&&(this._unfoldOnClickAfterEndOfLine=this.editor.getOptions().get(48)),le.hasChanged(46)&&(this._foldingImportsByDefault=this.editor.getOptions().get(46))})),this.onModelChanged()}saveViewState(){const X=this.editor.getModel();if(!X||!this._isEnabled||X.isTooLargeForTokenization())return{};if(this.foldingModel){const B=this.foldingModel.getMemento(),$=this.rangeProvider?this.rangeProvider.id:void 0;return{collapsedRegions:B,lineCount:X.getLineCount(),provider:$,foldedImports:this._currentModelHasFoldedImports}}}restoreViewState(X){const B=this.editor.getModel();if(!(!B||!this._isEnabled||B.isTooLargeForTokenization()||!this.hiddenRangeModel)&&X&&(this._currentModelHasFoldedImports=!!X.foldedImports,X.collapsedRegions&&X.collapsedRegions.length>0&&this.foldingModel)){this._restoringViewState=!0;try{this.foldingModel.applyMemento(X.collapsedRegions)}finally{this._restoringViewState=!1}}}onModelChanged(){this.localToDispose.clear();const X=this.editor.getModel();!this._isEnabled||!X||X.isTooLargeForTokenization()||(this._currentModelHasFoldedImports=!1,this.foldingModel=new i.FoldingModel(X,this.foldingDecorationProvider),this.localToDispose.add(this.foldingModel),this.hiddenRangeModel=new s.HiddenRangeModel(this.foldingModel),this.localToDispose.add(this.hiddenRangeModel),this.localToDispose.add(this.hiddenRangeModel.onDidChange(B=>this.onHiddenRangesChanges(B))),this.updateScheduler=new d.Delayer(this.updateDebounceInfo.get(X)),this.cursorChangedScheduler=new d.RunOnceScheduler(()=>this.revealCursor(),200),this.localToDispose.add(this.cursorChangedScheduler),this.localToDispose.add(this.languageFeaturesService.foldingRangeProvider.onDidChange(()=>this.onFoldingStrategyChanged())),this.localToDispose.add(this.editor.onDidChangeModelLanguageConfiguration(()=>this.onFoldingStrategyChanged())),this.localToDispose.add(this.editor.onDidChangeModelContent(B=>this.onDidChangeModelContent(B))),this.localToDispose.add(this.editor.onDidChangeCursorPosition(()=>this.onCursorPositionChanged())),this.localToDispose.add(this.editor.onMouseDown(B=>this.onEditorMouseDown(B))),this.localToDispose.add(this.editor.onMouseUp(B=>this.onEditorMouseUp(B))),this.localToDispose.add({dispose:()=>{this.foldingRegionPromise&&(this.foldingRegionPromise.cancel(),this.foldingRegionPromise=null),this.updateScheduler?.cancel(),this.updateScheduler=null,this.foldingModel=null,this.foldingModelPromise=null,this.hiddenRangeModel=null,this.cursorChangedScheduler=null,this.rangeProvider?.dispose(),this.rangeProvider=null}}),this.triggerFoldingModelChanged())}onFoldingStrategyChanged(){this.rangeProvider?.dispose(),this.rangeProvider=null,this.triggerFoldingModelChanged()}getRangeProvider(X){if(this.rangeProvider)return this.rangeProvider;const B=new g.IndentRangeProvider(X,this.languageConfigurationService,this._foldingLimitReporter);if(this.rangeProvider=B,this._useFoldingProviders&&this.foldingModel){const $=M.getFoldingRangeProviders(this.languageFeaturesService,X);$.length>0&&(this.rangeProvider=new u.SyntaxRangeProvider(X,$,()=>this.triggerFoldingModelChanged(),this._foldingLimitReporter,B))}return this.rangeProvider}getFoldingModel(){return this.foldingModelPromise}onDidChangeModelContent(X){this.hiddenRangeModel?.notifyChangeModelContent(X),this.triggerFoldingModelChanged()}triggerFoldingModelChanged(){this.updateScheduler&&(this.foldingRegionPromise&&(this.foldingRegionPromise.cancel(),this.foldingRegionPromise=null),this.foldingModelPromise=this.updateScheduler.trigger(()=>{const X=this.foldingModel;if(!X)return null;const B=new h.StopWatch,$=this.getRangeProvider(X.textModel),Q=this.foldingRegionPromise=(0,d.createCancelablePromise)(Z=>$.compute(Z));return Q.then(Z=>{if(Z&&Q===this.foldingRegionPromise){let te;if(this._foldingImportsByDefault&&!this._currentModelHasFoldedImports){const me=Z.setCollapsedAllOfType(o.FoldingRangeKind.Imports.value,!0);me&&(te=b.StableEditorScrollState.capture(this.editor),this._currentModelHasFoldedImports=me)}const re=this.editor.getSelections();X.update(Z,F(re)),te?.restore(this.editor);const le=this.updateDebounceInfo.update(X.textModel,B.elapsed());this.updateScheduler&&(this.updateScheduler.defaultDelay=le)}return X})}).then(void 0,X=>((0,I.onUnexpectedError)(X),null)))}onHiddenRangesChanges(X){if(this.hiddenRangeModel&&X.length&&!this._restoringViewState){const B=this.editor.getSelections();B&&this.hiddenRangeModel.adjustSelections(B)&&this.editor.setSelections(B)}this.editor.setHiddenAreas(X,this)}onCursorPositionChanged(){this.hiddenRangeModel&&this.hiddenRangeModel.hasRanges()&&this.cursorChangedScheduler.schedule()}revealCursor(){const X=this.getFoldingModel();X&&X.then(B=>{if(B){const $=this.editor.getSelections();if($&&$.length>0){const Q=[];for(const Z of $){const te=Z.selectionStartLineNumber;this.hiddenRangeModel&&this.hiddenRangeModel.isHidden(te)&&Q.push(...B.getAllRegionsAtLine(te,re=>re.isCollapsed&&te>re.startLineNumber))}Q.length&&(B.toggleCollapseState(Q),this.reveal($[0].getPosition()))}}}).then(void 0,I.onUnexpectedError)}onEditorMouseDown(X){if(this.mouseDownInfo=null,!this.hiddenRangeModel||!X.target||!X.target.range||!X.event.leftButton&&!X.event.middleButton)return;const B=X.target.range;let $=!1;switch(X.target.type){case 4:{const Q=X.target.detail,Z=X.target.element.offsetLeft;if(Q.offsetX-Z<4)return;$=!0;break}case 7:{if(this._unfoldOnClickAfterEndOfLine&&this.hiddenRangeModel.hasRanges()&&!X.target.detail.isAfterLines)break;return}case 6:{if(this.hiddenRangeModel.hasRanges()){const Q=this.editor.getModel();if(Q&&B.startColumn===Q.getLineMaxColumn(B.startLineNumber))break}return}default:return}this.mouseDownInfo={lineNumber:B.startLineNumber,iconClicked:$}}onEditorMouseUp(X){const B=this.foldingModel;if(!B||!this.mouseDownInfo||!X.target)return;const $=this.mouseDownInfo.lineNumber,Q=this.mouseDownInfo.iconClicked,Z=X.target.range;if(!Z||Z.startLineNumber!==$)return;if(Q){if(X.target.type!==4)return}else{const re=this.editor.getModel();if(!re||Z.startColumn!==re.getLineMaxColumn($))return}const te=B.getRegionAtLine($);if(te&&te.startLineNumber===$){const re=te.isCollapsed;if(Q||re){const le=X.event.altKey;let me=[];if(le){const Ce=Le=>!Le.containedBy(te)&&!te.containedBy(Le),ye=B.getRegionsInside(null,Ce);for(const Le of ye)Le.isCollapsed&&me.push(Le);me.length===0&&(me=ye)}else{const Ce=X.event.middleButton||X.event.shiftKey;if(Ce)for(const ye of B.getRegionsInside(te))ye.isCollapsed===re&&me.push(ye);(re||!Ce||me.length===0)&&me.push(te)}B.toggleCollapseState(me),this.reveal({lineNumber:$,column:1})}}}reveal(X){this.editor.revealPositionInCenterIfOutsideViewport(X,0)}};e.FoldingController=P,e.FoldingController=P=M=ke([ce(1,l.IContextKeyService),ce(2,t.ILanguageConfigurationService),ce(3,C.INotificationService),ce(4,f.ILanguageFeatureDebounceService),ce(5,v.ILanguageFeaturesService)],P);class N{constructor(X){this.editor=X,this._onDidChange=new w.Emitter,this._computed=0,this._limited=!1}get limit(){return this.editor.getOptions().get(47)}update(X,B){(X!==this._computed||B!==this._limited)&&(this._computed=X,this._limited=B,this._onDidChange.fire())}}e.RangesLimitReporter=N;class O extends p.EditorAction{runEditorCommand(X,B,$){const Q=X.get(t.ILanguageConfigurationService),Z=P.get(B);if(!Z)return;const te=Z.getFoldingModel();if(te)return this.reportTelemetry(X,B),te.then(re=>{if(re){this.invoke(Z,re,B,$,Q);const le=B.getSelection();le&&Z.reveal(le.getStartPosition())}})}getSelectedLines(X){const B=X.getSelections();return B?B.map($=>$.startLineNumber):[]}getLineNumbers(X,B){return X&&X.selectionLines?X.selectionLines.map($=>$+1):this.getSelectedLines(B)}run(X,B){}}function F(ge){return!ge||ge.length===0?{startsInside:()=>!1}:{startsInside(X,B){for(const $ of ge){const Q=$.startLineNumber;if(Q>=X&&Q<=B)return!0}return!1}}}function x(ge){if(!_.isUndefined(ge)){if(!_.isObject(ge))return!1;const X=ge;if(!_.isUndefined(X.levels)&&!_.isNumber(X.levels)||!_.isUndefined(X.direction)&&!_.isString(X.direction)||!_.isUndefined(X.selectionLines)&&(!Array.isArray(X.selectionLines)||!X.selectionLines.every(_.isNumber)))return!1}return!0}class W extends O{constructor(){super({id:"editor.unfold",label:c.localize(891,"Unfold"),alias:"Unfold",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:3166,mac:{primary:2654},weight:100},metadata:{description:"Unfold the content in the editor",args:[{name:"Unfold editor argument",description:`Property-value pairs that can be passed through this argument: * 'levels': Number of levels to unfold. If not set, defaults to 1. * 'direction': If 'up', unfold given number of levels up otherwise unfolds down. * 'selectionLines': Array of the start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used. `,constraint:x,schema:{type:"object",properties:{levels:{type:"number",default:1},direction:{type:"string",enum:["up","down"],default:"down"},selectionLines:{type:"array",items:{type:"number"}}}}}]}})}invoke(X,B,$,Q){const Z=Q&&Q.levels||1,te=this.getLineNumbers(Q,$);Q&&Q.direction==="up"?(0,i.setCollapseStateLevelsUp)(B,!1,Z,te):(0,i.setCollapseStateLevelsDown)(B,!1,Z,te)}}class V extends O{constructor(){super({id:"editor.unfoldRecursively",label:c.localize(892,"Unfold Recursively"),alias:"Unfold Recursively",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2142),weight:100}})}invoke(X,B,$,Q){(0,i.setCollapseStateLevelsDown)(B,!1,Number.MAX_VALUE,this.getSelectedLines($))}}class q extends O{constructor(){super({id:"editor.fold",label:c.localize(893,"Fold"),alias:"Fold",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:3164,mac:{primary:2652},weight:100},metadata:{description:"Fold the content in the editor",args:[{name:"Fold editor argument",description:`Property-value pairs that can be passed through this argument: * 'levels': Number of levels to fold. * 'direction': If 'up', folds given number of levels up otherwise folds down. * 'selectionLines': Array of the start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used. If no levels or direction is set, folds the region at the locations or if already collapsed, the first uncollapsed parent instead. `,constraint:x,schema:{type:"object",properties:{levels:{type:"number"},direction:{type:"string",enum:["up","down"]},selectionLines:{type:"array",items:{type:"number"}}}}}]}})}invoke(X,B,$,Q){const Z=this.getLineNumbers(Q,$),te=Q&&Q.levels,re=Q&&Q.direction;typeof te!="number"&&typeof re!="string"?(0,i.setCollapseStateUp)(B,!0,Z):re==="up"?(0,i.setCollapseStateLevelsUp)(B,!0,te||1,Z):(0,i.setCollapseStateLevelsDown)(B,!0,te||1,Z)}}class H extends O{constructor(){super({id:"editor.toggleFold",label:c.localize(894,"Toggle Fold"),alias:"Toggle Fold",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2090),weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);(0,i.toggleCollapseState)(B,1,Q)}}class z extends O{constructor(){super({id:"editor.foldRecursively",label:c.localize(895,"Fold Recursively"),alias:"Fold Recursively",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2140),weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);(0,i.setCollapseStateLevelsDown)(B,!0,Number.MAX_VALUE,Q)}}class U extends O{constructor(){super({id:"editor.toggleFoldRecursively",label:c.localize(896,"Toggle Fold Recursively"),alias:"Toggle Fold Recursively",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,3114),weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);(0,i.toggleCollapseState)(B,Number.MAX_VALUE,Q)}}class j extends O{constructor(){super({id:"editor.foldAllBlockComments",label:c.localize(897,"Fold All Block Comments"),alias:"Fold All Block Comments",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2138),weight:100}})}invoke(X,B,$,Q,Z){if(B.regions.hasTypes())(0,i.setCollapseStateForType)(B,o.FoldingRangeKind.Comment.value,!0);else{const te=$.getModel();if(!te)return;const re=Z.getLanguageConfiguration(te.getLanguageId()).comments;if(re&&re.blockCommentStartToken){const le=new RegExp("^\\s*"+(0,m.escapeRegExpCharacters)(re.blockCommentStartToken));(0,i.setCollapseStateForMatchingLines)(B,le,!0)}}}}class Y extends O{constructor(){super({id:"editor.foldAllMarkerRegions",label:c.localize(898,"Fold All Regions"),alias:"Fold All Regions",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2077),weight:100}})}invoke(X,B,$,Q,Z){if(B.regions.hasTypes())(0,i.setCollapseStateForType)(B,o.FoldingRangeKind.Region.value,!0);else{const te=$.getModel();if(!te)return;const re=Z.getLanguageConfiguration(te.getLanguageId()).foldingRules;if(re&&re.markers&&re.markers.start){const le=new RegExp(re.markers.start);(0,i.setCollapseStateForMatchingLines)(B,le,!0)}}}}class G extends O{constructor(){super({id:"editor.unfoldAllMarkerRegions",label:c.localize(899,"Unfold All Regions"),alias:"Unfold All Regions",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2078),weight:100}})}invoke(X,B,$,Q,Z){if(B.regions.hasTypes())(0,i.setCollapseStateForType)(B,o.FoldingRangeKind.Region.value,!1);else{const te=$.getModel();if(!te)return;const re=Z.getLanguageConfiguration(te.getLanguageId()).foldingRules;if(re&&re.markers&&re.markers.start){const le=new RegExp(re.markers.start);(0,i.setCollapseStateForMatchingLines)(B,le,!1)}}}}class K extends O{constructor(){super({id:"editor.foldAllExcept",label:c.localize(900,"Fold All Except Selected"),alias:"Fold All Except Selected",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2136),weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);(0,i.setCollapseStateForRest)(B,!0,Q)}}class R extends O{constructor(){super({id:"editor.unfoldAllExcept",label:c.localize(901,"Unfold All Except Selected"),alias:"Unfold All Except Selected",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2134),weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);(0,i.setCollapseStateForRest)(B,!1,Q)}}class J extends O{constructor(){super({id:"editor.foldAll",label:c.localize(902,"Fold All"),alias:"Fold All",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2069),weight:100}})}invoke(X,B,$){(0,i.setCollapseStateLevelsDown)(B,!0)}}class ie extends O{constructor(){super({id:"editor.unfoldAll",label:c.localize(903,"Unfold All"),alias:"Unfold All",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2088),weight:100}})}invoke(X,B,$){(0,i.setCollapseStateLevelsDown)(B,!1)}}class ue extends O{static{this.ID_PREFIX="editor.foldLevel"}static{this.ID=X=>ue.ID_PREFIX+X}getFoldingLevel(){return parseInt(this.id.substr(ue.ID_PREFIX.length))}invoke(X,B,$){(0,i.setCollapseStateAtLevel)(B,this.getFoldingLevel(),!0,this.getSelectedLines($))}}class he extends O{constructor(){super({id:"editor.gotoParentFold",label:c.localize(904,"Go to Parent Fold"),alias:"Go to Parent Fold",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);if(Q.length>0){const Z=(0,i.getParentFoldLine)(Q[0],B);Z!==null&&$.setSelection({startLineNumber:Z,startColumn:1,endLineNumber:Z,endColumn:1})}}}class pe extends O{constructor(){super({id:"editor.gotoPreviousFold",label:c.localize(905,"Go to Previous Folding Range"),alias:"Go to Previous Folding Range",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);if(Q.length>0){const Z=(0,i.getPreviousFoldLine)(Q[0],B);Z!==null&&$.setSelection({startLineNumber:Z,startColumn:1,endLineNumber:Z,endColumn:1})}}}class ae extends O{constructor(){super({id:"editor.gotoNextFold",label:c.localize(906,"Go to Next Folding Range"),alias:"Go to Next Folding Range",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,weight:100}})}invoke(X,B,$){const Q=this.getSelectedLines($);if(Q.length>0){const Z=(0,i.getNextFoldLine)(Q[0],B);Z!==null&&$.setSelection({startLineNumber:Z,startColumn:1,endLineNumber:Z,endColumn:1})}}}class ee extends O{constructor(){super({id:"editor.createFoldingRangeFromSelection",label:c.localize(907,"Create Folding Range from Selection"),alias:"Create Folding Range from Selection",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2135),weight:100}})}invoke(X,B,$){const Q=[],Z=$.getSelections();if(Z){for(const te of Z){let re=te.endLineNumber;te.endColumn===1&&--re,re>te.startLineNumber&&(Q.push({startLineNumber:te.startLineNumber,endLineNumber:re,type:void 0,isCollapsed:!0,source:1}),$.setSelection({startLineNumber:te.startLineNumber,startColumn:1,endLineNumber:te.startLineNumber,endColumn:1}))}if(Q.length>0){Q.sort((re,le)=>re.startLineNumber-le.startLineNumber);const te=r.FoldingRegions.sanitizeAndMerge(B.regions,Q,$.getModel()?.getLineCount());B.updatePost(r.FoldingRegions.fromFoldRanges(te))}}}}class de extends O{constructor(){super({id:"editor.removeManualFoldingRanges",label:c.localize(908,"Remove Manual Folding Ranges"),alias:"Remove Manual Folding Ranges",precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2137),weight:100}})}invoke(X,B,$){const Q=$.getSelections();if(Q){const Z=[];for(const te of Q){const{startLineNumber:re,endLineNumber:le}=te;Z.push(le>=re?{startLineNumber:re,endLineNumber:le}:{endLineNumber:le,startLineNumber:re})}B.removeManualRanges(Z),X.triggerFoldingModelChanged()}}}(0,p.registerEditorContribution)(P.ID,P,0),(0,p.registerEditorAction)(W),(0,p.registerEditorAction)(V),(0,p.registerEditorAction)(q),(0,p.registerEditorAction)(z),(0,p.registerEditorAction)(U),(0,p.registerEditorAction)(J),(0,p.registerEditorAction)(ie),(0,p.registerEditorAction)(j),(0,p.registerEditorAction)(Y),(0,p.registerEditorAction)(G),(0,p.registerEditorAction)(K),(0,p.registerEditorAction)(R),(0,p.registerEditorAction)(H),(0,p.registerEditorAction)(he),(0,p.registerEditorAction)(pe),(0,p.registerEditorAction)(ae),(0,p.registerEditorAction)(ee),(0,p.registerEditorAction)(de);for(let ge=1;ge<=7;ge++)(0,p.registerInstantiatedEditorAction)(new ue({id:ue.ID(ge),label:c.localize(909,"Fold Level {0}",ge),alias:`Fold Level ${ge}`,precondition:A,kbOpts:{kbExpr:n.EditorContextKeys.editorTextFocus,primary:(0,E.KeyChord)(2089,2048|21+ge),weight:100}}));S.CommandsRegistry.registerCommand("_executeFoldingRangeProvider",async function(ge,...X){const[B]=X;if(!(B instanceof L.URI))throw(0,I.illegalArgument)();const $=ge.get(v.ILanguageFeaturesService),Q=ge.get(D.IModelService).getModel(B);if(!Q)throw(0,I.illegalArgument)();const Z=ge.get(T.IConfigurationService);if(!Z.getValue("editor.folding",{resource:B}))return[];const te=ge.get(t.ILanguageConfigurationService),re=Z.getValue("editor.foldingStrategy",{resource:B}),le={get limit(){return Z.getValue("editor.foldingMaximumRegions",{resource:B})},update:(Ee,Me)=>{}},me=new g.IndentRangeProvider(Q,te,le);let Ce=me;if(re!=="indentation"){const Ee=P.getFoldingRangeProviders($,Q);Ee.length&&(Ce=new u.SyntaxRangeProvider(Q,Ee,()=>{},le,me))}const ye=await Ce.compute(k.CancellationToken.None),Le=[];try{if(ye)for(let Ee=0;Eethis.editorWorkerService.navigateValueSet(h,C,a)),this.currentRequest.then(v=>{if(!v||!v.range||!v.value||!f.validate(this.editor))return;const w=y.Range.lift(v.range);let S=v.range;const L=v.value.length-(C.endColumn-C.startColumn);S={startLineNumber:S.startLineNumber,startColumn:S.startColumn,endLineNumber:S.endLineNumber,endColumn:S.startColumn+v.value.length},L>1&&(C=new m.Selection(C.startLineNumber,C.startColumn,C.endLineNumber,C.endColumn+L-1));const D=new o.InPlaceReplaceCommand(w,C,v.value);this.editor.pushUndoStop(),this.editor.executeCommand(l,D),this.editor.pushUndoStop(),this.decorations.set([{range:S,options:t.DECORATION}]),this.decorationRemover?.cancel(),this.decorationRemover=(0,d.timeout)(350),this.decorationRemover.then(()=>this.decorations.clear()).catch(k.onUnexpectedError)}).catch(k.onUnexpectedError)):Promise.resolve(void 0)}};i=t=ke([ce(1,p.IEditorWorkerService)],i);class s extends E.EditorAction{constructor(){super({id:"editor.action.inPlaceReplace.up",label:n.localize(1103,"Replace with Previous Value"),alias:"Replace with Previous Value",precondition:_.EditorContextKeys.writable,kbOpts:{kbExpr:_.EditorContextKeys.editorTextFocus,primary:3159,weight:100}})}run(l,a){const r=i.get(a);return r?r.run(this.id,!1):Promise.resolve(void 0)}}class g extends E.EditorAction{constructor(){super({id:"editor.action.inPlaceReplace.down",label:n.localize(1104,"Replace with Next Value"),alias:"Replace with Next Value",precondition:_.EditorContextKeys.writable,kbOpts:{kbExpr:_.EditorContextKeys.editorTextFocus,primary:3161,weight:100}})}run(l,a){const r=i.get(a);return r?r.run(this.id,!0):Promise.resolve(void 0)}}(0,E.registerEditorContribution)(i.ID,i,4),(0,E.registerEditorAction)(s),(0,E.registerEditorAction)(g)}),define(ne[828],se([1,0,2,21,9,4,43,40,150,205,139,518]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.GhostTextWidget=e.INLINE_EDIT_DESCRIPTION=void 0,e.INLINE_EDIT_DESCRIPTION="inline-edit";let n=class extends d.Disposable{constructor(t,i,s){super(),this.editor=t,this.model=i,this.languageService=s,this.isDisposed=(0,k.observableValue)(this,!1),this.currentTextModel=(0,k.observableFromEvent)(this,this.editor.onDidChangeModel,()=>this.editor.getModel()),this.uiState=(0,k.derived)(this,g=>{if(this.isDisposed.read(g))return;const c=this.currentTextModel.read(g);if(c!==this.model.targetTextModel.read(g))return;const l=this.model.ghostText.read(g);if(!l)return;let a=this.model.range?.read(g);a&&a.startLineNumber===a.endLineNumber&&a.startColumn===a.endColumn&&(a=void 0);const r=(a?a.startLineNumber===a.endLineNumber:!0)&&l.parts.length===1&&l.parts[0].lines.length===1,u=l.parts.length===1&&l.parts[0].lines.every(T=>T.length===0),C=[],f=[];function h(T,M){if(f.length>0){const A=f[f.length-1];M&&A.decorations.push(new _.LineDecoration(A.content.length+1,A.content.length+1+T[0].length,M,0)),A.content+=T[0],T=T.slice(1)}for(const A of T)f.push({content:A,decorations:M?[new _.LineDecoration(1,A.length+1,M,0)]:[]})}const v=c.getLineContent(l.lineNumber);let w,S=0;if(!u&&(r||!a)){for(const T of l.parts){let M=T.lines;a&&!r&&(h(M,e.INLINE_EDIT_DESCRIPTION),M=[]),w===void 0?(C.push({column:T.column,text:M[0],preview:T.preview}),M=M.slice(1)):h([v.substring(S,T.column-1)],void 0),M.length>0&&(h(M,e.INLINE_EDIT_DESCRIPTION),w===void 0&&T.column<=v.length&&(w=T.column)),S=T.column-1}w!==void 0&&h([v.substring(S)],void 0)}const L=w!==void 0?new b.ColumnRange(w,v.length+1):void 0,D=r||!a?l.lineNumber:a.endLineNumber-1;return{inlineTexts:C,additionalLines:f,hiddenRange:L,lineNumber:D,additionalReservedLineCount:this.model.minReservedLineCount.read(g),targetTextModel:c,range:a,isSingleLine:r,isPureRemove:u}}),this.decorations=(0,k.derived)(this,g=>{const c=this.uiState.read(g);if(!c)return[];const l=[];if(c.hiddenRange&&l.push({range:c.hiddenRange.toRange(c.lineNumber),options:{inlineClassName:"inline-edit-hidden",description:"inline-edit-hidden"}}),c.range){const a=[];if(c.isSingleLine)a.push(c.range);else if(!c.isPureRemove){const r=c.range.endLineNumber-c.range.startLineNumber;for(let u=0;u{this.isDisposed.set(!0,void 0)})),this._register((0,b.applyObservableDecorations)(this.editor,this.decorations))}};e.GhostTextWidget=n,e.GhostTextWidget=n=ke([ce(2,y.ILanguageService)],n)}),define(ne[829],se([1,0,5,18,2,21,65,22,112,125,215,139,9,4,70,35,51,7,520]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";var l,a;Object.defineProperty(e,"__esModule",{value:!0}),e.InlineEditSideBySideWidget=void 0;function*r(h,v,w=1){v===void 0&&([v,h]=[h,0]);for(let S=h;SS.replace(new RegExp("^"+v),"")),shift:w}}let C=class extends I.Disposable{static{l=this}static{this._modelId=0}static _createUniqueUri(){return m.URI.from({scheme:"inline-edit-widget",path:new Date().toString()+String(l._modelId++)})}constructor(v,w,S,L,D){super(),this._editor=v,this._model=w,this._instantiationService=S,this._diffProviderFactoryService=L,this._modelService=D,this._position=(0,E.derived)(this,T=>{const M=this._model.read(T);if(!M||M.text.length===0||M.range.startLineNumber===M.range.endLineNumber&&!(M.range.startColumn===M.range.endColumn&&M.range.startColumn===1))return null;const A=this._editor.getModel();if(!A)return null;const P=Array.from(r(M.range.startLineNumber,M.range.endLineNumber+1)),N=P.map(V=>A.getLineLastNonWhitespaceColumn(V)),O=Math.max(...N),F=P[N.indexOf(O)],x=new o.Position(F,O);return{top:M.range.startLineNumber,left:x}}),this._text=(0,E.derived)(this,T=>{const M=this._model.read(T);if(!M)return{text:"",shift:0};const A=u(M.text.split(` `));return{text:A.text.join(` `),shift:A.shift}}),this._originalModel=(0,y.derivedDisposable)(()=>this._modelService.createModel("",null,l._createUniqueUri())).keepObserved(this._store),this._modifiedModel=(0,y.derivedDisposable)(()=>this._modelService.createModel("",null,l._createUniqueUri())).keepObserved(this._store),this._diff=(0,E.derived)(this,T=>this._diffPromise.read(T)?.promiseResult.read(T)?.data),this._diffPromise=(0,E.derived)(this,T=>{const M=this._model.read(T);if(!M)return;const A=this._editor.getModel();if(!A)return;const P=u(A.getValueInRange(M.range).split(` `)).text.join(` `),N=u(M.text.split(` `)).text.join(` `);this._originalModel.get().setValue(P),this._modifiedModel.get().setValue(N);const O=this._diffProviderFactoryService.createDiffProvider({diffAlgorithm:"advanced"});return E.ObservablePromise.fromFn(async()=>{const F=await O.computeDiff(this._originalModel.get(),this._modifiedModel.get(),{computeMoves:!1,ignoreTrimWhitespace:!1,maxComputationTimeMs:1e3},k.CancellationToken.None);if(!F.identical)return F.changes})}),this._register((0,E.autorunWithStore)((T,M)=>{if(!this._model.read(T)||this._position.get()===null)return;const P=M.add(this._instantiationService.createInstance(f,this._editor,this._position,this._text.map(N=>N.text),this._text.map(N=>N.shift),this._diff));v.addOverlayWidget(P),M.add((0,I.toDisposable)(()=>v.removeOverlayWidget(P)))}))}};e.InlineEditSideBySideWidget=C,e.InlineEditSideBySideWidget=C=l=ke([ce(2,c.IInstantiationService),ce(3,p.IDiffProviderFactoryService),ce(4,g.IModelService)],C);let f=class extends I.Disposable{static{a=this}static{this.id=0}constructor(v,w,S,L,D,T){super(),this._editor=v,this._position=w,this._text=S,this._shift=L,this._diff=D,this._instantiationService=T,this.id=`InlineEditSideBySideContentWidget${a.id++}`,this.allowEditorOverflow=!1,this._nodes=(0,d.$)("div.inlineEditSideBySide",void 0),this._scrollChanged=(0,E.observableSignalFromEvent)("editor.onDidScrollChange",this._editor.onDidScrollChange),this._previewEditor=this._register(this._instantiationService.createInstance(b.EmbeddedCodeEditorWidget,this._nodes,{glyphMargin:!1,lineNumbers:"off",minimap:{enabled:!1},guides:{indentation:!1,bracketPairs:!1,bracketPairsHorizontal:!1,highlightActiveIndentation:!1},folding:!1,selectOnLineNumbers:!1,selectionHighlight:!1,columnSelection:!1,overviewRulerBorder:!1,overviewRulerLanes:0,lineDecorationsWidth:0,lineNumbersMinChars:0,scrollbar:{vertical:"hidden",horizontal:"hidden",alwaysConsumeMouseWheel:!1,handleMouseWheel:!1},readOnly:!0,wordWrap:"off",wordWrapOverride1:"off",wordWrapOverride2:"off",wrappingIndent:"none",wrappingStrategy:void 0},{contributions:[],isSimpleWidget:!0},this._editor)),this._previewEditorObs=(0,_.observableCodeEditor)(this._previewEditor),this._editorObs=(0,_.observableCodeEditor)(this._editor),this._previewTextModel=this._register(this._instantiationService.createInstance(s.TextModel,"",this._editor.getModel()?.getLanguageId()??i.PLAINTEXT_LANGUAGE_ID,s.TextModel.DEFAULT_CREATION_OPTIONS,null)),this._setText=(0,E.derived)(M=>{const A=this._text.read(M);A&&this._previewTextModel.setValue(A)}).recomputeInitiallyAndOnChange(this._store),this._decorations=(0,E.derived)(this,M=>{this._setText.read(M);const A=this._position.read(M);if(!A)return{org:[],mod:[]};const P=this._diff.read(M);if(!P)return{org:[],mod:[]};const N=[],O=[];if(P.length===1&&P[0].innerChanges[0].modifiedRange.equalsRange(this._previewTextModel.getFullModelRange()))return{org:[],mod:[]};const F=this._shift.get(),x=W=>new t.Range(W.startLineNumber+A.top-1,W.startColumn+F,W.endLineNumber+A.top-1,W.endColumn+F);for(const W of P)if(W.original.isEmpty||N.push({range:x(W.original.toInclusiveRange()),options:n.diffLineDeleteDecorationBackgroundWithIndicator}),W.modified.isEmpty||O.push({range:W.modified.toInclusiveRange(),options:n.diffLineAddDecorationBackgroundWithIndicator}),W.modified.isEmpty||W.original.isEmpty)W.original.isEmpty||N.push({range:x(W.original.toInclusiveRange()),options:n.diffWholeLineDeleteDecoration}),W.modified.isEmpty||O.push({range:W.modified.toInclusiveRange(),options:n.diffWholeLineAddDecoration});else for(const V of W.innerChanges||[])W.original.contains(V.originalRange.startLineNumber)&&N.push({range:x(V.originalRange),options:V.originalRange.isEmpty()?n.diffDeleteDecorationEmpty:n.diffDeleteDecoration}),W.modified.contains(V.modifiedRange.startLineNumber)&&O.push({range:V.modifiedRange,options:V.modifiedRange.isEmpty()?n.diffAddDecorationEmpty:n.diffAddDecoration});return{org:N,mod:O}}),this._originalDecorations=(0,E.derived)(this,M=>this._decorations.read(M).org),this._modifiedDecorations=(0,E.derived)(this,M=>this._decorations.read(M).mod),this._previewEditor.setModel(this._previewTextModel),this._register(this._editorObs.setDecorations(this._originalDecorations)),this._register(this._previewEditorObs.setDecorations(this._modifiedDecorations)),this._register((0,E.autorun)(M=>{const A=this._previewEditorObs.contentWidth.read(M),P=this._text.read(M).split(` `).length-1,N=this._editor.getOption(67)*P;A<=0||this._previewEditor.layout({height:N,width:A})})),this._register((0,E.autorun)(M=>{this._position.read(M),this._editor.layoutOverlayWidget(this)})),this._register((0,E.autorun)(M=>{this._scrollChanged.read(M),this._position.read(M)&&this._editor.layoutOverlayWidget(this)}))}getId(){return this.id}getDomNode(){return this._nodes}getPosition(){const v=this._position.get();if(!v)return null;const w=this._editor.getLayoutInfo(),S=this._editor.getScrolledVisiblePosition(new o.Position(v.top,1));if(!S)return null;const L=S.top-1,D=this._editor.getOffsetForColumn(v.left.lineNumber,v.left.column);return{preference:{left:w.contentLeft+D+10,top:L}}}};f=a=ke([ce(5,c.IInstantiationService)],f)}),define(ne[425],se([1,0,2,21,75,9,4,828,12,7,27,17,18,204,24,800,5,28,8,65,829,215,51]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C){"use strict";var f;Object.defineProperty(e,"__esModule",{value:!0}),e.InlineEditController=void 0;let h=class extends d.Disposable{static{f=this}static{this.ID="editor.contrib.inlineEditController"}static{this.inlineEditVisibleKey="inlineEditVisible"}static{this.inlineEditVisibleContext=new _.RawContextKey(this.inlineEditVisibleKey,!1)}static{this.cursorAtInlineEditKey="cursorAtInlineEdit"}static{this.cursorAtInlineEditContext=new _.RawContextKey(this.cursorAtInlineEditKey,!1)}static get(S){return S.getContribution(f.ID)}constructor(S,L,D,T,M,A,P,N){super(),this.editor=S,this.instantiationService=L,this.contextKeyService=D,this.languageFeaturesService=T,this._commandService=M,this._configurationService=A,this._diffProviderFactoryService=P,this._modelService=N,this._isVisibleContext=f.inlineEditVisibleContext.bindTo(this.contextKeyService),this._isCursorAtInlineEditContext=f.cursorAtInlineEditContext.bindTo(this.contextKeyService),this._currentEdit=(0,k.observableValue)(this,void 0),this._currentWidget=(0,a.derivedDisposable)(this._currentEdit,q=>{const H=this._currentEdit.read(q);if(!H)return;const z=H.range.endLineNumber,U=H.range.endColumn,j=H.text.endsWith(` `)&&!(H.range.startLineNumber===H.range.endLineNumber&&H.range.startColumn===H.range.endColumn)?H.text.slice(0,-1):H.text,Y=new t.GhostText(z,[new t.GhostTextPart(U,j,!1)]),G=H.range.startLineNumber===H.range.endLineNumber&&Y.parts.length===1&&Y.parts[0].lines.length===1,K=H.text==="";return!G&&!K?void 0:this.instantiationService.createInstance(m.GhostTextWidget,this.editor,{ghostText:(0,k.constObservable)(Y),minReservedLineCount:(0,k.constObservable)(0),targetTextModel:(0,k.constObservable)(this.editor.getModel()??void 0),range:(0,k.constObservable)(H.range)})}),this._isAccepting=(0,k.observableValue)(this,!1),this._enabled=(0,k.observableFromEvent)(this,this.editor.onDidChangeConfiguration,()=>this.editor.getOption(63).enabled),this._fontFamily=(0,k.observableFromEvent)(this,this.editor.onDidChangeConfiguration,()=>this.editor.getOption(63).fontFamily);const O=(0,k.observableSignalFromEvent)("InlineEditController.modelContentChangedSignal",S.onDidChangeModelContent);this._register((0,k.autorun)(q=>{this._enabled.read(q)&&(O.read(q),!this._isAccepting.read(q)&&this.getInlineEdit(S,!0))}));const F=(0,k.observableFromEvent)(this,S.onDidChangeCursorPosition,()=>S.getPosition());this._register((0,k.autorun)(q=>{if(!this._enabled.read(q))return;const H=F.read(q);H&&this.checkCursorPosition(H)})),this._register((0,k.autorun)(q=>{const H=this._currentEdit.read(q);if(this._isCursorAtInlineEditContext.set(!1),!H){this._isVisibleContext.set(!1);return}this._isVisibleContext.set(!0);const z=S.getPosition();z&&this.checkCursorPosition(z)}));const x=(0,k.observableSignalFromEvent)("InlineEditController.editorBlurSignal",S.onDidBlurEditorWidget);this._register((0,k.autorun)(async q=>{this._enabled.read(q)&&(x.read(q),!(this._configurationService.getValue("editor.experimentalInlineEdit.keepOnBlur")||S.getOption(63).keepOnBlur)&&(this._currentRequestCts?.dispose(!0),this._currentRequestCts=void 0,await this.clear(!1)))}));const W=(0,k.observableSignalFromEvent)("InlineEditController.editorFocusSignal",S.onDidFocusEditorText);this._register((0,k.autorun)(q=>{this._enabled.read(q)&&(W.read(q),this.getInlineEdit(S,!0))}));const V=this._register((0,g.createStyleSheet2)());this._register((0,k.autorun)(q=>{const H=this._fontFamily.read(q);V.setStyle(H===""||H==="default"?"":` .monaco-editor .inline-edit-decoration, .monaco-editor .inline-edit-decoration-preview, .monaco-editor .inline-edit { font-family: ${H}; }`)})),this._register(new s.InlineEditHintsWidget(this.editor,this._currentWidget,this.instantiationService)),this._register(new r.InlineEditSideBySideWidget(this.editor,this._currentEdit,this.instantiationService,this._diffProviderFactoryService,this._modelService))}checkCursorPosition(S){if(!this._currentEdit){this._isCursorAtInlineEditContext.set(!1);return}const L=this._currentEdit.get();if(!L){this._isCursorAtInlineEditContext.set(!1);return}this._isCursorAtInlineEditContext.set(y.Range.containsPosition(L.range,S))}validateInlineEdit(S,L){if(L.text.includes(` `)&&L.range.startLineNumber!==L.range.endLineNumber&&L.range.startColumn!==L.range.endColumn){if(L.range.startColumn!==1)return!1;const T=L.range.endLineNumber,M=L.range.endColumn,A=S.getModel()?.getLineLength(T)??0;if(M!==A+1)return!1}return!0}async fetchInlineEdit(S,L){this._currentRequestCts&&this._currentRequestCts.dispose(!0);const D=S.getModel();if(!D)return;const T=D.getVersionId(),M=this.languageFeaturesService.inlineEditProvider.all(D);if(M.length===0)return;const A=M[0];this._currentRequestCts=new o.CancellationTokenSource;const P=this._currentRequestCts.token,N=L?p.InlineEditTriggerKind.Automatic:p.InlineEditTriggerKind.Invoke;if(L&&await v(50,P),P.isCancellationRequested||D.isDisposed()||D.getVersionId()!==T)return;const F=await A.provideInlineEdit(D,{triggerKind:N},P);if(F&&!(P.isCancellationRequested||D.isDisposed()||D.getVersionId()!==T)&&this.validateInlineEdit(S,F))return F}async getInlineEdit(S,L){this._isCursorAtInlineEditContext.set(!1),await this.clear();const D=await this.fetchInlineEdit(S,L);D&&this._currentEdit.set(D,void 0)}async trigger(){await this.getInlineEdit(this.editor,!1)}async jumpBack(){this._jumpBackPosition&&(this.editor.setPosition(this._jumpBackPosition),this.editor.revealPositionInCenterIfOutsideViewport(this._jumpBackPosition))}async accept(){this._isAccepting.set(!0,void 0);const S=this._currentEdit.get();if(!S)return;let L=S.text;S.text.startsWith(` `)&&(L=S.text.substring(1)),this.editor.pushUndoStop(),this.editor.executeEdits("acceptCurrent",[I.EditOperation.replace(y.Range.lift(S.range),L)]),S.accepted&&await this._commandService.executeCommand(S.accepted.id,...S.accepted.arguments||[]).then(void 0,l.onUnexpectedExternalError),this.freeEdit(S),(0,k.transaction)(D=>{this._currentEdit.set(void 0,D),this._isAccepting.set(!1,D)})}jumpToCurrent(){this._jumpBackPosition=this.editor.getSelection()?.getStartPosition();const S=this._currentEdit.get();if(!S)return;const L=E.Position.lift({lineNumber:S.range.startLineNumber,column:S.range.startColumn});this.editor.setPosition(L),this.editor.revealPositionInCenterIfOutsideViewport(L)}async clear(S=!0){const L=this._currentEdit.get();L&&L?.rejected&&S&&await this._commandService.executeCommand(L.rejected.id,...L.rejected.arguments||[]).then(void 0,l.onUnexpectedExternalError),L&&this.freeEdit(L),this._currentEdit.set(void 0,void 0)}freeEdit(S){const L=this.editor.getModel();if(!L)return;const D=this.languageFeaturesService.inlineEditProvider.all(L);D.length!==0&&D[0].freeInlineEdit(S)}};e.InlineEditController=h,e.InlineEditController=h=f=ke([ce(1,b.IInstantiationService),ce(2,_.IContextKeyService),ce(3,n.ILanguageFeaturesService),ce(4,i.ICommandService),ce(5,c.IConfigurationService),ce(6,u.IDiffProviderFactoryService),ce(7,C.IModelService)],h);function v(w,S){return new Promise(L=>{let D;const T=setTimeout(()=>{D&&D.dispose(),L()},w);S&&(D=S.onCancellationRequested(()=>{clearTimeout(T),D&&D.dispose(),L()}))})}}),define(ne[830],se([1,0,15,20,618,425,29,12]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RejectInlineEdit=e.JumpBackInlineEdit=e.JumpToInlineEdit=e.TriggerInlineEdit=e.AcceptInlineEdit=void 0;class _ extends d.EditorAction{constructor(){super({id:I.inlineEditAcceptId,label:"Accept Inline Edit",alias:"Accept Inline Edit",precondition:m.ContextKeyExpr.and(k.EditorContextKeys.writable,E.InlineEditController.inlineEditVisibleContext),kbOpts:[{weight:101,primary:2,kbExpr:m.ContextKeyExpr.and(k.EditorContextKeys.writable,E.InlineEditController.inlineEditVisibleContext,E.InlineEditController.cursorAtInlineEditContext)}],menuOpts:[{menuId:y.MenuId.InlineEditToolbar,title:"Accept",group:"primary",order:1}]})}async run(i,s){await E.InlineEditController.get(s)?.accept()}}e.AcceptInlineEdit=_;class b extends d.EditorAction{constructor(){const i=m.ContextKeyExpr.and(k.EditorContextKeys.writable,m.ContextKeyExpr.not(E.InlineEditController.inlineEditVisibleKey));super({id:"editor.action.inlineEdit.trigger",label:"Trigger Inline Edit",alias:"Trigger Inline Edit",precondition:i,kbOpts:{weight:101,primary:2646,kbExpr:i}})}async run(i,s){E.InlineEditController.get(s)?.trigger()}}e.TriggerInlineEdit=b;class p extends d.EditorAction{constructor(){const i=m.ContextKeyExpr.and(k.EditorContextKeys.writable,E.InlineEditController.inlineEditVisibleContext,m.ContextKeyExpr.not(E.InlineEditController.cursorAtInlineEditKey));super({id:I.inlineEditJumpToId,label:"Jump to Inline Edit",alias:"Jump to Inline Edit",precondition:i,kbOpts:{weight:101,primary:2646,kbExpr:i},menuOpts:[{menuId:y.MenuId.InlineEditToolbar,title:"Jump To Edit",group:"primary",order:3,when:i}]})}async run(i,s){E.InlineEditController.get(s)?.jumpToCurrent()}}e.JumpToInlineEdit=p;class n extends d.EditorAction{constructor(){const i=m.ContextKeyExpr.and(k.EditorContextKeys.writable,E.InlineEditController.cursorAtInlineEditContext);super({id:I.inlineEditJumpBackId,label:"Jump Back from Inline Edit",alias:"Jump Back from Inline Edit",precondition:i,kbOpts:{weight:110,primary:2646,kbExpr:i},menuOpts:[{menuId:y.MenuId.InlineEditToolbar,title:"Jump Back",group:"primary",order:3,when:i}]})}async run(i,s){E.InlineEditController.get(s)?.jumpBack()}}e.JumpBackInlineEdit=n;class o extends d.EditorAction{constructor(){const i=m.ContextKeyExpr.and(k.EditorContextKeys.writable,E.InlineEditController.inlineEditVisibleContext);super({id:I.inlineEditRejectId,label:"Reject Inline Edit",alias:"Reject Inline Edit",precondition:i,kbOpts:{weight:100,primary:9,kbExpr:i},menuOpts:[{menuId:y.MenuId.InlineEditToolbar,title:"Reject",group:"secondary",order:2}]})}async run(i,s){await E.InlineEditController.get(s)?.clear()}}e.RejectInlineEdit=o}),define(ne[831],se([1,0,15,830,425]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorAction)(k.AcceptInlineEdit),(0,d.registerEditorAction)(k.RejectInlineEdit),(0,d.registerEditorAction)(k.JumpToInlineEdit),(0,d.registerEditorAction)(k.JumpBackInlineEdit),(0,d.registerEditorAction)(k.TriggerInlineEdit),(0,d.registerEditorContribution)(I.InlineEditController.ID,I.InlineEditController,3)}),define(ne[290],se([1,0,5,14,26,2,11,30,4,35,7,522]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlineProgressManager=void 0;const n=b.ModelDecorationOptions.register({description:"inline-progress-widget",stickiness:1,showIfCollapsed:!0,after:{content:y.noBreakWhitespace,inlineClassName:"inline-editor-progress-decoration",inlineClassNameAffectsLetterSpacing:!0}});class o extends E.Disposable{static{this.baseId="editor.widget.inlineProgressWidget"}constructor(s,g,c,l,a){super(),this.typeId=s,this.editor=g,this.range=c,this.delegate=a,this.allowEditorOverflow=!1,this.suppressMouseDown=!0,this.create(l),this.editor.addContentWidget(this),this.editor.layoutContentWidget(this)}create(s){this.domNode=d.$(".inline-progress-widget"),this.domNode.role="button",this.domNode.title=s;const g=d.$("span.icon");this.domNode.append(g),g.classList.add(...m.ThemeIcon.asClassNameArray(I.Codicon.loading),"codicon-modifier-spin");const c=()=>{const l=this.editor.getOption(67);this.domNode.style.height=`${l}px`,this.domNode.style.width=`${Math.ceil(.8*l)}px`};c(),this._register(this.editor.onDidChangeConfiguration(l=>{(l.hasChanged(52)||l.hasChanged(67))&&c()})),this._register(d.addDisposableListener(this.domNode,d.EventType.CLICK,l=>{this.delegate.cancel()}))}getId(){return o.baseId+"."+this.typeId}getDomNode(){return this.domNode}getPosition(){return{position:{lineNumber:this.range.startLineNumber,column:this.range.startColumn},preference:[0]}}dispose(){super.dispose(),this.editor.removeContentWidget(this)}}let t=class extends E.Disposable{constructor(s,g,c){super(),this.id=s,this._editor=g,this._instantiationService=c,this._showDelay=500,this._showPromise=this._register(new E.MutableDisposable),this._currentWidget=this._register(new E.MutableDisposable),this._operationIdPool=0,this._currentDecorations=g.createDecorationsCollection()}dispose(){super.dispose(),this._currentDecorations.clear()}async showWhile(s,g,c,l,a){const r=this._operationIdPool++;this._currentOperation=r,this.clear(),this._showPromise.value=(0,k.disposableTimeout)(()=>{const u=_.Range.fromPositions(s);this._currentDecorations.set([{range:u,options:n}]).length>0&&(this._currentWidget.value=this._instantiationService.createInstance(o,this.id,this._editor,u,g,l))},a??this._showDelay);try{return await c}finally{this._currentOperation===r&&(this.clear(),this._currentOperation=void 0)}}clear(){this._showPromise.clear(),this._currentDecorations.clear(),this._currentWidget.clear()}};e.InlineProgressManager=t,e.InlineProgressManager=t=ke([ce(2,p.IInstantiationService)],t)}),define(ne[832],se([1,0,13,14,194,91,2,400,4,17,327,678,122,290,3,28,12,399,7,268,396]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r){"use strict";var u;Object.defineProperty(e,"__esModule",{value:!0}),e.DropIntoEditorController=e.dropWidgetVisibleCtx=e.changeDropTypeCommandId=e.defaultProviderConfig=void 0,e.defaultProviderConfig="editor.experimental.dropIntoEditor.defaultProvider",e.changeDropTypeCommandId="editor.changeDropType",e.dropWidgetVisibleCtx=new g.RawContextKey("dropWidgetVisible",!1,(0,i.localize)(842,"Whether the drop widget is showing"));let C=class extends y.Disposable{static{u=this}static{this.ID="editor.contrib.dropIntoEditorController"}static get(h){return h.getContribution(u.ID)}constructor(h,v,w,S,L){super(),this._configService=w,this._languageFeaturesService=S,this._treeViewsDragAndDropService=L,this.treeItemsTransfer=c.LocalSelectionTransfer.getInstance(),this._dropProgressManager=this._register(v.createInstance(t.InlineProgressManager,"dropIntoEditor",h)),this._postDropWidgetManager=this._register(v.createInstance(r.PostEditWidgetManager,"dropIntoEditor",h,e.dropWidgetVisibleCtx,{id:e.changeDropTypeCommandId,label:(0,i.localize)(843,"Show drop options...")})),this._register(h.onDropIntoEditor(D=>this.onDropIntoEditor(h,D.position,D.event)))}clearWidgets(){this._postDropWidgetManager.clear()}changeDropType(){this._postDropWidgetManager.tryShowSelector()}async onDropIntoEditor(h,v,w){if(!w.dataTransfer||!h.hasModel())return;this._currentOperation?.cancel(),h.focus(),h.setPosition(v);const S=(0,k.createCancelablePromise)(async L=>{const D=new y.DisposableStore,T=D.add(new o.EditorStateCancellationTokenSource(h,1,void 0,L));try{const M=await this.extractDataTransferData(w);if(M.size===0||T.token.isCancellationRequested)return;const A=h.getModel();if(!A)return;const P=this._languageFeaturesService.documentDropEditProvider.ordered(A).filter(O=>O.dropMimeTypes?O.dropMimeTypes.some(F=>M.matches(F)):!0),N=D.add(await this.getDropEdits(P,A,v,M,T));if(T.token.isCancellationRequested)return;if(N.edits.length){const O=this.getInitialActiveEditIndex(A,N.edits),F=h.getOption(36).showDropSelector==="afterDrop";await this._postDropWidgetManager.applyEditAndShowIfNeeded([_.Range.fromPositions(v)],{activeEditIndex:O,allEdits:N.edits},F,async x=>x,L)}}finally{D.dispose(),this._currentOperation===S&&(this._currentOperation=void 0)}});this._dropProgressManager.showWhile(v,(0,i.localize)(844,"Running drop handlers. Click to cancel"),S,{cancel:()=>S.cancel()}),this._currentOperation=S}async getDropEdits(h,v,w,S,L){const D=new y.DisposableStore,T=await(0,k.raceCancellation)(Promise.all(h.map(async A=>{try{const P=await A.provideDocumentDropEdits(v,w,S,L.token);return P&&D.add(P),P?.edits.map(N=>({...N,providerId:A.id}))}catch(P){console.error(P)}})),L.token),M=(0,d.coalesce)(T??[]).flat();return{edits:(0,a.sortEditsByYieldTo)(M),dispose:()=>D.dispose()}}getInitialActiveEditIndex(h,v){const w=this._configService.getValue(e.defaultProviderConfig,{resource:h.uri});for(const[S,L]of Object.entries(w)){const D=new E.HierarchicalKind(L),T=v.findIndex(M=>D.value===M.providerId&&M.handledMimeType&&(0,I.matchesMimeType)(S,[M.handledMimeType]));if(T>=0)return T}return 0}async extractDataTransferData(h){if(!h.dataTransfer)return new I.VSDataTransfer;const v=(0,m.toExternalVSDataTransfer)(h.dataTransfer);if(this.treeItemsTransfer.hasData(p.DraggedTreeItemsIdentifier.prototype)){const w=this.treeItemsTransfer.getData(p.DraggedTreeItemsIdentifier.prototype);if(Array.isArray(w))for(const S of w){const L=await this._treeViewsDragAndDropService.removeDragOperationTransfer(S.identifier);if(L)for(const[D,T]of L)v.replace(D,T)}}return v}};e.DropIntoEditorController=C,e.DropIntoEditorController=C=u=ke([ce(1,l.IInstantiationService),ce(2,s.IConfigurationService),ce(3,b.ILanguageFeaturesService),ce(4,n.ITreeViewsDnDService)],C)}),define(ne[833],se([1,0,13,14,18,33,8,6,2,11,22,15,34,9,4,20,35,36,3,12,17,32,79,54,523]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f){"use strict";var h;Object.defineProperty(e,"__esModule",{value:!0}),e.editorLinkedEditingBackground=e.LinkedEditingAction=e.LinkedEditingContribution=e.CONTEXT_ONTYPE_RENAME_INPUT_VISIBLE=void 0,e.CONTEXT_ONTYPE_RENAME_INPUT_VISIBLE=new a.RawContextKey("LinkedEditingInputVisible",!1);const v="linked-editing-decoration";let w=class extends _.Disposable{static{h=this}static{this.ID="editor.contrib.linkedEditing"}static{this.DECORATION=g.ModelDecorationOptions.register({description:"linked-editing",stickiness:0,className:v})}static get(M){return M.getContribution(h.ID)}constructor(M,A,P,N,O){super(),this.languageConfigurationService=N,this._syncRangesToken=0,this._localToDispose=this._register(new _.DisposableStore),this._editor=M,this._providers=P.linkedEditingRangeProvider,this._enabled=!1,this._visibleContextKey=e.CONTEXT_ONTYPE_RENAME_INPUT_VISIBLE.bindTo(A),this._debounceInformation=O.for(this._providers,"Linked Editing",{max:200}),this._currentDecorations=this._editor.createDecorationsCollection(),this._languageWordPattern=null,this._currentWordPattern=null,this._ignoreChangeEvent=!1,this._localToDispose=this._register(new _.DisposableStore),this._rangeUpdateTriggerPromise=null,this._rangeSyncTriggerPromise=null,this._currentRequestCts=null,this._currentRequestPosition=null,this._currentRequestModelVersion=null,this._register(this._editor.onDidChangeModel(()=>this.reinitialize(!0))),this._register(this._editor.onDidChangeConfiguration(F=>{(F.hasChanged(70)||F.hasChanged(94))&&this.reinitialize(!1)})),this._register(this._providers.onDidChange(()=>this.reinitialize(!1))),this._register(this._editor.onDidChangeModelLanguage(()=>this.reinitialize(!0))),this.reinitialize(!0)}reinitialize(M){const A=this._editor.getModel(),P=A!==null&&(this._editor.getOption(70)||this._editor.getOption(94))&&this._providers.has(A);if(P===this._enabled&&!M||(this._enabled=P,this.clearRanges(),this._localToDispose.clear(),!P||A===null))return;this._localToDispose.add(m.Event.runAndSubscribe(A.onDidChangeLanguageConfiguration,()=>{this._languageWordPattern=this.languageConfigurationService.getLanguageConfiguration(A.getLanguageId()).getWordDefinition()}));const N=new k.Delayer(this._debounceInformation.get(A)),O=()=>{this._rangeUpdateTriggerPromise=N.trigger(()=>this.updateRanges(),this._debounceDuration??this._debounceInformation.get(A))},F=new k.Delayer(0),x=W=>{this._rangeSyncTriggerPromise=F.trigger(()=>this._syncRanges(W))};this._localToDispose.add(this._editor.onDidChangeCursorPosition(()=>{O()})),this._localToDispose.add(this._editor.onDidChangeModelContent(W=>{if(!this._ignoreChangeEvent&&this._currentDecorations.length>0){const V=this._currentDecorations.getRange(0);if(V&&W.changes.every(q=>V.intersectRanges(q.range))){x(this._syncRangesToken);return}}O()})),this._localToDispose.add({dispose:()=>{N.dispose(),F.dispose()}}),this.updateRanges()}_syncRanges(M){if(!this._editor.hasModel()||M!==this._syncRangesToken||this._currentDecorations.length===0)return;const A=this._editor.getModel(),P=this._currentDecorations.getRange(0);if(!P||P.startLineNumber!==P.endLineNumber)return this.clearRanges();const N=A.getValueInRange(P);if(this._currentWordPattern){const F=N.match(this._currentWordPattern);if((F?F[0].length:0)!==N.length)return this.clearRanges()}const O=[];for(let F=1,x=this._currentDecorations.length;F1){this.clearRanges();return}const P=this._editor.getModel(),N=P.getVersionId();if(this._currentRequestPosition&&this._currentRequestModelVersion===N){if(A.equals(this._currentRequestPosition))return;if(this._currentDecorations.length>0){const F=this._currentDecorations.getRange(0);if(F&&F.containsPosition(A))return}}this.clearRanges(),this._currentRequestPosition=A,this._currentRequestModelVersion=N;const O=this._currentRequestCts=new I.CancellationTokenSource;try{const F=new f.StopWatch(!1),x=await D(this._providers,P,A,O.token);if(this._debounceInformation.update(P,F.elapsed()),O!==this._currentRequestCts||(this._currentRequestCts=null,N!==P.getVersionId()))return;let W=[];x?.ranges&&(W=x.ranges),this._currentWordPattern=x?.wordPattern||this._languageWordPattern;let V=!1;for(let H=0,z=W.length;H({range:H,options:h.DECORATION}));this._visibleContextKey.set(!0),this._currentDecorations.set(q),this._syncRangesToken++}catch(F){(0,y.isCancellationError)(F)||(0,y.onUnexpectedError)(F),(this._currentRequestCts===O||!this._currentRequestCts)&&this.clearRanges()}}};e.LinkedEditingContribution=w,e.LinkedEditingContribution=w=h=ke([ce(1,a.IContextKeyService),ce(2,r.ILanguageFeaturesService),ce(3,c.ILanguageConfigurationService),ce(4,C.ILanguageFeatureDebounceService)],w);class S extends n.EditorAction{constructor(){super({id:"editor.action.linkedEditing",label:l.localize(1136,"Start Linked Editing"),alias:"Start Linked Editing",precondition:a.ContextKeyExpr.and(s.EditorContextKeys.writable,s.EditorContextKeys.hasRenameProvider),kbOpts:{kbExpr:s.EditorContextKeys.editorTextFocus,primary:3132,weight:100}})}runCommand(M,A){const P=M.get(o.ICodeEditorService),[N,O]=Array.isArray(A)&&A||[void 0,void 0];return p.URI.isUri(N)&&t.Position.isIPosition(O)?P.openCodeEditor({resource:N},P.getActiveCodeEditor()).then(F=>{F&&(F.setPosition(O),F.invokeWithinContext(x=>(this.reportTelemetry(x,F),this.run(x,F))))},y.onUnexpectedError):super.runCommand(M,A)}run(M,A){const P=w.get(A);return P?Promise.resolve(P.updateRanges(!0)):Promise.resolve()}}e.LinkedEditingAction=S;const L=n.EditorCommand.bindToContribution(w.get);(0,n.registerEditorCommand)(new L({id:"cancelLinkedEditingInput",precondition:e.CONTEXT_ONTYPE_RENAME_INPUT_VISIBLE,handler:T=>T.clearRanges(),kbOpts:{kbExpr:s.EditorContextKeys.editorTextFocus,weight:199,primary:9,secondary:[1033]}}));function D(T,M,A,P){const N=T.ordered(M);return(0,k.first)(N.map(O=>async()=>{try{return await O.provideLinkedEditingRanges(M,A,P)}catch(F){(0,y.onUnexpectedExternalError)(F);return}}),O=>!!O&&d.isNonEmptyArray(O?.ranges))}e.editorLinkedEditingBackground=(0,u.registerColor)("editor.linkedEditingBackground",{dark:E.Color.fromHex("#f00").transparent(.3),light:E.Color.fromHex("#f00").transparent(.3),hcDark:E.Color.fromHex("#f00").transparent(.3),hcLight:E.Color.white},l.localize(1137,"Background color when the editor auto renames on type.")),(0,n.registerModelAndPositionCommand)("_executeLinkedEditingProvider",(T,M,A)=>{const{linkedEditingRangeProvider:P}=T.get(r.ILanguageFeaturesService);return D(P,M,A,I.CancellationToken.None)}),(0,n.registerEditorContribution)(w.ID,w,1),(0,n.registerEditorAction)(S)}),define(ne[834],se([1,0,14,18,8,57,2,42,16,48,54,22,15,35,79,17,209,681,3,50,59,524]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r){"use strict";var u;Object.defineProperty(e,"__esModule",{value:!0}),e.LinkDetector=void 0;let C=class extends y.Disposable{static{u=this}static{this.ID="editor.linkDetector"}static get(L){return L.getContribution(u.ID)}constructor(L,D,T,M,A){super(),this.editor=L,this.openerService=D,this.notificationService=T,this.languageFeaturesService=M,this.providers=this.languageFeaturesService.linkProvider,this.debounceInformation=A.for(this.providers,"Links",{min:1e3,max:4e3}),this.computeLinks=this._register(new d.RunOnceScheduler(()=>this.computeLinksNow(),1e3)),this.computePromise=null,this.activeLinksList=null,this.currentOccurrences={},this.activeLinkDecorationId=null;const P=this._register(new g.ClickLinkGesture(L));this._register(P.onMouseMoveOrRelevantKeyDown(([N,O])=>{this._onEditorMouseMove(N,O)})),this._register(P.onExecute(N=>{this.onEditorMouseUp(N)})),this._register(P.onCancel(N=>{this.cleanUpActiveLinkDecoration()})),this._register(L.onDidChangeConfiguration(N=>{N.hasChanged(71)&&(this.updateDecorations([]),this.stop(),this.computeLinks.schedule(0))})),this._register(L.onDidChangeModelContent(N=>{this.editor.hasModel()&&this.computeLinks.schedule(this.debounceInformation.get(this.editor.getModel()))})),this._register(L.onDidChangeModel(N=>{this.currentOccurrences={},this.activeLinkDecorationId=null,this.stop(),this.computeLinks.schedule(0)})),this._register(L.onDidChangeModelLanguage(N=>{this.stop(),this.computeLinks.schedule(0)})),this._register(this.providers.onDidChange(N=>{this.stop(),this.computeLinks.schedule(0)})),this.computeLinks.schedule(0)}async computeLinksNow(){if(!this.editor.hasModel()||!this.editor.getOption(71))return;const L=this.editor.getModel();if(!L.isTooLargeForSyncing()&&this.providers.has(L)){this.activeLinksList&&(this.activeLinksList.dispose(),this.activeLinksList=null),this.computePromise=(0,d.createCancelablePromise)(D=>(0,c.getLinks)(this.providers,L,D));try{const D=new p.StopWatch(!1);if(this.activeLinksList=await this.computePromise,this.debounceInformation.update(L,D.elapsed()),L.isDisposed())return;this.updateDecorations(this.activeLinksList.links)}catch(D){(0,I.onUnexpectedError)(D)}finally{this.computePromise=null}}}updateDecorations(L){const D=this.editor.getOption(78)==="altKey",T=[],M=Object.keys(this.currentOccurrences);for(const P of M){const N=this.currentOccurrences[P];T.push(N.decorationId)}const A=[];if(L)for(const P of L)A.push(h.decoration(P,D));this.editor.changeDecorations(P=>{const N=P.deltaDecorations(T,A);this.currentOccurrences={},this.activeLinkDecorationId=null;for(let O=0,F=N.length;O{M.activate(A,T),this.activeLinkDecorationId=M.decorationId})}else this.cleanUpActiveLinkDecoration()}cleanUpActiveLinkDecoration(){const L=this.editor.getOption(78)==="altKey";if(this.activeLinkDecorationId){const D=this.currentOccurrences[this.activeLinkDecorationId];D&&this.editor.changeDecorations(T=>{D.deactivate(T,L)}),this.activeLinkDecorationId=null}}onEditorMouseUp(L){if(!this.isEnabled(L))return;const D=this.getLinkOccurrence(L.target.position);D&&this.openLinkOccurrence(D,L.hasSideBySideModifier,!0)}openLinkOccurrence(L,D,T=!1){if(!this.openerService)return;const{link:M}=L;M.resolve(k.CancellationToken.None).then(A=>{if(typeof A=="string"&&this.editor.hasModel()){const P=this.editor.getModel().uri;if(P.scheme===m.Schemas.file&&A.startsWith(`${m.Schemas.file}:`)){const N=n.URI.parse(A);if(N.scheme===m.Schemas.file){const O=b.originalFSPath(N);let F=null;O.startsWith("/./")||O.startsWith("\\.\\")?F=`.${O.substr(1)}`:(O.startsWith("//./")||O.startsWith("\\\\.\\"))&&(F=`.${O.substr(2)}`),F&&(A=b.joinPath(P,F))}}}return this.openerService.open(A,{openToSide:D,fromUserGesture:T,allowContributedOpeners:!0,allowCommands:!0,fromWorkspace:!0})},A=>{const P=A instanceof Error?A.message:A;P==="invalid"?this.notificationService.warn(l.localize(1138,"Failed to open this link because it is not well-formed: {0}",M.url.toString())):P==="missing"?this.notificationService.warn(l.localize(1139,"Failed to open this link because its target is missing.")):(0,I.onUnexpectedError)(A)})}getLinkOccurrence(L){if(!this.editor.hasModel()||!L)return null;const D=this.editor.getModel().getDecorationsInRange({startLineNumber:L.lineNumber,startColumn:L.column,endLineNumber:L.lineNumber,endColumn:L.column},0,!0);for(const T of D){const M=this.currentOccurrences[T.id];if(M)return M}return null}isEnabled(L,D){return!!(L.target.type===6&&(L.hasTriggerModifier||D&&D.keyCodeIsTriggerKey))}stop(){this.computeLinks.cancel(),this.activeLinksList&&(this.activeLinksList?.dispose(),this.activeLinksList=null),this.computePromise&&(this.computePromise.cancel(),this.computePromise=null)}dispose(){super.dispose(),this.stop()}};e.LinkDetector=C,e.LinkDetector=C=u=ke([ce(1,r.IOpenerService),ce(2,a.INotificationService),ce(3,s.ILanguageFeaturesService),ce(4,i.ILanguageFeatureDebounceService)],C);const f={general:t.ModelDecorationOptions.register({description:"detected-link",stickiness:1,collapseOnReplaceEdit:!0,inlineClassName:"detected-link"}),active:t.ModelDecorationOptions.register({description:"detected-link-active",stickiness:1,collapseOnReplaceEdit:!0,inlineClassName:"detected-link-active"})};class h{static decoration(L,D){return{range:L.range,options:h._getOptions(L,D,!1)}}static _getOptions(L,D,T){const M={...T?f.active:f.general};return M.hoverMessage=v(L,D),M}constructor(L,D){this.link=L,this.decorationId=D}activate(L,D){L.changeDecorationOptions(this.decorationId,h._getOptions(this.link,D,!0))}deactivate(L,D){L.changeDecorationOptions(this.decorationId,h._getOptions(this.link,D,!1))}}function v(S,L){const D=S.url&&/^command:/i.test(S.url.toString()),T=S.tooltip?S.tooltip:D?l.localize(1140,"Execute command"):l.localize(1141,"Follow link"),M=L?_.isMacintosh?l.localize(1142,"cmd + click"):l.localize(1143,"ctrl + click"):_.isMacintosh?l.localize(1144,"option + click"):l.localize(1145,"alt + click");if(S.url){let A="";if(/^command:/i.test(S.url.toString())){const N=S.url.toString().match(/^command:([^?#]+)/);if(N){const O=N[1];A=l.localize(1146,"Execute command {0}",O)}}return new E.MarkdownString("",!0).appendLink(S.url.toString(!0).replace(/ /g,"%20"),T,A).appendMarkdown(` (${M})`)}else return new E.MarkdownString().appendText(`${T} (${M})`)}class w extends o.EditorAction{constructor(){super({id:"editor.action.openLink",label:l.localize(1147,"Open Link"),alias:"Open Link",precondition:void 0})}run(L,D){const T=C.get(D);if(!T||!D.hasModel())return;const M=D.getSelections();for(const A of M){const P=T.getLinkOccurrence(A.getEndPosition());P&&T.openLinkOccurrence(P,!1)}}}(0,o.registerEditorContribution)(C.ID,C,1),(0,o.registerEditorAction)(w)}),define(ne[835],se([1,0,14,2,15,36,35,100]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SectionHeaderDetector=void 0;let _=class extends k.Disposable{static{this.ID="editor.sectionHeaderDetector"}constructor(n,o,t){super(),this.editor=n,this.languageConfigurationService=o,this.editorWorkerService=t,this.decorations=this.editor.createDecorationsCollection(),this.options=this.createOptions(n.getOption(73)),this.computePromise=null,this.currentOccurrences={},this._register(n.onDidChangeModel(i=>{this.currentOccurrences={},this.options=this.createOptions(n.getOption(73)),this.stop(),this.computeSectionHeaders.schedule(0)})),this._register(n.onDidChangeModelLanguage(i=>{this.currentOccurrences={},this.options=this.createOptions(n.getOption(73)),this.stop(),this.computeSectionHeaders.schedule(0)})),this._register(o.onDidChange(i=>{const s=this.editor.getModel()?.getLanguageId();s&&i.affects(s)&&(this.currentOccurrences={},this.options=this.createOptions(n.getOption(73)),this.stop(),this.computeSectionHeaders.schedule(0))})),this._register(n.onDidChangeConfiguration(i=>{this.options&&!i.hasChanged(73)||(this.options=this.createOptions(n.getOption(73)),this.updateDecorations([]),this.stop(),this.computeSectionHeaders.schedule(0))})),this._register(this.editor.onDidChangeModelContent(i=>{this.computeSectionHeaders.schedule()})),this._register(n.onDidChangeModelTokens(i=>{this.computeSectionHeaders.isScheduled()||this.computeSectionHeaders.schedule(1e3)})),this.computeSectionHeaders=this._register(new d.RunOnceScheduler(()=>{this.findSectionHeaders()},250)),this.computeSectionHeaders.schedule(0)}createOptions(n){if(!n||!this.editor.hasModel())return;const o=this.editor.getModel().getLanguageId();if(!o)return;const t=this.languageConfigurationService.getLanguageConfiguration(o).comments,i=this.languageConfigurationService.getLanguageConfiguration(o).foldingRules;if(!(!t&&!i?.markers))return{foldingRules:i,findMarkSectionHeaders:n.showMarkSectionHeaders,findRegionSectionHeaders:n.showRegionSectionHeaders}}findSectionHeaders(){if(!this.editor.hasModel()||!this.options?.findMarkSectionHeaders&&!this.options?.findRegionSectionHeaders)return;const n=this.editor.getModel();if(n.isDisposed()||n.isTooLargeForSyncing())return;const o=n.getVersionId();this.editorWorkerService.findSectionHeaders(n.uri,this.options).then(t=>{n.isDisposed()||n.getVersionId()!==o||this.updateDecorations(t)})}updateDecorations(n){const o=this.editor.getModel();o&&(n=n.filter(s=>{if(!s.shouldBeInComments)return!0;const g=o.validateRange(s.range),c=o.tokenization.getLineTokens(g.startLineNumber),l=c.findTokenIndexAtOffset(g.startColumn-1),a=c.getStandardTokenType(l);return c.getLanguageId(l)===o.getLanguageId()&&a===1}));const t=Object.values(this.currentOccurrences).map(s=>s.decorationId),i=n.map(s=>b(s));this.editor.changeDecorations(s=>{const g=s.deltaDecorations(t,i);this.currentOccurrences={};for(let c=0,l=g.length;cf.dispose()),this._updateOperation.clear(),this._cancelModelPromise(),super.dispose()}_cancelModelPromise(){this._modelPromise&&(this._modelPromise.cancel(),this._modelPromise=null)}async update(f){return this._updateOperation.clear(),this._updateOperation.add({dispose:()=>{this._cancelModelPromise(),this._updateScheduler.cancel()}}),this._cancelModelPromise(),await this._updateScheduler.trigger(async()=>{for(const h of this._modelProviders){const{statusPromise:v,modelPromise:w}=h.computeStickyModel(f);this._modelPromise=w;const S=await v;if(this._modelPromise!==w)return null;switch(S){case s.CANCELED:return this._updateOperation.clear(),null;case s.VALID:return h.stickyModel}}return null}).catch(h=>((0,p.onUnexpectedError)(h),null))}};e.StickyModelProvider=g,e.StickyModelProvider=g=ke([ce(2,t.IInstantiationService),ce(3,k.ILanguageFeaturesService)],g);class c extends d.Disposable{constructor(f){super(),this._editor=f,this._stickyModel=null}get stickyModel(){return this._stickyModel}_invalid(){return this._stickyModel=null,s.INVALID}computeStickyModel(f){if(f.isCancellationRequested||!this.isProviderValid())return{statusPromise:this._invalid(),modelPromise:null};const h=(0,E.createCancelablePromise)(v=>this.createModelFromProvider(v));return{statusPromise:h.then(v=>this.isModelValid(v)?f.isCancellationRequested?s.CANCELED:(this._stickyModel=this.createStickyModel(f,v),s.VALID):this._invalid()).then(void 0,v=>((0,p.onUnexpectedError)(v),s.CANCELED)),modelPromise:h}}isModelValid(f){return!0}isProviderValid(){return!0}}let l=class extends c{constructor(f,h){super(f),this._languageFeaturesService=h}createModelFromProvider(f){return I.OutlineModel.create(this._languageFeaturesService.documentSymbolProvider,this._editor.getModel(),f)}createStickyModel(f,h){const{stickyOutlineElement:v,providerID:w}=this._stickyModelFromOutlineModel(h,this._stickyModel?.outlineProviderId),S=this._editor.getModel();return new n.StickyModel(S.uri,S.getVersionId(),v,w)}isModelValid(f){return f&&f.children.size>0}_stickyModelFromOutlineModel(f,h){let v;if(o.Iterable.first(f.children.values())instanceof I.OutlineGroup){const D=o.Iterable.find(f.children.values(),T=>T.id===h);if(D)v=D.children;else{let T="",M=-1,A;for(const[P,N]of f.children.entries()){const O=this._findSumOfRangesOfGroup(N);O>M&&(A=N,M=O,T=N.id)}h=T,v=A.children}}else v=f.children;const w=[],S=Array.from(v.values()).sort((D,T)=>{const M=new n.StickyRange(D.symbol.range.startLineNumber,D.symbol.range.endLineNumber),A=new n.StickyRange(T.symbol.range.startLineNumber,T.symbol.range.endLineNumber);return this._comparator(M,A)});for(const D of S)w.push(this._stickyModelFromOutlineElement(D,D.symbol.selectionRange.startLineNumber));return{stickyOutlineElement:new n.StickyElement(void 0,w,void 0),providerID:h}}_stickyModelFromOutlineElement(f,h){const v=[];for(const S of f.children.values())if(S.symbol.selectionRange.startLineNumber!==S.symbol.range.endLineNumber)if(S.symbol.selectionRange.startLineNumber!==h)v.push(this._stickyModelFromOutlineElement(S,S.symbol.selectionRange.startLineNumber));else for(const L of S.children.values())v.push(this._stickyModelFromOutlineElement(L,S.symbol.selectionRange.startLineNumber));v.sort((S,L)=>this._comparator(S.range,L.range));const w=new n.StickyRange(f.symbol.selectionRange.startLineNumber,f.symbol.range.endLineNumber);return new n.StickyElement(w,v,void 0)}_comparator(f,h){return f.startLineNumber!==h.startLineNumber?f.startLineNumber-h.startLineNumber:h.endLineNumber-f.endLineNumber}_findSumOfRangesOfGroup(f){let h=0;for(const v of f.children.values())h+=this._findSumOfRangesOfGroup(v);return f instanceof I.OutlineElement?h+f.symbol.range.endLineNumber-f.symbol.selectionRange.startLineNumber:h}};l=ke([ce(1,k.ILanguageFeaturesService)],l);class a extends c{constructor(f){super(f),this._foldingLimitReporter=new y.RangesLimitReporter(f)}createStickyModel(f,h){const v=this._fromFoldingRegions(h),w=this._editor.getModel();return new n.StickyModel(w.uri,w.getVersionId(),v,void 0)}isModelValid(f){return f!==null}_fromFoldingRegions(f){const h=f.length,v=[],w=new n.StickyElement(void 0,[],void 0);for(let S=0;S0&&(this.provider=this._register(new m.SyntaxRangeProvider(f.getModel(),w,h,this._foldingLimitReporter,void 0)))}isProviderValid(){return this.provider!==void 0}async createModelFromProvider(f){return this.provider?.compute(f)??null}};u=ke([ce(2,k.ILanguageFeaturesService)],u)}),define(ne[837],se([1,0,2,17,18,14,13,6,36,836]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StickyLineCandidateProvider=e.StickyLineCandidate=void 0;class p{constructor(t,i,s){this.startLineNumber=t,this.endLineNumber=i,this.nestingDepth=s}}e.StickyLineCandidate=p;let n=class extends d.Disposable{constructor(t,i,s){super(),this._languageFeaturesService=i,this._languageConfigurationService=s,this._onDidChangeStickyScroll=this._register(new m.Emitter),this.onDidChangeStickyScroll=this._onDidChangeStickyScroll.event,this._model=null,this._cts=null,this._stickyModelProvider=null,this._editor=t,this._sessionStore=this._register(new d.DisposableStore),this._updateSoon=this._register(new E.RunOnceScheduler(()=>this.update(),50)),this._register(this._editor.onDidChangeConfiguration(g=>{g.hasChanged(116)&&this.readConfiguration()})),this.readConfiguration()}readConfiguration(){this._sessionStore.clear(),this._editor.getOption(116).enabled&&(this._sessionStore.add(this._editor.onDidChangeModel(()=>{this._model=null,this.updateStickyModelProvider(),this._onDidChangeStickyScroll.fire(),this.update()})),this._sessionStore.add(this._editor.onDidChangeHiddenAreas(()=>this.update())),this._sessionStore.add(this._editor.onDidChangeModelContent(()=>this._updateSoon.schedule())),this._sessionStore.add(this._languageFeaturesService.documentSymbolProvider.onDidChange(()=>this.update())),this._sessionStore.add((0,d.toDisposable)(()=>{this._stickyModelProvider?.dispose(),this._stickyModelProvider=null})),this.updateStickyModelProvider(),this.update())}getVersionId(){return this._model?.version}updateStickyModelProvider(){this._stickyModelProvider?.dispose(),this._stickyModelProvider=null;const t=this._editor;t.hasModel()&&(this._stickyModelProvider=new b.StickyModelProvider(t,()=>this._updateSoon.schedule(),this._languageConfigurationService,this._languageFeaturesService))}async update(){this._cts?.dispose(!0),this._cts=new I.CancellationTokenSource,await this.updateStickyModel(this._cts.token),this._onDidChangeStickyScroll.fire()}async updateStickyModel(t){if(!this._editor.hasModel()||!this._stickyModelProvider||this._editor.getModel().isTooLargeForTokenization()){this._model=null;return}const i=await this._stickyModelProvider.update(t);t.isCancellationRequested||(this._model=i)}updateIndex(t){return t===-1?t=0:t<0&&(t=-t-2),t}getCandidateStickyLinesIntersectingFromStickyModel(t,i,s,g,c){if(i.children.length===0)return;let l=c;const a=[];for(let C=0;CC-f)),u=this.updateIndex((0,y.binarySearch)(a,t.startLineNumber+g,(C,f)=>C-f));for(let C=r;C<=u;C++){const f=i.children[C];if(!f)return;if(f.range){const h=f.range.startLineNumber,v=f.range.endLineNumber;t.startLineNumber<=v+1&&h-1<=t.endLineNumber&&h!==l&&(l=h,s.push(new p(h,v-1,g+1)),this.getCandidateStickyLinesIntersectingFromStickyModel(t,f,s,g+1,h))}else this.getCandidateStickyLinesIntersectingFromStickyModel(t,f,s,g,c)}}getCandidateStickyLinesIntersecting(t){if(!this._model?.element)return[];let i=[];this.getCandidateStickyLinesIntersectingFromStickyModel(t,this._model.element,i,0,-1);const s=this._editor._getViewModel()?.getHiddenAreas();if(s)for(const g of s)i=i.filter(c=>!(c.startLineNumber>=g.startLineNumber&&c.endLineNumber<=g.endLineNumber+1));return i}};e.StickyLineCandidateProvider=n,e.StickyLineCandidateProvider=n=ke([ce(1,k.ILanguageFeaturesService),ce(2,_.ILanguageConfigurationService)],n)}),define(ne[838],se([1,0,5,103,13,2,30,281,125,9,116,150,136,424,531]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StickyScrollWidget=e.StickyScrollWidgetState=void 0;class i{constructor(h,v,w,S=null){this.startLineNumbers=h,this.endLineNumbers=v,this.lastLineRelativePosition=w,this.showEndForLine=S}equals(h){return!!h&&this.lastLineRelativePosition===h.lastLineRelativePosition&&this.showEndForLine===h.showEndForLine&&(0,I.equals)(this.startLineNumbers,h.startLineNumbers)&&(0,I.equals)(this.endLineNumbers,h.endLineNumbers)}static get Empty(){return new i([],[],0)}}e.StickyScrollWidgetState=i;const s=(0,k.createTrustedTypesPolicy)("stickyScrollViewLayer",{createHTML:f=>f}),g="data-sticky-line-index",c="data-sticky-is-line",l="data-sticky-is-line-number",a="data-sticky-is-folding-icon";class r extends E.Disposable{constructor(h){super(),this._editor=h,this._foldingIconStore=new E.DisposableStore,this._rootDomNode=document.createElement("div"),this._lineNumbersDomNode=document.createElement("div"),this._linesDomNodeScrollable=document.createElement("div"),this._linesDomNode=document.createElement("div"),this._lineHeight=this._editor.getOption(67),this._renderedStickyLines=[],this._lineNumbers=[],this._lastLineRelativePosition=0,this._minContentWidthInPx=0,this._isOnGlyphMargin=!1,this._lineNumbersDomNode.className="sticky-widget-line-numbers",this._lineNumbersDomNode.setAttribute("role","none"),this._linesDomNode.className="sticky-widget-lines",this._linesDomNode.setAttribute("role","list"),this._linesDomNodeScrollable.className="sticky-widget-lines-scrollable",this._linesDomNodeScrollable.appendChild(this._linesDomNode),this._rootDomNode.className="sticky-widget",this._rootDomNode.classList.toggle("peek",h instanceof _.EmbeddedCodeEditorWidget),this._rootDomNode.appendChild(this._lineNumbersDomNode),this._rootDomNode.appendChild(this._linesDomNodeScrollable);const v=()=>{this._linesDomNode.style.left=this._editor.getOption(116).scrollWithEditor?`-${this._editor.getScrollLeft()}px`:"0px"};this._register(this._editor.onDidChangeConfiguration(w=>{w.hasChanged(116)&&v(),w.hasChanged(67)&&(this._lineHeight=this._editor.getOption(67))})),this._register(this._editor.onDidScrollChange(w=>{w.scrollLeftChanged&&v(),w.scrollWidthChanged&&this._updateWidgetWidth()})),this._register(this._editor.onDidChangeModel(()=>{v(),this._updateWidgetWidth()})),this._register(this._foldingIconStore),v(),this._register(this._editor.onDidLayoutChange(w=>{this._updateWidgetWidth()})),this._updateWidgetWidth()}get lineNumbers(){return this._lineNumbers}get lineNumberCount(){return this._lineNumbers.length}getRenderedStickyLine(h){return this._renderedStickyLines.find(v=>v.lineNumber===h)}getCurrentLines(){return this._lineNumbers}setState(h,v,w){if(w===void 0&&(!this._previousState&&!h||this._previousState&&this._previousState.equals(h)))return;const S=this._isWidgetHeightZero(h),L=S?void 0:h,D=S?0:this._findLineToRebuildWidgetFrom(h,w);this._renderRootNode(L,v,D),this._previousState=h}_isWidgetHeightZero(h){if(!h)return!0;const v=h.startLineNumbers.length*this._lineHeight+h.lastLineRelativePosition;if(v>0){this._lastLineRelativePosition=h.lastLineRelativePosition;const w=[...h.startLineNumbers];h.showEndForLine!==null&&(w[h.showEndForLine]=h.endLineNumbers[h.showEndForLine]),this._lineNumbers=w}else this._lastLineRelativePosition=0,this._lineNumbers=[];return v===0}_findLineToRebuildWidgetFrom(h,v){if(!h||!this._previousState)return 0;if(v!==void 0)return v;const w=this._previousState,S=h.startLineNumbers.findIndex(L=>!w.startLineNumbers.includes(L));return S===-1?0:S}_updateWidgetWidth(){const h=this._editor.getLayoutInfo(),v=h.contentLeft;this._lineNumbersDomNode.style.width=`${v}px`,this._linesDomNodeScrollable.style.setProperty("--vscode-editorStickyScroll-scrollableWidth",`${this._editor.getScrollWidth()-h.verticalScrollbarWidth}px`),this._rootDomNode.style.width=`${h.width-h.verticalScrollbarWidth}px`}_clearStickyLinesFromLine(h){this._foldingIconStore.clear();for(let v=h;vT.scrollWidth))+S.verticalScrollbarWidth,this._editor.layoutOverlayWidget(this)}_setFoldingHoverListeners(){this._editor.getOption(111)==="mouseover"&&(this._foldingIconStore.add(d.addDisposableListener(this._lineNumbersDomNode,d.EventType.MOUSE_ENTER,()=>{this._isOnGlyphMargin=!0,this._setFoldingIconsVisibility(!0)})),this._foldingIconStore.add(d.addDisposableListener(this._lineNumbersDomNode,d.EventType.MOUSE_LEAVE,()=>{this._isOnGlyphMargin=!1,this._useFoldingOpacityTransition(!0),this._setFoldingIconsVisibility(!1)})))}_renderChildNode(h,v,w,S){const L=this._editor._getViewModel();if(!L)return;const D=L.coordinatesConverter.convertModelPositionToViewPosition(new b.Position(v,1)).lineNumber,T=L.getViewLineRenderingData(D),M=this._editor.getOption(68);let A;try{A=n.LineDecoration.filter(T.inlineDecorations,D,T.minColumn,T.maxColumn)}catch{A=[]}const P=new o.RenderLineInput(!0,!0,T.content,T.continuesWithWrappedLine,T.isBasicASCII,T.containsRTL,0,T.tokens,A,T.tabSize,T.startVisibleColumn,1,1,1,500,"none",!0,!0,null),N=new p.StringBuilder(2e3),O=(0,o.renderViewLine)(P,N);let F;s?F=s.createHTML(N.build()):F=N.build();const x=document.createElement("span");x.setAttribute(g,String(h)),x.setAttribute(c,""),x.setAttribute("role","listitem"),x.tabIndex=0,x.className="sticky-line-content",x.classList.add(`stickyLine${v}`),x.style.lineHeight=`${this._lineHeight}px`,x.innerHTML=F;const W=document.createElement("span");W.setAttribute(g,String(h)),W.setAttribute(l,""),W.className="sticky-line-number",W.style.lineHeight=`${this._lineHeight}px`;const V=S.contentLeft;W.style.width=`${V}px`;const q=document.createElement("span");M.renderType===1||M.renderType===3&&v%10===0?q.innerText=v.toString():M.renderType===2&&(q.innerText=Math.abs(v-this._editor.getPosition().lineNumber).toString()),q.className="sticky-line-number-inner",q.style.lineHeight=`${this._lineHeight}px`,q.style.width=`${S.lineNumbersWidth}px`,q.style.paddingLeft=`${S.lineNumbersLeft}px`,W.appendChild(q);const H=this._renderFoldingIconForLine(w,v);H&&W.appendChild(H.domNode),this._editor.applyFontInfo(x),this._editor.applyFontInfo(q),W.style.lineHeight=`${this._lineHeight}px`,x.style.lineHeight=`${this._lineHeight}px`,W.style.height=`${this._lineHeight}px`,x.style.height=`${this._lineHeight}px`;const z=new u(h,v,x,W,H,O.characterMapping,x.scrollWidth);return this._updateTopAndZIndexOfStickyLine(z)}_updateTopAndZIndexOfStickyLine(h){const v=h.index,w=h.lineDomNode,S=h.lineNumberDomNode,L=v===this._lineNumbers.length-1,D="0",T="1";w.style.zIndex=L?D:T,S.style.zIndex=L?D:T;const M=`${v*this._lineHeight+this._lastLineRelativePosition+(h.foldingIcon?.isCollapsed?1:0)}px`,A=`${v*this._lineHeight}px`;return w.style.top=L?M:A,S.style.top=L?M:A,h}_renderFoldingIconForLine(h,v){const w=this._editor.getOption(111);if(!h||w==="never")return;const S=h.regions,L=S.findRange(v),D=S.getStartLineNumber(L);if(!(v===D))return;const M=S.isCollapsed(L),A=new C(M,D,S.getEndLineNumber(L),this._lineHeight);return A.setVisible(this._isOnGlyphMargin?!0:M||w==="always"),A.domNode.setAttribute(a,""),A}getId(){return"editor.contrib.stickyScrollWidget"}getDomNode(){return this._rootDomNode}getPosition(){return{preference:2,stackOridinal:10}}getMinContentWidthInPx(){return this._minContentWidthInPx}focusLineWithIndex(h){0<=h&&h0)return null;const v=this._getRenderedStickyLineFromChildDomNode(h);if(!v)return null;const w=(0,m.getColumnOfNodeOffset)(v.characterMapping,h,0);return new b.Position(v.lineNumber,w)}getLineNumberFromChildDomNode(h){return this._getRenderedStickyLineFromChildDomNode(h)?.lineNumber??null}_getRenderedStickyLineFromChildDomNode(h){const v=this.getLineIndexFromChildDomNode(h);return v===null||v<0||v>=this._renderedStickyLines.length?null:this._renderedStickyLines[v]}getLineIndexFromChildDomNode(h){const v=this._getAttributeValue(h,g);return v?parseInt(v,10):null}isInStickyLine(h){return this._getAttributeValue(h,c)!==void 0}isInFoldingIconDomNode(h){return this._getAttributeValue(h,a)!==void 0}_getAttributeValue(h,v){for(;h&&h!==this._rootDomNode;){const w=h.getAttribute(v);if(w!==null)return w;h=h.parentElement}}}e.StickyScrollWidget=r;class u{constructor(h,v,w,S,L,D,T){this.index=h,this.lineNumber=v,this.lineDomNode=w,this.lineNumberDomNode=S,this.foldingIcon=L,this.characterMapping=D,this.scrollWidth=T}}class C{constructor(h,v,w,S){this.isCollapsed=h,this.foldingStartLine=v,this.foldingEndLine=w,this.dimension=S,this.domNode=document.createElement("div"),this.domNode.style.width=`${S}px`,this.domNode.style.height=`${S}px`,this.domNode.className=y.ThemeIcon.asClassName(h?t.foldingCollapsedIcon:t.foldingExpandedIcon)}setVisible(h){this.domNode.style.cursor=h?"pointer":"default",this.domNode.style.opacity=h?"1":"0"}}}),define(ne[839],se([1,0,5,115,14,8,6,2,141,11,125,798,3,12,7,101,32,97,25,255,155,402,793,110,46,195,532,280]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h){"use strict";var v;Object.defineProperty(e,"__esModule",{value:!0}),e.SuggestContentWidget=e.SuggestWidget=e.editorSuggestWidgetSelectedBackground=void 0,(0,g.registerColor)("editorSuggestWidget.background",g.editorWidgetBackground,o.localize(1328,"Background color of the suggest widget.")),(0,g.registerColor)("editorSuggestWidget.border",g.editorWidgetBorder,o.localize(1329,"Border color of the suggest widget."));const w=(0,g.registerColor)("editorSuggestWidget.foreground",g.editorForeground,o.localize(1330,"Foreground color of the suggest widget."));(0,g.registerColor)("editorSuggestWidget.selectedForeground",g.quickInputListFocusForeground,o.localize(1331,"Foreground color of the selected entry in the suggest widget.")),(0,g.registerColor)("editorSuggestWidget.selectedIconForeground",g.quickInputListFocusIconForeground,o.localize(1332,"Icon foreground color of the selected entry in the suggest widget.")),e.editorSuggestWidgetSelectedBackground=(0,g.registerColor)("editorSuggestWidget.selectedBackground",g.quickInputListFocusBackground,o.localize(1333,"Background color of the selected entry in the suggest widget.")),(0,g.registerColor)("editorSuggestWidget.highlightForeground",g.listHighlightForeground,o.localize(1334,"Color of the match highlights in the suggest widget.")),(0,g.registerColor)("editorSuggestWidget.focusHighlightForeground",g.listFocusHighlightForeground,o.localize(1335,"Color of the match highlights in the suggest widget when an item is focused.")),(0,g.registerColor)("editorSuggestWidgetStatus.foreground",(0,g.transparent)(w,.5),o.localize(1336,"Foreground color of the suggest widget status."));class S{constructor(M,A){this._service=M,this._key=`suggestWidget.size/${A.getEditorType()}/${A instanceof p.EmbeddedCodeEditorWidget}`}restore(){const M=this._service.get(this._key,0)??"";try{const A=JSON.parse(M);if(d.Dimension.is(A))return d.Dimension.lift(A)}catch{}}store(M){this._service.store(this._key,JSON.stringify(M),0,1)}reset(){this._service.remove(this._key,0)}}let L=class{static{v=this}static{this.LOADING_MESSAGE=o.localize(1337,"Loading...")}static{this.NO_SUGGESTIONS_MESSAGE=o.localize(1338,"No suggestions.")}constructor(M,A,P,N,O){this.editor=M,this._storageService=A,this._state=0,this._isAuto=!1,this._pendingLayout=new m.MutableDisposable,this._pendingShowDetails=new m.MutableDisposable,this._ignoreFocusEvents=!1,this._forceRenderingAbove=!1,this._explainMode=!1,this._showTimeout=new I.TimeoutTimer,this._disposables=new m.DisposableStore,this._onDidSelect=new y.PauseableEmitter,this._onDidFocus=new y.PauseableEmitter,this._onDidHide=new y.Emitter,this._onDidShow=new y.Emitter,this.onDidSelect=this._onDidSelect.event,this.onDidFocus=this._onDidFocus.event,this.onDidHide=this._onDidHide.event,this.onDidShow=this._onDidShow.event,this._onDetailsKeydown=new y.Emitter,this.onDetailsKeyDown=this._onDetailsKeydown.event,this.element=new a.ResizableHTMLElement,this.element.domNode.classList.add("editor-widget","suggest-widget"),this._contentWidget=new D(this,M),this._persistedSize=new S(A,M);class F{constructor(U,j,Y=!1,G=!1){this.persistedSize=U,this.currentSize=j,this.persistHeight=Y,this.persistWidth=G}}let x;this._disposables.add(this.element.onDidWillResize(()=>{this._contentWidget.lockPreference(),x=new F(this._persistedSize.restore(),this.element.size)})),this._disposables.add(this.element.onDidResize(z=>{if(this._resize(z.dimension.width,z.dimension.height),x&&(x.persistHeight=x.persistHeight||!!z.north||!!z.south,x.persistWidth=x.persistWidth||!!z.east||!!z.west),!!z.done){if(x){const{itemHeight:U,defaultSize:j}=this.getLayoutInfo(),Y=Math.round(U/2);let{width:G,height:K}=this.element.size;(!x.persistHeight||Math.abs(x.currentSize.height-K)<=Y)&&(K=x.persistedSize?.height??j.height),(!x.persistWidth||Math.abs(x.currentSize.width-G)<=Y)&&(G=x.persistedSize?.width??j.width),this._persistedSize.store(new d.Dimension(G,K))}this._contentWidget.unlockPreference(),x=void 0}})),this._messageElement=d.append(this.element.domNode,d.$(".message")),this._listElement=d.append(this.element.domNode,d.$(".tree"));const W=this._disposables.add(O.createInstance(u.SuggestDetailsWidget,this.editor));W.onDidClose(this.toggleDetails,this,this._disposables),this._details=new u.SuggestDetailsOverlay(W,this.editor);const V=()=>this.element.domNode.classList.toggle("no-icons",!this.editor.getOption(119).showIcons);V();const q=O.createInstance(C.ItemRenderer,this.editor);this._disposables.add(q),this._disposables.add(q.onDidToggleDetails(()=>this.toggleDetails())),this._list=new k.List("SuggestWidget",this._listElement,{getHeight:z=>this.getLayoutInfo().itemHeight,getTemplateId:z=>"suggestion"},[q],{alwaysConsumeMouseWheel:!0,useShadows:!1,mouseSupport:!1,multipleSelectionSupport:!1,accessibilityProvider:{getRole:()=>"option",getWidgetAriaLabel:()=>o.localize(1339,"Suggest"),getWidgetRole:()=>"listbox",getAriaLabel:z=>{let U=z.textLabel;if(typeof z.completion.label!="string"){const{detail:K,description:R}=z.completion.label;K&&R?U=o.localize(1340,"{0} {1}, {2}",U,K,R):K?U=o.localize(1341,"{0} {1}",U,K):R&&(U=o.localize(1342,"{0}, {1}",U,R))}if(!z.isResolved||!this._isDetailsVisible())return U;const{documentation:j,detail:Y}=z.completion,G=b.format("{0}{1}",Y||"",j?typeof j=="string"?j:j.value:"");return o.localize(1343,"{0}, docs: {1}",U,G)}}}),this._list.style((0,f.getListStyles)({listInactiveFocusBackground:e.editorSuggestWidgetSelectedBackground,listInactiveFocusOutline:g.activeContrastBorder})),this._status=O.createInstance(n.SuggestWidgetStatus,this.element.domNode,r.suggestWidgetStatusbarMenu);const H=()=>this.element.domNode.classList.toggle("with-status-bar",this.editor.getOption(119).showStatusBar);H(),this._disposables.add(N.onDidColorThemeChange(z=>this._onThemeChange(z))),this._onThemeChange(N.getColorTheme()),this._disposables.add(this._list.onMouseDown(z=>this._onListMouseDownOrTap(z))),this._disposables.add(this._list.onTap(z=>this._onListMouseDownOrTap(z))),this._disposables.add(this._list.onDidChangeSelection(z=>this._onListSelection(z))),this._disposables.add(this._list.onDidChangeFocus(z=>this._onListFocus(z))),this._disposables.add(this.editor.onDidChangeCursorSelection(()=>this._onCursorSelectionChanged())),this._disposables.add(this.editor.onDidChangeConfiguration(z=>{z.hasChanged(119)&&(H(),V()),this._completionModel&&(z.hasChanged(50)||z.hasChanged(120)||z.hasChanged(121))&&this._list.splice(0,this._list.length,this._completionModel.items)})),this._ctxSuggestWidgetVisible=r.Context.Visible.bindTo(P),this._ctxSuggestWidgetDetailsVisible=r.Context.DetailsVisible.bindTo(P),this._ctxSuggestWidgetMultipleSuggestions=r.Context.MultipleSuggestions.bindTo(P),this._ctxSuggestWidgetHasFocusedSuggestion=r.Context.HasFocusedSuggestion.bindTo(P),this._disposables.add(d.addStandardDisposableListener(this._details.widget.domNode,"keydown",z=>{this._onDetailsKeydown.fire(z)})),this._disposables.add(this.editor.onMouseDown(z=>this._onEditorMouseDown(z)))}dispose(){this._details.widget.dispose(),this._details.dispose(),this._list.dispose(),this._status.dispose(),this._disposables.dispose(),this._loadingTimeout?.dispose(),this._pendingLayout.dispose(),this._pendingShowDetails.dispose(),this._showTimeout.dispose(),this._contentWidget.dispose(),this.element.dispose()}_onEditorMouseDown(M){this._details.widget.domNode.contains(M.target.element)?this._details.widget.domNode.focus():this.element.domNode.contains(M.target.element)&&this.editor.focus()}_onCursorSelectionChanged(){this._state!==0&&this._contentWidget.layout()}_onListMouseDownOrTap(M){typeof M.element>"u"||typeof M.index>"u"||(M.browserEvent.preventDefault(),M.browserEvent.stopPropagation(),this._select(M.element,M.index))}_onListSelection(M){M.elements.length&&this._select(M.elements[0],M.indexes[0])}_select(M,A){const P=this._completionModel;P&&(this._onDidSelect.fire({item:M,index:A,model:P}),this.editor.focus())}_onThemeChange(M){this._details.widget.borderWidth=(0,c.isHighContrast)(M.type)?2:1}_onListFocus(M){if(this._ignoreFocusEvents)return;if(!M.elements.length){this._currentSuggestionDetails&&(this._currentSuggestionDetails.cancel(),this._currentSuggestionDetails=void 0,this._focusedItem=void 0),this.editor.setAriaOptions({activeDescendant:void 0}),this._ctxSuggestWidgetHasFocusedSuggestion.set(!1);return}if(!this._completionModel)return;this._ctxSuggestWidgetHasFocusedSuggestion.set(!0);const A=M.elements[0],P=M.indexes[0];A!==this._focusedItem&&(this._currentSuggestionDetails?.cancel(),this._currentSuggestionDetails=void 0,this._focusedItem=A,this._list.reveal(P),this._currentSuggestionDetails=(0,I.createCancelablePromise)(async N=>{const O=(0,I.disposableTimeout)(()=>{this._isDetailsVisible()&&this.showDetails(!0)},250),F=N.onCancellationRequested(()=>O.dispose());try{return await A.resolve(N)}finally{O.dispose(),F.dispose()}}),this._currentSuggestionDetails.then(()=>{P>=this._list.length||A!==this._list.element(P)||(this._ignoreFocusEvents=!0,this._list.splice(P,1,[A]),this._list.setFocus([P]),this._ignoreFocusEvents=!1,this._isDetailsVisible()?this.showDetails(!1):this.element.domNode.classList.remove("docs-side"),this.editor.setAriaOptions({activeDescendant:(0,C.getAriaId)(P)}))}).catch(E.onUnexpectedError)),this._onDidFocus.fire({item:A,index:P,model:this._completionModel})}_setState(M){if(this._state!==M)switch(this._state=M,this.element.domNode.classList.toggle("frozen",M===4),this.element.domNode.classList.remove("message"),M){case 0:d.hide(this._messageElement,this._listElement,this._status.element),this._details.hide(!0),this._status.hide(),this._contentWidget.hide(),this._ctxSuggestWidgetVisible.reset(),this._ctxSuggestWidgetMultipleSuggestions.reset(),this._ctxSuggestWidgetHasFocusedSuggestion.reset(),this._showTimeout.cancel(),this.element.domNode.classList.remove("visible"),this._list.splice(0,this._list.length),this._focusedItem=void 0,this._cappedHeight=void 0,this._explainMode=!1;break;case 1:this.element.domNode.classList.add("message"),this._messageElement.textContent=v.LOADING_MESSAGE,d.hide(this._listElement,this._status.element),d.show(this._messageElement),this._details.hide(),this._show(),this._focusedItem=void 0,(0,h.status)(v.LOADING_MESSAGE);break;case 2:this.element.domNode.classList.add("message"),this._messageElement.textContent=v.NO_SUGGESTIONS_MESSAGE,d.hide(this._listElement,this._status.element),d.show(this._messageElement),this._details.hide(),this._show(),this._focusedItem=void 0,(0,h.status)(v.NO_SUGGESTIONS_MESSAGE);break;case 3:d.hide(this._messageElement),d.show(this._listElement,this._status.element),this._show();break;case 4:d.hide(this._messageElement),d.show(this._listElement,this._status.element),this._show();break;case 5:d.hide(this._messageElement),d.show(this._listElement,this._status.element),this._details.show(),this._show();break}}_show(){this._status.show(),this._contentWidget.show(),this._layout(this._persistedSize.restore()),this._ctxSuggestWidgetVisible.set(!0),this._showTimeout.cancelAndSet(()=>{this.element.domNode.classList.add("visible"),this._onDidShow.fire(this)},100)}showTriggered(M,A){this._state===0&&(this._contentWidget.setPosition(this.editor.getPosition()),this._isAuto=!!M,this._isAuto||(this._loadingTimeout=(0,I.disposableTimeout)(()=>this._setState(1),A)))}showSuggestions(M,A,P,N,O){if(this._contentWidget.setPosition(this.editor.getPosition()),this._loadingTimeout?.dispose(),this._currentSuggestionDetails?.cancel(),this._currentSuggestionDetails=void 0,this._completionModel!==M&&(this._completionModel=M),P&&this._state!==2&&this._state!==0){this._setState(4);return}const F=this._completionModel.items.length,x=F===0;if(this._ctxSuggestWidgetMultipleSuggestions.set(F>1),x){this._setState(N?0:2),this._completionModel=void 0;return}this._focusedItem=void 0,this._onDidFocus.pause(),this._onDidSelect.pause();try{this._list.splice(0,this._list.length,this._completionModel.items),this._setState(P?4:3),this._list.reveal(A,0),this._list.setFocus(O?[]:[A])}finally{this._onDidFocus.resume(),this._onDidSelect.resume()}this._pendingLayout.value=d.runAtThisOrScheduleAtNextAnimationFrame(d.getWindow(this.element.domNode),()=>{this._pendingLayout.clear(),this._layout(this.element.size),this._details.widget.domNode.classList.remove("focused")})}focusSelected(){this._list.length>0&&this._list.setFocus([0])}selectNextPage(){switch(this._state){case 0:return!1;case 5:return this._details.widget.pageDown(),!0;case 1:return!this._isAuto;default:return this._list.focusNextPage(),!0}}selectNext(){switch(this._state){case 0:return!1;case 1:return!this._isAuto;default:return this._list.focusNext(1,!0),!0}}selectLast(){switch(this._state){case 0:return!1;case 5:return this._details.widget.scrollBottom(),!0;case 1:return!this._isAuto;default:return this._list.focusLast(),!0}}selectPreviousPage(){switch(this._state){case 0:return!1;case 5:return this._details.widget.pageUp(),!0;case 1:return!this._isAuto;default:return this._list.focusPreviousPage(),!0}}selectPrevious(){switch(this._state){case 0:return!1;case 1:return!this._isAuto;default:return this._list.focusPrevious(1,!0),!1}}selectFirst(){switch(this._state){case 0:return!1;case 5:return this._details.widget.scrollTop(),!0;case 1:return!this._isAuto;default:return this._list.focusFirst(),!0}}getFocusedItem(){if(this._state!==0&&this._state!==2&&this._state!==1&&this._completionModel&&this._list.getFocus().length>0)return{item:this._list.getFocusedElements()[0],index:this._list.getFocus()[0],model:this._completionModel}}toggleDetailsFocus(){this._state===5?(this._setState(3),this._details.widget.domNode.classList.remove("focused")):this._state===3&&this._isDetailsVisible()&&(this._setState(5),this._details.widget.domNode.classList.add("focused"))}toggleDetails(){this._isDetailsVisible()?(this._pendingShowDetails.clear(),this._ctxSuggestWidgetDetailsVisible.set(!1),this._setDetailsVisible(!1),this._details.hide(),this.element.domNode.classList.remove("shows-details")):((0,u.canExpandCompletionItem)(this._list.getFocusedElements()[0])||this._explainMode)&&(this._state===3||this._state===5||this._state===4)&&(this._ctxSuggestWidgetDetailsVisible.set(!0),this._setDetailsVisible(!0),this.showDetails(!1))}showDetails(M){this._pendingShowDetails.value=d.runAtThisOrScheduleAtNextAnimationFrame(d.getWindow(this.element.domNode),()=>{this._pendingShowDetails.clear(),this._details.show(),M?this._details.widget.renderLoading():this._details.widget.renderItem(this._list.getFocusedElements()[0],this._explainMode),this._details.widget.isEmpty?this._details.hide():(this._positionDetails(),this.element.domNode.classList.add("shows-details")),this.editor.focus()})}toggleExplainMode(){this._list.getFocusedElements()[0]&&(this._explainMode=!this._explainMode,this._isDetailsVisible()?this.showDetails(!1):this.toggleDetails())}resetPersistedSize(){this._persistedSize.reset()}hideWidget(){this._pendingLayout.clear(),this._pendingShowDetails.clear(),this._loadingTimeout?.dispose(),this._setState(0),this._onDidHide.fire(this),this.element.clearSashHoverState();const M=this._persistedSize.restore(),A=Math.ceil(this.getLayoutInfo().itemHeight*4.3);M&&M.heightF&&(O=F);const x=this._completionModel?this._completionModel.stats.pLabelLen*P.typicalHalfwidthCharacterWidth:O,W=P.statusBarHeight+this._list.contentHeight+P.borderHeight,V=P.itemHeight+P.statusBarHeight,q=d.getDomNodePagePosition(this.editor.getDomNode()),H=this.editor.getScrolledVisiblePosition(this.editor.getPosition()),z=q.top+H.top+H.height,U=Math.min(A.height-z-P.verticalPadding,W),j=q.top+H.top-P.verticalPadding,Y=Math.min(j,W);let G=Math.min(Math.max(Y,U)+P.borderHeight,W);N===this._cappedHeight?.capped&&(N=this._cappedHeight.wanted),NG&&(N=G),N>U||this._forceRenderingAbove&&j>150?(this._contentWidget.setPreference(1),this.element.enableSashes(!0,!0,!1,!1),G=Y):(this._contentWidget.setPreference(2),this.element.enableSashes(!1,!0,!0,!1),G=U),this.element.preferredSize=new d.Dimension(x,P.defaultSize.height),this.element.maxSize=new d.Dimension(F,G),this.element.minSize=new d.Dimension(220,V),this._cappedHeight=N===W?{wanted:this._cappedHeight?.wanted??M.height,capped:N}:void 0}this._resize(O,N)}_resize(M,A){const{width:P,height:N}=this.element.maxSize;M=Math.min(P,M),A=Math.min(N,A);const{statusBarHeight:O}=this.getLayoutInfo();this._list.layout(A-O,M),this._listElement.style.height=`${A-O}px`,this.element.layout(A,M),this._contentWidget.layout(),this._positionDetails()}_positionDetails(){this._isDetailsVisible()&&this._details.placeAtAnchor(this.element.domNode,this._contentWidget.getPosition()?.preference[0]===2)}getLayoutInfo(){const M=this.editor.getOption(50),A=(0,_.clamp)(this.editor.getOption(121)||M.lineHeight,8,1e3),P=!this.editor.getOption(119).showStatusBar||this._state===2||this._state===1?0:A,N=this._details.widget.borderWidth,O=2*N;return{itemHeight:A,statusBarHeight:P,borderWidth:N,borderHeight:O,typicalHalfwidthCharacterWidth:M.typicalHalfwidthCharacterWidth,verticalPadding:22,horizontalPadding:14,defaultSize:new d.Dimension(430,P+12*A+O)}}_isDetailsVisible(){return this._storageService.getBoolean("expandSuggestionDocs",0,!1)}_setDetailsVisible(M){this._storageService.store("expandSuggestionDocs",M,0,0)}forceRenderingAbove(){this._forceRenderingAbove||(this._forceRenderingAbove=!0,this._layout(this._persistedSize.restore()))}stopForceRenderingAbove(){this._forceRenderingAbove=!1}};e.SuggestWidget=L,e.SuggestWidget=L=v=ke([ce(1,s.IStorageService),ce(2,t.IContextKeyService),ce(3,l.IThemeService),ce(4,i.IInstantiationService)],L);class D{constructor(M,A){this._widget=M,this._editor=A,this.allowEditorOverflow=!0,this.suppressMouseDown=!1,this._preferenceLocked=!1,this._added=!1,this._hidden=!1}dispose(){this._added&&(this._added=!1,this._editor.removeContentWidget(this))}getId(){return"editor.widget.suggestWidget"}getDomNode(){return this._widget.element.domNode}show(){this._hidden=!1,this._added||(this._added=!0,this._editor.addContentWidget(this))}hide(){this._hidden||(this._hidden=!0,this.layout())}layout(){this._editor.layoutContentWidget(this)}getPosition(){return this._hidden||!this._position||!this._preference?null:{position:this._position,preference:[this._preference]}}beforeRender(){const{height:M,width:A}=this._widget.element.size,{borderWidth:P,horizontalPadding:N}=this._widget.getLayoutInfo();return new d.Dimension(A+2*P+N,M+2*P)}afterRender(M){this._widget._afterRender(M)}setPreference(M){this._preferenceLocked||(this._preference=M)}lockPreference(){this._preferenceLocked=!0}unlockPreference(){this._preferenceLocked=!1}setPosition(M){this._position=M}}e.SuggestContentWidget=D}),define(ne[426],se([1,0,40,35,27,3,32,25,536]),function(oe,e,d,k,I,E,y,m){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getHighlightDecorationOptions=l,e.getSelectionHighlightDecorationOptions=a;const _=(0,y.registerColor)("editor.wordHighlightBackground",{dark:"#575757B8",light:"#57575740",hcDark:null,hcLight:null},E.localize(1415,"Background color of a symbol during read-access, like reading a variable. The color must not be opaque so as not to hide underlying decorations."),!0);(0,y.registerColor)("editor.wordHighlightStrongBackground",{dark:"#004972B8",light:"#0e639c40",hcDark:null,hcLight:null},E.localize(1416,"Background color of a symbol during write-access, like writing to a variable. The color must not be opaque so as not to hide underlying decorations."),!0),(0,y.registerColor)("editor.wordHighlightTextBackground",_,E.localize(1417,"Background color of a textual occurrence for a symbol. The color must not be opaque so as not to hide underlying decorations."),!0);const b=(0,y.registerColor)("editor.wordHighlightBorder",{light:null,dark:null,hcDark:y.activeContrastBorder,hcLight:y.activeContrastBorder},E.localize(1418,"Border color of a symbol during read-access, like reading a variable."));(0,y.registerColor)("editor.wordHighlightStrongBorder",{light:null,dark:null,hcDark:y.activeContrastBorder,hcLight:y.activeContrastBorder},E.localize(1419,"Border color of a symbol during write-access, like writing to a variable.")),(0,y.registerColor)("editor.wordHighlightTextBorder",b,E.localize(1420,"Border color of a textual occurrence for a symbol."));const p=(0,y.registerColor)("editorOverviewRuler.wordHighlightForeground","#A0A0A0CC",E.localize(1421,"Overview ruler marker color for symbol highlights. The color must not be opaque so as not to hide underlying decorations."),!0),n=(0,y.registerColor)("editorOverviewRuler.wordHighlightStrongForeground","#C0A0C0CC",E.localize(1422,"Overview ruler marker color for write-access symbol highlights. The color must not be opaque so as not to hide underlying decorations."),!0),o=(0,y.registerColor)("editorOverviewRuler.wordHighlightTextForeground",y.overviewRulerSelectionHighlightForeground,E.localize(1423,"Overview ruler marker color of a textual occurrence for a symbol. The color must not be opaque so as not to hide underlying decorations."),!0),t=k.ModelDecorationOptions.register({description:"word-highlight-strong",stickiness:1,className:"wordHighlightStrong",overviewRuler:{color:(0,m.themeColorFromId)(n),position:d.OverviewRulerLane.Center},minimap:{color:(0,m.themeColorFromId)(y.minimapSelectionOccurrenceHighlight),position:1}}),i=k.ModelDecorationOptions.register({description:"word-highlight-text",stickiness:1,className:"wordHighlightText",overviewRuler:{color:(0,m.themeColorFromId)(o),position:d.OverviewRulerLane.Center},minimap:{color:(0,m.themeColorFromId)(y.minimapSelectionOccurrenceHighlight),position:1}}),s=k.ModelDecorationOptions.register({description:"selection-highlight-overview",stickiness:1,className:"selectionHighlight",overviewRuler:{color:(0,m.themeColorFromId)(y.overviewRulerSelectionHighlightForeground),position:d.OverviewRulerLane.Center},minimap:{color:(0,m.themeColorFromId)(y.minimapSelectionOccurrenceHighlight),position:1}}),g=k.ModelDecorationOptions.register({description:"selection-highlight",stickiness:1,className:"selectionHighlight"}),c=k.ModelDecorationOptions.register({description:"word-highlight",stickiness:1,className:"wordHighlight",overviewRuler:{color:(0,m.themeColorFromId)(p),position:d.OverviewRulerLane.Center},minimap:{color:(0,m.themeColorFromId)(y.minimapSelectionOccurrenceHighlight),position:1}});function l(r){return r===I.DocumentHighlightKind.Write?t:r===I.DocumentHighlightKind.Text?i:c}function a(r){return r?g:s}(0,m.registerThemingParticipant)((r,u)=>{const C=r.getColor(y.editorSelectionHighlight);C&&u.addRule(`.monaco-editor .selectionHighlight { background-color: ${C.transparent(.5)}; }`)})}),define(ne[840],se([1,0,46,14,72,2,15,235,4,23,20,423,3,29,12,17,426,7]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";var l;Object.defineProperty(e,"__esModule",{value:!0}),e.FocusPreviousCursor=e.FocusNextCursor=e.SelectionHighlighter=e.CompatChangeAll=e.SelectHighlightsAction=e.MoveSelectionToPreviousFindMatchAction=e.MoveSelectionToNextFindMatchAction=e.AddSelectionToPreviousFindMatchAction=e.AddSelectionToNextFindMatchAction=e.MultiCursorSelectionControllerAction=e.MultiCursorSelectionController=e.MultiCursorSession=e.MultiCursorSessionResult=e.InsertCursorBelow=e.InsertCursorAbove=void 0;function a(H,z){const U=z.filter(j=>!H.find(Y=>Y.equals(j)));if(U.length>=1){const j=U.map(G=>`line ${G.viewState.position.lineNumber} column ${G.viewState.position.column}`).join(", "),Y=U.length===1?o.localize(1149,"Cursor added: {0}",j):o.localize(1150,"Cursors added: {0}",j);(0,d.status)(Y)}}class r extends y.EditorAction{constructor(){super({id:"editor.action.insertCursorAbove",label:o.localize(1151,"Add Cursor Above"),alias:"Add Cursor Above",precondition:void 0,kbOpts:{kbExpr:p.EditorContextKeys.editorTextFocus,primary:2576,linux:{primary:1552,secondary:[3088]},weight:100},menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"3_multi",title:o.localize(1152,"&&Add Cursor Above"),order:2}})}run(z,U,j){if(!U.hasModel())return;let Y=!0;j&&j.logicalLine===!1&&(Y=!1);const G=U._getViewModel();if(G.cursorConfig.readOnly)return;G.model.pushStackElement();const K=G.getCursorStates();G.setCursorStates(j.source,3,m.CursorMoveCommands.addCursorUp(G,K,Y)),G.revealTopMostCursor(j.source),a(K,G.getCursorStates())}}e.InsertCursorAbove=r;class u extends y.EditorAction{constructor(){super({id:"editor.action.insertCursorBelow",label:o.localize(1153,"Add Cursor Below"),alias:"Add Cursor Below",precondition:void 0,kbOpts:{kbExpr:p.EditorContextKeys.editorTextFocus,primary:2578,linux:{primary:1554,secondary:[3090]},weight:100},menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"3_multi",title:o.localize(1154,"A&&dd Cursor Below"),order:3}})}run(z,U,j){if(!U.hasModel())return;let Y=!0;j&&j.logicalLine===!1&&(Y=!1);const G=U._getViewModel();if(G.cursorConfig.readOnly)return;G.model.pushStackElement();const K=G.getCursorStates();G.setCursorStates(j.source,3,m.CursorMoveCommands.addCursorDown(G,K,Y)),G.revealBottomMostCursor(j.source),a(K,G.getCursorStates())}}e.InsertCursorBelow=u;class C extends y.EditorAction{constructor(){super({id:"editor.action.insertCursorAtEndOfEachLineSelected",label:o.localize(1155,"Add Cursors to Line Ends"),alias:"Add Cursors to Line Ends",precondition:void 0,kbOpts:{kbExpr:p.EditorContextKeys.editorTextFocus,primary:1575,weight:100},menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"3_multi",title:o.localize(1156,"Add C&&ursors to Line Ends"),order:4}})}getCursorsForSelection(z,U,j){if(!z.isEmpty()){for(let Y=z.startLineNumber;Y1&&j.push(new b.Selection(z.endLineNumber,z.endColumn,z.endLineNumber,z.endColumn))}}run(z,U){if(!U.hasModel())return;const j=U.getModel(),Y=U.getSelections(),G=U._getViewModel(),K=G.getCursorStates(),R=[];Y.forEach(J=>this.getCursorsForSelection(J,j,R)),R.length>0&&U.setSelections(R),a(K,G.getCursorStates())}}class f extends y.EditorAction{constructor(){super({id:"editor.action.addCursorsToBottom",label:o.localize(1157,"Add Cursors To Bottom"),alias:"Add Cursors To Bottom",precondition:void 0})}run(z,U){if(!U.hasModel())return;const j=U.getSelections(),Y=U.getModel().getLineCount(),G=[];for(let J=j[0].startLineNumber;J<=Y;J++)G.push(new b.Selection(J,j[0].startColumn,J,j[0].endColumn));const K=U._getViewModel(),R=K.getCursorStates();G.length>0&&U.setSelections(G),a(R,K.getCursorStates())}}class h extends y.EditorAction{constructor(){super({id:"editor.action.addCursorsToTop",label:o.localize(1158,"Add Cursors To Top"),alias:"Add Cursors To Top",precondition:void 0})}run(z,U){if(!U.hasModel())return;const j=U.getSelections(),Y=[];for(let R=j[0].startLineNumber;R>=1;R--)Y.push(new b.Selection(R,j[0].startColumn,R,j[0].endColumn));const G=U._getViewModel(),K=G.getCursorStates();Y.length>0&&U.setSelections(Y),a(K,G.getCursorStates())}}class v{constructor(z,U,j){this.selections=z,this.revealRange=U,this.revealScrollType=j}}e.MultiCursorSessionResult=v;class w{static create(z,U){if(!z.hasModel())return null;const j=U.getState();if(!z.hasTextFocus()&&j.isRevealed&&j.searchString.length>0)return new w(z,U,!1,j.searchString,j.wholeWord,j.matchCase,null);let Y=!1,G,K;const R=z.getSelections();R.length===1&&R[0].isEmpty()?(Y=!0,G=!0,K=!0):(G=j.wholeWord,K=j.matchCase);const J=z.getSelection();let ie,ue=null;if(J.isEmpty()){const he=z.getConfiguredWordAtPosition(J.getStartPosition());if(!he)return null;ie=he.word,ue=new b.Selection(J.startLineNumber,he.startColumn,J.startLineNumber,he.endColumn)}else ie=z.getModel().getValueInRange(J).replace(/\r\n/g,` `);return new w(z,U,Y,ie,G,K,ue)}constructor(z,U,j,Y,G,K,R){this._editor=z,this.findController=U,this.isDisconnectedFromFindController=j,this.searchText=Y,this.wholeWord=G,this.matchCase=K,this.currentMatch=R}addSelectionToNextFindMatch(){if(!this._editor.hasModel())return null;const z=this._getNextMatch();if(!z)return null;const U=this._editor.getSelections();return new v(U.concat(z),z,0)}moveSelectionToNextFindMatch(){if(!this._editor.hasModel())return null;const z=this._getNextMatch();if(!z)return null;const U=this._editor.getSelections();return new v(U.slice(0,U.length-1).concat(z),z,0)}_getNextMatch(){if(!this._editor.hasModel())return null;if(this.currentMatch){const Y=this.currentMatch;return this.currentMatch=null,Y}this.findController.highlightFindOptions();const z=this._editor.getSelections(),U=z[z.length-1],j=this._editor.getModel().findNextMatch(this.searchText,U.getEndPosition(),!1,this.matchCase,this.wholeWord?this._editor.getOption(132):null,!1);return j?new b.Selection(j.range.startLineNumber,j.range.startColumn,j.range.endLineNumber,j.range.endColumn):null}addSelectionToPreviousFindMatch(){if(!this._editor.hasModel())return null;const z=this._getPreviousMatch();if(!z)return null;const U=this._editor.getSelections();return new v(U.concat(z),z,0)}moveSelectionToPreviousFindMatch(){if(!this._editor.hasModel())return null;const z=this._getPreviousMatch();if(!z)return null;const U=this._editor.getSelections();return new v(U.slice(0,U.length-1).concat(z),z,0)}_getPreviousMatch(){if(!this._editor.hasModel())return null;if(this.currentMatch){const Y=this.currentMatch;return this.currentMatch=null,Y}this.findController.highlightFindOptions();const z=this._editor.getSelections(),U=z[z.length-1],j=this._editor.getModel().findPreviousMatch(this.searchText,U.getStartPosition(),!1,this.matchCase,this.wholeWord?this._editor.getOption(132):null,!1);return j?new b.Selection(j.range.startLineNumber,j.range.startColumn,j.range.endLineNumber,j.range.endColumn):null}selectAll(z){if(!this._editor.hasModel())return[];this.findController.highlightFindOptions();const U=this._editor.getModel();return z?U.findMatches(this.searchText,z,!1,this.matchCase,this.wholeWord?this._editor.getOption(132):null,!1,1073741824):U.findMatches(this.searchText,!0,!1,this.matchCase,this.wholeWord?this._editor.getOption(132):null,!1,1073741824)}}e.MultiCursorSession=w;class S extends E.Disposable{static{this.ID="editor.contrib.multiCursorController"}static get(z){return z.getContribution(S.ID)}constructor(z){super(),this._sessionDispose=this._register(new E.DisposableStore),this._editor=z,this._ignoreSelectionChange=!1,this._session=null}dispose(){this._endSession(),super.dispose()}_beginSessionIfNeeded(z){if(!this._session){const U=w.create(this._editor,z);if(!U)return;this._session=U;const j={searchString:this._session.searchText};this._session.isDisconnectedFromFindController&&(j.wholeWordOverride=1,j.matchCaseOverride=1,j.isRegexOverride=2),z.getState().change(j,!1),this._sessionDispose.add(this._editor.onDidChangeCursorSelection(Y=>{this._ignoreSelectionChange||this._endSession()})),this._sessionDispose.add(this._editor.onDidBlurEditorText(()=>{this._endSession()})),this._sessionDispose.add(z.getState().onFindReplaceStateChange(Y=>{(Y.matchCase||Y.wholeWord)&&this._endSession()}))}}_endSession(){if(this._sessionDispose.clear(),this._session&&this._session.isDisconnectedFromFindController){const z={wholeWordOverride:0,matchCaseOverride:0,isRegexOverride:0};this._session.findController.getState().change(z,!1)}this._session=null}_setSelections(z){this._ignoreSelectionChange=!0,this._editor.setSelections(z),this._ignoreSelectionChange=!1}_expandEmptyToWord(z,U){if(!U.isEmpty())return U;const j=this._editor.getConfiguredWordAtPosition(U.getStartPosition());return j?new b.Selection(U.startLineNumber,j.startColumn,U.startLineNumber,j.endColumn):U}_applySessionResult(z){z&&(this._setSelections(z.selections),z.revealRange&&this._editor.revealRangeInCenterIfOutsideViewport(z.revealRange,z.revealScrollType))}getSession(z){return this._session}addSelectionToNextFindMatch(z){if(this._editor.hasModel()){if(!this._session){const U=this._editor.getSelections();if(U.length>1){const Y=z.getState().matchCase;if(!x(this._editor.getModel(),U,Y)){const K=this._editor.getModel(),R=[];for(let J=0,ie=U.length;J0&&j.isRegex){const Y=this._editor.getModel();j.searchScope?U=Y.findMatches(j.searchString,j.searchScope,j.isRegex,j.matchCase,j.wholeWord?this._editor.getOption(132):null,!1,1073741824):U=Y.findMatches(j.searchString,!0,j.isRegex,j.matchCase,j.wholeWord?this._editor.getOption(132):null,!1,1073741824)}else{if(this._beginSessionIfNeeded(z),!this._session)return;U=this._session.selectAll(j.searchScope)}if(U.length>0){const Y=this._editor.getSelection();for(let G=0,K=U.length;Gnew b.Selection(G.range.startLineNumber,G.range.startColumn,G.range.endLineNumber,G.range.endColumn)))}}}e.MultiCursorSelectionController=S;class L extends y.EditorAction{run(z,U){const j=S.get(U);if(!j)return;const Y=U._getViewModel();if(Y){const G=Y.getCursorStates(),K=n.CommonFindController.get(U);if(K)this._run(j,K);else{const R=z.get(c.IInstantiationService).createInstance(n.CommonFindController,U);this._run(j,R),R.dispose()}a(G,Y.getCursorStates())}}}e.MultiCursorSelectionControllerAction=L;class D extends L{constructor(){super({id:"editor.action.addSelectionToNextFindMatch",label:o.localize(1159,"Add Selection To Next Find Match"),alias:"Add Selection To Next Find Match",precondition:void 0,kbOpts:{kbExpr:p.EditorContextKeys.focus,primary:2082,weight:100},menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"3_multi",title:o.localize(1160,"Add &&Next Occurrence"),order:5}})}_run(z,U){z.addSelectionToNextFindMatch(U)}}e.AddSelectionToNextFindMatchAction=D;class T extends L{constructor(){super({id:"editor.action.addSelectionToPreviousFindMatch",label:o.localize(1161,"Add Selection To Previous Find Match"),alias:"Add Selection To Previous Find Match",precondition:void 0,menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"3_multi",title:o.localize(1162,"Add P&&revious Occurrence"),order:6}})}_run(z,U){z.addSelectionToPreviousFindMatch(U)}}e.AddSelectionToPreviousFindMatchAction=T;class M extends L{constructor(){super({id:"editor.action.moveSelectionToNextFindMatch",label:o.localize(1163,"Move Last Selection To Next Find Match"),alias:"Move Last Selection To Next Find Match",precondition:void 0,kbOpts:{kbExpr:p.EditorContextKeys.focus,primary:(0,I.KeyChord)(2089,2082),weight:100}})}_run(z,U){z.moveSelectionToNextFindMatch(U)}}e.MoveSelectionToNextFindMatchAction=M;class A extends L{constructor(){super({id:"editor.action.moveSelectionToPreviousFindMatch",label:o.localize(1164,"Move Last Selection To Previous Find Match"),alias:"Move Last Selection To Previous Find Match",precondition:void 0})}_run(z,U){z.moveSelectionToPreviousFindMatch(U)}}e.MoveSelectionToPreviousFindMatchAction=A;class P extends L{constructor(){super({id:"editor.action.selectHighlights",label:o.localize(1165,"Select All Occurrences of Find Match"),alias:"Select All Occurrences of Find Match",precondition:void 0,kbOpts:{kbExpr:p.EditorContextKeys.focus,primary:3114,weight:100},menuOpts:{menuId:t.MenuId.MenubarSelectionMenu,group:"3_multi",title:o.localize(1166,"Select All &&Occurrences"),order:7}})}_run(z,U){z.selectAll(U)}}e.SelectHighlightsAction=P;class N extends L{constructor(){super({id:"editor.action.changeAll",label:o.localize(1167,"Change All Occurrences"),alias:"Change All Occurrences",precondition:i.ContextKeyExpr.and(p.EditorContextKeys.writable,p.EditorContextKeys.editorTextFocus),kbOpts:{kbExpr:p.EditorContextKeys.editorTextFocus,primary:2108,weight:100},contextMenuOpts:{group:"1_modification",order:1.2}})}_run(z,U){z.selectAll(U)}}e.CompatChangeAll=N;class O{constructor(z,U,j,Y,G){this._model=z,this._searchText=U,this._matchCase=j,this._wordSeparators=Y,this._modelVersionId=this._model.getVersionId(),this._cachedFindMatches=null,G&&this._model===G._model&&this._searchText===G._searchText&&this._matchCase===G._matchCase&&this._wordSeparators===G._wordSeparators&&this._modelVersionId===G._modelVersionId&&(this._cachedFindMatches=G._cachedFindMatches)}findMatches(){return this._cachedFindMatches===null&&(this._cachedFindMatches=this._model.findMatches(this._searchText,!0,!1,this._matchCase,this._wordSeparators,!1).map(z=>z.range),this._cachedFindMatches.sort(_.Range.compareRangesUsingStarts)),this._cachedFindMatches}}let F=class extends E.Disposable{static{l=this}static{this.ID="editor.contrib.selectionHighlighter"}constructor(z,U){super(),this._languageFeaturesService=U,this.editor=z,this._isEnabled=z.getOption(109),this._decorations=z.createDecorationsCollection(),this.updateSoon=this._register(new k.RunOnceScheduler(()=>this._update(),300)),this.state=null,this._register(z.onDidChangeConfiguration(Y=>{this._isEnabled=z.getOption(109)})),this._register(z.onDidChangeCursorSelection(Y=>{this._isEnabled&&(Y.selection.isEmpty()?Y.reason===3?(this.state&&this._setState(null),this.updateSoon.schedule()):this._setState(null):this._update())})),this._register(z.onDidChangeModel(Y=>{this._setState(null)})),this._register(z.onDidChangeModelContent(Y=>{this._isEnabled&&this.updateSoon.schedule()}));const j=n.CommonFindController.get(z);j&&this._register(j.getState().onFindReplaceStateChange(Y=>{this._update()})),this.updateSoon.schedule()}_update(){this._setState(l._createState(this.state,this._isEnabled,this.editor))}static _createState(z,U,j){if(!U||!j.hasModel())return null;const Y=j.getSelection();if(Y.startLineNumber!==Y.endLineNumber)return null;const G=S.get(j);if(!G)return null;const K=n.CommonFindController.get(j);if(!K)return null;let R=G.getSession(K);if(!R){const ue=j.getSelections();if(ue.length>1){const pe=K.getState().matchCase;if(!x(j.getModel(),ue,pe))return null}R=w.create(j,K)}if(!R||R.currentMatch||/^[ \t]+$/.test(R.searchText)||R.searchText.length>200)return null;const J=K.getState(),ie=J.matchCase;if(J.isRevealed){let ue=J.searchString;ie||(ue=ue.toLowerCase());let he=R.searchText;if(ie||(he=he.toLowerCase()),ue===he&&R.matchCase===J.matchCase&&R.wholeWord===J.wholeWord&&!J.isRegex)return null}return new O(j.getModel(),R.searchText,R.matchCase,R.wholeWord?j.getOption(132):null,z)}_setState(z){if(this.state=z,!this.state){this._decorations.clear();return}if(!this.editor.hasModel())return;const U=this.editor.getModel();if(U.isTooLargeForTokenization())return;const j=this.state.findMatches(),Y=this.editor.getSelections();Y.sort(_.Range.compareRangesUsingStarts);const G=[];for(let ie=0,ue=0,he=j.length,pe=Y.length;ie=pe)G.push(ae),ie++;else{const ee=_.Range.compareRangesUsingStarts(ae,Y[ue]);ee<0?((Y[ue].isEmpty()||!_.Range.areIntersecting(ae,Y[ue]))&&G.push(ae),ie++):(ee>0||ie++,ue++)}}const K=this.editor.getOption(81)!=="off",R=this._languageFeaturesService.documentHighlightProvider.has(U)&&K,J=G.map(ie=>({range:ie,options:(0,g.getSelectionHighlightDecorationOptions)(R)}));this._decorations.set(J)}dispose(){this._setState(null),super.dispose()}};e.SelectionHighlighter=F,e.SelectionHighlighter=F=l=ke([ce(1,s.ILanguageFeaturesService)],F);function x(H,z,U){const j=W(H,z[0],!U);for(let Y=1,G=z.length;Y()=>Promise.resolve(j.provideDocumentHighlights(q,H,z)).then(void 0,y.onUnexpectedExternalError)),j=>j!=null).then(j=>{if(j){const Y=new l.ResourceMap;return Y.set(q.uri,j),Y}return new l.ResourceMap})}function S(V,q,H,z,U,j){const Y=V.ordered(q);return(0,I.first)(Y.map(G=>()=>{const K=j.filter(R=>(0,t.shouldSynchronizeModel)(R)).filter(R=>(0,a.score)(G.selector,R.uri,R.getLanguageId(),!0,void 0,void 0)>0);return Promise.resolve(G.provideMultiDocumentHighlights(q,H,K,U)).then(void 0,y.onUnexpectedExternalError)}),G=>G!=null)}class L{constructor(q,H,z){this._model=q,this._selection=H,this._wordSeparators=z,this._wordRange=this._getCurrentWordRange(q,H),this._result=null}get result(){return this._result||(this._result=(0,I.createCancelablePromise)(q=>this._compute(this._model,this._selection,this._wordSeparators,q))),this._result}_getCurrentWordRange(q,H){const z=q.getWordAtPosition(H.getPosition());return z?new n.Range(H.startLineNumber,z.startColumn,H.startLineNumber,z.endColumn):null}isValid(q,H,z){const U=H.startLineNumber,j=H.startColumn,Y=H.endColumn,G=this._getCurrentWordRange(q,H);let K=!!(this._wordRange&&this._wordRange.equalsRange(G));for(let R=0,J=z.length;!K&&R=Y&&(K=!0)}return K}cancel(){this.result.cancel()}}class D extends L{constructor(q,H,z,U){super(q,H,z),this._providers=U}_compute(q,H,z,U){return w(this._providers,q,H.getPosition(),U).then(j=>j||new l.ResourceMap)}}class T extends L{constructor(q,H,z,U,j){super(q,H,z),this._providers=U,this._otherModels=j}_compute(q,H,z,U){return S(this._providers,q,H.getPosition(),z,U,this._otherModels).then(j=>j||new l.ResourceMap)}}function M(V,q,H,z,U){return new D(q,H,U,V)}function A(V,q,H,z,U,j){return new T(q,H,U,V,j)}(0,b.registerModelAndPositionCommand)("_executeDocumentHighlights",async(V,q,H)=>{const z=V.get(i.ILanguageFeaturesService);return(await w(z.documentHighlightProvider,q,H,E.CancellationToken.None))?.get(q.uri)});let P=class{static{f=this}static{this.storedDecorationIDs=new l.ResourceMap}static{this.query=null}constructor(q,H,z,U,j){this.toUnhook=new m.DisposableStore,this.workerRequestTokenId=0,this.workerRequestCompleted=!1,this.workerRequestValue=new l.ResourceMap,this.lastCursorPositionChangeTime=0,this.renderDecorationsTimer=-1,this.runDelayer=this.toUnhook.add(new I.Delayer(50)),this.editor=q,this.providers=H,this.multiDocumentProviders=z,this.codeEditorService=j,this._hasWordHighlights=v.bindTo(U),this._ignorePositionChangeEvent=!1,this.occurrencesHighlight=this.editor.getOption(81),this.model=this.editor.getModel(),this.toUnhook.add(q.onDidChangeCursorPosition(Y=>{this._ignorePositionChangeEvent||this.occurrencesHighlight!=="off"&&this.runDelayer.trigger(()=>{this._onPositionChanged(Y)})})),this.toUnhook.add(q.onDidFocusEditorText(Y=>{this.occurrencesHighlight!=="off"&&(this.workerRequest||this.runDelayer.trigger(()=>{this._run()}))})),this.toUnhook.add(q.onDidChangeModelContent(Y=>{(0,c.matchesScheme)(this.model.uri,"output")||this._stopAll()})),this.toUnhook.add(q.onDidChangeModel(Y=>{!Y.newModelUrl&&Y.oldModelUrl?this._stopSingular():f.query&&this._run()})),this.toUnhook.add(q.onDidChangeConfiguration(Y=>{const G=this.editor.getOption(81);if(this.occurrencesHighlight!==G)switch(this.occurrencesHighlight=G,G){case"off":this._stopAll();break;case"singleFile":this._stopAll(f.query?.modelInfo?.model);break;case"multiFile":f.query&&this._run(!0);break;default:console.warn("Unknown occurrencesHighlight setting value:",G);break}})),this.decorations=this.editor.createDecorationsCollection(),this.workerRequestTokenId=0,this.workerRequest=null,this.workerRequestCompleted=!1,this.lastCursorPositionChangeTime=0,this.renderDecorationsTimer=-1,f.query&&this._run()}hasDecorations(){return this.decorations.length>0}restore(){this.occurrencesHighlight!=="off"&&(this.runDelayer.cancel(),this._run())}_getSortedHighlights(){return this.decorations.getRanges().sort(n.Range.compareRangesUsingStarts)}moveNext(){const q=this._getSortedHighlights(),z=(q.findIndex(j=>j.containsPosition(this.editor.getPosition()))+1)%q.length,U=q[z];try{this._ignorePositionChangeEvent=!0,this.editor.setPosition(U.getStartPosition()),this.editor.revealRangeInCenterIfOutsideViewport(U);const j=this._getWord();if(j){const Y=this.editor.getModel().getLineContent(U.startLineNumber);(0,k.alert)(`${Y}, ${z+1} of ${q.length} for '${j.word}'`)}}finally{this._ignorePositionChangeEvent=!1}}moveBack(){const q=this._getSortedHighlights(),z=(q.findIndex(j=>j.containsPosition(this.editor.getPosition()))-1+q.length)%q.length,U=q[z];try{this._ignorePositionChangeEvent=!0,this.editor.setPosition(U.getStartPosition()),this.editor.revealRangeInCenterIfOutsideViewport(U);const j=this._getWord();if(j){const Y=this.editor.getModel().getLineContent(U.startLineNumber);(0,k.alert)(`${Y}, ${z+1} of ${q.length} for '${j.word}'`)}}finally{this._ignorePositionChangeEvent=!1}}_removeSingleDecorations(){if(!this.editor.hasModel())return;const q=f.storedDecorationIDs.get(this.editor.getModel().uri);q&&(this.editor.removeDecorations(q),f.storedDecorationIDs.delete(this.editor.getModel().uri),this.decorations.length>0&&(this.decorations.clear(),this._hasWordHighlights.set(!1)))}_removeAllDecorations(q){const H=this.codeEditorService.listCodeEditors(),z=[];for(const U of H){if(!U.hasModel()||(0,r.isEqual)(U.getModel().uri,q?.uri))continue;const j=f.storedDecorationIDs.get(U.getModel().uri);if(!j)continue;U.removeDecorations(j),z.push(U.getModel().uri);const Y=N.get(U);Y?.wordHighlighter&&Y.wordHighlighter.decorations.length>0&&(Y.wordHighlighter.decorations.clear(),Y.wordHighlighter.workerRequest=null,Y.wordHighlighter._hasWordHighlights.set(!1))}for(const U of z)f.storedDecorationIDs.delete(U)}_stopSingular(){this._removeSingleDecorations(),this.editor.hasTextFocus()&&(this.editor.getModel()?.uri.scheme!==c.Schemas.vscodeNotebookCell&&f.query?.modelInfo?.model.uri.scheme!==c.Schemas.vscodeNotebookCell?(f.query=null,this._run()):f.query?.modelInfo&&(f.query.modelInfo=null)),this.renderDecorationsTimer!==-1&&(clearTimeout(this.renderDecorationsTimer),this.renderDecorationsTimer=-1),this.workerRequest!==null&&(this.workerRequest.cancel(),this.workerRequest=null),this.workerRequestCompleted||(this.workerRequestTokenId++,this.workerRequestCompleted=!0)}_stopAll(q){this._removeAllDecorations(q),this.renderDecorationsTimer!==-1&&(clearTimeout(this.renderDecorationsTimer),this.renderDecorationsTimer=-1),this.workerRequest!==null&&(this.workerRequest.cancel(),this.workerRequest=null),this.workerRequestCompleted||(this.workerRequestTokenId++,this.workerRequestCompleted=!0)}_onPositionChanged(q){if(this.occurrencesHighlight==="off"){this._stopAll();return}if(q.reason!==3&&this.editor.getModel()?.uri.scheme!==c.Schemas.vscodeNotebookCell){this._stopAll();return}this._run()}_getWord(){const q=this.editor.getSelection(),H=q.startLineNumber,z=q.startColumn;return this.model.isDisposed()?null:this.model.getWordAtPosition({lineNumber:H,column:z})}getOtherModelsToHighlight(q){if(!q)return[];if(q.uri.scheme===c.Schemas.vscodeNotebookCell){const j=[],Y=this.codeEditorService.listCodeEditors();for(const G of Y){const K=G.getModel();K&&K!==q&&K.uri.scheme===c.Schemas.vscodeNotebookCell&&j.push(K)}return j}const z=[],U=this.codeEditorService.listCodeEditors();for(const j of U){if(!(0,_.isDiffEditor)(j))continue;const Y=j.getModel();Y&&q===Y.modified&&z.push(Y.modified)}if(z.length)return z;if(this.occurrencesHighlight==="singleFile")return[];for(const j of U){const Y=j.getModel();Y&&Y!==q&&z.push(Y)}return z}_run(q){let H;if(this.editor.hasTextFocus()){const U=this.editor.getSelection();if(!U||U.startLineNumber!==U.endLineNumber){f.query=null,this._stopAll();return}const j=U.startColumn,Y=U.endColumn,G=this._getWord();if(!G||G.startColumn>j||G.endColumn{U===this.workerRequestTokenId&&(this.workerRequestCompleted=!0,this.workerRequestValue=Y||[],this._beginRenderDecorations())},y.onUnexpectedError)}}computeWithModel(q,H,z,U){return U.length?A(this.multiDocumentProviders,q,H,z,this.editor.getOption(132),U):M(this.providers,q,H,z,this.editor.getOption(132))}_beginRenderDecorations(){const q=new Date().getTime(),H=this.lastCursorPositionChangeTime+250;q>=H?(this.renderDecorationsTimer=-1,this.renderDecorations()):this.renderDecorationsTimer=setTimeout(()=>{this.renderDecorations()},H-q)}renderDecorations(){this.renderDecorationsTimer=-1;const q=this.codeEditorService.listCodeEditors();for(const H of q){const z=N.get(H);if(!z)continue;const U=[],j=H.getModel()?.uri;if(j&&this.workerRequestValue.has(j)){const Y=f.storedDecorationIDs.get(j),G=this.workerRequestValue.get(j);if(G)for(const R of G)R.range&&U.push({range:R.range,options:(0,s.getHighlightDecorationOptions)(R.kind)});let K=[];H.changeDecorations(R=>{K=R.deltaDecorations(Y??[],U)}),f.storedDecorationIDs=f.storedDecorationIDs.set(j,K),U.length>0&&(z.wordHighlighter?.decorations.set(U),z.wordHighlighter?._hasWordHighlights.set(!0))}}}dispose(){this._stopSingular(),this.toUnhook.dispose()}};P=f=ke([ce(4,p.ICodeEditorService)],P);let N=class extends m.Disposable{static{h=this}static{this.ID="editor.contrib.wordHighlighter"}static get(q){return q.getContribution(h.ID)}constructor(q,H,z,U){super(),this._wordHighlighter=null;const j=()=>{q.hasModel()&&!q.getModel().isTooLargeForTokenization()&&(this._wordHighlighter=new P(q,z.documentHighlightProvider,z.multiDocumentHighlightProvider,H,U))};this._register(q.onDidChangeModel(Y=>{this._wordHighlighter&&(this._wordHighlighter.dispose(),this._wordHighlighter=null),j()})),j()}get wordHighlighter(){return this._wordHighlighter}saveViewState(){return!!(this._wordHighlighter&&this._wordHighlighter.hasDecorations())}moveNext(){this._wordHighlighter?.moveNext()}moveBack(){this._wordHighlighter?.moveBack()}restoreViewState(q){this._wordHighlighter&&q&&this._wordHighlighter.restore()}dispose(){this._wordHighlighter&&(this._wordHighlighter.dispose(),this._wordHighlighter=null),super.dispose()}};e.WordHighlighterContribution=N,e.WordHighlighterContribution=N=h=ke([ce(1,g.IContextKeyService),ce(2,i.ILanguageFeaturesService),ce(3,p.ICodeEditorService)],N);class O extends b.EditorAction{constructor(q,H){super(H),this._isNext=q}run(q,H){const z=N.get(H);z&&(this._isNext?z.moveNext():z.moveBack())}}class F extends O{constructor(){super(!0,{id:"editor.action.wordHighlight.next",label:d.localize(1424,"Go to Next Symbol Highlight"),alias:"Go to Next Symbol Highlight",precondition:v,kbOpts:{kbExpr:o.EditorContextKeys.editorTextFocus,primary:65,weight:100}})}}class x extends O{constructor(){super(!1,{id:"editor.action.wordHighlight.prev",label:d.localize(1425,"Go to Previous Symbol Highlight"),alias:"Go to Previous Symbol Highlight",precondition:v,kbOpts:{kbExpr:o.EditorContextKeys.editorTextFocus,primary:1089,weight:100}})}}class W extends b.EditorAction{constructor(){super({id:"editor.action.wordHighlight.trigger",label:d.localize(1426,"Trigger Symbol Highlight"),alias:"Trigger Symbol Highlight",precondition:void 0,kbOpts:{kbExpr:o.EditorContextKeys.editorTextFocus,primary:0,weight:100}})}run(q,H,z){const U=N.get(H);U&&U.restoreViewState(!0)}}(0,b.registerEditorContribution)(N.ID,N,0),(0,b.registerEditorAction)(F),(0,b.registerEditorAction)(x),(0,b.registerEditorAction)(W),(0,C.registerEditorFeature)(u.TextualMultiDocumentHighlightFeature)}),define(ne[842],se([1,0,5,173,33,187,2,60,4,35,537]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ZoneWidget=e.OverlayWidgetDelegate=void 0;const p=new I.Color(new I.RGBA(0,122,204)),n={showArrow:!0,showFrame:!0,className:"",frameColor:p,arrowColor:p,keepEditorSelection:!1},o="vs.editor.contrib.zoneWidget";class t{constructor(l,a,r,u,C,f,h,v){this.id="",this.domNode=l,this.afterLineNumber=a,this.afterColumn=r,this.heightInLines=u,this.showInHiddenAreas=h,this.ordinal=v,this._onDomNodeTop=C,this._onComputedHeight=f}onDomNodeTop(l){this._onDomNodeTop(l)}onComputedHeight(l){this._onComputedHeight(l)}}class i{constructor(l,a){this._id=l,this._domNode=a}getId(){return this._id}getDomNode(){return this._domNode}getPosition(){return null}}e.OverlayWidgetDelegate=i;class s{static{this._IdGenerator=new E.IdGenerator(".arrow-decoration-")}constructor(l){this._editor=l,this._ruleName=s._IdGenerator.nextId(),this._decorations=this._editor.createDecorationsCollection(),this._color=null,this._height=-1}dispose(){this.hide(),d.removeCSSRulesContainingSelector(this._ruleName)}set color(l){this._color!==l&&(this._color=l,this._updateStyle())}set height(l){this._height!==l&&(this._height=l,this._updateStyle())}_updateStyle(){d.removeCSSRulesContainingSelector(this._ruleName),d.createCSSRule(`.monaco-editor ${this._ruleName}`,`border-style: solid; border-color: transparent; border-bottom-color: ${this._color}; border-width: ${this._height}px; bottom: -${this._height}px !important; margin-left: -${this._height}px; `)}show(l){l.column===1&&(l={lineNumber:l.lineNumber,column:2}),this._decorations.set([{range:_.Range.fromPositions(l),options:{description:"zone-widget-arrow",className:this._ruleName,stickiness:1}}])}hide(){this._decorations.clear()}}class g{constructor(l,a={}){this._arrow=null,this._overlayWidget=null,this._resizeSash=null,this._viewZone=null,this._disposables=new y.DisposableStore,this.container=null,this._isShowing=!1,this.editor=l,this._positionMarkerId=this.editor.createDecorationsCollection(),this.options=m.deepClone(a),m.mixin(this.options,n,!1),this.domNode=document.createElement("div"),this.options.isAccessible||(this.domNode.setAttribute("aria-hidden","true"),this.domNode.setAttribute("role","presentation")),this._disposables.add(this.editor.onDidLayoutChange(r=>{const u=this._getWidth(r);this.domNode.style.width=u+"px",this.domNode.style.left=this._getLeft(r)+"px",this._onWidth(u)}))}dispose(){this._overlayWidget&&(this.editor.removeOverlayWidget(this._overlayWidget),this._overlayWidget=null),this._viewZone&&this.editor.changeViewZones(l=>{this._viewZone&&l.removeZone(this._viewZone.id),this._viewZone=null}),this._positionMarkerId.clear(),this._disposables.dispose()}create(){this.domNode.classList.add("zone-widget"),this.options.className&&this.domNode.classList.add(this.options.className),this.container=document.createElement("div"),this.container.classList.add("zone-widget-container"),this.domNode.appendChild(this.container),this.options.showArrow&&(this._arrow=new s(this.editor),this._disposables.add(this._arrow)),this._fillContainer(this.container),this._initSash(),this._applyStyles()}style(l){l.frameColor&&(this.options.frameColor=l.frameColor),l.arrowColor&&(this.options.arrowColor=l.arrowColor),this._applyStyles()}_applyStyles(){if(this.container&&this.options.frameColor){const l=this.options.frameColor.toString();this.container.style.borderTopColor=l,this.container.style.borderBottomColor=l}if(this._arrow&&this.options.arrowColor){const l=this.options.arrowColor.toString();this._arrow.color=l}}_getWidth(l){return l.width-l.minimap.minimapWidth-l.verticalScrollbarWidth}_getLeft(l){return l.minimap.minimapWidth>0&&l.minimap.minimapLeft===0?l.minimap.minimapWidth:0}_onViewZoneTop(l){this.domNode.style.top=l+"px"}_onViewZoneHeight(l){if(this.domNode.style.height=`${l}px`,this.container){const a=l-this._decoratingElementsHeight();this.container.style.height=`${a}px`;const r=this.editor.getLayoutInfo();this._doLayout(a,this._getWidth(r))}this._resizeSash?.layout()}get position(){const l=this._positionMarkerId.getRange(0);if(l)return l.getStartPosition()}show(l,a){const r=_.Range.isIRange(l)?_.Range.lift(l):_.Range.fromPositions(l);this._isShowing=!0,this._showImpl(r,a),this._isShowing=!1,this._positionMarkerId.set([{range:r,options:b.ModelDecorationOptions.EMPTY}])}hide(){this._viewZone&&(this.editor.changeViewZones(l=>{this._viewZone&&l.removeZone(this._viewZone.id)}),this._viewZone=null),this._overlayWidget&&(this.editor.removeOverlayWidget(this._overlayWidget),this._overlayWidget=null),this._arrow?.hide(),this._positionMarkerId.clear()}_decoratingElementsHeight(){const l=this.editor.getOption(67);let a=0;if(this.options.showArrow){const r=Math.round(l/3);a+=2*r}if(this.options.showFrame){const r=Math.round(l/9);a+=2*r}return a}_showImpl(l,a){const r=l.getStartPosition(),u=this.editor.getLayoutInfo(),C=this._getWidth(u);this.domNode.style.width=`${C}px`,this.domNode.style.left=this._getLeft(u)+"px";const f=document.createElement("div");f.style.overflow="hidden";const h=this.editor.getOption(67);if(!this.options.allowUnlimitedHeight){const D=Math.max(12,this.editor.getLayoutInfo().height/h*.8);a=Math.min(a,D)}let v=0,w=0;if(this._arrow&&this.options.showArrow&&(v=Math.round(h/3),this._arrow.height=v,this._arrow.show(r)),this.options.showFrame&&(w=Math.round(h/9)),this.editor.changeViewZones(D=>{this._viewZone&&D.removeZone(this._viewZone.id),this._overlayWidget&&(this.editor.removeOverlayWidget(this._overlayWidget),this._overlayWidget=null),this.domNode.style.top="-1000px",this._viewZone=new t(f,r.lineNumber,r.column,a,T=>this._onViewZoneTop(T),T=>this._onViewZoneHeight(T),this.options.showInHiddenAreas,this.options.ordinal),this._viewZone.id=D.addZone(this._viewZone),this._overlayWidget=new i(o+this._viewZone.id,this.domNode),this.editor.addOverlayWidget(this._overlayWidget)}),this.container&&this.options.showFrame){const D=this.options.frameWidth?this.options.frameWidth:w;this.container.style.borderTopWidth=D+"px",this.container.style.borderBottomWidth=D+"px"}const S=a*h-this._decoratingElementsHeight();this.container&&(this.container.style.top=v+"px",this.container.style.height=S+"px",this.container.style.overflow="hidden"),this._doLayout(S,C),this.options.keepEditorSelection||this.editor.setSelection(l);const L=this.editor.getModel();if(L){const D=L.validateRange(new _.Range(l.startLineNumber,1,l.endLineNumber+1,1));this.revealRange(D,D.startLineNumber===L.getLineCount())}}revealRange(l,a){a?this.editor.revealLineNearTop(l.endLineNumber,0):this.editor.revealRange(l,0)}setCssClass(l,a){this.container&&(a&&this.container.classList.remove(a),this.container.classList.add(l))}_onWidth(l){}_doLayout(l,a){}_relayout(l){this._viewZone&&this._viewZone.heightInLines!==l&&this.editor.changeViewZones(a=>{this._viewZone&&(this._viewZone.heightInLines=l,a.layoutZone(this._viewZone.id))})}_initSash(){if(this._resizeSash)return;this._resizeSash=this._disposables.add(new k.Sash(this.domNode,this,{orientation:1})),this.options.isResizeable||(this._resizeSash.state=0);let l;this._disposables.add(this._resizeSash.onDidStart(a=>{this._viewZone&&(l={startY:a.startY,heightInLines:this._viewZone.heightInLines})})),this._disposables.add(this._resizeSash.onDidEnd(()=>{l=void 0})),this._disposables.add(this._resizeSash.onDidChange(a=>{if(l){const r=(a.currentY-l.startY)/this.editor.getOption(67),u=r<0?Math.ceil(r):Math.floor(r),C=l.heightInLines+u;C>5&&C<35&&this._relayout(C)}}))}getHorizontalSashLeft(){return 0}getHorizontalSashTop(){return(this.domNode.style.height===null?0:parseInt(this.domNode.style.height))-this._decoratingElementsHeight()/2}getHorizontalSashWidth(){const l=this.editor.getLayoutInfo();return l.width-l.minimap.minimapWidth}}e.ZoneWidget=g}),define(ne[158],se([1,0,5,87,41,26,30,33,6,60,15,34,125,842,3,124,12,49,7,32,527]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.peekViewEditorMatchHighlightBorder=e.peekViewEditorMatchHighlight=e.peekViewResultsMatchHighlight=e.peekViewEditorStickyScrollBackground=e.peekViewEditorGutterBackground=e.peekViewEditorBackground=e.peekViewResultsSelectionForeground=e.peekViewResultsSelectionBackground=e.peekViewResultsFileForeground=e.peekViewResultsMatchForeground=e.peekViewResultsBackground=e.peekViewBorder=e.peekViewTitleInfoForeground=e.peekViewTitleForeground=e.peekViewTitleBackground=e.PeekViewWidget=e.PeekContext=e.IPeekViewService=void 0,e.getOuterEditor=C,e.IPeekViewService=(0,l.createDecorator)("IPeekViewService"),(0,c.registerSingleton)(e.IPeekViewService,class{constructor(){this._widgets=new Map}addExclusiveWidget(v,w){const S=this._widgets.get(v);S&&(S.listener.dispose(),S.widget.dispose());const L=()=>{const D=this._widgets.get(v);D&&D.widget===w&&(D.listener.dispose(),this._widgets.delete(v))};this._widgets.set(v,{widget:w,listener:w.onDidClose(L)})}},1);var r;(function(v){v.inPeekEditor=new g.RawContextKey("inReferenceSearchEditor",!0,i.localize(1177,"Whether the current code editor is embedded inside peek")),v.notInPeekEditor=v.inPeekEditor.toNegated()})(r||(e.PeekContext=r={}));let u=class{static{this.ID="editor.contrib.referenceController"}constructor(w,S){w instanceof o.EmbeddedCodeEditorWidget&&r.inPeekEditor.bindTo(S)}dispose(){}};u=ke([ce(1,g.IContextKeyService)],u),(0,p.registerEditorContribution)(u.ID,u,0);function C(v){const w=v.get(n.ICodeEditorService).getFocusedCodeEditor();return w instanceof o.EmbeddedCodeEditorWidget?w.getParentEditor():w}const f={headerBackgroundColor:m.Color.white,primaryHeadingColor:m.Color.fromHex("#333333"),secondaryHeadingColor:m.Color.fromHex("#6c6c6cb3")};let h=class extends t.ZoneWidget{constructor(w,S,L){super(w,S),this.instantiationService=L,this._onDidClose=new _.Emitter,this.onDidClose=this._onDidClose.event,b.mixin(this.options,f,!1)}dispose(){this.disposed||(this.disposed=!0,super.dispose(),this._onDidClose.fire(this))}style(w){const S=this.options;w.headerBackgroundColor&&(S.headerBackgroundColor=w.headerBackgroundColor),w.primaryHeadingColor&&(S.primaryHeadingColor=w.primaryHeadingColor),w.secondaryHeadingColor&&(S.secondaryHeadingColor=w.secondaryHeadingColor),super.style(w)}_applyStyles(){super._applyStyles();const w=this.options;this._headElement&&w.headerBackgroundColor&&(this._headElement.style.backgroundColor=w.headerBackgroundColor.toString()),this._primaryHeading&&w.primaryHeadingColor&&(this._primaryHeading.style.color=w.primaryHeadingColor.toString()),this._secondaryHeading&&w.secondaryHeadingColor&&(this._secondaryHeading.style.color=w.secondaryHeadingColor.toString()),this._bodyElement&&w.frameColor&&(this._bodyElement.style.borderColor=w.frameColor.toString())}_fillContainer(w){this.setCssClass("peekview-widget"),this._headElement=d.$(".head"),this._bodyElement=d.$(".body"),this._fillHead(this._headElement),this._fillBody(this._bodyElement),w.appendChild(this._headElement),w.appendChild(this._bodyElement)}_fillHead(w,S){this._titleElement=d.$(".peekview-title"),this.options.supportOnTitleClick&&(this._titleElement.classList.add("clickable"),d.addStandardDisposableListener(this._titleElement,"click",T=>this._onTitleClick(T))),d.append(this._headElement,this._titleElement),this._fillTitleIcon(this._titleElement),this._primaryHeading=d.$("span.filename"),this._secondaryHeading=d.$("span.dirname"),this._metaHeading=d.$("span.meta"),d.append(this._titleElement,this._primaryHeading,this._secondaryHeading,this._metaHeading);const L=d.$(".peekview-actions");d.append(this._headElement,L);const D=this._getActionBarOptions();this._actionbarWidget=new k.ActionBar(L,D),this._disposables.add(this._actionbarWidget),S||this._actionbarWidget.push(new I.Action("peekview.close",i.localize(1178,"Close"),y.ThemeIcon.asClassName(E.Codicon.close),!0,()=>(this.dispose(),Promise.resolve())),{label:!1,icon:!0})}_fillTitleIcon(w){}_getActionBarOptions(){return{actionViewItemProvider:s.createActionViewItem.bind(void 0,this.instantiationService),orientation:0}}_onTitleClick(w){}setTitle(w,S){this._primaryHeading&&this._secondaryHeading&&(this._primaryHeading.innerText=w,this._primaryHeading.setAttribute("title",w),S?this._secondaryHeading.innerText=S:d.clearNode(this._secondaryHeading))}setMetaTitle(w){this._metaHeading&&(w?(this._metaHeading.innerText=w,d.show(this._metaHeading)):d.hide(this._metaHeading))}_doLayout(w,S){if(!this._isShowing&&w<0){this.dispose();return}const L=Math.ceil(this.editor.getOption(67)*1.2),D=Math.round(w-(L+2));this._doLayoutHead(L,S),this._doLayoutBody(D,S)}_doLayoutHead(w,S){this._headElement&&(this._headElement.style.height=`${w}px`,this._headElement.style.lineHeight=this._headElement.style.height)}_doLayoutBody(w,S){this._bodyElement&&(this._bodyElement.style.height=`${w}px`)}};e.PeekViewWidget=h,e.PeekViewWidget=h=ke([ce(2,l.IInstantiationService)],h),e.peekViewTitleBackground=(0,a.registerColor)("peekViewTitle.background",{dark:"#252526",light:"#F3F3F3",hcDark:m.Color.black,hcLight:m.Color.white},i.localize(1179,"Background color of the peek view title area.")),e.peekViewTitleForeground=(0,a.registerColor)("peekViewTitleLabel.foreground",{dark:m.Color.white,light:m.Color.black,hcDark:m.Color.white,hcLight:a.editorForeground},i.localize(1180,"Color of the peek view title.")),e.peekViewTitleInfoForeground=(0,a.registerColor)("peekViewTitleDescription.foreground",{dark:"#ccccccb3",light:"#616161",hcDark:"#FFFFFF99",hcLight:"#292929"},i.localize(1181,"Color of the peek view title info.")),e.peekViewBorder=(0,a.registerColor)("peekView.border",{dark:a.editorInfoForeground,light:a.editorInfoForeground,hcDark:a.contrastBorder,hcLight:a.contrastBorder},i.localize(1182,"Color of the peek view borders and arrow.")),e.peekViewResultsBackground=(0,a.registerColor)("peekViewResult.background",{dark:"#252526",light:"#F3F3F3",hcDark:m.Color.black,hcLight:m.Color.white},i.localize(1183,"Background color of the peek view result list.")),e.peekViewResultsMatchForeground=(0,a.registerColor)("peekViewResult.lineForeground",{dark:"#bbbbbb",light:"#646465",hcDark:m.Color.white,hcLight:a.editorForeground},i.localize(1184,"Foreground color for line nodes in the peek view result list.")),e.peekViewResultsFileForeground=(0,a.registerColor)("peekViewResult.fileForeground",{dark:m.Color.white,light:"#1E1E1E",hcDark:m.Color.white,hcLight:a.editorForeground},i.localize(1185,"Foreground color for file nodes in the peek view result list.")),e.peekViewResultsSelectionBackground=(0,a.registerColor)("peekViewResult.selectionBackground",{dark:"#3399ff33",light:"#3399ff33",hcDark:null,hcLight:null},i.localize(1186,"Background color of the selected entry in the peek view result list.")),e.peekViewResultsSelectionForeground=(0,a.registerColor)("peekViewResult.selectionForeground",{dark:m.Color.white,light:"#6C6C6C",hcDark:m.Color.white,hcLight:a.editorForeground},i.localize(1187,"Foreground color of the selected entry in the peek view result list.")),e.peekViewEditorBackground=(0,a.registerColor)("peekViewEditor.background",{dark:"#001F33",light:"#F2F8FC",hcDark:m.Color.black,hcLight:m.Color.white},i.localize(1188,"Background color of the peek view editor.")),e.peekViewEditorGutterBackground=(0,a.registerColor)("peekViewEditorGutter.background",e.peekViewEditorBackground,i.localize(1189,"Background color of the gutter in the peek view editor.")),e.peekViewEditorStickyScrollBackground=(0,a.registerColor)("peekViewEditorStickyScroll.background",e.peekViewEditorBackground,i.localize(1190,"Background color of sticky scroll in the peek view editor.")),e.peekViewResultsMatchHighlight=(0,a.registerColor)("peekViewResult.matchHighlightBackground",{dark:"#ea5c004d",light:"#ea5c004d",hcDark:null,hcLight:null},i.localize(1191,"Match highlight color in the peek view result list.")),e.peekViewEditorMatchHighlight=(0,a.registerColor)("peekViewEditor.matchHighlightBackground",{dark:"#ff8f0099",light:"#f5d802de",hcDark:null,hcLight:null},i.localize(1192,"Match highlight color in the peek view editor.")),e.peekViewEditorMatchHighlightBorder=(0,a.registerColor)("peekViewEditor.matchHighlightBorder",{dark:null,light:null,hcDark:a.activeContrastBorder,hcLight:a.activeContrastBorder},i.localize(1193,"Match highlight border in the peek view editor."))}),define(ne[843],se([1,0,5,86,13,33,6,2,48,11,4,158,3,124,29,12,7,181,108,59,723,32,25,512]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C){"use strict";var f;Object.defineProperty(e,"__esModule",{value:!0}),e.MarkerNavigationWidget=void 0;class h{constructor(x,W,V,q,H){this._openerService=q,this._labelService=H,this._lines=0,this._longestLineLength=0,this._relatedDiagnostics=new WeakMap,this._disposables=new m.DisposableStore,this._editor=W;const z=document.createElement("div");z.className="descriptioncontainer",this._messageBlock=document.createElement("div"),this._messageBlock.classList.add("message"),this._messageBlock.setAttribute("aria-live","assertive"),this._messageBlock.setAttribute("role","alert"),z.appendChild(this._messageBlock),this._relatedBlock=document.createElement("div"),z.appendChild(this._relatedBlock),this._disposables.add(d.addStandardDisposableListener(this._relatedBlock,"click",U=>{U.preventDefault();const j=this._relatedDiagnostics.get(U.target);j&&V(j)})),this._scrollable=new k.ScrollableElement(z,{horizontal:1,vertical:1,useShadows:!1,horizontalScrollbarSize:6,verticalScrollbarSize:6}),x.appendChild(this._scrollable.getDomNode()),this._disposables.add(this._scrollable.onScroll(U=>{z.style.left=`-${U.scrollLeft}px`,z.style.top=`-${U.scrollTop}px`})),this._disposables.add(this._scrollable)}dispose(){(0,m.dispose)(this._disposables)}update(x){const{source:W,message:V,relatedInformation:q,code:H}=x;let z=(W?.length||0)+2;H&&(typeof H=="string"?z+=H.length:z+=H.value.length);const U=(0,b.splitLines)(V);this._lines=U.length,this._longestLineLength=0;for(const R of U)this._longestLineLength=Math.max(R.length+z,this._longestLineLength);d.clearNode(this._messageBlock),this._messageBlock.setAttribute("aria-label",this.getAriaLabel(x)),this._editor.applyFontInfo(this._messageBlock);let j=this._messageBlock;for(const R of U)j=document.createElement("div"),j.innerText=R,R===""&&(j.style.height=this._messageBlock.style.lineHeight),this._messageBlock.appendChild(j);if(W||H){const R=document.createElement("span");if(R.classList.add("details"),j.appendChild(R),W){const J=document.createElement("span");J.innerText=W,J.classList.add("source"),R.appendChild(J)}if(H)if(typeof H=="string"){const J=document.createElement("span");J.innerText=`(${H})`,J.classList.add("code"),R.appendChild(J)}else{this._codeLink=d.$("a.code-link"),this._codeLink.setAttribute("href",`${H.target.toString()}`),this._codeLink.onclick=ie=>{this._openerService.open(H.target,{allowCommands:!0}),ie.preventDefault(),ie.stopPropagation()};const J=d.append(this._codeLink,d.$("span"));J.innerText=H.value,R.appendChild(this._codeLink)}}if(d.clearNode(this._relatedBlock),this._editor.applyFontInfo(this._relatedBlock),(0,I.isNonEmptyArray)(q)){const R=this._relatedBlock.appendChild(document.createElement("div"));R.style.paddingTop=`${Math.floor(this._editor.getOption(67)*.66)}px`,this._lines+=1;for(const J of q){const ie=document.createElement("div"),ue=document.createElement("a");ue.classList.add("filename"),ue.innerText=`${this._labelService.getUriBasenameLabel(J.resource)}(${J.startLineNumber}, ${J.startColumn}): `,ue.title=this._labelService.getUriLabel(J.resource),this._relatedDiagnostics.set(ue,J);const he=document.createElement("span");he.innerText=J.message,ie.appendChild(ue),ie.appendChild(he),this._lines+=1,R.appendChild(ie)}}const Y=this._editor.getOption(50),G=Math.ceil(Y.typicalFullwidthCharacterWidth*this._longestLineLength*.75),K=Y.lineHeight*this._lines;this._scrollable.setScrollDimensions({scrollWidth:G,scrollHeight:K})}layout(x,W){this._scrollable.getDomNode().style.height=`${x}px`,this._scrollable.getDomNode().style.width=`${W}px`,this._scrollable.setScrollDimensions({width:W,height:x})}getHeightInLines(){return Math.min(17,this._lines)}getAriaLabel(x){let W="";switch(x.severity){case l.MarkerSeverity.Error:W=o.localize(932,"Error");break;case l.MarkerSeverity.Warning:W=o.localize(933,"Warning");break;case l.MarkerSeverity.Info:W=o.localize(934,"Info");break;case l.MarkerSeverity.Hint:W=o.localize(935,"Hint");break}let V=o.localize(936,"{0} at {1}. ",W,x.startLineNumber+":"+x.startColumn);const q=this._editor.getModel();return q&&x.startLineNumber<=q.getLineCount()&&x.startLineNumber>=1&&(V=`${q.getLineContent(x.startLineNumber)}, ${V}`),V}}let v=class extends n.PeekViewWidget{static{f=this}static{this.TitleMenu=new i.MenuId("gotoErrorTitleMenu")}constructor(x,W,V,q,H,z,U){super(x,{showArrow:!0,showFrame:!0,isAccessible:!0,frameWidth:1},H),this._themeService=W,this._openerService=V,this._menuService=q,this._contextKeyService=z,this._labelService=U,this._callOnDispose=new m.DisposableStore,this._onDidSelectRelatedInformation=new y.Emitter,this.onDidSelectRelatedInformation=this._onDidSelectRelatedInformation.event,this._severity=l.MarkerSeverity.Warning,this._backgroundColor=E.Color.white,this._applyTheme(W.getColorTheme()),this._callOnDispose.add(W.onDidColorThemeChange(this._applyTheme.bind(this))),this.create()}_applyTheme(x){this._backgroundColor=x.getColor(O);let W=D,V=T;this._severity===l.MarkerSeverity.Warning?(W=M,V=A):this._severity===l.MarkerSeverity.Info&&(W=P,V=N);const q=x.getColor(W),H=x.getColor(V);this.style({arrowColor:q,frameColor:q,headerBackgroundColor:H,primaryHeadingColor:x.getColor(n.peekViewTitleForeground),secondaryHeadingColor:x.getColor(n.peekViewTitleInfoForeground)})}_applyStyles(){this._parentContainer&&(this._parentContainer.style.backgroundColor=this._backgroundColor?this._backgroundColor.toString():""),super._applyStyles()}dispose(){this._callOnDispose.dispose(),super.dispose()}_fillHead(x){super._fillHead(x),this._disposables.add(this._actionbarWidget.actionRunner.onWillRun(q=>this.editor.focus()));const W=[],V=this._menuService.getMenuActions(f.TitleMenu,this._contextKeyService);(0,t.createAndFillInActionBarActions)(V,W),this._actionbarWidget.push(W,{label:!1,icon:!0,index:0})}_fillTitleIcon(x){this._icon=d.append(x,d.$(""))}_fillBody(x){this._parentContainer=x,x.classList.add("marker-widget"),this._parentContainer.tabIndex=0,this._parentContainer.setAttribute("role","tooltip"),this._container=document.createElement("div"),x.appendChild(this._container),this._message=new h(this._container,this.editor,W=>this._onDidSelectRelatedInformation.fire(W),this._openerService,this._labelService),this._disposables.add(this._message)}show(){throw new Error("call showAtMarker")}showAtMarker(x,W,V){this._container.classList.remove("stale"),this._message.update(x),this._severity=x.severity,this._applyTheme(this._themeService.getColorTheme());const q=p.Range.lift(x),H=this.editor.getPosition(),z=H&&q.containsPosition(H)?H:q.getStartPosition();super.show(z,this.computeRequiredHeight());const U=this.editor.getModel();if(U){const j=V>1?o.localize(937,"{0} of {1} problems",W,V):o.localize(938,"{0} of {1} problem",W,V);this.setTitle((0,_.basename)(U.uri),j)}this._icon.className=`codicon ${r.SeverityIcon.className(l.MarkerSeverity.toSeverity(this._severity))}`,this.editor.revealPositionNearTop(z,0),this.editor.focus()}updateMarker(x){this._container.classList.remove("stale"),this._message.update(x)}showStale(){this._container.classList.add("stale"),this._relayout()}_doLayoutBody(x,W){super._doLayoutBody(x,W),this._heightInPixel=x,this._message.layout(x,W),this._container.style.height=`${x}px`}_onWidth(x){this._message.layout(this._heightInPixel,x)}_relayout(){super._relayout(this.computeRequiredHeight())}computeRequiredHeight(){return 3+this._message.getHeightInLines()}};e.MarkerNavigationWidget=v,e.MarkerNavigationWidget=v=f=ke([ce(1,C.IThemeService),ce(2,a.IOpenerService),ce(3,i.IMenuService),ce(4,g.IInstantiationService),ce(5,s.IContextKeyService),ce(6,c.ILabelService)],v);const w=(0,u.oneOf)(u.editorErrorForeground,u.editorErrorBorder),S=(0,u.oneOf)(u.editorWarningForeground,u.editorWarningBorder),L=(0,u.oneOf)(u.editorInfoForeground,u.editorInfoBorder),D=(0,u.registerColor)("editorMarkerNavigationError.background",{dark:w,light:w,hcDark:u.contrastBorder,hcLight:u.contrastBorder},o.localize(939,"Editor marker navigation widget error color.")),T=(0,u.registerColor)("editorMarkerNavigationError.headerBackground",{dark:(0,u.transparent)(D,.1),light:(0,u.transparent)(D,.1),hcDark:null,hcLight:null},o.localize(940,"Editor marker navigation widget error heading background.")),M=(0,u.registerColor)("editorMarkerNavigationWarning.background",{dark:S,light:S,hcDark:u.contrastBorder,hcLight:u.contrastBorder},o.localize(941,"Editor marker navigation widget warning color.")),A=(0,u.registerColor)("editorMarkerNavigationWarning.headerBackground",{dark:(0,u.transparent)(M,.1),light:(0,u.transparent)(M,.1),hcDark:"#0C141F",hcLight:(0,u.transparent)(M,.2)},o.localize(942,"Editor marker navigation widget warning heading background.")),P=(0,u.registerColor)("editorMarkerNavigationInfo.background",{dark:L,light:L,hcDark:u.contrastBorder,hcLight:u.contrastBorder},o.localize(943,"Editor marker navigation widget info color.")),N=(0,u.registerColor)("editorMarkerNavigationInfo.headerBackground",{dark:(0,u.transparent)(P,.1),light:(0,u.transparent)(P,.1),hcDark:null,hcLight:null},o.localize(944,"Editor marker navigation widget info heading background.")),O=(0,u.registerColor)("editorMarkerNavigation.background",u.editorBackground,o.localize(945,"Editor marker navigation widget background."))}),define(ne[427],se([1,0,26,2,15,34,9,4,20,698,3,29,12,7,71,843]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";var g;Object.defineProperty(e,"__esModule",{value:!0}),e.NextMarkerAction=e.MarkerController=void 0;let c=class{static{g=this}static{this.ID="editor.contrib.markerController"}static get(w){return w.getContribution(g.ID)}constructor(w,S,L,D,T){this._markerNavigationService=S,this._contextKeyService=L,this._editorService=D,this._instantiationService=T,this._sessionDispoables=new k.DisposableStore,this._editor=w,this._widgetVisible=f.bindTo(this._contextKeyService)}dispose(){this._cleanUp(),this._sessionDispoables.dispose()}_cleanUp(){this._widgetVisible.reset(),this._sessionDispoables.clear(),this._widget=void 0,this._model=void 0}_getOrCreateModel(w){if(this._model&&this._model.matches(w))return this._model;let S=!1;return this._model&&(S=!0,this._cleanUp()),this._model=this._markerNavigationService.getMarkerList(w),S&&this._model.move(!0,this._editor.getModel(),this._editor.getPosition()),this._widget=this._instantiationService.createInstance(s.MarkerNavigationWidget,this._editor),this._widget.onDidClose(()=>this.close(),this,this._sessionDispoables),this._widgetVisible.set(!0),this._sessionDispoables.add(this._model),this._sessionDispoables.add(this._widget),this._sessionDispoables.add(this._editor.onDidChangeCursorPosition(L=>{(!this._model?.selected||!m.Range.containsPosition(this._model?.selected.marker,L.position))&&this._model?.resetIndex()})),this._sessionDispoables.add(this._model.onDidChange(()=>{if(!this._widget||!this._widget.position||!this._model)return;const L=this._model.find(this._editor.getModel().uri,this._widget.position);L?this._widget.updateMarker(L.marker):this._widget.showStale()})),this._sessionDispoables.add(this._widget.onDidSelectRelatedInformation(L=>{this._editorService.openCodeEditor({resource:L.resource,options:{pinned:!0,revealIfOpened:!0,selection:m.Range.lift(L).collapseToStart()}},this._editor),this.close(!1)})),this._sessionDispoables.add(this._editor.onDidChangeModel(()=>this._cleanUp())),this._model}close(w=!0){this._cleanUp(),w&&this._editor.focus()}showAtMarker(w){if(this._editor.hasModel()){const S=this._getOrCreateModel(this._editor.getModel().uri);S.resetIndex(),S.move(!0,this._editor.getModel(),new y.Position(w.startLineNumber,w.startColumn)),S.selected&&this._widget.showAtMarker(S.selected.marker,S.selected.index,S.selected.total)}}async nagivate(w,S){if(this._editor.hasModel()){const L=this._getOrCreateModel(S?void 0:this._editor.getModel().uri);if(L.move(w,this._editor.getModel(),this._editor.getPosition()),!L.selected)return;if(L.selected.marker.resource.toString()!==this._editor.getModel().uri.toString()){this._cleanUp();const D=await this._editorService.openCodeEditor({resource:L.selected.marker.resource,options:{pinned:!1,revealIfOpened:!0,selectionRevealType:2,selection:L.selected.marker}},this._editor);D&&(g.get(D)?.close(),g.get(D)?.nagivate(w,S))}else this._widget.showAtMarker(L.selected.marker,L.selected.index,L.selected.total)}}};e.MarkerController=c,e.MarkerController=c=g=ke([ce(1,b.IMarkerNavigationService),ce(2,o.IContextKeyService),ce(3,E.ICodeEditorService),ce(4,t.IInstantiationService)],c);class l extends I.EditorAction{constructor(w,S,L){super(L),this._next=w,this._multiFile=S}async run(w,S){S.hasModel()&&c.get(S)?.nagivate(this._next,this._multiFile)}}class a extends l{static{this.ID="editor.action.marker.next"}static{this.LABEL=p.localize(924,"Go to Next Problem (Error, Warning, Info)")}constructor(){super(!0,!1,{id:a.ID,label:a.LABEL,alias:"Go to Next Problem (Error, Warning, Info)",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.focus,primary:578,weight:100},menuOpts:{menuId:s.MarkerNavigationWidget.TitleMenu,title:a.LABEL,icon:(0,i.registerIcon)("marker-navigation-next",d.Codicon.arrowDown,p.localize(925,"Icon for goto next marker.")),group:"navigation",order:1}})}}e.NextMarkerAction=a;class r extends l{static{this.ID="editor.action.marker.prev"}static{this.LABEL=p.localize(926,"Go to Previous Problem (Error, Warning, Info)")}constructor(){super(!1,!1,{id:r.ID,label:r.LABEL,alias:"Go to Previous Problem (Error, Warning, Info)",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.focus,primary:1602,weight:100},menuOpts:{menuId:s.MarkerNavigationWidget.TitleMenu,title:r.LABEL,icon:(0,i.registerIcon)("marker-navigation-previous",d.Codicon.arrowUp,p.localize(927,"Icon for goto previous marker.")),group:"navigation",order:2}})}}class u extends l{constructor(){super(!0,!0,{id:"editor.action.marker.nextInFiles",label:p.localize(928,"Go to Next Problem in Files (Error, Warning, Info)"),alias:"Go to Next Problem in Files (Error, Warning, Info)",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.focus,primary:66,weight:100},menuOpts:{menuId:n.MenuId.MenubarGoMenu,title:p.localize(929,"Next &&Problem"),group:"6_problem_nav",order:1}})}}class C extends l{constructor(){super(!1,!0,{id:"editor.action.marker.prevInFiles",label:p.localize(930,"Go to Previous Problem in Files (Error, Warning, Info)"),alias:"Go to Previous Problem in Files (Error, Warning, Info)",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.focus,primary:1090,weight:100},menuOpts:{menuId:n.MenuId.MenubarGoMenu,title:p.localize(931,"Previous &&Problem"),group:"6_problem_nav",order:2}})}}(0,I.registerEditorContribution)(c.ID,c,4),(0,I.registerEditorAction)(a),(0,I.registerEditorAction)(r),(0,I.registerEditorAction)(u),(0,I.registerEditorAction)(C);const f=new o.RawContextKey("markersNavigationVisible",!1),h=I.EditorCommand.bindToContribution(c.get);(0,I.registerEditorCommand)(new h({id:"closeMarkersNavigation",precondition:f,handler:v=>v.close(),kbOpts:{weight:150,kbExpr:_.EditorContextKeys.focus,primary:9,secondary:[1033]}}))}),define(ne[844],se([1,0,5,357,33,6,2,42,48,125,4,35,70,78,758,158,3,7,31,181,216,25,178,514]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ReferenceWidget=e.LayoutData=void 0;class f{static{this.DecorationOptions=n.ModelDecorationOptions.register({description:"reference-decoration",stickiness:1,className:"reference-decoration"})}constructor(L,D){this._editor=L,this._model=D,this._decorations=new Map,this._decorationIgnoreSet=new Set,this._callOnDispose=new y.DisposableStore,this._callOnModelChange=new y.DisposableStore,this._callOnDispose.add(this._editor.onDidChangeModel(()=>this._onModelChanged())),this._onModelChanged()}dispose(){this._callOnModelChange.dispose(),this._callOnDispose.dispose(),this.removeDecorations()}_onModelChanged(){this._callOnModelChange.clear();const L=this._editor.getModel();if(L){for(const D of this._model.references)if(D.uri.toString()===L.uri.toString()){this._addDecorations(D.parent);return}}}_addDecorations(L){if(!this._editor.hasModel())return;this._callOnModelChange.add(this._editor.getModel().onDidChangeDecorations(()=>this._onDecorationChanged()));const D=[],T=[];for(let M=0,A=L.children.length;M{const A=M.deltaDecorations([],D);for(let P=0;P{A.equals(9)&&(this._keybindingService.dispatchEvent(A,A.target),A.stopPropagation())},!0)),this._tree=this._instantiationService.createInstance(v,"ReferencesWidget",this._treeContainer,new i.Delegate,[this._instantiationService.createInstance(i.FileReferencesRenderer),this._instantiationService.createInstance(i.OneReferenceRenderer)],this._instantiationService.createInstance(i.DataSource),T),this._splitView.addView({onDidChange:E.Event.None,element:this._previewContainer,minimumSize:200,maximumSize:Number.MAX_VALUE,layout:A=>{this._preview.layout({height:this._dim.height,width:A})}},k.Sizing.Distribute),this._splitView.addView({onDidChange:E.Event.None,element:this._treeContainer,minimumSize:100,maximumSize:Number.MAX_VALUE,layout:A=>{this._treeContainer.style.height=`${this._dim.height}px`,this._treeContainer.style.width=`${A}px`,this._tree.layout(this._dim.height,A)}},k.Sizing.Distribute),this._disposables.add(this._splitView.onDidSashChange(()=>{this._dim.width&&(this.layoutData.ratio=this._splitView.getViewSize(0)/this._dim.width)},void 0));const M=(A,P)=>{A instanceof C.OneReference&&(P==="show"&&this._revealReference(A,!1),this._onDidSelectReference.fire({element:A,kind:P,source:"tree"}))};this._disposables.add(this._tree.onDidOpen(A=>{A.sideBySide?M(A.element,"side"):A.editorOptions.pinned?M(A.element,"goto"):M(A.element,"show")})),d.hide(this._treeContainer)}_onWidth(L){this._dim&&this._doLayoutBody(this._dim.height,L)}_doLayoutBody(L,D){super._doLayoutBody(L,D),this._dim=new d.Dimension(D,L),this.layoutData.heightInLines=this._viewZone?this._viewZone.heightInLines:this.layoutData.heightInLines,this._splitView.layout(D),this._splitView.resizeView(0,D*this.layoutData.ratio)}setSelection(L){return this._revealReference(L,!0).then(()=>{this._model&&(this._tree.setSelection([L]),this._tree.setFocus([L]))})}setModel(L){return this._disposeOnNewModel.clear(),this._model=L,this._model?this._onNewModel():Promise.resolve()}_onNewModel(){return this._model?this._model.isEmpty?(this.setTitle(""),this._messageContainer.innerText=g.localize(993,"No results"),d.show(this._messageContainer),Promise.resolve(void 0)):(d.hide(this._messageContainer),this._decorationsManager=new f(this._preview,this._model),this._disposeOnNewModel.add(this._decorationsManager),this._disposeOnNewModel.add(this._model.onDidChangeReferenceRange(L=>this._tree.rerender(L))),this._disposeOnNewModel.add(this._preview.onMouseDown(L=>{const{event:D,target:T}=L;if(D.detail!==2)return;const M=this._getFocusedReference();M&&this._onDidSelectReference.fire({element:{uri:M.uri,range:T.range},kind:D.ctrlKey||D.metaKey||D.altKey?"side":"open",source:"editor"})})),this.container.classList.add("results-loaded"),d.show(this._treeContainer),d.show(this._previewContainer),this._splitView.layout(this._dim.width),this.focusOnReferenceTree(),this._tree.setInput(this._model.groups.length===1?this._model.groups[0]:this._model)):Promise.resolve(void 0)}_getFocusedReference(){const[L]=this._tree.getFocus();if(L instanceof C.OneReference)return L;if(L instanceof C.FileReferences&&L.children.length>0)return L.children[0]}async revealReference(L){await this._revealReference(L,!1),this._onDidSelectReference.fire({element:L,kind:"goto",source:"tree"})}async _revealReference(L,D){if(this._revealedReference===L)return;this._revealedReference=L,L.uri.scheme!==m.Schemas.inMemory?this.setTitle((0,_.basenameOrAuthority)(L.uri),this._uriLabel.getUriLabel((0,_.dirname)(L.uri))):this.setTitle(g.localize(994,"References"));const T=this._textModelResolverService.createModelReference(L.uri);this._tree.getInput()===L.parent?this._tree.reveal(L):(D&&this._tree.reveal(L.parent),await this._tree.expand(L.parent),this._tree.reveal(L));const M=await T;if(!this._model){M.dispose();return}(0,y.dispose)(this._previewModelReference);const A=M.object;if(A){const P=this._preview.getModel()===A.textEditorModel?0:1,N=p.Range.lift(L.range).collapseToStart();this._previewModelReference=M,this._preview.setModel(A.textEditorModel),this._preview.setSelection(N),this._preview.revealRangeInCenter(N,P)}else this._preview.setModel(this._previewNotAvailableMessage),M.dispose()}};e.ReferenceWidget=w,e.ReferenceWidget=w=ke([ce(3,u.IThemeService),ce(4,t.ITextModelService),ce(5,c.IInstantiationService),ce(6,s.IPeekViewService),ce(7,a.ILabelService),ce(8,l.IKeybindingService)],w)}),define(ne[428],se([1,0,14,8,72,2,34,9,4,158,3,24,28,12,7,121,216,50,101,178,844,20,179]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C){"use strict";var f;Object.defineProperty(e,"__esModule",{value:!0}),e.ReferencesController=e.ctxReferenceSearchVisible=void 0,e.ctxReferenceSearchVisible=new t.RawContextKey("referenceSearchVisible",!1,p.localize(986,"Whether reference peek is visible, like 'Peek References' or 'Peek Definition'"));let h=class{static{f=this}static{this.ID="editor.contrib.referencesController"}static get(S){return S.getContribution(f.ID)}constructor(S,L,D,T,M,A,P,N){this._defaultTreeKeyboardSupport=S,this._editor=L,this._editorService=T,this._notificationService=M,this._instantiationService=A,this._storageService=P,this._configurationService=N,this._disposables=new E.DisposableStore,this._requestIdPool=0,this._ignoreModelChangeEvent=!1,this._referenceSearchVisible=e.ctxReferenceSearchVisible.bindTo(D)}dispose(){this._referenceSearchVisible.reset(),this._disposables.dispose(),this._widget?.dispose(),this._model?.dispose(),this._widget=void 0,this._model=void 0}toggleWidget(S,L,D){let T;if(this._widget&&(T=this._widget.position),this.closeWidget(),T&&S.containsPosition(T))return;this._peekMode=D,this._referenceSearchVisible.set(!0),this._disposables.add(this._editor.onDidChangeModelLanguage(()=>{this.closeWidget()})),this._disposables.add(this._editor.onDidChangeModel(()=>{this._ignoreModelChangeEvent||this.closeWidget()}));const M="peekViewLayout",A=r.LayoutData.fromJSON(this._storageService.get(M,0,"{}"));this._widget=this._instantiationService.createInstance(r.ReferenceWidget,this._editor,this._defaultTreeKeyboardSupport,A),this._widget.setTitle(p.localize(987,"Loading...")),this._widget.show(S),this._disposables.add(this._widget.onDidClose(()=>{L.cancel(),this._widget?(this._storageService.store(M,JSON.stringify(this._widget.layoutData),0,1),this._widget.isClosing||this.closeWidget(),this._widget=void 0):this.closeWidget()})),this._disposables.add(this._widget.onDidSelectReference(N=>{const{element:O,kind:F}=N;if(O)switch(F){case"open":(N.source!=="editor"||!this._configurationService.getValue("editor.stablePeek"))&&this.openReference(O,!1,!1);break;case"side":this.openReference(O,!0,!1);break;case"goto":D?this._gotoReference(O,!0):this.openReference(O,!1,!0);break}}));const P=++this._requestIdPool;L.then(N=>{if(P!==this._requestIdPool||!this._widget){N.dispose();return}return this._model?.dispose(),this._model=N,this._widget.setModel(this._model).then(()=>{if(this._widget&&this._model&&this._editor.hasModel()){this._model.isEmpty?this._widget.setMetaTitle(""):this._widget.setMetaTitle(p.localize(988,"{0} ({1})",this._model.title,this._model.references.length));const O=this._editor.getModel().uri,F=new m.Position(S.startLineNumber,S.startColumn),x=this._model.nearestReference(O,F);if(x)return this._widget.setSelection(x).then(()=>{this._widget&&this._editor.getOption(87)==="editor"&&this._widget.focusOnPreviewEditor()})}})},N=>{this._notificationService.error(N)})}changeFocusBetweenPreviewAndReferences(){this._widget&&(this._widget.isPreviewEditorFocused()?this._widget.focusOnReferenceTree():this._widget.focusOnPreviewEditor())}async goToNextOrPreviousReference(S){if(!this._editor.hasModel()||!this._model||!this._widget)return;const L=this._widget.position;if(!L)return;const D=this._model.nearestReference(this._editor.getModel().uri,L);if(!D)return;const T=this._model.nextOrPreviousReference(D,S),M=this._editor.hasTextFocus(),A=this._widget.isPreviewEditorFocused();await this._widget.setSelection(T),await this._gotoReference(T,!1),M?this._editor.focus():this._widget&&A&&this._widget.focusOnPreviewEditor()}async revealReference(S){!this._editor.hasModel()||!this._model||!this._widget||await this._widget.revealReference(S)}closeWidget(S=!0){this._widget?.dispose(),this._model?.dispose(),this._referenceSearchVisible.reset(),this._disposables.clear(),this._widget=void 0,this._model=void 0,S&&this._editor.focus(),this._requestIdPool+=1}_gotoReference(S,L){this._widget?.hide(),this._ignoreModelChangeEvent=!0;const D=_.Range.lift(S.range).collapseToStart();return this._editorService.openCodeEditor({resource:S.uri,options:{selection:D,selectionSource:"code.jump",pinned:L}},this._editor).then(T=>{if(this._ignoreModelChangeEvent=!1,!T||!this._widget){this.closeWidget();return}if(this._editor===T)this._widget.show(D),this._widget.focusOnReferenceTree();else{const M=f.get(T),A=this._model.clone();this.closeWidget(),T.focus(),M?.toggleWidget(D,(0,d.createCancelablePromise)(P=>Promise.resolve(A)),this._peekMode??!1)}},T=>{this._ignoreModelChangeEvent=!1,(0,k.onUnexpectedError)(T)})}openReference(S,L,D){L||this.closeWidget();const{uri:T,range:M}=S;this._editorService.openCodeEditor({resource:T,options:{selection:M,selectionSource:"code.jump",pinned:D}},this._editor,L)}};e.ReferencesController=h,e.ReferencesController=h=f=ke([ce(2,t.IContextKeyService),ce(3,y.ICodeEditorService),ce(4,c.INotificationService),ce(5,i.IInstantiationService),ce(6,l.IStorageService),ce(7,o.IConfigurationService)],h);function v(w,S){const L=(0,b.getOuterEditor)(w);if(!L)return;const D=h.get(L);D&&S(D)}s.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"togglePeekWidgetFocus",weight:100,primary:(0,I.KeyChord)(2089,60),when:t.ContextKeyExpr.or(e.ctxReferenceSearchVisible,b.PeekContext.inPeekEditor),handler(w){v(w,S=>{S.changeFocusBetweenPreviewAndReferences()})}}),s.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"goToNextReference",weight:90,primary:62,secondary:[70],when:t.ContextKeyExpr.or(e.ctxReferenceSearchVisible,b.PeekContext.inPeekEditor),handler(w){v(w,S=>{S.goToNextOrPreviousReference(!0)})}}),s.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"goToPreviousReference",weight:90,primary:1086,secondary:[1094],when:t.ContextKeyExpr.or(e.ctxReferenceSearchVisible,b.PeekContext.inPeekEditor),handler(w){v(w,S=>{S.goToNextOrPreviousReference(!1)})}}),n.CommandsRegistry.registerCommandAlias("goToNextReferenceFromEmbeddedEditor","goToNextReference"),n.CommandsRegistry.registerCommandAlias("goToPreviousReferenceFromEmbeddedEditor","goToPreviousReference"),n.CommandsRegistry.registerCommandAlias("closeReferenceSearchEditor","closeReferenceSearch"),n.CommandsRegistry.registerCommand("closeReferenceSearch",w=>v(w,S=>S.closeWidget())),s.KeybindingsRegistry.registerKeybindingRule({id:"closeReferenceSearch",weight:-1,primary:9,secondary:[1033],when:t.ContextKeyExpr.and(b.PeekContext.inPeekEditor,t.ContextKeyExpr.not("config.editor.stablePeek"))}),s.KeybindingsRegistry.registerKeybindingRule({id:"closeReferenceSearch",weight:250,primary:9,secondary:[1033],when:t.ContextKeyExpr.and(e.ctxReferenceSearchVisible,t.ContextKeyExpr.not("config.editor.stablePeek"),t.ContextKeyExpr.or(u.EditorContextKeys.editorTextFocus,C.InputFocusedContext.negate()))}),s.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"revealReference",weight:200,primary:3,mac:{primary:3,secondary:[2066]},when:t.ContextKeyExpr.and(e.ctxReferenceSearchVisible,g.WorkbenchListFocusContextKey,g.WorkbenchTreeElementCanCollapse.negate(),g.WorkbenchTreeElementCanExpand.negate()),handler(w){const L=w.get(g.IListService).lastFocusedList?.getFocus();Array.isArray(L)&&L[0]instanceof a.OneReference&&v(w,D=>D.revealReference(L[0]))}}),s.KeybindingsRegistry.registerCommandAndKeybindingRule({id:"openReferenceToSide",weight:100,primary:2051,mac:{primary:259},when:t.ContextKeyExpr.and(e.ctxReferenceSearchVisible,g.WorkbenchListFocusContextKey,g.WorkbenchTreeElementCanCollapse.negate(),g.WorkbenchTreeElementCanExpand.negate()),handler(w){const L=w.get(g.IListService).lastFocusedList?.getFocus();Array.isArray(L)&&L[0]instanceof a.OneReference&&v(w,D=>D.openReference(L[0],!0,!0))}}),n.CommandsRegistry.registerCommand("openReference",w=>{const L=w.get(g.IListService).lastFocusedList?.getFocus();Array.isArray(L)&&L[0]instanceof a.OneReference&&v(w,D=>D.openReference(L[0],!1,!0))})}),define(ne[291],se([1,0,46,14,72,19,22,122,168,15,34,125,9,4,20,27,428,178,736,184,158,3,29,24,12,7,50,96,277,17,53,179]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DefinitionAction=e.SymbolNavigationAction=e.SymbolNavigationAnchor=void 0,C.MenuRegistry.appendMenuItem(C.MenuId.EditorContext,{submenu:C.MenuId.EditorContextPeek,title:u.localize(946,"Peek"),group:"navigation",order:100});class A{static is(H){return!H||typeof H!="object"?!1:!!(H instanceof A||o.Position.isIPosition(H.position)&&H.model)}constructor(H,z){this.model=H,this.position=z}}e.SymbolNavigationAnchor=A;class P extends b.EditorAction2{static{this._allSymbolNavigationCommands=new Map}static{this._activeAlternativeCommands=new Set}static all(){return P._allSymbolNavigationCommands.values()}static _patchConfig(H){const z={...H,f1:!0};if(z.menu)for(const U of T.Iterable.wrap(z.menu))(U.id===C.MenuId.EditorContext||U.id===C.MenuId.EditorContextPeek)&&(U.when=h.ContextKeyExpr.and(H.precondition,U.when));return z}constructor(H,z){super(P._patchConfig(z)),this.configuration=H,P._allSymbolNavigationCommands.set(z.id,this)}runEditorCommand(H,z,U,j){if(!z.hasModel())return Promise.resolve(void 0);const Y=H.get(w.INotificationService),G=H.get(p.ICodeEditorService),K=H.get(S.IEditorProgressService),R=H.get(l.ISymbolNavigationService),J=H.get(D.ILanguageFeaturesService),ie=H.get(v.IInstantiationService),ue=z.getModel(),he=z.getPosition(),pe=A.is(U)?U:new A(ue,he),ae=new m.EditorStateCancellationTokenSource(z,5),ee=(0,k.raceCancellation)(this._getLocationModel(J,pe.model,pe.position,ae.token),ae.token).then(async de=>{if(!de||ae.token.isCancellationRequested)return;(0,d.alert)(de.ariaMessage);let ge;if(de.referenceAt(ue.uri,he)){const B=this._getAlternativeCommand(z);!P._activeAlternativeCommands.has(B)&&P._allSymbolNavigationCommands.has(B)&&(ge=P._allSymbolNavigationCommands.get(B))}const X=de.references.length;if(X===0){if(!this.configuration.muteMessage){const B=ue.getWordAtPosition(he);a.MessageController.get(z)?.showMessage(this._getNoResultFoundMessage(B),he)}}else if(X===1&&ge)P._activeAlternativeCommands.add(this.desc.id),ie.invokeFunction(B=>ge.runEditorCommand(B,z,U,j).finally(()=>{P._activeAlternativeCommands.delete(this.desc.id)}));else return this._onResult(G,R,z,de,j)},de=>{Y.error(de)}).finally(()=>{ae.dispose()});return K.showWhile(ee,250),ee}async _onResult(H,z,U,j,Y){const G=this._getGoToPreference(U);if(!(U instanceof n.EmbeddedCodeEditorWidget)&&(this.configuration.openInPeek||G==="peek"&&j.references.length>1))this._openInPeek(U,j,Y);else{const K=j.firstReference(),R=j.references.length>1&&G==="gotoAndPeek",J=await this._openReference(U,H,K,this.configuration.openToSide,!R);R&&J?this._openInPeek(J,j,Y):j.dispose(),G==="goto"&&z.put(K)}}async _openReference(H,z,U,j,Y){let G;if((0,s.isLocationLink)(U)&&(G=U.targetSelectionRange),G||(G=U.range),!G)return;const K=await z.openCodeEditor({resource:U.uri,options:{selection:t.Range.collapseToStart(G),selectionRevealType:3,selectionSource:"code.jump"}},H,j);if(K){if(Y){const R=K.getModel(),J=K.createDecorationsCollection([{range:G,options:{description:"symbol-navigate-action-highlight",className:"symbolHighlight"}}]);setTimeout(()=>{K.getModel()===R&&J.clear()},350)}return K}}_openInPeek(H,z,U){const j=g.ReferencesController.get(H);j&&H.hasModel()?j.toggleWidget(U??H.getSelection(),(0,k.createCancelablePromise)(Y=>Promise.resolve(z)),this.configuration.openInPeek):z.dispose()}}e.SymbolNavigationAction=P;class N extends P{async _getLocationModel(H,z,U,j){return new c.ReferencesModel(await(0,L.getDefinitionsAtPosition)(H.definitionProvider,z,U,!1,j),u.localize(947,"Definitions"))}_getNoResultFoundMessage(H){return H&&H.word?u.localize(948,"No definition found for '{0}'",H.word):u.localize(949,"No definition found")}_getAlternativeCommand(H){return H.getOption(58).alternativeDefinitionCommand}_getGoToPreference(H){return H.getOption(58).multipleDefinitions}}e.DefinitionAction=N,(0,C.registerAction2)(class Gt extends N{static{this.id="editor.action.revealDefinition"}constructor(){super({openToSide:!1,openInPeek:!1,muteMessage:!1},{id:Gt.id,title:{...u.localize2(973,"Go to Definition"),mnemonicTitle:u.localize(950,"Go to &&Definition")},precondition:i.EditorContextKeys.hasDefinitionProvider,keybinding:[{when:i.EditorContextKeys.editorTextFocus,primary:70,weight:100},{when:h.ContextKeyExpr.and(i.EditorContextKeys.editorTextFocus,M.IsWebContext),primary:2118,weight:100}],menu:[{id:C.MenuId.EditorContext,group:"navigation",order:1.1},{id:C.MenuId.MenubarGoMenu,precondition:null,group:"4_symbol_nav",order:2}]}),f.CommandsRegistry.registerCommandAlias("editor.action.goToDeclaration",Gt.id)}}),(0,C.registerAction2)(class Yt extends N{static{this.id="editor.action.revealDefinitionAside"}constructor(){super({openToSide:!0,openInPeek:!1,muteMessage:!1},{id:Yt.id,title:u.localize2(974,"Open Definition to the Side"),precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasDefinitionProvider,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),keybinding:[{when:i.EditorContextKeys.editorTextFocus,primary:(0,I.KeyChord)(2089,70),weight:100},{when:h.ContextKeyExpr.and(i.EditorContextKeys.editorTextFocus,M.IsWebContext),primary:(0,I.KeyChord)(2089,2118),weight:100}]}),f.CommandsRegistry.registerCommandAlias("editor.action.openDeclarationToTheSide",Yt.id)}}),(0,C.registerAction2)(class Qt extends N{static{this.id="editor.action.peekDefinition"}constructor(){super({openToSide:!1,openInPeek:!0,muteMessage:!1},{id:Qt.id,title:u.localize2(975,"Peek Definition"),precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasDefinitionProvider,r.PeekContext.notInPeekEditor,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),keybinding:{when:i.EditorContextKeys.editorTextFocus,primary:582,linux:{primary:3140},weight:100},menu:{id:C.MenuId.EditorContextPeek,group:"peek",order:2}}),f.CommandsRegistry.registerCommandAlias("editor.action.previewDeclaration",Qt.id)}});class O extends P{async _getLocationModel(H,z,U,j){return new c.ReferencesModel(await(0,L.getDeclarationsAtPosition)(H.declarationProvider,z,U,!1,j),u.localize(951,"Declarations"))}_getNoResultFoundMessage(H){return H&&H.word?u.localize(952,"No declaration found for '{0}'",H.word):u.localize(953,"No declaration found")}_getAlternativeCommand(H){return H.getOption(58).alternativeDeclarationCommand}_getGoToPreference(H){return H.getOption(58).multipleDeclarations}}(0,C.registerAction2)(class hi extends O{static{this.id="editor.action.revealDeclaration"}constructor(){super({openToSide:!1,openInPeek:!1,muteMessage:!1},{id:hi.id,title:{...u.localize2(976,"Go to Declaration"),mnemonicTitle:u.localize(954,"Go to &&Declaration")},precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasDeclarationProvider,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),menu:[{id:C.MenuId.EditorContext,group:"navigation",order:1.3},{id:C.MenuId.MenubarGoMenu,precondition:null,group:"4_symbol_nav",order:3}]})}_getNoResultFoundMessage(H){return H&&H.word?u.localize(955,"No declaration found for '{0}'",H.word):u.localize(956,"No declaration found")}}),(0,C.registerAction2)(class extends O{constructor(){super({openToSide:!1,openInPeek:!0,muteMessage:!1},{id:"editor.action.peekDeclaration",title:u.localize2(977,"Peek Declaration"),precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasDeclarationProvider,r.PeekContext.notInPeekEditor,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),menu:{id:C.MenuId.EditorContextPeek,group:"peek",order:3}})}});class F extends P{async _getLocationModel(H,z,U,j){return new c.ReferencesModel(await(0,L.getTypeDefinitionsAtPosition)(H.typeDefinitionProvider,z,U,!1,j),u.localize(957,"Type Definitions"))}_getNoResultFoundMessage(H){return H&&H.word?u.localize(958,"No type definition found for '{0}'",H.word):u.localize(959,"No type definition found")}_getAlternativeCommand(H){return H.getOption(58).alternativeTypeDefinitionCommand}_getGoToPreference(H){return H.getOption(58).multipleTypeDefinitions}}(0,C.registerAction2)(class gi extends F{static{this.ID="editor.action.goToTypeDefinition"}constructor(){super({openToSide:!1,openInPeek:!1,muteMessage:!1},{id:gi.ID,title:{...u.localize2(978,"Go to Type Definition"),mnemonicTitle:u.localize(960,"Go to &&Type Definition")},precondition:i.EditorContextKeys.hasTypeDefinitionProvider,keybinding:{when:i.EditorContextKeys.editorTextFocus,primary:0,weight:100},menu:[{id:C.MenuId.EditorContext,group:"navigation",order:1.4},{id:C.MenuId.MenubarGoMenu,precondition:null,group:"4_symbol_nav",order:3}]})}}),(0,C.registerAction2)(class fi extends F{static{this.ID="editor.action.peekTypeDefinition"}constructor(){super({openToSide:!1,openInPeek:!0,muteMessage:!1},{id:fi.ID,title:u.localize2(979,"Peek Type Definition"),precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasTypeDefinitionProvider,r.PeekContext.notInPeekEditor,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),menu:{id:C.MenuId.EditorContextPeek,group:"peek",order:4}})}});class x extends P{async _getLocationModel(H,z,U,j){return new c.ReferencesModel(await(0,L.getImplementationsAtPosition)(H.implementationProvider,z,U,!1,j),u.localize(961,"Implementations"))}_getNoResultFoundMessage(H){return H&&H.word?u.localize(962,"No implementation found for '{0}'",H.word):u.localize(963,"No implementation found")}_getAlternativeCommand(H){return H.getOption(58).alternativeImplementationCommand}_getGoToPreference(H){return H.getOption(58).multipleImplementations}}(0,C.registerAction2)(class mi extends x{static{this.ID="editor.action.goToImplementation"}constructor(){super({openToSide:!1,openInPeek:!1,muteMessage:!1},{id:mi.ID,title:{...u.localize2(980,"Go to Implementations"),mnemonicTitle:u.localize(964,"Go to &&Implementations")},precondition:i.EditorContextKeys.hasImplementationProvider,keybinding:{when:i.EditorContextKeys.editorTextFocus,primary:2118,weight:100},menu:[{id:C.MenuId.EditorContext,group:"navigation",order:1.45},{id:C.MenuId.MenubarGoMenu,precondition:null,group:"4_symbol_nav",order:4}]})}}),(0,C.registerAction2)(class pi extends x{static{this.ID="editor.action.peekImplementation"}constructor(){super({openToSide:!1,openInPeek:!0,muteMessage:!1},{id:pi.ID,title:u.localize2(981,"Peek Implementations"),precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasImplementationProvider,r.PeekContext.notInPeekEditor,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),keybinding:{when:i.EditorContextKeys.editorTextFocus,primary:3142,weight:100},menu:{id:C.MenuId.EditorContextPeek,group:"peek",order:5}})}});class W extends P{_getNoResultFoundMessage(H){return H?u.localize(965,"No references found for '{0}'",H.word):u.localize(966,"No references found")}_getAlternativeCommand(H){return H.getOption(58).alternativeReferenceCommand}_getGoToPreference(H){return H.getOption(58).multipleReferences}}(0,C.registerAction2)(class extends W{constructor(){super({openToSide:!1,openInPeek:!1,muteMessage:!1},{id:"editor.action.goToReferences",title:{...u.localize2(982,"Go to References"),mnemonicTitle:u.localize(967,"Go to &&References")},precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasReferenceProvider,r.PeekContext.notInPeekEditor,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),keybinding:{when:i.EditorContextKeys.editorTextFocus,primary:1094,weight:100},menu:[{id:C.MenuId.EditorContext,group:"navigation",order:1.45},{id:C.MenuId.MenubarGoMenu,precondition:null,group:"4_symbol_nav",order:5}]})}async _getLocationModel(H,z,U,j){return new c.ReferencesModel(await(0,L.getReferencesAtPosition)(H.referenceProvider,z,U,!0,!1,j),u.localize(968,"References"))}}),(0,C.registerAction2)(class extends W{constructor(){super({openToSide:!1,openInPeek:!0,muteMessage:!1},{id:"editor.action.referenceSearch.trigger",title:u.localize2(983,"Peek References"),precondition:h.ContextKeyExpr.and(i.EditorContextKeys.hasReferenceProvider,r.PeekContext.notInPeekEditor,i.EditorContextKeys.isInEmbeddedEditor.toNegated()),menu:{id:C.MenuId.EditorContextPeek,group:"peek",order:6}})}async _getLocationModel(H,z,U,j){return new c.ReferencesModel(await(0,L.getReferencesAtPosition)(H.referenceProvider,z,U,!1,!1,j),u.localize(969,"References"))}});class V extends P{constructor(H,z,U){super(H,{id:"editor.action.goToLocation",title:u.localize2(984,"Go to Any Symbol"),precondition:h.ContextKeyExpr.and(r.PeekContext.notInPeekEditor,i.EditorContextKeys.isInEmbeddedEditor.toNegated())}),this._references=z,this._gotoMultipleBehaviour=U}async _getLocationModel(H,z,U,j){return new c.ReferencesModel(this._references,u.localize(970,"Locations"))}_getNoResultFoundMessage(H){return H&&u.localize(971,"No results for '{0}'",H.word)||""}_getGoToPreference(H){return this._gotoMultipleBehaviour??H.getOption(58).multipleReferences}_getAlternativeCommand(){return""}}f.CommandsRegistry.registerCommand({id:"editor.action.goToLocations",metadata:{description:"Go to locations from a position in a file",args:[{name:"uri",description:"The text document in which to start",constraint:y.URI},{name:"position",description:"The position at which to start",constraint:o.Position.isIPosition},{name:"locations",description:"An array of locations.",constraint:Array},{name:"multiple",description:"Define what to do when having multiple results, either `peek`, `gotoAndPeek`, or `goto`"},{name:"noResultsMessage",description:"Human readable message that shows when locations is empty."}]},handler:async(q,H,z,U,j,Y,G)=>{(0,E.assertType)(y.URI.isUri(H)),(0,E.assertType)(o.Position.isIPosition(z)),(0,E.assertType)(Array.isArray(U)),(0,E.assertType)(typeof j>"u"||typeof j=="string"),(0,E.assertType)(typeof G>"u"||typeof G=="boolean");const K=q.get(p.ICodeEditorService),R=await K.openCodeEditor({resource:H},K.getFocusedCodeEditor());if((0,_.isCodeEditor)(R))return R.setPosition(z),R.revealPositionInCenterIfOutsideViewport(z,0),R.invokeWithinContext(J=>{const ie=new class extends V{_getNoResultFoundMessage(ue){return Y||super._getNoResultFoundMessage(ue)}}({muteMessage:!Y,openInPeek:!!G,openToSide:!1},U,j);J.get(v.IInstantiationService).invokeFunction(ie.run.bind(ie),R)})}}),f.CommandsRegistry.registerCommand({id:"editor.action.peekLocations",metadata:{description:"Peek locations from a position in a file",args:[{name:"uri",description:"The text document in which to start",constraint:y.URI},{name:"position",description:"The position at which to start",constraint:o.Position.isIPosition},{name:"locations",description:"An array of locations.",constraint:Array},{name:"multiple",description:"Define what to do when having multiple results, either `peek`, `gotoAndPeek`, or `goto`"}]},handler:async(q,H,z,U,j)=>{q.get(f.ICommandService).executeCommand("editor.action.goToLocations",H,z,U,j,void 0,!0)}}),f.CommandsRegistry.registerCommand({id:"editor.action.findReferences",handler:(q,H,z)=>{(0,E.assertType)(y.URI.isUri(H)),(0,E.assertType)(o.Position.isIPosition(z));const U=q.get(D.ILanguageFeaturesService),j=q.get(p.ICodeEditorService);return j.openCodeEditor({resource:H},j.getFocusedCodeEditor()).then(Y=>{if(!(0,_.isCodeEditor)(Y)||!Y.hasModel())return;const G=g.ReferencesController.get(Y);if(!G)return;const K=(0,k.createCancelablePromise)(J=>(0,L.getReferencesAtPosition)(U.referenceProvider,Y.getModel(),o.Position.lift(z),!1,!1,J).then(ie=>new c.ReferencesModel(ie,u.localize(972,"References")))),R=new t.Range(z.lineNumber,z.column,z.lineNumber,z.column);return Promise.resolve(G.toggleWidget(R,K,!1))})}}),f.CommandsRegistry.registerCommandAlias("editor.action.showReferences","editor.action.peekLocations")}),define(ne[429],se([1,0,14,8,57,2,122,15,4,43,78,209,158,3,12,291,277,17,35,513]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l){"use strict";var a;Object.defineProperty(e,"__esModule",{value:!0}),e.GotoDefinitionAtPositionEditorContribution=void 0;let r=class{static{a=this}static{this.ID="editor.contrib.gotodefinitionatposition"}static{this.MAX_SOURCE_PREVIEW_LINES=8}constructor(C,f,h,v){this.textModelResolverService=f,this.languageService=h,this.languageFeaturesService=v,this.toUnhook=new E.DisposableStore,this.toUnhookForKeyboard=new E.DisposableStore,this.currentWordAtPosition=null,this.previousPromise=null,this.editor=C,this.linkDecorations=this.editor.createDecorationsCollection();const w=new n.ClickLinkGesture(C);this.toUnhook.add(w),this.toUnhook.add(w.onMouseMoveOrRelevantKeyDown(([S,L])=>{this.startFindDefinitionFromMouse(S,L??void 0)})),this.toUnhook.add(w.onExecute(S=>{this.isEnabled(S)&&this.gotoDefinition(S.target.position,S.hasSideBySideModifier).catch(L=>{(0,k.onUnexpectedError)(L)}).finally(()=>{this.removeLinkDecorations()})})),this.toUnhook.add(w.onCancel(()=>{this.removeLinkDecorations(),this.currentWordAtPosition=null}))}static get(C){return C.getContribution(a.ID)}async startFindDefinitionFromCursor(C){await this.startFindDefinition(C),this.toUnhookForKeyboard.add(this.editor.onDidChangeCursorPosition(()=>{this.currentWordAtPosition=null,this.removeLinkDecorations(),this.toUnhookForKeyboard.clear()})),this.toUnhookForKeyboard.add(this.editor.onKeyDown(f=>{f&&(this.currentWordAtPosition=null,this.removeLinkDecorations(),this.toUnhookForKeyboard.clear())}))}startFindDefinitionFromMouse(C,f){if(C.target.type===9&&this.linkDecorations.length>0)return;if(!this.editor.hasModel()||!this.isEnabled(C,f)){this.currentWordAtPosition=null,this.removeLinkDecorations();return}const h=C.target.position;this.startFindDefinition(h)}async startFindDefinition(C){this.toUnhookForKeyboard.clear();const f=C?this.editor.getModel()?.getWordAtPosition(C):null;if(!f){this.currentWordAtPosition=null,this.removeLinkDecorations();return}if(this.currentWordAtPosition&&this.currentWordAtPosition.startColumn===f.startColumn&&this.currentWordAtPosition.endColumn===f.endColumn&&this.currentWordAtPosition.word===f.word)return;this.currentWordAtPosition=f;const h=new y.EditorState(this.editor,15);this.previousPromise&&(this.previousPromise.cancel(),this.previousPromise=null),this.previousPromise=(0,d.createCancelablePromise)(S=>this.findDefinition(C,S));let v;try{v=await this.previousPromise}catch(S){(0,k.onUnexpectedError)(S);return}if(!v||!v.length||!h.validate(this.editor)){this.removeLinkDecorations();return}const w=v[0].originSelectionRange?_.Range.lift(v[0].originSelectionRange):new _.Range(C.lineNumber,f.startColumn,C.lineNumber,f.endColumn);if(v.length>1){let S=w;for(const{originSelectionRange:L}of v)L&&(S=_.Range.plusRange(S,L));this.addDecoration(S,new I.MarkdownString().appendText(t.localize(985,"Click to show {0} definitions.",v.length)))}else{const S=v[0];if(!S.uri)return;this.textModelResolverService.createModelReference(S.uri).then(L=>{if(!L.object||!L.object.textEditorModel){L.dispose();return}const{object:{textEditorModel:D}}=L,{startLineNumber:T}=S.range;if(T<1||T>D.getLineCount()){L.dispose();return}const M=this.getPreviewValue(D,T,S),A=this.languageService.guessLanguageIdByFilepathOrFirstLine(D.uri);this.addDecoration(w,M?new I.MarkdownString().appendCodeblock(A||"",M):void 0),L.dispose()})}}getPreviewValue(C,f,h){let v=h.range;return v.endLineNumber-v.startLineNumber>=a.MAX_SOURCE_PREVIEW_LINES&&(v=this.getPreviewRangeBasedOnIndentation(C,f)),this.stripIndentationFromPreviewRange(C,f,v)}stripIndentationFromPreviewRange(C,f,h){let w=C.getLineFirstNonWhitespaceColumn(f);for(let L=f+1;L{const v=!f&&this.editor.getOption(89)&&!this.isInPeekEditor(h);return new s.DefinitionAction({openToSide:f,openInPeek:v,muteMessage:!0},{title:{value:"",original:""},id:"",precondition:void 0}).run(h)})}isInPeekEditor(C){const f=C.get(i.IContextKeyService);return o.PeekContext.inPeekEditor.getValue(f)}dispose(){this.toUnhook.dispose(),this.toUnhookForKeyboard.dispose()}};e.GotoDefinitionAtPositionEditorContribution=r,e.GotoDefinitionAtPositionEditorContribution=r=a=ke([ce(1,p.ITextModelService),ce(2,b.ILanguageService),ce(3,c.ILanguageFeaturesService)],r),(0,m.registerEditorContribution)(r.ID,r,2)}),define(ne[845],se([1,0,5,13,14,8,2,48,4,17,266,157,287,134,427,84,3,108,59,96]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.MarkerHoverParticipant=e.MarkerHover=void 0;const r=d.$;class u{constructor(v,w,S){this.owner=v,this.range=w,this.marker=S}isValidForHoverAnchor(v){return v.type===1&&this.range.startColumn<=v.range.startColumn&&this.range.endColumn>=v.range.endColumn}}e.MarkerHover=u;const C={type:1,filter:{include:t.CodeActionKind.QuickFix},triggerAction:t.CodeActionTriggerSource.QuickFixHover};let f=class{constructor(v,w,S,L){this._editor=v,this._markerDecorationsService=w,this._openerService=S,this._languageFeaturesService=L,this.hoverOrdinal=1,this.recentMarkerCodeActionsInfo=void 0}computeSync(v,w){if(!this._editor.hasModel()||v.type!==1&&!v.supportsMarkerHover)return[];const S=this._editor.getModel(),L=v.range.startLineNumber,D=S.getLineMaxColumn(L),T=[];for(const M of w){const A=M.range.startLineNumber===L?M.range.startColumn:1,P=M.range.endLineNumber===L?M.range.endColumn:D,N=this._markerDecorationsService.getMarker(S.uri,M);if(!N)continue;const O=new _.Range(v.range.startLineNumber,A,v.range.startLineNumber,P);T.push(new u(this,O,N))}return T}renderHoverParts(v,w){if(!w.length)return new s.RenderedHoverParts([]);const S=new y.DisposableStore,L=[];w.forEach(T=>{const M=this._renderMarkerHover(T);v.fragment.appendChild(M.hoverElement),L.push(M)});const D=w.length===1?w[0]:w.sort((T,M)=>c.MarkerSeverity.compare(T.marker.severity,M.marker.severity))[0];return this.renderMarkerStatusbar(v,D,S),new s.RenderedHoverParts(L)}_renderMarkerHover(v){const w=new y.DisposableStore,S=r("div.hover-row"),L=d.append(S,r("div.marker.hover-contents")),{source:D,message:T,code:M,relatedInformation:A}=v.marker;this._editor.applyFontInfo(L);const P=d.append(L,r("span"));if(P.style.whiteSpace="pre-wrap",P.innerText=T,D||M)if(M&&typeof M!="string"){const O=r("span");if(D){const V=d.append(O,r("span"));V.innerText=D}const F=d.append(O,r("a.code-link"));F.setAttribute("href",M.target.toString()),w.add(d.addDisposableListener(F,"click",V=>{this._openerService.open(M.target,{allowCommands:!0}),V.preventDefault(),V.stopPropagation()}));const x=d.append(F,r("span"));x.innerText=M.value;const W=d.append(L,O);W.style.opacity="0.6",W.style.paddingLeft="6px"}else{const O=d.append(L,r("span"));O.style.opacity="0.6",O.style.paddingLeft="6px",O.innerText=D&&M?`${D}(${M})`:D||`(${M})`}if((0,k.isNonEmptyArray)(A))for(const{message:O,resource:F,startLineNumber:x,startColumn:W}of A){const V=d.append(L,r("div"));V.style.marginTop="8px";const q=d.append(V,r("a"));q.innerText=`${(0,m.basename)(F)}(${x}, ${W}): `,q.style.cursor="pointer",w.add(d.addDisposableListener(q,"click",z=>{if(z.stopPropagation(),z.preventDefault(),this._openerService){const U={selection:{startLineNumber:x,startColumn:W}};this._openerService.open(F,{fromUserGesture:!0,editorOptions:U}).catch(E.onUnexpectedError)}}));const H=d.append(V,r("span"));H.innerText=O,this._editor.applyFontInfo(H)}return{hoverPart:v,hoverElement:S,dispose:()=>w.dispose()}}renderMarkerStatusbar(v,w,S){if(w.marker.severity===c.MarkerSeverity.Error||w.marker.severity===c.MarkerSeverity.Warning||w.marker.severity===c.MarkerSeverity.Info){const L=i.MarkerController.get(this._editor);L&&v.statusBar.addAction({label:g.localize(1040,"View Problem"),commandId:i.NextMarkerAction.ID,run:()=>{v.hide(),L.showAtMarker(w.marker),this._editor.focus()}})}if(!this._editor.getOption(92)){const L=v.statusBar.append(r("div"));this.recentMarkerCodeActionsInfo&&(c.IMarkerData.makeKey(this.recentMarkerCodeActionsInfo.marker)===c.IMarkerData.makeKey(w.marker)?this.recentMarkerCodeActionsInfo.hasCodeActions||(L.textContent=g.localize(1041,"No quick fixes available")):this.recentMarkerCodeActionsInfo=void 0);const D=this.recentMarkerCodeActionsInfo&&!this.recentMarkerCodeActionsInfo.hasCodeActions?y.Disposable.None:(0,I.disposableTimeout)(()=>L.textContent=g.localize(1042,"Checking for quick fixes..."),200,S);L.textContent||(L.textContent="\xA0");const T=this.getCodeActions(w.marker);S.add((0,y.toDisposable)(()=>T.cancel())),T.then(M=>{if(D.dispose(),this.recentMarkerCodeActionsInfo={marker:w.marker,hasCodeActions:M.validActions.length>0},!this.recentMarkerCodeActionsInfo.hasCodeActions){M.dispose(),L.textContent=g.localize(1043,"No quick fixes available");return}L.style.display="none";let A=!1;S.add((0,y.toDisposable)(()=>{A||M.dispose()})),v.statusBar.addAction({label:g.localize(1044,"Quick Fix..."),commandId:n.quickFixCommandId,run:P=>{A=!0;const N=o.CodeActionController.get(this._editor),O=d.getDomNodePagePosition(P);v.hide(),N?.showCodeActions(C,M,{x:O.left,y:O.top,width:O.width,height:O.height})}})},E.onUnexpectedError)}}getCodeActions(v){return(0,I.createCancelablePromise)(w=>(0,n.getCodeActions)(this._languageFeaturesService.codeActionProvider,this._editor.getModel(),new _.Range(v.startLineNumber,v.startColumn,v.endLineNumber,v.endColumn),C,a.Progress.None,w))}};e.MarkerHoverParticipant=f,e.MarkerHoverParticipant=f=ke([ce(1,p.IMarkerDecorationsService),ce(2,l.IOpenerService),ce(3,b.ILanguageFeaturesService)],f)}),define(ne[430],se([1,0,5,41,18,193,4,78,291,158,29,24,12,58,7,50]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.showGoToContextMenu=g,e.goToDefinitionWithLocation=c;async function g(l,a,r,u){const C=l.get(m.ITextModelService),f=l.get(t.IContextMenuService),h=l.get(n.ICommandService),v=l.get(i.IInstantiationService),w=l.get(s.INotificationService);if(await u.item.resolve(I.CancellationToken.None),!u.part.location)return;const S=u.part.location,L=[],D=new Set(p.MenuRegistry.getMenuItems(p.MenuId.EditorContext).map(M=>(0,p.isIMenuItem)(M)?M.command.id:(0,E.generateUuid)()));for(const M of _.SymbolNavigationAction.all())D.has(M.desc.id)&&L.push(new k.Action(M.desc.id,p.MenuItemAction.label(M.desc,{renderShortTitle:!0}),void 0,!0,async()=>{const A=await C.createModelReference(S.uri);try{const P=new _.SymbolNavigationAnchor(A.object.textEditorModel,y.Range.getStartPosition(S.range)),N=u.item.anchor.range;await v.invokeFunction(M.runEditorCommand.bind(M),a,P,N)}finally{A.dispose()}}));if(u.part.command){const{command:M}=u.part;L.push(new k.Separator),L.push(new k.Action(M.id,M.title,void 0,!0,async()=>{try{await h.executeCommand(M.id,...M.arguments??[])}catch(A){w.notify({severity:s.Severity.Error,source:u.item.provider.displayName,message:A})}}))}const T=a.getOption(128);f.showContextMenu({domForShadowRoot:T?a.getDomNode()??void 0:void 0,getAnchor:()=>{const M=d.getDomNodePagePosition(r);return{x:M.left,y:M.top+M.height+8}},getActions:()=>L,onHide:()=>{a.focus()},autoSelectFirstItem:!0})}async function c(l,a,r,u){const f=await l.get(m.ITextModelService).createModelReference(u.uri);await r.invokeWithinContext(async h=>{const v=a.hasSideBySideModifier,w=h.get(o.IContextKeyService),S=b.PeekContext.inPeekEditor.getValue(w),L=!v&&r.getOption(89)&&!S;return new _.DefinitionAction({openToSide:v,openInPeek:L,muteMessage:!0},{title:{value:"",original:""},id:"",precondition:void 0}).run(h,new _.SymbolNavigationAnchor(f.object.textEditorModel,y.Range.getStartPosition(u.range)),y.Range.lift(u.range))}),f.dispose()}}),define(ne[431],se([1,0,5,13,14,18,8,2,45,19,22,185,143,37,75,4,27,40,35,79,17,78,209,377,430,24,49,7,50,32,25]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T){"use strict";var M;Object.defineProperty(e,"__esModule",{value:!0}),e.InlayHintsController=e.RenderedInlayHintLabelPart=void 0;class A{constructor(){this._entries=new _.LRUCache(50)}get(V){const q=A._key(V);return this._entries.get(q)}set(V,q){const H=A._key(V);this._entries.set(H,q)}static _key(V){return`${V.uri.toString()}/${V.getVersionId()}`}}const P=(0,S.createDecorator)("IInlayHintsCache");(0,w.registerSingleton)(P,A,1);class N{constructor(V,q){this.item=V,this.index=q}get part(){const V=this.item.hint.label;return typeof V=="string"?{label:V}:V[this.index]}}e.RenderedInlayHintLabelPart=N;class O{constructor(V,q){this.part=V,this.hasTriggerModifier=q}}let F=class{static{M=this}static{this.ID="editor.contrib.InlayHints"}static{this._MAX_DECORATORS=1500}static{this._MAX_LABEL_LEN=43}static get(V){return V.getContribution(M.ID)??void 0}constructor(V,q,H,z,U,j,Y){this._editor=V,this._languageFeaturesService=q,this._inlayHintsCache=z,this._commandService=U,this._notificationService=j,this._instaService=Y,this._disposables=new m.DisposableStore,this._sessionDisposables=new m.DisposableStore,this._decorationsMetadata=new Map,this._ruleFactory=new n.DynamicCssRules(this._editor),this._activeRenderMode=0,this._debounceInfo=H.for(q.inlayHintsProvider,"InlayHint",{min:25}),this._disposables.add(q.inlayHintsProvider.onDidChange(()=>this._update())),this._disposables.add(V.onDidChangeModel(()=>this._update())),this._disposables.add(V.onDidChangeModelLanguage(()=>this._update())),this._disposables.add(V.onDidChangeConfiguration(G=>{G.hasChanged(142)&&this._update()})),this._update()}dispose(){this._sessionDisposables.dispose(),this._removeAllDecorations(),this._disposables.dispose()}_update(){this._sessionDisposables.clear(),this._removeAllDecorations();const V=this._editor.getOption(142);if(V.enabled==="off")return;const q=this._editor.getModel();if(!q||!this._languageFeaturesService.inlayHintsProvider.has(q))return;if(V.enabled==="on")this._activeRenderMode=0;else{let Y,G;V.enabled==="onUnlessPressed"?(Y=0,G=1):(Y=1,G=0),this._activeRenderMode=Y,this._sessionDisposables.add(d.ModifierKeyEmitter.getInstance().event(K=>{if(!this._editor.hasModel())return;const R=K.altKey&&K.ctrlKey&&!(K.shiftKey||K.metaKey)?G:Y;if(R!==this._activeRenderMode){this._activeRenderMode=R;const J=this._editor.getModel(),ie=this._copyInlayHintsWithCurrentAnchor(J);this._updateHintsDecorators([J.getFullModelRange()],ie),j.schedule(0)}}))}const H=this._inlayHintsCache.get(q);H&&this._updateHintsDecorators([q.getFullModelRange()],H),this._sessionDisposables.add((0,m.toDisposable)(()=>{q.isDisposed()||this._cacheHintsForFastRestore(q)}));let z;const U=new Set,j=new I.RunOnceScheduler(async()=>{const Y=Date.now();z?.dispose(!0),z=new E.CancellationTokenSource;const G=q.onWillDispose(()=>z?.cancel());try{const K=z.token,R=await f.InlayHintsFragments.create(this._languageFeaturesService.inlayHintsProvider,q,this._getHintsRanges(),K);if(j.delay=this._debounceInfo.update(q,Date.now()-Y),K.isCancellationRequested){R.dispose();return}for(const J of R.provider)typeof J.onDidChangeInlayHints=="function"&&!U.has(J)&&(U.add(J),this._sessionDisposables.add(J.onDidChangeInlayHints(()=>{j.isScheduled()||j.schedule()})));this._sessionDisposables.add(R),this._updateHintsDecorators(R.ranges,R.items),this._cacheHintsForFastRestore(q)}catch(K){(0,y.onUnexpectedError)(K)}finally{z.dispose(),G.dispose()}},this._debounceInfo.get(q));this._sessionDisposables.add(j),this._sessionDisposables.add((0,m.toDisposable)(()=>z?.dispose(!0))),j.schedule(0),this._sessionDisposables.add(this._editor.onDidScrollChange(Y=>{(Y.scrollTopChanged||!j.isScheduled())&&j.schedule()})),this._sessionDisposables.add(this._editor.onDidChangeModelContent(Y=>{z?.cancel();const G=Math.max(j.delay,1250);j.schedule(G)})),this._sessionDisposables.add(this._installDblClickGesture(()=>j.schedule(0))),this._sessionDisposables.add(this._installLinkGesture()),this._sessionDisposables.add(this._installContextMenu())}_installLinkGesture(){const V=new m.DisposableStore,q=V.add(new C.ClickLinkGesture(this._editor)),H=new m.DisposableStore;return V.add(H),V.add(q.onMouseMoveOrRelevantKeyDown(z=>{const[U]=z,j=this._getInlayHintLabelPart(U),Y=this._editor.getModel();if(!j||!Y){H.clear();return}const G=new E.CancellationTokenSource;H.add((0,m.toDisposable)(()=>G.dispose(!0))),j.item.resolve(G.token),this._activeInlayHintPart=j.part.command||j.part.location?new O(j,U.hasTriggerModifier):void 0;const K=Y.validatePosition(j.item.hint.position).lineNumber,R=new s.Range(K,1,K,Y.getLineMaxColumn(K)),J=this._getInlineHintsForRange(R);this._updateHintsDecorators([R],J),H.add((0,m.toDisposable)(()=>{this._activeInlayHintPart=void 0,this._updateHintsDecorators([R],J)}))})),V.add(q.onCancel(()=>H.clear())),V.add(q.onExecute(async z=>{const U=this._getInlayHintLabelPart(z);if(U){const j=U.part;j.location?this._instaService.invokeFunction(h.goToDefinitionWithLocation,z,this._editor,j.location):g.Command.is(j.command)&&await this._invokeCommand(j.command,U.item)}})),V}_getInlineHintsForRange(V){const q=new Set;for(const H of this._decorationsMetadata.values())V.containsRange(H.item.anchor.range)&&q.add(H.item);return Array.from(q)}_installDblClickGesture(V){return this._editor.onMouseUp(async q=>{if(q.event.detail!==2)return;const H=this._getInlayHintLabelPart(q);if(H&&(q.event.preventDefault(),await H.item.resolve(E.CancellationToken.None),(0,k.isNonEmptyArray)(H.item.hint.textEdits))){const z=H.item.hint.textEdits.map(U=>i.EditOperation.replace(s.Range.lift(U.range),U.text));this._editor.executeEdits("inlayHint.default",z),V()}})}_installContextMenu(){return this._editor.onContextMenu(async V=>{if(!(0,d.isHTMLElement)(V.event.target))return;const q=this._getInlayHintLabelPart(V);q&&await this._instaService.invokeFunction(h.showGoToContextMenu,this._editor,V.event.target,q)})}_getInlayHintLabelPart(V){if(V.target.type!==6)return;const q=V.target.detail.injectedText?.options;if(q instanceof l.ModelDecorationInjectedTextOptions&&q?.attachedData instanceof N)return q.attachedData}async _invokeCommand(V,q){try{await this._commandService.executeCommand(V.id,...V.arguments??[])}catch(H){this._notificationService.notify({severity:L.Severity.Error,source:q.provider.displayName,message:H})}}_cacheHintsForFastRestore(V){const q=this._copyInlayHintsWithCurrentAnchor(V);this._inlayHintsCache.set(V,q)}_copyInlayHintsWithCurrentAnchor(V){const q=new Map;for(const[H,z]of this._decorationsMetadata){if(q.has(z.item))continue;const U=V.getDecorationRange(H);if(U){const j=new f.InlayHintAnchor(U,z.item.anchor.direction),Y=z.item.with({anchor:j});q.set(z.item,Y)}}return Array.from(q.values())}_getHintsRanges(){const q=this._editor.getModel(),H=this._editor.getVisibleRangesPlusViewportAboveBelow(),z=[];for(const U of H.sort(s.Range.compareRangesUsingStarts)){const j=q.validateRange(new s.Range(U.startLineNumber-30,U.startColumn,U.endLineNumber+30,U.endColumn));z.length===0||!s.Range.areIntersectingOrTouching(z[z.length-1],j)?z.push(j):z[z.length-1]=s.Range.plusRange(z[z.length-1],j)}return z}_updateHintsDecorators(V,q){const H=[],z=(he,pe,ae,ee,de)=>{const ge={content:ae,inlineClassNameAffectsLetterSpacing:!0,inlineClassName:pe.className,cursorStops:ee,attachedData:de};H.push({item:he,classNameRef:pe,decoration:{range:he.anchor.range,options:{description:"InlayHint",showIfCollapsed:he.anchor.range.isEmpty(),collapseOnReplaceEdit:!he.anchor.range.isEmpty(),stickiness:0,[he.anchor.direction]:this._activeRenderMode===0?ge:void 0}}})},U=(he,pe)=>{const ae=this._ruleFactory.createClassNameRef({width:`${j/3|0}px`,display:"inline-block"});z(he,ae,"\u200A",pe?c.InjectedTextCursorStops.Right:c.InjectedTextCursorStops.None)},{fontSize:j,fontFamily:Y,padding:G,isUniform:K}=this._getLayoutInfo(),R="--code-editorInlayHintsFontFamily";this._editor.getContainerDomNode().style.setProperty(R,Y);let J={line:0,totalLen:0};for(const he of q){if(J.line!==he.anchor.range.startLineNumber&&(J={line:he.anchor.range.startLineNumber,totalLen:0}),J.totalLen>M._MAX_LABEL_LEN)continue;he.hint.paddingLeft&&U(he,!1);const pe=typeof he.hint.label=="string"?[{label:he.hint.label}]:he.hint.label;for(let ae=0;ae0&&(B=B.slice(0,-Q)+"\u2026",$=!0),z(he,this._ruleFactory.createClassNameRef(X),x(B),ge&&!he.hint.paddingRight?c.InjectedTextCursorStops.Right:c.InjectedTextCursorStops.None,new N(he,ae)),$)break}if(he.hint.paddingRight&&U(he,!0),H.length>M._MAX_DECORATORS)break}const ie=[];for(const[he,pe]of this._decorationsMetadata){const ae=this._editor.getModel()?.getDecorationRange(he);ae&&V.some(ee=>ee.containsRange(ae))&&(ie.push(he),pe.classNameRef.dispose(),this._decorationsMetadata.delete(he))}const ue=o.StableEditorScrollState.capture(this._editor);this._editor.changeDecorations(he=>{const pe=he.deltaDecorations(ie,H.map(ae=>ae.decoration));for(let ae=0;aeH)&&(U=H);const j=V.fontFamily||z;return{fontSize:U,fontFamily:j,padding:q,isUniform:!q&&j===z&&U===H}}_removeAllDecorations(){this._editor.removeDecorations(Array.from(this._decorationsMetadata.keys()));for(const V of this._decorationsMetadata.values())V.classNameRef.dispose();this._decorationsMetadata.clear()}};e.InlayHintsController=F,e.InlayHintsController=F=M=ke([ce(1,r.ILanguageFeaturesService),ce(2,a.ILanguageFeatureDebounceService),ce(3,P),ce(4,v.ICommandService),ce(5,L.INotificationService),ce(6,S.IInstantiationService)],F);function x(W){return W.replace(/[ \t]/g,"\xA0")}v.CommandsRegistry.registerCommand("_executeInlayHintProvider",async(W,...V)=>{const[q,H]=V;(0,b.assertType)(p.URI.isUri(q)),(0,b.assertType)(s.Range.isIRange(H));const{inlayHintsProvider:z}=W.get(r.ILanguageFeaturesService),U=await W.get(u.ITextModelService).createModelReference(q);try{const j=await f.InlayHintsFragments.create(z,U.object.textEditorModel,[s.Range.lift(H)],E.CancellationToken.None),Y=j.items.map(G=>G.hint);return setTimeout(()=>j.dispose(),0),Y}finally{U.dispose()}})}),define(ne[432],se([1,0,14,57,9,35,84,43,78,410,217,431,28,59,17,3,16,377,13,31,118,24]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlayHintsHover=void 0;class C extends y.HoverForeignElementAnchor{constructor(v,w,S,L){super(10,w,v.item.anchor.range,S,L,!0),this.part=v}}let f=class extends p.MarkdownHoverParticipant{constructor(v,w,S,L,D,T,M,A,P){super(v,w,S,T,A,L,D,P),this._resolverService=M,this.hoverOrdinal=6}suggestHoverAnchor(v){if(!n.InlayHintsController.get(this._editor)||v.target.type!==6)return null;const S=v.target.detail.injectedText?.options;return S instanceof E.ModelDecorationInjectedTextOptions&&S.attachedData instanceof n.RenderedInlayHintLabelPart?new C(S.attachedData,this,v.event.posx,v.event.posy):null}computeSync(){return[]}computeAsync(v,w,S){return v instanceof C?new d.AsyncIterableObject(async L=>{const{part:D}=v;if(await D.item.resolve(S),S.isCancellationRequested)return;let T;typeof D.item.hint.tooltip=="string"?T=new k.MarkdownString().appendText(D.item.hint.tooltip):D.item.hint.tooltip&&(T=D.item.hint.tooltip),T&&L.emitOne(new p.MarkdownHover(this,v.range,[T],!1,0)),(0,l.isNonEmptyArray)(D.item.hint.textEdits)&&L.emitOne(new p.MarkdownHover(this,v.range,[new k.MarkdownString().appendText((0,s.localize)(1065,"Double-click to insert"))],!1,10001));let M;if(typeof D.part.tooltip=="string"?M=new k.MarkdownString().appendText(D.part.tooltip):D.part.tooltip&&(M=D.part.tooltip),M&&L.emitOne(new p.MarkdownHover(this,v.range,[M],!1,1)),D.part.location||D.part.command){let P;const O=this._editor.getOption(78)==="altKey"?g.isMacintosh?(0,s.localize)(1066,"cmd + click"):(0,s.localize)(1067,"ctrl + click"):g.isMacintosh?(0,s.localize)(1068,"option + click"):(0,s.localize)(1069,"alt + click");D.part.location&&D.part.command?P=new k.MarkdownString().appendText((0,s.localize)(1070,"Go to Definition ({0}), right click for more",O)):D.part.location?P=new k.MarkdownString().appendText((0,s.localize)(1071,"Go to Definition ({0})",O)):D.part.command&&(P=new k.MarkdownString(`[${(0,s.localize)(1072,"Execute Command")}](${(0,c.asCommandLink)(D.part.command)} "${D.part.command.title}") (${O})`,{isTrusted:!0})),P&&L.emitOne(new p.MarkdownHover(this,v.range,[P],!1,1e4))}const A=await this._resolveInlayHintLabelPartHover(D,S);for await(const P of A)L.emitOne(P)}):d.AsyncIterableObject.EMPTY}async _resolveInlayHintLabelPartHover(v,w){if(!v.part.location)return d.AsyncIterableObject.EMPTY;const{uri:S,range:L}=v.part.location,D=await this._resolverService.createModelReference(S);try{const T=D.object.textEditorModel;return this._languageFeaturesService.hoverProvider.has(T)?(0,b.getHoverProviderResultsAsAsyncIterable)(this._languageFeaturesService.hoverProvider,T,new I.Position(L.startLineNumber,L.startColumn),w).filter(M=>!(0,k.isEmptyMarkdownString)(M.hover.contents)).map(M=>new p.MarkdownHover(this,v.item.anchor.range,M.hover.contents,!1,2+M.ordinal)):d.AsyncIterableObject.EMPTY}finally{D.dispose()}}};e.InlayHintsHover=f,e.InlayHintsHover=f=ke([ce(1,m.ILanguageService),ce(2,t.IOpenerService),ce(3,a.IKeybindingService),ce(4,r.IHoverService),ce(5,o.IConfigurationService),ce(6,_.ITextModelService),ce(7,i.ILanguageFeaturesService),ce(8,u.ICommandService)],f)}),define(ne[846],se([1,0,84,2,391,35,9,4,5,217,288,432,8]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RenderedContentHover=void 0;class t extends k.Disposable{constructor(c,l,a,r,u,C){super();const f=l.anchor,h=l.hoverParts;this._renderedHoverParts=this._register(new s(c,a,h,C,u));const{showAtPosition:v,showAtSecondaryPosition:w}=t.computeHoverPositions(c,f.range,h);this.shouldAppearBeforeContent=h.some(S=>S.isBeforeContent),this.showAtPosition=v,this.showAtSecondaryPosition=w,this.initialMousePosX=f.initialMousePosX,this.initialMousePosY=f.initialMousePosY,this.shouldFocus=r.shouldFocus,this.source=r.source}get domNode(){return this._renderedHoverParts.domNode}get domNodeHasChildren(){return this._renderedHoverParts.domNodeHasChildren}get focusedHoverPartIndex(){return this._renderedHoverParts.focusedHoverPartIndex}async updateHoverVerbosityLevel(c,l,a){this._renderedHoverParts.updateHoverVerbosityLevel(c,l,a)}isColorPickerVisible(){return this._renderedHoverParts.isColorPickerVisible()}static computeHoverPositions(c,l,a){let r=1;if(c.hasModel()){const w=c._getViewModel(),S=w.coordinatesConverter,L=S.convertModelRangeToViewRange(l),D=w.getLineMinColumn(L.startLineNumber),T=new y.Position(L.startLineNumber,D);r=S.convertViewPositionToModelPosition(T).column}const u=l.startLineNumber;let C=l.startColumn,f;for(const w of a){const S=w.range,L=S.startLineNumber===u,D=S.endLineNumber===u;if(L&&D){const M=S.startColumn,A=Math.min(C,M);C=Math.max(A,r)}w.forceShowAtRange&&(f=S)}let h,v;if(f){const w=f.getStartPosition();h=w,v=w}else h=l.getStartPosition(),v=new y.Position(u,C);return{showAtPosition:h,showAtSecondaryPosition:v}}}e.RenderedContentHover=t;class i{constructor(c,l){this._statusBar=l,c.appendChild(this._statusBar.hoverElement)}get hoverElement(){return this._statusBar.hoverElement}get actions(){return this._statusBar.actions}dispose(){this._statusBar.dispose()}}class s extends k.Disposable{static{this._DECORATION_OPTIONS=E.ModelDecorationOptions.register({description:"content-hover-highlight",className:"hoverHighlight"})}constructor(c,l,a,r,u){super(),this._renderedParts=[],this._focusedHoverPartIndex=-1,this._context=u,this._fragment=document.createDocumentFragment(),this._register(this._renderParts(l,a,u,r)),this._register(this._registerListenersOnRenderedParts()),this._register(this._createEditorDecorations(c,a)),this._updateMarkdownAndColorParticipantInfo(l)}_createEditorDecorations(c,l){if(l.length===0)return k.Disposable.None;let a=l[0].range;for(const u of l){const C=u.range;a=m.Range.plusRange(a,C)}const r=c.createDecorationsCollection();return r.set([{range:a,options:s._DECORATION_OPTIONS}]),(0,k.toDisposable)(()=>{r.clear()})}_renderParts(c,l,a,r){const u=new I.EditorHoverStatusBar(r),C={fragment:this._fragment,statusBar:u,...a},f=new k.DisposableStore;for(const v of c){const w=this._renderHoverPartsForParticipant(l,v,C);f.add(w);for(const S of w.renderedHoverParts)this._renderedParts.push({type:"hoverPart",participant:v,hoverPart:S.hoverPart,hoverElement:S.hoverElement})}const h=this._renderStatusBar(this._fragment,u);return h&&(f.add(h),this._renderedParts.push({type:"statusBar",hoverElement:h.hoverElement,actions:h.actions})),(0,k.toDisposable)(()=>{f.dispose()})}_renderHoverPartsForParticipant(c,l,a){const r=c.filter(C=>C.owner===l);return r.length>0?l.renderHoverParts(a,r):new d.RenderedHoverParts([])}_renderStatusBar(c,l){if(l.hasContent)return new i(c,l)}_registerListenersOnRenderedParts(){const c=new k.DisposableStore;return this._renderedParts.forEach((l,a)=>{const r=l.hoverElement;r.tabIndex=0,c.add(_.addDisposableListener(r,_.EventType.FOCUS_IN,u=>{u.stopPropagation(),this._focusedHoverPartIndex=a})),c.add(_.addDisposableListener(r,_.EventType.FOCUS_OUT,u=>{u.stopPropagation(),this._focusedHoverPartIndex=-1}))}),c}_updateMarkdownAndColorParticipantInfo(c){const l=c.find(a=>a instanceof b.MarkdownHoverParticipant&&!(a instanceof n.InlayHintsHover));l&&(this._markdownHoverParticipant=l),this._colorHoverParticipant=c.find(a=>a instanceof p.ColorHoverParticipant)}async updateHoverVerbosityLevel(c,l,a){if(!this._markdownHoverParticipant)return;const r=this._normalizedIndexToMarkdownHoverIndexRange(this._markdownHoverParticipant,l);if(r===void 0)return;const u=await this._markdownHoverParticipant.updateMarkdownHoverVerbosityLevel(c,r,a);u&&(this._renderedParts[l]={type:"hoverPart",participant:this._markdownHoverParticipant,hoverPart:u.hoverPart,hoverElement:u.hoverElement},this._context.onContentsChanged())}isColorPickerVisible(){return this._colorHoverParticipant?.isColorPickerVisible()??!1}_normalizedIndexToMarkdownHoverIndexRange(c,l){const a=this._renderedParts[l];if(!a||a.type!=="hoverPart"||!(a.participant===c))return;const u=this._renderedParts.findIndex(C=>C.type==="hoverPart"&&C.participant===c);if(u===-1)throw new o.BugIndicatingError;return l-u}get domNode(){return this._fragment}get domNodeHasChildren(){return this._fragment.hasChildNodes()}get focusedHoverPartIndex(){return this._focusedHoverPartIndex}}}),define(ne[847],se([1,0,5,2,27,376,84,7,31,690,668,614,6,846,210]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ContentHoverWidgetWrapper=void 0;let s=class extends k.Disposable{constructor(c,l,a){super(),this._editor=c,this._instantiationService=l,this._keybindingService=a,this._currentResult=null,this._onContentsChanged=this._register(new o.Emitter),this.onContentsChanged=this._onContentsChanged.event,this._contentHoverWidget=this._register(this._instantiationService.createInstance(b.ContentHoverWidget,this._editor)),this._participants=this._initializeHoverParticipants(),this._computer=new p.ContentHoverComputer(this._editor,this._participants),this._hoverOperation=this._register(new E.HoverOperation(this._editor,this._computer)),this._registerListeners()}_initializeHoverParticipants(){const c=[];for(const l of y.HoverParticipantRegistry.getAll()){const a=this._instantiationService.createInstance(l,this._editor);c.push(a)}return c.sort((l,a)=>l.hoverOrdinal-a.hoverOrdinal),this._register(this._contentHoverWidget.onDidResize(()=>{this._participants.forEach(l=>l.handleResize?.())})),c}_registerListeners(){this._register(this._hoverOperation.onResult(l=>{if(!this._computer.anchor)return;const a=l.hasLoadingMessage?this._addLoadingMessage(l.value):l.value;this._withResult(new n.HoverResult(this._computer.anchor,a,l.isComplete))}));const c=this._contentHoverWidget.getDomNode();this._register(d.addStandardDisposableListener(c,"keydown",l=>{l.equals(9)&&this.hide()})),this._register(d.addStandardDisposableListener(c,"mouseleave",l=>{this._onMouseLeave(l)})),this._register(I.TokenizationRegistry.onDidChange(()=>{this._contentHoverWidget.position&&this._currentResult&&this._setCurrentResult(this._currentResult)}))}_startShowingOrUpdateHover(c,l,a,r,u){if(!(this._contentHoverWidget.position&&this._currentResult))return c?(this._startHoverOperationIfNecessary(c,l,a,r,!1),!0):!1;const f=this._editor.getOption(60).sticky,h=u&&this._contentHoverWidget.isMouseGettingCloser(u.event.posx,u.event.posy);return f&&h?(c&&this._startHoverOperationIfNecessary(c,l,a,r,!0),!0):c?this._currentResult.anchor.equals(c)?!0:c.canAdoptVisibleHover(this._currentResult.anchor,this._contentHoverWidget.position)?(this._setCurrentResult(this._currentResult.filter(c)),this._startHoverOperationIfNecessary(c,l,a,r,!1),!0):(this._setCurrentResult(null),this._startHoverOperationIfNecessary(c,l,a,r,!1),!0):(this._setCurrentResult(null),!1)}_startHoverOperationIfNecessary(c,l,a,r,u){this._computer.anchor&&this._computer.anchor.equals(c)||(this._hoverOperation.cancel(),this._computer.anchor=c,this._computer.shouldFocus=r,this._computer.source=a,this._computer.insistOnKeepingHoverVisible=u,this._hoverOperation.start(l))}_setCurrentResult(c){let l=c;if(this._currentResult===l)return;l&&l.hoverParts.length===0&&(l=null),this._currentResult=l,this._currentResult?this._showHover(this._currentResult):this._hideHover()}_addLoadingMessage(c){if(!this._computer.anchor)return c;for(const l of this._participants){if(!l.createLoadingMessage)continue;const a=l.createLoadingMessage(this._computer.anchor);if(a)return c.slice(0).concat([a])}return c}_withResult(c){if(this._contentHoverWidget.position&&this._currentResult&&this._currentResult.isComplete||this._setCurrentResult(c),!c.isComplete)return;const r=c.hoverParts.length===0,u=this._computer.insistOnKeepingHoverVisible;r&&u||this._setCurrentResult(c)}_showHover(c){const l=this._getHoverContext();this._renderedContentHover=new t.RenderedContentHover(this._editor,c,this._participants,this._computer,l,this._keybindingService),this._renderedContentHover.domNodeHasChildren?this._contentHoverWidget.show(this._renderedContentHover):this._renderedContentHover.dispose()}_hideHover(){this._contentHoverWidget.hide()}_getHoverContext(){return{hide:()=>{this.hide()},onContentsChanged:()=>{this._onContentsChanged.fire(),this._contentHoverWidget.onContentsChanged()},setMinimumDimensions:r=>{this._contentHoverWidget.setMinimumDimensions(r)}}}showsOrWillShow(c){if(this._contentHoverWidget.isResizing)return!0;const a=this._findHoverAnchorCandidates(c);if(!(a.length>0))return this._startShowingOrUpdateHover(null,0,0,!1,c);const u=a[0];return this._startShowingOrUpdateHover(u,0,0,!1,c)}_findHoverAnchorCandidates(c){const l=[];for(const r of this._participants){if(!r.suggestHoverAnchor)continue;const u=r.suggestHoverAnchor(c);u&&l.push(u)}const a=c.target;switch(a.type){case 6:{l.push(new y.HoverRangeAnchor(0,a.range,c.event.posx,c.event.posy));break}case 7:{const r=this._editor.getOption(50).typicalHalfwidthCharacterWidth/2;if(!(!a.detail.isAfterLines&&typeof a.detail.horizontalDistanceToText=="number"&&a.detail.horizontalDistanceToTextu.priority-r.priority),l}_onMouseLeave(c){const l=this._editor.getDomNode();(!l||!(0,i.isMousePositionWithinElement)(l,c.x,c.y))&&this.hide()}startShowingAtRange(c,l,a,r){this._startShowingOrUpdateHover(new y.HoverRangeAnchor(0,c,void 0,void 0),l,a,r,null)}async updateHoverVerbosityLevel(c,l,a){this._renderedContentHover?.updateHoverVerbosityLevel(c,l,a)}focusedHoverPartIndex(){return this._renderedContentHover?.focusedHoverPartIndex??-1}containsNode(c){return c?this._contentHoverWidget.getDomNode().contains(c):!1}focus(){this._contentHoverWidget.focus()}scrollUp(){this._contentHoverWidget.scrollUp()}scrollDown(){this._contentHoverWidget.scrollDown()}scrollLeft(){this._contentHoverWidget.scrollLeft()}scrollRight(){this._contentHoverWidget.scrollRight()}pageUp(){this._contentHoverWidget.pageUp()}pageDown(){this._contentHoverWidget.pageDown()}goToTop(){this._contentHoverWidget.goToTop()}goToBottom(){this._contentHoverWidget.goToBottom()}hide(){this._computer.anchor=null,this._hoverOperation.cancel(),this._setCurrentResult(null)}getDomNode(){return this._contentHoverWidget.getDomNode()}get isColorPickerVisible(){return this._renderedContentHover?.isColorPickerVisible()??!1}get isVisibleFromKeyboard(){return this._contentHoverWidget.isVisibleFromKeyboard}get isVisible(){return this._contentHoverWidget.isVisible}get isFocused(){return this._contentHoverWidget.isFocused}get isResizing(){return this._contentHoverWidget.isResizing}get widget(){return this._contentHoverWidget}};e.ContentHoverWidgetWrapper=s,e.ContentHoverWidgetWrapper=s=ke([ce(1,m.IInstantiationService),ce(2,_.IKeybindingService)],s)}),define(ne[292],se([1,0,264,2,7,283,31,14,210,847,6,196]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";var n;Object.defineProperty(e,"__esModule",{value:!0}),e.ContentHoverController=void 0;const o=!1;let t=class extends k.Disposable{static{n=this}static{this.ID="editor.contrib.contentHover"}constructor(s,g,c){super(),this._editor=s,this._instantiationService=g,this._keybindingService=c,this._onHoverContentsChanged=this._register(new p.Emitter),this.shouldKeepOpenOnEditorMouseMoveOrLeave=!1,this._listenersStore=new k.DisposableStore,this._hoverState={mouseDown:!1,activatedByDecoratorClick:!1},this._reactToEditorMouseMoveRunner=this._register(new m.RunOnceScheduler(()=>this._reactToEditorMouseMove(this._mouseMoveEvent),0)),this._hookListeners(),this._register(this._editor.onDidChangeConfiguration(l=>{l.hasChanged(60)&&(this._unhookListeners(),this._hookListeners())}))}static get(s){return s.getContribution(n.ID)}_hookListeners(){const s=this._editor.getOption(60);this._hoverSettings={enabled:s.enabled,sticky:s.sticky,hidingDelay:s.hidingDelay},s.enabled?(this._listenersStore.add(this._editor.onMouseDown(g=>this._onEditorMouseDown(g))),this._listenersStore.add(this._editor.onMouseUp(()=>this._onEditorMouseUp())),this._listenersStore.add(this._editor.onMouseMove(g=>this._onEditorMouseMove(g))),this._listenersStore.add(this._editor.onKeyDown(g=>this._onKeyDown(g)))):(this._listenersStore.add(this._editor.onMouseMove(g=>this._onEditorMouseMove(g))),this._listenersStore.add(this._editor.onKeyDown(g=>this._onKeyDown(g)))),this._listenersStore.add(this._editor.onMouseLeave(g=>this._onEditorMouseLeave(g))),this._listenersStore.add(this._editor.onDidChangeModel(()=>{this._cancelScheduler(),this._hideWidgets()})),this._listenersStore.add(this._editor.onDidChangeModelContent(()=>this._cancelScheduler())),this._listenersStore.add(this._editor.onDidScrollChange(g=>this._onEditorScrollChanged(g)))}_unhookListeners(){this._listenersStore.clear()}_cancelScheduler(){this._mouseMoveEvent=void 0,this._reactToEditorMouseMoveRunner.cancel()}_onEditorScrollChanged(s){(s.scrollTopChanged||s.scrollLeftChanged)&&this._hideWidgets()}_onEditorMouseDown(s){this._hoverState.mouseDown=!0,!this._shouldNotHideCurrentHoverWidget(s)&&this._hideWidgets()}_shouldNotHideCurrentHoverWidget(s){return this._isMouseOnContentHoverWidget(s)||this._isContentWidgetResizing()}_isMouseOnContentHoverWidget(s){const g=this._contentWidget?.getDomNode();return g?(0,_.isMousePositionWithinElement)(g,s.event.posx,s.event.posy):!1}_onEditorMouseUp(){this._hoverState.mouseDown=!1}_onEditorMouseLeave(s){this.shouldKeepOpenOnEditorMouseMoveOrLeave||(this._cancelScheduler(),this._shouldNotHideCurrentHoverWidget(s))||o||this._hideWidgets()}_shouldNotRecomputeCurrentHoverWidget(s){const g=this._hoverSettings.sticky,c=(r,u)=>{const C=this._isMouseOnContentHoverWidget(r);return u&&C},l=r=>{const u=this._isMouseOnContentHoverWidget(r),C=this._contentWidget?.isColorPickerVisible??!1;return u&&C},a=(r,u)=>(u&&this._contentWidget?.containsNode(r.event.browserEvent.view?.document.activeElement)&&!r.event.browserEvent.view?.getSelection()?.isCollapsed)??!1;return c(s,g)||l(s)||a(s,g)}_onEditorMouseMove(s){if(this.shouldKeepOpenOnEditorMouseMoveOrLeave||(this._mouseMoveEvent=s,this._contentWidget?.isFocused||this._contentWidget?.isResizing))return;const g=this._hoverSettings.sticky;if(g&&this._contentWidget?.isVisibleFromKeyboard)return;if(this._shouldNotRecomputeCurrentHoverWidget(s)){this._reactToEditorMouseMoveRunner.cancel();return}const l=this._hoverSettings.hidingDelay;if(this._contentWidget?.isVisible&&g&&l>0){this._reactToEditorMouseMoveRunner.isScheduled()||this._reactToEditorMouseMoveRunner.schedule(l);return}this._reactToEditorMouseMove(s)}_reactToEditorMouseMove(s){if(!s)return;const c=s.target.element?.classList.contains("colorpicker-color-decoration"),l=this._editor.getOption(149),a=this._hoverSettings.enabled,r=this._hoverState.activatedByDecoratorClick;if(c&&(l==="click"&&!r||l==="hover"&&!a&&!o||l==="clickAndHover"&&!a&&!r)||!c&&!a&&!r){this._hideWidgets();return}this._tryShowHoverWidget(s)||o||this._hideWidgets()}_tryShowHoverWidget(s){return this._getOrCreateContentWidget().showsOrWillShow(s)}_onKeyDown(s){if(!this._editor.hasModel())return;const g=this._keybindingService.softDispatch(s,this._editor.getDomNode()),c=g.kind===1||g.kind===2&&(g.commandId===d.SHOW_OR_FOCUS_HOVER_ACTION_ID||g.commandId===d.INCREASE_HOVER_VERBOSITY_ACTION_ID||g.commandId===d.DECREASE_HOVER_VERBOSITY_ACTION_ID)&&this._contentWidget?.isVisible;s.keyCode===5||s.keyCode===6||s.keyCode===57||s.keyCode===4||c||this._hideWidgets()}_hideWidgets(){o||this._hoverState.mouseDown&&this._contentWidget?.isColorPickerVisible||E.InlineSuggestionHintsContentWidget.dropDownVisible||(this._hoverState.activatedByDecoratorClick=!1,this._contentWidget?.hide())}_getOrCreateContentWidget(){return this._contentWidget||(this._contentWidget=this._instantiationService.createInstance(b.ContentHoverWidgetWrapper,this._editor),this._listenersStore.add(this._contentWidget.onContentsChanged(()=>this._onHoverContentsChanged.fire()))),this._contentWidget}showContentHover(s,g,c,l,a=!1){this._hoverState.activatedByDecoratorClick=a,this._getOrCreateContentWidget().startShowingAtRange(s,g,c,l)}_isContentWidgetResizing(){return this._contentWidget?.widget.isResizing||!1}focusedHoverPartIndex(){return this._getOrCreateContentWidget().focusedHoverPartIndex()}updateHoverVerbosityLevel(s,g,c){this._getOrCreateContentWidget().updateHoverVerbosityLevel(s,g,c)}focus(){this._contentWidget?.focus()}scrollUp(){this._contentWidget?.scrollUp()}scrollDown(){this._contentWidget?.scrollDown()}scrollLeft(){this._contentWidget?.scrollLeft()}scrollRight(){this._contentWidget?.scrollRight()}pageUp(){this._contentWidget?.pageUp()}pageDown(){this._contentWidget?.pageDown()}goToTop(){this._contentWidget?.goToTop()}goToBottom(){this._contentWidget?.goToBottom()}get isColorPickerVisible(){return this._contentWidget?.isColorPickerVisible}get isHoverVisible(){return this._contentWidget?.isVisible}dispose(){super.dispose(),this._unhookListeners(),this._listenersStore.dispose(),this._contentWidget?.dispose()}};e.ContentHoverController=t,e.ContentHoverController=t=n=ke([ce(1,I.IInstantiationService),ce(2,y.IKeybindingService)],t)}),define(ne[848],se([1,0,2,15,4,422,288,292,84]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ColorContribution=void 0;class b extends d.Disposable{static{this.ID="editor.contrib.colorContribution"}constructor(n){super(),this._editor=n,this._register(n.onMouseDown(o=>this.onMouseDown(o)))}dispose(){super.dispose()}onMouseDown(n){const o=this._editor.getOption(149);if(o!=="click"&&o!=="clickAndHover")return;const t=n.target;if(t.type!==6||!t.detail.injectedText||t.detail.injectedText.options.attachedData!==E.ColorDecorationInjectedTextMarker||!t.range)return;const i=this._editor.getContribution(m.ContentHoverController.ID);if(i&&!i.isColorPickerVisible){const s=new I.Range(t.range.startLineNumber,t.range.startColumn+1,t.range.endLineNumber,t.range.endColumn+1);i.showContentHover(s,1,0,!1,!0)}}}e.ColorContribution=b,(0,k.registerEditorContribution)(b.ID,b,2),_.HoverParticipantRegistry.register(y.ColorHoverParticipant)}),define(ne[849],se([1,0,264,72,15,4,20,429,292,27,3,196]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DecreaseHoverVerbosityLevel=e.IncreaseHoverVerbosityLevel=e.GoToBottomHoverAction=e.GoToTopHoverAction=e.PageDownHoverAction=e.PageUpHoverAction=e.ScrollRightHoverAction=e.ScrollLeftHoverAction=e.ScrollDownHoverAction=e.ScrollUpHoverAction=e.ShowDefinitionPreviewHoverAction=e.ShowOrFocusHoverAction=void 0;var n;(function(h){h.NoAutoFocus="noAutoFocus",h.FocusIfVisible="focusIfVisible",h.AutoFocusImmediately="autoFocusImmediately"})(n||(n={}));class o extends I.EditorAction{constructor(){super({id:d.SHOW_OR_FOCUS_HOVER_ACTION_ID,label:p.localize(1008,"Show or Focus Hover"),metadata:{description:p.localize2(1021,"Show or focus the editor hover which shows documentation, references, and other content for a symbol at the current cursor position."),args:[{name:"args",schema:{type:"object",properties:{focus:{description:"Controls if and when the hover should take focus upon being triggered by this action.",enum:[n.NoAutoFocus,n.FocusIfVisible,n.AutoFocusImmediately],enumDescriptions:[p.localize(1009,"The hover will not automatically take focus."),p.localize(1010,"The hover will take focus only if it is already visible."),p.localize(1011,"The hover will automatically take focus when it appears.")],default:n.FocusIfVisible}}}}]},alias:"Show or Focus Hover",precondition:void 0,kbOpts:{kbExpr:y.EditorContextKeys.editorTextFocus,primary:(0,k.KeyChord)(2089,2087),weight:100}})}run(v,w,S){if(!w.hasModel())return;const L=_.ContentHoverController.get(w);if(!L)return;const D=S?.focus;let T=n.FocusIfVisible;Object.values(n).includes(D)?T=D:typeof D=="boolean"&&D&&(T=n.AutoFocusImmediately);const M=P=>{const N=w.getPosition(),O=new E.Range(N.lineNumber,N.column,N.lineNumber,N.column);L.showContentHover(O,1,1,P)},A=w.getOption(2)===2;L.isHoverVisible?T!==n.NoAutoFocus?L.focus():M(A):M(A||T===n.AutoFocusImmediately)}}e.ShowOrFocusHoverAction=o;class t extends I.EditorAction{constructor(){super({id:d.SHOW_DEFINITION_PREVIEW_HOVER_ACTION_ID,label:p.localize(1012,"Show Definition Preview Hover"),alias:"Show Definition Preview Hover",precondition:void 0,metadata:{description:p.localize2(1022,"Show the definition preview hover in the editor.")}})}run(v,w){const S=_.ContentHoverController.get(w);if(!S)return;const L=w.getPosition();if(!L)return;const D=new E.Range(L.lineNumber,L.column,L.lineNumber,L.column),T=m.GotoDefinitionAtPositionEditorContribution.get(w);if(!T)return;T.startFindDefinitionFromCursor(L).then(()=>{S.showContentHover(D,1,1,!0)})}}e.ShowDefinitionPreviewHoverAction=t;class i extends I.EditorAction{constructor(){super({id:d.SCROLL_UP_HOVER_ACTION_ID,label:p.localize(1013,"Scroll Up Hover"),alias:"Scroll Up Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:16,weight:100},metadata:{description:p.localize2(1023,"Scroll up the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.scrollUp()}}e.ScrollUpHoverAction=i;class s extends I.EditorAction{constructor(){super({id:d.SCROLL_DOWN_HOVER_ACTION_ID,label:p.localize(1014,"Scroll Down Hover"),alias:"Scroll Down Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:18,weight:100},metadata:{description:p.localize2(1024,"Scroll down the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.scrollDown()}}e.ScrollDownHoverAction=s;class g extends I.EditorAction{constructor(){super({id:d.SCROLL_LEFT_HOVER_ACTION_ID,label:p.localize(1015,"Scroll Left Hover"),alias:"Scroll Left Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:15,weight:100},metadata:{description:p.localize2(1025,"Scroll left the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.scrollLeft()}}e.ScrollLeftHoverAction=g;class c extends I.EditorAction{constructor(){super({id:d.SCROLL_RIGHT_HOVER_ACTION_ID,label:p.localize(1016,"Scroll Right Hover"),alias:"Scroll Right Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:17,weight:100},metadata:{description:p.localize2(1026,"Scroll right the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.scrollRight()}}e.ScrollRightHoverAction=c;class l extends I.EditorAction{constructor(){super({id:d.PAGE_UP_HOVER_ACTION_ID,label:p.localize(1017,"Page Up Hover"),alias:"Page Up Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:11,secondary:[528],weight:100},metadata:{description:p.localize2(1027,"Page up the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.pageUp()}}e.PageUpHoverAction=l;class a extends I.EditorAction{constructor(){super({id:d.PAGE_DOWN_HOVER_ACTION_ID,label:p.localize(1018,"Page Down Hover"),alias:"Page Down Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:12,secondary:[530],weight:100},metadata:{description:p.localize2(1028,"Page down the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.pageDown()}}e.PageDownHoverAction=a;class r extends I.EditorAction{constructor(){super({id:d.GO_TO_TOP_HOVER_ACTION_ID,label:p.localize(1019,"Go To Top Hover"),alias:"Go To Bottom Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:14,secondary:[2064],weight:100},metadata:{description:p.localize2(1029,"Go to the top of the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.goToTop()}}e.GoToTopHoverAction=r;class u extends I.EditorAction{constructor(){super({id:d.GO_TO_BOTTOM_HOVER_ACTION_ID,label:p.localize(1020,"Go To Bottom Hover"),alias:"Go To Bottom Hover",precondition:y.EditorContextKeys.hoverFocused,kbOpts:{kbExpr:y.EditorContextKeys.hoverFocused,primary:13,secondary:[2066],weight:100},metadata:{description:p.localize2(1030,"Go to the bottom of the editor hover.")}})}run(v,w){const S=_.ContentHoverController.get(w);S&&S.goToBottom()}}e.GoToBottomHoverAction=u;class C extends I.EditorAction{constructor(){super({id:d.INCREASE_HOVER_VERBOSITY_ACTION_ID,label:d.INCREASE_HOVER_VERBOSITY_ACTION_LABEL,alias:"Increase Hover Verbosity Level",precondition:y.EditorContextKeys.hoverVisible})}run(v,w,S){const L=_.ContentHoverController.get(w);if(!L)return;const D=S?.index!==void 0?S.index:L.focusedHoverPartIndex();L.updateHoverVerbosityLevel(b.HoverVerbosityAction.Increase,D,S?.focus)}}e.IncreaseHoverVerbosityLevel=C;class f extends I.EditorAction{constructor(){super({id:d.DECREASE_HOVER_VERBOSITY_ACTION_ID,label:d.DECREASE_HOVER_VERBOSITY_ACTION_LABEL,alias:"Decrease Hover Verbosity Level",precondition:y.EditorContextKeys.hoverVisible})}run(v,w,S){const L=_.ContentHoverController.get(w);if(!L)return;const D=S?.index!==void 0?S.index:L.focusedHoverPartIndex();_.ContentHoverController.get(w)?.updateHoverVerbosityLevel(b.HoverVerbosityAction.Decrease,D,S?.focus)}}e.DecreaseHoverVerbosityLevel=f}),define(ne[850],se([1,0,849,15,32,25,84,217,845,292,713,380,615,196]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,k.registerEditorContribution)(b.ContentHoverController.ID,b.ContentHoverController,2),(0,k.registerEditorContribution)(p.MarginHoverController.ID,p.MarginHoverController,2),(0,k.registerEditorAction)(d.ShowOrFocusHoverAction),(0,k.registerEditorAction)(d.ShowDefinitionPreviewHoverAction),(0,k.registerEditorAction)(d.ScrollUpHoverAction),(0,k.registerEditorAction)(d.ScrollDownHoverAction),(0,k.registerEditorAction)(d.ScrollLeftHoverAction),(0,k.registerEditorAction)(d.ScrollRightHoverAction),(0,k.registerEditorAction)(d.PageUpHoverAction),(0,k.registerEditorAction)(d.PageDownHoverAction),(0,k.registerEditorAction)(d.GoToTopHoverAction),(0,k.registerEditorAction)(d.GoToBottomHoverAction),(0,k.registerEditorAction)(d.IncreaseHoverVerbosityLevel),(0,k.registerEditorAction)(d.DecreaseHoverVerbosityLevel),y.HoverParticipantRegistry.register(m.MarkdownHoverParticipant),y.HoverParticipantRegistry.register(_.MarkerHoverParticipant),(0,E.registerThemingParticipant)((t,i)=>{const s=t.getColor(I.editorHoverBorder);s&&(i.addRule(`.monaco-editor .monaco-hover .hover-row:not(:first-child):not(:empty) { border-top: 1px solid ${s.transparent(.5)}; }`),i.addRule(`.monaco-editor .monaco-hover hr { border-top: 1px solid ${s.transparent(.5)}; }`),i.addRule(`.monaco-editor .monaco-hover hr { border-bottom: 0px solid ${s.transparent(.5)}; }`))}),n.AccessibleViewRegistry.register(new o.HoverAccessibleView),n.AccessibleViewRegistry.register(new o.HoverAccessibilityHelp),n.AccessibleViewRegistry.register(new o.ExtHoverAccessibleView)}),define(ne[851],se([1,0,15,84,431,432]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorContribution)(I.InlayHintsController.ID,I.InlayHintsController,1),k.HoverParticipantRegistry.register(E.InlayHintsHover)}),define(ne[433],se([1,0,2,17,838,837,7,58,29,12,20,209,4,277,430,9,18,36,79,5,341,77,289,334]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f){"use strict";var h;Object.defineProperty(e,"__esModule",{value:!0}),e.StickyScrollController=void 0;let v=class extends d.Disposable{static{h=this}static{this.ID="store.contrib.stickyScrollController"}constructor(S,L,D,T,M,A,P){super(),this._editor=S,this._contextMenuService=L,this._languageFeaturesService=D,this._instaService=T,this._contextKeyService=P,this._sessionStore=new d.DisposableStore,this._maxStickyLines=Number.MAX_SAFE_INTEGER,this._candidateDefinitionsLength=-1,this._focusedStickyElementIndex=-1,this._enabled=!1,this._focused=!1,this._positionRevealed=!1,this._onMouseDown=!1,this._endLineNumbers=[],this._stickyScrollWidget=new I.StickyScrollWidget(this._editor),this._stickyLineCandidateProvider=new E.StickyLineCandidateProvider(this._editor,D,M),this._register(this._stickyScrollWidget),this._register(this._stickyLineCandidateProvider),this._widgetState=I.StickyScrollWidgetState.Empty,this._onDidResize(),this._readConfiguration();const N=this._stickyScrollWidget.getDomNode();this._register(this._editor.onDidChangeConfiguration(F=>{this._readConfigurationChange(F)})),this._register(a.addDisposableListener(N,a.EventType.CONTEXT_MENU,async F=>{this._onContextMenu(a.getWindow(N),F)})),this._stickyScrollFocusedContextKey=p.EditorContextKeys.stickyScrollFocused.bindTo(this._contextKeyService),this._stickyScrollVisibleContextKey=p.EditorContextKeys.stickyScrollVisible.bindTo(this._contextKeyService);const O=this._register(a.trackFocus(N));this._register(O.onDidBlur(F=>{this._positionRevealed===!1&&N.clientHeight===0?(this._focusedStickyElementIndex=-1,this.focus()):this._disposeFocusStickyScrollStore()})),this._register(O.onDidFocus(F=>{this.focus()})),this._registerMouseListeners(),this._register(a.addDisposableListener(N,a.EventType.MOUSE_DOWN,F=>{this._onMouseDown=!0}))}static get(S){return S.getContribution(h.ID)}_disposeFocusStickyScrollStore(){this._stickyScrollFocusedContextKey.set(!1),this._focusDisposableStore?.dispose(),this._focused=!1,this._positionRevealed=!1,this._onMouseDown=!1}focus(){if(this._onMouseDown){this._onMouseDown=!1,this._editor.focus();return}this._stickyScrollFocusedContextKey.get()!==!0&&(this._focused=!0,this._focusDisposableStore=new d.DisposableStore,this._stickyScrollFocusedContextKey.set(!0),this._focusedStickyElementIndex=this._stickyScrollWidget.lineNumbers.length-1,this._stickyScrollWidget.focusLineWithIndex(this._focusedStickyElementIndex))}focusNext(){this._focusedStickyElementIndex0&&this._focusNav(!1)}selectEditor(){this._editor.focus()}_focusNav(S){this._focusedStickyElementIndex=S?this._focusedStickyElementIndex+1:this._focusedStickyElementIndex-1,this._stickyScrollWidget.focusLineWithIndex(this._focusedStickyElementIndex)}goToFocused(){const S=this._stickyScrollWidget.lineNumbers;this._disposeFocusStickyScrollStore(),this._revealPosition({lineNumber:S[this._focusedStickyElementIndex],column:1})}_revealPosition(S){this._reveaInEditor(S,()=>this._editor.revealPosition(S))}_revealLineInCenterIfOutsideViewport(S){this._reveaInEditor(S,()=>this._editor.revealLineInCenterIfOutsideViewport(S.lineNumber,0))}_reveaInEditor(S,L){this._focused&&this._disposeFocusStickyScrollStore(),this._positionRevealed=!0,L(),this._editor.setSelection(o.Range.fromPositions(S)),this._editor.focus()}_registerMouseListeners(){const S=this._register(new d.DisposableStore),L=this._register(new n.ClickLinkGesture(this._editor,{extractLineNumberFromMouseEvent:M=>{const A=this._stickyScrollWidget.getEditorPositionFromNode(M.target.element);return A?A.lineNumber:0}})),D=M=>{if(!this._editor.hasModel()||M.target.type!==12||M.target.detail!==this._stickyScrollWidget.getId())return null;const A=M.target.element;if(!A||A.innerText!==A.innerHTML)return null;const P=this._stickyScrollWidget.getEditorPositionFromNode(A);return P?{range:new o.Range(P.lineNumber,P.column,P.lineNumber,P.column+A.innerText.length),textElement:A}:null},T=this._stickyScrollWidget.getDomNode();this._register(a.addStandardDisposableListener(T,a.EventType.CLICK,M=>{if(M.ctrlKey||M.altKey||M.metaKey||!M.leftButton)return;if(M.shiftKey){const O=this._stickyScrollWidget.getLineIndexFromChildDomNode(M.target);if(O===null)return;const F=new s.Position(this._endLineNumbers[O],1);this._revealLineInCenterIfOutsideViewport(F);return}if(this._stickyScrollWidget.isInFoldingIconDomNode(M.target)){const O=this._stickyScrollWidget.getLineNumberFromChildDomNode(M.target);this._toggleFoldingRegionForLine(O);return}if(!this._stickyScrollWidget.isInStickyLine(M.target))return;let N=this._stickyScrollWidget.getEditorPositionFromNode(M.target);if(!N){const O=this._stickyScrollWidget.getLineNumberFromChildDomNode(M.target);if(O===null)return;N=new s.Position(O,1)}this._revealPosition(N)})),this._register(a.addStandardDisposableListener(T,a.EventType.MOUSE_MOVE,M=>{if(M.shiftKey){const A=this._stickyScrollWidget.getLineIndexFromChildDomNode(M.target);if(A===null||this._showEndForLine!==null&&this._showEndForLine===A)return;this._showEndForLine=A,this._renderStickyScroll();return}this._showEndForLine!==void 0&&(this._showEndForLine=void 0,this._renderStickyScroll())})),this._register(a.addDisposableListener(T,a.EventType.MOUSE_LEAVE,M=>{this._showEndForLine!==void 0&&(this._showEndForLine=void 0,this._renderStickyScroll())})),this._register(L.onMouseMoveOrRelevantKeyDown(([M,A])=>{const P=D(M);if(!P||!M.hasTriggerModifier||!this._editor.hasModel()){S.clear();return}const{range:N,textElement:O}=P;if(!N.equalsRange(this._stickyRangeProjectedOnEditor))this._stickyRangeProjectedOnEditor=N,S.clear();else if(O.style.textDecoration==="underline")return;const F=new g.CancellationTokenSource;S.add((0,d.toDisposable)(()=>F.dispose(!0)));let x;(0,t.getDefinitionsAtPosition)(this._languageFeaturesService.definitionProvider,this._editor.getModel(),new s.Position(N.startLineNumber,N.startColumn+1),!1,F.token).then(W=>{if(!F.token.isCancellationRequested)if(W.length!==0){this._candidateDefinitionsLength=W.length;const V=O;x!==V?(S.clear(),x=V,x.style.textDecoration="underline",S.add((0,d.toDisposable)(()=>{x.style.textDecoration="none"}))):x||(x=V,x.style.textDecoration="underline",S.add((0,d.toDisposable)(()=>{x.style.textDecoration="none"})))}else S.clear()})})),this._register(L.onCancel(()=>{S.clear()})),this._register(L.onExecute(async M=>{if(M.target.type!==12||M.target.detail!==this._stickyScrollWidget.getId())return;const A=this._stickyScrollWidget.getEditorPositionFromNode(M.target.element);A&&(!this._editor.hasModel()||!this._stickyRangeProjectedOnEditor||(this._candidateDefinitionsLength>1&&(this._focused&&this._disposeFocusStickyScrollStore(),this._revealPosition({lineNumber:A.lineNumber,column:1})),this._instaService.invokeFunction(i.goToDefinitionWithLocation,M,this._editor,{uri:this._editor.getModel().uri,range:this._stickyRangeProjectedOnEditor})))}))}_onContextMenu(S,L){const D=new u.StandardMouseEvent(S,L);this._contextMenuService.showContextMenu({menuId:_.MenuId.StickyScrollContext,getAnchor:()=>D})}_toggleFoldingRegionForLine(S){if(!this._foldingModel||S===null)return;const L=this._stickyScrollWidget.getRenderedStickyLine(S),D=L?.foldingIcon;if(!D)return;(0,f.toggleCollapseState)(this._foldingModel,Number.MAX_VALUE,[S]),D.isCollapsed=!D.isCollapsed;const T=(D.isCollapsed?this._editor.getTopForLineNumber(D.foldingEndLine):this._editor.getTopForLineNumber(D.foldingStartLine))-this._editor.getOption(67)*L.index+1;this._editor.setScrollTop(T),this._renderStickyScroll(S)}_readConfiguration(){const S=this._editor.getOption(116);if(S.enabled===!1){this._editor.removeOverlayWidget(this._stickyScrollWidget),this._sessionStore.clear(),this._enabled=!1;return}else S.enabled&&!this._enabled&&(this._editor.addOverlayWidget(this._stickyScrollWidget),this._sessionStore.add(this._editor.onDidScrollChange(D=>{D.scrollTopChanged&&(this._showEndForLine=void 0,this._renderStickyScroll())})),this._sessionStore.add(this._editor.onDidLayoutChange(()=>this._onDidResize())),this._sessionStore.add(this._editor.onDidChangeModelTokens(D=>this._onTokensChange(D))),this._sessionStore.add(this._stickyLineCandidateProvider.onDidChangeStickyScroll(()=>{this._showEndForLine=void 0,this._renderStickyScroll()})),this._enabled=!0);this._editor.getOption(68).renderType===2&&this._sessionStore.add(this._editor.onDidChangeCursorPosition(()=>{this._showEndForLine=void 0,this._renderStickyScroll(0)}))}_readConfigurationChange(S){(S.hasChanged(116)||S.hasChanged(73)||S.hasChanged(67)||S.hasChanged(111)||S.hasChanged(68))&&this._readConfiguration(),S.hasChanged(68)&&this._renderStickyScroll(0)}_needsUpdate(S){const L=this._stickyScrollWidget.getCurrentLines();for(const D of L)for(const T of S.ranges)if(D>=T.fromLineNumber&&D<=T.toLineNumber)return!0;return!1}_onTokensChange(S){this._needsUpdate(S)&&this._renderStickyScroll(0)}_onDidResize(){const L=this._editor.getLayoutInfo().height/this._editor.getOption(67);this._maxStickyLines=Math.round(L*.25)}async _renderStickyScroll(S){const L=this._editor.getModel();if(!L||L.isTooLargeForTokenization()){this._resetState();return}const D=this._updateAndGetMinRebuildFromLine(S),T=this._stickyLineCandidateProvider.getVersionId();if(T===void 0||T===L.getVersionId())if(!this._focused)await this._updateState(D);else if(this._focusedStickyElementIndex===-1)await this._updateState(D),this._focusedStickyElementIndex=this._stickyScrollWidget.lineNumberCount-1,this._focusedStickyElementIndex!==-1&&this._stickyScrollWidget.focusLineWithIndex(this._focusedStickyElementIndex);else{const A=this._stickyScrollWidget.lineNumbers[this._focusedStickyElementIndex];await this._updateState(D),this._stickyScrollWidget.lineNumberCount===0?this._focusedStickyElementIndex=-1:(this._stickyScrollWidget.lineNumbers.includes(A)||(this._focusedStickyElementIndex=this._stickyScrollWidget.lineNumberCount-1),this._stickyScrollWidget.focusLineWithIndex(this._focusedStickyElementIndex))}}_updateAndGetMinRebuildFromLine(S){if(S!==void 0){const L=this._minRebuildFromLine!==void 0?this._minRebuildFromLine:1/0;this._minRebuildFromLine=Math.min(S,L)}return this._minRebuildFromLine}async _updateState(S){this._minRebuildFromLine=void 0,this._foldingModel=await C.FoldingController.get(this._editor)?.getFoldingModel()??void 0,this._widgetState=this.findScrollWidgetState();const L=this._widgetState.startLineNumbers.length>0;this._stickyScrollVisibleContextKey.set(L),this._stickyScrollWidget.setState(this._widgetState,this._foldingModel,S)}async _resetState(){this._minRebuildFromLine=void 0,this._foldingModel=void 0,this._widgetState=I.StickyScrollWidgetState.Empty,this._stickyScrollVisibleContextKey.set(!1),this._stickyScrollWidget.setState(void 0,void 0)}findScrollWidgetState(){const S=this._editor.getOption(67),L=Math.min(this._maxStickyLines,this._editor.getOption(116).maxLineCount),D=this._editor.getScrollTop();let T=0;const M=[],A=[],P=this._editor.getVisibleRanges();if(P.length!==0){const N=new r.StickyRange(P[0].startLineNumber,P[P.length-1].endLineNumber),O=this._stickyLineCandidateProvider.getCandidateStickyLinesIntersecting(N);for(const F of O){const x=F.startLineNumber,W=F.endLineNumber,V=F.nestingDepth;if(W-x>0){const q=(V-1)*S,H=V*S,z=this._editor.getBottomForLineNumber(x)-D,U=this._editor.getTopForLineNumber(W)-D,j=this._editor.getBottomForLineNumber(W)-D;if(q>U&&q<=j){M.push(x),A.push(W+1),T=j-H;break}else H>z&&H<=j&&(M.push(x),A.push(W+1));if(M.length===L)break}}}return this._endLineNumbers=A,new I.StickyScrollWidgetState(M,A,T,this._showEndForLine)}dispose(){super.dispose(),this._sessionStore.dispose()}};e.StickyScrollController=v,e.StickyScrollController=v=h=ke([ce(1,m.IContextMenuService),ce(2,k.ILanguageFeaturesService),ce(3,y.IInstantiationService),ce(4,c.ILanguageConfigurationService),ce(5,l.ILanguageFeatureDebounceService),ce(6,b.IContextKeyService)],v)}),define(ne[852],se([1,0,15,3,671,29,28,12,20,433]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SelectEditor=e.GoToStickyScrollLine=e.SelectPreviousStickyScrollLine=e.SelectNextStickyScrollLine=e.FocusStickyScroll=e.ToggleStickyScroll=void 0;class p extends E.Action2{constructor(){super({id:"editor.action.toggleStickyScroll",title:{...(0,k.localize2)(1303,"Toggle Editor Sticky Scroll"),mnemonicTitle:(0,k.localize)(1299,"&&Toggle Editor Sticky Scroll")},metadata:{description:(0,k.localize2)(1304,"Toggle/enable the editor sticky scroll which shows the nested scopes at the top of the viewport")},category:I.Categories.View,toggled:{condition:m.ContextKeyExpr.equals("config.editor.stickyScroll.enabled",!0),title:(0,k.localize)(1300,"Sticky Scroll"),mnemonicTitle:(0,k.localize)(1301,"&&Sticky Scroll")},menu:[{id:E.MenuId.CommandPalette},{id:E.MenuId.MenubarAppearanceMenu,group:"4_editor",order:3},{id:E.MenuId.StickyScrollContext}]})}async run(l){const a=l.get(y.IConfigurationService),r=!a.getValue("editor.stickyScroll.enabled");return a.updateValue("editor.stickyScroll.enabled",r)}}e.ToggleStickyScroll=p;const n=100;class o extends d.EditorAction2{constructor(){super({id:"editor.action.focusStickyScroll",title:{...(0,k.localize2)(1305,"Focus on the editor sticky scroll"),mnemonicTitle:(0,k.localize)(1302,"&&Focus Sticky Scroll")},precondition:m.ContextKeyExpr.and(m.ContextKeyExpr.has("config.editor.stickyScroll.enabled"),_.EditorContextKeys.stickyScrollVisible),menu:[{id:E.MenuId.CommandPalette}]})}runEditorCommand(l,a){b.StickyScrollController.get(a)?.focus()}}e.FocusStickyScroll=o;class t extends d.EditorAction2{constructor(){super({id:"editor.action.selectNextStickyScrollLine",title:(0,k.localize2)(1306,"Select the next editor sticky scroll line"),precondition:_.EditorContextKeys.stickyScrollFocused.isEqualTo(!0),keybinding:{weight:n,primary:18}})}runEditorCommand(l,a){b.StickyScrollController.get(a)?.focusNext()}}e.SelectNextStickyScrollLine=t;class i extends d.EditorAction2{constructor(){super({id:"editor.action.selectPreviousStickyScrollLine",title:(0,k.localize2)(1307,"Select the previous sticky scroll line"),precondition:_.EditorContextKeys.stickyScrollFocused.isEqualTo(!0),keybinding:{weight:n,primary:16}})}runEditorCommand(l,a){b.StickyScrollController.get(a)?.focusPrevious()}}e.SelectPreviousStickyScrollLine=i;class s extends d.EditorAction2{constructor(){super({id:"editor.action.goToFocusedStickyScrollLine",title:(0,k.localize2)(1308,"Go to the focused sticky scroll line"),precondition:_.EditorContextKeys.stickyScrollFocused.isEqualTo(!0),keybinding:{weight:n,primary:3}})}runEditorCommand(l,a){b.StickyScrollController.get(a)?.goToFocused()}}e.GoToStickyScrollLine=s;class g extends d.EditorAction2{constructor(){super({id:"editor.action.selectEditor",title:(0,k.localize2)(1309,"Select Editor"),precondition:_.EditorContextKeys.stickyScrollFocused.isEqualTo(!0),keybinding:{weight:n,primary:9}})}runEditorCommand(l,a){b.StickyScrollController.get(a)?.selectEditor()}}e.SelectEditor=g}),define(ne[853],se([1,0,15,852,433,29]),function(oe,e,d,k,I,E){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorContribution)(I.StickyScrollController.ID,I.StickyScrollController,1),(0,E.registerAction2)(k.ToggleStickyScroll),(0,E.registerAction2)(k.FocusStickyScroll),(0,E.registerAction2)(k.SelectPreviousStickyScrollLine),(0,E.registerAction2)(k.SelectNextStickyScrollLine),(0,E.registerAction2)(k.GoToStickyScrollLine),(0,E.registerAction2)(k.SelectEditor)}),define(ne[854],se([1,0,15,34,428,28,12,7,50,101]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneReferencesController=void 0;let p=class extends I.ReferencesController{constructor(o,t,i,s,g,c,l){super(!0,o,t,i,s,g,c,l)}};e.StandaloneReferencesController=p,e.StandaloneReferencesController=p=ke([ce(1,y.IContextKeyService),ce(2,k.ICodeEditorService),ce(3,_.INotificationService),ce(4,m.IInstantiationService),ce(5,b.IStorageService),ce(6,E.IConfigurationService)],p),(0,d.registerEditorContribution)(I.ReferencesController.ID,p,4)}),define(ne[855],se([1,0,8,2,42,111,3,180,49,50,284]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UndoRedoService=void 0;const n=!1;function o(f){return f.scheme===I.Schemas.file?f.fsPath:f.path}let t=0;class i{constructor(h,v,w,S,L,D,T){this.id=++t,this.type=0,this.actual=h,this.label=h.label,this.confirmBeforeUndo=h.confirmBeforeUndo||!1,this.resourceLabel=v,this.strResource=w,this.resourceLabels=[this.resourceLabel],this.strResources=[this.strResource],this.groupId=S,this.groupOrder=L,this.sourceId=D,this.sourceOrder=T,this.isValid=!0}setValid(h){this.isValid=h}toString(){return`[id:${this.id}] [group:${this.groupId}] [${this.isValid?" VALID":"INVALID"}] ${this.actual.constructor.name} - ${this.actual}`}}class s{constructor(h,v){this.resourceLabel=h,this.reason=v}}class g{constructor(){this.elements=new Map}createMessage(){const h=[],v=[];for(const[,S]of this.elements)(S.reason===0?h:v).push(S.resourceLabel);const w=[];return h.length>0&&w.push(y.localize(1843,"The following files have been closed and modified on disk: {0}.",h.join(", "))),v.length>0&&w.push(y.localize(1844,"The following files have been modified in an incompatible way: {0}.",v.join(", "))),w.join(` `)}get size(){return this.elements.size}has(h){return this.elements.has(h)}set(h,v){this.elements.set(h,v)}delete(h){return this.elements.delete(h)}}class c{constructor(h,v,w,S,L,D,T){this.id=++t,this.type=1,this.actual=h,this.label=h.label,this.confirmBeforeUndo=h.confirmBeforeUndo||!1,this.resourceLabels=v,this.strResources=w,this.groupId=S,this.groupOrder=L,this.sourceId=D,this.sourceOrder=T,this.removedResources=null,this.invalidatedResources=null}canSplit(){return typeof this.actual.split=="function"}removeResource(h,v,w){this.removedResources||(this.removedResources=new g),this.removedResources.has(v)||this.removedResources.set(v,new s(h,w))}setValid(h,v,w){w?this.invalidatedResources&&(this.invalidatedResources.delete(v),this.invalidatedResources.size===0&&(this.invalidatedResources=null)):(this.invalidatedResources||(this.invalidatedResources=new g),this.invalidatedResources.has(v)||this.invalidatedResources.set(v,new s(h,0)))}toString(){return`[id:${this.id}] [group:${this.groupId}] [${this.invalidatedResources?"INVALID":" VALID"}] ${this.actual.constructor.name} - ${this.actual}`}}class l{constructor(h,v){this.resourceLabel=h,this.strResource=v,this._past=[],this._future=[],this.locked=!1,this.versionId=1}dispose(){for(const h of this._past)h.type===1&&h.removeResource(this.resourceLabel,this.strResource,0);for(const h of this._future)h.type===1&&h.removeResource(this.resourceLabel,this.strResource,0);this.versionId++}toString(){const h=[];h.push(`* ${this.strResource}:`);for(let v=0;v=0;v--)h.push(` * [REDO] ${this._future[v]}`);return h.join(` `)}flushAllElements(){this._past=[],this._future=[],this.versionId++}_setElementValidFlag(h,v){h.type===1?h.setValid(this.resourceLabel,this.strResource,v):h.setValid(v)}setElementsValidFlag(h,v){for(const w of this._past)v(w.actual)&&this._setElementValidFlag(w,h);for(const w of this._future)v(w.actual)&&this._setElementValidFlag(w,h)}pushElement(h){for(const v of this._future)v.type===1&&v.removeResource(this.resourceLabel,this.strResource,1);this._future=[],this._past.push(h),this.versionId++}createSnapshot(h){const v=[];for(let w=0,S=this._past.length;w=0;w--)v.push(this._future[w].id);return new p.ResourceEditStackSnapshot(h,v)}restoreSnapshot(h){const v=h.elements.length;let w=!0,S=0,L=-1;for(let T=0,M=this._past.length;T=v||A.id!==h.elements[S])&&(w=!1,L=0),!w&&A.type===1&&A.removeResource(this.resourceLabel,this.strResource,0)}let D=-1;for(let T=this._future.length-1;T>=0;T--,S++){const M=this._future[T];w&&(S>=v||M.id!==h.elements[S])&&(w=!1,D=T),!w&&M.type===1&&M.removeResource(this.resourceLabel,this.strResource,0)}L!==-1&&(this._past=this._past.slice(0,L)),D!==-1&&(this._future=this._future.slice(D+1)),this.versionId++}getElements(){const h=[],v=[];for(const w of this._past)h.push(w.actual);for(const w of this._future)v.push(w.actual);return{past:h,future:v}}getClosestPastElement(){return this._past.length===0?null:this._past[this._past.length-1]}getSecondClosestPastElement(){return this._past.length<2?null:this._past[this._past.length-2]}getClosestFutureElement(){return this._future.length===0?null:this._future[this._future.length-1]}hasPastElements(){return this._past.length>0}hasFutureElements(){return this._future.length>0}splitPastWorkspaceElement(h,v){for(let w=this._past.length-1;w>=0;w--)if(this._past[w]===h){v.has(this.strResource)?this._past[w]=v.get(this.strResource):this._past.splice(w,1);break}this.versionId++}splitFutureWorkspaceElement(h,v){for(let w=this._future.length-1;w>=0;w--)if(this._future[w]===h){v.has(this.strResource)?this._future[w]=v.get(this.strResource):this._future.splice(w,1);break}this.versionId++}moveBackward(h){this._past.pop(),this._future.push(h),this.versionId++}moveForward(h){this._future.pop(),this._past.push(h),this.versionId++}}class a{constructor(h){this.editStacks=h,this._versionIds=[];for(let v=0,w=this.editStacks.length;vv.sourceOrder)&&(v=D,w=S)}return[v,w]}canUndo(h){if(h instanceof p.UndoRedoSource){const[,w]=this._findClosestUndoElementWithSource(h.id);return!!w}const v=this.getUriComparisonKey(h);return this._editStacks.has(v)?this._editStacks.get(v).hasPastElements():!1}_onError(h,v){(0,d.onUnexpectedError)(h);for(const w of v.strResources)this.removeElements(w);this._notificationService.error(h)}_acquireLocks(h){for(const v of h.editStacks)if(v.locked)throw new Error("Cannot acquire edit stack lock");for(const v of h.editStacks)v.locked=!0;return()=>{for(const v of h.editStacks)v.locked=!1}}_safeInvokeWithLocks(h,v,w,S,L){const D=this._acquireLocks(w);let T;try{T=v()}catch(M){return D(),S.dispose(),this._onError(M,h)}return T?T.then(()=>(D(),S.dispose(),L()),M=>(D(),S.dispose(),this._onError(M,h))):(D(),S.dispose(),L())}async _invokeWorkspacePrepare(h){if(typeof h.actual.prepareUndoRedo>"u")return k.Disposable.None;const v=h.actual.prepareUndoRedo();return typeof v>"u"?k.Disposable.None:v}_invokeResourcePrepare(h,v){if(h.actual.type!==1||typeof h.actual.prepareUndoRedo>"u")return v(k.Disposable.None);const w=h.actual.prepareUndoRedo();return w?(0,k.isDisposable)(w)?v(w):w.then(S=>v(S)):v(k.Disposable.None)}_getAffectedEditStacks(h){const v=[];for(const w of h.strResources)v.push(this._editStacks.get(w)||r);return new a(v)}_tryToSplitAndUndo(h,v,w,S){if(v.canSplit())return this._splitPastWorkspaceElement(v,w),this._notificationService.warn(S),new C(this._undo(h,0,!0));for(const L of v.strResources)this.removeElements(L);return this._notificationService.warn(S),new C}_checkWorkspaceUndo(h,v,w,S){if(v.removedResources)return this._tryToSplitAndUndo(h,v,v.removedResources,y.localize(1845,"Could not undo '{0}' across all files. {1}",v.label,v.removedResources.createMessage()));if(S&&v.invalidatedResources)return this._tryToSplitAndUndo(h,v,v.invalidatedResources,y.localize(1846,"Could not undo '{0}' across all files. {1}",v.label,v.invalidatedResources.createMessage()));const L=[];for(const T of w.editStacks)T.getClosestPastElement()!==v&&L.push(T.resourceLabel);if(L.length>0)return this._tryToSplitAndUndo(h,v,null,y.localize(1847,"Could not undo '{0}' across all files because changes were made to {1}",v.label,L.join(", ")));const D=[];for(const T of w.editStacks)T.locked&&D.push(T.resourceLabel);return D.length>0?this._tryToSplitAndUndo(h,v,null,y.localize(1848,"Could not undo '{0}' across all files because there is already an undo or redo operation running on {1}",v.label,D.join(", "))):w.isValid()?null:this._tryToSplitAndUndo(h,v,null,y.localize(1849,"Could not undo '{0}' across all files because an undo or redo operation occurred in the meantime",v.label))}_workspaceUndo(h,v,w){const S=this._getAffectedEditStacks(v),L=this._checkWorkspaceUndo(h,v,S,!1);return L?L.returnValue:this._confirmAndExecuteWorkspaceUndo(h,v,S,w)}_isPartOfUndoGroup(h){if(!h.groupId)return!1;for(const[,v]of this._editStacks){const w=v.getClosestPastElement();if(w){if(w===h){const S=v.getSecondClosestPastElement();if(S&&S.groupId===h.groupId)return!0}if(w.groupId===h.groupId)return!0}}return!1}async _confirmAndExecuteWorkspaceUndo(h,v,w,S){if(v.canSplit()&&!this._isPartOfUndoGroup(v)){let T;(function(P){P[P.All=0]="All",P[P.This=1]="This",P[P.Cancel=2]="Cancel"})(T||(T={}));const{result:M}=await this._dialogService.prompt({type:E.default.Info,message:y.localize(1850,"Would you like to undo '{0}' across all files?",v.label),buttons:[{label:y.localize(1851,"&&Undo in {0} Files",w.editStacks.length),run:()=>T.All},{label:y.localize(1852,"Undo this &&File"),run:()=>T.This}],cancelButton:{run:()=>T.Cancel}});if(M===T.Cancel)return;if(M===T.This)return this._splitPastWorkspaceElement(v,null),this._undo(h,0,!0);const A=this._checkWorkspaceUndo(h,v,w,!1);if(A)return A.returnValue;S=!0}let L;try{L=await this._invokeWorkspacePrepare(v)}catch(T){return this._onError(T,v)}const D=this._checkWorkspaceUndo(h,v,w,!0);if(D)return L.dispose(),D.returnValue;for(const T of w.editStacks)T.moveBackward(v);return this._safeInvokeWithLocks(v,()=>v.actual.undo(),w,L,()=>this._continueUndoInGroup(v.groupId,S))}_resourceUndo(h,v,w){if(!v.isValid){h.flushAllElements();return}if(h.locked){const S=y.localize(1853,"Could not undo '{0}' because there is already an undo or redo operation running.",v.label);this._notificationService.warn(S);return}return this._invokeResourcePrepare(v,S=>(h.moveBackward(v),this._safeInvokeWithLocks(v,()=>v.actual.undo(),new a([h]),S,()=>this._continueUndoInGroup(v.groupId,w))))}_findClosestUndoElementInGroup(h){if(!h)return[null,null];let v=null,w=null;for(const[S,L]of this._editStacks){const D=L.getClosestPastElement();D&&D.groupId===h&&(!v||D.groupOrder>v.groupOrder)&&(v=D,w=S)}return[v,w]}_continueUndoInGroup(h,v){if(!h)return;const[,w]=this._findClosestUndoElementInGroup(h);if(w)return this._undo(w,0,v)}undo(h){if(h instanceof p.UndoRedoSource){const[,v]=this._findClosestUndoElementWithSource(h.id);return v?this._undo(v,h.id,!1):void 0}return typeof h=="string"?this._undo(h,0,!1):this._undo(this.getUriComparisonKey(h),0,!1)}_undo(h,v=0,w){if(!this._editStacks.has(h))return;const S=this._editStacks.get(h),L=S.getClosestPastElement();if(!L)return;if(L.groupId){const[T,M]=this._findClosestUndoElementInGroup(L.groupId);if(L!==T&&M)return this._undo(M,v,w)}if((L.sourceId!==v||L.confirmBeforeUndo)&&!w)return this._confirmAndContinueUndo(h,v,L);try{return L.type===1?this._workspaceUndo(h,L,w):this._resourceUndo(S,L,w)}finally{n&&this._print("undo")}}async _confirmAndContinueUndo(h,v,w){if((await this._dialogService.confirm({message:y.localize(1854,"Would you like to undo '{0}'?",w.label),primaryButton:y.localize(1855,"&&Yes"),cancelButton:y.localize(1856,"No")})).confirmed)return this._undo(h,v,!0)}_findClosestRedoElementWithSource(h){if(!h)return[null,null];let v=null,w=null;for(const[S,L]of this._editStacks){const D=L.getClosestFutureElement();D&&D.sourceId===h&&(!v||D.sourceOrder0)return this._tryToSplitAndRedo(h,v,null,y.localize(1859,"Could not redo '{0}' across all files because changes were made to {1}",v.label,L.join(", ")));const D=[];for(const T of w.editStacks)T.locked&&D.push(T.resourceLabel);return D.length>0?this._tryToSplitAndRedo(h,v,null,y.localize(1860,"Could not redo '{0}' across all files because there is already an undo or redo operation running on {1}",v.label,D.join(", "))):w.isValid()?null:this._tryToSplitAndRedo(h,v,null,y.localize(1861,"Could not redo '{0}' across all files because an undo or redo operation occurred in the meantime",v.label))}_workspaceRedo(h,v){const w=this._getAffectedEditStacks(v),S=this._checkWorkspaceRedo(h,v,w,!1);return S?S.returnValue:this._executeWorkspaceRedo(h,v,w)}async _executeWorkspaceRedo(h,v,w){let S;try{S=await this._invokeWorkspacePrepare(v)}catch(D){return this._onError(D,v)}const L=this._checkWorkspaceRedo(h,v,w,!0);if(L)return S.dispose(),L.returnValue;for(const D of w.editStacks)D.moveForward(v);return this._safeInvokeWithLocks(v,()=>v.actual.redo(),w,S,()=>this._continueRedoInGroup(v.groupId))}_resourceRedo(h,v){if(!v.isValid){h.flushAllElements();return}if(h.locked){const w=y.localize(1862,"Could not redo '{0}' because there is already an undo or redo operation running.",v.label);this._notificationService.warn(w);return}return this._invokeResourcePrepare(v,w=>(h.moveForward(v),this._safeInvokeWithLocks(v,()=>v.actual.redo(),new a([h]),w,()=>this._continueRedoInGroup(v.groupId))))}_findClosestRedoElementInGroup(h){if(!h)return[null,null];let v=null,w=null;for(const[S,L]of this._editStacks){const D=L.getClosestFutureElement();D&&D.groupId===h&&(!v||D.groupOrder"u")return typeof i=="string"?{id:(0,k.basename)(i)}:s?e.EXTENSION_DEVELOPMENT_EMPTY_WINDOW_WORKSPACE:e.UNKNOWN_EMPTY_WINDOW_WORKSPACE;const g=i;return g.configuration?{id:g.id,configPath:g.configuration}:g.folders.length===1?{id:g.id,uri:g.folders[0].uri}:{id:g.id}}function p(i){const s=i;return typeof s?.id=="string"&&E.URI.isUri(s.configPath)}class n{constructor(s,g,c,l,a){this._id=s,this._transient=c,this._configuration=l,this._ignorePathCasing=a,this._foldersMap=I.TernarySearchTree.forUris(this._ignorePathCasing,()=>!0),this.folders=g}get folders(){return this._folders}set folders(s){this._folders=s,this.updateFoldersMap()}get id(){return this._id}get transient(){return this._transient}get configuration(){return this._configuration}set configuration(s){this._configuration=s}getFolder(s){return s&&this._foldersMap.findSubstr(s)||null}updateFoldersMap(){this._foldersMap=I.TernarySearchTree.forUris(this._ignorePathCasing,()=>!0);for(const s of this.folders)this._foldersMap.set(s.uri,s)}toJSON(){return{id:this.id,folders:this.folders,transient:this.transient,configuration:this.configuration}}}e.Workspace=n;class o{constructor(s,g){this.raw=g,this.uri=s.uri,this.index=s.index,this.name=s.name}toJSON(){return{uri:this.uri,name:this.name,index:this.index}}}e.WorkspaceFolder=o,e.WORKSPACE_EXTENSION="code-workspace",e.WORKSPACE_FILTER=[{name:(0,d.localize)(1863,"Code Workspace"),extensions:[e.WORKSPACE_EXTENSION]}],e.STANDALONE_EDITOR_WORKSPACE_ID="4064f6ec-cb38-4ad0-af64-ee6467e63c82";function t(i){return i.id===e.STANDALONE_EDITOR_WORKSPACE_ID}}),define(ne[434],se([1,0,5,151,41,2,16,15,20,3,29,12,58,31,28,186]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";var g;Object.defineProperty(e,"__esModule",{value:!0}),e.ContextMenuController=void 0;let c=class{static{g=this}static{this.ID="editor.contrib.contextmenu"}static get(r){return r.getContribution(g.ID)}constructor(r,u,C,f,h,v,w,S){this._contextMenuService=u,this._contextViewService=C,this._contextKeyService=f,this._keybindingService=h,this._menuService=v,this._configurationService=w,this._workspaceContextService=S,this._toDispose=new E.DisposableStore,this._contextMenuIsBeingShownCount=0,this._editor=r,this._toDispose.add(this._editor.onContextMenu(L=>this._onContextMenu(L))),this._toDispose.add(this._editor.onMouseWheel(L=>{if(this._contextMenuIsBeingShownCount>0){const D=this._contextViewService.getContextViewElement(),T=L.srcElement;T.shadowRoot&&d.getShadowRoot(D)===T.shadowRoot||this._contextViewService.hideContextView()}})),this._toDispose.add(this._editor.onKeyDown(L=>{this._editor.getOption(24)&&L.keyCode===58&&(L.preventDefault(),L.stopPropagation(),this.showContextMenu())}))}_onContextMenu(r){if(!this._editor.hasModel())return;if(!this._editor.getOption(24)){this._editor.focus(),r.target.position&&!this._editor.getSelection().containsPosition(r.target.position)&&this._editor.setPosition(r.target.position);return}if(r.target.type===12||r.target.type===6&&r.target.detail.injectedText)return;if(r.event.preventDefault(),r.event.stopPropagation(),r.target.type===11)return this._showScrollbarContextMenu(r.event);if(r.target.type!==6&&r.target.type!==7&&r.target.type!==1)return;if(this._editor.focus(),r.target.position){let C=!1;for(const f of this._editor.getSelections())if(f.containsPosition(r.target.position)){C=!0;break}C||this._editor.setPosition(r.target.position)}let u=null;r.target.type!==1&&(u=r.event),this.showContextMenu(u)}showContextMenu(r){if(!this._editor.getOption(24)||!this._editor.hasModel())return;const u=this._getMenuActions(this._editor.getModel(),this._editor.contextMenuId);u.length>0&&this._doShowContextMenu(u,r)}_getMenuActions(r,u){const C=[],f=this._menuService.getMenuActions(u,this._contextKeyService,{arg:r.uri});for(const h of f){const[,v]=h;let w=0;for(const S of v)if(S instanceof p.SubmenuItemAction){const L=this._getMenuActions(r,S.item.submenu);L.length>0&&(C.push(new I.SubmenuAction(S.id,S.label,L)),w++)}else C.push(S),w++;w&&C.push(new I.Separator)}return C.length&&C.pop(),C}_doShowContextMenu(r,u=null){if(!this._editor.hasModel())return;const C=this._editor.getOption(60);this._editor.updateOptions({hover:{enabled:!1}});let f=u;if(!f){this._editor.revealPosition(this._editor.getPosition(),1),this._editor.render();const v=this._editor.getScrolledVisiblePosition(this._editor.getPosition()),w=d.getDomNodePagePosition(this._editor.getDomNode()),S=w.left+v.left,L=w.top+v.top+v.height;f={x:S,y:L}}const h=this._editor.getOption(128)&&!y.isIOS;this._contextMenuIsBeingShownCount++,this._contextMenuService.showContextMenu({domForShadowRoot:h?this._editor.getOverflowWidgetsDomNode()??this._editor.getDomNode():void 0,getAnchor:()=>f,getActions:()=>r,getActionViewItem:v=>{const w=this._keybindingFor(v);if(w)return new k.ActionViewItem(v,v,{label:!0,keybinding:w.getLabel(),isMenu:!0});const S=v;return typeof S.getActionViewItem=="function"?S.getActionViewItem():new k.ActionViewItem(v,v,{icon:!0,label:!0,isMenu:!0})},getKeyBinding:v=>this._keybindingFor(v),onHide:v=>{this._contextMenuIsBeingShownCount--,this._editor.updateOptions({hover:C})}})}_showScrollbarContextMenu(r){if(!this._editor.hasModel()||(0,s.isStandaloneEditorWorkspace)(this._workspaceContextService.getWorkspace()))return;const u=this._editor.getOption(73);let C=0;const f=L=>({id:`menu-action-${++C}`,label:L.label,tooltip:"",class:void 0,enabled:typeof L.enabled>"u"?!0:L.enabled,checked:L.checked,run:L.run}),h=(L,D)=>new I.SubmenuAction(`menu-action-${++C}`,L,D,void 0),v=(L,D,T,M,A)=>{if(!D)return f({label:L,enabled:D,run:()=>{}});const P=O=>()=>{this._configurationService.updateValue(T,O)},N=[];for(const O of A)N.push(f({label:O.label,checked:M===O.value,run:P(O.value)}));return h(L,N)},w=[];w.push(f({label:b.localize(811,"Minimap"),checked:u.enabled,run:()=>{this._configurationService.updateValue("editor.minimap.enabled",!u.enabled)}})),w.push(new I.Separator),w.push(f({label:b.localize(812,"Render Characters"),enabled:u.enabled,checked:u.renderCharacters,run:()=>{this._configurationService.updateValue("editor.minimap.renderCharacters",!u.renderCharacters)}})),w.push(v(b.localize(813,"Vertical size"),u.enabled,"editor.minimap.size",u.size,[{label:b.localize(814,"Proportional"),value:"proportional"},{label:b.localize(815,"Fill"),value:"fill"},{label:b.localize(816,"Fit"),value:"fit"}])),w.push(v(b.localize(817,"Slider"),u.enabled,"editor.minimap.showSlider",u.showSlider,[{label:b.localize(818,"Mouse Over"),value:"mouseover"},{label:b.localize(819,"Always"),value:"always"}]));const S=this._editor.getOption(128)&&!y.isIOS;this._contextMenuIsBeingShownCount++,this._contextMenuService.showContextMenu({domForShadowRoot:S?this._editor.getDomNode():void 0,getAnchor:()=>r,getActions:()=>w,onHide:L=>{this._contextMenuIsBeingShownCount--,this._editor.focus()}})}_keybindingFor(r){return this._keybindingService.lookupKeybinding(r.id)}dispose(){this._contextMenuIsBeingShownCount>0&&this._contextViewService.hideContextView(),this._toDispose.dispose()}};e.ContextMenuController=c,e.ContextMenuController=c=g=ke([ce(1,o.IContextMenuService),ce(2,o.IContextViewService),ce(3,n.IContextKeyService),ce(4,t.IKeybindingService),ce(5,p.IMenuService),ce(6,i.IConfigurationService),ce(7,s.IWorkspaceContextService)],c);class l extends m.EditorAction{constructor(){super({id:"editor.action.showContextMenu",label:b.localize(820,"Show Editor Context Menu"),alias:"Show Editor Context Menu",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.textInputFocus,primary:1092,weight:100}})}run(r,u){c.get(u)?.showContextMenu()}}(0,m.registerEditorContribution)(c.ID,c,2),(0,m.registerEditorAction)(l)}),define(ne[293],se([1,0,13,194,91,2,128,42,48,22,27,17,3,186]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.DefaultPasteProvidersFeature=e.DefaultDropProvidersFeature=e.DefaultTextPasteOrDropEditProvider=void 0;class i{async provideDocumentPasteEdits(f,h,v,w,S){const L=await this.getEdit(v,S);if(L)return{edits:[{insertText:L.insertText,title:L.title,kind:L.kind,handledMimeType:L.handledMimeType,yieldTo:L.yieldTo}],dispose(){}}}async provideDocumentDropEdits(f,h,v,w){const S=await this.getEdit(v,w);if(S)return{edits:[{insertText:S.insertText,title:S.title,kind:S.kind,handledMimeType:S.handledMimeType,yieldTo:S.yieldTo}],dispose(){}}}}class s extends i{constructor(){super(...arguments),this.kind=s.kind,this.dropMimeTypes=[y.Mimes.text],this.pasteMimeTypes=[y.Mimes.text]}static{this.id="text"}static{this.kind=new I.HierarchicalKind("text.plain")}async getEdit(f,h){const v=f.get(y.Mimes.text);if(!v||f.has(y.Mimes.uriList))return;const w=await v.asString();return{handledMimeType:y.Mimes.text,title:(0,o.localize)(833,"Insert Plain Text"),insertText:w,kind:this.kind}}}e.DefaultTextPasteOrDropEditProvider=s;class g extends i{constructor(){super(...arguments),this.kind=new I.HierarchicalKind("uri.absolute"),this.dropMimeTypes=[y.Mimes.uriList],this.pasteMimeTypes=[y.Mimes.uriList]}async getEdit(f,h){const v=await a(f);if(!v.length||h.isCancellationRequested)return;let w=0;const S=v.map(({uri:D,originalText:T})=>D.scheme===m.Schemas.file?D.fsPath:(w++,T)).join(" ");let L;return w>0?L=v.length>1?(0,o.localize)(834,"Insert Uris"):(0,o.localize)(835,"Insert Uri"):L=v.length>1?(0,o.localize)(836,"Insert Paths"):(0,o.localize)(837,"Insert Path"),{handledMimeType:y.Mimes.uriList,insertText:S,title:L,kind:this.kind}}}let c=class extends i{constructor(f){super(),this._workspaceContextService=f,this.kind=new I.HierarchicalKind("uri.relative"),this.dropMimeTypes=[y.Mimes.uriList],this.pasteMimeTypes=[y.Mimes.uriList]}async getEdit(f,h){const v=await a(f);if(!v.length||h.isCancellationRequested)return;const w=(0,d.coalesce)(v.map(({uri:S})=>{const L=this._workspaceContextService.getWorkspaceFolder(S);return L?(0,_.relativePath)(L.uri,S):void 0}));if(w.length)return{handledMimeType:y.Mimes.uriList,insertText:w.join(" "),title:v.length>1?(0,o.localize)(838,"Insert Relative Paths"):(0,o.localize)(839,"Insert Relative Path"),kind:this.kind}}};c=ke([ce(0,t.IWorkspaceContextService)],c);class l{constructor(){this.kind=new I.HierarchicalKind("html"),this.pasteMimeTypes=["text/html"],this._yieldTo=[{mimeType:y.Mimes.text}]}async provideDocumentPasteEdits(f,h,v,w,S){if(w.triggerKind!==p.DocumentPasteTriggerKind.PasteAs&&!w.only?.contains(this.kind))return;const D=await v.get("text/html")?.asString();if(!(!D||S.isCancellationRequested))return{dispose(){},edits:[{insertText:D,yieldTo:this._yieldTo,title:(0,o.localize)(840,"Insert HTML"),kind:this.kind}]}}}async function a(C){const f=C.get(y.Mimes.uriList);if(!f)return[];const h=await f.asString(),v=[];for(const w of k.UriList.parse(h))try{v.push({uri:b.URI.parse(w),originalText:w})}catch{}return v}let r=class extends E.Disposable{constructor(f,h){super(),this._register(f.documentDropEditProvider.register("*",new s)),this._register(f.documentDropEditProvider.register("*",new g)),this._register(f.documentDropEditProvider.register("*",new c(h)))}};e.DefaultDropProvidersFeature=r,e.DefaultDropProvidersFeature=r=ke([ce(0,n.ILanguageFeaturesService),ce(1,t.IWorkspaceContextService)],r);let u=class extends E.Disposable{constructor(f,h){super(),this._register(f.documentPasteEditProvider.register("*",new s)),this._register(f.documentPasteEditProvider.register("*",new g)),this._register(f.documentPasteEditProvider.register("*",new c(h))),this._register(f.documentPasteEditProvider.register("*",new l))}};e.DefaultPasteProvidersFeature=u,e.DefaultPasteProvidersFeature=u=ke([ce(0,n.ILanguageFeaturesService),ce(1,t.IWorkspaceContextService)],u)}),define(ne[435],se([1,0,5,13,14,18,194,91,2,128,16,193,212,400,152,4,27,17,293,268,122,290,184,3,117,12,7,96,66,396,8]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T){"use strict";var M;Object.defineProperty(e,"__esModule",{value:!0}),e.CopyPasteController=e.pasteWidgetVisibleCtx=e.changePasteTypeCommandId=void 0,e.changePasteTypeCommandId="editor.changePasteType",e.pasteWidgetVisibleCtx=new v.RawContextKey("pasteWidgetVisible",!1,(0,f.localize)(826,"Whether the paste widget is showing"));const A="application/vnd.code.copyMetadata";let P=class extends _.Disposable{static{M=this}static{this.ID="editor.contrib.copyPasteActionController"}static get(O){return O.getContribution(M.ID)}constructor(O,F,x,W,V,q,H){super(),this._bulkEditService=x,this._clipboardService=W,this._languageFeaturesService=V,this._quickInputService=q,this._progressService=H,this._editor=O;const z=O.getContainerDomNode();this._register((0,d.addDisposableListener)(z,"copy",U=>this.handleCopy(U))),this._register((0,d.addDisposableListener)(z,"cut",U=>this.handleCopy(U))),this._register((0,d.addDisposableListener)(z,"paste",U=>this.handlePaste(U),!0)),this._pasteProgressManager=this._register(new u.InlineProgressManager("pasteIntoEditor",O,F)),this._postPasteWidgetManager=this._register(F.createInstance(D.PostEditWidgetManager,"pasteIntoEditor",O,e.pasteWidgetVisibleCtx,{id:e.changePasteTypeCommandId,label:(0,f.localize)(827,"Show paste options...")}))}changePasteType(){this._postPasteWidgetManager.tryShowSelector()}pasteAs(O){this._editor.focus();try{this._pasteAsActionContext={preferred:O},(0,d.getActiveDocument)().execCommand("paste")}finally{this._pasteAsActionContext=void 0}}clearWidgets(){this._postPasteWidgetManager.clear()}isPasteAsEnabled(){return this._editor.getOption(85).enabled}async finishedPaste(){await this._currentPasteOperation}handleCopy(O){if(!this._editor.hasTextFocus()||(this._clipboardService.clearInternalState?.(),!O.clipboardData||!this.isPasteAsEnabled()))return;const F=this._editor.getModel(),x=this._editor.getSelections();if(!F||!x?.length)return;const W=this._editor.getOption(37);let V=x;const q=x.length===1&&x[0].isEmpty();if(q){if(!W)return;V=[new s.Range(V[0].startLineNumber,1,V[0].startLineNumber,1+F.getLineLength(V[0].startLineNumber))]}const H=this._editor._getViewModel()?.getPlainTextToCopy(x,W,p.isWindows),U={multicursorText:Array.isArray(H)?H:null,pasteOnNewLine:q,mode:null},j=this._languageFeaturesService.documentPasteEditProvider.ordered(F).filter(J=>!!J.prepareDocumentPaste);if(!j.length){this.setCopyMetadata(O.clipboardData,{defaultPastePayload:U});return}const Y=(0,t.toVSDataTransfer)(O.clipboardData),G=j.flatMap(J=>J.copyMimeTypes??[]),K=(0,n.generateUuid)();this.setCopyMetadata(O.clipboardData,{id:K,providerCopyMimeTypes:G,defaultPastePayload:U});const R=(0,I.createCancelablePromise)(async J=>{const ie=(0,k.coalesce)(await Promise.all(j.map(async ue=>{try{return await ue.prepareDocumentPaste(F,V,Y,J)}catch(he){console.error(he);return}})));ie.reverse();for(const ue of ie)for(const[he,pe]of ue)Y.replace(he,pe);return Y});M._currentCopyOperation?.dataTransferPromise.cancel(),M._currentCopyOperation={handle:K,dataTransferPromise:R}}async handlePaste(O){if(!O.clipboardData||!this._editor.hasTextFocus())return;C.MessageController.get(this._editor)?.closeMessage(),this._currentPasteOperation?.cancel(),this._currentPasteOperation=void 0;const F=this._editor.getModel(),x=this._editor.getSelections();if(!x?.length||!F||this._editor.getOption(92)||!this.isPasteAsEnabled()&&!this._pasteAsActionContext)return;const W=this.fetchCopyMetadata(O),V=(0,t.toExternalVSDataTransfer)(O.clipboardData);V.delete(A);const q=[...O.clipboardData.types,...W?.providerCopyMimeTypes??[],b.Mimes.uriList],H=this._languageFeaturesService.documentPasteEditProvider.ordered(F).filter(z=>{const U=this._pasteAsActionContext?.preferred;return U&&z.providedPasteEditKinds&&!this.providerMatchesPreference(z,U)?!1:z.pasteMimeTypes?.some(j=>(0,y.matchesMimeType)(j,q))});if(!H.length){this._pasteAsActionContext?.preferred&&this.showPasteAsNoEditMessage(x,this._pasteAsActionContext.preferred);return}O.preventDefault(),O.stopImmediatePropagation(),this._pasteAsActionContext?this.showPasteAsPick(this._pasteAsActionContext.preferred,H,x,V,W):this.doPasteInline(H,x,V,W,O)}showPasteAsNoEditMessage(O,F){C.MessageController.get(this._editor)?.showMessage((0,f.localize)(828,"No paste edits for '{0}' found",F instanceof m.HierarchicalKind?F.value:F.providerId),O[0].getStartPosition())}doPasteInline(O,F,x,W,V){const q=this._editor;if(!q.hasModel())return;const H=new r.EditorStateCancellationTokenSource(q,3,void 0),z=(0,I.createCancelablePromise)(async U=>{const j=this._editor;if(!j.hasModel())return;const Y=j.getModel(),G=new _.DisposableStore,K=G.add(new E.CancellationTokenSource(U));G.add(H.token.onCancellationRequested(()=>K.cancel()));const R=K.token;try{if(await this.mergeInDataFromCopy(x,W,R),R.isCancellationRequested)return;const J=O.filter(he=>this.isSupportedPasteProvider(he,x));if(!J.length||J.length===1&&J[0]instanceof l.DefaultTextPasteOrDropEditProvider)return this.applyDefaultPasteHandler(x,W,R,V);const ie={triggerKind:g.DocumentPasteTriggerKind.Automatic},ue=await this.getPasteEdits(J,x,Y,F,ie,R);if(G.add(ue),R.isCancellationRequested)return;if(ue.edits.length===1&&ue.edits[0].provider instanceof l.DefaultTextPasteOrDropEditProvider)return this.applyDefaultPasteHandler(x,W,R,V);if(ue.edits.length){const he=j.getOption(85).showPasteSelector==="afterPaste";return this._postPasteWidgetManager.applyEditAndShowIfNeeded(F,{activeEditIndex:0,allEdits:ue.edits},he,(pe,ae)=>new Promise((ee,de)=>{(async()=>{try{const ge=pe.provider.resolveDocumentPasteEdit?.(pe,ae),X=new I.DeferredPromise,B=ge&&await this._pasteProgressManager.showWhile(F[0].getEndPosition(),(0,f.localize)(829,"Resolving paste edit. Click to cancel"),Promise.race([X.p,ge]),{cancel:()=>(X.cancel(),de(new T.CancellationError))},0);return B&&(pe.additionalEdit=B.additionalEdit),ee(pe)}catch(ge){return de(ge)}})()}),R)}await this.applyDefaultPasteHandler(x,W,R,V)}finally{G.dispose(),this._currentPasteOperation===z&&(this._currentPasteOperation=void 0)}});this._pasteProgressManager.showWhile(F[0].getEndPosition(),(0,f.localize)(830,"Running paste handlers. Click to cancel and do basic paste"),z,{cancel:async()=>{try{if(z.cancel(),H.token.isCancellationRequested)return;await this.applyDefaultPasteHandler(x,W,H.token,V)}finally{H.dispose()}}}).then(()=>{H.dispose()}),this._currentPasteOperation=z}showPasteAsPick(O,F,x,W,V){const q=(0,I.createCancelablePromise)(async H=>{const z=this._editor;if(!z.hasModel())return;const U=z.getModel(),j=new _.DisposableStore,Y=j.add(new r.EditorStateCancellationTokenSource(z,3,void 0,H));try{if(await this.mergeInDataFromCopy(W,V,Y.token),Y.token.isCancellationRequested)return;let G=F.filter(ue=>this.isSupportedPasteProvider(ue,W,O));O&&(G=G.filter(ue=>this.providerMatchesPreference(ue,O)));const K={triggerKind:g.DocumentPasteTriggerKind.PasteAs,only:O&&O instanceof m.HierarchicalKind?O:void 0};let R=j.add(await this.getPasteEdits(G,W,U,x,K,Y.token));if(Y.token.isCancellationRequested)return;if(O&&(R={edits:R.edits.filter(ue=>O instanceof m.HierarchicalKind?O.contains(ue.kind):O.providerId===ue.provider.id),dispose:R.dispose}),!R.edits.length){K.only&&this.showPasteAsNoEditMessage(x,K.only);return}let J;if(O?J=R.edits.at(0):J=(await this._quickInputService.pick(R.edits.map(he=>({label:he.title,description:he.kind?.value,edit:he})),{placeHolder:(0,f.localize)(831,"Select Paste Action")}))?.edit,!J)return;const ie=(0,a.createCombinedWorkspaceEdit)(U.uri,x,J);await this._bulkEditService.apply(ie,{editor:this._editor})}finally{j.dispose(),this._currentPasteOperation===q&&(this._currentPasteOperation=void 0)}});this._progressService.withProgress({location:10,title:(0,f.localize)(832,"Running paste handlers")},()=>q)}setCopyMetadata(O,F){O.setData(A,JSON.stringify(F))}fetchCopyMetadata(O){if(!O.clipboardData)return;const F=O.clipboardData.getData(A);if(F)try{return JSON.parse(F)}catch{return}const[x,W]=o.ClipboardEventUtils.getTextData(O.clipboardData);if(W)return{defaultPastePayload:{mode:W.mode,multicursorText:W.multicursorText??null,pasteOnNewLine:!!W.isFromEmptySelection}}}async mergeInDataFromCopy(O,F,x){if(F?.id&&M._currentCopyOperation?.handle===F.id){const W=await M._currentCopyOperation.dataTransferPromise;if(x.isCancellationRequested)return;for(const[V,q]of W)O.replace(V,q)}if(!O.has(b.Mimes.uriList)){const W=await this._clipboardService.readResources();if(x.isCancellationRequested)return;W.length&&O.append(b.Mimes.uriList,(0,y.createStringDataTransferItem)(y.UriList.create(W)))}}async getPasteEdits(O,F,x,W,V,q){const H=new _.DisposableStore,z=await(0,I.raceCancellation)(Promise.all(O.map(async j=>{try{const Y=await j.provideDocumentPasteEdits?.(x,W,F,V,q);return Y&&H.add(Y),Y?.edits?.map(G=>({...G,provider:j}))}catch(Y){(0,T.isCancellationError)(Y)||console.error(Y);return}})),q),U=(0,k.coalesce)(z??[]).flat().filter(j=>!V.only||V.only.contains(j.kind));return{edits:(0,a.sortEditsByYieldTo)(U),dispose:()=>H.dispose()}}async applyDefaultPasteHandler(O,F,x,W){const q=await(O.get(b.Mimes.text)??O.get("text"))?.asString()??"";if(x.isCancellationRequested)return;const H={clipboardEvent:W,text:q,pasteOnNewLine:F?.defaultPastePayload.pasteOnNewLine??!1,multicursorText:F?.defaultPastePayload.multicursorText??null,mode:null};this._editor.trigger("keyboard","paste",H)}isSupportedPasteProvider(O,F,x){return O.pasteMimeTypes?.some(W=>F.matches(W))?!x||this.providerMatchesPreference(O,x):!1}providerMatchesPreference(O,F){return F instanceof m.HierarchicalKind?O.providedPasteEditKinds?O.providedPasteEditKinds.some(x=>F.contains(x)):!0:O.id===F.providerId}};e.CopyPasteController=P,e.CopyPasteController=P=M=ke([ce(1,w.IInstantiationService),ce(2,i.IBulkEditService),ce(3,h.IClipboardService),ce(4,c.ILanguageFeaturesService),ce(5,L.IQuickInputService),ce(6,S.IProgressService)],P)}),define(ne[856],se([1,0,64,5,16,212,15,34,20,435,3,29,117,12]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PasteAction=e.CopyAction=e.CutAction=void 0;const i="9_cutcopypaste",s=I.isNative||document.queryCommandSupported("cut"),g=I.isNative||document.queryCommandSupported("copy"),c=typeof navigator.clipboard>"u"||d.isFirefox?document.queryCommandSupported("paste"):!0;function l(u){return u.register(),u}e.CutAction=s?l(new y.MultiCommand({id:"editor.action.clipboardCutAction",precondition:void 0,kbOpts:I.isNative?{primary:2102,win:{primary:2102,secondary:[1044]},weight:100}:void 0,menuOpts:[{menuId:n.MenuId.MenubarEditMenu,group:"2_ccp",title:p.localize(725,"Cu&&t"),order:1},{menuId:n.MenuId.EditorContext,group:i,title:p.localize(726,"Cut"),when:_.EditorContextKeys.writable,order:1},{menuId:n.MenuId.CommandPalette,group:"",title:p.localize(727,"Cut"),order:1},{menuId:n.MenuId.SimpleEditorContext,group:i,title:p.localize(728,"Cut"),when:_.EditorContextKeys.writable,order:1}]})):void 0,e.CopyAction=g?l(new y.MultiCommand({id:"editor.action.clipboardCopyAction",precondition:void 0,kbOpts:I.isNative?{primary:2081,win:{primary:2081,secondary:[2067]},weight:100}:void 0,menuOpts:[{menuId:n.MenuId.MenubarEditMenu,group:"2_ccp",title:p.localize(729,"&&Copy"),order:2},{menuId:n.MenuId.EditorContext,group:i,title:p.localize(730,"Copy"),order:2},{menuId:n.MenuId.CommandPalette,group:"",title:p.localize(731,"Copy"),order:1},{menuId:n.MenuId.SimpleEditorContext,group:i,title:p.localize(732,"Copy"),order:2}]})):void 0,n.MenuRegistry.appendMenuItem(n.MenuId.MenubarEditMenu,{submenu:n.MenuId.MenubarCopy,title:p.localize2(738,"Copy As"),group:"2_ccp",order:3}),n.MenuRegistry.appendMenuItem(n.MenuId.EditorContext,{submenu:n.MenuId.EditorContextCopy,title:p.localize2(739,"Copy As"),group:i,order:3}),n.MenuRegistry.appendMenuItem(n.MenuId.EditorContext,{submenu:n.MenuId.EditorContextShare,title:p.localize2(740,"Share"),group:"11_share",order:-1,when:t.ContextKeyExpr.and(t.ContextKeyExpr.notEquals("resourceScheme","output"),_.EditorContextKeys.editorTextFocus)}),n.MenuRegistry.appendMenuItem(n.MenuId.ExplorerContext,{submenu:n.MenuId.ExplorerContextShare,title:p.localize2(741,"Share"),group:"11_share",order:-1}),e.PasteAction=c?l(new y.MultiCommand({id:"editor.action.clipboardPasteAction",precondition:void 0,kbOpts:I.isNative?{primary:2100,win:{primary:2100,secondary:[1043]},linux:{primary:2100,secondary:[1043]},weight:100}:void 0,menuOpts:[{menuId:n.MenuId.MenubarEditMenu,group:"2_ccp",title:p.localize(733,"&&Paste"),order:4},{menuId:n.MenuId.EditorContext,group:i,title:p.localize(734,"Paste"),when:_.EditorContextKeys.writable,order:4},{menuId:n.MenuId.CommandPalette,group:"",title:p.localize(735,"Paste"),order:1},{menuId:n.MenuId.SimpleEditorContext,group:i,title:p.localize(736,"Paste"),when:_.EditorContextKeys.writable,order:4}]})):void 0;class a extends y.EditorAction{constructor(){super({id:"editor.action.clipboardCopyWithSyntaxHighlightingAction",label:p.localize(737,"Copy With Syntax Highlighting"),alias:"Copy With Syntax Highlighting",precondition:void 0,kbOpts:{kbExpr:_.EditorContextKeys.textInputFocus,primary:0,weight:100}})}run(C,f){!f.hasModel()||!f.getOption(37)&&f.getSelection().isEmpty()||(E.CopyOptions.forceCopyWithSyntaxHighlighting=!0,f.focus(),f.getContainerDomNode().ownerDocument.execCommand("copy"),E.CopyOptions.forceCopyWithSyntaxHighlighting=!1)}}function r(u,C){u&&(u.addImplementation(1e4,"code-editor",(f,h)=>{const v=f.get(m.ICodeEditorService).getFocusedCodeEditor();if(v&&v.hasTextFocus()){const w=v.getOption(37),S=v.getSelection();return S&&S.isEmpty()&&!w||v.getContainerDomNode().ownerDocument.execCommand(C),!0}return!1}),u.addImplementation(0,"generic-dom",(f,h)=>((0,k.getActiveDocument)().execCommand(C),!0)))}r(e.CutAction,"cut"),r(e.CopyAction,"copy"),e.PasteAction&&(e.PasteAction.addImplementation(1e4,"code-editor",(u,C)=>{const f=u.get(m.ICodeEditorService),h=u.get(o.IClipboardService),v=f.getFocusedCodeEditor();return v&&v.hasTextFocus()?v.getContainerDomNode().ownerDocument.execCommand("paste")?b.CopyPasteController.get(v)?.finishedPaste()??Promise.resolve():I.isWeb?(async()=>{const S=await h.readText();if(S!==""){const L=E.InMemoryClipboardMetadataManager.INSTANCE.get(S);let D=!1,T=null,M=null;L&&(D=v.getOption(37)&&!!L.isFromEmptySelection,T=typeof L.multicursorText<"u"?L.multicursorText:null,M=L.mode),v.trigger("keyboard","paste",{text:S,pasteOnNewLine:D,multicursorText:T,mode:M})}})():!0:!1}),e.PasteAction.addImplementation(0,"generic-dom",(u,C)=>((0,k.getActiveDocument)().execCommand("paste"),!0))),g&&(0,y.registerEditorAction)(a)}),define(ne[857],se([1,0,91,15,20,130,435,293,3]),function(oe,e,d,k,I,E,y,m,_){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,k.registerEditorContribution)(y.CopyPasteController.ID,y.CopyPasteController,0),(0,E.registerEditorFeature)(m.DefaultPasteProvidersFeature),(0,k.registerEditorCommand)(new class extends k.EditorCommand{constructor(){super({id:y.changePasteTypeCommandId,precondition:y.pasteWidgetVisibleCtx,kbOpts:{weight:100,primary:2137}})}runEditorCommand(b,p){return y.CopyPasteController.get(p)?.changePasteType()}}),(0,k.registerEditorCommand)(new class extends k.EditorCommand{constructor(){super({id:"editor.hidePasteWidget",precondition:y.pasteWidgetVisibleCtx,kbOpts:{weight:100,primary:9}})}runEditorCommand(b,p){y.CopyPasteController.get(p)?.clearWidgets()}}),(0,k.registerEditorAction)(class bi extends k.EditorAction{static{this.argsSchema={type:"object",properties:{kind:{type:"string",description:_.localize(823,"The kind of the paste edit to try applying. If not provided or there are multiple edits for this kind, the editor will show a picker.")}}}}constructor(){super({id:"editor.action.pasteAs",label:_.localize(824,"Paste As..."),alias:"Paste As...",precondition:I.EditorContextKeys.writable,metadata:{description:"Paste as",args:[{name:"args",schema:bi.argsSchema}]}})}run(p,n,o){let t=typeof o?.kind=="string"?o.kind:void 0;return!t&&o&&(t=typeof o.id=="string"?o.id:void 0),y.CopyPasteController.get(n)?.pasteAs(t?new d.HierarchicalKind(t):void 0)}}),(0,k.registerEditorAction)(class extends k.EditorAction{constructor(){super({id:"editor.action.pasteAsText",label:_.localize(825,"Paste as Text"),alias:"Paste as Text",precondition:I.EditorContextKeys.writable})}run(b,p){return y.CopyPasteController.get(p)?.pasteAs({providerId:m.DefaultTextPasteOrDropEditProvider.id})}})}),define(ne[858],se([1,0,15,274,130,293,3,109,38,832]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorContribution)(b.DropIntoEditorController.ID,b.DropIntoEditorController,2),(0,I.registerEditorFeature)(E.DefaultDropProvidersFeature),(0,d.registerEditorCommand)(new class extends d.EditorCommand{constructor(){super({id:b.changeDropTypeCommandId,precondition:b.dropWidgetVisibleCtx,kbOpts:{weight:100,primary:2137}})}runEditorCommand(p,n,o){b.DropIntoEditorController.get(n)?.changeDropType()}}),(0,d.registerEditorCommand)(new class extends d.EditorCommand{constructor(){super({id:"editor.hideDropWidget",precondition:b.dropWidgetVisibleCtx,kbOpts:{weight:100,primary:9}})}runEditorCommand(p,n,o){b.DropIntoEditorController.get(n)?.clearWidgets()}}),_.Registry.as(m.Extensions.Configuration).registerConfiguration({...k.editorConfigurationBaseNode,properties:{[b.defaultProviderConfig]:{type:"object",scope:5,description:y.localize(841,"Configures the default drop provider to use for content of a given mime type."),default:{},additionalProperties:{type:"string"}}}})}),define(ne[859],se([1,0,629,99,48,11,193,36,135,3,186]),function(oe,e,d,k,I,E,y,m,_,b,p){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.RandomBasedVariableResolver=e.WorkspaceBasedVariableResolver=e.TimeBasedVariableResolver=e.CommentBasedVariableResolver=e.ClipboardBasedVariableResolver=e.ModelBasedVariableResolver=e.SelectionBasedVariableResolver=e.CompositeSnippetVariableResolver=e.KnownSnippetVariableNames=void 0,e.KnownSnippetVariableNames=Object.freeze({CURRENT_YEAR:!0,CURRENT_YEAR_SHORT:!0,CURRENT_MONTH:!0,CURRENT_DATE:!0,CURRENT_HOUR:!0,CURRENT_MINUTE:!0,CURRENT_SECOND:!0,CURRENT_DAY_NAME:!0,CURRENT_DAY_NAME_SHORT:!0,CURRENT_MONTH_NAME:!0,CURRENT_MONTH_NAME_SHORT:!0,CURRENT_SECONDS_UNIX:!0,CURRENT_TIMEZONE_OFFSET:!0,SELECTION:!0,CLIPBOARD:!0,TM_SELECTED_TEXT:!0,TM_CURRENT_LINE:!0,TM_CURRENT_WORD:!0,TM_LINE_INDEX:!0,TM_LINE_NUMBER:!0,TM_FILENAME:!0,TM_FILENAME_BASE:!0,TM_DIRECTORY:!0,TM_FILEPATH:!0,CURSOR_INDEX:!0,CURSOR_NUMBER:!0,RELATIVE_FILEPATH:!0,BLOCK_COMMENT_START:!0,BLOCK_COMMENT_END:!0,LINE_COMMENT:!0,WORKSPACE_NAME:!0,WORKSPACE_FOLDER:!0,RANDOM:!0,RANDOM_HEX:!0,UUID:!0});class n{constructor(r){this._delegates=r}resolve(r){for(const u of this._delegates){const C=u.resolve(r);if(C!==void 0)return C}}}e.CompositeSnippetVariableResolver=n;class o{constructor(r,u,C,f){this._model=r,this._selection=u,this._selectionIdx=C,this._overtypingCapturer=f}resolve(r){const{name:u}=r;if(u==="SELECTION"||u==="TM_SELECTED_TEXT"){let C=this._model.getValueInRange(this._selection)||void 0,f=this._selection.startLineNumber!==this._selection.endLineNumber;if(!C&&this._overtypingCapturer){const h=this._overtypingCapturer.getLastOvertypedInfo(this._selectionIdx);h&&(C=h.value,f=h.multiline)}if(C&&f&&r.snippet){const h=this._model.getLineContent(this._selection.startLineNumber),v=(0,E.getLeadingWhitespace)(h,0,this._selection.startColumn-1);let w=v;r.snippet.walk(L=>L===r?!1:(L instanceof _.Text&&(w=(0,E.getLeadingWhitespace)((0,E.splitLines)(L.value).pop())),!0));const S=(0,E.commonPrefixLength)(w,v);C=C.replace(/(\r\n|\r|\n)(.*)/g,(L,D,T)=>`${D}${w.substr(S)}${T}`)}return C}else{if(u==="TM_CURRENT_LINE")return this._model.getLineContent(this._selection.positionLineNumber);if(u==="TM_CURRENT_WORD"){const C=this._model.getWordAtPosition({lineNumber:this._selection.positionLineNumber,column:this._selection.positionColumn});return C&&C.word||void 0}else{if(u==="TM_LINE_INDEX")return String(this._selection.positionLineNumber-1);if(u==="TM_LINE_NUMBER")return String(this._selection.positionLineNumber);if(u==="CURSOR_INDEX")return String(this._selectionIdx);if(u==="CURSOR_NUMBER")return String(this._selectionIdx+1)}}}}e.SelectionBasedVariableResolver=o;class t{constructor(r,u){this._labelService=r,this._model=u}resolve(r){const{name:u}=r;if(u==="TM_FILENAME")return k.basename(this._model.uri.fsPath);if(u==="TM_FILENAME_BASE"){const C=k.basename(this._model.uri.fsPath),f=C.lastIndexOf(".");return f<=0?C:C.slice(0,f)}else{if(u==="TM_DIRECTORY")return k.dirname(this._model.uri.fsPath)==="."?"":this._labelService.getUriLabel((0,I.dirname)(this._model.uri));if(u==="TM_FILEPATH")return this._labelService.getUriLabel(this._model.uri);if(u==="RELATIVE_FILEPATH")return this._labelService.getUriLabel(this._model.uri,{relative:!0,noPrefix:!0})}}}e.ModelBasedVariableResolver=t;class i{constructor(r,u,C,f){this._readClipboardText=r,this._selectionIdx=u,this._selectionCount=C,this._spread=f}resolve(r){if(r.name!=="CLIPBOARD")return;const u=this._readClipboardText();if(u){if(this._spread){const C=u.split(/\r\n|\n|\r/).filter(f=>!(0,E.isFalsyOrWhitespace)(f));if(C.length===this._selectionCount)return C[this._selectionIdx]}return u}}}e.ClipboardBasedVariableResolver=i;let s=class{constructor(r,u,C){this._model=r,this._selection=u,this._languageConfigurationService=C}resolve(r){const{name:u}=r,C=this._model.getLanguageIdAtPosition(this._selection.selectionStartLineNumber,this._selection.selectionStartColumn),f=this._languageConfigurationService.getLanguageConfiguration(C).comments;if(f){if(u==="LINE_COMMENT")return f.lineCommentToken||void 0;if(u==="BLOCK_COMMENT_START")return f.blockCommentStartToken||void 0;if(u==="BLOCK_COMMENT_END")return f.blockCommentEndToken||void 0}}};e.CommentBasedVariableResolver=s,e.CommentBasedVariableResolver=s=ke([ce(2,m.ILanguageConfigurationService)],s);class g{constructor(){this._date=new Date}static{this.dayNames=[b.localize(1261,"Sunday"),b.localize(1262,"Monday"),b.localize(1263,"Tuesday"),b.localize(1264,"Wednesday"),b.localize(1265,"Thursday"),b.localize(1266,"Friday"),b.localize(1267,"Saturday")]}static{this.dayNamesShort=[b.localize(1268,"Sun"),b.localize(1269,"Mon"),b.localize(1270,"Tue"),b.localize(1271,"Wed"),b.localize(1272,"Thu"),b.localize(1273,"Fri"),b.localize(1274,"Sat")]}static{this.monthNames=[b.localize(1275,"January"),b.localize(1276,"February"),b.localize(1277,"March"),b.localize(1278,"April"),b.localize(1279,"May"),b.localize(1280,"June"),b.localize(1281,"July"),b.localize(1282,"August"),b.localize(1283,"September"),b.localize(1284,"October"),b.localize(1285,"November"),b.localize(1286,"December")]}static{this.monthNamesShort=[b.localize(1287,"Jan"),b.localize(1288,"Feb"),b.localize(1289,"Mar"),b.localize(1290,"Apr"),b.localize(1291,"May"),b.localize(1292,"Jun"),b.localize(1293,"Jul"),b.localize(1294,"Aug"),b.localize(1295,"Sep"),b.localize(1296,"Oct"),b.localize(1297,"Nov"),b.localize(1298,"Dec")]}resolve(r){const{name:u}=r;if(u==="CURRENT_YEAR")return String(this._date.getFullYear());if(u==="CURRENT_YEAR_SHORT")return String(this._date.getFullYear()).slice(-2);if(u==="CURRENT_MONTH")return String(this._date.getMonth().valueOf()+1).padStart(2,"0");if(u==="CURRENT_DATE")return String(this._date.getDate().valueOf()).padStart(2,"0");if(u==="CURRENT_HOUR")return String(this._date.getHours().valueOf()).padStart(2,"0");if(u==="CURRENT_MINUTE")return String(this._date.getMinutes().valueOf()).padStart(2,"0");if(u==="CURRENT_SECOND")return String(this._date.getSeconds().valueOf()).padStart(2,"0");if(u==="CURRENT_DAY_NAME")return g.dayNames[this._date.getDay()];if(u==="CURRENT_DAY_NAME_SHORT")return g.dayNamesShort[this._date.getDay()];if(u==="CURRENT_MONTH_NAME")return g.monthNames[this._date.getMonth()];if(u==="CURRENT_MONTH_NAME_SHORT")return g.monthNamesShort[this._date.getMonth()];if(u==="CURRENT_SECONDS_UNIX")return String(Math.floor(this._date.getTime()/1e3));if(u==="CURRENT_TIMEZONE_OFFSET"){const C=this._date.getTimezoneOffset(),f=C>0?"-":"+",h=Math.trunc(Math.abs(C/60)),v=h<10?"0"+h:h,w=Math.abs(C)-h*60,S=w<10?"0"+w:w;return f+v+":"+S}}}e.TimeBasedVariableResolver=g;class c{constructor(r){this._workspaceService=r}resolve(r){if(!this._workspaceService)return;const u=(0,p.toWorkspaceIdentifier)(this._workspaceService.getWorkspace());if(!(0,p.isEmptyWorkspaceIdentifier)(u)){if(r.name==="WORKSPACE_NAME")return this._resolveWorkspaceName(u);if(r.name==="WORKSPACE_FOLDER")return this._resoveWorkspacePath(u)}}_resolveWorkspaceName(r){if((0,p.isSingleFolderWorkspaceIdentifier)(r))return k.basename(r.uri.path);let u=k.basename(r.configPath.path);return u.endsWith(p.WORKSPACE_EXTENSION)&&(u=u.substr(0,u.length-p.WORKSPACE_EXTENSION.length-1)),u}_resoveWorkspacePath(r){if((0,p.isSingleFolderWorkspaceIdentifier)(r))return(0,d.normalizeDriveLetter)(r.uri.fsPath);const u=k.basename(r.configPath.path);let C=r.configPath.fsPath;return C.endsWith(u)&&(C=C.substr(0,C.length-u.length-1)),C?(0,d.normalizeDriveLetter)(C):"/"}}e.WorkspaceBasedVariableResolver=c;class l{resolve(r){const{name:u}=r;if(u==="RANDOM")return Math.random().toString().slice(-6);if(u==="RANDOM_HEX")return Math.random().toString(16).slice(-6);if(u==="UUID")return(0,y.generateUuid)()}}e.RandomBasedVariableResolver=l}),define(ne[436],se([1,0,13,2,11,75,4,23,36,35,181,186,135,859,530]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";var i;Object.defineProperty(e,"__esModule",{value:!0}),e.SnippetSession=e.OneSnippet=void 0;class s{static{this._decor={active:b.ModelDecorationOptions.register({description:"snippet-placeholder-1",stickiness:0,className:"snippet-placeholder"}),inactive:b.ModelDecorationOptions.register({description:"snippet-placeholder-2",stickiness:1,className:"snippet-placeholder"}),activeFinal:b.ModelDecorationOptions.register({description:"snippet-placeholder-3",stickiness:1,className:"finish-snippet-placeholder"}),inactiveFinal:b.ModelDecorationOptions.register({description:"snippet-placeholder-4",stickiness:1,className:"finish-snippet-placeholder"})}}constructor(a,r,u){this._editor=a,this._snippet=r,this._snippetLineLeadingWhitespace=u,this._offset=-1,this._nestingLevel=1,this._placeholderGroups=(0,d.groupBy)(r.placeholders,o.Placeholder.compareByIndex),this._placeholderGroupsIdx=-1}initialize(a){this._offset=a.newPosition}dispose(){this._placeholderDecorations&&this._editor.removeDecorations([...this._placeholderDecorations.values()]),this._placeholderGroups.length=0}_initDecorations(){if(this._offset===-1)throw new Error("Snippet not initialized!");if(this._placeholderDecorations)return;this._placeholderDecorations=new Map;const a=this._editor.getModel();this._editor.changeDecorations(r=>{for(const u of this._snippet.placeholders){const C=this._snippet.offset(u),f=this._snippet.fullLen(u),h=y.Range.fromPositions(a.getPositionAt(this._offset+C),a.getPositionAt(this._offset+C+f)),v=u.isFinalTabstop?s._decor.inactiveFinal:s._decor.inactive,w=r.addDecoration(h,v);this._placeholderDecorations.set(u,w)}})}move(a){if(!this._editor.hasModel())return[];if(this._initDecorations(),this._placeholderGroupsIdx>=0){const C=[];for(const f of this._placeholderGroups[this._placeholderGroupsIdx])if(f.transform){const h=this._placeholderDecorations.get(f),v=this._editor.getModel().getDecorationRange(h),w=this._editor.getModel().getValueInRange(v),S=f.transform.resolve(w).split(/\r\n|\r|\n/);for(let L=1;L0&&this._editor.executeEdits("snippet.placeholderTransform",C)}let r=!1;a===!0&&this._placeholderGroupsIdx0&&(this._placeholderGroupsIdx-=1,r=!0);const u=this._editor.getModel().changeDecorations(C=>{const f=new Set,h=[];for(const v of this._placeholderGroups[this._placeholderGroupsIdx]){const w=this._placeholderDecorations.get(v),S=this._editor.getModel().getDecorationRange(w);h.push(new m.Selection(S.startLineNumber,S.startColumn,S.endLineNumber,S.endColumn)),r=r&&this._hasPlaceholderBeenCollapsed(v),C.changeDecorationOptions(w,v.isFinalTabstop?s._decor.activeFinal:s._decor.active),f.add(v);for(const L of this._snippet.enclosingPlaceholders(v)){const D=this._placeholderDecorations.get(L);C.changeDecorationOptions(D,L.isFinalTabstop?s._decor.activeFinal:s._decor.active),f.add(L)}}for(const[v,w]of this._placeholderDecorations)f.has(v)||C.changeDecorationOptions(w,v.isFinalTabstop?s._decor.inactiveFinal:s._decor.inactive);return h});return r?this.move(a):u??[]}_hasPlaceholderBeenCollapsed(a){let r=a;for(;r;){if(r instanceof o.Placeholder){const u=this._placeholderDecorations.get(r);if(this._editor.getModel().getDecorationRange(u).isEmpty()&&r.toString().length>0)return!0}r=r.parent}return!1}get isAtFirstPlaceholder(){return this._placeholderGroupsIdx<=0||this._placeholderGroups.length===0}get isAtLastPlaceholder(){return this._placeholderGroupsIdx===this._placeholderGroups.length-1}get hasPlaceholder(){return this._snippet.placeholders.length>0}get isTrivialSnippet(){if(this._snippet.placeholders.length===0)return!0;if(this._snippet.placeholders.length===1){const[a]=this._snippet.placeholders;if(a.isFinalTabstop&&this._snippet.rightMostDescendant===a)return!0}return!1}computePossibleSelections(){const a=new Map;for(const r of this._placeholderGroups){let u;for(const C of r){if(C.isFinalTabstop)break;u||(u=[],a.set(C.index,u));const f=this._placeholderDecorations.get(C),h=this._editor.getModel().getDecorationRange(f);if(!h){a.delete(C.index);break}u.push(h)}}return a}get activeChoice(){if(!this._placeholderDecorations)return;const a=this._placeholderGroups[this._placeholderGroupsIdx][0];if(!a?.choice)return;const r=this._placeholderDecorations.get(a);if(!r)return;const u=this._editor.getModel().getDecorationRange(r);if(u)return{range:u,choice:a.choice}}get hasChoice(){let a=!1;return this._snippet.walk(r=>(a=r instanceof o.Choice,!a)),a}merge(a){const r=this._editor.getModel();this._nestingLevel*=10,this._editor.changeDecorations(u=>{for(const C of this._placeholderGroups[this._placeholderGroupsIdx]){const f=a.shift();console.assert(f._offset!==-1),console.assert(!f._placeholderDecorations);const h=f._snippet.placeholderInfo.last.index;for(const w of f._snippet.placeholderInfo.all)w.isFinalTabstop?w.index=C.index+(h+1)/this._nestingLevel:w.index=C.index+w.index/this._nestingLevel;this._snippet.replace(C,f._snippet.children);const v=this._placeholderDecorations.get(C);u.removeDecoration(v),this._placeholderDecorations.delete(C);for(const w of f._snippet.placeholders){const S=f._snippet.offset(w),L=f._snippet.fullLen(w),D=y.Range.fromPositions(r.getPositionAt(f._offset+S),r.getPositionAt(f._offset+S+L)),T=u.addDecoration(D,s._decor.inactive);this._placeholderDecorations.set(w,T)}}this._placeholderGroups=(0,d.groupBy)(this._snippet.placeholders,o.Placeholder.compareByIndex)})}}e.OneSnippet=s;const g={overwriteBefore:0,overwriteAfter:0,adjustWhitespace:!0,clipboardText:void 0,overtypingCapturer:void 0};let c=i=class{static adjustWhitespace(a,r,u,C,f){const h=a.getLineContent(r.lineNumber),v=(0,I.getLeadingWhitespace)(h,0,r.column-1);let w;return C.walk(S=>{if(!(S instanceof o.Text)||S.parent instanceof o.Choice||f&&!f.has(S))return!0;const L=S.value.split(/\r\n|\r|\n/);if(u){const T=C.offset(S);if(T===0)L[0]=a.normalizeIndentation(L[0]);else{w=w??C.toString();const M=w.charCodeAt(T-1);(M===10||M===13)&&(L[0]=a.normalizeIndentation(v+L[0]))}for(let M=1;MW.get(n.IWorkspaceContextService)),A=a.invokeWithinContext(W=>new t.ModelBasedVariableResolver(W.get(p.ILabelService),T)),P=()=>v,N=T.getValueInRange(i.adjustSelection(T,a.getSelection(),u,0)),O=T.getValueInRange(i.adjustSelection(T,a.getSelection(),0,C)),F=T.getLineFirstNonWhitespaceColumn(a.getSelection().positionLineNumber),x=a.getSelections().map((W,V)=>({selection:W,idx:V})).sort((W,V)=>y.Range.compareRangesUsingStarts(W.selection,V.selection));for(const{selection:W,idx:V}of x){let q=i.adjustSelection(T,W,u,0),H=i.adjustSelection(T,W,0,C);N!==T.getValueInRange(q)&&(q=W),O!==T.getValueInRange(H)&&(H=W);const z=W.setStartPosition(q.startLineNumber,q.startColumn).setEndPosition(H.endLineNumber,H.endColumn),U=new o.SnippetParser().parse(r,!0,f),j=z.getStartPosition(),Y=i.adjustWhitespace(T,j,h||V>0&&F!==T.getLineFirstNonWhitespaceColumn(W.positionLineNumber),U);U.resolveVariables(new t.CompositeSnippetVariableResolver([A,new t.ClipboardBasedVariableResolver(P,V,x.length,a.getOption(79)==="spread"),new t.SelectionBasedVariableResolver(T,W,V,w),new t.CommentBasedVariableResolver(T,W,S),new t.TimeBasedVariableResolver,new t.WorkspaceBasedVariableResolver(M),new t.RandomBasedVariableResolver])),L[V]=E.EditOperation.replace(z,U.toString()),L[V].identifier={major:V,minor:0},L[V]._isTracked=!0,D[V]=new s(a,U,Y)}return{edits:L,snippets:D}}static createEditsAndSnippetsFromEdits(a,r,u,C,f,h,v){if(!a.hasModel()||r.length===0)return{edits:[],snippets:[]};const w=[],S=a.getModel(),L=new o.SnippetParser,D=new o.TextmateSnippet,T=new t.CompositeSnippetVariableResolver([a.invokeWithinContext(A=>new t.ModelBasedVariableResolver(A.get(p.ILabelService),S)),new t.ClipboardBasedVariableResolver(()=>f,0,a.getSelections().length,a.getOption(79)==="spread"),new t.SelectionBasedVariableResolver(S,a.getSelection(),0,h),new t.CommentBasedVariableResolver(S,a.getSelection(),v),new t.TimeBasedVariableResolver,new t.WorkspaceBasedVariableResolver(a.invokeWithinContext(A=>A.get(n.IWorkspaceContextService))),new t.RandomBasedVariableResolver]);r=r.sort((A,P)=>y.Range.compareRangesUsingStarts(A.range,P.range));let M=0;for(let A=0;A0){const V=r[A-1].range,q=y.Range.fromPositions(V.getEndPosition(),P.getStartPosition()),H=new o.Text(S.getValueInRange(q));D.appendChild(H),M+=H.value.length}const O=L.parseFragment(N,D);i.adjustWhitespace(S,P.getStartPosition(),!0,D,new Set(O)),D.resolveVariables(T);const F=D.toString(),x=F.slice(M);M=F.length;const W=E.EditOperation.replace(P,x);W.identifier={major:A,minor:0},W._isTracked=!0,w.push(W)}return L.ensureFinalTabstop(D,u,!0),{edits:w,snippets:[new s(a,D,"")]}}constructor(a,r,u=g,C){this._editor=a,this._template=r,this._options=u,this._languageConfigurationService=C,this._templateMerges=[],this._snippets=[]}dispose(){(0,k.dispose)(this._snippets)}_logInfo(){return`template="${this._template}", merged_templates="${this._templateMerges.join(" -> ")}"`}insert(){if(!this._editor.hasModel())return;const{edits:a,snippets:r}=typeof this._template=="string"?i.createEditsAndSnippetsFromSelections(this._editor,this._template,this._options.overwriteBefore,this._options.overwriteAfter,!1,this._options.adjustWhitespace,this._options.clipboardText,this._options.overtypingCapturer,this._languageConfigurationService):i.createEditsAndSnippetsFromEdits(this._editor,this._template,!1,this._options.adjustWhitespace,this._options.clipboardText,this._options.overtypingCapturer,this._languageConfigurationService);this._snippets=r,this._editor.executeEdits("snippet",a,u=>{const C=u.filter(f=>!!f.identifier);for(let f=0;fm.Selection.fromPositions(f.range.getEndPosition()))}),this._editor.revealRange(this._editor.getSelections()[0])}merge(a,r=g){if(!this._editor.hasModel())return;this._templateMerges.push([this._snippets[0]._nestingLevel,this._snippets[0]._placeholderGroupsIdx,a]);const{edits:u,snippets:C}=i.createEditsAndSnippetsFromSelections(this._editor,a,r.overwriteBefore,r.overwriteAfter,!0,r.adjustWhitespace,r.clipboardText,r.overtypingCapturer,this._languageConfigurationService);this._editor.executeEdits("snippet",u,f=>{const h=f.filter(w=>!!w.identifier);for(let w=0;wm.Selection.fromPositions(w.range.getEndPosition()))})}next(){const a=this._move(!0);this._editor.setSelections(a),this._editor.revealPositionInCenterIfOutsideViewport(a[0].getPosition())}prev(){const a=this._move(!1);this._editor.setSelections(a),this._editor.revealPositionInCenterIfOutsideViewport(a[0].getPosition())}_move(a){const r=[];for(const u of this._snippets){const C=u.move(a);r.push(...C)}return r}get isAtFirstPlaceholder(){return this._snippets[0].isAtFirstPlaceholder}get isAtLastPlaceholder(){return this._snippets[0].isAtLastPlaceholder}get hasPlaceholder(){return this._snippets[0].hasPlaceholder}get hasChoice(){return this._snippets[0].hasChoice}get activeChoice(){return this._snippets[0].activeChoice}isSelectionWithinPlaceholders(){if(!this.hasPlaceholder)return!1;const a=this._editor.getSelections();if(a.length{f.push(...C.get(h))})}a.sort(y.Range.compareRangesUsingStarts);for(const[u,C]of r){if(C.length!==a.length){r.delete(u);continue}C.sort(y.Range.compareRangesUsingStarts);for(let f=0;f0}};e.SnippetSession=c,e.SnippetSession=c=i=ke([ce(3,_.ILanguageConfigurationService)],c)}),define(ne[221],se([1,0,2,19,15,9,20,36,17,155,3,12,62,436]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";var i;Object.defineProperty(e,"__esModule",{value:!0}),e.SnippetController2=void 0;const s={overwriteBefore:0,overwriteAfter:0,undoStopBefore:!0,undoStopAfter:!0,adjustWhitespace:!0,clipboardText:void 0,overtypingCapturer:void 0};let g=class{static{i=this}static{this.ID="snippetController2"}static get(a){return a.getContribution(i.ID)}static{this.InSnippetMode=new n.RawContextKey("inSnippetMode",!1,(0,p.localize)(1257,"Whether the editor in current in snippet mode"))}static{this.HasNextTabstop=new n.RawContextKey("hasNextTabstop",!1,(0,p.localize)(1258,"Whether there is a next tab stop when in snippet mode"))}static{this.HasPrevTabstop=new n.RawContextKey("hasPrevTabstop",!1,(0,p.localize)(1259,"Whether there is a previous tab stop when in snippet mode"))}constructor(a,r,u,C,f){this._editor=a,this._logService=r,this._languageFeaturesService=u,this._languageConfigurationService=f,this._snippetListener=new d.DisposableStore,this._modelVersionId=-1,this._inSnippet=i.InSnippetMode.bindTo(C),this._hasNextTabstop=i.HasNextTabstop.bindTo(C),this._hasPrevTabstop=i.HasPrevTabstop.bindTo(C)}dispose(){this._inSnippet.reset(),this._hasPrevTabstop.reset(),this._hasNextTabstop.reset(),this._session?.dispose(),this._snippetListener.dispose()}insert(a,r){try{this._doInsert(a,typeof r>"u"?s:{...s,...r})}catch(u){this.cancel(),this._logService.error(u),this._logService.error("snippet_error"),this._logService.error("insert_template=",a),this._logService.error("existing_template=",this._session?this._session._logInfo():"")}}_doInsert(a,r){if(this._editor.hasModel()){if(this._snippetListener.clear(),r.undoStopBefore&&this._editor.getModel().pushStackElement(),this._session&&typeof a!="string"&&this.cancel(),this._session?((0,k.assertType)(typeof a=="string"),this._session.merge(a,r)):(this._modelVersionId=this._editor.getModel().getAlternativeVersionId(),this._session=new t.SnippetSession(this._editor,a,r,this._languageConfigurationService),this._session.insert()),r.undoStopAfter&&this._editor.getModel().pushStackElement(),this._session?.hasChoice){const u={_debugDisplayName:"snippetChoiceCompletions",provideCompletionItems:(S,L)=>{if(!this._session||S!==this._editor.getModel()||!E.Position.equals(this._editor.getPosition(),L))return;const{activeChoice:D}=this._session;if(!D||D.choice.options.length===0)return;const T=S.getValueInRange(D.range),M=!!D.choice.options.find(P=>P.value===T),A=[];for(let P=0;P{f?.dispose(),h=!1},w=()=>{h||(f=this._languageFeaturesService.completionProvider.register({language:C.getLanguageId(),pattern:C.uri.fsPath,scheme:C.uri.scheme,exclusive:!0},u),this._snippetListener.add(f),h=!0)};this._choiceCompletions={provider:u,enable:w,disable:v}}this._updateState(),this._snippetListener.add(this._editor.onDidChangeModelContent(u=>u.isFlush&&this.cancel())),this._snippetListener.add(this._editor.onDidChangeModel(()=>this.cancel())),this._snippetListener.add(this._editor.onDidChangeCursorSelection(()=>this._updateState()))}}_updateState(){if(!(!this._session||!this._editor.hasModel())){if(this._modelVersionId===this._editor.getModel().getAlternativeVersionId())return this.cancel();if(!this._session.hasPlaceholder)return this.cancel();if(this._session.isAtLastPlaceholder||!this._session.isSelectionWithinPlaceholders())return this._editor.getModel().pushStackElement(),this.cancel();this._inSnippet.set(!0),this._hasPrevTabstop.set(!this._session.isAtFirstPlaceholder),this._hasNextTabstop.set(!this._session.isAtLastPlaceholder),this._handleChoice()}}_handleChoice(){if(!this._session||!this._editor.hasModel()){this._currentChoice=void 0;return}const{activeChoice:a}=this._session;if(!a||!this._choiceCompletions){this._choiceCompletions?.disable(),this._currentChoice=void 0;return}this._currentChoice!==a.choice&&(this._currentChoice=a.choice,this._choiceCompletions.enable(),queueMicrotask(()=>{(0,b.showSimpleSuggestions)(this._editor,this._choiceCompletions.provider)}))}finish(){for(;this._inSnippet.get();)this.next()}cancel(a=!1){this._inSnippet.reset(),this._hasPrevTabstop.reset(),this._hasNextTabstop.reset(),this._snippetListener.clear(),this._currentChoice=void 0,this._session?.dispose(),this._session=void 0,this._modelVersionId=-1,a&&this._editor.setSelections([this._editor.getSelection()])}prev(){this._session?.prev(),this._updateState()}next(){this._session?.next(),this._updateState()}isInSnippet(){return!!this._inSnippet.get()}};e.SnippetController2=g,e.SnippetController2=g=i=ke([ce(1,o.ILogService),ce(2,_.ILanguageFeaturesService),ce(3,n.IContextKeyService),ce(4,m.ILanguageConfigurationService)],g),(0,I.registerEditorContribution)(g.ID,g,4);const c=I.EditorCommand.bindToContribution(g.get);(0,I.registerEditorCommand)(new c({id:"jumpToNextSnippetPlaceholder",precondition:n.ContextKeyExpr.and(g.InSnippetMode,g.HasNextTabstop),handler:l=>l.next(),kbOpts:{weight:130,kbExpr:y.EditorContextKeys.textInputFocus,primary:2}})),(0,I.registerEditorCommand)(new c({id:"jumpToPrevSnippetPlaceholder",precondition:n.ContextKeyExpr.and(g.InSnippetMode,g.HasPrevTabstop),handler:l=>l.prev(),kbOpts:{weight:130,kbExpr:y.EditorContextKeys.textInputFocus,primary:1026}})),(0,I.registerEditorCommand)(new c({id:"leaveSnippet",precondition:g.InSnippetMode,handler:l=>l.cancel(!0),kbOpts:{weight:130,kbExpr:y.EditorContextKeys.textInputFocus,primary:9,secondary:[1033]}})),(0,I.registerEditorCommand)(new c({id:"acceptSnippet",precondition:g.InSnippetMode,handler:l=>l.finish()}))}),define(ne[860],se([1,0,13,67,102,8,2,21,11,19,75,9,4,23,104,113,27,36,204,715,246,205,221,24,7]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.VersionIdChangeReason=e.InlineCompletionsModel=void 0,e.getSecondaryEdits=S;let v=class extends y.Disposable{get isAcceptingPartially(){return this._isAcceptingPartially}constructor(M,A,P,N,O,F,x,W,V,q,H,z){super(),this.textModel=M,this.selectedSuggestItem=A,this._textModelVersionId=P,this._positions=N,this._debounceValue=O,this._suggestPreviewEnabled=F,this._suggestPreviewMode=x,this._inlineSuggestMode=W,this._enabled=V,this._instantiationService=q,this._commandService=H,this._languageConfigurationService=z,this._source=this._register(this._instantiationService.createInstance(a.InlineCompletionsSource,this.textModel,this._textModelVersionId,this._debounceValue)),this._isActive=(0,m.observableValue)(this,!1),this._forceUpdateExplicitlySignal=(0,m.observableSignal)(this),this._selectedInlineCompletionId=(0,m.observableValue)(this,void 0),this._primaryPosition=(0,m.derived)(this,j=>this._positions.read(j)[0]??new n.Position(1,1)),this._isAcceptingPartially=!1,this._preserveCurrentCompletionReasons=new Set([w.Redo,w.Undo,w.AcceptWord]),this._fetchInlineCompletionsPromise=(0,m.derivedHandleChanges)({owner:this,createEmptyChangeSummary:()=>({preserveCurrentCompletion:!1,inlineCompletionTriggerKind:g.InlineCompletionTriggerKind.Automatic}),handleChange:(j,Y)=>(j.didChange(this._textModelVersionId)&&this._preserveCurrentCompletionReasons.has(this._getReason(j.change))?Y.preserveCurrentCompletion=!0:j.didChange(this._forceUpdateExplicitlySignal)&&(Y.inlineCompletionTriggerKind=g.InlineCompletionTriggerKind.Explicit),!0)},(j,Y)=>{if(this._forceUpdateExplicitlySignal.read(j),!(this._enabled.read(j)&&this.selectedSuggestItem.read(j)||this._isActive.read(j))){this._source.cancelUpdate();return}this._textModelVersionId.read(j);const K=this._source.suggestWidgetInlineCompletions.get(),R=this.selectedSuggestItem.read(j);if(K&&!R){const pe=this._source.inlineCompletions.get();(0,m.transaction)(ae=>{(!pe||K.request.versionId>pe.request.versionId)&&this._source.inlineCompletions.set(K.clone(),ae),this._source.clearSuggestWidgetInlineCompletions(ae)})}const J=this._primaryPosition.read(j),ie={triggerKind:Y.inlineCompletionTriggerKind,selectedSuggestionInfo:R?.toSelectedSuggestionInfo()},ue=this.selectedInlineCompletion.get(),he=Y.preserveCurrentCompletion||ue?.forwardStable?ue:void 0;return this._source.fetch(J,ie,he)}),this._filteredInlineCompletionItems=(0,m.derivedOpts)({owner:this,equalsFn:(0,I.itemsEquals)()},j=>{const Y=this._source.inlineCompletions.read(j);if(!Y)return[];const G=this._primaryPosition.read(j);return Y.inlineCompletions.filter(R=>R.isVisible(this.textModel,G,j))}),this.selectedInlineCompletionIndex=(0,m.derived)(this,j=>{const Y=this._selectedInlineCompletionId.read(j),G=this._filteredInlineCompletionItems.read(j),K=this._selectedInlineCompletionId===void 0?-1:G.findIndex(R=>R.semanticId===Y);return K===-1?(this._selectedInlineCompletionId.set(void 0,void 0),0):K}),this.selectedInlineCompletion=(0,m.derived)(this,j=>{const Y=this._filteredInlineCompletionItems.read(j),G=this.selectedInlineCompletionIndex.read(j);return Y[G]}),this.activeCommands=(0,m.derivedOpts)({owner:this,equalsFn:(0,I.itemsEquals)()},j=>this.selectedInlineCompletion.read(j)?.inlineCompletion.source.inlineCompletions.commands??[]),this.lastTriggerKind=this._source.inlineCompletions.map(this,j=>j?.request.context.triggerKind),this.inlineCompletionsCount=(0,m.derived)(this,j=>{if(this.lastTriggerKind.read(j)===g.InlineCompletionTriggerKind.Explicit)return this._filteredInlineCompletionItems.read(j).length}),this.state=(0,m.derivedOpts)({owner:this,equalsFn:(j,Y)=>!j||!Y?j===Y:(0,l.ghostTextsOrReplacementsEqual)(j.ghostTexts,Y.ghostTexts)&&j.inlineCompletion===Y.inlineCompletion&&j.suggestItem===Y.suggestItem},j=>{const Y=this.textModel,G=this.selectedSuggestItem.read(j);if(G){const K=(0,r.singleTextRemoveCommonPrefix)(G.toSingleTextEdit(),Y),R=this._computeAugmentation(K,j);if(!this._suggestPreviewEnabled.read(j)&&!R)return;const ie=R?.edit??K,ue=R?R.edit.text.length-K.text.length:0,he=this._suggestPreviewMode.read(j),pe=this._positions.read(j),ae=[ie,...S(this.textModel,pe,ie)],ee=ae.map((ge,X)=>(0,r.computeGhostText)(ge,Y,he,pe[X],ue)).filter(b.isDefined),de=ee[0]??new l.GhostText(ie.range.endLineNumber,[]);return{edits:ae,primaryGhostText:de,ghostTexts:ee,inlineCompletion:R?.completion,suggestItem:G}}else{if(!this._isActive.read(j))return;const K=this.selectedInlineCompletion.read(j);if(!K)return;const R=K.toSingleTextEdit(j),J=this._inlineSuggestMode.read(j),ie=this._positions.read(j),ue=[R,...S(this.textModel,ie,R)],he=ue.map((pe,ae)=>(0,r.computeGhostText)(pe,Y,J,ie[ae],0)).filter(b.isDefined);return he[0]?{edits:ue,primaryGhostText:he[0],ghostTexts:he,inlineCompletion:K,suggestItem:void 0}:void 0}}),this.ghostTexts=(0,m.derivedOpts)({owner:this,equalsFn:l.ghostTextsOrReplacementsEqual},j=>{const Y=this.state.read(j);if(Y)return Y.ghostTexts}),this.primaryGhostText=(0,m.derivedOpts)({owner:this,equalsFn:l.ghostTextOrReplacementEquals},j=>{const Y=this.state.read(j);if(Y)return Y?.primaryGhostText}),this._register((0,m.recomputeInitiallyAndOnChange)(this._fetchInlineCompletionsPromise));let U;this._register((0,m.autorun)(j=>{const G=this.state.read(j)?.inlineCompletion;if(G?.semanticId!==U?.semanticId&&(U=G,G)){const K=G.inlineCompletion,R=K.source;R.provider.handleItemDidShow?.(R.inlineCompletions,K.sourceInlineCompletion,K.insertText)}}))}_getReason(M){return M?.isUndoing?w.Undo:M?.isRedoing?w.Redo:this.isAcceptingPartially?w.AcceptWord:w.Other}async trigger(M){this._isActive.set(!0,M),await this._fetchInlineCompletionsPromise.get()}async triggerExplicitly(M){(0,m.subtransaction)(M,A=>{this._isActive.set(!0,A),this._forceUpdateExplicitlySignal.trigger(A)}),await this._fetchInlineCompletionsPromise.get()}stop(M){(0,m.subtransaction)(M,A=>{this._isActive.set(!1,A),this._source.clear(A)})}_computeAugmentation(M,A){const P=this.textModel,N=this._source.suggestWidgetInlineCompletions.read(A),O=N?N.inlineCompletions:[this.selectedInlineCompletion.read(A)].filter(b.isDefined);return(0,k.mapFindFirst)(O,x=>{let W=x.toSingleTextEdit(A);return W=(0,r.singleTextRemoveCommonPrefix)(W,P,o.Range.fromPositions(W.range.getStartPosition(),M.range.getEndPosition())),(0,r.singleTextEditAugments)(W,M)?{completion:x,edit:W}:void 0})}async _deltaSelectedInlineCompletionIndex(M){await this.triggerExplicitly();const A=this._filteredInlineCompletionItems.get()||[];if(A.length>0){const P=(this.selectedInlineCompletionIndex.get()+M+A.length)%A.length;this._selectedInlineCompletionId.set(A[P].semanticId,void 0)}else this._selectedInlineCompletionId.set(void 0,void 0)}async next(){await this._deltaSelectedInlineCompletionIndex(1)}async previous(){await this._deltaSelectedInlineCompletionIndex(-1)}async accept(M){if(M.getModel()!==this.textModel)throw new E.BugIndicatingError;const A=this.state.get();if(!A||A.primaryGhostText.isEmpty()||!A.inlineCompletion)return;const P=A.inlineCompletion.toInlineCompletion(void 0);if(P.command&&P.source.addRef(),M.pushUndoStop(),P.snippetInfo)M.executeEdits("inlineSuggestion.accept",[p.EditOperation.replace(P.range,""),...P.additionalTextEdits]),M.setPosition(P.snippetInfo.range.getStartPosition(),"inlineCompletionAccept"),C.SnippetController2.get(M)?.insert(P.snippetInfo.snippet,{undoStopBefore:!1});else{const N=A.edits,O=D(N).map(F=>t.Selection.fromPositions(F));M.executeEdits("inlineSuggestion.accept",[...N.map(F=>p.EditOperation.replace(F.range,F.text)),...P.additionalTextEdits]),M.setSelections(O,"inlineCompletionAccept")}this.stop(),P.command&&(await this._commandService.executeCommand(P.command.id,...P.command.arguments||[]).then(void 0,E.onUnexpectedExternalError),P.source.removeRef())}async acceptNextWord(M){await this._acceptNext(M,(A,P)=>{const N=this.textModel.getLanguageIdAtPosition(A.lineNumber,A.column),O=this._languageConfigurationService.getLanguageConfiguration(N),F=new RegExp(O.wordDefinition.source,O.wordDefinition.flags.replace("g","")),x=P.match(F);let W=0;x&&x.index!==void 0?x.index===0?W=x[0].length:W=x.index:W=P.length;const q=/\s+/g.exec(P);return q&&q.index!==void 0&&q.index+q[0].length{const N=P.match(/\n/);return N&&N.index!==void 0?N.index+1:P.length},1)}async _acceptNext(M,A,P){if(M.getModel()!==this.textModel)throw new E.BugIndicatingError;const N=this.state.get();if(!N||N.primaryGhostText.isEmpty()||!N.inlineCompletion)return;const O=N.primaryGhostText,F=N.inlineCompletion.toInlineCompletion(void 0);if(F.snippetInfo||F.filterText!==F.insertText){await this.accept(M);return}const x=O.parts[0],W=new n.Position(O.lineNumber,x.column),V=x.text,q=A(W,V);if(q===V.length&&O.parts.length===1){this.accept(M);return}const H=V.substring(0,q),z=this._positions.get(),U=z[0];F.source.addRef();try{this._isAcceptingPartially=!0;try{M.pushUndoStop();const j=o.Range.fromPositions(U,W),Y=M.getModel().getValueInRange(j)+H,G=new i.SingleTextEdit(j,Y),K=[G,...S(this.textModel,z,G)],R=D(K).map(J=>t.Selection.fromPositions(J));M.executeEdits("inlineSuggestion.accept",K.map(J=>p.EditOperation.replace(J.range,J.text))),M.setSelections(R,"inlineCompletionPartialAccept"),M.revealPositionInCenterIfOutsideViewport(M.getPosition(),1)}finally{this._isAcceptingPartially=!1}if(F.source.provider.handlePartialAccept){const j=o.Range.fromPositions(F.range.getStartPosition(),s.TextLength.ofText(H).addToPosition(W)),Y=M.getModel().getValueInRange(j,1);F.source.provider.handlePartialAccept(F.source.inlineCompletions,F.sourceInlineCompletion,Y.length,{kind:P})}}finally{F.source.removeRef()}}handleSuggestAccepted(M){const A=(0,r.singleTextRemoveCommonPrefix)(M.toSingleTextEdit(),this.textModel),P=this._computeAugmentation(A,void 0);if(!P)return;const N=P.completion.inlineCompletion;N.source.provider.handlePartialAccept?.(N.source.inlineCompletions,N.sourceInlineCompletion,A.text.length,{kind:2})}};e.InlineCompletionsModel=v,e.InlineCompletionsModel=v=ke([ce(9,h.IInstantiationService),ce(10,f.ICommandService),ce(11,c.ILanguageConfigurationService)],v);var w;(function(T){T[T.Undo=0]="Undo",T[T.Redo=1]="Redo",T[T.AcceptWord=2]="AcceptWord",T[T.Other=3]="Other"})(w||(e.VersionIdChangeReason=w={}));function S(T,M,A){if(M.length===1)return[];const P=M[0],N=M.slice(1),O=A.range.getStartPosition(),F=A.range.getEndPosition(),x=T.getValueInRange(o.Range.fromPositions(P,F)),W=(0,u.subtractPositions)(P,O);if(W.lineNumber<1)return(0,E.onUnexpectedError)(new E.BugIndicatingError(`positionWithinTextEdit line number should be bigger than 0. Invalid subtraction between ${P.toString()} and ${O.toString()}`)),[];const V=L(A.text,W);return N.map(q=>{const H=(0,u.addPositions)((0,u.subtractPositions)(q,O),F),z=T.getValueInRange(o.Range.fromPositions(q,H)),U=(0,_.commonPrefixLength)(x,z),j=o.Range.fromPositions(q,q.delta(0,U));return new i.SingleTextEdit(j,V)})}function L(T,M){let A="";const P=(0,_.splitLinesIncludeSeparators)(T);for(let N=M.lineNumber-1;NO.range,o.Range.compareRangesUsingStarts)),P=new i.TextEdit(M.apply(T)).getNewRanges();return M.inverse().apply(P).map(O=>O.getEndPosition())}}),define(ne[437],se([1,0,14,18,8,6,2,11,23,100,343,117,28,12,62,63,342,155,17,82,19,269,221,271]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f){"use strict";var h;Object.defineProperty(e,"__esModule",{value:!0}),e.SuggestModel=e.LineContext=void 0;class v{static shouldAutoTrigger(T){if(!T.hasModel())return!1;const M=T.getModel(),A=T.getPosition();M.tokenization.tokenizeIfCheap(A.lineNumber);const P=M.getWordAtPosition(A);return!(!P||P.endColumn!==A.column&&P.startColumn+1!==A.column||!isNaN(Number(P.word)))}constructor(T,M,A){this.leadingLineContent=T.getLineContent(M.lineNumber).substr(0,M.column-1),this.leadingWord=T.getWordUntilPosition(M),this.lineNumber=M.lineNumber,this.column=M.column,this.triggerOptions=A}}e.LineContext=v;function w(D,T,M){if(!T.getContextKeyValue(u.InlineCompletionContextKeys.inlineSuggestionVisible.key))return!0;const A=T.getContextKeyValue(u.InlineCompletionContextKeys.suppressSuggestions.key);return A!==void 0?!A:!D.getOption(62).suppressSuggestions}function S(D,T,M){if(!T.getContextKeyValue("inlineSuggestionVisible"))return!0;const A=T.getContextKeyValue(u.InlineCompletionContextKeys.suppressSuggestions.key);return A!==void 0?!A:!D.getOption(62).suppressSuggestions}let L=h=class{constructor(T,M,A,P,N,O,F,x,W){this._editor=T,this._editorWorkerService=M,this._clipboardService=A,this._telemetryService=P,this._logService=N,this._contextKeyService=O,this._configurationService=F,this._languageFeaturesService=x,this._envService=W,this._toDispose=new y.DisposableStore,this._triggerCharacterListener=new y.DisposableStore,this._triggerQuickSuggest=new d.TimeoutTimer,this._triggerState=void 0,this._completionDisposables=new y.DisposableStore,this._onDidCancel=new E.Emitter,this._onDidTrigger=new E.Emitter,this._onDidSuggest=new E.Emitter,this.onDidCancel=this._onDidCancel.event,this.onDidTrigger=this._onDidTrigger.event,this.onDidSuggest=this._onDidSuggest.event,this._telemetryGate=0,this._currentSelection=this._editor.getSelection()||new _.Selection(1,1,1,1),this._toDispose.add(this._editor.onDidChangeModel(()=>{this._updateTriggerCharacters(),this.cancel()})),this._toDispose.add(this._editor.onDidChangeModelLanguage(()=>{this._updateTriggerCharacters(),this.cancel()})),this._toDispose.add(this._editor.onDidChangeConfiguration(()=>{this._updateTriggerCharacters()})),this._toDispose.add(this._languageFeaturesService.completionProvider.onDidChange(()=>{this._updateTriggerCharacters(),this._updateActiveSuggestSession()}));let V=!1;this._toDispose.add(this._editor.onDidCompositionStart(()=>{V=!0})),this._toDispose.add(this._editor.onDidCompositionEnd(()=>{V=!1,this._onCompositionEnd()})),this._toDispose.add(this._editor.onDidChangeCursorSelection(q=>{V||this._onCursorChange(q)})),this._toDispose.add(this._editor.onDidChangeModelContent(()=>{!V&&this._triggerState!==void 0&&this._refilterCompletionItems()})),this._updateTriggerCharacters()}dispose(){(0,y.dispose)(this._triggerCharacterListener),(0,y.dispose)([this._onDidCancel,this._onDidSuggest,this._onDidTrigger,this._triggerQuickSuggest]),this._toDispose.dispose(),this._completionDisposables.dispose(),this.cancel()}_updateTriggerCharacters(){if(this._triggerCharacterListener.clear(),this._editor.getOption(92)||!this._editor.hasModel()||!this._editor.getOption(122))return;const T=new Map;for(const A of this._languageFeaturesService.completionProvider.all(this._editor.getModel()))for(const P of A.triggerCharacters||[]){let N=T.get(P);if(!N){N=new Set;const O=(0,c.getSnippetSuggestSupport)();O&&N.add(O),T.set(P,N)}N.add(A)}const M=A=>{if(!S(this._editor,this._contextKeyService,this._configurationService)||v.shouldAutoTrigger(this._editor))return;if(!A){const O=this._editor.getPosition();A=this._editor.getModel().getLineContent(O.lineNumber).substr(0,O.column-1)}let P="";(0,m.isLowSurrogate)(A.charCodeAt(A.length-1))?(0,m.isHighSurrogate)(A.charCodeAt(A.length-2))&&(P=A.substr(A.length-2)):P=A.charAt(A.length-1);const N=T.get(P);if(N){const O=new Map;if(this._completionModel)for(const[F,x]of this._completionModel.getItemsByProvider())N.has(F)||O.set(F,x);this.trigger({auto:!0,triggerKind:1,triggerCharacter:P,retrigger:!!this._completionModel,clipboardText:this._completionModel?.clipboardText,completionOptions:{providerFilter:N,providerItemsToReuse:O}})}};this._triggerCharacterListener.add(this._editor.onDidType(M)),this._triggerCharacterListener.add(this._editor.onDidCompositionEnd(()=>M()))}get state(){return this._triggerState?this._triggerState.auto?2:1:0}cancel(T=!1){this._triggerState!==void 0&&(this._triggerQuickSuggest.cancel(),this._requestToken?.cancel(),this._requestToken=void 0,this._triggerState=void 0,this._completionModel=void 0,this._context=void 0,this._onDidCancel.fire({retrigger:T}))}clear(){this._completionDisposables.clear()}_updateActiveSuggestSession(){this._triggerState!==void 0&&(!this._editor.hasModel()||!this._languageFeaturesService.completionProvider.has(this._editor.getModel())?this.cancel():this.trigger({auto:this._triggerState.auto,retrigger:!0}))}_onCursorChange(T){if(!this._editor.hasModel())return;const M=this._currentSelection;if(this._currentSelection=this._editor.getSelection(),!T.selection.isEmpty()||T.reason!==0&&T.reason!==3||T.source!=="keyboard"&&T.source!=="deleteLeft"){this.cancel();return}this._triggerState===void 0&&T.reason===0?(M.containsRange(this._currentSelection)||M.getEndPosition().isBeforeOrEqual(this._currentSelection.getPosition()))&&this._doTriggerQuickSuggest():this._triggerState!==void 0&&T.reason===3&&this._refilterCompletionItems()}_onCompositionEnd(){this._triggerState===void 0?this._doTriggerQuickSuggest():this._refilterCompletionItems()}_doTriggerQuickSuggest(){c.QuickSuggestionsOptions.isAllOff(this._editor.getOption(90))||this._editor.getOption(119).snippetsPreventQuickSuggestions&&C.SnippetController2.get(this._editor)?.isInSnippet()||(this.cancel(),this._triggerQuickSuggest.cancelAndSet(()=>{if(this._triggerState!==void 0||!v.shouldAutoTrigger(this._editor)||!this._editor.hasModel()||!this._editor.hasWidgetFocus())return;const T=this._editor.getModel(),M=this._editor.getPosition(),A=this._editor.getOption(90);if(!c.QuickSuggestionsOptions.isAllOff(A)){if(!c.QuickSuggestionsOptions.isAllOn(A)){T.tokenization.tokenizeIfCheap(M.lineNumber);const P=T.tokenization.getLineTokens(M.lineNumber),N=P.getStandardTokenType(P.findTokenIndexAtOffset(Math.max(M.column-1-1,0)));if(c.QuickSuggestionsOptions.valueFor(A,N)!=="on")return}w(this._editor,this._contextKeyService,this._configurationService)&&this._languageFeaturesService.completionProvider.has(T)&&this.trigger({auto:!0})}},this._editor.getOption(91)))}_refilterCompletionItems(){(0,r.assertType)(this._editor.hasModel()),(0,r.assertType)(this._triggerState!==void 0);const T=this._editor.getModel(),M=this._editor.getPosition(),A=new v(T,M,{...this._triggerState,refilter:!0});this._onNewContext(A)}trigger(T){if(!this._editor.hasModel())return;const M=this._editor.getModel(),A=new v(M,this._editor.getPosition(),T);this.cancel(T.retrigger),this._triggerState=T,this._onDidTrigger.fire({auto:T.auto,shy:T.shy??!1,position:this._editor.getPosition()}),this._context=A;let P={triggerKind:T.triggerKind??0};T.triggerCharacter&&(P={triggerKind:1,triggerCharacter:T.triggerCharacter}),this._requestToken=new k.CancellationTokenSource;const N=this._editor.getOption(113);let O=1;switch(N){case"top":O=0;break;case"bottom":O=2;break}const{itemKind:F,showDeprecated:x}=h.createSuggestFilter(this._editor),W=new c.CompletionOptions(O,T.completionOptions?.kindFilter??F,T.completionOptions?.providerFilter,T.completionOptions?.providerItemsToReuse,x),V=p.WordDistance.create(this._editorWorkerService,this._editor),q=(0,c.provideSuggestionItems)(this._languageFeaturesService.completionProvider,M,this._editor.getPosition(),W,P,this._requestToken.token);Promise.all([q,V]).then(async([H,z])=>{if(this._requestToken?.dispose(),!this._editor.hasModel())return;let U=T?.clipboardText;if(!U&&H.needsClipboard&&(U=await this._clipboardService.readText()),this._triggerState===void 0)return;const j=this._editor.getModel(),Y=new v(j,this._editor.getPosition(),T),G={...a.FuzzyScoreOptions.default,firstMatchCanBeWeak:!this._editor.getOption(119).matchOnWordStartOnly};if(this._completionModel=new g.CompletionModel(H.items,this._context.column,{leadingLineContent:Y.leadingLineContent,characterCountDelta:Y.column-this._context.column},z,this._editor.getOption(119),this._editor.getOption(113),G,U),this._completionDisposables.add(H.disposable),this._onNewContext(Y),this._reportDurationsTelemetry(H.durations),!this._envService.isBuilt||this._envService.isExtensionDevelopment)for(const K of H.items)K.isInvalid&&this._logService.warn(`[suggest] did IGNORE invalid completion item from ${K.provider._debugDisplayName}`,K.completion)}).catch(I.onUnexpectedError)}_reportDurationsTelemetry(T){this._telemetryGate++%230===0&&setTimeout(()=>{this._telemetryService.publicLog2("suggest.durations.json",{data:JSON.stringify(T)}),this._logService.debug("suggest.durations.json",T)})}static createSuggestFilter(T){const M=new Set;T.getOption(113)==="none"&&M.add(27);const P=T.getOption(119);return P.showMethods||M.add(0),P.showFunctions||M.add(1),P.showConstructors||M.add(2),P.showFields||M.add(3),P.showVariables||M.add(4),P.showClasses||M.add(5),P.showStructs||M.add(6),P.showInterfaces||M.add(7),P.showModules||M.add(8),P.showProperties||M.add(9),P.showEvents||M.add(10),P.showOperators||M.add(11),P.showUnits||M.add(12),P.showValues||M.add(13),P.showConstants||M.add(14),P.showEnums||M.add(15),P.showEnumMembers||M.add(16),P.showKeywords||M.add(17),P.showWords||M.add(18),P.showColors||M.add(19),P.showFiles||M.add(20),P.showReferences||M.add(21),P.showColors||M.add(22),P.showFolders||M.add(23),P.showTypeParameters||M.add(24),P.showSnippets||M.add(27),P.showUsers||M.add(25),P.showIssues||M.add(26),{itemKind:M,showDeprecated:P.showDeprecated}}_onNewContext(T){if(this._context){if(T.lineNumber!==this._context.lineNumber){this.cancel();return}if((0,m.getLeadingWhitespace)(T.leadingLineContent)!==(0,m.getLeadingWhitespace)(this._context.leadingLineContent)){this.cancel();return}if(T.columnthis._context.leadingWord.startColumn){if(v.shouldAutoTrigger(this._editor)&&this._context){const A=this._completionModel.getItemsByProvider();this.trigger({auto:this._context.triggerOptions.auto,retrigger:!0,clipboardText:this._completionModel.clipboardText,completionOptions:{providerItemsToReuse:A}})}return}if(T.column>this._context.column&&this._completionModel.getIncompleteProvider().size>0&&T.leadingWord.word.length!==0){const M=new Map,A=new Set;for(const[P,N]of this._completionModel.getItemsByProvider())N.length>0&&N[0].container.incomplete?A.add(P):M.set(P,N);this.trigger({auto:this._context.triggerOptions.auto,triggerKind:2,retrigger:!0,clipboardText:this._completionModel.clipboardText,completionOptions:{providerFilter:A,providerItemsToReuse:M}})}else{const M=this._completionModel.lineContext;let A=!1;if(this._completionModel.lineContext={leadingLineContent:T.leadingLineContent,characterCountDelta:T.column-this._context.column},this._completionModel.items.length===0){const P=v.shouldAutoTrigger(this._editor);if(!this._context){this.cancel();return}if(P&&this._context.leadingWord.endColumn0,A&&T.leadingWord.word.length===0){this.cancel();return}}this._onDidSuggest.fire({completionModel:this._completionModel,triggerOptions:T.triggerOptions,isFrozen:A})}}}}};e.SuggestModel=L,e.SuggestModel=L=h=ke([ce(1,b.IEditorWorkerService),ce(2,n.IClipboardService),ce(3,s.ITelemetryService),ce(4,i.ILogService),ce(5,t.IContextKeyService),ce(6,o.IConfigurationService),ce(7,l.ILanguageFeaturesService),ce(8,f.IEnvironmentService)],L)}),define(ne[294],se([1,0,46,13,18,8,6,140,2,16,54,19,143,15,75,9,4,20,221,135,405,685,3,24,12,7,62,155,684,622,437,623,839,63,48,129,5,35]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M,A,P,N,O,F,x){"use strict";var W;Object.defineProperty(e,"__esModule",{value:!0}),e.TriggerSuggestAction=e.SuggestController=void 0;const V=!1;class q{constructor(K,R){if(this._model=K,this._position=R,this._decorationOptions=x.ModelDecorationOptions.register({description:"suggest-line-suffix",stickiness:1}),K.getLineMaxColumn(R.lineNumber)!==R.column){const ie=K.getOffsetAt(R),ue=K.getPositionAt(ie+1);K.changeDecorations(he=>{this._marker&&he.removeDecoration(this._marker),this._marker=he.addDecoration(g.Range.fromPositions(R,ue),this._decorationOptions)})}}dispose(){this._marker&&!this._model.isDisposed()&&this._model.changeDecorations(K=>{K.removeDecoration(this._marker),this._marker=void 0})}delta(K){if(this._model.isDisposed()||this._position.lineNumber!==K.lineNumber)return 0;if(this._marker){const R=this._model.getDecorationRange(this._marker);return this._model.getOffsetAt(R.getStartPosition())-this._model.getOffsetAt(K)}else return this._model.getLineMaxColumn(K.lineNumber)-K.column}}let H=class{static{W=this}static{this.ID="editor.contrib.suggestController"}static get(K){return K.getContribution(W.ID)}constructor(K,R,J,ie,ue,he,pe){this._memoryService=R,this._commandService=J,this._contextKeyService=ie,this._instantiationService=ue,this._logService=he,this._telemetryService=pe,this._lineSuffix=new _.MutableDisposable,this._toDispose=new _.DisposableStore,this._selectors=new z(ge=>ge.priority),this._onWillInsertSuggestItem=new y.Emitter,this.onWillInsertSuggestItem=this._onWillInsertSuggestItem.event,this.editor=K,this.model=ue.createInstance(T.SuggestModel,this.editor),this._selectors.register({priority:0,select:(ge,X,B)=>this._memoryService.select(ge,X,B)});const ae=S.Context.InsertMode.bindTo(ie);ae.set(K.getOption(119).insertMode),this._toDispose.add(this.model.onDidTrigger(()=>ae.set(K.getOption(119).insertMode))),this.widget=this._toDispose.add(new F.WindowIdleValue((0,F.getWindow)(K.getDomNode()),()=>{const ge=this._instantiationService.createInstance(A.SuggestWidget,this.editor);this._toDispose.add(ge),this._toDispose.add(ge.onDidSelect(Z=>this._insertSuggestion(Z,0),this));const X=new D.CommitCharacterController(this.editor,ge,this.model,Z=>this._insertSuggestion(Z,2));this._toDispose.add(X);const B=S.Context.MakesTextEdit.bindTo(this._contextKeyService),$=S.Context.HasInsertAndReplaceRange.bindTo(this._contextKeyService),Q=S.Context.CanResolve.bindTo(this._contextKeyService);return this._toDispose.add((0,_.toDisposable)(()=>{B.reset(),$.reset(),Q.reset()})),this._toDispose.add(ge.onDidFocus(({item:Z})=>{const te=this.editor.getPosition(),re=Z.editStart.column,le=te.column;let me=!0;this.editor.getOption(1)==="smart"&&this.model.state===2&&!Z.completion.additionalTextEdits&&!(Z.completion.insertTextRules&4)&&le-re===Z.completion.insertText.length&&(me=this.editor.getModel().getValueInRange({startLineNumber:te.lineNumber,startColumn:re,endLineNumber:te.lineNumber,endColumn:le})!==Z.completion.insertText),B.set(me),$.set(!s.Position.equals(Z.editInsertEnd,Z.editReplaceEnd)),Q.set(!!Z.provider.resolveCompletionItem||!!Z.completion.documentation||Z.completion.detail!==Z.completion.label)})),this._toDispose.add(ge.onDetailsKeyDown(Z=>{if(Z.toKeyCodeChord().equals(new m.KeyCodeChord(!0,!1,!1,!1,33))||b.isMacintosh&&Z.toKeyCodeChord().equals(new m.KeyCodeChord(!1,!1,!1,!0,33))){Z.stopPropagation();return}Z.toKeyCodeChord().isModifierKey()||this.editor.focus()})),ge})),this._overtypingCapturer=this._toDispose.add(new F.WindowIdleValue((0,F.getWindow)(K.getDomNode()),()=>this._toDispose.add(new M.OvertypingCapturer(this.editor,this.model)))),this._alternatives=this._toDispose.add(new F.WindowIdleValue((0,F.getWindow)(K.getDomNode()),()=>this._toDispose.add(new L.SuggestAlternatives(this.editor,this._contextKeyService)))),this._toDispose.add(ue.createInstance(u.WordContextKey,K)),this._toDispose.add(this.model.onDidTrigger(ge=>{this.widget.value.showTriggered(ge.auto,ge.shy?250:50),this._lineSuffix.value=new q(this.editor.getModel(),ge.position)})),this._toDispose.add(this.model.onDidSuggest(ge=>{if(ge.triggerOptions.shy)return;let X=-1;for(const $ of this._selectors.itemsOrderedByPriorityDesc)if(X=$.select(this.editor.getModel(),this.editor.getPosition(),ge.completionModel.items),X!==-1)break;if(X===-1&&(X=0),this.model.state===0)return;let B=!1;if(ge.triggerOptions.auto){const $=this.editor.getOption(119);$.selectionMode==="never"||$.selectionMode==="always"?B=$.selectionMode==="never":$.selectionMode==="whenTriggerCharacter"?B=ge.triggerOptions.triggerKind!==1:$.selectionMode==="whenQuickSuggestion"&&(B=ge.triggerOptions.triggerKind===1&&!ge.triggerOptions.refilter)}this.widget.value.showSuggestions(ge.completionModel,X,ge.isFrozen,ge.triggerOptions.auto,B)})),this._toDispose.add(this.model.onDidCancel(ge=>{ge.retrigger||this.widget.value.hideWidget()})),this._toDispose.add(this.editor.onDidBlurEditorWidget(()=>{V||(this.model.cancel(),this.model.clear())}));const ee=S.Context.AcceptSuggestionsOnEnter.bindTo(ie),de=()=>{const ge=this.editor.getOption(1);ee.set(ge==="on"||ge==="smart")};this._toDispose.add(this.editor.onDidChangeConfiguration(()=>de())),de()}dispose(){this._alternatives.dispose(),this._toDispose.dispose(),this.widget.dispose(),this.model.dispose(),this._lineSuffix.dispose(),this._onWillInsertSuggestItem.dispose()}_insertSuggestion(K,R){if(!K||!K.item){this._alternatives.value.reset(),this.model.cancel(),this.model.clear();return}if(!this.editor.hasModel())return;const J=l.SnippetController2.get(this.editor);if(!J)return;this._onWillInsertSuggestItem.fire({item:K.item});const ie=this.editor.getModel(),ue=ie.getAlternativeVersionId(),{item:he}=K,pe=[],ae=new I.CancellationTokenSource;R&1||this.editor.pushUndoStop();const ee=this.getOverwriteInfo(he,!!(R&8));this._memoryService.memorize(ie,this.editor.getPosition(),he);const de=he.isResolved;let ge=-1,X=-1;if(Array.isArray(he.completion.additionalTextEdits)){this.model.cancel();const $=o.StableEditorScrollState.capture(this.editor);this.editor.executeEdits("suggestController.additionalTextEdits.sync",he.completion.additionalTextEdits.map(Q=>{let Z=g.Range.lift(Q.range);if(Z.startLineNumber===he.position.lineNumber&&Z.startColumn>he.position.column){const te=this.editor.getPosition().column-he.position.column,re=te,le=g.Range.spansMultipleLines(Z)?0:te;Z=new g.Range(Z.startLineNumber,Z.startColumn+re,Z.endLineNumber,Z.endColumn+le)}return i.EditOperation.replaceMove(Z,Q.text)})),$.restoreRelativeVerticalPositionOfCursor(this.editor)}else if(!de){const $=new p.StopWatch;let Q;const Z=ie.onDidChangeContent(me=>{if(me.isFlush){ae.cancel(),Z.dispose();return}for(const Ce of me.changes){const ye=g.Range.getEndPosition(Ce.range);(!Q||s.Position.isBefore(ye,Q))&&(Q=ye)}}),te=R;R|=2;let re=!1;const le=this.editor.onWillType(()=>{le.dispose(),re=!0,te&2||this.editor.pushUndoStop()});pe.push(he.resolve(ae.token).then(()=>{if(!he.completion.additionalTextEdits||ae.token.isCancellationRequested)return;if(Q&&he.completion.additionalTextEdits.some(Ce=>s.Position.isBefore(Q,g.Range.getStartPosition(Ce.range))))return!1;re&&this.editor.pushUndoStop();const me=o.StableEditorScrollState.capture(this.editor);return this.editor.executeEdits("suggestController.additionalTextEdits.async",he.completion.additionalTextEdits.map(Ce=>i.EditOperation.replaceMove(g.Range.lift(Ce.range),Ce.text))),me.restoreRelativeVerticalPositionOfCursor(this.editor),(re||!(te&2))&&this.editor.pushUndoStop(),!0}).then(me=>{this._logService.trace("[suggest] async resolving of edits DONE (ms, applied?)",$.elapsed(),me),X=me===!0?1:me===!1?0:-2}).finally(()=>{Z.dispose(),le.dispose()}))}let{insertText:B}=he.completion;if(he.completion.insertTextRules&4||(B=a.SnippetParser.escape(B)),this.model.cancel(),J.insert(B,{overwriteBefore:ee.overwriteBefore,overwriteAfter:ee.overwriteAfter,undoStopBefore:!1,undoStopAfter:!1,adjustWhitespace:!(he.completion.insertTextRules&1),clipboardText:K.model.clipboardText,overtypingCapturer:this._overtypingCapturer.value}),R&2||this.editor.pushUndoStop(),he.completion.command)if(he.completion.command.id===U.id)this.model.trigger({auto:!0,retrigger:!0});else{const $=new p.StopWatch;pe.push(this._commandService.executeCommand(he.completion.command.id,...he.completion.command.arguments?[...he.completion.command.arguments]:[]).catch(Q=>{he.completion.extensionId?(0,E.onUnexpectedExternalError)(Q):(0,E.onUnexpectedError)(Q)}).finally(()=>{ge=$.elapsed()}))}R&4&&this._alternatives.value.set(K,$=>{for(ae.cancel();ie.canUndo();){ue!==ie.getAlternativeVersionId()&&ie.undo(),this._insertSuggestion($,3|(R&8?8:0));break}}),this._alertCompletionItem(he),Promise.all(pe).finally(()=>{this._reportSuggestionAcceptedTelemetry(he,ie,de,ge,X,K.index,K.model.items),this.model.clear(),ae.dispose()})}_reportSuggestionAcceptedTelemetry(K,R,J,ie,ue,he,pe){if(Math.floor(Math.random()*100)===0)return;const ae=new Map;for(let X=0;X1?ee[0]:-1;this._telemetryService.publicLog2("suggest.acceptedSuggestion",{extensionId:K.extensionId?.value??"unknown",providerId:K.provider._debugDisplayName??"unknown",kind:K.completion.kind,basenameHash:(0,O.hash)((0,N.basename)(R.uri)).toString(16),languageId:R.getLanguageId(),fileExtension:(0,N.extname)(R.uri),resolveInfo:K.provider.resolveCompletionItem?J?1:0:-1,resolveDuration:K.resolveDuration,commandDuration:ie,additionalEditsAsync:ue,index:he,firstIndex:ge})}getOverwriteInfo(K,R){(0,n.assertType)(this.editor.hasModel());let J=this.editor.getOption(119).insertMode==="replace";R&&(J=!J);const ie=K.position.column-K.editStart.column,ue=(J?K.editReplaceEnd.column:K.editInsertEnd.column)-K.position.column,he=this.editor.getPosition().column-K.position.column,pe=this._lineSuffix.value?this._lineSuffix.value.delta(this.editor.getPosition()):0;return{overwriteBefore:ie+he,overwriteAfter:ue+pe}}_alertCompletionItem(K){if((0,k.isNonEmptyArray)(K.completion.additionalTextEdits)){const R=C.localize(1318,"Accepting '{0}' made {1} additional edits",K.textLabel,K.completion.additionalTextEdits.length);(0,d.alert)(R)}}triggerSuggest(K,R,J){this.editor.hasModel()&&(this.model.trigger({auto:R??!1,completionOptions:{providerFilter:K,kindFilter:J?new Set:void 0}}),this.editor.revealPosition(this.editor.getPosition(),0),this.editor.focus())}triggerSuggestAndAcceptBest(K){if(!this.editor.hasModel())return;const R=this.editor.getPosition(),J=()=>{R.equals(this.editor.getPosition())&&this._commandService.executeCommand(K.fallback)},ie=ue=>{if(ue.completion.insertTextRules&4||ue.completion.additionalTextEdits)return!0;const he=this.editor.getPosition(),pe=ue.editStart.column,ae=he.column;return ae-pe!==ue.completion.insertText.length?!0:this.editor.getModel().getValueInRange({startLineNumber:he.lineNumber,startColumn:pe,endLineNumber:he.lineNumber,endColumn:ae})!==ue.completion.insertText};y.Event.once(this.model.onDidTrigger)(ue=>{const he=[];y.Event.any(this.model.onDidTrigger,this.model.onDidCancel)(()=>{(0,_.dispose)(he),J()},void 0,he),this.model.onDidSuggest(({completionModel:pe})=>{if((0,_.dispose)(he),pe.items.length===0){J();return}const ae=this._memoryService.select(this.editor.getModel(),this.editor.getPosition(),pe.items),ee=pe.items[ae];if(!ie(ee)){J();return}this.editor.pushUndoStop(),this._insertSuggestion({index:ae,item:ee,model:pe},7)},void 0,he)}),this.model.trigger({auto:!1,shy:!0}),this.editor.revealPosition(R,0),this.editor.focus()}acceptSelectedSuggestion(K,R){const J=this.widget.value.getFocusedItem();let ie=0;K&&(ie|=4),R&&(ie|=8),this._insertSuggestion(J,ie)}acceptNextSuggestion(){this._alternatives.value.next()}acceptPrevSuggestion(){this._alternatives.value.prev()}cancelSuggestWidget(){this.model.cancel(),this.model.clear(),this.widget.value.hideWidget()}focusSuggestion(){this.widget.value.focusSelected()}selectNextSuggestion(){this.widget.value.selectNext()}selectNextPageSuggestion(){this.widget.value.selectNextPage()}selectLastSuggestion(){this.widget.value.selectLast()}selectPrevSuggestion(){this.widget.value.selectPrevious()}selectPrevPageSuggestion(){this.widget.value.selectPreviousPage()}selectFirstSuggestion(){this.widget.value.selectFirst()}toggleSuggestionDetails(){this.widget.value.toggleDetails()}toggleExplainMode(){this.widget.value.toggleExplainMode()}toggleSuggestionFocus(){this.widget.value.toggleDetailsFocus()}resetWidgetSize(){this.widget.value.resetPersistedSize()}forceRenderingAbove(){this.widget.value.forceRenderingAbove()}stopForceRenderingAbove(){this.widget.isInitialized&&this.widget.value.stopForceRenderingAbove()}registerSelector(K){return this._selectors.register(K)}};e.SuggestController=H,e.SuggestController=H=W=ke([ce(1,r.ISuggestMemoryService),ce(2,f.ICommandService),ce(3,h.IContextKeyService),ce(4,v.IInstantiationService),ce(5,w.ILogService),ce(6,P.ITelemetryService)],H);class z{constructor(K){this.prioritySelector=K,this._items=new Array}register(K){if(this._items.indexOf(K)!==-1)throw new Error("Value is already registered");return this._items.push(K),this._items.sort((R,J)=>this.prioritySelector(J)-this.prioritySelector(R)),{dispose:()=>{const R=this._items.indexOf(K);R>=0&&this._items.splice(R,1)}}}get itemsOrderedByPriorityDesc(){return this._items}}class U extends t.EditorAction{static{this.id="editor.action.triggerSuggest"}constructor(){super({id:U.id,label:C.localize(1319,"Trigger Suggest"),alias:"Trigger Suggest",precondition:h.ContextKeyExpr.and(c.EditorContextKeys.writable,c.EditorContextKeys.hasCompletionItemProvider,S.Context.Visible.toNegated()),kbOpts:{kbExpr:c.EditorContextKeys.textInputFocus,primary:2058,secondary:[2087],mac:{primary:266,secondary:[521,2087]},weight:100}})}run(K,R,J){const ie=H.get(R);if(!ie)return;let ue;J&&typeof J=="object"&&J.auto===!0&&(ue=!0),ie.triggerSuggest(void 0,ue,void 0)}}e.TriggerSuggestAction=U,(0,t.registerEditorContribution)(H.ID,H,2),(0,t.registerEditorAction)(U);const j=190,Y=t.EditorCommand.bindToContribution(H.get);(0,t.registerEditorCommand)(new Y({id:"acceptSelectedSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,S.Context.HasFocusedSuggestion),handler(G){G.acceptSelectedSuggestion(!0,!1)},kbOpts:[{primary:2,kbExpr:h.ContextKeyExpr.and(S.Context.Visible,c.EditorContextKeys.textInputFocus),weight:j},{primary:3,kbExpr:h.ContextKeyExpr.and(S.Context.Visible,c.EditorContextKeys.textInputFocus,S.Context.AcceptSuggestionsOnEnter,S.Context.MakesTextEdit),weight:j}],menuOpts:[{menuId:S.suggestWidgetStatusbarMenu,title:C.localize(1320,"Insert"),group:"left",order:1,when:S.Context.HasInsertAndReplaceRange.toNegated()},{menuId:S.suggestWidgetStatusbarMenu,title:C.localize(1321,"Insert"),group:"left",order:1,when:h.ContextKeyExpr.and(S.Context.HasInsertAndReplaceRange,S.Context.InsertMode.isEqualTo("insert"))},{menuId:S.suggestWidgetStatusbarMenu,title:C.localize(1322,"Replace"),group:"left",order:1,when:h.ContextKeyExpr.and(S.Context.HasInsertAndReplaceRange,S.Context.InsertMode.isEqualTo("replace"))}]})),(0,t.registerEditorCommand)(new Y({id:"acceptAlternativeSelectedSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,c.EditorContextKeys.textInputFocus,S.Context.HasFocusedSuggestion),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:1027,secondary:[1026]},handler(G){G.acceptSelectedSuggestion(!1,!0)},menuOpts:[{menuId:S.suggestWidgetStatusbarMenu,group:"left",order:2,when:h.ContextKeyExpr.and(S.Context.HasInsertAndReplaceRange,S.Context.InsertMode.isEqualTo("insert")),title:C.localize(1323,"Replace")},{menuId:S.suggestWidgetStatusbarMenu,group:"left",order:2,when:h.ContextKeyExpr.and(S.Context.HasInsertAndReplaceRange,S.Context.InsertMode.isEqualTo("replace")),title:C.localize(1324,"Insert")}]})),f.CommandsRegistry.registerCommandAlias("acceptSelectedSuggestionOnEnter","acceptSelectedSuggestion"),(0,t.registerEditorCommand)(new Y({id:"hideSuggestWidget",precondition:S.Context.Visible,handler:G=>G.cancelSuggestWidget(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:9,secondary:[1033]}})),(0,t.registerEditorCommand)(new Y({id:"selectNextSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,h.ContextKeyExpr.or(S.Context.MultipleSuggestions,S.Context.HasFocusedSuggestion.negate())),handler:G=>G.selectNextSuggestion(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:18,secondary:[2066],mac:{primary:18,secondary:[2066,300]}}})),(0,t.registerEditorCommand)(new Y({id:"selectNextPageSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,h.ContextKeyExpr.or(S.Context.MultipleSuggestions,S.Context.HasFocusedSuggestion.negate())),handler:G=>G.selectNextPageSuggestion(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:12,secondary:[2060]}})),(0,t.registerEditorCommand)(new Y({id:"selectLastSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,h.ContextKeyExpr.or(S.Context.MultipleSuggestions,S.Context.HasFocusedSuggestion.negate())),handler:G=>G.selectLastSuggestion()})),(0,t.registerEditorCommand)(new Y({id:"selectPrevSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,h.ContextKeyExpr.or(S.Context.MultipleSuggestions,S.Context.HasFocusedSuggestion.negate())),handler:G=>G.selectPrevSuggestion(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:16,secondary:[2064],mac:{primary:16,secondary:[2064,302]}}})),(0,t.registerEditorCommand)(new Y({id:"selectPrevPageSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,h.ContextKeyExpr.or(S.Context.MultipleSuggestions,S.Context.HasFocusedSuggestion.negate())),handler:G=>G.selectPrevPageSuggestion(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:11,secondary:[2059]}})),(0,t.registerEditorCommand)(new Y({id:"selectFirstSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,h.ContextKeyExpr.or(S.Context.MultipleSuggestions,S.Context.HasFocusedSuggestion.negate())),handler:G=>G.selectFirstSuggestion()})),(0,t.registerEditorCommand)(new Y({id:"focusSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,S.Context.HasFocusedSuggestion.negate()),handler:G=>G.focusSuggestion(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:2058,secondary:[2087],mac:{primary:266,secondary:[2087]}}})),(0,t.registerEditorCommand)(new Y({id:"focusAndAcceptSuggestion",precondition:h.ContextKeyExpr.and(S.Context.Visible,S.Context.HasFocusedSuggestion.negate()),handler:G=>{G.focusSuggestion(),G.acceptSelectedSuggestion(!0,!1)}})),(0,t.registerEditorCommand)(new Y({id:"toggleSuggestionDetails",precondition:h.ContextKeyExpr.and(S.Context.Visible,S.Context.HasFocusedSuggestion),handler:G=>G.toggleSuggestionDetails(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:2058,secondary:[2087],mac:{primary:266,secondary:[2087]}},menuOpts:[{menuId:S.suggestWidgetStatusbarMenu,group:"right",order:1,when:h.ContextKeyExpr.and(S.Context.DetailsVisible,S.Context.CanResolve),title:C.localize(1325,"Show Less")},{menuId:S.suggestWidgetStatusbarMenu,group:"right",order:1,when:h.ContextKeyExpr.and(S.Context.DetailsVisible.toNegated(),S.Context.CanResolve),title:C.localize(1326,"Show More")}]})),(0,t.registerEditorCommand)(new Y({id:"toggleExplainMode",precondition:S.Context.Visible,handler:G=>G.toggleExplainMode(),kbOpts:{weight:100,primary:2138}})),(0,t.registerEditorCommand)(new Y({id:"toggleSuggestionFocus",precondition:S.Context.Visible,handler:G=>G.toggleSuggestionFocus(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:2570,mac:{primary:778}}})),(0,t.registerEditorCommand)(new Y({id:"insertBestCompletion",precondition:h.ContextKeyExpr.and(c.EditorContextKeys.textInputFocus,h.ContextKeyExpr.equals("config.editor.tabCompletion","on"),u.WordContextKey.AtEnd,S.Context.Visible.toNegated(),L.SuggestAlternatives.OtherSuggestions.toNegated(),l.SnippetController2.InSnippetMode.toNegated()),handler:(G,K)=>{G.triggerSuggestAndAcceptBest((0,n.isObject)(K)?{fallback:"tab",...K}:{fallback:"tab"})},kbOpts:{weight:j,primary:2}})),(0,t.registerEditorCommand)(new Y({id:"insertNextSuggestion",precondition:h.ContextKeyExpr.and(c.EditorContextKeys.textInputFocus,h.ContextKeyExpr.equals("config.editor.tabCompletion","on"),L.SuggestAlternatives.OtherSuggestions,S.Context.Visible.toNegated(),l.SnippetController2.InSnippetMode.toNegated()),handler:G=>G.acceptNextSuggestion(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:2}})),(0,t.registerEditorCommand)(new Y({id:"insertPrevSuggestion",precondition:h.ContextKeyExpr.and(c.EditorContextKeys.textInputFocus,h.ContextKeyExpr.equals("config.editor.tabCompletion","on"),L.SuggestAlternatives.OtherSuggestions,S.Context.Visible.toNegated(),l.SnippetController2.InSnippetMode.toNegated()),handler:G=>G.acceptPrevSuggestion(),kbOpts:{weight:j,kbExpr:c.EditorContextKeys.textInputFocus,primary:1026}})),(0,t.registerEditorAction)(class extends t.EditorAction{constructor(){super({id:"editor.action.resetSuggestSize",label:C.localize(1327,"Reset Suggest Widget Size"),alias:"Reset Suggest Widget Size",precondition:void 0})}run(G,K){H.get(K)?.resetWidgetSize()}})}),define(ne[861],se([1,0,13,67,6,2,9,4,104,27,246,135,436,294]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SuggestItemInfo=e.SuggestWidgetAdaptor=void 0;class i extends E.Disposable{get selectedItem(){return this._currentSuggestItemInfo}constructor(l,a,r){super(),this.editor=l,this.suggestControllerPreselector=a,this.onWillAccept=r,this.isSuggestWidgetVisible=!1,this.isShiftKeyPressed=!1,this._isActive=!1,this._currentSuggestItemInfo=void 0,this._onDidSelectedItemChange=this._register(new I.Emitter),this.onDidSelectedItemChange=this._onDidSelectedItemChange.event,this._register(l.onKeyDown(C=>{C.shiftKey&&!this.isShiftKeyPressed&&(this.isShiftKeyPressed=!0,this.update(this._isActive))})),this._register(l.onKeyUp(C=>{C.shiftKey&&this.isShiftKeyPressed&&(this.isShiftKeyPressed=!1,this.update(this._isActive))}));const u=t.SuggestController.get(this.editor);if(u){this._register(u.registerSelector({priority:100,select:(h,v,w)=>{const S=this.editor.getModel();if(!S)return-1;const L=this.suggestControllerPreselector(),D=L?(0,p.singleTextRemoveCommonPrefix)(L,S):void 0;if(!D)return-1;const T=y.Position.lift(v),M=w.map((P,N)=>{const O=s.fromSuggestion(u,S,T,P,this.isShiftKeyPressed),F=(0,p.singleTextRemoveCommonPrefix)(O.toSingleTextEdit(),S),x=(0,p.singleTextEditAugments)(D,F);return{index:N,valid:x,prefixLength:F.text.length,suggestItem:P}}).filter(P=>P&&P.valid&&P.prefixLength>0),A=(0,k.findFirstMax)(M,(0,d.compareBy)(P=>P.prefixLength,d.numberComparator));return A?A.index:-1}}));let C=!1;const f=()=>{C||(C=!0,this._register(u.widget.value.onDidShow(()=>{this.isSuggestWidgetVisible=!0,this.update(!0)})),this._register(u.widget.value.onDidHide(()=>{this.isSuggestWidgetVisible=!1,this.update(!1)})),this._register(u.widget.value.onDidFocus(()=>{this.isSuggestWidgetVisible=!0,this.update(!0)})))};this._register(I.Event.once(u.model.onDidTrigger)(h=>{f()})),this._register(u.onWillInsertSuggestItem(h=>{const v=this.editor.getPosition(),w=this.editor.getModel();if(!v||!w)return;const S=s.fromSuggestion(u,w,v,h.item,this.isShiftKeyPressed);this.onWillAccept(S)}))}this.update(this._isActive)}update(l){const a=this.getSuggestItemInfo();(this._isActive!==l||!g(this._currentSuggestItemInfo,a))&&(this._isActive=l,this._currentSuggestItemInfo=a,this._onDidSelectedItemChange.fire())}getSuggestItemInfo(){const l=t.SuggestController.get(this.editor);if(!l||!this.isSuggestWidgetVisible)return;const a=l.widget.value.getFocusedItem(),r=this.editor.getPosition(),u=this.editor.getModel();if(!(!a||!r||!u))return s.fromSuggestion(l,u,r,a.item,this.isShiftKeyPressed)}stopForceRenderingAbove(){t.SuggestController.get(this.editor)?.stopForceRenderingAbove()}forceRenderingAbove(){t.SuggestController.get(this.editor)?.forceRenderingAbove()}}e.SuggestWidgetAdaptor=i;class s{static fromSuggestion(l,a,r,u,C){let{insertText:f}=u.completion,h=!1;if(u.completion.insertTextRules&4){const w=new n.SnippetParser().parse(f);w.children.length<100&&o.SnippetSession.adjustWhitespace(a,r,!0,w),f=w.toString(),h=!0}const v=l.getOverwriteInfo(u,C);return new s(m.Range.fromPositions(r.delta(0,-v.overwriteBefore),r.delta(0,Math.max(v.overwriteAfter,0))),f,u.completion.kind,h)}constructor(l,a,r,u){this.range=l,this.insertText=a,this.completionItemKind=r,this.isSnippetText=u}equals(l){return this.range.equalsRange(l.range)&&this.insertText===l.insertText&&this.completionItemKind===l.completionItemKind&&this.isSnippetText===l.isSnippetText}toSelectedSuggestionInfo(){return new b.SelectedSuggestionInfo(this.range,this.insertText,this.completionItemKind,this.isSnippetText)}toSingleTextEdit(){return new _.SingleTextEdit(this.range,this.insertText)}}e.SuggestItemInfo=s;function g(c,l){return c===l?!0:!c||!l?!1:c.equals(l)}}),define(ne[295],se([1,0,630,46,14,18,2,21,65,189,19,214,112,9,79,17,245,679,269,283,860,861,3,61,137,24,28,12,7,31]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D){"use strict";var T;Object.defineProperty(e,"__esModule",{value:!0}),e.InlineCompletionsController=void 0;let M=class extends y.Disposable{static{T=this}static{this.ID="editor.contrib.inlineCompletionsController"}static get(N){return N.getContribution(T.ID)}constructor(N,O,F,x,W,V,q,H,z,U){super(),this.editor=N,this._instantiationService=O,this._contextKeyService=F,this._configurationService=x,this._commandService=W,this._debounceService=V,this._languageFeaturesService=q,this._accessibilitySignalService=H,this._keybindingService=z,this._accessibilityService=U,this._editorObs=(0,o.observableCodeEditor)(this.editor),this._positions=(0,m.derived)(this,Y=>this._editorObs.selections.read(Y)?.map(G=>G.getEndPosition())??[new t.Position(1,1)]),this._suggestWidgetAdaptor=this._register(new u.SuggestWidgetAdaptor(this.editor,()=>(this._editorObs.forceUpdate(),this.model.get()?.selectedInlineCompletion.get()?.toSingleTextEdit(void 0)),Y=>this._editorObs.forceUpdate(G=>{this.model.get()?.handleSuggestAccepted(Y)}))),this._suggestWidgetSelectedItem=(0,m.observableFromEvent)(this,Y=>this._suggestWidgetAdaptor.onDidSelectedItemChange(()=>{this._editorObs.forceUpdate(G=>Y(void 0))}),()=>this._suggestWidgetAdaptor.selectedItem),this._enabledInConfig=(0,m.observableFromEvent)(this,this.editor.onDidChangeConfiguration,()=>this.editor.getOption(62).enabled),this._isScreenReaderEnabled=(0,m.observableFromEvent)(this,this._accessibilityService.onDidChangeScreenReaderOptimized,()=>this._accessibilityService.isScreenReaderOptimized()),this._editorDictationInProgress=(0,m.observableFromEvent)(this,this._contextKeyService.onDidChangeContext,()=>this._contextKeyService.getContext(this.editor.getDomNode()).getValue("editorDictation.inProgress")===!0),this._enabled=(0,m.derived)(this,Y=>this._enabledInConfig.read(Y)&&(!this._isScreenReaderEnabled.read(Y)||!this._editorDictationInProgress.read(Y))),this._debounceValue=this._debounceService.for(this._languageFeaturesService.inlineCompletionsProvider,"InlineCompletionsDebounce",{min:50,max:50}),this.model=(0,_.derivedDisposable)(this,Y=>{if(this._editorObs.isReadonly.read(Y))return;const G=this._editorObs.model.read(Y);return G?this._instantiationService.createInstance(r.InlineCompletionsModel,G,this._suggestWidgetSelectedItem,this._editorObs.versionId,this._positions,this._debounceValue,(0,m.observableFromEvent)(this.editor.onDidChangeConfiguration,()=>this.editor.getOption(119).preview),(0,m.observableFromEvent)(this.editor.onDidChangeConfiguration,()=>this.editor.getOption(119).previewMode),(0,m.observableFromEvent)(this.editor.onDidChangeConfiguration,()=>this.editor.getOption(62).mode),this._enabled):void 0}).recomputeInitiallyAndOnChange(this._store),this._ghostTexts=(0,m.derived)(this,Y=>this.model.read(Y)?.ghostTexts.read(Y)??[]),this._stablizedGhostTexts=A(this._ghostTexts,this._store),this._ghostTextWidgets=(0,b.mapObservableArrayCached)(this,this._stablizedGhostTexts,(Y,G)=>G.add(this._instantiationService.createInstance(c.GhostTextView,this.editor,{ghostText:Y,minReservedLineCount:(0,m.constObservable)(0),targetTextModel:this.model.map(K=>K?.textModel)}))).recomputeInitiallyAndOnChange(this._store),this._playAccessibilitySignal=(0,m.observableSignal)(this),this._fontFamily=(0,m.observableFromEvent)(this,this.editor.onDidChangeConfiguration,()=>this.editor.getOption(62).fontFamily),this._register(new l.InlineCompletionContextKeys(this._contextKeyService,this.model)),this._register((0,o.reactToChange)(this._editorObs.onDidType,(Y,G)=>{this._enabled.get()&&this.model.get()?.trigger()})),this._register(this._commandService.onDidExecuteCommand(Y=>{new Set([n.CoreEditingCommands.Tab.id,n.CoreEditingCommands.DeleteLeft.id,n.CoreEditingCommands.DeleteRight.id,g.inlineSuggestCommitId,"acceptSelectedSuggestion"]).has(Y.commandId)&&N.hasTextFocus()&&this._enabled.get()&&this._editorObs.forceUpdate(K=>{this.model.get()?.trigger(K)})})),this._register((0,o.reactToChange)(this._editorObs.selections,(Y,G)=>{G.some(K=>K.reason===3||K.source==="api")&&this.model.get()?.stop()})),this._register(this.editor.onDidBlurEditorWidget(()=>{this._contextKeyService.getContextKeyValue("accessibleViewIsShown")||this._configurationService.getValue("editor.inlineSuggest.keepOnBlur")||N.getOption(62).keepOnBlur||a.InlineSuggestionHintsContentWidget.dropDownVisible||(0,m.transaction)(Y=>{this.model.get()?.stop(Y)})})),this._register((0,m.autorun)(Y=>{const G=this.model.read(Y)?.state.read(Y);G?.suggestItem?G.primaryGhostText.lineCount>=2&&this._suggestWidgetAdaptor.forceRenderingAbove():this._suggestWidgetAdaptor.stopForceRenderingAbove()})),this._register((0,y.toDisposable)(()=>{this._suggestWidgetAdaptor.stopForceRenderingAbove()}));const j=(0,b.derivedObservableWithCache)(this,(Y,G)=>{const R=this.model.read(Y)?.state.read(Y);return this._suggestWidgetSelectedItem.get()?G:R?.inlineCompletion?.semanticId});this._register((0,o.reactToChangeWithStore)((0,m.derived)(Y=>(this._playAccessibilitySignal.read(Y),j.read(Y),{})),async(Y,G,K)=>{const R=this.model.get(),J=R?.state.get();if(!J||!R)return;const ie=R.textModel.getLineContent(J.primaryGhostText.lineNumber);await(0,I.timeout)(50,(0,E.cancelOnDispose)(K)),await(0,m.waitForState)(this._suggestWidgetSelectedItem,p.isUndefined,()=>!1,(0,E.cancelOnDispose)(K)),await this._accessibilitySignalService.playSignal(h.AccessibilitySignal.inlineSuggestion),this.editor.getOption(8)&&this._provideScreenReaderUpdate(J.primaryGhostText.renderForScreenReader(ie))})),this._register(new a.InlineCompletionsHintsWidget(this.editor,this.model,this._instantiationService)),this._register((0,d.createStyleSheetFromObservable)((0,m.derived)(Y=>{const G=this._fontFamily.read(Y);return G===""||G==="default"?"":` .monaco-editor .ghost-text-decoration, .monaco-editor .ghost-text-decoration-preview, .monaco-editor .ghost-text { font-family: ${G}; }`}))),this._register(this._configurationService.onDidChangeConfiguration(Y=>{Y.affectsConfiguration("accessibility.verbosity.inlineCompletions")&&this.editor.updateOptions({inlineCompletionsAccessibilityVerbose:this._configurationService.getValue("accessibility.verbosity.inlineCompletions")})})),this.editor.updateOptions({inlineCompletionsAccessibilityVerbose:this._configurationService.getValue("accessibility.verbosity.inlineCompletions")})}playAccessibilitySignal(N){this._playAccessibilitySignal.trigger(N)}_provideScreenReaderUpdate(N){const O=this._contextKeyService.getContextKeyValue("accessibleViewIsShown"),F=this._keybindingService.lookupKeybinding("editor.action.accessibleView");let x;!O&&F&&this.editor.getOption(150)&&(x=(0,C.localize)(1088,"Inspect this in the accessible view ({0})",F.getAriaLabel())),(0,k.alert)(x?N+", "+x:N)}shouldShowHoverAt(N){const O=this.model.get()?.primaryGhostText.get();return O?O.parts.some(F=>N.containsPosition(new t.Position(O.lineNumber,F.column))):!1}shouldShowHoverAtViewZone(N){return this._ghostTextWidgets.get()[0]?.ownsViewZone(N)??!1}};e.InlineCompletionsController=M,e.InlineCompletionsController=M=T=ke([ce(1,L.IInstantiationService),ce(2,S.IContextKeyService),ce(3,w.IConfigurationService),ce(4,v.ICommandService),ce(5,i.ILanguageFeatureDebounceService),ce(6,s.ILanguageFeaturesService),ce(7,h.IAccessibilitySignalService),ce(8,D.IKeybindingService),ce(9,f.IAccessibilityService)],M);function A(P,N){const O=(0,m.observableValue)("result",[]),F=[];return N.add((0,m.autorun)(x=>{const W=P.read(x);(0,m.transaction)(V=>{if(W.length!==F.length){F.length=W.length;for(let q=0;qq.set(W[H],V))})})),O}}),define(ne[862],se([1,0,21,92,15,20,245,269,295,155,3,29,28,12]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ToggleAlwaysShowInlineSuggestionToolbar=e.HideInlineCompletion=e.AcceptInlineCompletion=e.AcceptNextLineOfInlineCompletion=e.AcceptNextWordOfInlineCompletion=e.TriggerInlineSuggestionAction=e.ShowPreviousInlineSuggestionAction=e.ShowNextInlineSuggestionAction=void 0;class i extends I.EditorAction{static{this.ID=y.showNextInlineSuggestionActionId}constructor(){super({id:i.ID,label:p.localize(1073,"Show Next Inline Suggestion"),alias:"Show Next Inline Suggestion",precondition:t.ContextKeyExpr.and(E.EditorContextKeys.writable,m.InlineCompletionContextKeys.inlineSuggestionVisible),kbOpts:{weight:100,primary:606}})}async run(f,h){_.InlineCompletionsController.get(h)?.model.get()?.next()}}e.ShowNextInlineSuggestionAction=i;class s extends I.EditorAction{static{this.ID=y.showPreviousInlineSuggestionActionId}constructor(){super({id:s.ID,label:p.localize(1074,"Show Previous Inline Suggestion"),alias:"Show Previous Inline Suggestion",precondition:t.ContextKeyExpr.and(E.EditorContextKeys.writable,m.InlineCompletionContextKeys.inlineSuggestionVisible),kbOpts:{weight:100,primary:604}})}async run(f,h){_.InlineCompletionsController.get(h)?.model.get()?.previous()}}e.ShowPreviousInlineSuggestionAction=s;class g extends I.EditorAction{constructor(){super({id:"editor.action.inlineSuggest.trigger",label:p.localize(1075,"Trigger Inline Suggestion"),alias:"Trigger Inline Suggestion",precondition:E.EditorContextKeys.writable})}async run(f,h){const v=_.InlineCompletionsController.get(h);await(0,k.asyncTransaction)(async w=>{await v?.model.get()?.triggerExplicitly(w),v?.playAccessibilitySignal(w)})}}e.TriggerInlineSuggestionAction=g;class c extends I.EditorAction{constructor(){super({id:"editor.action.inlineSuggest.acceptNextWord",label:p.localize(1076,"Accept Next Word Of Inline Suggestion"),alias:"Accept Next Word Of Inline Suggestion",precondition:t.ContextKeyExpr.and(E.EditorContextKeys.writable,m.InlineCompletionContextKeys.inlineSuggestionVisible),kbOpts:{weight:101,primary:2065,kbExpr:t.ContextKeyExpr.and(E.EditorContextKeys.writable,m.InlineCompletionContextKeys.inlineSuggestionVisible)},menuOpts:[{menuId:n.MenuId.InlineSuggestionToolbar,title:p.localize(1077,"Accept Word"),group:"primary",order:2}]})}async run(f,h){const v=_.InlineCompletionsController.get(h);await v?.model.get()?.acceptNextWord(v.editor)}}e.AcceptNextWordOfInlineCompletion=c;class l extends I.EditorAction{constructor(){super({id:"editor.action.inlineSuggest.acceptNextLine",label:p.localize(1078,"Accept Next Line Of Inline Suggestion"),alias:"Accept Next Line Of Inline Suggestion",precondition:t.ContextKeyExpr.and(E.EditorContextKeys.writable,m.InlineCompletionContextKeys.inlineSuggestionVisible),kbOpts:{weight:101},menuOpts:[{menuId:n.MenuId.InlineSuggestionToolbar,title:p.localize(1079,"Accept Line"),group:"secondary",order:2}]})}async run(f,h){const v=_.InlineCompletionsController.get(h);await v?.model.get()?.acceptNextLine(v.editor)}}e.AcceptNextLineOfInlineCompletion=l;class a extends I.EditorAction{constructor(){super({id:y.inlineSuggestCommitId,label:p.localize(1080,"Accept Inline Suggestion"),alias:"Accept Inline Suggestion",precondition:m.InlineCompletionContextKeys.inlineSuggestionVisible,menuOpts:[{menuId:n.MenuId.InlineSuggestionToolbar,title:p.localize(1081,"Accept"),group:"primary",order:1}],kbOpts:{primary:2,weight:200,kbExpr:t.ContextKeyExpr.and(m.InlineCompletionContextKeys.inlineSuggestionVisible,E.EditorContextKeys.tabMovesFocus.toNegated(),m.InlineCompletionContextKeys.inlineSuggestionHasIndentationLessThanTabSize,b.Context.Visible.toNegated(),E.EditorContextKeys.hoverFocused.toNegated())}})}async run(f,h){const v=_.InlineCompletionsController.get(h);v&&(v.model.get()?.accept(v.editor),v.editor.focus())}}e.AcceptInlineCompletion=a;class r extends I.EditorAction{static{this.ID="editor.action.inlineSuggest.hide"}constructor(){super({id:r.ID,label:p.localize(1082,"Hide Inline Suggestion"),alias:"Hide Inline Suggestion",precondition:m.InlineCompletionContextKeys.inlineSuggestionVisible,kbOpts:{weight:100,primary:9}})}async run(f,h){const v=_.InlineCompletionsController.get(h);(0,d.transaction)(w=>{v?.model.get()?.stop(w)})}}e.HideInlineCompletion=r;class u extends n.Action2{static{this.ID="editor.action.inlineSuggest.toggleAlwaysShowToolbar"}constructor(){super({id:u.ID,title:p.localize(1083,"Always Show Toolbar"),f1:!1,precondition:void 0,menu:[{id:n.MenuId.InlineSuggestionToolbar,group:"secondary",order:10}],toggled:t.ContextKeyExpr.equals("config.editor.inlineSuggest.showToolbar","always")})}async run(f,h){const v=f.get(o.IConfigurationService),S=v.getValue("editor.inlineSuggest.showToolbar")==="always"?"onHover":"always";v.updateValue("editor.inlineSuggest.showToolbar",S)}}e.ToggleAlwaysShowInlineSuggestionToolbar=u}),define(ne[863],se([1,0,5,57,2,21,4,43,84,295,283,120,3,61,7,59,63]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlineCompletionsHoverParticipant=e.InlineCompletionsHover=void 0;class c{constructor(r,u,C){this.owner=r,this.range=u,this.controller=C}isValidForHoverAnchor(r){return r.type===1&&this.range.startColumn<=r.range.startColumn&&this.range.endColumn>=r.range.endColumn}}e.InlineCompletionsHover=c;let l=class{constructor(r,u,C,f,h,v){this._editor=r,this._languageService=u,this._openerService=C,this.accessibilityService=f,this._instantiationService=h,this._telemetryService=v,this.hoverOrdinal=4}suggestHoverAnchor(r){const u=b.InlineCompletionsController.get(this._editor);if(!u)return null;const C=r.target;if(C.type===8){const f=C.detail;if(u.shouldShowHoverAtViewZone(f.viewZoneId))return new _.HoverForeignElementAnchor(1e3,this,y.Range.fromPositions(this._editor.getModel().validatePosition(f.positionBefore||f.position)),r.event.posx,r.event.posy,!1)}return C.type===7&&u.shouldShowHoverAt(C.range)?new _.HoverForeignElementAnchor(1e3,this,C.range,r.event.posx,r.event.posy,!1):C.type===6&&C.detail.mightBeForeignElement&&u.shouldShowHoverAt(C.range)?new _.HoverForeignElementAnchor(1e3,this,C.range,r.event.posx,r.event.posy,!1):null}computeSync(r,u){if(this._editor.getOption(62).showToolbar!=="onHover")return[];const C=b.InlineCompletionsController.get(this._editor);return C&&C.shouldShowHoverAt(r.range)?[new c(this,r.range,C)]:[]}renderHoverParts(r,u){const C=new I.DisposableStore,f=u[0];this._telemetryService.publicLog2("inlineCompletionHover.shown"),this.accessibilityService.isScreenReaderOptimized()&&!this._editor.getOption(8)&&C.add(this.renderScreenReaderText(r,f));const h=f.controller.model.get(),v=this._instantiationService.createInstance(p.InlineSuggestionHintsContentWidget,this._editor,!1,(0,E.constObservable)(null),h.selectedInlineCompletionIndex,h.inlineCompletionsCount,h.activeCommands),w=v.getDomNode();r.fragment.appendChild(w),h.triggerExplicitly(),C.add(v);const S={hoverPart:f,hoverElement:w,dispose(){C.dispose()}};return new _.RenderedHoverParts([S])}renderScreenReaderText(r,u){const C=new I.DisposableStore,f=d.$,h=f("div.hover-row.markdown-hover"),v=d.append(h,f("div.hover-contents",{"aria-live":"assertive"})),w=C.add(new n.MarkdownRenderer({editor:this._editor},this._languageService,this._openerService)),S=L=>{C.add(w.onDidRenderAsync(()=>{v.className="hover-contents code-hover-contents",r.onContentsChanged()}));const D=o.localize(1089,"Suggestion:"),T=C.add(w.render(new k.MarkdownString().appendText(D).appendCodeblock("text",L)));v.replaceChildren(T.element)};return C.add((0,E.autorun)(L=>{const D=u.controller.model.read(L)?.primaryGhostText.read(L);if(D){const T=this._editor.getModel().getLineContent(D.lineNumber);S(D.renderForScreenReader(T))}else d.reset(v)})),r.fragment.appendChild(h),C}};e.InlineCompletionsHoverParticipant=l,e.InlineCompletionsHoverParticipant=l=ke([ce(1,m.ILanguageService),ce(2,s.IOpenerService),ce(3,t.IAccessibilityService),ce(4,i.IInstantiationService),ce(5,g.ITelemetryService)],l)}),define(ne[864],se([1,0,15,84,862,863,617,295,380,29]),function(oe,e,d,k,I,E,y,m,_,b){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorContribution)(m.InlineCompletionsController.ID,m.InlineCompletionsController,3),(0,d.registerEditorAction)(I.TriggerInlineSuggestionAction),(0,d.registerEditorAction)(I.ShowNextInlineSuggestionAction),(0,d.registerEditorAction)(I.ShowPreviousInlineSuggestionAction),(0,d.registerEditorAction)(I.AcceptNextWordOfInlineCompletion),(0,d.registerEditorAction)(I.AcceptNextLineOfInlineCompletion),(0,d.registerEditorAction)(I.AcceptInlineCompletion),(0,d.registerEditorAction)(I.HideInlineCompletion),(0,b.registerAction2)(I.ToggleAlwaysShowInlineSuggestionToolbar),k.HoverParticipantRegistry.register(E.InlineCompletionsHoverParticipant),_.AccessibleViewRegistry.register(new y.InlineCompletionsAccessibleView)}),define(ne[438],se([1,0,5,347,2,21,65,15,112,125,139,88,70,35,434,379,294,7,521]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.InlineEditsWidget=e.InlineEdit=void 0;class l{constructor(v,w,S){this.range=v,this.newLines=w,this.changes=S}}e.InlineEdit=l;let a=class extends I.Disposable{constructor(v,w,S,L){super(),this._editor=v,this._edit=w,this._userPrompt=S,this._instantiationService=L,this._editorObs=(0,_.observableCodeEditor)(this._editor),this._elements=(0,d.h)("div.inline-edits-widget",{style:{position:"absolute",overflow:"visible",top:"0px",left:"0px"}},[(0,d.h)("div@editorContainer",{style:{position:"absolute",top:"0px",left:"0px",width:"500px",height:"500px"}},[(0,d.h)("div.toolbar@toolbar",{style:{position:"absolute",top:"-25px",left:"0px"}}),(0,d.h)("div.promptEditor@promptEditor",{style:{position:"absolute",top:"-25px",left:"80px",width:"300px",height:"22px"}}),(0,d.h)("div.preview@editor",{style:{position:"absolute",top:"0px",left:"0px"}})]),(0,d.svgElem)("svg",{style:{overflow:"visible",pointerEvents:"none"}},[(0,d.svgElem)("defs",[(0,d.svgElem)("linearGradient",{id:"Gradient2",x1:"0",y1:"0",x2:"1",y2:"0"},[(0,d.svgElem)("stop",{offset:"0%",class:"gradient-stop"}),(0,d.svgElem)("stop",{offset:"100%",class:"gradient-stop"})])]),(0,d.svgElem)("path@path",{d:"",fill:"url(#Gradient2)"})])]),this._previewTextModel=this._register(this._instantiationService.createInstance(t.TextModel,"",o.PLAINTEXT_LANGUAGE_ID,t.TextModel.DEFAULT_CREATION_OPTIONS,null)),this._setText=(0,E.derived)(T=>{const M=this._edit.read(T);M&&this._previewTextModel.setValue(M.newLines.join(` `))}).recomputeInitiallyAndOnChange(this._store),this._promptTextModel=this._register(this._instantiationService.createInstance(t.TextModel,"",o.PLAINTEXT_LANGUAGE_ID,t.TextModel.DEFAULT_CREATION_OPTIONS,null)),this._promptEditor=this._register(this._instantiationService.createInstance(b.EmbeddedCodeEditorWidget,this._elements.promptEditor,{glyphMargin:!1,lineNumbers:"off",minimap:{enabled:!1},guides:{indentation:!1,bracketPairs:!1,bracketPairsHorizontal:!1,highlightActiveIndentation:!1},folding:!1,selectOnLineNumbers:!1,selectionHighlight:!1,columnSelection:!1,overviewRulerBorder:!1,overviewRulerLanes:0,lineDecorationsWidth:0,lineNumbersMinChars:0,placeholder:"Describe the change you want...",fontFamily:k.DEFAULT_FONT_FAMILY},{contributions:m.EditorExtensionsRegistry.getSomeEditorContributions([g.SuggestController.ID,s.PlaceholderTextContribution.ID,i.ContextMenuController.ID]),isSimpleWidget:!0},this._editor)),this._previewEditor=this._register(this._instantiationService.createInstance(b.EmbeddedCodeEditorWidget,this._elements.editor,{glyphMargin:!1,lineNumbers:"off",minimap:{enabled:!1},guides:{indentation:!1,bracketPairs:!1,bracketPairsHorizontal:!1,highlightActiveIndentation:!1},folding:!1,selectOnLineNumbers:!1,selectionHighlight:!1,columnSelection:!1,overviewRulerBorder:!1,overviewRulerLanes:0,lineDecorationsWidth:0,lineNumbersMinChars:0},{contributions:[]},this._editor)),this._previewEditorObs=(0,_.observableCodeEditor)(this._previewEditor),this._decorations=(0,E.derived)(this,T=>{this._setText.read(T);const M=this._edit.read(T)?.changes;if(!M)return[];const A=[],P=[];if(M.length===1&&M[0].innerChanges[0].modifiedRange.equalsRange(this._previewTextModel.getFullModelRange()))return[];for(const N of M)if(N.original.isEmpty||A.push({range:N.original.toInclusiveRange(),options:p.diffLineDeleteDecorationBackgroundWithIndicator}),N.modified.isEmpty||P.push({range:N.modified.toInclusiveRange(),options:p.diffLineAddDecorationBackgroundWithIndicator}),N.modified.isEmpty||N.original.isEmpty)N.original.isEmpty||A.push({range:N.original.toInclusiveRange(),options:p.diffWholeLineDeleteDecoration}),N.modified.isEmpty||P.push({range:N.modified.toInclusiveRange(),options:p.diffWholeLineAddDecoration});else for(const O of N.innerChanges||[])N.original.contains(O.originalRange.startLineNumber)&&A.push({range:O.originalRange,options:O.originalRange.isEmpty()?p.diffDeleteDecorationEmpty:p.diffDeleteDecoration}),N.modified.contains(O.modifiedRange.startLineNumber)&&P.push({range:O.modifiedRange,options:O.modifiedRange.isEmpty()?p.diffAddDecorationEmpty:p.diffAddDecoration});return P}),this._layout1=(0,E.derived)(this,T=>{const M=this._editor.getModel(),A=this._edit.read(T);if(!A)return null;const P=A.range;let N=0;for(let x=P.startLineNumber;x{const M=this._edit.read(T);if(!M)return null;const A=M.range,P=this._editorObs.scrollLeft.read(T),N=this._layout1.read(T).left+20-P,O=this._editor.getTopForLineNumber(A.startLineNumber)-this._editorObs.scrollTop.read(T),F=this._editor.getTopForLineNumber(A.endLineNumberExclusive)-this._editorObs.scrollTop.read(T),x=new u(N,O),W=new u(N,F),V=F-O,q=50,H=this._editor.getOption(67)*M.newLines.length,z=V-H,U=new u(N+q,O+z/2),j=new u(N+q,F-z/2);return{topCode:x,bottomCode:W,codeHeight:V,topEdit:U,bottomEdit:j,editHeight:H}});const D=(0,E.derived)(this,T=>this._edit.read(T)!==void 0||this._userPrompt.read(T)!==void 0);this._register((0,n.applyStyle)(this._elements.root,{display:(0,E.derived)(this,T=>D.read(T)?"block":"none")})),this._register((0,n.appendRemoveOnDispose)(this._editor.getDomNode(),this._elements.root)),this._register((0,_.observableCodeEditor)(v).createOverlayWidget({domNode:this._elements.root,position:(0,E.constObservable)(null),allowEditorOverflow:!1,minContentWidthInPx:(0,E.derived)(T=>{const M=this._layout1.read(T)?.left;if(M===void 0)return 0;const A=this._previewEditorObs.contentWidth.read(T);return M+A})})),this._previewEditor.setModel(this._previewTextModel),this._register(this._previewEditorObs.setDecorations(this._decorations)),this._register((0,E.autorun)(T=>{const M=this._layout.read(T);if(!M)return;const{topCode:A,bottomCode:P,topEdit:N,bottomEdit:O,editHeight:F}=M,x=10,W=0,V=40,q=new C().moveTo(A).lineTo(A.deltaX(x)).curveTo(A.deltaX(x+V),N.deltaX(-V-W),N.deltaX(-W)).lineTo(N).lineTo(O).lineTo(O.deltaX(-W)).curveTo(O.deltaX(-V-W),P.deltaX(x+V),P.deltaX(x)).lineTo(P).build();this._elements.path.setAttribute("d",q),this._elements.editorContainer.style.top=`${N.y}px`,this._elements.editorContainer.style.left=`${N.x}px`,this._elements.editorContainer.style.height=`${F}px`;const H=this._previewEditorObs.contentWidth.read(T);this._previewEditor.layout({height:F,width:H})})),this._promptEditor.setModel(this._promptTextModel),this._promptEditor.layout(),this._register(f(r(this._userPrompt,T=>T??"",T=>T),(0,_.observableCodeEditor)(this._promptEditor).value)),this._register((0,E.autorun)(T=>{const M=(0,_.observableCodeEditor)(this._promptEditor).isFocused.read(T);this._elements.root.classList.toggle("focused",M)}))}};e.InlineEditsWidget=a,e.InlineEditsWidget=a=ke([ce(3,c.IInstantiationService)],a);function r(h,v,w){return(0,y.derivedWithSetter)(void 0,S=>v(h.read(S)),(S,L)=>h.set(w(S),L))}class u{constructor(v,w){this.x=v,this.y=w}deltaX(v){return new u(this.x+v,this.y)}}class C{constructor(){this._data=""}moveTo(v){return this._data+=`M ${v.x} ${v.y} `,this}lineTo(v){return this._data+=`L ${v.x} ${v.y} `,this}curveTo(v,w,S){return this._data+=`C ${v.x} ${v.y} ${w.x} ${w.y} ${S.x} ${S.y} `,this}build(){return this._data}}function f(h,v){const w=new I.DisposableStore;return w.add((0,E.autorun)(S=>{const L=h.read(S);v.set(L,void 0)})),w.add((0,E.autorun)(S=>{const L=v.read(S);h.set(L,void 0)})),w}}),define(ne[865],se([1,0,14,18,102,8,2,21,65,22,215,55,27,17,51,378,438]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";var c;Object.defineProperty(e,"__esModule",{value:!0}),e.InlineEditsModel=void 0;let l=class extends y.Disposable{static{c=this}static{this._modelId=0}static _createUniqueUri(){return b.URI.from({scheme:"inline-edits",path:new Date().toString()+String(c._modelId++)})}constructor(C,f,h,v,w,S,L){super(),this.textModel=C,this._textModelVersionId=f,this._selection=h,this._debounceValue=v,this.languageFeaturesService=w,this._diffProviderFactoryService=S,this._modelService=L,this._forceUpdateExplicitlySignal=(0,m.observableSignal)(this),this._selectedInlineCompletionId=(0,m.observableValue)(this,void 0),this._isActive=(0,m.observableValue)(this,!1),this._originalModel=(0,_.derivedDisposable)(()=>this._modelService.createModel("",null,c._createUniqueUri())).keepObserved(this._store),this._modifiedModel=(0,_.derivedDisposable)(()=>this._modelService.createModel("",null,c._createUniqueUri())).keepObserved(this._store),this._pinnedRange=new r(this.textModel,this._textModelVersionId),this.isPinned=this._pinnedRange.range.map(D=>!!D),this.userPrompt=(0,m.observableValue)(this,void 0),this.inlineEdit=(0,m.derived)(this,D=>this._inlineEdit.read(D)?.promiseResult.read(D)?.data),this._inlineEdit=(0,m.derived)(this,D=>{const T=this.selectedInlineEdit.read(D);if(!T)return;const M=T.inlineCompletion.range;if(T.inlineCompletion.insertText.trim()==="")return;let A=T.inlineCompletion.insertText.split(/\r\n|\r|\n/);function P(x){const W=x[0].match(/^\s*/)?.[0]??"";return x.map(V=>V.replace(new RegExp("^"+W),""))}A=P(A);let O=this.textModel.getValueInRange(M).split(/\r\n|\r|\n/);O=P(O),this._originalModel.get().setValue(O.join(` `)),this._modifiedModel.get().setValue(A.join(` `));const F=this._diffProviderFactoryService.createDiffProvider({diffAlgorithm:"advanced"});return m.ObservablePromise.fromFn(async()=>{const x=await F.computeDiff(this._originalModel.get(),this._modifiedModel.get(),{computeMoves:!1,ignoreTrimWhitespace:!1,maxComputationTimeMs:1e3},k.CancellationToken.None);if(!x.identical)return new g.InlineEdit(n.LineRange.fromRangeInclusive(M),P(A),x.changes)})}),this._fetchStore=this._register(new y.DisposableStore),this._inlineEditsFetchResult=(0,m.disposableObservableValue)(this,void 0),this._inlineEdits=(0,m.derivedOpts)({owner:this,equalsFn:I.structuralEquals},D=>this._inlineEditsFetchResult.read(D)?.completions.map(T=>new a(T))??[]),this._fetchInlineEditsPromise=(0,m.derivedHandleChanges)({owner:this,createEmptyChangeSummary:()=>({inlineCompletionTriggerKind:o.InlineCompletionTriggerKind.Automatic}),handleChange:(D,T)=>(D.didChange(this._forceUpdateExplicitlySignal)&&(T.inlineCompletionTriggerKind=o.InlineCompletionTriggerKind.Explicit),!0)},async(D,T)=>{this._fetchStore.clear(),this._forceUpdateExplicitlySignal.read(D),this._textModelVersionId.read(D);function M(F,x){return x(F)}const A=this._pinnedRange.range.read(D)??M(this._selection.read(D),F=>F.isEmpty()?void 0:F);if(!A){this._inlineEditsFetchResult.set(void 0,void 0),this.userPrompt.set(void 0,void 0);return}const P={triggerKind:T.inlineCompletionTriggerKind,selectedSuggestionInfo:void 0,userPrompt:this.userPrompt.read(D)},N=(0,k.cancelOnDispose)(this._fetchStore);await(0,d.timeout)(200,N);const O=await(0,s.provideInlineCompletions)(this.languageFeaturesService.inlineCompletionsProvider,A,this.textModel,P,N);N.isCancellationRequested||this._inlineEditsFetchResult.set(O,void 0)}),this._filteredInlineEditItems=(0,m.derivedOpts)({owner:this,equalsFn:(0,I.itemsEquals)()},D=>this._inlineEdits.read(D)),this.selectedInlineCompletionIndex=(0,m.derived)(this,D=>{const T=this._selectedInlineCompletionId.read(D),M=this._filteredInlineEditItems.read(D),A=this._selectedInlineCompletionId===void 0?-1:M.findIndex(P=>P.semanticId===T);return A===-1?(this._selectedInlineCompletionId.set(void 0,void 0),0):A}),this.selectedInlineEdit=(0,m.derived)(this,D=>{const T=this._filteredInlineEditItems.read(D),M=this.selectedInlineCompletionIndex.read(D);return T[M]}),this._register((0,m.recomputeInitiallyAndOnChange)(this._fetchInlineEditsPromise))}async triggerExplicitly(C){(0,m.subtransaction)(C,f=>{this._isActive.set(!0,f),this._forceUpdateExplicitlySignal.trigger(f)}),await this._fetchInlineEditsPromise.get()}stop(C){(0,m.subtransaction)(C,f=>{this.userPrompt.set(void 0,f),this._isActive.set(!1,f),this._inlineEditsFetchResult.set(void 0,f),this._pinnedRange.setRange(void 0,f)})}async _deltaSelectedInlineCompletionIndex(C){await this.triggerExplicitly();const f=this._filteredInlineEditItems.get()||[];if(f.length>0){const h=(this.selectedInlineCompletionIndex.get()+C+f.length)%f.length;this._selectedInlineCompletionId.set(f[h].semanticId,void 0)}else this._selectedInlineCompletionId.set(void 0,void 0)}async next(){await this._deltaSelectedInlineCompletionIndex(1)}async previous(){await this._deltaSelectedInlineCompletionIndex(-1)}async accept(C){if(C.getModel()!==this.textModel)throw new E.BugIndicatingError;const f=this.selectedInlineEdit.get();f&&(C.pushUndoStop(),C.executeEdits("inlineSuggestion.accept",[f.inlineCompletion.toSingleTextEdit().toSingleEditOperation()]),this.stop())}};e.InlineEditsModel=l,e.InlineEditsModel=l=c=ke([ce(4,t.ILanguageFeaturesService),ce(5,p.IDiffProviderFactoryService),ce(6,i.IModelService)],l);class a{constructor(C){this.inlineCompletion=C,this.semanticId=this.inlineCompletion.hash()}}class r extends y.Disposable{constructor(C,f){super(),this._textModel=C,this._versionId=f,this._decorations=(0,m.observableValue)(this,[]),this.range=(0,m.derived)(this,h=>{this._versionId.read(h);const v=this._decorations.read(h)[0];return v?this._textModel.getDecorationRange(v)??null:null}),this._register((0,y.toDisposable)(()=>{this._textModel.deltaDecorations(this._decorations.get(),[])}))}setRange(C,f){this._decorations.set(this._textModel.deltaDecorations(this._decorations.get(),C?[{range:C,options:{description:"trackedRange"}}]:[]),f)}}}),define(ne[439],se([1,0,2,21,65,112,171,23,79,17,390,865,438,28,12,7,397]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g){"use strict";var c;Object.defineProperty(e,"__esModule",{value:!0}),e.InlineEditsController=void 0;let l=class extends d.Disposable{static{c=this}static{this.ID="editor.contrib.inlineEditsController"}static get(u){return u.getContribution(c.ID)}constructor(u,C,f,h,v,w){super(),this.editor=u,this._instantiationService=C,this._contextKeyService=f,this._debounceService=h,this._languageFeaturesService=v,this._configurationService=w,this._enabled=(0,g.observableConfigValue)("editor.inlineEdits.enabled",!1,this._configurationService),this._editorObs=(0,E.observableCodeEditor)(this.editor),this._selection=(0,k.derived)(this,S=>this._editorObs.cursorSelection.read(S)??new m.Selection(1,1,1,1)),this._debounceValue=this._debounceService.for(this._languageFeaturesService.inlineCompletionsProvider,"InlineEditsDebounce",{min:50,max:50}),this.model=(0,I.derivedDisposable)(this,S=>{if(!this._enabled.read(S)||this._editorObs.isReadonly.read(S))return;const L=this._editorObs.model.read(S);return L?this._instantiationService.createInstance((0,y.readHotReloadableExport)(n.InlineEditsModel,S),L,this._editorObs.versionId,this._selection,this._debounceValue):void 0}),this._hadInlineEdit=(0,k.derivedObservableWithCache)(this,(S,L)=>L||this.model.read(S)?.inlineEdit.read(S)!==void 0),this._widget=(0,I.derivedDisposable)(this,S=>{if(this._hadInlineEdit.read(S))return this._instantiationService.createInstance((0,y.readHotReloadableExport)(o.InlineEditsWidget,S),this.editor,this.model.map((L,D)=>L?.inlineEdit.read(D)),a(L=>this.model.read(L)?.userPrompt??(0,k.observableValue)("empty","")))}),this._register((0,g.bindContextKey)(p.inlineEditVisible,this._contextKeyService,S=>!!this.model.read(S)?.inlineEdit.read(S))),this._register((0,g.bindContextKey)(p.isPinnedContextKey,this._contextKeyService,S=>!!this.model.read(S)?.isPinned.read(S))),this.model.recomputeInitiallyAndOnChange(this._store),this._widget.recomputeInitiallyAndOnChange(this._store)}};e.InlineEditsController=l,e.InlineEditsController=l=c=ke([ce(1,s.IInstantiationService),ce(2,i.IContextKeyService),ce(3,_.ILanguageFeatureDebounceService),ce(4,b.ILanguageFeaturesService),ce(5,t.IConfigurationService)],l);function a(r){return(0,I.derivedWithSetter)(void 0,u=>r(u).read(u),(u,C)=>{r(void 0).set(u,C)})}}),define(ne[866],se([1,0,26,21,92,15,125,20,390,439,3,29,12]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HideInlineEdit=e.AcceptInlineEdit=e.TriggerInlineEditAction=e.ShowPreviousInlineEditAction=e.ShowNextInlineEditAction=void 0;function t(a){return{label:a.value,alias:a.original}}class i extends E.EditorAction{static{this.ID=_.showNextInlineEditActionId}constructor(){super({id:i.ID,...t(p.localize2(1096,"Show Next Inline Edit")),precondition:o.ContextKeyExpr.and(m.EditorContextKeys.writable,_.inlineEditVisible),kbOpts:{weight:100,primary:606}})}async run(r,u){b.InlineEditsController.get(u)?.model.get()?.next()}}e.ShowNextInlineEditAction=i;class s extends E.EditorAction{static{this.ID=_.showPreviousInlineEditActionId}constructor(){super({id:s.ID,...t(p.localize2(1097,"Show Previous Inline Edit")),precondition:o.ContextKeyExpr.and(m.EditorContextKeys.writable,_.inlineEditVisible),kbOpts:{weight:100,primary:604}})}async run(r,u){b.InlineEditsController.get(u)?.model.get()?.previous()}}e.ShowPreviousInlineEditAction=s;class g extends E.EditorAction{constructor(){super({id:"editor.action.inlineEdits.trigger",...t(p.localize2(1098,"Trigger Inline Edit")),precondition:m.EditorContextKeys.writable})}async run(r,u){const C=b.InlineEditsController.get(u);await(0,I.asyncTransaction)(async f=>{await C?.model.get()?.triggerExplicitly(f)})}}e.TriggerInlineEditAction=g;class c extends E.EditorAction{constructor(){super({id:_.inlineEditAcceptId,...t(p.localize2(1099,"Accept Inline Edit")),precondition:_.inlineEditVisible,menuOpts:{menuId:n.MenuId.InlineEditsActions,title:p.localize(1095,"Accept Inline Edit"),group:"primary",order:1,icon:d.Codicon.check},kbOpts:{primary:2058,weight:2e4,kbExpr:_.inlineEditVisible}})}async run(r,u){u instanceof y.EmbeddedCodeEditorWidget&&(u=u.getParentEditor());const C=b.InlineEditsController.get(u);C&&(C.model.get()?.accept(C.editor),C.editor.focus())}}e.AcceptInlineEdit=c;class l extends E.EditorAction{static{this.ID="editor.action.inlineEdits.hide"}constructor(){super({id:l.ID,...t(p.localize2(1100,"Hide Inline Edit")),precondition:_.inlineEditVisible,kbOpts:{weight:100,primary:9}})}async run(r,u){const C=b.InlineEditsController.get(u);(0,k.transaction)(f=>{C?.model.get()?.stop(f)})}}e.HideInlineEdit=l}),define(ne[867],se([1,0,15,866,439]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),(0,d.registerEditorContribution)(I.InlineEditsController.ID,I.InlineEditsController,3),(0,d.registerEditorAction)(k.TriggerInlineEditAction),(0,d.registerEditorAction)(k.ShowNextInlineEditAction),(0,d.registerEditorAction)(k.ShowPreviousInlineEditAction),(0,d.registerEditorAction)(k.AcceptInlineEdit),(0,d.registerEditorAction)(k.HideInlineEdit)}),define(ne[868],se([1,0,18,82,53,2,34,4,130,17,342,155,405,437,343,117]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SuggestInlineCompletions=void 0;class g{constructor(r,u,C,f,h,v){this.range=r,this.insertText=u,this.filterText=C,this.additionalTextEdits=f,this.command=h,this.completion=v}}let c=class extends E.RefCountedDisposable{constructor(r,u,C,f,h,v){super(h.disposable),this.model=r,this.line=u,this.word=C,this.completionModel=f,this._suggestMemoryService=v}canBeReused(r,u,C){return this.model===r&&this.line===u&&this.word.word.length>0&&this.word.startColumn===C.startColumn&&this.word.endColumn=0&&w.resolve(d.CancellationToken.None)}return r}};c=ke([ce(5,o.ISuggestMemoryService)],c);let l=class extends E.Disposable{constructor(r,u,C,f){super(),this._languageFeatureService=r,this._clipboardService=u,this._suggestMemoryService=C,this._editorService=f,this._store.add(r.inlineCompletionsProvider.register("*",this))}async provideInlineCompletions(r,u,C,f){if(C.selectedSuggestionInfo)return;let h;for(const A of this._editorService.listCodeEditors())if(A.getModel()===r){h=A;break}if(!h)return;const v=h.getOption(90);if(n.QuickSuggestionsOptions.isAllOff(v))return;r.tokenization.tokenizeIfCheap(u.lineNumber);const w=r.tokenization.getLineTokens(u.lineNumber),S=w.getStandardTokenType(w.findTokenIndexAtOffset(Math.max(u.column-1-1,0)));if(n.QuickSuggestionsOptions.valueFor(v,S)!=="inline")return;let L=r.getWordAtPosition(u),D;if(L?.word||(D=this._getTriggerCharacterInfo(r,u)),!L?.word&&!D||(L||(L=r.getWordUntilPosition(u)),L.endColumn!==u.column))return;let T;const M=r.getValueInRange(new m.Range(u.lineNumber,1,u.lineNumber,u.column));if(!D&&this._lastResult?.canBeReused(r,u.lineNumber,L)){const A=new p.LineContext(M,u.column-this._lastResult.word.endColumn);this._lastResult.completionModel.lineContext=A,this._lastResult.acquire(),T=this._lastResult}else{const A=await(0,n.provideSuggestionItems)(this._languageFeatureService.completionProvider,r,u,new n.CompletionOptions(void 0,t.SuggestModel.createSuggestFilter(h).itemKind,D?.providers),D&&{triggerKind:1,triggerCharacter:D.ch},f);let P;A.needsClipboard&&(P=await this._clipboardService.readText());const N=new p.CompletionModel(A.items,u.column,new p.LineContext(M,0),i.WordDistance.None,h.getOption(119),h.getOption(113),{boostFullMatch:!1,firstMatchCanBeWeak:!1},P);T=new c(r,u.lineNumber,L,N,A,this._suggestMemoryService)}return this._lastResult=T,T}handleItemDidShow(r,u){u.completion.resolve(d.CancellationToken.None)}freeInlineCompletions(r){r.release()}_getTriggerCharacterInfo(r,u){const C=r.getValueInRange(m.Range.fromPositions({lineNumber:u.lineNumber,column:u.column-1},u)),f=new Set;for(const h of this._languageFeatureService.completionProvider.all(r))h.triggerCharacters?.includes(C)&&f.add(h);if(f.size!==0)return{providers:f,ch:C}}};e.SuggestInlineCompletions=l,e.SuggestInlineCompletions=l=ke([ce(0,b.ILanguageFeaturesService),ce(1,s.IClipboardService),ce(2,o.ISuggestMemoryService),ce(3,y.ICodeEditorService)],l),(0,_.registerEditorFeature)(l)}),define(ne[440],se([1,0,7]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IWorkspaceTrustManagementService=void 0,e.IWorkspaceTrustManagementService=(0,d.createDecorator)("workspaceTrustManagementService")}),define(ne[869],se([1,0,14,26,57,2,16,11,15,37,35,328,100,43,375,84,217,766,3,28,7,59,66,71,440,535]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ShowExcludeOptions=e.DisableHighlightingOfNonBasicAsciiCharactersAction=e.DisableHighlightingOfInvisibleCharactersAction=e.DisableHighlightingOfAmbiguousCharactersAction=e.DisableHighlightingInStringsAction=e.DisableHighlightingInCommentsAction=e.UnicodeHighlighterHoverParticipant=e.UnicodeHighlighter=e.warningIcon=void 0,e.warningIcon=(0,f.registerIcon)("extensions-warning-message",k.Codicon.warning,l.localize(1386,"Icon shown with a warning message in the extensions editor."));let v=class extends E.Disposable{static{this.ID="editor.contrib.unicodeHighlighter"}constructor(G,K,R,J){super(),this._editor=G,this._editorWorkerService=K,this._workspaceTrustService=R,this._highlighter=null,this._bannerClosed=!1,this._updateState=ie=>{if(ie&&ie.hasMore){if(this._bannerClosed)return;const ue=Math.max(ie.ambiguousCharacterCount,ie.nonBasicAsciiCharacterCount,ie.invisibleCharacterCount);let he;if(ie.nonBasicAsciiCharacterCount>=ue)he={message:l.localize(1387,"This document contains many non-basic ASCII unicode characters"),command:new q};else if(ie.ambiguousCharacterCount>=ue)he={message:l.localize(1388,"This document contains many ambiguous unicode characters"),command:new W};else if(ie.invisibleCharacterCount>=ue)he={message:l.localize(1389,"This document contains many invisible unicode characters"),command:new V};else throw new Error("Unreachable");this._bannerController.show({id:"unicodeHighlightBanner",message:he.message,icon:e.warningIcon,actions:[{label:he.command.shortLabel,href:`command:${he.command.id}`}],onClose:()=>{this._bannerClosed=!0}})}else this._bannerController.hide()},this._bannerController=this._register(J.createInstance(c.BannerController,G)),this._register(this._editor.onDidChangeModel(()=>{this._bannerClosed=!1,this._updateHighlighter()})),this._options=G.getOption(126),this._register(R.onDidChangeTrust(ie=>{this._updateHighlighter()})),this._register(G.onDidChangeConfiguration(ie=>{ie.hasChanged(126)&&(this._options=G.getOption(126),this._updateHighlighter())})),this._updateHighlighter()}dispose(){this._highlighter&&(this._highlighter.dispose(),this._highlighter=null),super.dispose()}_updateHighlighter(){if(this._updateState(null),this._highlighter&&(this._highlighter.dispose(),this._highlighter=null),!this._editor.hasModel())return;const G=w(this._workspaceTrustService.isWorkspaceTrusted(),this._options);if([G.nonBasicASCII,G.ambiguousCharacters,G.invisibleCharacters].every(R=>R===!1))return;const K={nonBasicASCII:G.nonBasicASCII,ambiguousCharacters:G.ambiguousCharacters,invisibleCharacters:G.invisibleCharacters,includeComments:G.includeComments,includeStrings:G.includeStrings,allowedCodePoints:Object.keys(G.allowedCharacters).map(R=>R.codePointAt(0)),allowedLocales:Object.keys(G.allowedLocales).map(R=>R==="_os"?new Intl.NumberFormat().resolvedOptions().locale:R==="_vscode"?y.language:R)};this._editorWorkerService.canComputeUnicodeHighlights(this._editor.getModel().uri)?this._highlighter=new S(this._editor,K,this._updateState,this._editorWorkerService):this._highlighter=new L(this._editor,K,this._updateState)}getDecorationInfo(G){return this._highlighter?this._highlighter.getDecorationInfo(G):null}};e.UnicodeHighlighter=v,e.UnicodeHighlighter=v=ke([ce(1,o.IEditorWorkerService),ce(2,h.IWorkspaceTrustManagementService),ce(3,r.IInstantiationService)],v);function w(Y,G){return{nonBasicASCII:G.nonBasicASCII===b.inUntrustedWorkspace?!Y:G.nonBasicASCII,ambiguousCharacters:G.ambiguousCharacters,invisibleCharacters:G.invisibleCharacters,includeComments:G.includeComments===b.inUntrustedWorkspace?!Y:G.includeComments,includeStrings:G.includeStrings===b.inUntrustedWorkspace?!Y:G.includeStrings,allowedCharacters:G.allowedCharacters,allowedLocales:G.allowedLocales}}let S=class extends E.Disposable{constructor(G,K,R,J){super(),this._editor=G,this._options=K,this._updateState=R,this._editorWorkerService=J,this._model=this._editor.getModel(),this._decorations=this._editor.createDecorationsCollection(),this._updateSoon=this._register(new d.RunOnceScheduler(()=>this._update(),250)),this._register(this._editor.onDidChangeModelContent(()=>{this._updateSoon.schedule()})),this._updateSoon.schedule()}dispose(){this._decorations.clear(),super.dispose()}_update(){if(this._model.isDisposed())return;if(!this._model.mightContainNonBasicASCII()){this._decorations.clear();return}const G=this._model.getVersionId();this._editorWorkerService.computedUnicodeHighlights(this._model.uri,this._options).then(K=>{if(this._model.isDisposed()||this._model.getVersionId()!==G)return;this._updateState(K);const R=[];if(!K.hasMore)for(const J of K.ranges)R.push({range:J,options:O.instance.getDecorationFromOptions(this._options)});this._decorations.set(R)})}getDecorationInfo(G){if(!this._decorations.has(G))return null;const K=this._editor.getModel();if(!(0,i.isModelDecorationVisible)(K,G))return null;const R=K.getValueInRange(G.range);return{reason:N(R,this._options),inComment:(0,i.isModelDecorationInComment)(K,G),inString:(0,i.isModelDecorationInString)(K,G)}}};S=ke([ce(3,o.IEditorWorkerService)],S);class L extends E.Disposable{constructor(G,K,R){super(),this._editor=G,this._options=K,this._updateState=R,this._model=this._editor.getModel(),this._decorations=this._editor.createDecorationsCollection(),this._updateSoon=this._register(new d.RunOnceScheduler(()=>this._update(),250)),this._register(this._editor.onDidLayoutChange(()=>{this._updateSoon.schedule()})),this._register(this._editor.onDidScrollChange(()=>{this._updateSoon.schedule()})),this._register(this._editor.onDidChangeHiddenAreas(()=>{this._updateSoon.schedule()})),this._register(this._editor.onDidChangeModelContent(()=>{this._updateSoon.schedule()})),this._updateSoon.schedule()}dispose(){this._decorations.clear(),super.dispose()}_update(){if(this._model.isDisposed())return;if(!this._model.mightContainNonBasicASCII()){this._decorations.clear();return}const G=this._editor.getVisibleRanges(),K=[],R={ranges:[],ambiguousCharacterCount:0,invisibleCharacterCount:0,nonBasicAsciiCharacterCount:0,hasMore:!1};for(const J of G){const ie=n.UnicodeTextModelHighlighter.computeUnicodeHighlights(this._model,this._options,J);for(const ue of ie.ranges)R.ranges.push(ue);R.ambiguousCharacterCount+=R.ambiguousCharacterCount,R.invisibleCharacterCount+=R.invisibleCharacterCount,R.nonBasicAsciiCharacterCount+=R.nonBasicAsciiCharacterCount,R.hasMore=R.hasMore||ie.hasMore}if(!R.hasMore)for(const J of R.ranges)K.push({range:J,options:O.instance.getDecorationFromOptions(this._options)});this._updateState(R),this._decorations.set(K)}getDecorationInfo(G){if(!this._decorations.has(G))return null;const K=this._editor.getModel(),R=K.getValueInRange(G.range);return(0,i.isModelDecorationVisible)(K,G)?{reason:N(R,this._options),inComment:(0,i.isModelDecorationInComment)(K,G),inString:(0,i.isModelDecorationInString)(K,G)}:null}}const D=l.localize(1390,"Configure Unicode Highlight Options");let T=class{constructor(G,K,R){this._editor=G,this._languageService=K,this._openerService=R,this.hoverOrdinal=5}computeSync(G,K){if(!this._editor.hasModel()||G.type!==1)return[];const R=this._editor.getModel(),J=this._editor.getContribution(v.ID);if(!J)return[];const ie=[],ue=new Set;let he=300;for(const pe of K){const ae=J.getDecorationInfo(pe);if(!ae)continue;const de=R.getValueInRange(pe.range).codePointAt(0),ge=A(de);let X;switch(ae.reason.kind){case 0:{(0,m.isBasicASCII)(ae.reason.confusableWith)?X=l.localize(1391,"The character {0} could be confused with the ASCII character {1}, which is more common in source code.",ge,A(ae.reason.confusableWith.codePointAt(0))):X=l.localize(1392,"The character {0} could be confused with the character {1}, which is more common in source code.",ge,A(ae.reason.confusableWith.codePointAt(0)));break}case 1:X=l.localize(1393,"The character {0} is invisible.",ge);break;case 2:X=l.localize(1394,"The character {0} is not a basic ASCII character.",ge);break}if(ue.has(X))continue;ue.add(X);const B={codePoint:de,reason:ae.reason,inComment:ae.inComment,inString:ae.inString},$=l.localize(1395,"Adjust settings"),Q=`command:${H.ID}?${encodeURIComponent(JSON.stringify(B))}`,Z=new I.MarkdownString("",!0).appendMarkdown(X).appendText(" ").appendLink(Q,$,D);ie.push(new g.MarkdownHover(this,pe.range,[Z],!1,he++))}return ie}renderHoverParts(G,K){return(0,g.renderMarkdownHovers)(G,K,this._editor,this._languageService,this._openerService)}};e.UnicodeHighlighterHoverParticipant=T,e.UnicodeHighlighterHoverParticipant=T=ke([ce(1,t.ILanguageService),ce(2,u.IOpenerService)],T);function M(Y){return`U+${Y.toString(16).padStart(4,"0")}`}function A(Y){let G=`\`${M(Y)}\``;return m.InvisibleCharacters.isInvisibleCharacter(Y)||(G+=` "${`${P(Y)}`}"`),G}function P(Y){return Y===96?"`` ` ``":"`"+String.fromCodePoint(Y)+"`"}function N(Y,G){return n.UnicodeTextModelHighlighter.computeUnicodeHighlightReason(Y,G)}class O{constructor(){this.map=new Map}static{this.instance=new O}getDecorationFromOptions(G){return this.getDecoration(!G.includeComments,!G.includeStrings)}getDecoration(G,K){const R=`${G}${K}`;let J=this.map.get(R);return J||(J=p.ModelDecorationOptions.createDynamic({description:"unicode-highlight",stickiness:1,className:"unicode-highlight",showIfCollapsed:!0,overviewRuler:null,minimap:null,hideInCommentTokens:G,hideInStringTokens:K}),this.map.set(R,J)),J}}class F extends _.EditorAction{constructor(){super({id:W.ID,label:l.localize(1397,"Disable highlighting of characters in comments"),alias:"Disable highlighting of characters in comments",precondition:void 0}),this.shortLabel=l.localize(1396,"Disable Highlight In Comments")}async run(G,K,R){const J=G?.get(a.IConfigurationService);J&&this.runAction(J)}async runAction(G){await G.updateValue(b.unicodeHighlightConfigKeys.includeComments,!1,2)}}e.DisableHighlightingInCommentsAction=F;class x extends _.EditorAction{constructor(){super({id:W.ID,label:l.localize(1399,"Disable highlighting of characters in strings"),alias:"Disable highlighting of characters in strings",precondition:void 0}),this.shortLabel=l.localize(1398,"Disable Highlight In Strings")}async run(G,K,R){const J=G?.get(a.IConfigurationService);J&&this.runAction(J)}async runAction(G){await G.updateValue(b.unicodeHighlightConfigKeys.includeStrings,!1,2)}}e.DisableHighlightingInStringsAction=x;class W extends _.EditorAction{static{this.ID="editor.action.unicodeHighlight.disableHighlightingOfAmbiguousCharacters"}constructor(){super({id:W.ID,label:l.localize(1401,"Disable highlighting of ambiguous characters"),alias:"Disable highlighting of ambiguous characters",precondition:void 0}),this.shortLabel=l.localize(1400,"Disable Ambiguous Highlight")}async run(G,K,R){const J=G?.get(a.IConfigurationService);J&&this.runAction(J)}async runAction(G){await G.updateValue(b.unicodeHighlightConfigKeys.ambiguousCharacters,!1,2)}}e.DisableHighlightingOfAmbiguousCharactersAction=W;class V extends _.EditorAction{static{this.ID="editor.action.unicodeHighlight.disableHighlightingOfInvisibleCharacters"}constructor(){super({id:V.ID,label:l.localize(1403,"Disable highlighting of invisible characters"),alias:"Disable highlighting of invisible characters",precondition:void 0}),this.shortLabel=l.localize(1402,"Disable Invisible Highlight")}async run(G,K,R){const J=G?.get(a.IConfigurationService);J&&this.runAction(J)}async runAction(G){await G.updateValue(b.unicodeHighlightConfigKeys.invisibleCharacters,!1,2)}}e.DisableHighlightingOfInvisibleCharactersAction=V;class q extends _.EditorAction{static{this.ID="editor.action.unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters"}constructor(){super({id:q.ID,label:l.localize(1405,"Disable highlighting of non basic ASCII characters"),alias:"Disable highlighting of non basic ASCII characters",precondition:void 0}),this.shortLabel=l.localize(1404,"Disable Non ASCII Highlight")}async run(G,K,R){const J=G?.get(a.IConfigurationService);J&&this.runAction(J)}async runAction(G){await G.updateValue(b.unicodeHighlightConfigKeys.nonBasicASCII,!1,2)}}e.DisableHighlightingOfNonBasicAsciiCharactersAction=q;class H extends _.EditorAction{static{this.ID="editor.action.unicodeHighlight.showExcludeOptions"}constructor(){super({id:H.ID,label:l.localize(1406,"Show Exclude Options"),alias:"Show Exclude Options",precondition:void 0})}async run(G,K,R){const{codePoint:J,reason:ie,inString:ue,inComment:he}=R,pe=String.fromCodePoint(J),ae=G.get(C.IQuickInputService),ee=G.get(a.IConfigurationService);function de(B){return m.InvisibleCharacters.isInvisibleCharacter(B)?l.localize(1407,"Exclude {0} (invisible character) from being highlighted",M(B)):l.localize(1408,"Exclude {0} from being highlighted",`${M(B)} "${pe}"`)}const ge=[];if(ie.kind===0)for(const B of ie.notAmbiguousInLocales)ge.push({label:l.localize(1409,'Allow unicode characters that are more common in the language "{0}".',B),run:async()=>{U(ee,[B])}});if(ge.push({label:de(J),run:()=>z(ee,[J])}),he){const B=new F;ge.push({label:B.label,run:async()=>B.runAction(ee)})}else if(ue){const B=new x;ge.push({label:B.label,run:async()=>B.runAction(ee)})}if(ie.kind===0){const B=new W;ge.push({label:B.label,run:async()=>B.runAction(ee)})}else if(ie.kind===1){const B=new V;ge.push({label:B.label,run:async()=>B.runAction(ee)})}else if(ie.kind===2){const B=new q;ge.push({label:B.label,run:async()=>B.runAction(ee)})}else j(ie);const X=await ae.pick(ge,{title:D});X&&await X.run()}}e.ShowExcludeOptions=H;async function z(Y,G){const K=Y.getValue(b.unicodeHighlightConfigKeys.allowedCharacters);let R;typeof K=="object"&&K?R=K:R={};for(const J of G)R[String.fromCodePoint(J)]=!0;await Y.updateValue(b.unicodeHighlightConfigKeys.allowedCharacters,R,2)}async function U(Y,G){const K=Y.inspect(b.unicodeHighlightConfigKeys.allowedLocales).user?.value;let R;typeof K=="object"&&K?R=Object.assign({},K):R={};for(const J of G)R[J]=!0;await Y.updateValue(b.unicodeHighlightConfigKeys.allowedLocales,R,2)}function j(Y){throw new Error(`Unexpected value: ${Y}`)}(0,_.registerEditorAction)(W),(0,_.registerEditorAction)(V),(0,_.registerEditorAction)(q),(0,_.registerEditorAction)(H),(0,_.registerEditorContribution)(v.ID,v,1),s.HoverParticipantRegistry.register(T)}),define(ne[870],se([1,0,214,219,812,727,815,728,729,856,817,819,848,821,730,434,731,822,857,858,423,289,734,735,695,864,290,291,429,427,850,737,851,827,738,739,833,834,740,840,831,867,765,786,790,835,791,792,742,221,853,294,868,743,718,869,744,841,411,745,741,694,107,195]),function(oe,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0})}),define(ne[222],se([1,0,11,5,47,6,140,2,16,111,22,152,274,75,9,4,51,78,211,24,28,403,12,180,7,691,31,392,121,393,692,181,50,96,63,186,119,107,48,34,62,440,58,395,711,801,49,701,100,401,43,784,266,808,805,419,153,693,61,29,406,696,117,687,265,688,154,216,108,699,59,66,101,717,137,17,36,697,130,8,271,52,45,384,624,418,394,855,79,785,677,772]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M,A,P,N,O,F,x,W,V,q,H,z,U,j,Y,G,K,R,J,ie,ue,he,pe,ae,ee,de,ge,X,B,$,Q,Z,te,re,le,me,Ce,ye,Le,Ee,Me,Ae,Ne,Ke,ze,Ge,it,Oe,Fe,fe,_e,xe,be,ve){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneServices=e.standaloneEditorWorkerDescriptor=e.StandaloneConfigurationService=e.StandaloneKeybindingService=e.StandaloneCommandService=e.StandaloneNotificationService=void 0,e.updateConfigurationService=Re;class we{constructor(Ve){this.disposed=!1,this.model=Ve,this._onWillDispose=new E.Emitter}get textEditorModel(){return this.model}dispose(){this.disposed=!0,this._onWillDispose.fire()}}let Te=class{constructor(Ve){this.modelService=Ve}createModelReference(Ve){const Ye=this.modelService.getModel(Ve);return Ye?Promise.resolve(new m.ImmortalReference(new we(Ye))):Promise.reject(new Error("Model not found"))}};Te=ke([ce(0,g.IModelService)],Te);class Pe{static{this.NULL_PROGRESS_RUNNER={done:()=>{},total:()=>{},worked:()=>{}}}show(){return Pe.NULL_PROGRESS_RUNNER}async showWhile(Ve,Ye){await Ve}}class Be{withProgress(Ve,Ye,Ze){return Ye({report:()=>{}})}}class He{constructor(){this.isExtensionDevelopment=!1,this.isBuilt=!1}}class $e{async confirm(Ve){return{confirmed:this.doConfirm(Ve.message,Ve.detail),checkboxChecked:!1}}doConfirm(Ve,Ye){let Ze=Ve;return Ye&&(Ze=Ze+` `+Ye),_e.mainWindow.confirm(Ze)}async prompt(Ve){let Ye;if(this.doConfirm(Ve.message,Ve.detail)){const nt=[...Ve.buttons??[]];Ve.cancelButton&&typeof Ve.cancelButton!="string"&&typeof Ve.cancelButton!="boolean"&&nt.push(Ve.cancelButton),Ye=await nt[0]?.run({checkboxChecked:!1})}return{result:Ye}}async error(Ve,Ye){await this.prompt({type:b.default.Error,message:Ve,detail:Ye})}}class je{static{this.NO_OP=new A.NoOpNotification}info(Ve){return this.notify({severity:b.default.Info,message:Ve})}warn(Ve){return this.notify({severity:b.default.Warning,message:Ve})}error(Ve){return this.notify({severity:b.default.Error,message:Ve})}notify(Ve){switch(Ve.severity){case b.default.Error:console.error(Ve.message);break;case b.default.Warning:console.warn(Ve.message);break;default:console.log(Ve.message);break}return je.NO_OP}prompt(Ve,Ye,Ze,nt){return je.NO_OP}status(Ve,Ye){return m.Disposable.None}}e.StandaloneNotificationService=je;let Xe=class{constructor(Ve){this._onWillExecuteCommand=new E.Emitter,this._onDidExecuteCommand=new E.Emitter,this.onDidExecuteCommand=this._onDidExecuteCommand.event,this._instantiationService=Ve}executeCommand(Ve,...Ye){const Ze=a.CommandsRegistry.getCommand(Ve);if(!Ze)return Promise.reject(new Error(`command '${Ve}' not found`));try{this._onWillExecuteCommand.fire({commandId:Ve,args:Ye});const nt=this._instantiationService.invokeFunction.apply(this._instantiationService,[Ze.handler,...Ye]);return this._onDidExecuteCommand.fire({commandId:Ve,args:Ye}),Promise.resolve(nt)}catch(nt){return Promise.reject(nt)}}};e.StandaloneCommandService=Xe,e.StandaloneCommandService=Xe=ke([ce(0,h.IInstantiationService)],Xe);let et=class extends v.AbstractKeybindingService{constructor(Ve,Ye,Ze,nt,ct,ht){super(Ve,Ye,Ze,nt,ct),this._cachedResolver=null,this._dynamicKeybindings=[],this._domNodeListeners=[];const ft=wt=>{const kt=new m.DisposableStore;kt.add(k.addDisposableListener(wt,k.EventType.KEY_DOWN,Mt=>{const Tt=new I.StandardKeyboardEvent(Mt);this._dispatch(Tt,Tt.target)&&(Tt.preventDefault(),Tt.stopPropagation())})),kt.add(k.addDisposableListener(wt,k.EventType.KEY_UP,Mt=>{const Tt=new I.StandardKeyboardEvent(Mt);this._singleModifierDispatch(Tt,Tt.target)&&Tt.preventDefault()})),this._domNodeListeners.push(new dt(wt,kt))},gt=wt=>{for(let kt=0;kt{wt.getOption(61)||ft(wt.getContainerDomNode())},vt=wt=>{wt.getOption(61)||gt(wt.getContainerDomNode())};this._register(ht.onCodeEditorAdd(mt)),this._register(ht.onCodeEditorRemove(vt)),ht.listCodeEditors().forEach(mt);const Dt=wt=>{ft(wt.getContainerDomNode())},ui=wt=>{gt(wt.getContainerDomNode())};this._register(ht.onDiffEditorAdd(Dt)),this._register(ht.onDiffEditorRemove(ui)),ht.listDiffEditors().forEach(Dt)}addDynamicKeybinding(Ve,Ye,Ze,nt){return(0,m.combinedDisposable)(a.CommandsRegistry.registerCommand(Ve,Ze),this.addDynamicKeybindings([{keybinding:Ye,command:Ve,when:nt}]))}addDynamicKeybindings(Ve){const Ye=Ve.map(Ze=>({keybinding:(0,y.decodeKeybinding)(Ze.keybinding,_.OS),command:Ze.command??null,commandArgs:Ze.commandArgs,when:Ze.when,weight1:1e3,weight2:0,extensionId:null,isBuiltinExtension:!1}));return this._dynamicKeybindings=this._dynamicKeybindings.concat(Ye),this.updateResolver(),(0,m.toDisposable)(()=>{for(let Ze=0;Zethis._log(Ze))}return this._cachedResolver}_documentHasFocus(){return _e.mainWindow.document.hasFocus()}_toNormalizedKeybindingItems(Ve,Ye){const Ze=[];let nt=0;for(const ct of Ve){const ht=ct.when||void 0,ft=ct.keybinding;if(!ft)Ze[nt++]=new D.ResolvedKeybindingItem(void 0,ct.command,ct.commandArgs,ht,Ye,null,!1);else{const gt=T.USLayoutResolvedKeybinding.resolveKeybinding(ft,_.OS);for(const mt of gt)Ze[nt++]=new D.ResolvedKeybindingItem(mt,ct.command,ct.commandArgs,ht,Ye,null,!1)}}return Ze}resolveKeyboardEvent(Ve){const Ye=new y.KeyCodeChord(Ve.ctrlKey,Ve.shiftKey,Ve.altKey,Ve.metaKey,Ve.keyCode);return new T.USLayoutResolvedKeybinding([Ye],_.OS)}};e.StandaloneKeybindingService=et,e.StandaloneKeybindingService=et=ke([ce(0,C.IContextKeyService),ce(1,a.ICommandService),ce(2,N.ITelemetryService),ce(3,A.INotificationService),ce(4,q.ILogService),ce(5,V.ICodeEditorService)],et);class dt extends m.Disposable{constructor(Ve,Ye){super(),this.domNode=Ve,this._register(Ye)}}function at(ot){return ot&&typeof ot=="object"&&(!ot.overrideIdentifier||typeof ot.overrideIdentifier=="string")&&(!ot.resource||ot.resource instanceof p.URI)}let st=class{constructor(Ve){this.logService=Ve,this._onDidChangeConfiguration=new E.Emitter,this.onDidChangeConfiguration=this._onDidChangeConfiguration.event;const Ye=new Ne.DefaultConfiguration(Ve);this._configuration=new u.Configuration(Ye.reload(),u.ConfigurationModel.createEmptyModel(Ve),u.ConfigurationModel.createEmptyModel(Ve),u.ConfigurationModel.createEmptyModel(Ve),u.ConfigurationModel.createEmptyModel(Ve),u.ConfigurationModel.createEmptyModel(Ve),new xe.ResourceMap,u.ConfigurationModel.createEmptyModel(Ve),new xe.ResourceMap,Ve),Ye.dispose()}getValue(Ve,Ye){const Ze=typeof Ve=="string"?Ve:void 0,nt=at(Ve)?Ve:at(Ye)?Ye:{};return this._configuration.getValue(Ze,nt,void 0)}updateValues(Ve){const Ye={data:this._configuration.toData()},Ze=[];for(const nt of Ve){const[ct,ht]=nt;this.getValue(ct)!==ht&&(this._configuration.updateValue(ct,ht),Ze.push(ct))}if(Ze.length>0){const nt=new u.ConfigurationChangeEvent({keys:Ze,overrides:[]},Ye,this._configuration,void 0,this.logService);nt.source=8,this._onDidChangeConfiguration.fire(nt)}return Promise.resolve()}updateValue(Ve,Ye,Ze,nt){return this.updateValues([[Ve,Ye]])}inspect(Ve,Ye={}){return this._configuration.inspect(Ve,Ye,void 0)}};e.StandaloneConfigurationService=st,e.StandaloneConfigurationService=st=ke([ce(0,q.ILogService)],st);let pt=class{constructor(Ve,Ye,Ze){this.configurationService=Ve,this.modelService=Ye,this.languageService=Ze,this._onDidChangeConfiguration=new E.Emitter,this.configurationService.onDidChangeConfiguration(nt=>{this._onDidChangeConfiguration.fire({affectedKeys:nt.affectedKeys,affectsConfiguration:(ct,ht)=>nt.affectsConfiguration(ht)})})}getValue(Ve,Ye,Ze){const nt=i.Position.isIPosition(Ye)?Ye:null,ct=nt?typeof Ze=="string"?Ze:void 0:typeof Ye=="string"?Ye:void 0,ht=Ve?this.getLanguage(Ve,nt):void 0;return typeof ct>"u"?this.configurationService.getValue({resource:Ve,overrideIdentifier:ht}):this.configurationService.getValue(ct,{resource:Ve,overrideIdentifier:ht})}getLanguage(Ve,Ye){const Ze=this.modelService.getModel(Ve);return Ze?Ye?Ze.getLanguageIdAtPosition(Ye.lineNumber,Ye.column):Ze.getLanguageId():this.languageService.guessLanguageIdByFilepathOrFirstLine(Ve)}};pt=ke([ce(0,r.IConfigurationService),ce(1,g.IModelService),ce(2,ie.ILanguageService)],pt);let bt=class{constructor(Ve){this.configurationService=Ve}getEOL(Ve,Ye){const Ze=this.configurationService.getValue("files.eol",{overrideIdentifier:Ye,resource:Ve});return Ze&&typeof Ze=="string"&&Ze!=="auto"?Ze:_.isLinux||_.isMacintosh?` `:`\r `}};bt=ke([ce(0,r.IConfigurationService)],bt);class De{publicLog2(){}}class Ie{static{this.SCHEME="inmemory"}constructor(){const Ve=p.URI.from({scheme:Ie.SCHEME,authority:"model",path:"/"});this.workspace={id:O.STANDALONE_EDITOR_WORKSPACE_ID,folders:[new O.WorkspaceFolder({uri:Ve,name:"",index:0})]}}getWorkspace(){return this.workspace}getWorkspaceFolder(Ve){return Ve&&Ve.scheme===Ie.SCHEME?this.workspace.folders[0]:null}}function Re(ot,Ve,Ye){if(!Ve||!(ot instanceof st))return;const Ze=[];Object.keys(Ve).forEach(nt=>{(0,o.isEditorConfigurationKey)(nt)&&Ze.push([`editor.${nt}`,Ve[nt]]),Ye&&(0,o.isDiffEditorConfigurationKey)(nt)&&Ze.push([`diffEditor.${nt}`,Ve[nt]])}),Ze.length>0&&ot.updateValues(Ze)}let Se=class{constructor(Ve){this._modelService=Ve}hasPreviewHandler(){return!1}async apply(Ve,Ye){const Ze=Array.isArray(Ve)?Ve:n.ResourceEdit.convert(Ve),nt=new Map;for(const ft of Ze){if(!(ft instanceof n.ResourceTextEdit))throw new Error("bad edit - only text edits are supported");const gt=this._modelService.getModel(ft.resource);if(!gt)throw new Error("bad edit - model not found");if(typeof ft.versionId=="number"&>.getVersionId()!==ft.versionId)throw new Error("bad state - model changed in the meantime");let mt=nt.get(gt);mt||(mt=[],nt.set(gt,mt)),mt.push(t.EditOperation.replaceMove(s.Range.lift(ft.textEdit.range),ft.textEdit.text))}let ct=0,ht=0;for(const[ft,gt]of nt)ft.pushStackElement(),ft.pushEditOperations([],gt,()=>[]),ft.pushStackElement(),ht+=1,ct+=gt.length;return{ariaSummary:d.format(x.StandaloneServicesNLS.bulkEditServiceSummary,ct,ht),isApplied:ct>0}}};Se=ke([ce(0,g.IModelService)],Se);class We{getUriLabel(Ve,Ye){return Ve.scheme==="file"?Ve.fsPath:Ve.path}getUriBasenameLabel(Ve){return(0,W.basename)(Ve)}}let qe=class extends U.ContextViewService{constructor(Ve,Ye){super(Ve),this._codeEditorService=Ye}showContextView(Ve,Ye,Ze){if(!Ye){const nt=this._codeEditorService.getFocusedCodeEditor()||this._codeEditorService.getActiveCodeEditor();nt&&(Ye=nt.getContainerDomNode())}return super.showContextView(Ve,Ye,Ze)}};qe=ke([ce(0,F.ILayoutService),ce(1,V.ICodeEditorService)],qe);class Ue{constructor(){this._neverEmitter=new E.Emitter,this.onDidChangeTrust=this._neverEmitter.event}isWorkspaceTrusted(){return!0}}class Je extends j.LanguageService{constructor(){super()}}class tt extends it.LogService{constructor(){super(new q.ConsoleLogger)}}let Qe=class extends Y.ContextMenuService{constructor(Ve,Ye,Ze,nt,ct,ht){super(Ve,Ye,Ze,nt,ct,ht),this.configure({blockMouse:!1})}};Qe=ke([ce(0,N.ITelemetryService),ce(1,A.INotificationService),ce(2,z.IContextViewService),ce(3,w.IKeybindingService),ce(4,B.IMenuService),ce(5,C.IContextKeyService)],Qe),e.standaloneEditorWorkerDescriptor={amdModuleId:"vs/editor/common/services/editorSimpleWorker",esmModuleLocation:void 0,label:"editorWorkerService"};let rt=class extends J.EditorWorkerService{constructor(Ve,Ye,Ze,nt,ct){super(e.standaloneEditorWorkerDescriptor,Ve,Ye,Ze,nt,ct)}};rt=ke([ce(0,g.IModelService),ce(1,l.ITextResourceConfigurationService),ce(2,q.ILogService),ce(3,Ge.ILanguageConfigurationService),ce(4,ze.ILanguageFeaturesService)],rt);class Ct{async playSignal(Ve,Ye){}}(0,G.registerSingleton)(q.ILogService,tt,0),(0,G.registerSingleton)(r.IConfigurationService,st,0),(0,G.registerSingleton)(l.ITextResourceConfigurationService,pt,0),(0,G.registerSingleton)(l.ITextResourcePropertiesService,bt,0),(0,G.registerSingleton)(O.IWorkspaceContextService,Ie,0),(0,G.registerSingleton)(M.ILabelService,We,0),(0,G.registerSingleton)(N.ITelemetryService,De,0),(0,G.registerSingleton)(f.IDialogService,$e,0),(0,G.registerSingleton)(fe.IEnvironmentService,He,0),(0,G.registerSingleton)(A.INotificationService,je,0),(0,G.registerSingleton)(ye.IMarkerService,Le.MarkerService,0),(0,G.registerSingleton)(ie.ILanguageService,Je,0),(0,G.registerSingleton)(de.IStandaloneThemeService,ee.StandaloneThemeService,0),(0,G.registerSingleton)(g.IModelService,pe.ModelService,0),(0,G.registerSingleton)(he.IMarkerDecorationsService,ue.MarkerDecorationsService,0),(0,G.registerSingleton)(C.IContextKeyService,te.ContextKeyService,0),(0,G.registerSingleton)(P.IProgressService,Be,0),(0,G.registerSingleton)(P.IEditorProgressService,Pe,0),(0,G.registerSingleton)(Ae.IStorageService,Ae.InMemoryStorageService,0),(0,G.registerSingleton)(R.IEditorWorkerService,rt,0),(0,G.registerSingleton)(n.IBulkEditService,Se,0),(0,G.registerSingleton)(H.IWorkspaceTrustManagementService,Ue,0),(0,G.registerSingleton)(c.ITextModelService,Te,0),(0,G.registerSingleton)(X.IAccessibilityService,ge.AccessibilityService,0),(0,G.registerSingleton)(Ce.IListService,Ce.ListService,0),(0,G.registerSingleton)(a.ICommandService,Xe,0),(0,G.registerSingleton)(w.IKeybindingService,et,0),(0,G.registerSingleton)(Me.IQuickInputService,ae.StandaloneQuickInputService,0),(0,G.registerSingleton)(z.IContextViewService,qe,0),(0,G.registerSingleton)(Ee.IOpenerService,K.OpenerService,0),(0,G.registerSingleton)(Z.IClipboardService,Q.BrowserClipboardService,0),(0,G.registerSingleton)(z.IContextMenuService,Qe,0),(0,G.registerSingleton)(B.IMenuService,$.MenuService,0),(0,G.registerSingleton)(Ke.IAccessibilitySignalService,Ct,0),(0,G.registerSingleton)(be.ITreeSitterParserService,ve.StandaloneTreeSitterParserService,0);var ut;(function(ot){const Ve=new me.ServiceCollection;for(const[gt,mt]of(0,G.getSingletonServiceDescriptors)())Ve.set(gt,mt);const Ye=new le.InstantiationService(Ve,!0);Ve.set(h.IInstantiationService,Ye);function Ze(gt){nt||ht({});const mt=Ve.get(gt);if(!mt)throw new Error("Missing service "+gt);return mt instanceof re.SyncDescriptor?Ye.invokeFunction(vt=>vt.get(gt)):mt}ot.get=Ze;let nt=!1;const ct=new E.Emitter;function ht(gt){if(nt)return Ye;nt=!0;for(const[vt,Dt]of(0,G.getSingletonServiceDescriptors)())Ve.get(vt)||Ve.set(vt,Dt);for(const vt in gt)if(gt.hasOwnProperty(vt)){const Dt=(0,h.createDecorator)(vt);Ve.get(Dt)instanceof re.SyncDescriptor&&Ve.set(Dt,gt[vt])}const mt=(0,Oe.getEditorFeatures)();for(const vt of mt)try{Ye.createInstance(vt)}catch(Dt){(0,Fe.onUnexpectedError)(Dt)}return ct.fire(),Ye}ot.initialize=ht;function ft(gt){if(nt)return gt();const mt=new m.DisposableStore,vt=mt.add(ct.event(()=>{vt.dispose(),mt.add(gt())}));return mt}ot.withServices=ft})(ut||(e.StandaloneServices=ut={}))}),define(ne[871],se([1,0,46,2,34,219,318,222,153,29,24,28,12,58,7,31,50,25,61,107,117,96,51,43,418,70,36,17,286,137,52,44,118,81]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M,A,P){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.StandaloneDiffEditor2=e.StandaloneEditor=e.StandaloneCodeEditor=void 0,e.createTextModel=q;let N=0,O=!1;function F(z){if(!z){if(O)return;O=!0}d.setARIAContainer(z||T.mainWindow.document.body)}let x=class extends E.CodeEditorWidget{constructor(U,j,Y,G,K,R,J,ie,ue,he,pe,ae,ee){const de={...j};de.ariaLabel=de.ariaLabel||a.StandaloneCodeEditorNLS.editorViewAccessibleLabel,super(U,de,{},Y,G,K,R,ue,he,pe,ae,ee),ie instanceof m.StandaloneKeybindingService?this._standaloneKeybindingService=ie:this._standaloneKeybindingService=null,F(de.ariaContainerElement),(0,M.setHoverDelegateFactory)((ge,X)=>Y.createInstance(A.WorkbenchHoverDelegate,ge,X,{})),(0,P.setBaseLayerHoverDelegate)(J)}addCommand(U,j,Y){if(!this._standaloneKeybindingService)return console.warn("Cannot add command because the editor is configured with an unrecognized KeybindingService"),null;const G="DYNAMIC_"+ ++N,K=o.ContextKeyExpr.deserialize(Y);return this._standaloneKeybindingService.addDynamicKeybinding(G,U,j,K),G}createContextKey(U,j){return this._contextKeyService.createKey(U,j)}addAction(U){if(typeof U.id!="string"||typeof U.label!="string"||typeof U.run!="function")throw new Error("Invalid action descriptor, `id`, `label` and `run` are required properties!");if(!this._standaloneKeybindingService)return console.warn("Cannot add keybinding because the editor is configured with an unrecognized KeybindingService"),k.Disposable.None;const j=U.id,Y=U.label,G=o.ContextKeyExpr.and(o.ContextKeyExpr.equals("editorId",this.getId()),o.ContextKeyExpr.deserialize(U.precondition)),K=U.keybindings,R=o.ContextKeyExpr.and(G,o.ContextKeyExpr.deserialize(U.keybindingContext)),J=U.contextMenuGroupId||null,ie=U.contextMenuOrder||0,ue=(ee,...de)=>Promise.resolve(U.run(this,...de)),he=new k.DisposableStore,pe=this.getId()+":"+j;if(he.add(p.CommandsRegistry.registerCommand(pe,ue)),J){const ee={command:{id:pe,title:Y},when:G,group:J,order:ie};he.add(b.MenuRegistry.appendMenuItem(b.MenuId.EditorContext,ee))}if(Array.isArray(K))for(const ee of K)he.add(this._standaloneKeybindingService.addDynamicKeybinding(pe,ee,ue,R));const ae=new y.InternalEditorAction(pe,Y,Y,void 0,G,(...ee)=>Promise.resolve(U.run(this,...ee)),this._contextKeyService);return this._actions.set(j,ae),he.add((0,k.toDisposable)(()=>{this._actions.delete(j)})),he}_triggerCommand(U,j){if(this._codeEditorService instanceof h.StandaloneCodeEditorService)try{this._codeEditorService.setActiveCodeEditor(this),super._triggerCommand(U,j)}finally{this._codeEditorService.setActiveCodeEditor(null)}else super._triggerCommand(U,j)}};e.StandaloneCodeEditor=x,e.StandaloneCodeEditor=x=ke([ce(2,i.IInstantiationService),ce(3,I.ICodeEditorService),ce(4,p.ICommandService),ce(5,o.IContextKeyService),ce(6,A.IHoverService),ce(7,s.IKeybindingService),ce(8,c.IThemeService),ce(9,g.INotificationService),ce(10,l.IAccessibilityService),ce(11,w.ILanguageConfigurationService),ce(12,S.ILanguageFeaturesService)],x);let W=class extends x{constructor(U,j,Y,G,K,R,J,ie,ue,he,pe,ae,ee,de,ge,X){const B={...j};(0,m.updateConfigurationService)(pe,B,!1);const $=ue.registerEditorContainer(U);typeof B.theme=="string"&&ue.setTheme(B.theme),typeof B.autoDetectHighContrast<"u"&&ue.setAutoDetectHighContrast(!!B.autoDetectHighContrast);const Q=B.model;delete B.model,super(U,B,Y,G,K,R,J,ie,ue,he,ae,ge,X),this._configurationService=pe,this._standaloneThemeService=ue,this._register($);let Z;if(typeof Q>"u"){const te=de.getLanguageIdByMimeType(B.language)||B.language||v.PLAINTEXT_LANGUAGE_ID;Z=q(ee,de,B.value||"",te,void 0),this._ownsModel=!0}else Z=Q,this._ownsModel=!1;if(this._attachModel(Z),Z){const te={oldModelUrl:null,newModelUrl:Z.uri};this._onDidChangeModel.fire(te)}}dispose(){super.dispose()}updateOptions(U){(0,m.updateConfigurationService)(this._configurationService,U,!1),typeof U.theme=="string"&&this._standaloneThemeService.setTheme(U.theme),typeof U.autoDetectHighContrast<"u"&&this._standaloneThemeService.setAutoDetectHighContrast(!!U.autoDetectHighContrast),super.updateOptions(U)}_postDetachModelCleanup(U){super._postDetachModelCleanup(U),U&&this._ownsModel&&(U.dispose(),this._ownsModel=!1)}};e.StandaloneEditor=W,e.StandaloneEditor=W=ke([ce(2,i.IInstantiationService),ce(3,I.ICodeEditorService),ce(4,p.ICommandService),ce(5,o.IContextKeyService),ce(6,A.IHoverService),ce(7,s.IKeybindingService),ce(8,_.IStandaloneThemeService),ce(9,g.INotificationService),ce(10,n.IConfigurationService),ce(11,l.IAccessibilityService),ce(12,C.IModelService),ce(13,f.ILanguageService),ce(14,w.ILanguageConfigurationService),ce(15,S.ILanguageFeaturesService)],W);let V=class extends L.DiffEditorWidget{constructor(U,j,Y,G,K,R,J,ie,ue,he,pe,ae){const ee={...j};(0,m.updateConfigurationService)(ie,ee,!0);const de=R.registerEditorContainer(U);typeof ee.theme=="string"&&R.setTheme(ee.theme),typeof ee.autoDetectHighContrast<"u"&&R.setAutoDetectHighContrast(!!ee.autoDetectHighContrast),super(U,ee,{},G,Y,K,ae,he),this._configurationService=ie,this._standaloneThemeService=R,this._register(de)}dispose(){super.dispose()}updateOptions(U){(0,m.updateConfigurationService)(this._configurationService,U,!0),typeof U.theme=="string"&&this._standaloneThemeService.setTheme(U.theme),typeof U.autoDetectHighContrast<"u"&&this._standaloneThemeService.setAutoDetectHighContrast(!!U.autoDetectHighContrast),super.updateOptions(U)}_createInnerEditor(U,j,Y){return U.createInstance(x,j,Y)}getOriginalEditor(){return super.getOriginalEditor()}getModifiedEditor(){return super.getModifiedEditor()}addCommand(U,j,Y){return this.getModifiedEditor().addCommand(U,j,Y)}createContextKey(U,j){return this.getModifiedEditor().createContextKey(U,j)}addAction(U){return this.getModifiedEditor().addAction(U)}};e.StandaloneDiffEditor2=V,e.StandaloneDiffEditor2=V=ke([ce(2,i.IInstantiationService),ce(3,o.IContextKeyService),ce(4,I.ICodeEditorService),ce(5,_.IStandaloneThemeService),ce(6,g.INotificationService),ce(7,n.IConfigurationService),ce(8,t.IContextMenuService),ce(9,u.IEditorProgressService),ce(10,r.IClipboardService),ce(11,D.IAccessibilitySignalService)],V);function q(z,U,j,Y,G){if(j=j||"",!Y){const K=j.indexOf(` `);let R=j;return K!==-1&&(R=j.substring(0,K)),H(z,j,U.createByFilepathOrFirstLine(G||null,R),G)}return H(z,j,U.createById(Y),G)}function H(z,U,j,Y){return z.createModel(U,j,Y)}}),define(ne[872],se([1,0,33,4,27,43,36,70,17,238,222,625,389,153,28,108]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.TokenizationSupportAdapter=e.EncodedTokenizationSupportAdapter=void 0,e.register=g,e.getLanguages=c,e.getEncodedLanguageId=l,e.onLanguage=a,e.onLanguageEncountered=r,e.setLanguageConfiguration=u,e.setColorMap=S,e.registerTokensProviderFactory=D,e.setTokensProvider=T,e.setMonarchTokensProvider=M,e.registerReferenceProvider=A,e.registerRenameProvider=P,e.registerNewSymbolNameProvider=N,e.registerSignatureHelpProvider=O,e.registerHoverProvider=F,e.registerDocumentSymbolProvider=x,e.registerDocumentHighlightProvider=W,e.registerLinkedEditingRangeProvider=V,e.registerDefinitionProvider=q,e.registerImplementationProvider=H,e.registerTypeDefinitionProvider=z,e.registerCodeLensProvider=U,e.registerCodeActionProvider=j,e.registerDocumentFormattingEditProvider=Y,e.registerDocumentRangeFormattingEditProvider=G,e.registerOnTypeFormattingEditProvider=K,e.registerLinkProvider=R,e.registerCompletionItemProvider=J,e.registerColorProvider=ie,e.registerFoldingRangeProvider=ue,e.registerDeclarationProvider=he,e.registerSelectionRangeProvider=pe,e.registerDocumentSemanticTokensProvider=ae,e.registerDocumentRangeSemanticTokensProvider=ee,e.registerInlineCompletionsProvider=de,e.registerInlineEditProvider=ge,e.registerInlayHintsProvider=X,e.createMonacoLanguagesAPI=B;function g($){m.ModesRegistry.registerLanguage($)}function c(){let $=[];return $=$.concat(m.ModesRegistry.getLanguages()),$}function l($){return p.StandaloneServices.get(E.ILanguageService).languageIdCodec.encodeLanguageId($)}function a($,Q){return p.StandaloneServices.withServices(()=>{const te=p.StandaloneServices.get(E.ILanguageService).onDidRequestRichLanguageFeatures(re=>{re===$&&(te.dispose(),Q())});return te})}function r($,Q){return p.StandaloneServices.withServices(()=>{const te=p.StandaloneServices.get(E.ILanguageService).onDidRequestBasicLanguageFeatures(re=>{re===$&&(te.dispose(),Q())});return te})}function u($,Q){if(!p.StandaloneServices.get(E.ILanguageService).isRegisteredLanguageId($))throw new Error(`Cannot set configuration for unknown language ${$}`);return p.StandaloneServices.get(y.ILanguageConfigurationService).register($,Q,100)}class C{constructor(Q,Z){this._languageId=Q,this._actual=Z}dispose(){}getInitialState(){return this._actual.getInitialState()}tokenize(Q,Z,te){if(typeof this._actual.tokenize=="function")return f.adaptTokenize(this._languageId,this._actual,Q,te);throw new Error("Not supported!")}tokenizeEncoded(Q,Z,te){const re=this._actual.tokenizeEncoded(Q,te);return new I.EncodedTokenizationResult(re.tokens,re.endState)}}e.EncodedTokenizationSupportAdapter=C;class f{constructor(Q,Z,te,re){this._languageId=Q,this._actual=Z,this._languageService=te,this._standaloneThemeService=re}dispose(){}getInitialState(){return this._actual.getInitialState()}static _toClassicTokens(Q,Z){const te=[];let re=0;for(let le=0,me=Q.length;le0&&le[me-1]===Ae)continue;let Ne=Me.startIndex;Le===0?Ne=0:Ne{const te=await Promise.resolve(Q.create());return te?h(te)?L($,te):new o.MonarchTokenizer(p.StandaloneServices.get(E.ILanguageService),p.StandaloneServices.get(t.IStandaloneThemeService),$,(0,n.compile)($,te),p.StandaloneServices.get(i.IConfigurationService)):null});return I.TokenizationRegistry.registerFactory($,Z)}function T($,Q){if(!p.StandaloneServices.get(E.ILanguageService).isRegisteredLanguageId($))throw new Error(`Cannot set tokens provider for unknown language ${$}`);return w(Q)?D($,{create:()=>Q}):I.TokenizationRegistry.register($,L($,Q))}function M($,Q){const Z=te=>new o.MonarchTokenizer(p.StandaloneServices.get(E.ILanguageService),p.StandaloneServices.get(t.IStandaloneThemeService),$,(0,n.compile)($,te),p.StandaloneServices.get(i.IConfigurationService));return w(Q)?D($,{create:()=>Q}):I.TokenizationRegistry.register($,Z(Q))}function A($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).referenceProvider.register($,Q)}function P($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).renameProvider.register($,Q)}function N($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).newSymbolNamesProvider.register($,Q)}function O($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).signatureHelpProvider.register($,Q)}function F($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).hoverProvider.register($,{provideHover:async(te,re,le,me)=>{const Ce=te.getWordAtPosition(re);return Promise.resolve(Q.provideHover(te,re,le,me)).then(ye=>{if(ye)return!ye.range&&Ce&&(ye.range=new k.Range(re.lineNumber,Ce.startColumn,re.lineNumber,Ce.endColumn)),ye.range||(ye.range=new k.Range(re.lineNumber,re.column,re.lineNumber,re.column)),ye})}})}function x($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).documentSymbolProvider.register($,Q)}function W($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).documentHighlightProvider.register($,Q)}function V($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).linkedEditingRangeProvider.register($,Q)}function q($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).definitionProvider.register($,Q)}function H($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).implementationProvider.register($,Q)}function z($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).typeDefinitionProvider.register($,Q)}function U($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).codeLensProvider.register($,Q)}function j($,Q,Z){return p.StandaloneServices.get(_.ILanguageFeaturesService).codeActionProvider.register($,{providedCodeActionKinds:Z?.providedCodeActionKinds,documentation:Z?.documentation,provideCodeActions:(re,le,me,Ce)=>{const Le=p.StandaloneServices.get(s.IMarkerService).read({resource:re.uri}).filter(Ee=>k.Range.areIntersectingOrTouching(Ee,le));return Q.provideCodeActions(re,le,{markers:Le,only:me.only,trigger:me.trigger},Ce)},resolveCodeAction:Q.resolveCodeAction})}function Y($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).documentFormattingEditProvider.register($,Q)}function G($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).documentRangeFormattingEditProvider.register($,Q)}function K($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).onTypeFormattingEditProvider.register($,Q)}function R($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).linkProvider.register($,Q)}function J($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).completionProvider.register($,Q)}function ie($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).colorProvider.register($,Q)}function ue($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).foldingRangeProvider.register($,Q)}function he($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).declarationProvider.register($,Q)}function pe($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).selectionRangeProvider.register($,Q)}function ae($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).documentSemanticTokensProvider.register($,Q)}function ee($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).documentRangeSemanticTokensProvider.register($,Q)}function de($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).inlineCompletionsProvider.register($,Q)}function ge($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).inlineEditProvider.register($,Q)}function X($,Q){return p.StandaloneServices.get(_.ILanguageFeaturesService).inlayHintsProvider.register($,Q)}function B(){return{register:g,getLanguages:c,onLanguage:a,onLanguageEncountered:r,getEncodedLanguageId:l,setLanguageConfiguration:u,setColorMap:S,registerTokensProviderFactory:D,setTokensProvider:T,setMonarchTokensProvider:M,registerReferenceProvider:A,registerRenameProvider:P,registerNewSymbolNameProvider:N,registerCompletionItemProvider:J,registerSignatureHelpProvider:O,registerHoverProvider:F,registerDocumentSymbolProvider:x,registerDocumentHighlightProvider:W,registerLinkedEditingRangeProvider:V,registerDefinitionProvider:q,registerImplementationProvider:H,registerTypeDefinitionProvider:z,registerCodeLensProvider:U,registerCodeActionProvider:j,registerDocumentFormattingEditProvider:Y,registerDocumentRangeFormattingEditProvider:G,registerOnTypeFormattingEditProvider:K,registerLinkProvider:R,registerColorProvider:ie,registerFoldingRangeProvider:ue,registerDeclarationProvider:he,registerSelectionRangeProvider:pe,registerDocumentSemanticTokensProvider:ae,registerDocumentRangeSemanticTokensProvider:ee,registerInlineCompletionsProvider:de,registerInlineEditProvider:ge,registerInlayHintsProvider:X,DocumentHighlightKind:b.DocumentHighlightKind,CompletionItemKind:b.CompletionItemKind,CompletionItemTag:b.CompletionItemTag,CompletionItemInsertTextRule:b.CompletionItemInsertTextRule,SymbolKind:b.SymbolKind,SymbolTag:b.SymbolTag,IndentAction:b.IndentAction,CompletionTriggerKind:b.CompletionTriggerKind,SignatureHelpTriggerKind:b.SignatureHelpTriggerKind,InlayHintKind:b.InlayHintKind,InlineCompletionTriggerKind:b.InlineCompletionTriggerKind,InlineEditTriggerKind:b.InlineEditTriggerKind,CodeActionTriggerType:b.CodeActionTriggerType,NewSymbolNameTag:b.NewSymbolNameTag,NewSymbolNameTriggerKind:b.NewSymbolNameTriggerKind,PartialAcceptTriggerKind:b.PartialAcceptTriggerKind,HoverVerbosityAction:b.HoverVerbosityAction,FoldingRangeKind:I.FoldingRangeKind,SelectedSuggestionInfo:I.SelectedSuggestionInfo}}}),define(ne[873],se([1,0,60,401,222]),function(oe,e,d,k,I){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.createWebWorker=E;function E(m,_){return new y(m,_)}class y extends k.EditorWorkerClient{constructor(_,b){const p={amdModuleId:I.standaloneEditorWorkerDescriptor.amdModuleId,esmModuleLocation:I.standaloneEditorWorkerDescriptor.esmModuleLocation,label:b.label};super(p,b.keepIdleModels||!1,_),this._foreignModuleId=b.moduleId,this._foreignModuleCreateData=b.createData||null,this._foreignModuleHost=b.host||null,this._foreignProxy=null}fhr(_,b){if(!this._foreignModuleHost||typeof this._foreignModuleHost[_]!="function")return Promise.reject(new Error("Missing method "+_+" or missing main thread foreign host."));try{return Promise.resolve(this._foreignModuleHost[_].apply(this._foreignModuleHost,b))}catch(p){return Promise.reject(p)}}_getForeignProxy(){return this._foreignProxy||(this._foreignProxy=this._getProxy().then(_=>{const b=this._foreignModuleHost?(0,d.getAllMethodNames)(this._foreignModuleHost):[];return _.$loadForeignModule(this._foreignModuleId,this._foreignModuleCreateData,b).then(p=>{this._foreignModuleCreateData=null;const n=(i,s)=>_.$fmr(i,s),o=(i,s)=>function(){const g=Array.prototype.slice.call(arguments,0);return s(i,g)},t={};for(const i of p)t[i]=o(i,n);return t})})),this._foreignProxy}getProxy(){return this._getForeignProxy()}withSyncedResources(_){return this.workerWithSyncedResources(_).then(b=>this.getProxy())}}}),define(ne[874],se([1,0,52,2,11,22,366,15,34,873,37,165,261,198,27,43,70,177,40,51,238,682,871,222,153,29,24,12,31,108,59,814,541]),function(oe,e,d,k,I,E,y,m,_,b,p,n,o,t,i,s,g,c,l,a,r,u,C,f,h,v,w,S,L,D,T,M){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.create=A,e.onDidCreateEditor=P,e.onDidCreateDiffEditor=N,e.getEditors=O,e.getDiffEditors=F,e.createDiffEditor=x,e.createMultiFileDiffEditor=W,e.addCommand=V,e.addEditorAction=q,e.addKeybindingRule=H,e.addKeybindingRules=z,e.createModel=U,e.setModelLanguage=j,e.setModelMarkers=Y,e.removeAllMarkers=G,e.getModelMarkers=K,e.onDidChangeMarkers=R,e.getModel=J,e.getModels=ie,e.onDidCreateModel=ue,e.onWillDisposeModel=he,e.onDidChangeModelLanguage=pe,e.createWebWorker=ae,e.colorizeElement=ee,e.colorize=de,e.colorizeModelLine=ge,e.tokenize=B,e.defineTheme=$,e.setTheme=Q,e.remeasureFonts=Z,e.registerCommand=te,e.registerLinkOpener=re,e.registerEditorOpener=le,e.createMonacoEditorAPI=me;function A(Ce,ye,Le){return f.StandaloneServices.initialize(Le||{}).createInstance(C.StandaloneEditor,Ce,ye)}function P(Ce){return f.StandaloneServices.get(_.ICodeEditorService).onCodeEditorAdd(Le=>{Ce(Le)})}function N(Ce){return f.StandaloneServices.get(_.ICodeEditorService).onDiffEditorAdd(Le=>{Ce(Le)})}function O(){return f.StandaloneServices.get(_.ICodeEditorService).listCodeEditors()}function F(){return f.StandaloneServices.get(_.ICodeEditorService).listDiffEditors()}function x(Ce,ye,Le){return f.StandaloneServices.initialize(Le||{}).createInstance(C.StandaloneDiffEditor2,Ce,ye)}function W(Ce,ye){const Le=f.StandaloneServices.initialize(ye||{});return new M.MultiDiffEditorWidget(Ce,{},Le)}function V(Ce){if(typeof Ce.id!="string"||typeof Ce.run!="function")throw new Error("Invalid command descriptor, `id` and `run` are required properties!");return w.CommandsRegistry.registerCommand(Ce.id,Ce.run)}function q(Ce){if(typeof Ce.id!="string"||typeof Ce.label!="string"||typeof Ce.run!="function")throw new Error("Invalid action descriptor, `id`, `label` and `run` are required properties!");const ye=S.ContextKeyExpr.deserialize(Ce.precondition),Le=(Me,...Ae)=>m.EditorCommand.runEditorCommand(Me,Ae,ye,(Ne,Ke,ze)=>Promise.resolve(Ce.run(Ke,...ze))),Ee=new k.DisposableStore;if(Ee.add(w.CommandsRegistry.registerCommand(Ce.id,Le)),Ce.contextMenuGroupId){const Me={command:{id:Ce.id,title:Ce.label},when:ye,group:Ce.contextMenuGroupId,order:Ce.contextMenuOrder||0};Ee.add(v.MenuRegistry.appendMenuItem(v.MenuId.EditorContext,Me))}if(Array.isArray(Ce.keybindings)){const Me=f.StandaloneServices.get(L.IKeybindingService);if(!(Me instanceof f.StandaloneKeybindingService))console.warn("Cannot add keybinding because the editor is configured with an unrecognized KeybindingService");else{const Ae=S.ContextKeyExpr.and(ye,S.ContextKeyExpr.deserialize(Ce.keybindingContext));Ee.add(Me.addDynamicKeybindings(Ce.keybindings.map(Ne=>({keybinding:Ne,command:Ce.id,when:Ae}))))}}return Ee}function H(Ce){return z([Ce])}function z(Ce){const ye=f.StandaloneServices.get(L.IKeybindingService);return ye instanceof f.StandaloneKeybindingService?ye.addDynamicKeybindings(Ce.map(Le=>({keybinding:Le.keybinding,command:Le.command,commandArgs:Le.commandArgs,when:S.ContextKeyExpr.deserialize(Le.when)}))):(console.warn("Cannot add keybinding because the editor is configured with an unrecognized KeybindingService"),k.Disposable.None)}function U(Ce,ye,Le){const Ee=f.StandaloneServices.get(s.ILanguageService),Me=Ee.getLanguageIdByMimeType(ye)||ye;return(0,C.createTextModel)(f.StandaloneServices.get(a.IModelService),Ee,Ce,Me,Le)}function j(Ce,ye){const Le=f.StandaloneServices.get(s.ILanguageService),Ee=Le.getLanguageIdByMimeType(ye)||ye||g.PLAINTEXT_LANGUAGE_ID;Ce.setLanguage(Le.createById(Ee))}function Y(Ce,ye,Le){Ce&&f.StandaloneServices.get(D.IMarkerService).changeOne(ye,Ce.uri,Le)}function G(Ce){f.StandaloneServices.get(D.IMarkerService).changeAll(Ce,[])}function K(Ce){return f.StandaloneServices.get(D.IMarkerService).read(Ce)}function R(Ce){return f.StandaloneServices.get(D.IMarkerService).onMarkerChanged(Ce)}function J(Ce){return f.StandaloneServices.get(a.IModelService).getModel(Ce)}function ie(){return f.StandaloneServices.get(a.IModelService).getModels()}function ue(Ce){return f.StandaloneServices.get(a.IModelService).onModelAdded(Ce)}function he(Ce){return f.StandaloneServices.get(a.IModelService).onModelRemoved(Ce)}function pe(Ce){return f.StandaloneServices.get(a.IModelService).onModelLanguageChanged(Le=>{Ce({model:Le.model,oldLanguage:Le.oldLanguageId})})}function ae(Ce){return(0,b.createWebWorker)(f.StandaloneServices.get(a.IModelService),Ce)}function ee(Ce,ye){const Le=f.StandaloneServices.get(s.ILanguageService),Ee=f.StandaloneServices.get(h.IStandaloneThemeService);return u.Colorizer.colorizeElement(Ee,Le,Ce,ye).then(()=>{Ee.registerEditorContainer(Ce)})}function de(Ce,ye,Le){const Ee=f.StandaloneServices.get(s.ILanguageService);return f.StandaloneServices.get(h.IStandaloneThemeService).registerEditorContainer(d.mainWindow.document.body),u.Colorizer.colorize(Ee,Ce,ye,Le)}function ge(Ce,ye,Le=4){return f.StandaloneServices.get(h.IStandaloneThemeService).registerEditorContainer(d.mainWindow.document.body),u.Colorizer.colorizeModelLine(Ce,ye,Le)}function X(Ce){const ye=i.TokenizationRegistry.get(Ce);return ye||{getInitialState:()=>c.NullState,tokenize:(Le,Ee,Me)=>(0,c.nullTokenize)(Ce,Me)}}function B(Ce,ye){i.TokenizationRegistry.getOrCreate(ye);const Le=X(ye),Ee=(0,I.splitLines)(Ce),Me=[];let Ae=Le.getInitialState();for(let Ne=0,Ke=Ee.length;Ne{if(!Ee)return null;const Ae=Le.options?.selection;let Ne;return Ae&&typeof Ae.endLineNumber=="number"&&typeof Ae.endColumn=="number"?Ne=Ae:Ae&&(Ne={lineNumber:Ae.startLineNumber,column:Ae.startColumn}),await Ce.openCodeEditor(Ee,Le.resource,Ne)?Ee:null})}function me(){return{create:A,getEditors:O,getDiffEditors:F,onDidCreateEditor:P,onDidCreateDiffEditor:N,createDiffEditor:x,addCommand:V,addEditorAction:q,addKeybindingRule:H,addKeybindingRules:z,createModel:U,setModelLanguage:j,setModelMarkers:Y,getModelMarkers:K,removeAllMarkers:G,onDidChangeMarkers:R,getModels:ie,getModel:J,onDidCreateModel:ue,onWillDisposeModel:he,onDidChangeModelLanguage:pe,createWebWorker:ae,colorizeElement:ee,colorize:de,colorizeModelLine:ge,tokenize:B,defineTheme:$,setTheme:Q,remeasureFonts:Z,registerCommand:te,registerLinkOpener:re,registerEditorOpener:le,AccessibilitySupport:r.AccessibilitySupport,ContentWidgetPositionPreference:r.ContentWidgetPositionPreference,CursorChangeReason:r.CursorChangeReason,DefaultEndOfLine:r.DefaultEndOfLine,EditorAutoIndentStrategy:r.EditorAutoIndentStrategy,EditorOption:r.EditorOption,EndOfLinePreference:r.EndOfLinePreference,EndOfLineSequence:r.EndOfLineSequence,MinimapPosition:r.MinimapPosition,MinimapSectionHeaderStyle:r.MinimapSectionHeaderStyle,MouseTargetType:r.MouseTargetType,OverlayWidgetPositionPreference:r.OverlayWidgetPositionPreference,OverviewRulerLane:r.OverviewRulerLane,GlyphMarginLane:r.GlyphMarginLane,RenderLineNumbersType:r.RenderLineNumbersType,RenderMinimap:r.RenderMinimap,ScrollbarVisibility:r.ScrollbarVisibility,ScrollType:r.ScrollType,TextEditorCursorBlinkingStyle:r.TextEditorCursorBlinkingStyle,TextEditorCursorStyle:r.TextEditorCursorStyle,TrackedRangeStickiness:r.TrackedRangeStickiness,WrappingIndent:r.WrappingIndent,InjectedTextCursorStops:r.InjectedTextCursorStops,PositionAffinity:r.PositionAffinity,ShowLightbulbIconMode:r.ShowLightbulbIconMode,ConfigurationChangedEvent:p.ConfigurationChangedEvent,BareFontInfo:o.BareFontInfo,FontInfo:o.FontInfo,TextModelResolvedOptions:l.TextModelResolvedOptions,FindMatch:l.FindMatch,ApplyUpdateResult:p.ApplyUpdateResult,EditorZoom:n.EditorZoom,createMultiFileDiffEditor:W,EditorType:t.EditorType,EditorOptions:p.EditorOptions}}}),define(ne[875],se([1,0,37,372,874,872,409]),function(oe,e,d,k,I,E,y){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.languages=e.editor=e.Token=e.Uri=e.MarkerTag=e.MarkerSeverity=e.SelectionDirection=e.Selection=e.Range=e.Position=e.KeyMod=e.KeyCode=e.Emitter=e.CancellationTokenSource=void 0,d.EditorOptions.wrappingIndent.defaultValue=0,d.EditorOptions.glyphMargin.defaultValue=!1,d.EditorOptions.autoIndent.defaultValue=3,d.EditorOptions.overviewRulerLanes.defaultValue=2,y.FormattingConflicts.setFormatterSelector((b,p,n)=>Promise.resolve(b[0]));const m=(0,k.createMonacoBaseAPI)();m.editor=(0,I.createMonacoEditorAPI)(),m.languages=(0,E.createMonacoLanguagesAPI)(),e.CancellationTokenSource=m.CancellationTokenSource,e.Emitter=m.Emitter,e.KeyCode=m.KeyCode,e.KeyMod=m.KeyMod,e.Position=m.Position,e.Range=m.Range,e.Selection=m.Selection,e.SelectionDirection=m.SelectionDirection,e.MarkerSeverity=m.MarkerSeverity,e.MarkerTag=m.MarkerTag,e.Uri=m.Uri,e.Token=m.Token,e.editor=m.editor,e.languages=m.languages,(globalThis.MonacoEnvironment?.globalAPI||typeof define=="function"&&define.amd)&&(globalThis.monaco=m),typeof globalThis.require<"u"&&typeof globalThis.require.config=="function"&&globalThis.require.config({ignoreDuplicateModules:["vscode-languageserver-types","vscode-languageserver-types/main","vscode-languageserver-textdocument","vscode-languageserver-textdocument/main","vscode-nls","vscode-nls/vscode-nls","jsonc-parser","jsonc-parser/main","vscode-uri","vscode-uri/index","vs/basic-languages/typescript/typescript"]})});var Lt=this&&this.__exportStar||function(oe,e){for(var d in oe)d!=="default"&&!Object.prototype.hasOwnProperty.call(e,d)&&ci(e,oe,d)};define(ne[877],se([1,0,875,870,746,747,721,794,795,750,854,797]),function(oe,e,d){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),Lt(d,e)})}).call(this); /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/basic-languages/monaco.contribution", ["require","require","vs/editor/editor.api"],(require)=>{ "use strict";var moduleExports=(()=>{var y=Object.create;var g=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var A=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var a=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(r,s)=>(typeof require<"u"?require:r)[s]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var D=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports);var l=(e,r,s,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of q(r))!M.call(e,o)&&o!==s&&g(e,o,{get:()=>r[o],enumerable:!(n=x(r,o))||n.enumerable});return e},p=(e,r,s)=>(l(e,r,"default"),s&&l(s,r,"default")),c=(e,r,s)=>(s=e!=null?y(A(e)):{},l(r||!e||!e.__esModule?g(s,"default",{value:e,enumerable:!0}):s,e));var v=D((w,d)=>{var b=c(a("vs/editor/editor.api"));d.exports=b});var t={};p(t,c(v()));var f={},m={},u=class e{static getOrCreate(r){return m[r]||(m[r]=new e(r)),m[r]}constructor(r){this._languageId=r,this._loadingTriggered=!1,this._lazyLoadPromise=new Promise((s,n)=>{this._lazyLoadPromiseResolve=s,this._lazyLoadPromiseReject=n})}load(){return this._loadingTriggered||(this._loadingTriggered=!0,f[this._languageId].loader().then(r=>this._lazyLoadPromiseResolve(r),r=>this._lazyLoadPromiseReject(r))),this._lazyLoadPromise}};function i(e){let r=e.id;f[r]=e,t.languages.register(e);let s=u.getOrCreate(r);t.languages.registerTokensProviderFactory(r,{create:async()=>(await s.load()).language}),t.languages.onLanguageEncountered(r,async()=>{let n=await s.load();t.languages.setLanguageConfiguration(r,n.conf)})}i({id:"abap",extensions:[".abap"],aliases:["abap","ABAP"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/abap/abap"],e,r)})});i({id:"apex",extensions:[".cls"],aliases:["Apex","apex"],mimetypes:["text/x-apex-source","text/x-apex"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/apex/apex"],e,r)})});i({id:"azcli",extensions:[".azcli"],aliases:["Azure CLI","azcli"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/azcli/azcli"],e,r)})});i({id:"bat",extensions:[".bat",".cmd"],aliases:["Batch","bat"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/bat/bat"],e,r)})});i({id:"bicep",extensions:[".bicep"],aliases:["Bicep"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/bicep/bicep"],e,r)})});i({id:"cameligo",extensions:[".mligo"],aliases:["Cameligo"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/cameligo/cameligo"],e,r)})});i({id:"clojure",extensions:[".clj",".cljs",".cljc",".edn"],aliases:["clojure","Clojure"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/clojure/clojure"],e,r)})});i({id:"coffeescript",extensions:[".coffee"],aliases:["CoffeeScript","coffeescript","coffee"],mimetypes:["text/x-coffeescript","text/coffeescript"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/coffee/coffee"],e,r)})});i({id:"c",extensions:[".c",".h"],aliases:["C","c"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/cpp/cpp"],e,r)})});i({id:"cpp",extensions:[".cpp",".cc",".cxx",".hpp",".hh",".hxx"],aliases:["C++","Cpp","cpp"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/cpp/cpp"],e,r)})});i({id:"csharp",extensions:[".cs",".csx",".cake"],aliases:["C#","csharp"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/csharp/csharp"],e,r)})});i({id:"csp",extensions:[".csp"],aliases:["CSP","csp"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/csp/csp"],e,r)})});i({id:"css",extensions:[".css"],aliases:["CSS","css"],mimetypes:["text/css"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/css/css"],e,r)})});i({id:"cypher",extensions:[".cypher",".cyp"],aliases:["Cypher","OpenCypher"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/cypher/cypher"],e,r)})});i({id:"dart",extensions:[".dart"],aliases:["Dart","dart"],mimetypes:["text/x-dart-source","text/x-dart"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/dart/dart"],e,r)})});i({id:"dockerfile",extensions:[".dockerfile"],filenames:["Dockerfile"],aliases:["Dockerfile"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/dockerfile/dockerfile"],e,r)})});i({id:"ecl",extensions:[".ecl"],aliases:["ECL","Ecl","ecl"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/ecl/ecl"],e,r)})});i({id:"elixir",extensions:[".ex",".exs"],aliases:["Elixir","elixir","ex"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/elixir/elixir"],e,r)})});i({id:"flow9",extensions:[".flow"],aliases:["Flow9","Flow","flow9","flow"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/flow9/flow9"],e,r)})});i({id:"fsharp",extensions:[".fs",".fsi",".ml",".mli",".fsx",".fsscript"],aliases:["F#","FSharp","fsharp"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/fsharp/fsharp"],e,r)})});i({id:"freemarker2",extensions:[".ftl",".ftlh",".ftlx"],aliases:["FreeMarker2","Apache FreeMarker2"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/freemarker2/freemarker2"],e,r)}).then(e=>e.TagAngleInterpolationDollar)});i({id:"freemarker2.tag-angle.interpolation-dollar",aliases:["FreeMarker2 (Angle/Dollar)","Apache FreeMarker2 (Angle/Dollar)"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/freemarker2/freemarker2"],e,r)}).then(e=>e.TagAngleInterpolationDollar)});i({id:"freemarker2.tag-bracket.interpolation-dollar",aliases:["FreeMarker2 (Bracket/Dollar)","Apache FreeMarker2 (Bracket/Dollar)"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/freemarker2/freemarker2"],e,r)}).then(e=>e.TagBracketInterpolationDollar)});i({id:"freemarker2.tag-angle.interpolation-bracket",aliases:["FreeMarker2 (Angle/Bracket)","Apache FreeMarker2 (Angle/Bracket)"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/freemarker2/freemarker2"],e,r)}).then(e=>e.TagAngleInterpolationBracket)});i({id:"freemarker2.tag-bracket.interpolation-bracket",aliases:["FreeMarker2 (Bracket/Bracket)","Apache FreeMarker2 (Bracket/Bracket)"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/freemarker2/freemarker2"],e,r)}).then(e=>e.TagBracketInterpolationBracket)});i({id:"freemarker2.tag-auto.interpolation-dollar",aliases:["FreeMarker2 (Auto/Dollar)","Apache FreeMarker2 (Auto/Dollar)"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/freemarker2/freemarker2"],e,r)}).then(e=>e.TagAutoInterpolationDollar)});i({id:"freemarker2.tag-auto.interpolation-bracket",aliases:["FreeMarker2 (Auto/Bracket)","Apache FreeMarker2 (Auto/Bracket)"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/freemarker2/freemarker2"],e,r)}).then(e=>e.TagAutoInterpolationBracket)});i({id:"go",extensions:[".go"],aliases:["Go"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/go/go"],e,r)})});i({id:"graphql",extensions:[".graphql",".gql"],aliases:["GraphQL","graphql","gql"],mimetypes:["application/graphql"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/graphql/graphql"],e,r)})});i({id:"handlebars",extensions:[".handlebars",".hbs"],aliases:["Handlebars","handlebars","hbs"],mimetypes:["text/x-handlebars-template"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/handlebars/handlebars"],e,r)})});i({id:"hcl",extensions:[".tf",".tfvars",".hcl"],aliases:["Terraform","tf","HCL","hcl"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/hcl/hcl"],e,r)})});i({id:"html",extensions:[".html",".htm",".shtml",".xhtml",".mdoc",".jsp",".asp",".aspx",".jshtm"],aliases:["HTML","htm","html","xhtml"],mimetypes:["text/html","text/x-jshtm","text/template","text/ng-template"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/html/html"],e,r)})});i({id:"ini",extensions:[".ini",".properties",".gitconfig"],filenames:["config",".gitattributes",".gitconfig",".editorconfig"],aliases:["Ini","ini"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/ini/ini"],e,r)})});i({id:"java",extensions:[".java",".jav"],aliases:["Java","java"],mimetypes:["text/x-java-source","text/x-java"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/java/java"],e,r)})});i({id:"javascript",extensions:[".js",".es6",".jsx",".mjs",".cjs"],firstLine:"^#!.*\\bnode",filenames:["jakefile"],aliases:["JavaScript","javascript","js"],mimetypes:["text/javascript"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/javascript/javascript"],e,r)})});i({id:"julia",extensions:[".jl"],aliases:["julia","Julia"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/julia/julia"],e,r)})});i({id:"kotlin",extensions:[".kt",".kts"],aliases:["Kotlin","kotlin"],mimetypes:["text/x-kotlin-source","text/x-kotlin"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/kotlin/kotlin"],e,r)})});i({id:"less",extensions:[".less"],aliases:["Less","less"],mimetypes:["text/x-less","text/less"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/less/less"],e,r)})});i({id:"lexon",extensions:[".lex"],aliases:["Lexon"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/lexon/lexon"],e,r)})});i({id:"lua",extensions:[".lua"],aliases:["Lua","lua"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/lua/lua"],e,r)})});i({id:"liquid",extensions:[".liquid",".html.liquid"],aliases:["Liquid","liquid"],mimetypes:["application/liquid"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/liquid/liquid"],e,r)})});i({id:"m3",extensions:[".m3",".i3",".mg",".ig"],aliases:["Modula-3","Modula3","modula3","m3"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/m3/m3"],e,r)})});i({id:"markdown",extensions:[".md",".markdown",".mdown",".mkdn",".mkd",".mdwn",".mdtxt",".mdtext"],aliases:["Markdown","markdown"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/markdown/markdown"],e,r)})});i({id:"mdx",extensions:[".mdx"],aliases:["MDX","mdx"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/mdx/mdx"],e,r)})});i({id:"mips",extensions:[".s"],aliases:["MIPS","MIPS-V"],mimetypes:["text/x-mips","text/mips","text/plaintext"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/mips/mips"],e,r)})});i({id:"msdax",extensions:[".dax",".msdax"],aliases:["DAX","MSDAX"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/msdax/msdax"],e,r)})});i({id:"mysql",extensions:[],aliases:["MySQL","mysql"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/mysql/mysql"],e,r)})});i({id:"objective-c",extensions:[".m"],aliases:["Objective-C"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/objective-c/objective-c"],e,r)})});i({id:"pascal",extensions:[".pas",".p",".pp"],aliases:["Pascal","pas"],mimetypes:["text/x-pascal-source","text/x-pascal"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/pascal/pascal"],e,r)})});i({id:"pascaligo",extensions:[".ligo"],aliases:["Pascaligo","ligo"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/pascaligo/pascaligo"],e,r)})});i({id:"perl",extensions:[".pl",".pm"],aliases:["Perl","pl"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/perl/perl"],e,r)})});i({id:"pgsql",extensions:[],aliases:["PostgreSQL","postgres","pg","postgre"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/pgsql/pgsql"],e,r)})});i({id:"php",extensions:[".php",".php4",".php5",".phtml",".ctp"],aliases:["PHP","php"],mimetypes:["application/x-php"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/php/php"],e,r)})});i({id:"pla",extensions:[".pla"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/pla/pla"],e,r)})});i({id:"postiats",extensions:[".dats",".sats",".hats"],aliases:["ATS","ATS/Postiats"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/postiats/postiats"],e,r)})});i({id:"powerquery",extensions:[".pq",".pqm"],aliases:["PQ","M","Power Query","Power Query M"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/powerquery/powerquery"],e,r)})});i({id:"powershell",extensions:[".ps1",".psm1",".psd1"],aliases:["PowerShell","powershell","ps","ps1"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/powershell/powershell"],e,r)})});i({id:"proto",extensions:[".proto"],aliases:["protobuf","Protocol Buffers"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/protobuf/protobuf"],e,r)})});i({id:"pug",extensions:[".jade",".pug"],aliases:["Pug","Jade","jade"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/pug/pug"],e,r)})});i({id:"python",extensions:[".py",".rpy",".pyw",".cpy",".gyp",".gypi"],aliases:["Python","py"],firstLine:"^#!/.*\\bpython[0-9.-]*\\b",loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/python/python"],e,r)})});i({id:"qsharp",extensions:[".qs"],aliases:["Q#","qsharp"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/qsharp/qsharp"],e,r)})});i({id:"r",extensions:[".r",".rhistory",".rmd",".rprofile",".rt"],aliases:["R","r"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/r/r"],e,r)})});i({id:"razor",extensions:[".cshtml"],aliases:["Razor","razor"],mimetypes:["text/x-cshtml"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/razor/razor"],e,r)})});i({id:"redis",extensions:[".redis"],aliases:["redis"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/redis/redis"],e,r)})});i({id:"redshift",extensions:[],aliases:["Redshift","redshift"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/redshift/redshift"],e,r)})});i({id:"restructuredtext",extensions:[".rst"],aliases:["reStructuredText","restructuredtext"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/restructuredtext/restructuredtext"],e,r)})});i({id:"ruby",extensions:[".rb",".rbx",".rjs",".gemspec",".pp"],filenames:["rakefile","Gemfile"],aliases:["Ruby","rb"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/ruby/ruby"],e,r)})});i({id:"rust",extensions:[".rs",".rlib"],aliases:["Rust","rust"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/rust/rust"],e,r)})});i({id:"sb",extensions:[".sb"],aliases:["Small Basic","sb"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/sb/sb"],e,r)})});i({id:"scala",extensions:[".scala",".sc",".sbt"],aliases:["Scala","scala","SBT","Sbt","sbt","Dotty","dotty"],mimetypes:["text/x-scala-source","text/x-scala","text/x-sbt","text/x-dotty"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/scala/scala"],e,r)})});i({id:"scheme",extensions:[".scm",".ss",".sch",".rkt"],aliases:["scheme","Scheme"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/scheme/scheme"],e,r)})});i({id:"scss",extensions:[".scss"],aliases:["Sass","sass","scss"],mimetypes:["text/x-scss","text/scss"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/scss/scss"],e,r)})});i({id:"shell",extensions:[".sh",".bash"],aliases:["Shell","sh"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/shell/shell"],e,r)})});i({id:"sol",extensions:[".sol"],aliases:["sol","solidity","Solidity"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/solidity/solidity"],e,r)})});i({id:"aes",extensions:[".aes"],aliases:["aes","sophia","Sophia"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/sophia/sophia"],e,r)})});i({id:"sparql",extensions:[".rq"],aliases:["sparql","SPARQL"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/sparql/sparql"],e,r)})});i({id:"sql",extensions:[".sql"],aliases:["SQL"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/sql/sql"],e,r)})});i({id:"st",extensions:[".st",".iecst",".iecplc",".lc3lib",".TcPOU",".TcDUT",".TcGVL",".TcIO"],aliases:["StructuredText","scl","stl"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/st/st"],e,r)})});i({id:"swift",aliases:["Swift","swift"],extensions:[".swift"],mimetypes:["text/swift"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/swift/swift"],e,r)})});i({id:"systemverilog",extensions:[".sv",".svh"],aliases:["SV","sv","SystemVerilog","systemverilog"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/systemverilog/systemverilog"],e,r)})});i({id:"verilog",extensions:[".v",".vh"],aliases:["V","v","Verilog","verilog"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/systemverilog/systemverilog"],e,r)})});i({id:"tcl",extensions:[".tcl"],aliases:["tcl","Tcl","tcltk","TclTk","tcl/tk","Tcl/Tk"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/tcl/tcl"],e,r)})});i({id:"twig",extensions:[".twig"],aliases:["Twig","twig"],mimetypes:["text/x-twig"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/twig/twig"],e,r)})});i({id:"typescript",extensions:[".ts",".tsx",".cts",".mts"],aliases:["TypeScript","ts","typescript"],mimetypes:["text/typescript"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/typescript/typescript"],e,r)})});i({id:"typespec",extensions:[".tsp"],aliases:["TypeSpec"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/typespec/typespec"],e,r)})});i({id:"vb",extensions:[".vb"],aliases:["Visual Basic","vb"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/vb/vb"],e,r)})});i({id:"wgsl",extensions:[".wgsl"],aliases:["WebGPU Shading Language","WGSL","wgsl"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/wgsl/wgsl"],e,r)})});i({id:"xml",extensions:[".xml",".xsd",".dtd",".ascx",".csproj",".config",".props",".targets",".wxi",".wxl",".wxs",".xaml",".svg",".svgz",".opf",".xslt",".xsl"],firstLine:"(\\<\\?xml.*)|(\\new Promise((e,r)=>{a(["vs/basic-languages/xml/xml"],e,r)})});i({id:"yaml",extensions:[".yaml",".yml"],aliases:["YAML","yaml","YML","yml"],mimetypes:["application/x-yaml","text/x-yaml"],loader:()=>new Promise((e,r)=>{a(["vs/basic-languages/yaml/yaml"],e,r)})});})(); return moduleExports; }); /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/language/css/monaco.contribution", ["require","require","vs/editor/editor.api"],(require)=>{ "use strict";var moduleExports=(()=>{var C=Object.create;var g=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty;var l=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(n,r)=>(typeof require<"u"?require:n)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var I=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports),M=(e,n)=>{for(var r in n)g(e,r,{get:n[r],enumerable:!0})},s=(e,n,r,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of b(n))!h.call(e,t)&&t!==r&&g(e,t,{get:()=>n[t],enumerable:!(a=S(n,t))||a.enumerable});return e},y=(e,n,r)=>(s(e,n,"default"),r&&s(r,n,"default")),w=(e,n,r)=>(r=e!=null?C(x(e)):{},s(n||!e||!e.__esModule?g(r,"default",{value:e,enumerable:!0}):r,e)),P=e=>s(g({},"__esModule",{value:!0}),e);var v=I((k,D)=>{var O=w(l("vs/editor/editor.api"));D.exports=O});var R={};M(R,{cssDefaults:()=>p,lessDefaults:()=>f,scssDefaults:()=>c});var o={};y(o,w(v()));var i=class{constructor(n,r,a){this._onDidChange=new o.Emitter;this._languageId=n,this.setOptions(r),this.setModeConfiguration(a)}get onDidChange(){return this._onDidChange.event}get languageId(){return this._languageId}get modeConfiguration(){return this._modeConfiguration}get diagnosticsOptions(){return this.options}get options(){return this._options}setOptions(n){this._options=n||Object.create(null),this._onDidChange.fire(this)}setDiagnosticsOptions(n){this.setOptions(n)}setModeConfiguration(n){this._modeConfiguration=n||Object.create(null),this._onDidChange.fire(this)}},d={validate:!0,lint:{compatibleVendorPrefixes:"ignore",vendorPrefix:"warning",duplicateProperties:"warning",emptyRules:"warning",importStatement:"ignore",boxModel:"ignore",universalSelector:"ignore",zeroUnits:"ignore",fontFaceProperties:"warning",hexColorLength:"error",argumentsInColorFunction:"error",unknownProperties:"warning",ieHack:"ignore",unknownVendorSpecificProperties:"ignore",propertyIgnoredDueToDisplay:"warning",important:"ignore",float:"ignore",idSelector:"ignore"},data:{useDefaultDataProvider:!0},format:{newlineBetweenSelectors:!0,newlineBetweenRules:!0,spaceAroundSelectorSeparator:!1,braceStyle:"collapse",maxPreserveNewLines:void 0,preserveNewLines:!0}},u={completionItems:!0,hovers:!0,documentSymbols:!0,definitions:!0,references:!0,documentHighlights:!0,rename:!0,colors:!0,foldingRanges:!0,diagnostics:!0,selectionRanges:!0,documentFormattingEdits:!0,documentRangeFormattingEdits:!0},p=new i("css",d,u),c=new i("scss",d,u),f=new i("less",d,u);o.languages.css={cssDefaults:p,lessDefaults:f,scssDefaults:c};function m(){return new Promise((e,n)=>{l(["vs/language/css/cssMode"],e,n)})}o.languages.onLanguage("less",()=>{m().then(e=>e.setupMode(f))});o.languages.onLanguage("scss",()=>{m().then(e=>e.setupMode(c))});o.languages.onLanguage("css",()=>{m().then(e=>e.setupMode(p))});return P(R);})(); return moduleExports; }); /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/language/html/monaco.contribution", ["require","require","vs/editor/editor.api"],(require)=>{ "use strict";var moduleExports=(()=>{var w=Object.create;var l=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var f=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(n,t)=>(typeof require<"u"?require:n)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var k=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports),T=(e,n)=>{for(var t in n)l(e,t,{get:n[t],enumerable:!0})},d=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of H(n))!_.call(e,o)&&o!==t&&l(e,o,{get:()=>n[o],enumerable:!(r=R(n,o))||r.enumerable});return e},b=(e,n,t)=>(d(e,n,"default"),t&&d(t,n,"default")),v=(e,n,t)=>(t=e!=null?w(O(e)):{},d(n||!e||!e.__esModule?l(t,"default",{value:e,enumerable:!0}):t,e)),A=e=>d(l({},"__esModule",{value:!0}),e);var C=k((z,h)=>{var E=v(f("vs/editor/editor.api"));h.exports=E});var V={};T(V,{handlebarDefaults:()=>M,handlebarLanguageService:()=>m,htmlDefaults:()=>x,htmlLanguageService:()=>c,razorDefaults:()=>I,razorLanguageService:()=>y,registerHTMLLanguageService:()=>s});var a={};b(a,v(C()));var p=class{constructor(n,t,r){this._onDidChange=new a.Emitter;this._languageId=n,this.setOptions(t),this.setModeConfiguration(r)}get onDidChange(){return this._onDidChange.event}get languageId(){return this._languageId}get options(){return this._options}get modeConfiguration(){return this._modeConfiguration}setOptions(n){this._options=n||Object.create(null),this._onDidChange.fire(this)}setModeConfiguration(n){this._modeConfiguration=n||Object.create(null),this._onDidChange.fire(this)}},F={tabSize:4,insertSpaces:!1,wrapLineLength:120,unformatted:'default": "a, abbr, acronym, b, bdo, big, br, button, cite, code, dfn, em, i, img, input, kbd, label, map, object, q, samp, select, small, span, strong, sub, sup, textarea, tt, var',contentUnformatted:"pre",indentInnerHtml:!1,preserveNewLines:!0,maxPreserveNewLines:void 0,indentHandlebars:!1,endWithNewline:!1,extraLiners:"head, body, /html",wrapAttributes:"auto"},u={format:F,suggest:{},data:{useDefaultDataProvider:!0}};function g(e){return{completionItems:!0,hovers:!0,documentSymbols:!0,links:!0,documentHighlights:!0,rename:!0,colors:!0,foldingRanges:!0,selectionRanges:!0,diagnostics:e===i,documentFormattingEdits:e===i,documentRangeFormattingEdits:e===i}}var i="html",D="handlebars",L="razor",c=s(i,u,g(i)),x=c.defaults,m=s(D,u,g(D)),M=m.defaults,y=s(L,u,g(L)),I=y.defaults;a.languages.html={htmlDefaults:x,razorDefaults:I,handlebarDefaults:M,htmlLanguageService:c,handlebarLanguageService:m,razorLanguageService:y,registerHTMLLanguageService:s};function P(){return new Promise((e,n)=>{f(["vs/language/html/htmlMode"],e,n)})}function s(e,n=u,t=g(e)){let r=new p(e,n,t),o,S=a.languages.onLanguage(e,async()=>{o=(await P()).setupMode(r)});return{defaults:r,dispose(){S.dispose(),o?.dispose(),o=void 0}}}return A(V);})(); return moduleExports; }); /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/language/json/monaco.contribution", ["require","require","vs/editor/editor.api"],(require)=>{ "use strict";var moduleExports=(()=>{var f=Object.create;var s=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var d=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(n,o)=>(typeof require<"u"?require:n)[o]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var v=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports),x=(e,n)=>{for(var o in n)s(e,o,{get:n[o],enumerable:!0})},i=(e,n,o,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of N(n))!O.call(e,r)&&r!==o&&s(e,r,{get:()=>n[r],enumerable:!(a=h(n,r))||a.enumerable});return e},g=(e,n,o)=>(i(e,n,"default"),o&&i(o,n,"default")),c=(e,n,o)=>(o=e!=null?f(b(e)):{},i(n||!e||!e.__esModule?s(o,"default",{value:e,enumerable:!0}):o,e)),A=e=>i(s({},"__esModule",{value:!0}),e);var S=v((R,u)=>{var T=c(d("vs/editor/editor.api"));u.exports=T});var M={};x(M,{getWorker:()=>p,jsonDefaults:()=>m});var t={};g(t,c(S()));var l=class{constructor(n,o,a){this._onDidChange=new t.Emitter;this._languageId=n,this.setDiagnosticsOptions(o),this.setModeConfiguration(a)}get onDidChange(){return this._onDidChange.event}get languageId(){return this._languageId}get modeConfiguration(){return this._modeConfiguration}get diagnosticsOptions(){return this._diagnosticsOptions}setDiagnosticsOptions(n){this._diagnosticsOptions=n||Object.create(null),this._onDidChange.fire(this)}setModeConfiguration(n){this._modeConfiguration=n||Object.create(null),this._onDidChange.fire(this)}},D={validate:!0,allowComments:!0,schemas:[],enableSchemaRequest:!1,schemaRequest:"warning",schemaValidation:"warning",comments:"error",trailingCommas:"error"},C={documentFormattingEdits:!0,documentRangeFormattingEdits:!0,completionItems:!0,hovers:!0,documentSymbols:!0,tokens:!0,colors:!0,foldingRanges:!0,diagnostics:!0,selectionRanges:!0},m=new l("json",D,C),p=()=>y().then(e=>e.getWorker());t.languages.json={jsonDefaults:m,getWorker:p};function y(){return new Promise((e,n)=>{d(["vs/language/json/jsonMode"],e,n)})}t.languages.register({id:"json",extensions:[".json",".bowerrc",".jshintrc",".jscsrc",".eslintrc",".babelrc",".har"],aliases:["JSON","json"],mimetypes:["application/json"]});t.languages.onLanguage("json",()=>{y().then(e=>e.setupMode(m))});return A(M);})(); return moduleExports; }); /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/language/typescript/monaco.contribution", ["require","require","vs/editor/editor.api"],(require)=>{ "use strict";var moduleExports=(()=>{var N=Object.create;var m=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var c=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var w=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports),A=(n,e)=>{for(var t in e)m(n,t,{get:e[t],enumerable:!0})},g=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of M(e))!F.call(n,r)&&r!==t&&m(n,r,{get:()=>e[r],enumerable:!(i=H(e,r))||i.enumerable});return n},v=(n,e,t)=>(g(n,e,"default"),t&&g(t,e,"default")),C=(n,e,t)=>(t=n!=null?N(R(n)):{},g(e||!n||!n.__esModule?m(t,"default",{value:n,enumerable:!0}):t,n)),W=n=>g(m({},"__esModule",{value:!0}),n);var _=w((B,L)=>{var V=C(c("vs/editor/editor.api"));L.exports=V});var T={};A(T,{JsxEmit:()=>f,ModuleKind:()=>b,ModuleResolutionKind:()=>O,NewLineKind:()=>y,ScriptTarget:()=>h,getJavaScriptWorker:()=>k,getTypeScriptWorker:()=>P,javascriptDefaults:()=>D,typescriptDefaults:()=>x,typescriptVersion:()=>I});var E="5.4.5";var l={};v(l,C(_()));var b=(s=>(s[s.None=0]="None",s[s.CommonJS=1]="CommonJS",s[s.AMD=2]="AMD",s[s.UMD=3]="UMD",s[s.System=4]="System",s[s.ES2015=5]="ES2015",s[s.ESNext=99]="ESNext",s))(b||{}),f=(a=>(a[a.None=0]="None",a[a.Preserve=1]="Preserve",a[a.React=2]="React",a[a.ReactNative=3]="ReactNative",a[a.ReactJSX=4]="ReactJSX",a[a.ReactJSXDev=5]="ReactJSXDev",a))(f||{}),y=(t=>(t[t.CarriageReturnLineFeed=0]="CarriageReturnLineFeed",t[t.LineFeed=1]="LineFeed",t))(y||{}),h=(o=>(o[o.ES3=0]="ES3",o[o.ES5=1]="ES5",o[o.ES2015=2]="ES2015",o[o.ES2016=3]="ES2016",o[o.ES2017=4]="ES2017",o[o.ES2018=5]="ES2018",o[o.ES2019=6]="ES2019",o[o.ES2020=7]="ES2020",o[o.ESNext=99]="ESNext",o[o.JSON=100]="JSON",o[o.Latest=99]="Latest",o))(h||{}),O=(t=>(t[t.Classic=1]="Classic",t[t.NodeJs=2]="NodeJs",t))(O||{}),d=class{constructor(e,t,i,r,p){this._onDidChange=new l.Emitter;this._onDidExtraLibsChange=new l.Emitter;this._extraLibs=Object.create(null),this._removedExtraLibs=Object.create(null),this._eagerModelSync=!1,this.setCompilerOptions(e),this.setDiagnosticsOptions(t),this.setWorkerOptions(i),this.setInlayHintsOptions(r),this.setModeConfiguration(p),this._onDidExtraLibsChangeTimeout=-1}get onDidChange(){return this._onDidChange.event}get onDidExtraLibsChange(){return this._onDidExtraLibsChange.event}get modeConfiguration(){return this._modeConfiguration}get workerOptions(){return this._workerOptions}get inlayHintsOptions(){return this._inlayHintsOptions}getExtraLibs(){return this._extraLibs}addExtraLib(e,t){let i;if(typeof t>"u"?i=`ts:extralib-${Math.random().toString(36).substring(2,15)}`:i=t,this._extraLibs[i]&&this._extraLibs[i].content===e)return{dispose:()=>{}};let r=1;return this._removedExtraLibs[i]&&(r=this._removedExtraLibs[i]+1),this._extraLibs[i]&&(r=this._extraLibs[i].version+1),this._extraLibs[i]={content:e,version:r},this._fireOnDidExtraLibsChangeSoon(),{dispose:()=>{let p=this._extraLibs[i];p&&p.version===r&&(delete this._extraLibs[i],this._removedExtraLibs[i]=r,this._fireOnDidExtraLibsChangeSoon())}}}setExtraLibs(e){for(let t in this._extraLibs)this._removedExtraLibs[t]=this._extraLibs[t].version;if(this._extraLibs=Object.create(null),e&&e.length>0)for(let t of e){let i=t.filePath||`ts:extralib-${Math.random().toString(36).substring(2,15)}`,r=t.content,p=1;this._removedExtraLibs[i]&&(p=this._removedExtraLibs[i]+1),this._extraLibs[i]={content:r,version:p}}this._fireOnDidExtraLibsChangeSoon()}_fireOnDidExtraLibsChangeSoon(){this._onDidExtraLibsChangeTimeout===-1&&(this._onDidExtraLibsChangeTimeout=window.setTimeout(()=>{this._onDidExtraLibsChangeTimeout=-1,this._onDidExtraLibsChange.fire(void 0)},0))}getCompilerOptions(){return this._compilerOptions}setCompilerOptions(e){this._compilerOptions=e||Object.create(null),this._onDidChange.fire(void 0)}getDiagnosticsOptions(){return this._diagnosticsOptions}setDiagnosticsOptions(e){this._diagnosticsOptions=e||Object.create(null),this._onDidChange.fire(void 0)}setWorkerOptions(e){this._workerOptions=e||Object.create(null),this._onDidChange.fire(void 0)}setInlayHintsOptions(e){this._inlayHintsOptions=e||Object.create(null),this._onDidChange.fire(void 0)}setMaximumWorkerIdleTime(e){}setEagerModelSync(e){this._eagerModelSync=e}getEagerModelSync(){return this._eagerModelSync}setModeConfiguration(e){this._modeConfiguration=e||Object.create(null),this._onDidChange.fire(void 0)}},I=E,S={completionItems:!0,hovers:!0,documentSymbols:!0,definitions:!0,references:!0,documentHighlights:!0,rename:!0,diagnostics:!0,documentRangeFormattingEdits:!0,signatureHelp:!0,onTypeFormattingEdits:!0,codeActions:!0,inlayHints:!0},x=new d({allowNonTsExtensions:!0,target:99},{noSemanticValidation:!1,noSyntaxValidation:!1,onlyVisible:!1},{},{},S),D=new d({allowNonTsExtensions:!0,allowJs:!0,target:99},{noSemanticValidation:!0,noSyntaxValidation:!1,onlyVisible:!1},{},{},S),P=()=>u().then(n=>n.getTypeScriptWorker()),k=()=>u().then(n=>n.getJavaScriptWorker());l.languages.typescript={ModuleKind:b,JsxEmit:f,NewLineKind:y,ScriptTarget:h,ModuleResolutionKind:O,typescriptVersion:I,typescriptDefaults:x,javascriptDefaults:D,getTypeScriptWorker:P,getJavaScriptWorker:k};function u(){return new Promise((n,e)=>{c(["vs/language/typescript/tsMode"],n,e)})}l.languages.onLanguage("typescript",()=>u().then(n=>n.setupTypeScript(x)));l.languages.onLanguage("javascript",()=>u().then(n=>n.setupJavaScript(D)));return W(T);})(); return moduleExports; }); define("vs/editor/editor.main", ["vs/editor/edcore.main","vs/basic-languages/monaco.contribution","vs/language/css/monaco.contribution","vs/language/html/monaco.contribution","vs/language/json/monaco.contribution","vs/language/typescript/monaco.contribution"], function(api) { return api; }); //# sourceMappingURL=../../../min-maps/vs/editor/editor.main.js.map ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/language/css/cssMode.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/language/css/cssMode", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var Tt=Object.create;var X=Object.defineProperty;var _t=Object.getOwnPropertyDescriptor;var Ct=Object.getOwnPropertyNames;var bt=Object.getPrototypeOf,wt=Object.prototype.hasOwnProperty;var Et=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(n,i)=>(typeof require<"u"?require:n)[i]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var Rt=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports),Pt=(e,n)=>{for(var i in n)X(e,i,{get:n[i],enumerable:!0})},z=(e,n,i,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of Ct(n))!wt.call(e,t)&&t!==i&&X(e,t,{get:()=>n[t],enumerable:!(r=_t(n,t))||r.enumerable});return e},he=(e,n,i)=>(z(e,n,"default"),i&&z(i,n,"default")),me=(e,n,i)=>(i=e!=null?Tt(bt(e)):{},z(n||!e||!e.__esModule?X(i,"default",{value:e,enumerable:!0}):i,e)),Lt=e=>z(X({},"__esModule",{value:!0}),e);var ye=Rt((Qt,xe)=>{var Wt=me(Et("vs/editor/editor.api"));xe.exports=Wt});var Bt={};Pt(Bt,{CompletionAdapter:()=>D,DefinitionAdapter:()=>A,DiagnosticsAdapter:()=>W,DocumentColorAdapter:()=>N,DocumentFormattingEditProvider:()=>U,DocumentHighlightAdapter:()=>F,DocumentLinkAdapter:()=>fe,DocumentRangeFormattingEditProvider:()=>H,DocumentSymbolAdapter:()=>j,FoldingRangeAdapter:()=>O,HoverAdapter:()=>S,ReferenceAdapter:()=>M,RenameAdapter:()=>K,SelectionRangeAdapter:()=>V,WorkerManager:()=>_,fromPosition:()=>k,fromRange:()=>pe,setupMode:()=>$t,toRange:()=>y,toTextEdit:()=>P});var d={};he(d,me(ye()));var Dt=2*60*1e3,_=class{constructor(n){this._defaults=n,this._worker=null,this._client=null,this._idleCheckInterval=window.setInterval(()=>this._checkIfIdle(),30*1e3),this._lastUsedTime=0,this._configChangeListener=this._defaults.onDidChange(()=>this._stopWorker())}_stopWorker(){this._worker&&(this._worker.dispose(),this._worker=null),this._client=null}dispose(){clearInterval(this._idleCheckInterval),this._configChangeListener.dispose(),this._stopWorker()}_checkIfIdle(){if(!this._worker)return;Date.now()-this._lastUsedTime>Dt&&this._stopWorker()}_getClient(){return this._lastUsedTime=Date.now(),this._client||(this._worker=d.editor.createWebWorker({moduleId:"vs/language/css/cssWorker",label:this._defaults.languageId,createData:{options:this._defaults.options,languageId:this._defaults.languageId}}),this._client=this._worker.getProxy()),this._client}getLanguageServiceWorker(...n){let i;return this._getClient().then(r=>{i=r}).then(r=>{if(this._worker)return this._worker.withSyncedResources(n)}).then(r=>i)}};var ve;(function(e){function n(i){return typeof i=="string"}e.is=n})(ve||(ve={}));var Z;(function(e){function n(i){return typeof i=="string"}e.is=n})(Z||(Z={}));var Ie;(function(e){e.MIN_VALUE=-2147483648,e.MAX_VALUE=2147483647;function n(i){return typeof i=="number"&&e.MIN_VALUE<=i&&i<=e.MAX_VALUE}e.is=n})(Ie||(Ie={}));var $;(function(e){e.MIN_VALUE=0,e.MAX_VALUE=2147483647;function n(i){return typeof i=="number"&&e.MIN_VALUE<=i&&i<=e.MAX_VALUE}e.is=n})($||($={}));var I;(function(e){function n(r,t){return r===Number.MAX_VALUE&&(r=$.MAX_VALUE),t===Number.MAX_VALUE&&(t=$.MAX_VALUE),{line:r,character:t}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&a.uinteger(t.line)&&a.uinteger(t.character)}e.is=i})(I||(I={}));var h;(function(e){function n(r,t,o,s){if(a.uinteger(r)&&a.uinteger(t)&&a.uinteger(o)&&a.uinteger(s))return{start:I.create(r,t),end:I.create(o,s)};if(I.is(r)&&I.is(t))return{start:r,end:t};throw new Error(`Range#create called with invalid arguments[${r}, ${t}, ${o}, ${s}]`)}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&I.is(t.start)&&I.is(t.end)}e.is=i})(h||(h={}));var B;(function(e){function n(r,t){return{uri:r,range:t}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&h.is(t.range)&&(a.string(t.uri)||a.undefined(t.uri))}e.is=i})(B||(B={}));var ke;(function(e){function n(r,t,o,s){return{targetUri:r,targetRange:t,targetSelectionRange:o,originSelectionRange:s}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&h.is(t.targetRange)&&a.string(t.targetUri)&&h.is(t.targetSelectionRange)&&(h.is(t.originSelectionRange)||a.undefined(t.originSelectionRange))}e.is=i})(ke||(ke={}));var ee;(function(e){function n(r,t,o,s){return{red:r,green:t,blue:o,alpha:s}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&a.numberRange(t.red,0,1)&&a.numberRange(t.green,0,1)&&a.numberRange(t.blue,0,1)&&a.numberRange(t.alpha,0,1)}e.is=i})(ee||(ee={}));var Te;(function(e){function n(r,t){return{range:r,color:t}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&h.is(t.range)&&ee.is(t.color)}e.is=i})(Te||(Te={}));var _e;(function(e){function n(r,t,o){return{label:r,textEdit:t,additionalTextEdits:o}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&a.string(t.label)&&(a.undefined(t.textEdit)||w.is(t))&&(a.undefined(t.additionalTextEdits)||a.typedArray(t.additionalTextEdits,w.is))}e.is=i})(_e||(_e={}));var C;(function(e){e.Comment="comment",e.Imports="imports",e.Region="region"})(C||(C={}));var Ce;(function(e){function n(r,t,o,s,u,g){let f={startLine:r,endLine:t};return a.defined(o)&&(f.startCharacter=o),a.defined(s)&&(f.endCharacter=s),a.defined(u)&&(f.kind=u),a.defined(g)&&(f.collapsedText=g),f}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&a.uinteger(t.startLine)&&a.uinteger(t.startLine)&&(a.undefined(t.startCharacter)||a.uinteger(t.startCharacter))&&(a.undefined(t.endCharacter)||a.uinteger(t.endCharacter))&&(a.undefined(t.kind)||a.string(t.kind))}e.is=i})(Ce||(Ce={}));var te;(function(e){function n(r,t){return{location:r,message:t}}e.create=n;function i(r){let t=r;return a.defined(t)&&B.is(t.location)&&a.string(t.message)}e.is=i})(te||(te={}));var T;(function(e){e.Error=1,e.Warning=2,e.Information=3,e.Hint=4})(T||(T={}));var be;(function(e){e.Unnecessary=1,e.Deprecated=2})(be||(be={}));var we;(function(e){function n(i){let r=i;return a.objectLiteral(r)&&a.string(r.href)}e.is=n})(we||(we={}));var q;(function(e){function n(r,t,o,s,u,g){let f={range:r,message:t};return a.defined(o)&&(f.severity=o),a.defined(s)&&(f.code=s),a.defined(u)&&(f.source=u),a.defined(g)&&(f.relatedInformation=g),f}e.create=n;function i(r){var t;let o=r;return a.defined(o)&&h.is(o.range)&&a.string(o.message)&&(a.number(o.severity)||a.undefined(o.severity))&&(a.integer(o.code)||a.string(o.code)||a.undefined(o.code))&&(a.undefined(o.codeDescription)||a.string((t=o.codeDescription)===null||t===void 0?void 0:t.href))&&(a.string(o.source)||a.undefined(o.source))&&(a.undefined(o.relatedInformation)||a.typedArray(o.relatedInformation,te.is))}e.is=i})(q||(q={}));var b;(function(e){function n(r,t,...o){let s={title:r,command:t};return a.defined(o)&&o.length>0&&(s.arguments=o),s}e.create=n;function i(r){let t=r;return a.defined(t)&&a.string(t.title)&&a.string(t.command)}e.is=i})(b||(b={}));var w;(function(e){function n(o,s){return{range:o,newText:s}}e.replace=n;function i(o,s){return{range:{start:o,end:o},newText:s}}e.insert=i;function r(o){return{range:o,newText:""}}e.del=r;function t(o){let s=o;return a.objectLiteral(s)&&a.string(s.newText)&&h.is(s.range)}e.is=t})(w||(w={}));var ne;(function(e){function n(r,t,o){let s={label:r};return t!==void 0&&(s.needsConfirmation=t),o!==void 0&&(s.description=o),s}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&a.string(t.label)&&(a.boolean(t.needsConfirmation)||t.needsConfirmation===void 0)&&(a.string(t.description)||t.description===void 0)}e.is=i})(ne||(ne={}));var E;(function(e){function n(i){let r=i;return a.string(r)}e.is=n})(E||(E={}));var Ee;(function(e){function n(o,s,u){return{range:o,newText:s,annotationId:u}}e.replace=n;function i(o,s,u){return{range:{start:o,end:o},newText:s,annotationId:u}}e.insert=i;function r(o,s){return{range:o,newText:"",annotationId:s}}e.del=r;function t(o){let s=o;return w.is(s)&&(ne.is(s.annotationId)||E.is(s.annotationId))}e.is=t})(Ee||(Ee={}));var re;(function(e){function n(r,t){return{textDocument:r,edits:t}}e.create=n;function i(r){let t=r;return a.defined(t)&&ue.is(t.textDocument)&&Array.isArray(t.edits)}e.is=i})(re||(re={}));var ie;(function(e){function n(r,t,o){let s={kind:"create",uri:r};return t!==void 0&&(t.overwrite!==void 0||t.ignoreIfExists!==void 0)&&(s.options=t),o!==void 0&&(s.annotationId=o),s}e.create=n;function i(r){let t=r;return t&&t.kind==="create"&&a.string(t.uri)&&(t.options===void 0||(t.options.overwrite===void 0||a.boolean(t.options.overwrite))&&(t.options.ignoreIfExists===void 0||a.boolean(t.options.ignoreIfExists)))&&(t.annotationId===void 0||E.is(t.annotationId))}e.is=i})(ie||(ie={}));var oe;(function(e){function n(r,t,o,s){let u={kind:"rename",oldUri:r,newUri:t};return o!==void 0&&(o.overwrite!==void 0||o.ignoreIfExists!==void 0)&&(u.options=o),s!==void 0&&(u.annotationId=s),u}e.create=n;function i(r){let t=r;return t&&t.kind==="rename"&&a.string(t.oldUri)&&a.string(t.newUri)&&(t.options===void 0||(t.options.overwrite===void 0||a.boolean(t.options.overwrite))&&(t.options.ignoreIfExists===void 0||a.boolean(t.options.ignoreIfExists)))&&(t.annotationId===void 0||E.is(t.annotationId))}e.is=i})(oe||(oe={}));var se;(function(e){function n(r,t,o){let s={kind:"delete",uri:r};return t!==void 0&&(t.recursive!==void 0||t.ignoreIfNotExists!==void 0)&&(s.options=t),o!==void 0&&(s.annotationId=o),s}e.create=n;function i(r){let t=r;return t&&t.kind==="delete"&&a.string(t.uri)&&(t.options===void 0||(t.options.recursive===void 0||a.boolean(t.options.recursive))&&(t.options.ignoreIfNotExists===void 0||a.boolean(t.options.ignoreIfNotExists)))&&(t.annotationId===void 0||E.is(t.annotationId))}e.is=i})(se||(se={}));var ae;(function(e){function n(i){let r=i;return r&&(r.changes!==void 0||r.documentChanges!==void 0)&&(r.documentChanges===void 0||r.documentChanges.every(t=>a.string(t.kind)?ie.is(t)||oe.is(t)||se.is(t):re.is(t)))}e.is=n})(ae||(ae={}));var Re;(function(e){function n(r){return{uri:r}}e.create=n;function i(r){let t=r;return a.defined(t)&&a.string(t.uri)}e.is=i})(Re||(Re={}));var Pe;(function(e){function n(r,t){return{uri:r,version:t}}e.create=n;function i(r){let t=r;return a.defined(t)&&a.string(t.uri)&&a.integer(t.version)}e.is=i})(Pe||(Pe={}));var ue;(function(e){function n(r,t){return{uri:r,version:t}}e.create=n;function i(r){let t=r;return a.defined(t)&&a.string(t.uri)&&(t.version===null||a.integer(t.version))}e.is=i})(ue||(ue={}));var Le;(function(e){function n(r,t,o,s){return{uri:r,languageId:t,version:o,text:s}}e.create=n;function i(r){let t=r;return a.defined(t)&&a.string(t.uri)&&a.string(t.languageId)&&a.integer(t.version)&&a.string(t.text)}e.is=i})(Le||(Le={}));var de;(function(e){e.PlainText="plaintext",e.Markdown="markdown";function n(i){let r=i;return r===e.PlainText||r===e.Markdown}e.is=n})(de||(de={}));var L;(function(e){function n(i){let r=i;return a.objectLiteral(i)&&de.is(r.kind)&&a.string(r.value)}e.is=n})(L||(L={}));var m;(function(e){e.Text=1,e.Method=2,e.Function=3,e.Constructor=4,e.Field=5,e.Variable=6,e.Class=7,e.Interface=8,e.Module=9,e.Property=10,e.Unit=11,e.Value=12,e.Enum=13,e.Keyword=14,e.Snippet=15,e.Color=16,e.File=17,e.Reference=18,e.Folder=19,e.EnumMember=20,e.Constant=21,e.Struct=22,e.Event=23,e.Operator=24,e.TypeParameter=25})(m||(m={}));var Q;(function(e){e.PlainText=1,e.Snippet=2})(Q||(Q={}));var We;(function(e){e.Deprecated=1})(We||(We={}));var De;(function(e){function n(r,t,o){return{newText:r,insert:t,replace:o}}e.create=n;function i(r){let t=r;return t&&a.string(t.newText)&&h.is(t.insert)&&h.is(t.replace)}e.is=i})(De||(De={}));var Se;(function(e){e.asIs=1,e.adjustIndentation=2})(Se||(Se={}));var Fe;(function(e){function n(i){let r=i;return r&&(a.string(r.detail)||r.detail===void 0)&&(a.string(r.description)||r.description===void 0)}e.is=n})(Fe||(Fe={}));var Ae;(function(e){function n(i){return{label:i}}e.create=n})(Ae||(Ae={}));var Me;(function(e){function n(i,r){return{items:i||[],isIncomplete:!!r}}e.create=n})(Me||(Me={}));var G;(function(e){function n(r){return r.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&")}e.fromPlainText=n;function i(r){let t=r;return a.string(t)||a.objectLiteral(t)&&a.string(t.language)&&a.string(t.value)}e.is=i})(G||(G={}));var Ke;(function(e){function n(i){let r=i;return!!r&&a.objectLiteral(r)&&(L.is(r.contents)||G.is(r.contents)||a.typedArray(r.contents,G.is))&&(i.range===void 0||h.is(i.range))}e.is=n})(Ke||(Ke={}));var je;(function(e){function n(i,r){return r?{label:i,documentation:r}:{label:i}}e.create=n})(je||(je={}));var Ue;(function(e){function n(i,r,...t){let o={label:i};return a.defined(r)&&(o.documentation=r),a.defined(t)?o.parameters=t:o.parameters=[],o}e.create=n})(Ue||(Ue={}));var R;(function(e){e.Text=1,e.Read=2,e.Write=3})(R||(R={}));var He;(function(e){function n(i,r){let t={range:i};return a.number(r)&&(t.kind=r),t}e.create=n})(He||(He={}));var x;(function(e){e.File=1,e.Module=2,e.Namespace=3,e.Package=4,e.Class=5,e.Method=6,e.Property=7,e.Field=8,e.Constructor=9,e.Enum=10,e.Interface=11,e.Function=12,e.Variable=13,e.Constant=14,e.String=15,e.Number=16,e.Boolean=17,e.Array=18,e.Object=19,e.Key=20,e.Null=21,e.EnumMember=22,e.Struct=23,e.Event=24,e.Operator=25,e.TypeParameter=26})(x||(x={}));var Ne;(function(e){e.Deprecated=1})(Ne||(Ne={}));var Oe;(function(e){function n(i,r,t,o,s){let u={name:i,kind:r,location:{uri:o,range:t}};return s&&(u.containerName=s),u}e.create=n})(Oe||(Oe={}));var Ve;(function(e){function n(i,r,t,o){return o!==void 0?{name:i,kind:r,location:{uri:t,range:o}}:{name:i,kind:r,location:{uri:t}}}e.create=n})(Ve||(Ve={}));var ze;(function(e){function n(r,t,o,s,u,g){let f={name:r,detail:t,kind:o,range:s,selectionRange:u};return g!==void 0&&(f.children=g),f}e.create=n;function i(r){let t=r;return t&&a.string(t.name)&&a.number(t.kind)&&h.is(t.range)&&h.is(t.selectionRange)&&(t.detail===void 0||a.string(t.detail))&&(t.deprecated===void 0||a.boolean(t.deprecated))&&(t.children===void 0||Array.isArray(t.children))&&(t.tags===void 0||Array.isArray(t.tags))}e.is=i})(ze||(ze={}));var Xe;(function(e){e.Empty="",e.QuickFix="quickfix",e.Refactor="refactor",e.RefactorExtract="refactor.extract",e.RefactorInline="refactor.inline",e.RefactorRewrite="refactor.rewrite",e.Source="source",e.SourceOrganizeImports="source.organizeImports",e.SourceFixAll="source.fixAll"})(Xe||(Xe={}));var J;(function(e){e.Invoked=1,e.Automatic=2})(J||(J={}));var $e;(function(e){function n(r,t,o){let s={diagnostics:r};return t!=null&&(s.only=t),o!=null&&(s.triggerKind=o),s}e.create=n;function i(r){let t=r;return a.defined(t)&&a.typedArray(t.diagnostics,q.is)&&(t.only===void 0||a.typedArray(t.only,a.string))&&(t.triggerKind===void 0||t.triggerKind===J.Invoked||t.triggerKind===J.Automatic)}e.is=i})($e||($e={}));var Be;(function(e){function n(r,t,o){let s={title:r},u=!0;return typeof t=="string"?(u=!1,s.kind=t):b.is(t)?s.command=t:s.edit=t,u&&o!==void 0&&(s.kind=o),s}e.create=n;function i(r){let t=r;return t&&a.string(t.title)&&(t.diagnostics===void 0||a.typedArray(t.diagnostics,q.is))&&(t.kind===void 0||a.string(t.kind))&&(t.edit!==void 0||t.command!==void 0)&&(t.command===void 0||b.is(t.command))&&(t.isPreferred===void 0||a.boolean(t.isPreferred))&&(t.edit===void 0||ae.is(t.edit))}e.is=i})(Be||(Be={}));var qe;(function(e){function n(r,t){let o={range:r};return a.defined(t)&&(o.data=t),o}e.create=n;function i(r){let t=r;return a.defined(t)&&h.is(t.range)&&(a.undefined(t.command)||b.is(t.command))}e.is=i})(qe||(qe={}));var Qe;(function(e){function n(r,t){return{tabSize:r,insertSpaces:t}}e.create=n;function i(r){let t=r;return a.defined(t)&&a.uinteger(t.tabSize)&&a.boolean(t.insertSpaces)}e.is=i})(Qe||(Qe={}));var Ge;(function(e){function n(r,t,o){return{range:r,target:t,data:o}}e.create=n;function i(r){let t=r;return a.defined(t)&&h.is(t.range)&&(a.undefined(t.target)||a.string(t.target))}e.is=i})(Ge||(Ge={}));var Je;(function(e){function n(r,t){return{range:r,parent:t}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&h.is(t.range)&&(t.parent===void 0||e.is(t.parent))}e.is=i})(Je||(Je={}));var Ye;(function(e){e.namespace="namespace",e.type="type",e.class="class",e.enum="enum",e.interface="interface",e.struct="struct",e.typeParameter="typeParameter",e.parameter="parameter",e.variable="variable",e.property="property",e.enumMember="enumMember",e.event="event",e.function="function",e.method="method",e.macro="macro",e.keyword="keyword",e.modifier="modifier",e.comment="comment",e.string="string",e.number="number",e.regexp="regexp",e.operator="operator",e.decorator="decorator"})(Ye||(Ye={}));var Ze;(function(e){e.declaration="declaration",e.definition="definition",e.readonly="readonly",e.static="static",e.deprecated="deprecated",e.abstract="abstract",e.async="async",e.modification="modification",e.documentation="documentation",e.defaultLibrary="defaultLibrary"})(Ze||(Ze={}));var et;(function(e){function n(i){let r=i;return a.objectLiteral(r)&&(r.resultId===void 0||typeof r.resultId=="string")&&Array.isArray(r.data)&&(r.data.length===0||typeof r.data[0]=="number")}e.is=n})(et||(et={}));var tt;(function(e){function n(r,t){return{range:r,text:t}}e.create=n;function i(r){let t=r;return t!=null&&h.is(t.range)&&a.string(t.text)}e.is=i})(tt||(tt={}));var nt;(function(e){function n(r,t,o){return{range:r,variableName:t,caseSensitiveLookup:o}}e.create=n;function i(r){let t=r;return t!=null&&h.is(t.range)&&a.boolean(t.caseSensitiveLookup)&&(a.string(t.variableName)||t.variableName===void 0)}e.is=i})(nt||(nt={}));var rt;(function(e){function n(r,t){return{range:r,expression:t}}e.create=n;function i(r){let t=r;return t!=null&&h.is(t.range)&&(a.string(t.expression)||t.expression===void 0)}e.is=i})(rt||(rt={}));var it;(function(e){function n(r,t){return{frameId:r,stoppedLocation:t}}e.create=n;function i(r){let t=r;return a.defined(t)&&h.is(r.stoppedLocation)}e.is=i})(it||(it={}));var ce;(function(e){e.Type=1,e.Parameter=2;function n(i){return i===1||i===2}e.is=n})(ce||(ce={}));var le;(function(e){function n(r){return{value:r}}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&(t.tooltip===void 0||a.string(t.tooltip)||L.is(t.tooltip))&&(t.location===void 0||B.is(t.location))&&(t.command===void 0||b.is(t.command))}e.is=i})(le||(le={}));var ot;(function(e){function n(r,t,o){let s={position:r,label:t};return o!==void 0&&(s.kind=o),s}e.create=n;function i(r){let t=r;return a.objectLiteral(t)&&I.is(t.position)&&(a.string(t.label)||a.typedArray(t.label,le.is))&&(t.kind===void 0||ce.is(t.kind))&&t.textEdits===void 0||a.typedArray(t.textEdits,w.is)&&(t.tooltip===void 0||a.string(t.tooltip)||L.is(t.tooltip))&&(t.paddingLeft===void 0||a.boolean(t.paddingLeft))&&(t.paddingRight===void 0||a.boolean(t.paddingRight))}e.is=i})(ot||(ot={}));var st;(function(e){function n(i){return{kind:"snippet",value:i}}e.createSnippet=n})(st||(st={}));var at;(function(e){function n(i,r,t,o){return{insertText:i,filterText:r,range:t,command:o}}e.create=n})(at||(at={}));var ut;(function(e){function n(i){return{items:i}}e.create=n})(ut||(ut={}));var dt;(function(e){e.Invoked=0,e.Automatic=1})(dt||(dt={}));var ct;(function(e){function n(i,r){return{range:i,text:r}}e.create=n})(ct||(ct={}));var lt;(function(e){function n(i,r){return{triggerKind:i,selectedCompletionInfo:r}}e.create=n})(lt||(lt={}));var gt;(function(e){function n(i){let r=i;return a.objectLiteral(r)&&Z.is(r.uri)&&a.string(r.name)}e.is=n})(gt||(gt={}));var ft;(function(e){function n(o,s,u,g){return new ge(o,s,u,g)}e.create=n;function i(o){let s=o;return!!(a.defined(s)&&a.string(s.uri)&&(a.undefined(s.languageId)||a.string(s.languageId))&&a.uinteger(s.lineCount)&&a.func(s.getText)&&a.func(s.positionAt)&&a.func(s.offsetAt))}e.is=i;function r(o,s){let u=o.getText(),g=t(s,(l,p)=>{let v=l.range.start.line-p.range.start.line;return v===0?l.range.start.character-p.range.start.character:v}),f=u.length;for(let l=g.length-1;l>=0;l--){let p=g[l],v=o.offsetAt(p.range.start),c=o.offsetAt(p.range.end);if(c<=f)u=u.substring(0,v)+p.newText+u.substring(c,u.length);else throw new Error("Overlapping edit");f=v}return u}e.applyEdits=r;function t(o,s){if(o.length<=1)return o;let u=o.length/2|0,g=o.slice(0,u),f=o.slice(u);t(g,s),t(f,s);let l=0,p=0,v=0;for(;l0&&n.push(i.length),this._lineOffsets=n}return this._lineOffsets}positionAt(n){n=Math.max(Math.min(n,this._content.length),0);let i=this.getLineOffsets(),r=0,t=i.length;if(t===0)return I.create(0,n);for(;rn?t=s:r=s+1}let o=r-1;return I.create(o,n-i[o])}offsetAt(n){let i=this.getLineOffsets();if(n.line>=i.length)return this._content.length;if(n.line<0)return 0;let r=i[n.line],t=n.line+1"u"}e.undefined=r;function t(c){return c===!0||c===!1}e.boolean=t;function o(c){return n.call(c)==="[object String]"}e.string=o;function s(c){return n.call(c)==="[object Number]"}e.number=s;function u(c,Y,kt){return n.call(c)==="[object Number]"&&Y<=c&&c<=kt}e.numberRange=u;function g(c){return n.call(c)==="[object Number]"&&-2147483648<=c&&c<=2147483647}e.integer=g;function f(c){return n.call(c)==="[object Number]"&&0<=c&&c<=2147483647}e.uinteger=f;function l(c){return n.call(c)==="[object Function]"}e.func=l;function p(c){return c!==null&&typeof c=="object"}e.objectLiteral=p;function v(c,Y){return Array.isArray(c)&&c.every(Y)}e.typedArray=v})(a||(a={}));var W=class{constructor(n,i,r){this._languageId=n;this._worker=i;this._disposables=[];this._listener=Object.create(null);let t=s=>{let u=s.getLanguageId();if(u!==this._languageId)return;let g;this._listener[s.uri.toString()]=s.onDidChangeContent(()=>{window.clearTimeout(g),g=window.setTimeout(()=>this._doValidate(s.uri,u),500)}),this._doValidate(s.uri,u)},o=s=>{d.editor.setModelMarkers(s,this._languageId,[]);let u=s.uri.toString(),g=this._listener[u];g&&(g.dispose(),delete this._listener[u])};this._disposables.push(d.editor.onDidCreateModel(t)),this._disposables.push(d.editor.onWillDisposeModel(o)),this._disposables.push(d.editor.onDidChangeModelLanguage(s=>{o(s.model),t(s.model)})),this._disposables.push(r(s=>{d.editor.getModels().forEach(u=>{u.getLanguageId()===this._languageId&&(o(u),t(u))})})),this._disposables.push({dispose:()=>{d.editor.getModels().forEach(o);for(let s in this._listener)this._listener[s].dispose()}}),d.editor.getModels().forEach(t)}dispose(){this._disposables.forEach(n=>n&&n.dispose()),this._disposables.length=0}_doValidate(n,i){this._worker(n).then(r=>r.doValidation(n.toString())).then(r=>{let t=r.map(s=>At(n,s)),o=d.editor.getModel(n);o&&o.getLanguageId()===i&&d.editor.setModelMarkers(o,i,t)}).then(void 0,r=>{console.error(r)})}};function Ft(e){switch(e){case T.Error:return d.MarkerSeverity.Error;case T.Warning:return d.MarkerSeverity.Warning;case T.Information:return d.MarkerSeverity.Info;case T.Hint:return d.MarkerSeverity.Hint;default:return d.MarkerSeverity.Info}}function At(e,n){let i=typeof n.code=="number"?String(n.code):n.code;return{severity:Ft(n.severity),startLineNumber:n.range.start.line+1,startColumn:n.range.start.character+1,endLineNumber:n.range.end.line+1,endColumn:n.range.end.character+1,message:n.message,code:i,source:n.source}}var D=class{constructor(n,i){this._worker=n;this._triggerCharacters=i}get triggerCharacters(){return this._triggerCharacters}provideCompletionItems(n,i,r,t){let o=n.uri;return this._worker(o).then(s=>s.doComplete(o.toString(),k(i))).then(s=>{if(!s)return;let u=n.getWordUntilPosition(i),g=new d.Range(i.lineNumber,u.startColumn,i.lineNumber,u.endColumn),f=s.items.map(l=>{let p={label:l.label,insertText:l.insertText||l.label,sortText:l.sortText,filterText:l.filterText,documentation:l.documentation,detail:l.detail,command:jt(l.command),range:g,kind:Kt(l.kind)};return l.textEdit&&(Mt(l.textEdit)?p.range={insert:y(l.textEdit.insert),replace:y(l.textEdit.replace)}:p.range=y(l.textEdit.range),p.insertText=l.textEdit.newText),l.additionalTextEdits&&(p.additionalTextEdits=l.additionalTextEdits.map(P)),l.insertTextFormat===Q.Snippet&&(p.insertTextRules=d.languages.CompletionItemInsertTextRule.InsertAsSnippet),p});return{isIncomplete:s.isIncomplete,suggestions:f}})}};function k(e){if(e)return{character:e.column-1,line:e.lineNumber-1}}function pe(e){if(e)return{start:{line:e.startLineNumber-1,character:e.startColumn-1},end:{line:e.endLineNumber-1,character:e.endColumn-1}}}function y(e){if(e)return new d.Range(e.start.line+1,e.start.character+1,e.end.line+1,e.end.character+1)}function Mt(e){return typeof e.insert<"u"&&typeof e.replace<"u"}function Kt(e){let n=d.languages.CompletionItemKind;switch(e){case m.Text:return n.Text;case m.Method:return n.Method;case m.Function:return n.Function;case m.Constructor:return n.Constructor;case m.Field:return n.Field;case m.Variable:return n.Variable;case m.Class:return n.Class;case m.Interface:return n.Interface;case m.Module:return n.Module;case m.Property:return n.Property;case m.Unit:return n.Unit;case m.Value:return n.Value;case m.Enum:return n.Enum;case m.Keyword:return n.Keyword;case m.Snippet:return n.Snippet;case m.Color:return n.Color;case m.File:return n.File;case m.Reference:return n.Reference}return n.Property}function P(e){if(e)return{range:y(e.range),text:e.newText}}function jt(e){return e&&e.command==="editor.action.triggerSuggest"?{id:e.command,title:e.title,arguments:e.arguments}:void 0}var S=class{constructor(n){this._worker=n}provideHover(n,i,r){let t=n.uri;return this._worker(t).then(o=>o.doHover(t.toString(),k(i))).then(o=>{if(o)return{range:y(o.range),contents:Ht(o.contents)}})}};function Ut(e){return e&&typeof e=="object"&&typeof e.kind=="string"}function pt(e){return typeof e=="string"?{value:e}:Ut(e)?e.kind==="plaintext"?{value:e.value.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&")}:{value:e.value}:{value:"```"+e.language+` `+e.value+"\n```\n"}}function Ht(e){if(e)return Array.isArray(e)?e.map(pt):[pt(e)]}var F=class{constructor(n){this._worker=n}provideDocumentHighlights(n,i,r){let t=n.uri;return this._worker(t).then(o=>o.findDocumentHighlights(t.toString(),k(i))).then(o=>{if(o)return o.map(s=>({range:y(s.range),kind:Nt(s.kind)}))})}};function Nt(e){switch(e){case R.Read:return d.languages.DocumentHighlightKind.Read;case R.Write:return d.languages.DocumentHighlightKind.Write;case R.Text:return d.languages.DocumentHighlightKind.Text}return d.languages.DocumentHighlightKind.Text}var A=class{constructor(n){this._worker=n}provideDefinition(n,i,r){let t=n.uri;return this._worker(t).then(o=>o.findDefinition(t.toString(),k(i))).then(o=>{if(o)return[ht(o)]})}};function ht(e){return{uri:d.Uri.parse(e.uri),range:y(e.range)}}var M=class{constructor(n){this._worker=n}provideReferences(n,i,r,t){let o=n.uri;return this._worker(o).then(s=>s.findReferences(o.toString(),k(i))).then(s=>{if(s)return s.map(ht)})}},K=class{constructor(n){this._worker=n}provideRenameEdits(n,i,r,t){let o=n.uri;return this._worker(o).then(s=>s.doRename(o.toString(),k(i),r)).then(s=>Ot(s))}};function Ot(e){if(!e||!e.changes)return;let n=[];for(let i in e.changes){let r=d.Uri.parse(i);for(let t of e.changes[i])n.push({resource:r,versionId:void 0,textEdit:{range:y(t.range),text:t.newText}})}return{edits:n}}var j=class{constructor(n){this._worker=n}provideDocumentSymbols(n,i){let r=n.uri;return this._worker(r).then(t=>t.findDocumentSymbols(r.toString())).then(t=>{if(t)return t.map(o=>Vt(o)?mt(o):{name:o.name,detail:"",containerName:o.containerName,kind:xt(o.kind),range:y(o.location.range),selectionRange:y(o.location.range),tags:[]})})}};function Vt(e){return"children"in e}function mt(e){return{name:e.name,detail:e.detail??"",kind:xt(e.kind),range:y(e.range),selectionRange:y(e.selectionRange),tags:e.tags??[],children:(e.children??[]).map(n=>mt(n))}}function xt(e){let n=d.languages.SymbolKind;switch(e){case x.File:return n.File;case x.Module:return n.Module;case x.Namespace:return n.Namespace;case x.Package:return n.Package;case x.Class:return n.Class;case x.Method:return n.Method;case x.Property:return n.Property;case x.Field:return n.Field;case x.Constructor:return n.Constructor;case x.Enum:return n.Enum;case x.Interface:return n.Interface;case x.Function:return n.Function;case x.Variable:return n.Variable;case x.Constant:return n.Constant;case x.String:return n.String;case x.Number:return n.Number;case x.Boolean:return n.Boolean;case x.Array:return n.Array}return n.Function}var fe=class{constructor(n){this._worker=n}provideLinks(n,i){let r=n.uri;return this._worker(r).then(t=>t.findDocumentLinks(r.toString())).then(t=>{if(t)return{links:t.map(o=>({range:y(o.range),url:o.target}))}})}},U=class{constructor(n){this._worker=n}provideDocumentFormattingEdits(n,i,r){let t=n.uri;return this._worker(t).then(o=>o.format(t.toString(),null,yt(i)).then(s=>{if(!(!s||s.length===0))return s.map(P)}))}},H=class{constructor(n){this._worker=n;this.canFormatMultipleRanges=!1}provideDocumentRangeFormattingEdits(n,i,r,t){let o=n.uri;return this._worker(o).then(s=>s.format(o.toString(),pe(i),yt(r)).then(u=>{if(!(!u||u.length===0))return u.map(P)}))}};function yt(e){return{tabSize:e.tabSize,insertSpaces:e.insertSpaces}}var N=class{constructor(n){this._worker=n}provideDocumentColors(n,i){let r=n.uri;return this._worker(r).then(t=>t.findDocumentColors(r.toString())).then(t=>{if(t)return t.map(o=>({color:o.color,range:y(o.range)}))})}provideColorPresentations(n,i,r){let t=n.uri;return this._worker(t).then(o=>o.getColorPresentations(t.toString(),i.color,pe(i.range))).then(o=>{if(o)return o.map(s=>{let u={label:s.label};return s.textEdit&&(u.textEdit=P(s.textEdit)),s.additionalTextEdits&&(u.additionalTextEdits=s.additionalTextEdits.map(P)),u})})}},O=class{constructor(n){this._worker=n}provideFoldingRanges(n,i,r){let t=n.uri;return this._worker(t).then(o=>o.getFoldingRanges(t.toString(),i)).then(o=>{if(o)return o.map(s=>{let u={start:s.startLine+1,end:s.endLine+1};return typeof s.kind<"u"&&(u.kind=zt(s.kind)),u})})}};function zt(e){switch(e){case C.Comment:return d.languages.FoldingRangeKind.Comment;case C.Imports:return d.languages.FoldingRangeKind.Imports;case C.Region:return d.languages.FoldingRangeKind.Region}}var V=class{constructor(n){this._worker=n}provideSelectionRanges(n,i,r){let t=n.uri;return this._worker(t).then(o=>o.getSelectionRanges(t.toString(),i.map(k))).then(o=>{if(o)return o.map(s=>{let u=[];for(;s;)u.push({range:y(s.range)}),s=s.parent;return u})})}};function $t(e){let n=[],i=[],r=new _(e);n.push(r);let t=(...s)=>r.getLanguageServiceWorker(...s);function o(){let{languageId:s,modeConfiguration:u}=e;It(i),u.completionItems&&i.push(d.languages.registerCompletionItemProvider(s,new D(t,["/","-",":"]))),u.hovers&&i.push(d.languages.registerHoverProvider(s,new S(t))),u.documentHighlights&&i.push(d.languages.registerDocumentHighlightProvider(s,new F(t))),u.definitions&&i.push(d.languages.registerDefinitionProvider(s,new A(t))),u.references&&i.push(d.languages.registerReferenceProvider(s,new M(t))),u.documentSymbols&&i.push(d.languages.registerDocumentSymbolProvider(s,new j(t))),u.rename&&i.push(d.languages.registerRenameProvider(s,new K(t))),u.colors&&i.push(d.languages.registerColorProvider(s,new N(t))),u.foldingRanges&&i.push(d.languages.registerFoldingRangeProvider(s,new O(t))),u.diagnostics&&i.push(new W(s,t,e.onDidChange)),u.selectionRanges&&i.push(d.languages.registerSelectionRangeProvider(s,new V(t))),u.documentFormattingEdits&&i.push(d.languages.registerDocumentFormattingEditProvider(s,new U(t))),u.documentRangeFormattingEdits&&i.push(d.languages.registerDocumentRangeFormattingEditProvider(s,new H(t)))}return o(),n.push(vt(i)),vt(n)}function vt(e){return{dispose:()=>It(e)}}function It(e){for(;e.length;)e.pop().dispose()}return Lt(Bt);})(); return moduleExports; }); ================================================ FILE: public/js/monaco-editor-0.52.2/min/vs/language/css/cssWorker.js ================================================ /*!----------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1) * Released under the MIT license * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt *-----------------------------------------------------------------------------*/ define("vs/language/css/cssWorker", ["require","require"],(require)=>{ "use strict";var moduleExports=(()=>{var Er=Object.defineProperty;var Fo=Object.getOwnPropertyDescriptor;var Eo=Object.getOwnPropertyNames;var _o=Object.prototype.hasOwnProperty;var Io=(n,e)=>{for(var t in e)Er(n,t,{get:e[t],enumerable:!0})},Do=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Eo(e))!_o.call(n,i)&&i!==t&&Er(n,i,{get:()=>e[i],enumerable:!(r=Fo(e,i))||r.enumerable});return n};var Ro=n=>Do(Er({},"__esModule",{value:!0}),n);var nl={};Io(nl,{CSSWorker:()=>Fr,create:()=>tl});var c;(function(n){n[n.Ident=0]="Ident",n[n.AtKeyword=1]="AtKeyword",n[n.String=2]="String",n[n.BadString=3]="BadString",n[n.UnquotedString=4]="UnquotedString",n[n.Hash=5]="Hash",n[n.Num=6]="Num",n[n.Percentage=7]="Percentage",n[n.Dimension=8]="Dimension",n[n.UnicodeRange=9]="UnicodeRange",n[n.CDO=10]="CDO",n[n.CDC=11]="CDC",n[n.Colon=12]="Colon",n[n.SemiColon=13]="SemiColon",n[n.CurlyL=14]="CurlyL",n[n.CurlyR=15]="CurlyR",n[n.ParenthesisL=16]="ParenthesisL",n[n.ParenthesisR=17]="ParenthesisR",n[n.BracketL=18]="BracketL",n[n.BracketR=19]="BracketR",n[n.Whitespace=20]="Whitespace",n[n.Includes=21]="Includes",n[n.Dashmatch=22]="Dashmatch",n[n.SubstringOperator=23]="SubstringOperator",n[n.PrefixOperator=24]="PrefixOperator",n[n.SuffixOperator=25]="SuffixOperator",n[n.Delim=26]="Delim",n[n.EMS=27]="EMS",n[n.EXS=28]="EXS",n[n.Length=29]="Length",n[n.Angle=30]="Angle",n[n.Time=31]="Time",n[n.Freq=32]="Freq",n[n.Exclamation=33]="Exclamation",n[n.Resolution=34]="Resolution",n[n.Comma=35]="Comma",n[n.Charset=36]="Charset",n[n.EscapedJavaScript=37]="EscapedJavaScript",n[n.BadEscapedJavaScript=38]="BadEscapedJavaScript",n[n.Comment=39]="Comment",n[n.SingleLineComment=40]="SingleLineComment",n[n.EOF=41]="EOF",n[n.ContainerQueryLength=42]="ContainerQueryLength",n[n.CustomToken=43]="CustomToken"})(c||(c={}));var un=class{constructor(e){this.source=e,this.len=e.length,this.position=0}substring(e,t=this.position){return this.source.substring(e,t)}eos(){return this.len<=this.position}pos(){return this.position}goBackTo(e){this.position=e}goBack(e){this.position-=e}advance(e){this.position+=e}nextChar(){return this.source.charCodeAt(this.position++)||0}peekChar(e=0){return this.source.charCodeAt(this.position+e)||0}lookbackChar(e=0){return this.source.charCodeAt(this.position-e)||0}advanceIfChar(e){return e===this.source.charCodeAt(this.position)?(this.position++,!0):!1}advanceIfChars(e){if(this.position+e.length>this.source.length)return!1;let t=0;for(;tt&&r===Ui?(e=!0,!1):(t=r===_r,!0)),e&&this.stream.advance(1),!0}return!1}_number(){let e=0,t;return this.stream.peekChar()===Bi&&(e=1),t=this.stream.peekChar(e),t>=At&&t<=Wt?(this.stream.advance(e+1),this.stream.advanceWhileChar(r=>r>=At&&r<=Wt||e===0&&r===Bi),!0):!1}_newline(e){let t=this.stream.peekChar();switch(t){case dt:case $t:case ct:return this.stream.advance(1),e.push(String.fromCharCode(t)),t===dt&&this.stream.advanceIfChar(ct)&&e.push(` `),!0}return!1}_escape(e,t){let r=this.stream.peekChar();if(r===Ir){this.stream.advance(1),r=this.stream.peekChar();let i=0;for(;i<6&&(r>=At&&r<=Wt||r>=pn&&r<=Pi||r>=mn&&r<=Wi);)this.stream.advance(1),r=this.stream.peekChar(),i++;if(i>0){try{let s=parseInt(this.stream.substring(this.stream.pos()-i),16);s&&e.push(String.fromCharCode(s))}catch{}return r===Dr||r===Rr?this.stream.advance(1):this._newline([]),!0}if(r!==dt&&r!==$t&&r!==ct)return this.stream.advance(1),e.push(String.fromCharCode(r)),!0;if(t)return this._newline(e)}return!1}_stringChar(e,t){let r=this.stream.peekChar();return r!==0&&r!==e&&r!==Ir&&r!==dt&&r!==$t&&r!==ct?(this.stream.advance(1),t.push(String.fromCharCode(r)),!0):!1}_string(e){if(this.stream.peekChar()===ji||this.stream.peekChar()===Vi){let t=this.stream.nextChar();for(e.push(String.fromCharCode(t));this._stringChar(t,e)||this._escape(e,!0););return this.stream.peekChar()===t?(this.stream.nextChar(),e.push(String.fromCharCode(t)),c.String):c.BadString}return null}_unquotedChar(e){let t=this.stream.peekChar();return t!==0&&t!==Ir&&t!==ji&&t!==Vi&&t!==Ki&&t!==Gi&&t!==Dr&&t!==Rr&&t!==ct&&t!==$t&&t!==dt?(this.stream.advance(1),e.push(String.fromCharCode(t)),!0):!1}_unquotedString(e){let t=!1;for(;this._unquotedChar(e)||this._escape(e);)t=!0;return t}_whitespace(){return this.stream.advanceWhileChar(t=>t===Dr||t===Rr||t===ct||t===$t||t===dt)>0}_name(e){let t=!1;for(;this._identChar(e)||this._escape(e);)t=!0;return t}ident(e){let t=this.stream.pos();if(this._minus(e)){if(this._minus(e)||this._identFirstChar(e)||this._escape(e)){for(;this._identChar(e)||this._escape(e););return!0}}else if(this._identFirstChar(e)||this._escape(e)){for(;this._identChar(e)||this._escape(e););return!0}return this.stream.goBackTo(t),!1}_identFirstChar(e){let t=this.stream.peekChar();return t===$i||t>=pn&&t<=Ai||t>=mn&&t<=Li||t>=128&&t<=65535?(this.stream.advance(1),e.push(String.fromCharCode(t)),!0):!1}_minus(e){let t=this.stream.peekChar();return t===Qe?(this.stream.advance(1),e.push(String.fromCharCode(t)),!0):!1}_identChar(e){let t=this.stream.peekChar();return t===$i||t===Qe||t>=pn&&t<=Ai||t>=mn&&t<=Li||t>=At&&t<=Wt||t>=128&&t<=65535?(this.stream.advance(1),e.push(String.fromCharCode(t)),!0):!1}_unicodeRange(){if(this.stream.advanceIfChar(Ho)){let e=r=>r>=At&&r<=Wt||r>=pn&&r<=Pi||r>=mn&&r<=Wi,t=this.stream.advanceWhileChar(e)+this.stream.advanceWhileChar(r=>r===Go);if(t>=1&&t<=6)if(this.stream.advanceIfChar(Qe)){let r=this.stream.advanceWhileChar(e);if(r>=1&&r<=6)return!0}else return!0}return!1}};function V(n,e){if(n.length0?n.lastIndexOf(e)===t:t===0?n===e:!1}function Hi(n,e,t=4){let r=Math.abs(n.length-e.length);if(r>t)return 0;let i=[],s=[],a,l;for(a=0;a0;)(e&1)===1&&(t+=n),n+=n,e=e>>>1;return t}var m;(function(n){n[n.Undefined=0]="Undefined",n[n.Identifier=1]="Identifier",n[n.Stylesheet=2]="Stylesheet",n[n.Ruleset=3]="Ruleset",n[n.Selector=4]="Selector",n[n.SimpleSelector=5]="SimpleSelector",n[n.SelectorInterpolation=6]="SelectorInterpolation",n[n.SelectorCombinator=7]="SelectorCombinator",n[n.SelectorCombinatorParent=8]="SelectorCombinatorParent",n[n.SelectorCombinatorSibling=9]="SelectorCombinatorSibling",n[n.SelectorCombinatorAllSiblings=10]="SelectorCombinatorAllSiblings",n[n.SelectorCombinatorShadowPiercingDescendant=11]="SelectorCombinatorShadowPiercingDescendant",n[n.Page=12]="Page",n[n.PageBoxMarginBox=13]="PageBoxMarginBox",n[n.ClassSelector=14]="ClassSelector",n[n.IdentifierSelector=15]="IdentifierSelector",n[n.ElementNameSelector=16]="ElementNameSelector",n[n.PseudoSelector=17]="PseudoSelector",n[n.AttributeSelector=18]="AttributeSelector",n[n.Declaration=19]="Declaration",n[n.Declarations=20]="Declarations",n[n.Property=21]="Property",n[n.Expression=22]="Expression",n[n.BinaryExpression=23]="BinaryExpression",n[n.Term=24]="Term",n[n.Operator=25]="Operator",n[n.Value=26]="Value",n[n.StringLiteral=27]="StringLiteral",n[n.URILiteral=28]="URILiteral",n[n.EscapedValue=29]="EscapedValue",n[n.Function=30]="Function",n[n.NumericValue=31]="NumericValue",n[n.HexColorValue=32]="HexColorValue",n[n.RatioValue=33]="RatioValue",n[n.MixinDeclaration=34]="MixinDeclaration",n[n.MixinReference=35]="MixinReference",n[n.VariableName=36]="VariableName",n[n.VariableDeclaration=37]="VariableDeclaration",n[n.Prio=38]="Prio",n[n.Interpolation=39]="Interpolation",n[n.NestedProperties=40]="NestedProperties",n[n.ExtendsReference=41]="ExtendsReference",n[n.SelectorPlaceholder=42]="SelectorPlaceholder",n[n.Debug=43]="Debug",n[n.If=44]="If",n[n.Else=45]="Else",n[n.For=46]="For",n[n.Each=47]="Each",n[n.While=48]="While",n[n.MixinContentReference=49]="MixinContentReference",n[n.MixinContentDeclaration=50]="MixinContentDeclaration",n[n.Media=51]="Media",n[n.Keyframe=52]="Keyframe",n[n.FontFace=53]="FontFace",n[n.Import=54]="Import",n[n.Namespace=55]="Namespace",n[n.Invocation=56]="Invocation",n[n.FunctionDeclaration=57]="FunctionDeclaration",n[n.ReturnStatement=58]="ReturnStatement",n[n.MediaQuery=59]="MediaQuery",n[n.MediaCondition=60]="MediaCondition",n[n.MediaFeature=61]="MediaFeature",n[n.FunctionParameter=62]="FunctionParameter",n[n.FunctionArgument=63]="FunctionArgument",n[n.KeyframeSelector=64]="KeyframeSelector",n[n.ViewPort=65]="ViewPort",n[n.Document=66]="Document",n[n.AtApplyRule=67]="AtApplyRule",n[n.CustomPropertyDeclaration=68]="CustomPropertyDeclaration",n[n.CustomPropertySet=69]="CustomPropertySet",n[n.ListEntry=70]="ListEntry",n[n.Supports=71]="Supports",n[n.SupportsCondition=72]="SupportsCondition",n[n.NamespacePrefix=73]="NamespacePrefix",n[n.GridLine=74]="GridLine",n[n.Plugin=75]="Plugin",n[n.UnknownAtRule=76]="UnknownAtRule",n[n.Use=77]="Use",n[n.ModuleConfiguration=78]="ModuleConfiguration",n[n.Forward=79]="Forward",n[n.ForwardVisibility=80]="ForwardVisibility",n[n.Module=81]="Module",n[n.UnicodeRange=82]="UnicodeRange",n[n.Layer=83]="Layer",n[n.LayerNameList=84]="LayerNameList",n[n.LayerName=85]="LayerName",n[n.PropertyAtRule=86]="PropertyAtRule",n[n.Container=87]="Container"})(m||(m={}));var z;(function(n){n[n.Mixin=0]="Mixin",n[n.Rule=1]="Rule",n[n.Variable=2]="Variable",n[n.Function=3]="Function",n[n.Keyframe=4]="Keyframe",n[n.Unknown=5]="Unknown",n[n.Module=6]="Module",n[n.Forward=7]="Forward",n[n.ForwardVisibility=8]="ForwardVisibility",n[n.Property=9]="Property"})(z||(z={}));function Hn(n,e){let t=null;return!n||en.end?null:(n.accept(r=>r.offset===-1&&r.length===-1?!0:r.offset<=e&&r.end>=e?(t?r.length<=t.length&&(t=r):t=r,!0):!1),t)}function vt(n,e){let t=Hn(n,e),r=[];for(;t;)r.unshift(t),t=t.parent;return r}function Xi(n){let e=n.findParent(m.Declaration),t=e&&e.getValue();return t&&t.encloses(n)?e:null}var x=class{get end(){return this.offset+this.length}constructor(e=-1,t=-1,r){this.parent=null,this.offset=e,this.length=t,r&&(this.nodeType=r)}set type(e){this.nodeType=e}get type(){return this.nodeType||m.Undefined}getTextProvider(){let e=this;for(;e&&!e.textProvider;)e=e.parent;return e?e.textProvider:()=>"unknown"}getText(){return this.getTextProvider()(this.offset,this.length)}matches(e){return this.length===e.length&&this.getTextProvider()(this.offset,this.length)===e}startsWith(e){return this.length>=e.length&&this.getTextProvider()(this.offset,e.length)===e}endsWith(e){return this.length>=e.length&&this.getTextProvider()(this.end-e.length,e.length)===e}accept(e){if(e(this)&&this.children)for(let t of this.children)t.accept(e)}acceptVisitor(e){this.accept(e.visitNode.bind(e))}adoptChild(e,t=-1){if(e.parent&&e.parent.children){let i=e.parent.children.indexOf(e);i>=0&&e.parent.children.splice(i,1)}e.parent=this;let r=this.children;return r||(r=this.children=[]),t!==-1?r.splice(t,0,e):r.push(e),e}attachTo(e,t=-1){return e&&e.adoptChild(this,t),this}collectIssues(e){this.issues&&e.push.apply(e,this.issues)}addIssue(e){this.issues||(this.issues=[]),this.issues.push(e)}hasIssue(e){return Array.isArray(this.issues)&&this.issues.some(t=>t.getRule()===e)}isErroneous(e=!1){return this.issues&&this.issues.length>0?!0:e&&Array.isArray(this.children)&&this.children.some(t=>t.isErroneous(!0))}setNode(e,t,r=-1){return t?(t.attachTo(this,r),this[e]=t,!0):!1}addChild(e){return e?(this.children||(this.children=[]),e.attachTo(this),this.updateOffsetAndLength(e),!0):!1}updateOffsetAndLength(e){(e.offsetthis.end||this.length===-1)&&(this.length=t-this.offset)}hasChildren(){return!!this.children&&this.children.length>0}getChildren(){return this.children?this.children.slice(0):[]}getChild(e){return this.children&&e=0;r--)if(t=this.children[r],t.offset<=e)return t}return null}findChildAtOffset(e,t){let r=this.findFirstChildBeforeOffset(e);return r&&r.end>=e?t&&r.findChildAtOffset(e,!0)||r:null}encloses(e){return this.offset<=e.offset&&this.offset+this.length>=e.offset+e.length}getParent(){let e=this.parent;for(;e instanceof J;)e=e.parent;return e}findParent(e){let t=this;for(;t&&t.type!==e;)t=t.parent;return t}findAParent(...e){let t=this;for(;t&&!e.some(r=>t.type===r);)t=t.parent;return t}setData(e,t){this.options||(this.options={}),this.options[e]=t}getData(e){return!this.options||!this.options.hasOwnProperty(e)?null:this.options[e]}},J=class extends x{constructor(e,t=-1){super(-1,-1),this.attachTo(e,t),this.offset=-1,this.length=-1}},gn=class extends x{constructor(e,t){super(e,t)}get type(){return m.UnicodeRange}setRangeStart(e){return this.setNode("rangeStart",e)}getRangeStart(){return this.rangeStart}setRangeEnd(e){return this.setNode("rangeEnd",e)}getRangeEnd(){return this.rangeEnd}},G=class extends x{constructor(e,t){super(e,t),this.isCustomProperty=!1}get type(){return m.Identifier}containsInterpolation(){return this.hasChildren()}},bn=class extends x{constructor(e,t){super(e,t)}get type(){return m.Stylesheet}},Ze=class extends x{constructor(e,t){super(e,t)}get type(){return m.Declarations}},L=class extends x{constructor(e,t){super(e,t)}getDeclarations(){return this.declarations}setDeclarations(e){return this.setNode("declarations",e)}},ae=class extends L{constructor(e,t){super(e,t)}get type(){return m.Ruleset}getSelectors(){return this.selectors||(this.selectors=new J(this)),this.selectors}isNested(){return!!this.parent&&this.parent.findParent(m.Declarations)!==null}},de=class extends x{constructor(e,t){super(e,t)}get type(){return m.Selector}},he=class extends x{constructor(e,t){super(e,t)}get type(){return m.SimpleSelector}};var ht=class extends x{constructor(e,t){super(e,t)}},wn=class extends L{constructor(e,t){super(e,t)}get type(){return m.CustomPropertySet}},Q=class n extends ht{constructor(e,t){super(e,t),this.property=null}get type(){return m.Declaration}setProperty(e){return this.setNode("property",e)}getProperty(){return this.property}getFullPropertyName(){let e=this.property?this.property.getName():"unknown";if(this.parent instanceof Ze&&this.parent.getParent()instanceof Ut){let t=this.parent.getParent().getParent();if(t instanceof n)return t.getFullPropertyName()+e}return e}getNonPrefixedPropertyName(){let e=this.getFullPropertyName();if(e&&e.charAt(0)==="-"){let t=e.indexOf("-",1);if(t!==-1)return e.substring(t+1)}return e}setValue(e){return this.setNode("value",e)}getValue(){return this.value}setNestedProperties(e){return this.setNode("nestedProperties",e)}getNestedProperties(){return this.nestedProperties}},vn=class extends Q{constructor(e,t){super(e,t)}get type(){return m.CustomPropertyDeclaration}setPropertySet(e){return this.setNode("propertySet",e)}getPropertySet(){return this.propertySet}},Ve=class extends x{constructor(e,t){super(e,t)}get type(){return m.Property}setIdentifier(e){return this.setNode("identifier",e)}getIdentifier(){return this.identifier}getName(){return Ji(this.getText(),/[_\+]+$/)}isCustomProperty(){return!!this.identifier&&this.identifier.isCustomProperty}},Tr=class extends x{constructor(e,t){super(e,t)}get type(){return m.Invocation}getArguments(){return this.arguments||(this.arguments=new J(this)),this.arguments}},me=class extends Tr{constructor(e,t){super(e,t)}get type(){return m.Function}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}getName(){return this.identifier?this.identifier.getText():""}},ye=class extends x{constructor(e,t){super(e,t)}get type(){return m.FunctionParameter}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}getName(){return this.identifier?this.identifier.getText():""}setDefaultValue(e){return this.setNode("defaultValue",e,0)}getDefaultValue(){return this.defaultValue}},le=class extends x{constructor(e,t){super(e,t)}get type(){return m.FunctionArgument}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}getName(){return this.identifier?this.identifier.getText():""}setValue(e){return this.setNode("value",e,0)}getValue(){return this.value}},yn=class extends L{constructor(e,t){super(e,t)}get type(){return m.If}setExpression(e){return this.setNode("expression",e,0)}setElseClause(e){return this.setNode("elseClause",e)}},xn=class extends L{constructor(e,t){super(e,t)}get type(){return m.For}setVariable(e){return this.setNode("variable",e,0)}},Sn=class extends L{constructor(e,t){super(e,t)}get type(){return m.Each}getVariables(){return this.variables||(this.variables=new J(this)),this.variables}},Cn=class extends L{constructor(e,t){super(e,t)}get type(){return m.While}},kn=class extends L{constructor(e,t){super(e,t)}get type(){return m.Else}},De=class extends L{constructor(e,t){super(e,t)}get type(){return m.FunctionDeclaration}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}getName(){return this.identifier?this.identifier.getText():""}getParameters(){return this.parameters||(this.parameters=new J(this)),this.parameters}},Fn=class extends L{constructor(e,t){super(e,t)}get type(){return m.ViewPort}},pt=class extends L{constructor(e,t){super(e,t)}get type(){return m.FontFace}},Ut=class extends L{constructor(e,t){super(e,t)}get type(){return m.NestedProperties}},mt=class extends L{constructor(e,t){super(e,t)}get type(){return m.Keyframe}setKeyword(e){return this.setNode("keyword",e,0)}getKeyword(){return this.keyword}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}getName(){return this.identifier?this.identifier.getText():""}},Vt=class extends L{constructor(e,t){super(e,t)}get type(){return m.KeyframeSelector}},je=class extends x{constructor(e,t){super(e,t)}get type(){return m.Import}setMedialist(e){return e?(e.attachTo(this),!0):!1}},En=class extends x{get type(){return m.Use}getParameters(){return this.parameters||(this.parameters=new J(this)),this.parameters}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}},_n=class extends x{get type(){return m.ModuleConfiguration}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}getName(){return this.identifier?this.identifier.getText():""}setValue(e){return this.setNode("value",e,0)}getValue(){return this.value}},In=class extends x{get type(){return m.Forward}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}getMembers(){return this.members||(this.members=new J(this)),this.members}getParameters(){return this.parameters||(this.parameters=new J(this)),this.parameters}},Dn=class extends x{get type(){return m.ForwardVisibility}setIdentifier(e){return this.setNode("identifier",e,0)}getIdentifier(){return this.identifier}},Rn=class extends x{constructor(e,t){super(e,t)}get type(){return m.Namespace}},Be=class extends L{constructor(e,t){super(e,t)}get type(){return m.Media}},et=class extends L{constructor(e,t){super(e,t)}get type(){return m.Supports}},zn=class extends L{constructor(e,t){super(e,t)}get type(){return m.Layer}setNames(e){return this.setNode("names",e)}getNames(){return this.names}},Mn=class extends L{constructor(e,t){super(e,t)}get type(){return m.PropertyAtRule}setName(e){return e?(e.attachTo(this),this.name=e,!0):!1}getName(){return this.name}},Tn=class extends L{constructor(e,t){super(e,t)}get type(){return m.Document}},Nn=class extends L{constructor(e,t){super(e,t)}get type(){return m.Container}},ut=class extends x{constructor(e,t){super(e,t)}},ft=class extends x{constructor(e,t){super(e,t)}get type(){return m.MediaQuery}},On=class extends x{constructor(e,t){super(e,t)}get type(){return m.MediaCondition}},Pn=class extends x{constructor(e,t){super(e,t)}get type(){return m.MediaFeature}},Re=class extends x{constructor(e,t){super(e,t)}get type(){return m.SupportsCondition}},An=class extends L{constructor(e,t){super(e,t)}get type(){return m.Page}},Wn=class extends L{constructor(e,t){super(e,t)}get type(){return m.PageBoxMarginBox}},gt=class extends x{constructor(e,t){super(e,t)}get type(){return m.Expression}},qe=class extends x{constructor(e,t){super(e,t)}get type(){return m.BinaryExpression}setLeft(e){return this.setNode("left",e)}getLeft(){return this.left}setRight(e){return this.setNode("right",e)}getRight(){return this.right}setOperator(e){return this.setNode("operator",e)}getOperator(){return this.operator}},Ln=class extends x{constructor(e,t){super(e,t)}get type(){return m.Term}setOperator(e){return this.setNode("operator",e)}getOperator(){return this.operator}setExpression(e){return this.setNode("expression",e)}getExpression(){return this.expression}},$n=class extends x{constructor(e,t){super(e,t)}get type(){return m.AttributeSelector}setNamespacePrefix(e){return this.setNode("namespacePrefix",e)}getNamespacePrefix(){return this.namespacePrefix}setIdentifier(e){return this.setNode("identifier",e)}getIdentifier(){return this.identifier}setOperator(e){return this.setNode("operator",e)}getOperator(){return this.operator}setValue(e){return this.setNode("value",e)}getValue(){return this.value}};var tt=class extends x{constructor(e,t){super(e,t)}get type(){return m.HexColorValue}},Un=class extends x{constructor(e,t){super(e,t)}get type(){return m.RatioValue}},Yo=46,Qo=48,Zo=57,nt=class extends x{constructor(e,t){super(e,t)}get type(){return m.NumericValue}getValue(){let e=this.getText(),t=0,r;for(let i=0,s=e.length;i0&&(t+=`/${Array.isArray(e.comment)?e.comment.join(""):e.comment}`),i=e.args??{};let s=ea?.[t];return s?typeof s=="string"?Jn(s,i):s.comment?Jn(s.message,i):Jn(r,i):Jn(r,i)}var ta=/{([^}]+)}/g;function Jn(n,e){return Object.keys(e).length===0?n:n.replace(ta,(t,r)=>e[r]??t)}var O=class{constructor(e,t){this.id=e,this.message=t}},f={NumberExpected:new O("css-numberexpected",p("number expected")),ConditionExpected:new O("css-conditionexpected",p("condition expected")),RuleOrSelectorExpected:new O("css-ruleorselectorexpected",p("at-rule or selector expected")),DotExpected:new O("css-dotexpected",p("dot expected")),ColonExpected:new O("css-colonexpected",p("colon expected")),SemiColonExpected:new O("css-semicolonexpected",p("semi-colon expected")),TermExpected:new O("css-termexpected",p("term expected")),ExpressionExpected:new O("css-expressionexpected",p("expression expected")),OperatorExpected:new O("css-operatorexpected",p("operator expected")),IdentifierExpected:new O("css-identifierexpected",p("identifier expected")),PercentageExpected:new O("css-percentageexpected",p("percentage expected")),URIOrStringExpected:new O("css-uriorstringexpected",p("uri or string expected")),URIExpected:new O("css-uriexpected",p("URI expected")),VariableNameExpected:new O("css-varnameexpected",p("variable name expected")),VariableValueExpected:new O("css-varvalueexpected",p("variable value expected")),PropertyValueExpected:new O("css-propertyvalueexpected",p("property value expected")),LeftCurlyExpected:new O("css-lcurlyexpected",p("{ expected")),RightCurlyExpected:new O("css-rcurlyexpected",p("} expected")),LeftSquareBracketExpected:new O("css-rbracketexpected",p("[ expected")),RightSquareBracketExpected:new O("css-lbracketexpected",p("] expected")),LeftParenthesisExpected:new O("css-lparentexpected",p("( expected")),RightParenthesisExpected:new O("css-rparentexpected",p(") expected")),CommaExpected:new O("css-commaexpected",p("comma expected")),PageDirectiveOrDeclarationExpected:new O("css-pagedirordeclexpected",p("page directive or declaraton expected")),UnknownAtRule:new O("css-unknownatrule",p("at-rule unknown")),UnknownKeyword:new O("css-unknownkeyword",p("unknown keyword")),SelectorExpected:new O("css-selectorexpected",p("selector expected")),StringLiteralExpected:new O("css-stringliteralexpected",p("string literal expected")),WhitespaceExpected:new O("css-whitespaceexpected",p("whitespace expected")),MediaQueryExpected:new O("css-mediaqueryexpected",p("media query expected")),IdentifierOrWildcardExpected:new O("css-idorwildcardexpected",p("identifier or wildcard expected")),WildcardExpected:new O("css-wildcardexpected",p("wildcard expected")),IdentifierOrVariableExpected:new O("css-idorvarexpected",p("identifier or variable expected"))};var Nr;(function(n){function e(t){return typeof t=="string"}n.is=e})(Nr||(Nr={}));var Or;(function(n){function e(t){return typeof t=="string"}n.is=e})(Or||(Or={}));var Yi;(function(n){n.MIN_VALUE=-2147483648,n.MAX_VALUE=2147483647;function e(t){return typeof t=="number"&&n.MIN_VALUE<=t&&t<=n.MAX_VALUE}n.is=e})(Yi||(Yi={}));var Xn;(function(n){n.MIN_VALUE=0,n.MAX_VALUE=2147483647;function e(t){return typeof t=="number"&&n.MIN_VALUE<=t&&t<=n.MAX_VALUE}n.is=e})(Xn||(Xn={}));var H;(function(n){function e(r,i){return r===Number.MAX_VALUE&&(r=Xn.MAX_VALUE),i===Number.MAX_VALUE&&(i=Xn.MAX_VALUE),{line:r,character:i}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&g.uinteger(i.line)&&g.uinteger(i.character)}n.is=t})(H||(H={}));var R;(function(n){function e(r,i,s,a){if(g.uinteger(r)&&g.uinteger(i)&&g.uinteger(s)&&g.uinteger(a))return{start:H.create(r,i),end:H.create(s,a)};if(H.is(r)&&H.is(i))return{start:r,end:i};throw new Error(`Range#create called with invalid arguments[${r}, ${i}, ${s}, ${a}]`)}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&H.is(i.start)&&H.is(i.end)}n.is=t})(R||(R={}));var it;(function(n){function e(r,i){return{uri:r,range:i}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&R.is(i.range)&&(g.string(i.uri)||g.undefined(i.uri))}n.is=t})(it||(it={}));var Qi;(function(n){function e(r,i,s,a){return{targetUri:r,targetRange:i,targetSelectionRange:s,originSelectionRange:a}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&R.is(i.targetRange)&&g.string(i.targetUri)&&R.is(i.targetSelectionRange)&&(R.is(i.originSelectionRange)||g.undefined(i.originSelectionRange))}n.is=t})(Qi||(Qi={}));var Yn;(function(n){function e(r,i,s,a){return{red:r,green:i,blue:s,alpha:a}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&g.numberRange(i.red,0,1)&&g.numberRange(i.green,0,1)&&g.numberRange(i.blue,0,1)&&g.numberRange(i.alpha,0,1)}n.is=t})(Yn||(Yn={}));var Pr;(function(n){function e(r,i){return{range:r,color:i}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&R.is(i.range)&&Yn.is(i.color)}n.is=t})(Pr||(Pr={}));var Ar;(function(n){function e(r,i,s){return{label:r,textEdit:i,additionalTextEdits:s}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&g.string(i.label)&&(g.undefined(i.textEdit)||_.is(i))&&(g.undefined(i.additionalTextEdits)||g.typedArray(i.additionalTextEdits,_.is))}n.is=t})(Ar||(Ar={}));var Wr;(function(n){n.Comment="comment",n.Imports="imports",n.Region="region"})(Wr||(Wr={}));var Lr;(function(n){function e(r,i,s,a,l,o){let d={startLine:r,endLine:i};return g.defined(s)&&(d.startCharacter=s),g.defined(a)&&(d.endCharacter=a),g.defined(l)&&(d.kind=l),g.defined(o)&&(d.collapsedText=o),d}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&g.uinteger(i.startLine)&&g.uinteger(i.startLine)&&(g.undefined(i.startCharacter)||g.uinteger(i.startCharacter))&&(g.undefined(i.endCharacter)||g.uinteger(i.endCharacter))&&(g.undefined(i.kind)||g.string(i.kind))}n.is=t})(Lr||(Lr={}));var $r;(function(n){function e(r,i){return{location:r,message:i}}n.create=e;function t(r){let i=r;return g.defined(i)&&it.is(i.location)&&g.string(i.message)}n.is=t})($r||($r={}));var yt;(function(n){n.Error=1,n.Warning=2,n.Information=3,n.Hint=4})(yt||(yt={}));var Zi;(function(n){n.Unnecessary=1,n.Deprecated=2})(Zi||(Zi={}));var es;(function(n){function e(t){let r=t;return g.objectLiteral(r)&&g.string(r.href)}n.is=e})(es||(es={}));var Bt;(function(n){function e(r,i,s,a,l,o){let d={range:r,message:i};return g.defined(s)&&(d.severity=s),g.defined(a)&&(d.code=a),g.defined(l)&&(d.source=l),g.defined(o)&&(d.relatedInformation=o),d}n.create=e;function t(r){var i;let s=r;return g.defined(s)&&R.is(s.range)&&g.string(s.message)&&(g.number(s.severity)||g.undefined(s.severity))&&(g.integer(s.code)||g.string(s.code)||g.undefined(s.code))&&(g.undefined(s.codeDescription)||g.string((i=s.codeDescription)===null||i===void 0?void 0:i.href))&&(g.string(s.source)||g.undefined(s.source))&&(g.undefined(s.relatedInformation)||g.typedArray(s.relatedInformation,$r.is))}n.is=t})(Bt||(Bt={}));var Me;(function(n){function e(r,i,...s){let a={title:r,command:i};return g.defined(s)&&s.length>0&&(a.arguments=s),a}n.create=e;function t(r){let i=r;return g.defined(i)&&g.string(i.title)&&g.string(i.command)}n.is=t})(Me||(Me={}));var _;(function(n){function e(s,a){return{range:s,newText:a}}n.replace=e;function t(s,a){return{range:{start:s,end:s},newText:a}}n.insert=t;function r(s){return{range:s,newText:""}}n.del=r;function i(s){let a=s;return g.objectLiteral(a)&&g.string(a.newText)&&R.is(a.range)}n.is=i})(_||(_={}));var Ur;(function(n){function e(r,i,s){let a={label:r};return i!==void 0&&(a.needsConfirmation=i),s!==void 0&&(a.description=s),a}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&g.string(i.label)&&(g.boolean(i.needsConfirmation)||i.needsConfirmation===void 0)&&(g.string(i.description)||i.description===void 0)}n.is=t})(Ur||(Ur={}));var xt;(function(n){function e(t){let r=t;return g.string(r)}n.is=e})(xt||(xt={}));var ts;(function(n){function e(s,a,l){return{range:s,newText:a,annotationId:l}}n.replace=e;function t(s,a,l){return{range:{start:s,end:s},newText:a,annotationId:l}}n.insert=t;function r(s,a){return{range:s,newText:"",annotationId:a}}n.del=r;function i(s){let a=s;return _.is(a)&&(Ur.is(a.annotationId)||xt.is(a.annotationId))}n.is=i})(ts||(ts={}));var St;(function(n){function e(r,i){return{textDocument:r,edits:i}}n.create=e;function t(r){let i=r;return g.defined(i)&&qr.is(i.textDocument)&&Array.isArray(i.edits)}n.is=t})(St||(St={}));var Vr;(function(n){function e(r,i,s){let a={kind:"create",uri:r};return i!==void 0&&(i.overwrite!==void 0||i.ignoreIfExists!==void 0)&&(a.options=i),s!==void 0&&(a.annotationId=s),a}n.create=e;function t(r){let i=r;return i&&i.kind==="create"&&g.string(i.uri)&&(i.options===void 0||(i.options.overwrite===void 0||g.boolean(i.options.overwrite))&&(i.options.ignoreIfExists===void 0||g.boolean(i.options.ignoreIfExists)))&&(i.annotationId===void 0||xt.is(i.annotationId))}n.is=t})(Vr||(Vr={}));var jr;(function(n){function e(r,i,s,a){let l={kind:"rename",oldUri:r,newUri:i};return s!==void 0&&(s.overwrite!==void 0||s.ignoreIfExists!==void 0)&&(l.options=s),a!==void 0&&(l.annotationId=a),l}n.create=e;function t(r){let i=r;return i&&i.kind==="rename"&&g.string(i.oldUri)&&g.string(i.newUri)&&(i.options===void 0||(i.options.overwrite===void 0||g.boolean(i.options.overwrite))&&(i.options.ignoreIfExists===void 0||g.boolean(i.options.ignoreIfExists)))&&(i.annotationId===void 0||xt.is(i.annotationId))}n.is=t})(jr||(jr={}));var Br;(function(n){function e(r,i,s){let a={kind:"delete",uri:r};return i!==void 0&&(i.recursive!==void 0||i.ignoreIfNotExists!==void 0)&&(a.options=i),s!==void 0&&(a.annotationId=s),a}n.create=e;function t(r){let i=r;return i&&i.kind==="delete"&&g.string(i.uri)&&(i.options===void 0||(i.options.recursive===void 0||g.boolean(i.options.recursive))&&(i.options.ignoreIfNotExists===void 0||g.boolean(i.options.ignoreIfNotExists)))&&(i.annotationId===void 0||xt.is(i.annotationId))}n.is=t})(Br||(Br={}));var Qn;(function(n){function e(t){let r=t;return r&&(r.changes!==void 0||r.documentChanges!==void 0)&&(r.documentChanges===void 0||r.documentChanges.every(i=>g.string(i.kind)?Vr.is(i)||jr.is(i)||Br.is(i):St.is(i)))}n.is=e})(Qn||(Qn={}));var ns;(function(n){function e(r){return{uri:r}}n.create=e;function t(r){let i=r;return g.defined(i)&&g.string(i.uri)}n.is=t})(ns||(ns={}));var qt;(function(n){function e(r,i){return{uri:r,version:i}}n.create=e;function t(r){let i=r;return g.defined(i)&&g.string(i.uri)&&g.integer(i.version)}n.is=t})(qt||(qt={}));var qr;(function(n){function e(r,i){return{uri:r,version:i}}n.create=e;function t(r){let i=r;return g.defined(i)&&g.string(i.uri)&&(i.version===null||g.integer(i.version))}n.is=t})(qr||(qr={}));var rs;(function(n){function e(r,i,s,a){return{uri:r,languageId:i,version:s,text:a}}n.create=e;function t(r){let i=r;return g.defined(i)&&g.string(i.uri)&&g.string(i.languageId)&&g.integer(i.version)&&g.string(i.text)}n.is=t})(rs||(rs={}));var se;(function(n){n.PlainText="plaintext",n.Markdown="markdown";function e(t){let r=t;return r===n.PlainText||r===n.Markdown}n.is=e})(se||(se={}));var Ct;(function(n){function e(t){let r=t;return g.objectLiteral(t)&&se.is(r.kind)&&g.string(r.value)}n.is=e})(Ct||(Ct={}));var k;(function(n){n.Text=1,n.Method=2,n.Function=3,n.Constructor=4,n.Field=5,n.Variable=6,n.Class=7,n.Interface=8,n.Module=9,n.Property=10,n.Unit=11,n.Value=12,n.Enum=13,n.Keyword=14,n.Snippet=15,n.Color=16,n.File=17,n.Reference=18,n.Folder=19,n.EnumMember=20,n.Constant=21,n.Struct=22,n.Event=23,n.Operator=24,n.TypeParameter=25})(k||(k={}));var te;(function(n){n.PlainText=1,n.Snippet=2})(te||(te={}));var Te;(function(n){n.Deprecated=1})(Te||(Te={}));var is;(function(n){function e(r,i,s){return{newText:r,insert:i,replace:s}}n.create=e;function t(r){let i=r;return i&&g.string(i.newText)&&R.is(i.insert)&&R.is(i.replace)}n.is=t})(is||(is={}));var ss;(function(n){n.asIs=1,n.adjustIndentation=2})(ss||(ss={}));var os;(function(n){function e(t){let r=t;return r&&(g.string(r.detail)||r.detail===void 0)&&(g.string(r.description)||r.description===void 0)}n.is=e})(os||(os={}));var Kr;(function(n){function e(t){return{label:t}}n.create=e})(Kr||(Kr={}));var Gr;(function(n){function e(t,r){return{items:t||[],isIncomplete:!!r}}n.create=e})(Gr||(Gr={}));var Kt;(function(n){function e(r){return r.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&")}n.fromPlainText=e;function t(r){let i=r;return g.string(i)||g.objectLiteral(i)&&g.string(i.language)&&g.string(i.value)}n.is=t})(Kt||(Kt={}));var Hr;(function(n){function e(t){let r=t;return!!r&&g.objectLiteral(r)&&(Ct.is(r.contents)||Kt.is(r.contents)||g.typedArray(r.contents,Kt.is))&&(t.range===void 0||R.is(t.range))}n.is=e})(Hr||(Hr={}));var as;(function(n){function e(t,r){return r?{label:t,documentation:r}:{label:t}}n.create=e})(as||(as={}));var ls;(function(n){function e(t,r,...i){let s={label:t};return g.defined(r)&&(s.documentation=r),g.defined(i)?s.parameters=i:s.parameters=[],s}n.create=e})(ls||(ls={}));var Ge;(function(n){n.Text=1,n.Read=2,n.Write=3})(Ge||(Ge={}));var Jr;(function(n){function e(t,r){let i={range:t};return g.number(r)&&(i.kind=r),i}n.create=e})(Jr||(Jr={}));var ge;(function(n){n.File=1,n.Module=2,n.Namespace=3,n.Package=4,n.Class=5,n.Method=6,n.Property=7,n.Field=8,n.Constructor=9,n.Enum=10,n.Interface=11,n.Function=12,n.Variable=13,n.Constant=14,n.String=15,n.Number=16,n.Boolean=17,n.Array=18,n.Object=19,n.Key=20,n.Null=21,n.EnumMember=22,n.Struct=23,n.Event=24,n.Operator=25,n.TypeParameter=26})(ge||(ge={}));var cs;(function(n){n.Deprecated=1})(cs||(cs={}));var Xr;(function(n){function e(t,r,i,s,a){let l={name:t,kind:r,location:{uri:s,range:i}};return a&&(l.containerName=a),l}n.create=e})(Xr||(Xr={}));var ds;(function(n){function e(t,r,i,s){return s!==void 0?{name:t,kind:r,location:{uri:i,range:s}}:{name:t,kind:r,location:{uri:i}}}n.create=e})(ds||(ds={}));var Yr;(function(n){function e(r,i,s,a,l,o){let d={name:r,detail:i,kind:s,range:a,selectionRange:l};return o!==void 0&&(d.children=o),d}n.create=e;function t(r){let i=r;return i&&g.string(i.name)&&g.number(i.kind)&&R.is(i.range)&&R.is(i.selectionRange)&&(i.detail===void 0||g.string(i.detail))&&(i.deprecated===void 0||g.boolean(i.deprecated))&&(i.children===void 0||Array.isArray(i.children))&&(i.tags===void 0||Array.isArray(i.tags))}n.is=t})(Yr||(Yr={}));var Gt;(function(n){n.Empty="",n.QuickFix="quickfix",n.Refactor="refactor",n.RefactorExtract="refactor.extract",n.RefactorInline="refactor.inline",n.RefactorRewrite="refactor.rewrite",n.Source="source",n.SourceOrganizeImports="source.organizeImports",n.SourceFixAll="source.fixAll"})(Gt||(Gt={}));var Zn;(function(n){n.Invoked=1,n.Automatic=2})(Zn||(Zn={}));var Qr;(function(n){function e(r,i,s){let a={diagnostics:r};return i!=null&&(a.only=i),s!=null&&(a.triggerKind=s),a}n.create=e;function t(r){let i=r;return g.defined(i)&&g.typedArray(i.diagnostics,Bt.is)&&(i.only===void 0||g.typedArray(i.only,g.string))&&(i.triggerKind===void 0||i.triggerKind===Zn.Invoked||i.triggerKind===Zn.Automatic)}n.is=t})(Qr||(Qr={}));var Ht;(function(n){function e(r,i,s){let a={title:r},l=!0;return typeof i=="string"?(l=!1,a.kind=i):Me.is(i)?a.command=i:a.edit=i,l&&s!==void 0&&(a.kind=s),a}n.create=e;function t(r){let i=r;return i&&g.string(i.title)&&(i.diagnostics===void 0||g.typedArray(i.diagnostics,Bt.is))&&(i.kind===void 0||g.string(i.kind))&&(i.edit!==void 0||i.command!==void 0)&&(i.command===void 0||Me.is(i.command))&&(i.isPreferred===void 0||g.boolean(i.isPreferred))&&(i.edit===void 0||Qn.is(i.edit))}n.is=t})(Ht||(Ht={}));var hs;(function(n){function e(r,i){let s={range:r};return g.defined(i)&&(s.data=i),s}n.create=e;function t(r){let i=r;return g.defined(i)&&R.is(i.range)&&(g.undefined(i.command)||Me.is(i.command))}n.is=t})(hs||(hs={}));var ps;(function(n){function e(r,i){return{tabSize:r,insertSpaces:i}}n.create=e;function t(r){let i=r;return g.defined(i)&&g.uinteger(i.tabSize)&&g.boolean(i.insertSpaces)}n.is=t})(ps||(ps={}));var Zr;(function(n){function e(r,i,s){return{range:r,target:i,data:s}}n.create=e;function t(r){let i=r;return g.defined(i)&&R.is(i.range)&&(g.undefined(i.target)||g.string(i.target))}n.is=t})(Zr||(Zr={}));var kt;(function(n){function e(r,i){return{range:r,parent:i}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&R.is(i.range)&&(i.parent===void 0||n.is(i.parent))}n.is=t})(kt||(kt={}));var ms;(function(n){n.namespace="namespace",n.type="type",n.class="class",n.enum="enum",n.interface="interface",n.struct="struct",n.typeParameter="typeParameter",n.parameter="parameter",n.variable="variable",n.property="property",n.enumMember="enumMember",n.event="event",n.function="function",n.method="method",n.macro="macro",n.keyword="keyword",n.modifier="modifier",n.comment="comment",n.string="string",n.number="number",n.regexp="regexp",n.operator="operator",n.decorator="decorator"})(ms||(ms={}));var us;(function(n){n.declaration="declaration",n.definition="definition",n.readonly="readonly",n.static="static",n.deprecated="deprecated",n.abstract="abstract",n.async="async",n.modification="modification",n.documentation="documentation",n.defaultLibrary="defaultLibrary"})(us||(us={}));var fs;(function(n){function e(t){let r=t;return g.objectLiteral(r)&&(r.resultId===void 0||typeof r.resultId=="string")&&Array.isArray(r.data)&&(r.data.length===0||typeof r.data[0]=="number")}n.is=e})(fs||(fs={}));var gs;(function(n){function e(r,i){return{range:r,text:i}}n.create=e;function t(r){let i=r;return i!=null&&R.is(i.range)&&g.string(i.text)}n.is=t})(gs||(gs={}));var bs;(function(n){function e(r,i,s){return{range:r,variableName:i,caseSensitiveLookup:s}}n.create=e;function t(r){let i=r;return i!=null&&R.is(i.range)&&g.boolean(i.caseSensitiveLookup)&&(g.string(i.variableName)||i.variableName===void 0)}n.is=t})(bs||(bs={}));var ws;(function(n){function e(r,i){return{range:r,expression:i}}n.create=e;function t(r){let i=r;return i!=null&&R.is(i.range)&&(g.string(i.expression)||i.expression===void 0)}n.is=t})(ws||(ws={}));var vs;(function(n){function e(r,i){return{frameId:r,stoppedLocation:i}}n.create=e;function t(r){let i=r;return g.defined(i)&&R.is(r.stoppedLocation)}n.is=t})(vs||(vs={}));var ei;(function(n){n.Type=1,n.Parameter=2;function e(t){return t===1||t===2}n.is=e})(ei||(ei={}));var ti;(function(n){function e(r){return{value:r}}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&(i.tooltip===void 0||g.string(i.tooltip)||Ct.is(i.tooltip))&&(i.location===void 0||it.is(i.location))&&(i.command===void 0||Me.is(i.command))}n.is=t})(ti||(ti={}));var ys;(function(n){function e(r,i,s){let a={position:r,label:i};return s!==void 0&&(a.kind=s),a}n.create=e;function t(r){let i=r;return g.objectLiteral(i)&&H.is(i.position)&&(g.string(i.label)||g.typedArray(i.label,ti.is))&&(i.kind===void 0||ei.is(i.kind))&&i.textEdits===void 0||g.typedArray(i.textEdits,_.is)&&(i.tooltip===void 0||g.string(i.tooltip)||Ct.is(i.tooltip))&&(i.paddingLeft===void 0||g.boolean(i.paddingLeft))&&(i.paddingRight===void 0||g.boolean(i.paddingRight))}n.is=t})(ys||(ys={}));var xs;(function(n){function e(t){return{kind:"snippet",value:t}}n.createSnippet=e})(xs||(xs={}));var Ss;(function(n){function e(t,r,i,s){return{insertText:t,filterText:r,range:i,command:s}}n.create=e})(Ss||(Ss={}));var Cs;(function(n){function e(t){return{items:t}}n.create=e})(Cs||(Cs={}));var ks;(function(n){n.Invoked=0,n.Automatic=1})(ks||(ks={}));var Fs;(function(n){function e(t,r){return{range:t,text:r}}n.create=e})(Fs||(Fs={}));var Es;(function(n){function e(t,r){return{triggerKind:t,selectedCompletionInfo:r}}n.create=e})(Es||(Es={}));var _s;(function(n){function e(t){let r=t;return g.objectLiteral(r)&&Or.is(r.uri)&&g.string(r.name)}n.is=e})(_s||(_s={}));var Is;(function(n){function e(s,a,l,o){return new ni(s,a,l,o)}n.create=e;function t(s){let a=s;return!!(g.defined(a)&&g.string(a.uri)&&(g.undefined(a.languageId)||g.string(a.languageId))&&g.uinteger(a.lineCount)&&g.func(a.getText)&&g.func(a.positionAt)&&g.func(a.offsetAt))}n.is=t;function r(s,a){let l=s.getText(),o=i(a,(h,u)=>{let w=h.range.start.line-u.range.start.line;return w===0?h.range.start.character-u.range.start.character:w}),d=l.length;for(let h=o.length-1;h>=0;h--){let u=o[h],w=s.offsetAt(u.range.start),b=s.offsetAt(u.range.end);if(b<=d)l=l.substring(0,w)+u.newText+l.substring(b,l.length);else throw new Error("Overlapping edit");d=w}return l}n.applyEdits=r;function i(s,a){if(s.length<=1)return s;let l=s.length/2|0,o=s.slice(0,l),d=s.slice(l);i(o,a),i(d,a);let h=0,u=0,w=0;for(;h0&&e.push(t.length),this._lineOffsets=e}return this._lineOffsets}positionAt(e){e=Math.max(Math.min(e,this._content.length),0);let t=this.getLineOffsets(),r=0,i=t.length;if(i===0)return H.create(0,e);for(;re?i=a:r=a+1}let s=r-1;return H.create(s,e-t[s])}offsetAt(e){let t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;let r=t[e.line],i=e.line+1"u"}n.undefined=r;function i(b){return b===!0||b===!1}n.boolean=i;function s(b){return e.call(b)==="[object String]"}n.string=s;function a(b){return e.call(b)==="[object Number]"}n.number=a;function l(b,y,E){return e.call(b)==="[object Number]"&&y<=b&&b<=E}n.numberRange=l;function o(b){return e.call(b)==="[object Number]"&&-2147483648<=b&&b<=2147483647}n.integer=o;function d(b){return e.call(b)==="[object Number]"&&0<=b&&b<=2147483647}n.uinteger=d;function h(b){return e.call(b)==="[object Function]"}n.func=h;function u(b){return b!==null&&typeof b=="object"}n.objectLiteral=u;function w(b,y){return Array.isArray(b)&&b.every(y)}n.typedArray=w})(g||(g={}));var er=class n{constructor(e,t,r,i){this._uri=e,this._languageId=t,this._version=r,this._content=i,this._lineOffsets=void 0}get uri(){return this._uri}get languageId(){return this._languageId}get version(){return this._version}getText(e){if(e){let t=this.offsetAt(e.start),r=this.offsetAt(e.end);return this._content.substring(t,r)}return this._content}update(e,t){for(let r of e)if(n.isIncremental(r)){let i=Rs(r.range),s=this.offsetAt(i.start),a=this.offsetAt(i.end);this._content=this._content.substring(0,s)+r.text+this._content.substring(a,this._content.length);let l=Math.max(i.start.line,0),o=Math.max(i.end.line,0),d=this._lineOffsets,h=Ds(r.text,!1,s);if(o-l===h.length)for(let w=0,b=h.length;we?i=a:r=a+1}let s=r-1;return{line:s,character:e-t[s]}}offsetAt(e){let t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;let r=t[e.line],i=e.line+1{let w=h.range.start.line-u.range.start.line;return w===0?h.range.start.character-u.range.start.character:w}),o=0,d=[];for(let h of l){let u=i.offsetAt(h.range.start);if(uo&&d.push(a.substring(o,u)),h.newText.length&&d.push(h.newText),o=i.offsetAt(h.range.end)}return d.push(a.substr(o)),d.join("")}n.applyEdits=r})(Jt||(Jt={}));function ri(n,e){if(n.length<=1)return n;let t=n.length/2|0,r=n.slice(0,t),i=n.slice(t);ri(r,e),ri(i,e);let s=0,a=0,l=0;for(;st.line||e.line===t.line&&e.character>t.character?{start:t,end:e}:n}function na(n){let e=Rs(n.range);return e!==n.range?{newText:n.newText,range:e}:n}var zs;(function(n){n.LATEST={textDocument:{completion:{completionItem:{documentationFormat:[se.Markdown,se.PlainText]}},hover:{contentFormat:[se.Markdown,se.PlainText]}}}})(zs||(zs={}));var st;(function(n){n[n.Unknown=0]="Unknown",n[n.File=1]="File",n[n.Directory=2]="Directory",n[n.SymbolicLink=64]="SymbolicLink"})(st||(st={}));var Ms={E:"Edge",FF:"Firefox",S:"Safari",C:"Chrome",IE:"IE",O:"Opera"};function Ts(n){switch(n){case"experimental":return`\u26A0\uFE0F Property is experimental. Be cautious when using it.\uFE0F `;case"nonstandard":return`\u{1F6A8}\uFE0F Property is nonstandard. Avoid using it. `;case"obsolete":return`\u{1F6A8}\uFE0F\uFE0F\uFE0F Property is obsolete. Avoid using it. `;default:return""}}function Ce(n,e,t){let r;if(e?r={kind:"markdown",value:ia(n,t)}:r={kind:"plaintext",value:ra(n,t)},r.value!=="")return r}function tr(n){return n=n.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&"),n.replace(//g,">")}function ra(n,e){if(!n.description||n.description==="")return"";if(typeof n.description!="string")return n.description.value;let t="";if(e?.documentation!==!1){n.status&&(t+=Ts(n.status)),t+=n.description;let r=Ns(n.browsers);r&&(t+=` (`+r+")"),"syntax"in n&&(t+=` Syntax: ${n.syntax}`)}return n.references&&n.references.length>0&&e?.references!==!1&&(t.length>0&&(t+=` `),t+=n.references.map(r=>`${r.name}: ${r.url}`).join(" | ")),t}function ia(n,e){if(!n.description||n.description==="")return"";let t="";if(e?.documentation!==!1){n.status&&(t+=Ts(n.status)),typeof n.description=="string"?t+=tr(n.description):t+=n.description.kind===se.Markdown?n.description.value:tr(n.description.value);let r=Ns(n.browsers);r&&(t+=` (`+tr(r)+")"),"syntax"in n&&n.syntax&&(t+=` Syntax: ${tr(n.syntax)}`)}return n.references&&n.references.length>0&&e?.references!==!1&&(t.length>0&&(t+=` `),t+=n.references.map(r=>`[${r.name}](${r.url})`).join(" | ")),t}function Ns(n=[]){return n.length===0?null:n.map(e=>{let t="",r=e.match(/([A-Z]+)(\d+)?/),i=r[1],s=r[2];return i in Ms&&(t+=Ms[i]),s&&(t+=" "+s),t}).join(", ")}var sa=/(^#([0-9A-F]{3}){1,2}$)|(^#([0-9A-F]{4}){1,2}$)/i,Ws=[{label:"rgb",func:"rgb($red, $green, $blue)",insertText:"rgb(${1:red}, ${2:green}, ${3:blue})",desc:p("Creates a Color from red, green, and blue values.")},{label:"rgba",func:"rgba($red, $green, $blue, $alpha)",insertText:"rgba(${1:red}, ${2:green}, ${3:blue}, ${4:alpha})",desc:p("Creates a Color from red, green, blue, and alpha values.")},{label:"rgb relative",func:"rgb(from $color $red $green $blue)",insertText:"rgb(from ${1:color} ${2:r} ${3:g} ${4:b})",desc:p("Creates a Color from the red, green, and blue values of another Color.")},{label:"hsl",func:"hsl($hue, $saturation, $lightness)",insertText:"hsl(${1:hue}, ${2:saturation}, ${3:lightness})",desc:p("Creates a Color from hue, saturation, and lightness values.")},{label:"hsla",func:"hsla($hue, $saturation, $lightness, $alpha)",insertText:"hsla(${1:hue}, ${2:saturation}, ${3:lightness}, ${4:alpha})",desc:p("Creates a Color from hue, saturation, lightness, and alpha values.")},{label:"hsl relative",func:"hsl(from $color $hue $saturation $lightness)",insertText:"hsl(from ${1:color} ${2:h} ${3:s} ${4:l})",desc:p("Creates a Color from the hue, saturation, and lightness values of another Color.")},{label:"hwb",func:"hwb($hue $white $black)",insertText:"hwb(${1:hue} ${2:white} ${3:black})",desc:p("Creates a Color from hue, white, and black values.")},{label:"hwb relative",func:"hwb(from $color $hue $white $black)",insertText:"hwb(from ${1:color} ${2:h} ${3:w} ${4:b})",desc:p("Creates a Color from the hue, white, and black values of another Color.")},{label:"lab",func:"lab($lightness $a $b)",insertText:"lab(${1:lightness} ${2:a} ${3:b})",desc:p("Creates a Color from lightness, a, and b values.")},{label:"lab relative",func:"lab(from $color $lightness $a $b)",insertText:"lab(from ${1:color} ${2:l} ${3:a} ${4:b})",desc:p("Creates a Color from the lightness, a, and b values of another Color.")},{label:"oklab",func:"oklab($lightness $a $b)",insertText:"oklab(${1:lightness} ${2:a} ${3:b})",desc:p("Creates a Color from lightness, a, and b values.")},{label:"oklab relative",func:"oklab(from $color $lightness $a $b)",insertText:"oklab(from ${1:color} ${2:l} ${3:a} ${4:b})",desc:p("Creates a Color from the lightness, a, and b values of another Color.")},{label:"lch",func:"lch($lightness $chroma $hue)",insertText:"lch(${1:lightness} ${2:chroma} ${3:hue})",desc:p("Creates a Color from lightness, chroma, and hue values.")},{label:"lch relative",func:"lch(from $color $lightness $chroma $hue)",insertText:"lch(from ${1:color} ${2:l} ${3:c} ${4:h})",desc:p("Creates a Color from the lightness, chroma, and hue values of another Color.")},{label:"oklch",func:"oklch($lightness $chroma $hue)",insertText:"oklch(${1:lightness} ${2:chroma} ${3:hue})",desc:p("Creates a Color from lightness, chroma, and hue values.")},{label:"oklch relative",func:"oklch(from $color $lightness $chroma $hue)",insertText:"oklch(from ${1:color} ${2:l} ${3:c} ${4:h})",desc:p("Creates a Color from the lightness, chroma, and hue values of another Color.")},{label:"color",func:"color($color-space $red $green $blue)",insertText:"color(${1|srgb,srgb-linear,display-p3,a98-rgb,prophoto-rgb,rec2020,xyx,xyz-d50,xyz-d65|} ${2:red} ${3:green} ${4:blue})",desc:p("Creates a Color in a specific color space from red, green, and blue values.")},{label:"color relative",func:"color(from $color $color-space $red $green $blue)",insertText:"color(from ${1:color} ${2|srgb,srgb-linear,display-p3,a98-rgb,prophoto-rgb,rec2020,xyx,xyz-d50,xyz-d65|} ${3:r} ${4:g} ${5:b})",desc:p("Creates a Color in a specific color space from the red, green, and blue values of another Color.")},{label:"color-mix",func:"color-mix(in $color-space, $color $percentage, $color $percentage)",insertText:"color-mix(in ${1|srgb,srgb-linear,lab,oklab,xyz,xyz-d50,xyz-d65|}, ${3:color} ${4:percentage}, ${5:color} ${6:percentage})",desc:p("Mix two colors together in a rectangular color space.")},{label:"color-mix hue",func:"color-mix(in $color-space $interpolation-method hue, $color $percentage, $color $percentage)",insertText:"color-mix(in ${1|hsl,hwb,lch,oklch|} ${2|shorter hue,longer hue,increasing hue,decreasing hue|}, ${3:color} ${4:percentage}, ${5:color} ${6:percentage})",desc:p("Mix two colors together in a polar color space.")}],oa=/^(rgb|rgba|hsl|hsla|hwb)$/i,Xt={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rebeccapurple:"#663399",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},aa=new RegExp(`^(${Object.keys(Xt).join("|")})$`,"i"),rr={currentColor:"The value of the 'color' property. The computed value of the 'currentColor' keyword is the computed value of the 'color' property. If the 'currentColor' keyword is set on the 'color' property itself, it is treated as 'color:inherit' at parse time.",transparent:"Fully transparent. This keyword can be considered a shorthand for rgba(0,0,0,0) which is its computed value."},la=new RegExp(`^(${Object.keys(rr).join("|")})$`,"i");function He(n,e){let r=n.getText().match(/^([-+]?[0-9]*\.?[0-9]+)(%?)$/);if(r){r[2]&&(e=100);let i=parseFloat(r[1])/e;if(i>=0&&i<=1)return i}throw new Error}function Os(n){let e=n.getText(),t=e.match(/^([-+]?[0-9]*\.?[0-9]+)(deg|rad|grad|turn)?$/);if(t)switch(t[2]){case"deg":return parseFloat(e)%360;case"rad":return parseFloat(e)*180/Math.PI%360;case"grad":return parseFloat(e)*.9%360;case"turn":return parseFloat(e)*360%360;default:if(typeof t[2]>"u")return parseFloat(e)%360}throw new Error}function Ls(n){let e=n.getName();return e?oa.test(e):!1}function ii(n){return sa.test(n)||aa.test(n)||la.test(n)}var Ps=48,ca=57,da=65;var nr=97,ha=102;function B(n){return n=nr&&n<=ha?n-nr+10:0)}function As(n){if(n[0]!=="#")return null;switch(n.length){case 4:return{red:B(n.charCodeAt(1))*17/255,green:B(n.charCodeAt(2))*17/255,blue:B(n.charCodeAt(3))*17/255,alpha:1};case 5:return{red:B(n.charCodeAt(1))*17/255,green:B(n.charCodeAt(2))*17/255,blue:B(n.charCodeAt(3))*17/255,alpha:B(n.charCodeAt(4))*17/255};case 7:return{red:(B(n.charCodeAt(1))*16+B(n.charCodeAt(2)))/255,green:(B(n.charCodeAt(3))*16+B(n.charCodeAt(4)))/255,blue:(B(n.charCodeAt(5))*16+B(n.charCodeAt(6)))/255,alpha:1};case 9:return{red:(B(n.charCodeAt(1))*16+B(n.charCodeAt(2)))/255,green:(B(n.charCodeAt(3))*16+B(n.charCodeAt(4)))/255,blue:(B(n.charCodeAt(5))*16+B(n.charCodeAt(6)))/255,alpha:(B(n.charCodeAt(7))*16+B(n.charCodeAt(8)))/255}}return null}function $s(n,e,t,r=1){if(n=n/60,e===0)return{red:t,green:t,blue:t,alpha:r};{let i=(l,o,d)=>{for(;d<0;)d+=6;for(;d>=6;)d-=6;return d<1?(o-l)*d+l:d<3?o:d<4?(o-l)*(4-d)+l:l},s=t<=.5?t*(e+1):t+e-t*e,a=t*2-s;return{red:i(a,s,n+2),green:i(a,s,n),blue:i(a,s,n-2),alpha:r}}}function si(n){let e=n.red,t=n.green,r=n.blue,i=n.alpha,s=Math.max(e,t,r),a=Math.min(e,t,r),l=0,o=0,d=(a+s)/2,h=s-a;if(h>0){switch(o=Math.min(d<=.5?h/(2*d):h/(2-2*d),1),s){case e:l=(t-r)/h+(t=1){let o=e/(e+t);return{red:o,green:o,blue:o,alpha:r}}let i=$s(n,1,.5,r),s=i.red;s*=1-e-t,s+=e;let a=i.green;a*=1-e-t,a+=e;let l=i.blue;return l*=1-e-t,l+=e,{red:s,green:a,blue:l,alpha:r}}function Us(n){let e=si(n),t=Math.min(n.red,n.green,n.blue),r=1-Math.max(n.red,n.green,n.blue);return{h:e.h,w:t,b:r,a:e.a}}function Vs(n){if(n.type===m.HexColorValue){let e=n.getText();return As(e)}else if(n.type===m.Function){let e=n,t=e.getName(),r=e.getArguments().getChildren();if(r.length===1){let i=r[0].getChildren();if(i.length===1&&i[0].type===m.Expression&&(r=i[0].getChildren(),r.length===3)){let s=r[2];if(s instanceof qe){let a=s.getLeft(),l=s.getRight(),o=s.getOperator();a&&l&&o&&o.matches("/")&&(r=[r[0],r[1],a,l])}}}if(!t||r.length<3||r.length>4)return null;try{let i=r.length===4?He(r[3],1):1;if(t==="rgb"||t==="rgba")return{red:He(r[0],255),green:He(r[1],255),blue:He(r[2],255),alpha:i};if(t==="hsl"||t==="hsla"){let s=Os(r[0]),a=He(r[1],100),l=He(r[2],100);return $s(s,a,l,i)}else if(t==="hwb"){let s=Os(r[0]),a=He(r[1],100),l=He(r[2],100);return pa(s,a,l,i)}}catch{return null}}else if(n.type===m.Identifier){if(n.parent&&n.parent.type!==m.Term)return null;let e=n.parent;if(e&&e.parent&&e.parent.type===m.BinaryExpression){let i=e.parent;if(i.parent&&i.parent.type===m.ListEntry&&i.parent.key===i)return null}let t=n.getText().toLowerCase();if(t==="none")return null;let r=Xt[t];if(r)return As(r)}return null}var oi={bottom:"Computes to \u2018100%\u2019 for the vertical position if one or two values are given, otherwise specifies the bottom edge as the origin for the next offset.",center:"Computes to \u201850%\u2019 (\u2018left 50%\u2019) for the horizontal position if the horizontal position is not otherwise specified, or \u201850%\u2019 (\u2018top 50%\u2019) for the vertical position if it is.",left:"Computes to \u20180%\u2019 for the horizontal position if one or two values are given, otherwise specifies the left edge as the origin for the next offset.",right:"Computes to \u2018100%\u2019 for the horizontal position if one or two values are given, otherwise specifies the right edge as the origin for the next offset.",top:"Computes to \u20180%\u2019 for the vertical position if one or two values are given, otherwise specifies the top edge as the origin for the next offset."},ai={"no-repeat":"Placed once and not repeated in this direction.",repeat:"Repeated in this direction as often as needed to cover the background painting area.","repeat-x":"Computes to \u2018repeat no-repeat\u2019.","repeat-y":"Computes to \u2018no-repeat repeat\u2019.",round:"Repeated as often as will fit within the background positioning area. If it doesn\u2019t fit a whole number of times, it is rescaled so that it does.",space:"Repeated as often as will fit within the background positioning area without being clipped and then the images are spaced out to fill the area."},li={dashed:"A series of square-ended dashes.",dotted:"A series of round dots.",double:"Two parallel solid lines with some space between them.",groove:"Looks as if it were carved in the canvas.",hidden:"Same as \u2018none\u2019, but has different behavior in the border conflict resolution rules for border-collapsed tables.",inset:"Looks as if the content on the inside of the border is sunken into the canvas.",none:"No border. Color and width are ignored.",outset:"Looks as if the content on the inside of the border is coming out of the canvas.",ridge:"Looks as if it were coming out of the canvas.",solid:"A single line segment."},js=["medium","thick","thin"],ci={"border-box":"The background is painted within (clipped to) the border box.","content-box":"The background is painted within (clipped to) the content box.","padding-box":"The background is painted within (clipped to) the padding box."},di={"margin-box":"Uses the margin box as reference box.","fill-box":"Uses the object bounding box as reference box.","stroke-box":"Uses the stroke bounding box as reference box.","view-box":"Uses the nearest SVG viewport as reference box."},hi={initial:"Represents the value specified as the property\u2019s initial value.",inherit:"Represents the computed value of the property on the element\u2019s parent.",unset:"Acts as either `inherit` or `initial`, depending on whether the property is inherited or not."},pi={"var()":"Evaluates the value of a custom variable.","calc()":"Evaluates an mathematical expression. The following operators can be used: + - * /."},mi={"url()":"Reference an image file by URL","image()":"Provide image fallbacks and annotations.","-webkit-image-set()":"Provide multiple resolutions. Remember to use unprefixed image-set() in addition.","image-set()":"Provide multiple resolutions of an image and const the UA decide which is most appropriate in a given situation.","-moz-element()":"Use an element in the document as an image. Remember to use unprefixed element() in addition.","element()":"Use an element in the document as an image.","cross-fade()":"Indicates the two images to be combined and how far along in the transition the combination is.","-webkit-gradient()":"Deprecated. Use modern linear-gradient() or radial-gradient() instead.","-webkit-linear-gradient()":"Linear gradient. Remember to use unprefixed version in addition.","-moz-linear-gradient()":"Linear gradient. Remember to use unprefixed version in addition.","-o-linear-gradient()":"Linear gradient. Remember to use unprefixed version in addition.","linear-gradient()":"A linear gradient is created by specifying a straight gradient line, and then several colors placed along that line.","-webkit-repeating-linear-gradient()":"Repeating Linear gradient. Remember to use unprefixed version in addition.","-moz-repeating-linear-gradient()":"Repeating Linear gradient. Remember to use unprefixed version in addition.","-o-repeating-linear-gradient()":"Repeating Linear gradient. Remember to use unprefixed version in addition.","repeating-linear-gradient()":"Same as linear-gradient, except the color-stops are repeated infinitely in both directions, with their positions shifted by multiples of the difference between the last specified color-stop\u2019s position and the first specified color-stop\u2019s position.","-webkit-radial-gradient()":"Radial gradient. Remember to use unprefixed version in addition.","-moz-radial-gradient()":"Radial gradient. Remember to use unprefixed version in addition.","radial-gradient()":"Colors emerge from a single point and smoothly spread outward in a circular or elliptical shape.","-webkit-repeating-radial-gradient()":"Repeating radial gradient. Remember to use unprefixed version in addition.","-moz-repeating-radial-gradient()":"Repeating radial gradient. Remember to use unprefixed version in addition.","repeating-radial-gradient()":"Same as radial-gradient, except the color-stops are repeated infinitely in both directions, with their positions shifted by multiples of the difference between the last specified color-stop\u2019s position and the first specified color-stop\u2019s position."},ui={ease:"Equivalent to cubic-bezier(0.25, 0.1, 0.25, 1.0).","ease-in":"Equivalent to cubic-bezier(0.42, 0, 1.0, 1.0).","ease-in-out":"Equivalent to cubic-bezier(0.42, 0, 0.58, 1.0).","ease-out":"Equivalent to cubic-bezier(0, 0, 0.58, 1.0).",linear:"Equivalent to cubic-bezier(0.0, 0.0, 1.0, 1.0).","step-end":"Equivalent to steps(1, end).","step-start":"Equivalent to steps(1, start).","steps()":"The first parameter specifies the number of intervals in the function. The second parameter, which is optional, is either the value \u201Cstart\u201D or \u201Cend\u201D.","cubic-bezier()":"Specifies a cubic-bezier curve. The four values specify points P1 and P2 of the curve as (x1, y1, x2, y2).","cubic-bezier(0.6, -0.28, 0.735, 0.045)":"Ease-in Back. Overshoots.","cubic-bezier(0.68, -0.55, 0.265, 1.55)":"Ease-in-out Back. Overshoots.","cubic-bezier(0.175, 0.885, 0.32, 1.275)":"Ease-out Back. Overshoots.","cubic-bezier(0.6, 0.04, 0.98, 0.335)":"Ease-in Circular. Based on half circle.","cubic-bezier(0.785, 0.135, 0.15, 0.86)":"Ease-in-out Circular. Based on half circle.","cubic-bezier(0.075, 0.82, 0.165, 1)":"Ease-out Circular. Based on half circle.","cubic-bezier(0.55, 0.055, 0.675, 0.19)":"Ease-in Cubic. Based on power of three.","cubic-bezier(0.645, 0.045, 0.355, 1)":"Ease-in-out Cubic. Based on power of three.","cubic-bezier(0.215, 0.610, 0.355, 1)":"Ease-out Cubic. Based on power of three.","cubic-bezier(0.95, 0.05, 0.795, 0.035)":"Ease-in Exponential. Based on two to the power ten.","cubic-bezier(1, 0, 0, 1)":"Ease-in-out Exponential. Based on two to the power ten.","cubic-bezier(0.19, 1, 0.22, 1)":"Ease-out Exponential. Based on two to the power ten.","cubic-bezier(0.47, 0, 0.745, 0.715)":"Ease-in Sine.","cubic-bezier(0.445, 0.05, 0.55, 0.95)":"Ease-in-out Sine.","cubic-bezier(0.39, 0.575, 0.565, 1)":"Ease-out Sine.","cubic-bezier(0.55, 0.085, 0.68, 0.53)":"Ease-in Quadratic. Based on power of two.","cubic-bezier(0.455, 0.03, 0.515, 0.955)":"Ease-in-out Quadratic. Based on power of two.","cubic-bezier(0.25, 0.46, 0.45, 0.94)":"Ease-out Quadratic. Based on power of two.","cubic-bezier(0.895, 0.03, 0.685, 0.22)":"Ease-in Quartic. Based on power of four.","cubic-bezier(0.77, 0, 0.175, 1)":"Ease-in-out Quartic. Based on power of four.","cubic-bezier(0.165, 0.84, 0.44, 1)":"Ease-out Quartic. Based on power of four.","cubic-bezier(0.755, 0.05, 0.855, 0.06)":"Ease-in Quintic. Based on power of five.","cubic-bezier(0.86, 0, 0.07, 1)":"Ease-in-out Quintic. Based on power of five.","cubic-bezier(0.23, 1, 0.320, 1)":"Ease-out Quintic. Based on power of five."},fi={"circle()":"Defines a circle.","ellipse()":"Defines an ellipse.","inset()":"Defines an inset rectangle.","polygon()":"Defines a polygon."},ir={length:["cap","ch","cm","cqb","cqh","cqi","cqmax","cqmin","cqw","dvb","dvh","dvi","dvw","em","ex","ic","in","lh","lvb","lvh","lvi","lvw","mm","pc","pt","px","q","rcap","rch","rem","rex","ric","rlh","svb","svh","svi","svw","vb","vh","vi","vmax","vmin","vw"],angle:["deg","rad","grad","turn"],time:["ms","s"],frequency:["Hz","kHz"],resolution:["dpi","dpcm","dppx"],percentage:["%","fr"]},Bs=["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","const","video","wbr"],qs=["circle","clipPath","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","foreignObject","g","hatch","hatchpath","image","line","linearGradient","marker","mask","mesh","meshpatch","meshrow","metadata","mpath","path","pattern","polygon","polyline","radialGradient","rect","set","solidcolor","stop","svg","switch","symbol","text","textPath","tspan","use","view"],Ks=["@bottom-center","@bottom-left","@bottom-left-corner","@bottom-right","@bottom-right-corner","@left-bottom","@left-middle","@left-top","@right-bottom","@right-middle","@right-top","@top-center","@top-left","@top-left-corner","@top-right","@top-right-corner"];function Yt(n){return Object.keys(n).map(e=>n[e])}function ie(n){return typeof n<"u"}var ke=class{constructor(e=new ce){this.keyframeRegex=/^@(\-(webkit|ms|moz|o)\-)?keyframes$/i,this.scanner=e,this.token={type:c.EOF,offset:-1,len:0,text:""},this.prevToken=void 0}peekIdent(e){return c.Ident===this.token.type&&e.length===this.token.text.length&&e===this.token.text.toLowerCase()}peekKeyword(e){return c.AtKeyword===this.token.type&&e.length===this.token.text.length&&e===this.token.text.toLowerCase()}peekDelim(e){return c.Delim===this.token.type&&e===this.token.text}peek(e){return e===this.token.type}peekOne(...e){return e.indexOf(this.token.type)!==-1}peekRegExp(e,t){return e!==this.token.type?!1:t.test(this.token.text)}hasWhitespace(){return!!this.prevToken&&this.prevToken.offset+this.prevToken.len!==this.token.offset}consumeToken(){this.prevToken=this.token,this.token=this.scanner.scan()}acceptUnicodeRange(){let e=this.scanner.tryScanUnicode();return e?(this.prevToken=e,this.token=this.scanner.scan(),!0):!1}mark(){return{prev:this.prevToken,curr:this.token,pos:this.scanner.pos()}}restoreAtMark(e){this.prevToken=e.prev,this.token=e.curr,this.scanner.goBackTo(e.pos)}try(e){let t=this.mark(),r=e();return r||(this.restoreAtMark(t),null)}acceptOneKeyword(e){if(c.AtKeyword===this.token.type){for(let t of e)if(t.length===this.token.text.length&&t===this.token.text.toLowerCase())return this.consumeToken(),!0}return!1}accept(e){return e===this.token.type?(this.consumeToken(),!0):!1}acceptIdent(e){return this.peekIdent(e)?(this.consumeToken(),!0):!1}acceptKeyword(e){return this.peekKeyword(e)?(this.consumeToken(),!0):!1}acceptDelim(e){return this.peekDelim(e)?(this.consumeToken(),!0):!1}acceptRegexp(e){return e.test(this.token.text)?(this.consumeToken(),!0):!1}_parseRegexp(e){let t=this.createNode(m.Identifier);do;while(this.acceptRegexp(e));return this.finish(t)}acceptUnquotedString(){let e=this.scanner.pos();this.scanner.goBackTo(this.token.offset);let t=this.scanner.scanUnquotedString();return t?(this.token=t,this.consumeToken(),!0):(this.scanner.goBackTo(e),!1)}resync(e,t){for(;;){if(e&&e.indexOf(this.token.type)!==-1)return this.consumeToken(),!0;if(t&&t.indexOf(this.token.type)!==-1)return!0;if(this.token.type===c.EOF)return!1;this.token=this.scanner.scan()}}createNode(e){return new x(this.token.offset,this.token.len,e)}create(e){return new e(this.token.offset,this.token.len)}finish(e,t,r,i){if(!(e instanceof J)&&(t&&this.markError(e,t,r,i),this.prevToken)){let s=this.prevToken.offset+this.prevToken.len;e.length=s>e.offset?s-e.offset:0}return e}markError(e,t,r,i){this.token!==this.lastErrorToken&&(e.addIssue(new wt(e,t,ee.Error,void 0,this.token.offset,this.token.len)),this.lastErrorToken=this.token),(r||i)&&this.resync(r,i)}parseStylesheet(e){let t=e.version,r=e.getText(),i=(s,a)=>{if(e.version!==t)throw new Error("Underlying model has changed, AST is no longer valid");return r.substr(s,a)};return this.internalParse(r,this._parseStylesheet,i)}internalParse(e,t,r){this.scanner.setSource(e),this.token=this.scanner.scan();let i=t.bind(this)();return i&&(r?i.textProvider=r:i.textProvider=(s,a)=>e.substr(s,a)),i}_parseStylesheet(){let e=this.create(bn);for(;e.addChild(this._parseStylesheetStart()););let t=!1;do{let r=!1;do{r=!1;let i=this._parseStylesheetStatement();for(i&&(e.addChild(i),r=!0,t=!1,!this.peek(c.EOF)&&this._needsSemicolonAfter(i)&&!this.accept(c.SemiColon)&&this.markError(e,f.SemiColonExpected));this.accept(c.SemiColon)||this.accept(c.CDO)||this.accept(c.CDC);)r=!0,t=!1}while(r);if(this.peek(c.EOF))break;t||(this.peek(c.AtKeyword)?this.markError(e,f.UnknownAtRule):this.markError(e,f.RuleOrSelectorExpected),t=!0),this.consumeToken()}while(!this.peek(c.EOF));return this.finish(e)}_parseStylesheetStart(){return this._parseCharset()}_parseStylesheetStatement(e=!1){return this.peek(c.AtKeyword)?this._parseStylesheetAtStatement(e):this._parseRuleset(e)}_parseStylesheetAtStatement(e=!1){return this._parseImport()||this._parseMedia(e)||this._parsePage()||this._parseFontFace()||this._parseKeyframe()||this._parseSupports(e)||this._parseLayer(e)||this._parsePropertyAtRule()||this._parseViewPort()||this._parseNamespace()||this._parseDocument()||this._parseContainer(e)||this._parseUnknownAtRule()}_tryParseRuleset(e){let t=this.mark();if(this._parseSelector(e)){for(;this.accept(c.Comma)&&this._parseSelector(e););if(this.accept(c.CurlyL))return this.restoreAtMark(t),this._parseRuleset(e)}return this.restoreAtMark(t),null}_parseRuleset(e=!1){let t=this.create(ae),r=t.getSelectors();if(!r.addChild(this._parseSelector(e)))return null;for(;this.accept(c.Comma);)if(!r.addChild(this._parseSelector(e)))return this.finish(t,f.SelectorExpected);return this._parseBody(t,this._parseRuleSetDeclaration.bind(this))}_parseRuleSetDeclarationAtStatement(){return this._parseMedia(!0)||this._parseSupports(!0)||this._parseLayer(!0)||this._parseContainer(!0)||this._parseUnknownAtRule()}_parseRuleSetDeclaration(){return this.peek(c.AtKeyword)?this._parseRuleSetDeclarationAtStatement():this.peek(c.Ident)?this._tryParseRuleset(!0)||this._parseDeclaration():this._parseRuleset(!0)}_needsSemicolonAfter(e){switch(e.type){case m.Keyframe:case m.ViewPort:case m.Media:case m.Ruleset:case m.Namespace:case m.If:case m.For:case m.Each:case m.While:case m.MixinDeclaration:case m.FunctionDeclaration:case m.MixinContentDeclaration:return!1;case m.ExtendsReference:case m.MixinContentReference:case m.ReturnStatement:case m.MediaQuery:case m.Debug:case m.Import:case m.AtApplyRule:case m.CustomPropertyDeclaration:return!0;case m.VariableDeclaration:return e.needsSemicolon;case m.MixinReference:return!e.getContent();case m.Declaration:return!e.getNestedProperties()}return!1}_parseDeclarations(e){let t=this.create(Ze);if(!this.accept(c.CurlyL))return null;let r=e();for(;t.addChild(r)&&!this.peek(c.CurlyR);){if(this._needsSemicolonAfter(r)&&!this.accept(c.SemiColon))return this.finish(t,f.SemiColonExpected,[c.SemiColon,c.CurlyR]);for(r&&this.prevToken&&this.prevToken.type===c.SemiColon&&(r.semicolonPosition=this.prevToken.offset);this.accept(c.SemiColon););r=e()}return this.accept(c.CurlyR)?this.finish(t):this.finish(t,f.RightCurlyExpected,[c.CurlyR,c.SemiColon])}_parseBody(e,t){return e.setDeclarations(this._parseDeclarations(t))?this.finish(e):this.finish(e,f.LeftCurlyExpected,[c.CurlyR,c.SemiColon])}_parseSelector(e){let t=this.create(de),r=!1;for(e&&(r=t.addChild(this._parseCombinator()));t.addChild(this._parseSimpleSelector());)r=!0,t.addChild(this._parseCombinator());return r?this.finish(t):null}_parseDeclaration(e){let t=this._tryParseCustomPropertyDeclaration(e);if(t)return t;let r=this.create(Q);return r.setProperty(this._parseProperty())?this.accept(c.Colon)?(this.prevToken&&(r.colonPosition=this.prevToken.offset),r.setValue(this._parseExpr())?(r.addChild(this._parsePrio()),this.peek(c.SemiColon)&&(r.semicolonPosition=this.token.offset),this.finish(r)):this.finish(r,f.PropertyValueExpected)):this.finish(r,f.ColonExpected,[c.Colon],e||[c.SemiColon]):null}_tryParseCustomPropertyDeclaration(e){if(!this.peekRegExp(c.Ident,/^--/))return null;let t=this.create(vn);if(!t.setProperty(this._parseProperty()))return null;if(!this.accept(c.Colon))return this.finish(t,f.ColonExpected,[c.Colon]);this.prevToken&&(t.colonPosition=this.prevToken.offset);let r=this.mark();if(this.peek(c.CurlyL)){let s=this.create(wn),a=this._parseDeclarations(this._parseRuleSetDeclaration.bind(this));if(s.setDeclarations(a)&&!a.isErroneous(!0)&&(s.addChild(this._parsePrio()),this.peek(c.SemiColon)))return this.finish(s),t.setPropertySet(s),t.semicolonPosition=this.token.offset,this.finish(t);this.restoreAtMark(r)}let i=this._parseExpr();return i&&!i.isErroneous(!0)&&(this._parsePrio(),this.peekOne(...e||[],c.SemiColon,c.EOF))?(t.setValue(i),this.peek(c.SemiColon)&&(t.semicolonPosition=this.token.offset),this.finish(t)):(this.restoreAtMark(r),t.addChild(this._parseCustomPropertyValue(e)),t.addChild(this._parsePrio()),ie(t.colonPosition)&&this.token.offset===t.colonPosition+1?this.finish(t,f.PropertyValueExpected):this.finish(t))}_parseCustomPropertyValue(e=[c.CurlyR]){let t=this.create(x),r=()=>s===0&&a===0&&l===0,i=()=>e.indexOf(this.token.type)!==-1,s=0,a=0,l=0;e:for(;;){switch(this.token.type){case c.SemiColon:if(r())break e;break;case c.Exclamation:if(r())break e;break;case c.CurlyL:s++;break;case c.CurlyR:if(s--,s<0){if(i()&&a===0&&l===0)break e;return this.finish(t,f.LeftCurlyExpected)}break;case c.ParenthesisL:a++;break;case c.ParenthesisR:if(a--,a<0){if(i()&&l===0&&s===0)break e;return this.finish(t,f.LeftParenthesisExpected)}break;case c.BracketL:l++;break;case c.BracketR:if(l--,l<0)return this.finish(t,f.LeftSquareBracketExpected);break;case c.BadString:break e;case c.EOF:let o=f.RightCurlyExpected;return l>0?o=f.RightSquareBracketExpected:a>0&&(o=f.RightParenthesisExpected),this.finish(t,o)}this.consumeToken()}return this.finish(t)}_tryToParseDeclaration(e){let t=this.mark();return this._parseProperty()&&this.accept(c.Colon)?(this.restoreAtMark(t),this._parseDeclaration(e)):(this.restoreAtMark(t),null)}_parseProperty(){let e=this.create(Ve),t=this.mark();return(this.acceptDelim("*")||this.acceptDelim("_"))&&this.hasWhitespace()?(this.restoreAtMark(t),null):e.setIdentifier(this._parsePropertyIdentifier())?this.finish(e):null}_parsePropertyIdentifier(){return this._parseIdent()}_parseCharset(){if(!this.peek(c.Charset))return null;let e=this.create(x);return this.consumeToken(),this.accept(c.String)?this.accept(c.SemiColon)?this.finish(e):this.finish(e,f.SemiColonExpected):this.finish(e,f.IdentifierExpected)}_parseImport(){if(!this.peekKeyword("@import"))return null;let e=this.create(je);return this.consumeToken(),!e.addChild(this._parseURILiteral())&&!e.addChild(this._parseStringLiteral())?this.finish(e,f.URIOrStringExpected):this._completeParseImport(e)}_completeParseImport(e){if(this.acceptIdent("layer")&&this.accept(c.ParenthesisL)){if(!e.addChild(this._parseLayerName()))return this.finish(e,f.IdentifierExpected,[c.SemiColon]);if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[c.ParenthesisR],[])}return this.acceptIdent("supports")&&this.accept(c.ParenthesisL)&&(e.addChild(this._tryToParseDeclaration()||this._parseSupportsCondition()),!this.accept(c.ParenthesisR))?this.finish(e,f.RightParenthesisExpected,[c.ParenthesisR],[]):(!this.peek(c.SemiColon)&&!this.peek(c.EOF)&&e.setMedialist(this._parseMediaQueryList()),this.finish(e))}_parseNamespace(){if(!this.peekKeyword("@namespace"))return null;let e=this.create(Rn);return this.consumeToken(),!e.addChild(this._parseURILiteral())&&(e.addChild(this._parseIdent()),!e.addChild(this._parseURILiteral())&&!e.addChild(this._parseStringLiteral()))?this.finish(e,f.URIExpected,[c.SemiColon]):this.accept(c.SemiColon)?this.finish(e):this.finish(e,f.SemiColonExpected)}_parseFontFace(){if(!this.peekKeyword("@font-face"))return null;let e=this.create(pt);return this.consumeToken(),this._parseBody(e,this._parseRuleSetDeclaration.bind(this))}_parseViewPort(){if(!this.peekKeyword("@-ms-viewport")&&!this.peekKeyword("@-o-viewport")&&!this.peekKeyword("@viewport"))return null;let e=this.create(Fn);return this.consumeToken(),this._parseBody(e,this._parseRuleSetDeclaration.bind(this))}_parseKeyframe(){if(!this.peekRegExp(c.AtKeyword,this.keyframeRegex))return null;let e=this.create(mt),t=this.create(x);return this.consumeToken(),e.setKeyword(this.finish(t)),t.matches("@-ms-keyframes")&&this.markError(t,f.UnknownKeyword),e.setIdentifier(this._parseKeyframeIdent())?this._parseBody(e,this._parseKeyframeSelector.bind(this)):this.finish(e,f.IdentifierExpected,[c.CurlyR])}_parseKeyframeIdent(){return this._parseIdent([z.Keyframe])}_parseKeyframeSelector(){let e=this.create(Vt),t=!1;if(e.addChild(this._parseIdent())&&(t=!0),this.accept(c.Percentage)&&(t=!0),!t)return null;for(;this.accept(c.Comma);)if(t=!1,e.addChild(this._parseIdent())&&(t=!0),this.accept(c.Percentage)&&(t=!0),!t)return this.finish(e,f.PercentageExpected);return this._parseBody(e,this._parseRuleSetDeclaration.bind(this))}_tryParseKeyframeSelector(){let e=this.create(Vt),t=this.mark(),r=!1;if(e.addChild(this._parseIdent())&&(r=!0),this.accept(c.Percentage)&&(r=!0),!r)return null;for(;this.accept(c.Comma);)if(r=!1,e.addChild(this._parseIdent())&&(r=!0),this.accept(c.Percentage)&&(r=!0),!r)return this.restoreAtMark(t),null;return this.peek(c.CurlyL)?this._parseBody(e,this._parseRuleSetDeclaration.bind(this)):(this.restoreAtMark(t),null)}_parsePropertyAtRule(){if(!this.peekKeyword("@property"))return null;let e=this.create(Mn);return this.consumeToken(),!this.peekRegExp(c.Ident,/^--/)||!e.setName(this._parseIdent([z.Property]))?this.finish(e,f.IdentifierExpected):this._parseBody(e,this._parseDeclaration.bind(this))}_parseLayer(e=!1){if(!this.peekKeyword("@layer"))return null;let t=this.create(zn);this.consumeToken();let r=this._parseLayerNameList();return r&&t.setNames(r),(!r||r.getChildren().length===1)&&this.peek(c.CurlyL)?this._parseBody(t,this._parseLayerDeclaration.bind(this,e)):this.accept(c.SemiColon)?this.finish(t):this.finish(t,f.SemiColonExpected)}_parseLayerDeclaration(e=!1){return e?this._tryParseRuleset(!0)||this._tryToParseDeclaration()||this._parseStylesheetStatement(!0):this._parseStylesheetStatement(!1)}_parseLayerNameList(){let e=this.createNode(m.LayerNameList);if(!e.addChild(this._parseLayerName()))return null;for(;this.accept(c.Comma);)if(!e.addChild(this._parseLayerName()))return this.finish(e,f.IdentifierExpected);return this.finish(e)}_parseLayerName(){let e=this.createNode(m.LayerName);if(!e.addChild(this._parseIdent()))return null;for(;!this.hasWhitespace()&&this.acceptDelim(".");)if(this.hasWhitespace()||!e.addChild(this._parseIdent()))return this.finish(e,f.IdentifierExpected);return this.finish(e)}_parseSupports(e=!1){if(!this.peekKeyword("@supports"))return null;let t=this.create(et);return this.consumeToken(),t.addChild(this._parseSupportsCondition()),this._parseBody(t,this._parseSupportsDeclaration.bind(this,e))}_parseSupportsDeclaration(e=!1){return e?this._tryParseRuleset(!0)||this._tryToParseDeclaration()||this._parseStylesheetStatement(!0):this._parseStylesheetStatement(!1)}_parseSupportsCondition(){let e=this.create(Re);if(this.acceptIdent("not"))e.addChild(this._parseSupportsConditionInParens());else if(e.addChild(this._parseSupportsConditionInParens()),this.peekRegExp(c.Ident,/^(and|or)$/i)){let t=this.token.text.toLowerCase();for(;this.acceptIdent(t);)e.addChild(this._parseSupportsConditionInParens())}return this.finish(e)}_parseSupportsConditionInParens(){let e=this.create(Re);if(this.accept(c.ParenthesisL))return this.prevToken&&(e.lParent=this.prevToken.offset),!e.addChild(this._tryToParseDeclaration([c.ParenthesisR]))&&!this._parseSupportsCondition()?this.finish(e,f.ConditionExpected):this.accept(c.ParenthesisR)?(this.prevToken&&(e.rParent=this.prevToken.offset),this.finish(e)):this.finish(e,f.RightParenthesisExpected,[c.ParenthesisR],[]);if(this.peek(c.Ident)){let t=this.mark();if(this.consumeToken(),!this.hasWhitespace()&&this.accept(c.ParenthesisL)){let r=1;for(;this.token.type!==c.EOF&&r!==0;)this.token.type===c.ParenthesisL?r++:this.token.type===c.ParenthesisR&&r--,this.consumeToken();return this.finish(e)}else this.restoreAtMark(t)}return this.finish(e,f.LeftParenthesisExpected,[],[c.ParenthesisL])}_parseMediaDeclaration(e=!1){return e?this._tryParseRuleset(!0)||this._tryToParseDeclaration()||this._parseStylesheetStatement(!0):this._parseStylesheetStatement(!1)}_parseMedia(e=!1){if(!this.peekKeyword("@media"))return null;let t=this.create(Be);return this.consumeToken(),t.addChild(this._parseMediaQueryList())?this._parseBody(t,this._parseMediaDeclaration.bind(this,e)):this.finish(t,f.MediaQueryExpected)}_parseMediaQueryList(){let e=this.create(ut);if(!e.addChild(this._parseMediaQuery()))return this.finish(e,f.MediaQueryExpected);for(;this.accept(c.Comma);)if(!e.addChild(this._parseMediaQuery()))return this.finish(e,f.MediaQueryExpected);return this.finish(e)}_parseMediaQuery(){let e=this.create(ft),t=this.mark();if(this.acceptIdent("not"),this.peek(c.ParenthesisL))this.restoreAtMark(t),e.addChild(this._parseMediaCondition());else{if(this.acceptIdent("only"),!e.addChild(this._parseIdent()))return null;this.acceptIdent("and")&&e.addChild(this._parseMediaCondition())}return this.finish(e)}_parseRatio(){let e=this.mark(),t=this.create(Un);return this._parseNumeric()?this.acceptDelim("/")?this._parseNumeric()?this.finish(t):this.finish(t,f.NumberExpected):(this.restoreAtMark(e),null):null}_parseMediaCondition(){let e=this.create(On);this.acceptIdent("not");let t=!0;for(;t;){if(!this.accept(c.ParenthesisL))return this.finish(e,f.LeftParenthesisExpected,[],[c.CurlyL]);if(this.peek(c.ParenthesisL)||this.peekIdent("not")?e.addChild(this._parseMediaCondition()):e.addChild(this._parseMediaFeature()),!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[],[c.CurlyL]);t=this.acceptIdent("and")||this.acceptIdent("or")}return this.finish(e)}_parseMediaFeature(){let e=[c.ParenthesisR],t=this.create(Pn);if(t.addChild(this._parseMediaFeatureName())){if(this.accept(c.Colon)){if(!t.addChild(this._parseMediaFeatureValue()))return this.finish(t,f.TermExpected,[],e)}else if(this._parseMediaFeatureRangeOperator()){if(!t.addChild(this._parseMediaFeatureValue()))return this.finish(t,f.TermExpected,[],e);if(this._parseMediaFeatureRangeOperator()&&!t.addChild(this._parseMediaFeatureValue()))return this.finish(t,f.TermExpected,[],e)}}else if(t.addChild(this._parseMediaFeatureValue())){if(!this._parseMediaFeatureRangeOperator())return this.finish(t,f.OperatorExpected,[],e);if(!t.addChild(this._parseMediaFeatureName()))return this.finish(t,f.IdentifierExpected,[],e);if(this._parseMediaFeatureRangeOperator()&&!t.addChild(this._parseMediaFeatureValue()))return this.finish(t,f.TermExpected,[],e)}else return this.finish(t,f.IdentifierExpected,[],e);return this.finish(t)}_parseMediaFeatureRangeOperator(){return this.acceptDelim("<")||this.acceptDelim(">")?(this.hasWhitespace()||this.acceptDelim("="),!0):!!this.acceptDelim("=")}_parseMediaFeatureName(){return this._parseIdent()}_parseMediaFeatureValue(){return this._parseRatio()||this._parseTermExpression()}_parseMedium(){let e=this.create(x);return e.addChild(this._parseIdent())?this.finish(e):null}_parsePageDeclaration(){return this._parsePageMarginBox()||this._parseRuleSetDeclaration()}_parsePage(){if(!this.peekKeyword("@page"))return null;let e=this.create(An);if(this.consumeToken(),e.addChild(this._parsePageSelector())){for(;this.accept(c.Comma);)if(!e.addChild(this._parsePageSelector()))return this.finish(e,f.IdentifierExpected)}return this._parseBody(e,this._parsePageDeclaration.bind(this))}_parsePageMarginBox(){if(!this.peek(c.AtKeyword))return null;let e=this.create(Wn);return this.acceptOneKeyword(Ks)||this.markError(e,f.UnknownAtRule,[],[c.CurlyL]),this._parseBody(e,this._parseRuleSetDeclaration.bind(this))}_parsePageSelector(){if(!this.peek(c.Ident)&&!this.peek(c.Colon))return null;let e=this.create(x);return e.addChild(this._parseIdent()),this.accept(c.Colon)&&!e.addChild(this._parseIdent())?this.finish(e,f.IdentifierExpected):this.finish(e)}_parseDocument(){if(!this.peekKeyword("@-moz-document"))return null;let e=this.create(Tn);return this.consumeToken(),this.resync([],[c.CurlyL]),this._parseBody(e,this._parseStylesheetStatement.bind(this))}_parseContainerDeclaration(e=!1){return e?this._tryParseRuleset(!0)||this._tryToParseDeclaration()||this._parseStylesheetStatement(!0):this._parseStylesheetStatement(!1)}_parseContainer(e=!1){if(!this.peekKeyword("@container"))return null;let t=this.create(Nn);return this.consumeToken(),t.addChild(this._parseIdent()),t.addChild(this._parseContainerQuery()),this._parseBody(t,this._parseContainerDeclaration.bind(this,e))}_parseContainerQuery(){let e=this.create(x);if(this.acceptIdent("not"))e.addChild(this._parseContainerQueryInParens());else if(e.addChild(this._parseContainerQueryInParens()),this.peekIdent("and"))for(;this.acceptIdent("and");)e.addChild(this._parseContainerQueryInParens());else if(this.peekIdent("or"))for(;this.acceptIdent("or");)e.addChild(this._parseContainerQueryInParens());return this.finish(e)}_parseContainerQueryInParens(){let e=this.create(x);if(this.accept(c.ParenthesisL)){if(this.peekIdent("not")||this.peek(c.ParenthesisL)?e.addChild(this._parseContainerQuery()):e.addChild(this._parseMediaFeature()),!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[],[c.CurlyL])}else if(this.acceptIdent("style")){if(this.hasWhitespace()||!this.accept(c.ParenthesisL))return this.finish(e,f.LeftParenthesisExpected,[],[c.CurlyL]);if(e.addChild(this._parseStyleQuery()),!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[],[c.CurlyL])}else return this.finish(e,f.LeftParenthesisExpected,[],[c.CurlyL]);return this.finish(e)}_parseStyleQuery(){let e=this.create(x);if(this.acceptIdent("not"))e.addChild(this._parseStyleInParens());else if(this.peek(c.ParenthesisL)){if(e.addChild(this._parseStyleInParens()),this.peekIdent("and"))for(;this.acceptIdent("and");)e.addChild(this._parseStyleInParens());else if(this.peekIdent("or"))for(;this.acceptIdent("or");)e.addChild(this._parseStyleInParens())}else e.addChild(this._parseDeclaration([c.ParenthesisR]));return this.finish(e)}_parseStyleInParens(){let e=this.create(x);if(this.accept(c.ParenthesisL)){if(e.addChild(this._parseStyleQuery()),!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[],[c.CurlyL])}else return this.finish(e,f.LeftParenthesisExpected,[],[c.CurlyL]);return this.finish(e)}_parseUnknownAtRule(){if(!this.peek(c.AtKeyword))return null;let e=this.create(bt);e.addChild(this._parseUnknownAtRuleName());let t=()=>i===0&&s===0&&a===0,r=0,i=0,s=0,a=0;e:for(;;){switch(this.token.type){case c.SemiColon:if(t())break e;break;case c.EOF:return i>0?this.finish(e,f.RightCurlyExpected):a>0?this.finish(e,f.RightSquareBracketExpected):s>0?this.finish(e,f.RightParenthesisExpected):this.finish(e);case c.CurlyL:r++,i++;break;case c.CurlyR:if(i--,r>0&&i===0){if(this.consumeToken(),a>0)return this.finish(e,f.RightSquareBracketExpected);if(s>0)return this.finish(e,f.RightParenthesisExpected);break e}if(i<0){if(s===0&&a===0)break e;return this.finish(e,f.LeftCurlyExpected)}break;case c.ParenthesisL:s++;break;case c.ParenthesisR:if(s--,s<0)return this.finish(e,f.LeftParenthesisExpected);break;case c.BracketL:a++;break;case c.BracketR:if(a--,a<0)return this.finish(e,f.LeftSquareBracketExpected);break}this.consumeToken()}return e}_parseUnknownAtRuleName(){let e=this.create(x);return this.accept(c.AtKeyword)?this.finish(e):e}_parseOperator(){if(this.peekDelim("/")||this.peekDelim("*")||this.peekDelim("+")||this.peekDelim("-")||this.peek(c.Dashmatch)||this.peek(c.Includes)||this.peek(c.SubstringOperator)||this.peek(c.PrefixOperator)||this.peek(c.SuffixOperator)||this.peekDelim("=")){let e=this.createNode(m.Operator);return this.consumeToken(),this.finish(e)}else return null}_parseUnaryOperator(){if(!this.peekDelim("+")&&!this.peekDelim("-"))return null;let e=this.create(x);return this.consumeToken(),this.finish(e)}_parseCombinator(){if(this.peekDelim(">")){let e=this.create(x);this.consumeToken();let t=this.mark();if(!this.hasWhitespace()&&this.acceptDelim(">")){if(!this.hasWhitespace()&&this.acceptDelim(">"))return e.type=m.SelectorCombinatorShadowPiercingDescendant,this.finish(e);this.restoreAtMark(t)}return e.type=m.SelectorCombinatorParent,this.finish(e)}else if(this.peekDelim("+")){let e=this.create(x);return this.consumeToken(),e.type=m.SelectorCombinatorSibling,this.finish(e)}else if(this.peekDelim("~")){let e=this.create(x);return this.consumeToken(),e.type=m.SelectorCombinatorAllSiblings,this.finish(e)}else if(this.peekDelim("/")){let e=this.create(x);this.consumeToken();let t=this.mark();if(!this.hasWhitespace()&&this.acceptIdent("deep")&&!this.hasWhitespace()&&this.acceptDelim("/"))return e.type=m.SelectorCombinatorShadowPiercingDescendant,this.finish(e);this.restoreAtMark(t)}return null}_parseSimpleSelector(){let e=this.create(he),t=0;for(e.addChild(this._parseElementName()||this._parseNestingSelector())&&t++;(t===0||!this.hasWhitespace())&&e.addChild(this._parseSimpleSelectorBody());)t++;return t>0?this.finish(e):null}_parseNestingSelector(){if(this.peekDelim("&")){let e=this.createNode(m.SelectorCombinator);return this.consumeToken(),this.finish(e)}return null}_parseSimpleSelectorBody(){return this._parsePseudo()||this._parseHash()||this._parseClass()||this._parseAttrib()}_parseSelectorIdent(){return this._parseIdent()}_parseHash(){if(!this.peek(c.Hash)&&!this.peekDelim("#"))return null;let e=this.createNode(m.IdentifierSelector);if(this.acceptDelim("#")){if(this.hasWhitespace()||!e.addChild(this._parseSelectorIdent()))return this.finish(e,f.IdentifierExpected)}else this.consumeToken();return this.finish(e)}_parseClass(){if(!this.peekDelim("."))return null;let e=this.createNode(m.ClassSelector);return this.consumeToken(),this.hasWhitespace()||!e.addChild(this._parseSelectorIdent())?this.finish(e,f.IdentifierExpected):this.finish(e)}_parseElementName(){let e=this.mark(),t=this.createNode(m.ElementNameSelector);return t.addChild(this._parseNamespacePrefix()),!t.addChild(this._parseSelectorIdent())&&!this.acceptDelim("*")?(this.restoreAtMark(e),null):this.finish(t)}_parseNamespacePrefix(){let e=this.mark(),t=this.createNode(m.NamespacePrefix);return!t.addChild(this._parseIdent())&&this.acceptDelim("*"),this.acceptDelim("|")?this.finish(t):(this.restoreAtMark(e),null)}_parseAttrib(){if(!this.peek(c.BracketL))return null;let e=this.create($n);return this.consumeToken(),e.setNamespacePrefix(this._parseNamespacePrefix()),e.setIdentifier(this._parseIdent())?(e.setOperator(this._parseOperator())&&(e.setValue(this._parseBinaryExpr()),this.acceptIdent("i"),this.acceptIdent("s")),this.accept(c.BracketR)?this.finish(e):this.finish(e,f.RightSquareBracketExpected)):this.finish(e,f.IdentifierExpected)}_parsePseudo(){let e=this._tryParsePseudoIdentifier();if(e){if(!this.hasWhitespace()&&this.accept(c.ParenthesisL)){let t=()=>{let i=this.create(x);if(!i.addChild(this._parseSelector(!0)))return null;for(;this.accept(c.Comma)&&i.addChild(this._parseSelector(!0)););return this.peek(c.ParenthesisR)?this.finish(i):null};if(!e.addChild(this.try(t))&&e.addChild(this._parseBinaryExpr())&&this.acceptIdent("of")&&!e.addChild(this.try(t)))return this.finish(e,f.SelectorExpected);if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected)}return this.finish(e)}return null}_tryParsePseudoIdentifier(){if(!this.peek(c.Colon))return null;let e=this.mark(),t=this.createNode(m.PseudoSelector);return this.consumeToken(),this.hasWhitespace()?(this.restoreAtMark(e),null):(this.accept(c.Colon),this.hasWhitespace()||!t.addChild(this._parseIdent())?this.finish(t,f.IdentifierExpected):this.finish(t))}_tryParsePrio(){let e=this.mark(),t=this._parsePrio();return t||(this.restoreAtMark(e),null)}_parsePrio(){if(!this.peek(c.Exclamation))return null;let e=this.createNode(m.Prio);return this.accept(c.Exclamation)&&this.acceptIdent("important")?this.finish(e):null}_parseExpr(e=!1){let t=this.create(gt);if(!t.addChild(this._parseBinaryExpr()))return null;for(;;){if(this.peek(c.Comma)){if(e)return this.finish(t);this.consumeToken()}if(!t.addChild(this._parseBinaryExpr()))break}return this.finish(t)}_parseUnicodeRange(){if(!this.peekIdent("u"))return null;let e=this.create(gn);return this.acceptUnicodeRange()?this.finish(e):null}_parseNamedLine(){if(!this.peek(c.BracketL))return null;let e=this.createNode(m.GridLine);for(this.consumeToken();e.addChild(this._parseIdent()););return this.accept(c.BracketR)?this.finish(e):this.finish(e,f.RightSquareBracketExpected)}_parseBinaryExpr(e,t){let r=this.create(qe);if(!r.setLeft(e||this._parseTerm()))return null;if(!r.setOperator(t||this._parseOperator()))return this.finish(r);if(!r.setRight(this._parseTerm()))return this.finish(r,f.TermExpected);r=this.finish(r);let i=this._parseOperator();return i&&(r=this._parseBinaryExpr(r,i)),this.finish(r)}_parseTerm(){let e=this.create(Ln);return e.setOperator(this._parseUnaryOperator()),e.setExpression(this._parseTermExpression())?this.finish(e):null}_parseTermExpression(){return this._parseURILiteral()||this._parseUnicodeRange()||this._parseFunction()||this._parseIdent()||this._parseStringLiteral()||this._parseNumeric()||this._parseHexColor()||this._parseOperation()||this._parseNamedLine()}_parseOperation(){if(!this.peek(c.ParenthesisL))return null;let e=this.create(x);return this.consumeToken(),e.addChild(this._parseExpr()),this.accept(c.ParenthesisR)?this.finish(e):this.finish(e,f.RightParenthesisExpected)}_parseNumeric(){if(this.peek(c.Num)||this.peek(c.Percentage)||this.peek(c.Resolution)||this.peek(c.Length)||this.peek(c.EMS)||this.peek(c.EXS)||this.peek(c.Angle)||this.peek(c.Time)||this.peek(c.Dimension)||this.peek(c.ContainerQueryLength)||this.peek(c.Freq)){let e=this.create(nt);return this.consumeToken(),this.finish(e)}return null}_parseStringLiteral(){if(!this.peek(c.String)&&!this.peek(c.BadString))return null;let e=this.createNode(m.StringLiteral);return this.consumeToken(),this.finish(e)}_parseURILiteral(){if(!this.peekRegExp(c.Ident,/^url(-prefix)?$/i))return null;let e=this.mark(),t=this.createNode(m.URILiteral);return this.accept(c.Ident),this.hasWhitespace()||!this.peek(c.ParenthesisL)?(this.restoreAtMark(e),null):(this.scanner.inURL=!0,this.consumeToken(),t.addChild(this._parseURLArgument()),this.scanner.inURL=!1,this.accept(c.ParenthesisR)?this.finish(t):this.finish(t,f.RightParenthesisExpected))}_parseURLArgument(){let e=this.create(x);return!this.accept(c.String)&&!this.accept(c.BadString)&&!this.acceptUnquotedString()?null:this.finish(e)}_parseIdent(e){if(!this.peek(c.Ident))return null;let t=this.create(G);return e&&(t.referenceTypes=e),t.isCustomProperty=this.peekRegExp(c.Ident,/^--/),this.consumeToken(),this.finish(t)}_parseFunction(){let e=this.mark(),t=this.create(me);if(!t.setIdentifier(this._parseFunctionIdentifier()))return null;if(this.hasWhitespace()||!this.accept(c.ParenthesisL))return this.restoreAtMark(e),null;if(t.getArguments().addChild(this._parseFunctionArgument()))for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)t.getArguments().addChild(this._parseFunctionArgument())||this.markError(t,f.ExpressionExpected);return this.accept(c.ParenthesisR)?this.finish(t):this.finish(t,f.RightParenthesisExpected)}_parseFunctionIdentifier(){if(!this.peek(c.Ident))return null;let e=this.create(G);if(e.referenceTypes=[z.Function],this.acceptIdent("progid")){if(this.accept(c.Colon))for(;this.accept(c.Ident)&&this.acceptDelim("."););return this.finish(e)}return this.consumeToken(),this.finish(e)}_parseFunctionArgument(){let e=this.create(le);return e.setValue(this._parseExpr(!0))?this.finish(e):null}_parseHexColor(){if(this.peekRegExp(c.Hash,/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/g)){let e=this.create(tt);return this.consumeToken(),this.finish(e)}else return null}};function Hs(n,e){let t=0,r=n.length;if(r===0)return 0;for(;te+t||this.offset===e&&this.length===t?this.findInScope(e,t):null}findInScope(e,t=0){let r=e+t,i=Hs(this.children,a=>a.offset>r);if(i===0)return this;let s=this.children[i-1];return s.offset<=e&&s.offset+s.length>=e+t?s.findInScope(e,t):this}addSymbol(e){this.symbols.push(e)}getSymbol(e,t){for(let r=0;r{"use strict";var n={470:i=>{function s(o){if(typeof o!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(o))}function a(o,d){for(var h,u="",w=0,b=-1,y=0,E=0;E<=o.length;++E){if(E2){var A=u.lastIndexOf("/");if(A!==u.length-1){A===-1?(u="",w=0):w=(u=u.slice(0,A)).length-1-u.lastIndexOf("/"),b=E,y=0;continue}}else if(u.length===2||u.length===1){u="",w=0,b=E,y=0;continue}}d&&(u.length>0?u+="/..":u="..",w=2)}else u.length>0?u+="/"+o.slice(b+1,E):u=o.slice(b+1,E),w=E-b-1;b=E,y=0}else h===46&&y!==-1?++y:y=-1}return u}var l={resolve:function(){for(var o,d="",h=!1,u=arguments.length-1;u>=-1&&!h;u--){var w;u>=0?w=arguments[u]:(o===void 0&&(o=process.cwd()),w=o),s(w),w.length!==0&&(d=w+"/"+d,h=w.charCodeAt(0)===47)}return d=a(d,!h),h?d.length>0?"/"+d:"/":d.length>0?d:"."},normalize:function(o){if(s(o),o.length===0)return".";var d=o.charCodeAt(0)===47,h=o.charCodeAt(o.length-1)===47;return(o=a(o,!d)).length!==0||d||(o="."),o.length>0&&h&&(o+="/"),d?"/"+o:o},isAbsolute:function(o){return s(o),o.length>0&&o.charCodeAt(0)===47},join:function(){if(arguments.length===0)return".";for(var o,d=0;d0&&(o===void 0?o=h:o+="/"+h)}return o===void 0?".":l.normalize(o)},relative:function(o,d){if(s(o),s(d),o===d||(o=l.resolve(o))===(d=l.resolve(d)))return"";for(var h=1;hE){if(d.charCodeAt(b+I)===47)return d.slice(b+I+1);if(I===0)return d.slice(b+I)}else w>E&&(o.charCodeAt(h+I)===47?A=I:I===0&&(A=0));break}var P=o.charCodeAt(h+I);if(P!==d.charCodeAt(b+I))break;P===47&&(A=I)}var T="";for(I=h+A+1;I<=u;++I)I!==u&&o.charCodeAt(I)!==47||(T.length===0?T+="..":T+="/..");return T.length>0?T+d.slice(b+A):(b+=A,d.charCodeAt(b)===47&&++b,d.slice(b))},_makeLong:function(o){return o},dirname:function(o){if(s(o),o.length===0)return".";for(var d=o.charCodeAt(0),h=d===47,u=-1,w=!0,b=o.length-1;b>=1;--b)if((d=o.charCodeAt(b))===47){if(!w){u=b;break}}else w=!1;return u===-1?h?"/":".":h&&u===1?"//":o.slice(0,u)},basename:function(o,d){if(d!==void 0&&typeof d!="string")throw new TypeError('"ext" argument must be a string');s(o);var h,u=0,w=-1,b=!0;if(d!==void 0&&d.length>0&&d.length<=o.length){if(d.length===o.length&&d===o)return"";var y=d.length-1,E=-1;for(h=o.length-1;h>=0;--h){var A=o.charCodeAt(h);if(A===47){if(!b){u=h+1;break}}else E===-1&&(b=!1,E=h+1),y>=0&&(A===d.charCodeAt(y)?--y==-1&&(w=h):(y=-1,w=E))}return u===w?w=E:w===-1&&(w=o.length),o.slice(u,w)}for(h=o.length-1;h>=0;--h)if(o.charCodeAt(h)===47){if(!b){u=h+1;break}}else w===-1&&(b=!1,w=h+1);return w===-1?"":o.slice(u,w)},extname:function(o){s(o);for(var d=-1,h=0,u=-1,w=!0,b=0,y=o.length-1;y>=0;--y){var E=o.charCodeAt(y);if(E!==47)u===-1&&(w=!1,u=y+1),E===46?d===-1?d=y:b!==1&&(b=1):d!==-1&&(b=-1);else if(!w){h=y+1;break}}return d===-1||u===-1||b===0||b===1&&d===u-1&&d===h+1?"":o.slice(d,u)},format:function(o){if(o===null||typeof o!="object")throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof o);return function(d,h){var u=h.dir||h.root,w=h.base||(h.name||"")+(h.ext||"");return u?u===h.root?u+w:u+"/"+w:w}(0,o)},parse:function(o){s(o);var d={root:"",dir:"",base:"",ext:"",name:""};if(o.length===0)return d;var h,u=o.charCodeAt(0),w=u===47;w?(d.root="/",h=1):h=0;for(var b=-1,y=0,E=-1,A=!0,I=o.length-1,P=0;I>=h;--I)if((u=o.charCodeAt(I))!==47)E===-1&&(A=!1,E=I+1),u===46?b===-1?b=I:P!==1&&(P=1):b!==-1&&(P=-1);else if(!A){y=I+1;break}return b===-1||E===-1||P===0||P===1&&b===E-1&&b===y+1?E!==-1&&(d.base=d.name=y===0&&w?o.slice(1,E):o.slice(y,E)):(y===0&&w?(d.name=o.slice(1,b),d.base=o.slice(1,E)):(d.name=o.slice(y,b),d.base=o.slice(y,E)),d.ext=o.slice(b,E)),y>0?d.dir=o.slice(0,y-1):w&&(d.dir="/"),d},sep:"/",delimiter:":",win32:null,posix:null};l.posix=l,i.exports=l}},e={};function t(i){var s=e[i];if(s!==void 0)return s.exports;var a=e[i]={exports:{}};return n[i](a,a.exports,t),a.exports}t.d=(i,s)=>{for(var a in s)t.o(s,a)&&!t.o(i,a)&&Object.defineProperty(i,a,{enumerable:!0,get:s[a]})},t.o=(i,s)=>Object.prototype.hasOwnProperty.call(i,s),t.r=i=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(i,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(i,"__esModule",{value:!0})};var r={};(()=>{let i;t.r(r),t.d(r,{URI:()=>w,Utils:()=>Ie}),typeof process=="object"?i=process.platform==="win32":typeof navigator=="object"&&(i=navigator.userAgent.indexOf("Windows")>=0);let s=/^\w[\w\d+.-]*$/,a=/^\//,l=/^\/\//;function o(S,v){if(!S.scheme&&v)throw new Error(`[UriError]: Scheme is missing: {scheme: "", authority: "${S.authority}", path: "${S.path}", query: "${S.query}", fragment: "${S.fragment}"}`);if(S.scheme&&!s.test(S.scheme))throw new Error("[UriError]: Scheme contains illegal characters.");if(S.path){if(S.authority){if(!a.test(S.path))throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character')}else if(l.test(S.path))throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")')}}let d="",h="/",u=/^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;class w{static isUri(v){return v instanceof w||!!v&&typeof v.authority=="string"&&typeof v.fragment=="string"&&typeof v.path=="string"&&typeof v.query=="string"&&typeof v.scheme=="string"&&typeof v.fsPath=="string"&&typeof v.with=="function"&&typeof v.toString=="function"}scheme;authority;path;query;fragment;constructor(v,F,C,N,D,M=!1){typeof v=="object"?(this.scheme=v.scheme||d,this.authority=v.authority||d,this.path=v.path||d,this.query=v.query||d,this.fragment=v.fragment||d):(this.scheme=function(oe,Z){return oe||Z?oe:"file"}(v,M),this.authority=F||d,this.path=function(oe,Z){switch(oe){case"https":case"http":case"file":Z?Z[0]!==h&&(Z=h+Z):Z=h}return Z}(this.scheme,C||d),this.query=N||d,this.fragment=D||d,o(this,M))}get fsPath(){return P(this,!1)}with(v){if(!v)return this;let{scheme:F,authority:C,path:N,query:D,fragment:M}=v;return F===void 0?F=this.scheme:F===null&&(F=d),C===void 0?C=this.authority:C===null&&(C=d),N===void 0?N=this.path:N===null&&(N=d),D===void 0?D=this.query:D===null&&(D=d),M===void 0?M=this.fragment:M===null&&(M=d),F===this.scheme&&C===this.authority&&N===this.path&&D===this.query&&M===this.fragment?this:new y(F,C,N,D,M)}static parse(v,F=!1){let C=u.exec(v);return C?new y(C[2]||d,Y(C[4]||d),Y(C[5]||d),Y(C[7]||d),Y(C[9]||d),F):new y(d,d,d,d,d)}static file(v){let F=d;if(i&&(v=v.replace(/\\/g,h)),v[0]===h&&v[1]===h){let C=v.indexOf(h,2);C===-1?(F=v.substring(2),v=h):(F=v.substring(2,C),v=v.substring(C)||h)}return new y("file",F,v,d,d)}static from(v){let F=new y(v.scheme,v.authority,v.path,v.query,v.fragment);return o(F,!0),F}toString(v=!1){return T(this,v)}toJSON(){return this}static revive(v){if(v){if(v instanceof w)return v;{let F=new y(v);return F._formatted=v.external,F._fsPath=v._sep===b?v.fsPath:null,F}}return v}}let b=i?1:void 0;class y extends w{_formatted=null;_fsPath=null;get fsPath(){return this._fsPath||(this._fsPath=P(this,!1)),this._fsPath}toString(v=!1){return v?T(this,!0):(this._formatted||(this._formatted=T(this,!1)),this._formatted)}toJSON(){let v={$mid:1};return this._fsPath&&(v.fsPath=this._fsPath,v._sep=b),this._formatted&&(v.external=this._formatted),this.path&&(v.path=this.path),this.scheme&&(v.scheme=this.scheme),this.authority&&(v.authority=this.authority),this.query&&(v.query=this.query),this.fragment&&(v.fragment=this.fragment),v}}let E={58:"%3A",47:"%2F",63:"%3F",35:"%23",91:"%5B",93:"%5D",64:"%40",33:"%21",36:"%24",38:"%26",39:"%27",40:"%28",41:"%29",42:"%2A",43:"%2B",44:"%2C",59:"%3B",61:"%3D",32:"%20"};function A(S,v,F){let C,N=-1;for(let D=0;D=97&&M<=122||M>=65&&M<=90||M>=48&&M<=57||M===45||M===46||M===95||M===126||v&&M===47||F&&M===91||F&&M===93||F&&M===58)N!==-1&&(C+=encodeURIComponent(S.substring(N,D)),N=-1),C!==void 0&&(C+=S.charAt(D));else{C===void 0&&(C=S.substr(0,D));let oe=E[M];oe!==void 0?(N!==-1&&(C+=encodeURIComponent(S.substring(N,D)),N=-1),C+=oe):N===-1&&(N=D)}}return N!==-1&&(C+=encodeURIComponent(S.substring(N))),C!==void 0?C:S}function I(S){let v;for(let F=0;F1&&S.scheme==="file"?`//${S.authority}${S.path}`:S.path.charCodeAt(0)===47&&(S.path.charCodeAt(1)>=65&&S.path.charCodeAt(1)<=90||S.path.charCodeAt(1)>=97&&S.path.charCodeAt(1)<=122)&&S.path.charCodeAt(2)===58?v?S.path.substr(1):S.path[1].toLowerCase()+S.path.substr(2):S.path,i&&(F=F.replace(/\//g,"\\")),F}function T(S,v){let F=v?I:A,C="",{scheme:N,authority:D,path:M,query:oe,fragment:Z}=S;if(N&&(C+=N,C+=":"),(D||N==="file")&&(C+=h,C+=h),D){let $=D.indexOf("@");if($!==-1){let Ue=D.substr(0,$);D=D.substr($+1),$=Ue.lastIndexOf(":"),$===-1?C+=F(Ue,!1,!1):(C+=F(Ue.substr(0,$),!1,!1),C+=":",C+=F(Ue.substr($+1),!1,!0)),C+="@"}D=D.toLowerCase(),$=D.lastIndexOf(":"),$===-1?C+=F(D,!1,!0):(C+=F(D.substr(0,$),!1,!0),C+=D.substr($))}if(M){if(M.length>=3&&M.charCodeAt(0)===47&&M.charCodeAt(2)===58){let $=M.charCodeAt(1);$>=65&&$<=90&&(M=`/${String.fromCharCode($+32)}:${M.substr(3)}`)}else if(M.length>=2&&M.charCodeAt(1)===58){let $=M.charCodeAt(0);$>=65&&$<=90&&(M=`${String.fromCharCode($+32)}:${M.substr(2)}`)}C+=F(M,!0,!1)}return oe&&(C+="?",C+=F(oe,!1,!1)),Z&&(C+="#",C+=v?Z:A(Z,!1,!1)),C}function j(S){try{return decodeURIComponent(S)}catch{return S.length>3?S.substr(0,3)+j(S.substr(3)):S}}let X=/(%[0-9A-Za-z][0-9A-Za-z])+/g;function Y(S){return S.match(X)?S.replace(X,v=>j(v)):S}var $e=t(470);let K=$e.posix||$e,_e="/";var Ie;(function(S){S.joinPath=function(v,...F){return v.with({path:K.join(v.path,...F)})},S.resolvePath=function(v,...F){let C=v.path,N=!1;C[0]!==_e&&(C=_e+C,N=!0);let D=K.resolve(C,...F);return N&&D[0]===_e&&!v.authority&&(D=D.substring(1)),v.with({path:D})},S.dirname=function(v){if(v.path.length===0||v.path===_e)return v;let F=K.dirname(v.path);return F.length===1&&F.charCodeAt(0)===46&&(F=""),v.with({path:F})},S.basename=function(v){return K.basename(v.path)},S.extname=function(v){return K.extname(v.path)}})(Ie||(Ie={}))})(),Js=r})();var{URI:Zt,Utils:Fe}=Js;function ar(n){return Fe.dirname(Zt.parse(n)).toString(!0)}function Je(n,...e){return Fe.joinPath(Zt.parse(n),...e).toString(!0)}var cr=class{constructor(e){this.readDirectory=e,this.literalCompletions=[],this.importCompletions=[]}onCssURILiteralValue(e){this.literalCompletions.push(e)}onCssImportPath(e){this.importCompletions.push(e)}async computeCompletions(e,t){let r={items:[],isIncomplete:!1};for(let i of this.literalCompletions){let s=i.uriValue,a=vi(s);if(a==="."||a==="..")r.isIncomplete=!0;else{let l=await this.providePathSuggestions(s,i.position,i.range,e,t);for(let o of l)r.items.push(o)}}for(let i of this.importCompletions){let s=i.pathValue,a=vi(s);if(a==="."||a==="..")r.isIncomplete=!0;else{let l=await this.providePathSuggestions(s,i.position,i.range,e,t);e.languageId==="scss"&&l.forEach(o=>{V(o.label,"_")&&fn(o.label,".scss")&&(o.textEdit?o.textEdit.newText=o.label.slice(1,-5):o.label=o.label.slice(1,-5))});for(let o of l)r.items.push(o)}}return r}async providePathSuggestions(e,t,r,i,s){let a=vi(e),l=V(e,"'")||V(e,'"'),o=l?a.slice(0,t.character-(r.start.character+1)):a.slice(0,t.character-r.start.character),d=i.uri,h=l?ba(r,1,-1):r,u=fa(o,a,h),w=o.substring(0,o.lastIndexOf("/")+1),b=s.resolveReference(w||".",d);if(b)try{let y=[],E=await this.readDirectory(b);for(let[A,I]of E)A.charCodeAt(0)!==ua&&(I===st.Directory||Je(b,A)!==d)&&y.push(ga(A,I===st.Directory,u));return y}catch{}return[]}},ua=46;function vi(n){return V(n,"'")||V(n,'"')?n.slice(1,-1):n}function fa(n,e,t){let r,i=n.lastIndexOf("/");if(i===-1)r=t;else{let s=e.slice(i+1),a=dr(t.end,-s.length),l=s.indexOf(" "),o;l!==-1?o=dr(a,l):o=t.end,r=R.create(a,o)}return r}function ga(n,e,t){return e?(n=n+"/",{label:lr(n),kind:k.Folder,textEdit:_.replace(t,lr(n)),command:{title:"Suggest",command:"editor.action.triggerSuggest"}}):{label:lr(n),kind:k.File,textEdit:_.replace(t,lr(n))}}function lr(n){return n.replace(/(\s|\(|\)|,|"|')/g,"\\$1")}function dr(n,e){return H.create(n.line,n.character+e)}function ba(n,e,t){let r=dr(n.start,e),i=dr(n.end,t);return R.create(r,i)}var Ne=te.Snippet,Xs={title:"Suggest",command:"editor.action.triggerSuggest"},Ee;(function(n){n.Enums=" ",n.Normal="d",n.VendorPrefixed="x",n.Term="y",n.Variable="z"})(Ee||(Ee={}));var Xe=class{constructor(e=null,t,r){this.variablePrefix=e,this.lsOptions=t,this.cssDataManager=r,this.completionParticipants=[]}configure(e){this.defaultSettings=e}getSymbolContext(){return this.symbolContext||(this.symbolContext=new ot(this.styleSheet)),this.symbolContext}setCompletionParticipants(e){this.completionParticipants=e||[]}async doComplete2(e,t,r,i,s=this.defaultSettings){if(!this.lsOptions.fileSystemProvider||!this.lsOptions.fileSystemProvider.readDirectory)return this.doComplete(e,t,r,s);let a=new cr(this.lsOptions.fileSystemProvider.readDirectory),l=this.completionParticipants;this.completionParticipants=[a].concat(l);let o=this.doComplete(e,t,r,s);try{let d=await a.computeCompletions(e,i);return{isIncomplete:o.isIncomplete||d.isIncomplete,itemDefaults:o.itemDefaults,items:d.items.concat(o.items)}}finally{this.completionParticipants=l}}doComplete(e,t,r,i){this.offset=e.offsetAt(t),this.position=t,this.currentWord=va(e,this.offset),this.defaultReplaceRange=R.create(H.create(this.position.line,this.position.character-this.currentWord.length),this.position),this.textDocument=e,this.styleSheet=r,this.documentSettings=i;try{let s={isIncomplete:!1,itemDefaults:{editRange:{start:{line:t.line,character:t.character-this.currentWord.length},end:t}},items:[]};this.nodePath=vt(this.styleSheet,this.offset);for(let a=this.nodePath.length-1;a>=0;a--){let l=this.nodePath[a];if(l instanceof Ve)this.getCompletionsForDeclarationProperty(l.getParent(),s);else if(l instanceof gt)l.parent instanceof rt?this.getVariableProposals(null,s):this.getCompletionsForExpression(l,s);else if(l instanceof he){let o=l.findAParent(m.ExtendsReference,m.Ruleset);if(o)if(o.type===m.ExtendsReference)this.getCompletionsForExtendsReference(o,l,s);else{let d=o;this.getCompletionsForSelector(d,d&&d.isNested(),s)}}else if(l instanceof le)this.getCompletionsForFunctionArgument(l,l.getParent(),s);else if(l instanceof Ze)this.getCompletionsForDeclarations(l,s);else if(l instanceof xe)this.getCompletionsForVariableDeclaration(l,s);else if(l instanceof ae)this.getCompletionsForRuleSet(l,s);else if(l instanceof rt)this.getCompletionsForInterpolation(l,s);else if(l instanceof De)this.getCompletionsForFunctionDeclaration(l,s);else if(l instanceof ze)this.getCompletionsForMixinReference(l,s);else if(l instanceof me)this.getCompletionsForFunctionArgument(null,l,s);else if(l instanceof et)this.getCompletionsForSupports(l,s);else if(l instanceof Re)this.getCompletionsForSupportsCondition(l,s);else if(l instanceof Se)this.getCompletionsForExtendsReference(l,null,s);else if(l.type===m.URILiteral)this.getCompletionForUriLiteralValue(l,s);else if(l.parent===null)this.getCompletionForTopLevel(s);else if(l.type===m.StringLiteral&&this.isImportPathParent(l.parent.type))this.getCompletionForImportPath(l,s);else continue;if(s.items.length>0||this.offset>l.offset)return this.finalize(s)}return this.getCompletionsForStylesheet(s),s.items.length===0&&this.variablePrefix&&this.currentWord.indexOf(this.variablePrefix)===0&&this.getVariableProposals(null,s),this.finalize(s)}finally{this.position=null,this.currentWord=null,this.textDocument=null,this.styleSheet=null,this.symbolContext=null,this.defaultReplaceRange=null,this.nodePath=null}}isImportPathParent(e){return e===m.Import}finalize(e){return e}findInNodePath(...e){for(let t=this.nodePath.length-1;t>=0;t--){let r=this.nodePath[t];if(e.indexOf(r.type)!==-1)return r}return null}getCompletionsForDeclarationProperty(e,t){return this.getPropertyProposals(e,t)}getPropertyProposals(e,t){let r=this.isTriggerPropertyValueCompletionEnabled,i=this.isCompletePropertyWithSemicolonEnabled;return this.cssDataManager.getProperties().forEach(a=>{let l,o,d=!1;e?(l=this.getCompletionRange(e.getProperty()),o=a.name,ie(e.colonPosition)||(o+=": ",d=!0)):(l=this.getCompletionRange(null),o=a.name+": ",d=!0),!e&&i&&(o+="$0;"),e&&!e.semicolonPosition&&i&&this.offset>=this.textDocument.offsetAt(l.end)&&(o+="$0;");let h={label:a.name,documentation:Ce(a,this.doesSupportMarkdown()),tags:en(a)?[Te.Deprecated]:[],textEdit:_.replace(l,o),insertTextFormat:te.Snippet,kind:k.Property};a.restrictions||(d=!1),r&&d&&(h.command=Xs);let w=(255-(typeof a.relevance=="number"?Math.min(Math.max(a.relevance,0),99):50)).toString(16),b=V(a.name,"-")?Ee.VendorPrefixed:Ee.Normal;h.sortText=b+"_"+w,t.items.push(h)}),this.completionParticipants.forEach(a=>{a.onCssProperty&&a.onCssProperty({propertyName:this.currentWord,range:this.defaultReplaceRange})}),t}get isTriggerPropertyValueCompletionEnabled(){return this.documentSettings?.triggerPropertyValueCompletion??!0}get isCompletePropertyWithSemicolonEnabled(){return this.documentSettings?.completePropertyWithSemicolon??!0}getCompletionsForDeclarationValue(e,t){let r=e.getFullPropertyName(),i=this.cssDataManager.getProperty(r),s=e.getValue()||null;for(;s&&s.hasChildren();)s=s.findChildAtOffset(this.offset,!1);if(this.completionParticipants.forEach(a=>{a.onCssPropertyValue&&a.onCssPropertyValue({propertyName:r,propertyValue:this.currentWord,range:this.getCompletionRange(s)})}),i){if(i.restrictions)for(let a of i.restrictions)switch(a){case"color":this.getColorProposals(i,s,t);break;case"position":this.getPositionProposals(i,s,t);break;case"repeat":this.getRepeatStyleProposals(i,s,t);break;case"line-style":this.getLineStyleProposals(i,s,t);break;case"line-width":this.getLineWidthProposals(i,s,t);break;case"geometry-box":this.getGeometryBoxProposals(i,s,t);break;case"box":this.getBoxProposals(i,s,t);break;case"image":this.getImageProposals(i,s,t);break;case"timing-function":this.getTimingFunctionProposals(i,s,t);break;case"shape":this.getBasicShapeProposals(i,s,t);break}this.getValueEnumProposals(i,s,t),this.getCSSWideKeywordProposals(i,s,t),this.getUnitProposals(i,s,t)}else{let a=wa(this.styleSheet,e);for(let l of a.getEntries())t.items.push({label:l,textEdit:_.replace(this.getCompletionRange(s),l),kind:k.Value})}return this.getVariableProposals(s,t),this.getTermProposals(i,s,t),t}getValueEnumProposals(e,t,r){if(e.values)for(let i of e.values){let s=i.name,a;if(fn(s,")")){let d=s.lastIndexOf("(");d!==-1&&(s=s.substring(0,d+1)+"$1"+s.substring(d+1),a=Ne)}let l=Ee.Enums;V(i.name,"-")&&(l+=Ee.VendorPrefixed);let o={label:i.name,documentation:Ce(i,this.doesSupportMarkdown()),tags:en(e)?[Te.Deprecated]:[],textEdit:_.replace(this.getCompletionRange(t),s),sortText:l,kind:k.Value,insertTextFormat:a};r.items.push(o)}return r}getCSSWideKeywordProposals(e,t,r){for(let i in hi)r.items.push({label:i,documentation:hi[i],textEdit:_.replace(this.getCompletionRange(t),i),kind:k.Value});for(let i in pi){let s=Et(i);r.items.push({label:i,documentation:pi[i],textEdit:_.replace(this.getCompletionRange(t),s),kind:k.Function,insertTextFormat:Ne,command:V(i,"var")?Xs:void 0})}return r}getCompletionsForInterpolation(e,t){return this.offset>=e.offset+2&&this.getVariableProposals(null,t),t}getVariableProposals(e,t){let r=this.getSymbolContext().findSymbolsAtOffset(this.offset,z.Variable);for(let i of r){let s=V(i.name,"--")?`var(${i.name})`:i.name,a={label:i.name,documentation:i.value?zr(i.value):i.value,textEdit:_.replace(this.getCompletionRange(e),s),kind:k.Variable,sortText:Ee.Variable};if(typeof a.documentation=="string"&&ii(a.documentation)&&(a.kind=k.Color),i.node.type===m.FunctionParameter){let l=i.node.getParent();l.type===m.MixinDeclaration&&(a.detail=p("argument from '{0}'",l.getName()))}t.items.push(a)}return t}getVariableProposalsForCSSVarFunction(e){let t=new tn;this.styleSheet.acceptVisitor(new xi(t,this.offset));let r=this.getSymbolContext().findSymbolsAtOffset(this.offset,z.Variable);for(let i of r){if(V(i.name,"--")){let s={label:i.name,documentation:i.value?zr(i.value):i.value,textEdit:_.replace(this.getCompletionRange(null),i.name),kind:k.Variable};typeof s.documentation=="string"&&ii(s.documentation)&&(s.kind=k.Color),e.items.push(s)}t.remove(i.name)}for(let i of t.getEntries())if(V(i,"--")){let s={label:i,textEdit:_.replace(this.getCompletionRange(null),i),kind:k.Variable};e.items.push(s)}return e}getUnitProposals(e,t,r){let i="0";if(this.currentWord.length>0){let s=this.currentWord.match(/^-?\d[\.\d+]*/);s&&(i=s[0],r.isIncomplete=i.length===this.currentWord.length)}else this.currentWord.length===0&&(r.isIncomplete=!0);if(t&&t.parent&&t.parent.type===m.Term&&(t=t.getParent()),e.restrictions)for(let s of e.restrictions){let a=ir[s];if(a)for(let l of a){let o=i+l;r.items.push({label:o,textEdit:_.replace(this.getCompletionRange(t),o),kind:k.Unit})}}return r}getCompletionRange(e){if(e&&e.offset<=this.offset&&this.offset<=e.end){let t=e.end!==-1?this.textDocument.positionAt(e.end):this.position,r=this.textDocument.positionAt(e.offset);if(r.line===t.line)return R.create(r,t)}return this.defaultReplaceRange}getColorProposals(e,t,r){for(let s in Xt)r.items.push({label:s,documentation:Xt[s],textEdit:_.replace(this.getCompletionRange(t),s),kind:k.Color});for(let s in rr)r.items.push({label:s,documentation:rr[s],textEdit:_.replace(this.getCompletionRange(t),s),kind:k.Value});let i=new tn;this.styleSheet.acceptVisitor(new yi(i,this.offset));for(let s of i.getEntries())r.items.push({label:s,textEdit:_.replace(this.getCompletionRange(t),s),kind:k.Color});for(let s of Ws)r.items.push({label:s.label,detail:s.func,documentation:s.desc,textEdit:_.replace(this.getCompletionRange(t),s.insertText),insertTextFormat:Ne,kind:k.Function});return r}getPositionProposals(e,t,r){for(let i in oi)r.items.push({label:i,documentation:oi[i],textEdit:_.replace(this.getCompletionRange(t),i),kind:k.Value});return r}getRepeatStyleProposals(e,t,r){for(let i in ai)r.items.push({label:i,documentation:ai[i],textEdit:_.replace(this.getCompletionRange(t),i),kind:k.Value});return r}getLineStyleProposals(e,t,r){for(let i in li)r.items.push({label:i,documentation:li[i],textEdit:_.replace(this.getCompletionRange(t),i),kind:k.Value});return r}getLineWidthProposals(e,t,r){for(let i of js)r.items.push({label:i,textEdit:_.replace(this.getCompletionRange(t),i),kind:k.Value});return r}getGeometryBoxProposals(e,t,r){for(let i in di)r.items.push({label:i,documentation:di[i],textEdit:_.replace(this.getCompletionRange(t),i),kind:k.Value});return r}getBoxProposals(e,t,r){for(let i in ci)r.items.push({label:i,documentation:ci[i],textEdit:_.replace(this.getCompletionRange(t),i),kind:k.Value});return r}getImageProposals(e,t,r){for(let i in mi){let s=Et(i);r.items.push({label:i,documentation:mi[i],textEdit:_.replace(this.getCompletionRange(t),s),kind:k.Function,insertTextFormat:i!==s?Ne:void 0})}return r}getTimingFunctionProposals(e,t,r){for(let i in ui){let s=Et(i);r.items.push({label:i,documentation:ui[i],textEdit:_.replace(this.getCompletionRange(t),s),kind:k.Function,insertTextFormat:i!==s?Ne:void 0})}return r}getBasicShapeProposals(e,t,r){for(let i in fi){let s=Et(i);r.items.push({label:i,documentation:fi[i],textEdit:_.replace(this.getCompletionRange(t),s),kind:k.Function,insertTextFormat:i!==s?Ne:void 0})}return r}getCompletionsForStylesheet(e){let t=this.styleSheet.findFirstChildBeforeOffset(this.offset);return t?t instanceof ae?this.getCompletionsForRuleSet(t,e):t instanceof et?this.getCompletionsForSupports(t,e):e:this.getCompletionForTopLevel(e)}getCompletionForTopLevel(e){return this.cssDataManager.getAtDirectives().forEach(t=>{e.items.push({label:t.name,textEdit:_.replace(this.getCompletionRange(null),t.name),documentation:Ce(t,this.doesSupportMarkdown()),tags:en(t)?[Te.Deprecated]:[],kind:k.Keyword})}),this.getCompletionsForSelector(null,!1,e),e}getCompletionsForRuleSet(e,t){let r=e.getDeclarations();return r&&r.endsWith("}")&&this.offset>=r.end?this.getCompletionForTopLevel(t):!r||this.offset<=r.offset?this.getCompletionsForSelector(e,e.isNested(),t):this.getCompletionsForDeclarations(e.getDeclarations(),t)}getCompletionsForSelector(e,t,r){let i=this.findInNodePath(m.PseudoSelector,m.IdentifierSelector,m.ClassSelector,m.ElementNameSelector);if(!i&&this.hasCharacterAtPosition(this.offset-this.currentWord.length-1,":")&&(this.currentWord=":"+this.currentWord,this.hasCharacterAtPosition(this.offset-this.currentWord.length-1,":")&&(this.currentWord=":"+this.currentWord),this.defaultReplaceRange=R.create(H.create(this.position.line,this.position.character-this.currentWord.length),this.position)),this.cssDataManager.getPseudoClasses().forEach(d=>{let h=Et(d.name),u={label:d.name,textEdit:_.replace(this.getCompletionRange(i),h),documentation:Ce(d,this.doesSupportMarkdown()),tags:en(d)?[Te.Deprecated]:[],kind:k.Function,insertTextFormat:d.name!==h?Ne:void 0};V(d.name,":-")&&(u.sortText=Ee.VendorPrefixed),r.items.push(u)}),this.cssDataManager.getPseudoElements().forEach(d=>{let h=Et(d.name),u={label:d.name,textEdit:_.replace(this.getCompletionRange(i),h),documentation:Ce(d,this.doesSupportMarkdown()),tags:en(d)?[Te.Deprecated]:[],kind:k.Function,insertTextFormat:d.name!==h?Ne:void 0};V(d.name,"::-")&&(u.sortText=Ee.VendorPrefixed),r.items.push(u)}),!t){for(let d of Bs)r.items.push({label:d,textEdit:_.replace(this.getCompletionRange(i),d),kind:k.Keyword});for(let d of qs)r.items.push({label:d,textEdit:_.replace(this.getCompletionRange(i),d),kind:k.Keyword})}let l={};l[this.currentWord]=!0;let o=this.textDocument.getText();if(this.styleSheet.accept(d=>{if(d.type===m.SimpleSelector&&d.length>0){let h=o.substr(d.offset,d.length);return h.charAt(0)==="."&&!l[h]&&(l[h]=!0,r.items.push({label:h,textEdit:_.replace(this.getCompletionRange(i),h),kind:k.Keyword})),!1}return!0}),e&&e.isNested()){let d=e.getSelectors().findFirstChildBeforeOffset(this.offset);d&&e.getSelectors().getChildren().indexOf(d)===0&&this.getPropertyProposals(null,r)}return r}getCompletionsForDeclarations(e,t){if(!e||this.offset===e.offset)return t;let r=e.findFirstChildBeforeOffset(this.offset);if(!r)return this.getCompletionsForDeclarationProperty(null,t);if(r instanceof ht){let i=r;if(!ie(i.colonPosition)||this.offset<=i.colonPosition)return this.getCompletionsForDeclarationProperty(i,t);if(ie(i.semicolonPosition)&&i.semicolonPositione.colonPosition&&this.getVariableProposals(e.getValue()||null,t),t}getCompletionsForExpression(e,t){let r=e.getParent();if(r instanceof le)return this.getCompletionsForFunctionArgument(r,r.getParent(),t),t;let i=e.findParent(m.Declaration);if(!i)return this.getTermProposals(void 0,null,t),t;let s=e.findChildAtOffset(this.offset,!0);return s?s instanceof nt||s instanceof G?this.getCompletionsForDeclarationValue(i,t):t:this.getCompletionsForDeclarationValue(i,t)}getCompletionsForFunctionArgument(e,t,r){let i=t.getIdentifier();return i&&i.matches("var")&&(!t.getArguments().hasChildren()||t.getArguments().getChild(0)===e)&&this.getVariableProposalsForCSSVarFunction(r),r}getCompletionsForFunctionDeclaration(e,t){let r=e.getDeclarations();return r&&this.offset>r.offset&&this.offset{s.onCssMixinReference&&s.onCssMixinReference({mixinName:this.currentWord,range:this.getCompletionRange(i)})}),t}getTermProposals(e,t,r){let i=this.getSymbolContext().findSymbolsAtOffset(this.offset,z.Function);for(let s of i)s.node instanceof De&&r.items.push(this.makeTermProposal(s,s.node.getParameters(),t));return r}makeTermProposal(e,t,r){let i=e.node,s=t.getChildren().map(l=>l instanceof ye?l.getName():l.getText()),a=e.name+"("+s.map((l,o)=>"${"+(o+1)+":"+l+"}").join(", ")+")";return{label:e.name,detail:e.name+"("+s.join(", ")+")",textEdit:_.replace(this.getCompletionRange(r),a),insertTextFormat:Ne,kind:k.Function,sortText:Ee.Term}}getCompletionsForSupportsCondition(e,t){let r=e.findFirstChildBeforeOffset(this.offset);if(r){if(r instanceof Q)return!ie(r.colonPosition)||this.offset<=r.colonPosition?this.getCompletionsForDeclarationProperty(r,t):this.getCompletionsForDeclarationValue(r,t);if(r instanceof Re)return this.getCompletionsForSupportsCondition(r,t)}return ie(e.lParent)&&this.offset>e.lParent&&(!ie(e.rParent)||this.offset<=e.rParent)?this.getCompletionsForDeclarationProperty(null,t):t}getCompletionsForSupports(e,t){let r=e.getDeclarations();if(!r||this.offset<=r.offset){let s=e.findFirstChildBeforeOffset(this.offset);return s instanceof Re?this.getCompletionsForSupportsCondition(s,t):t}return this.getCompletionForTopLevel(t)}getCompletionsForExtendsReference(e,t,r){return r}getCompletionForUriLiteralValue(e,t){let r,i,s;if(e.hasChildren()){let a=e.getChild(0);r=a.getText(),i=this.position,s=this.getCompletionRange(a)}else{r="",i=this.position;let a=this.textDocument.positionAt(e.offset+4);s=R.create(a,a)}return this.completionParticipants.forEach(a=>{a.onCssURILiteralValue&&a.onCssURILiteralValue({uriValue:r,position:i,range:s})}),t}getCompletionForImportPath(e,t){return this.completionParticipants.forEach(r=>{r.onCssImportPath&&r.onCssImportPath({pathValue:e.getText(),position:this.position,range:this.getCompletionRange(e)})}),t}hasCharacterAtPosition(e,t){let r=this.textDocument.getText();return e>=0&&e=0&&` \r":{[()]},*>+`.indexOf(r.charAt(t))===-1;)t--;return r.substring(t+1,e)}var rn=class n{constructor(){this.parent=null,this.children=null,this.attributes=null}findAttribute(e){if(this.attributes){for(let t of this.attributes)if(t.name===e)return t.value}return null}addChild(e){e instanceof n&&(e.parent=this),this.children||(this.children=[]),this.children.push(e)}append(e){if(this.attributes){let t=this.attributes[this.attributes.length-1];t.value=t.value+e}}prepend(e){if(this.attributes){let t=this.attributes[0];t.value=e+t.value}}findRoot(){let e=this;for(;e.parent&&!(e.parent instanceof Ye);)e=e.parent;return e}removeChild(e){if(this.children){let t=this.children.indexOf(e);if(t!==-1)return this.children.splice(t,1),!0}return!1}addAttr(e,t){this.attributes||(this.attributes=[]);for(let r of this.attributes)if(r.name===e){r.value+=" "+t;return}this.attributes.push({name:e,value:t})}clone(e=!0){let t=new n;if(this.attributes){t.attributes=[];for(let r of this.attributes)t.addAttr(r.name,r.value)}if(e&&this.children){t.children=[];for(let r=0;r"),this.writeLine(t,i.join(""))}},Oe;(function(n){function e(r,i){return i+t(r)+i}n.ensure=e;function t(r){let i=r.match(/^['"](.*)["']$/);return i?i[1]:r}n.remove=t})(Oe||(Oe={}));var nn=class{constructor(){this.id=0,this.attr=0,this.tag=0}};function Ys(n,e){let t=new rn;for(let r of n.getChildren())switch(r.type){case m.SelectorCombinator:if(e){let l=r.getText().split("&");if(l.length===1){t.addAttr("name",l[0]);break}t=e.cloneWithParent(),l[0]&&t.findRoot().prepend(l[0]);for(let o=1;o1){let d=e.cloneWithParent();t.addChild(d.findRoot()),t=d}t.append(l[o])}}break;case m.SelectorPlaceholder:if(r.matches("@at-root"))return t;case m.ElementNameSelector:let i=r.getText();t.addAttr("name",i==="*"?"element":pe(i));break;case m.ClassSelector:t.addAttr("class",pe(r.getText().substring(1)));break;case m.IdentifierSelector:t.addAttr("id",pe(r.getText().substring(1)));break;case m.MixinDeclaration:t.addAttr("class",r.getName());break;case m.PseudoSelector:t.addAttr(pe(r.getText()),"");break;case m.AttributeSelector:let s=r,a=s.getIdentifier();if(a){let l=s.getValue(),o=s.getOperator(),d;if(l&&o)switch(pe(o.getText())){case"|=":d=`${Oe.remove(pe(l.getText()))}-\u2026`;break;case"^=":d=`${Oe.remove(pe(l.getText()))}\u2026`;break;case"$=":d=`\u2026${Oe.remove(pe(l.getText()))}`;break;case"~=":d=` \u2026 ${Oe.remove(pe(l.getText()))} \u2026 `;break;case"*=":d=`\u2026${Oe.remove(pe(l.getText()))}\u2026`;break;default:d=Oe.remove(pe(l.getText()));break}t.addAttr(pe(a.getText()),d)}break}return t}function pe(n){let e=new ce;e.setSource(n);let t=e.scanUnquotedString();return t?t.text:n}var pr=class{constructor(e){this.cssDataManager=e}selectorToMarkedString(e,t){let r=xa(e);if(r){let i=new hr('"').print(r,t);return i.push(this.selectorToSpecificityMarkedString(e)),i}else return[]}simpleSelectorToMarkedString(e){let t=Ys(e),r=new hr('"').print(t);return r.push(this.selectorToSpecificityMarkedString(e)),r}isPseudoElementIdentifier(e){let t=e.match(/^::?([\w-]+)/);return t?!!this.cssDataManager.getPseudoElement("::"+t[1]):!1}selectorToSpecificityMarkedString(e){let t=s=>{let a=new nn,l=new nn;for(let o of s)for(let d of o.getChildren()){let h=r(d);if(h.id>l.id){l=h;continue}else if(h.idl.attr){l=h;continue}else if(h.attrl.tag){l=h;continue}}return a.id+=l.id,a.attr+=l.attr,a.tag+=l.tag,a},r=s=>{let a=new nn;e:for(let l of s.getChildren()){switch(l.type){case m.IdentifierSelector:a.id++;break;case m.ClassSelector:case m.AttributeSelector:a.attr++;break;case m.ElementNameSelector:if(l.matches("*"))break;a.tag++;break;case m.PseudoSelector:let o=l.getText(),d=l.getChildren();if(this.isPseudoElementIdentifier(o)){if(o.match(/^::slotted/i)&&d.length>0){a.tag++;let h=t(d);a.id+=h.id,a.attr+=h.attr,a.tag+=h.tag;continue e}a.tag++;continue e}if(o.match(/^:where/i))continue e;if(o.match(/^:(?:not|has|is)/i)&&d.length>0){let h=t(d);a.id+=h.id,a.attr+=h.attr,a.tag+=h.tag;continue e}if(o.match(/^:(?:host|host-context)/i)&&d.length>0){a.attr++;let h=t(d);a.id+=h.id,a.attr+=h.attr,a.tag+=h.tag;continue e}if(o.match(/^:(?:nth-child|nth-last-child)/i)&&d.length>0){if(a.attr++,d.length===3&&d[1].type===23){let y=t(d[2].getChildren());a.id+=y.id,a.attr+=y.attr,a.tag+=y.tag;continue e}let h=new ke,u=d[1].getText();h.scanner.setSource(u);let w=h.scanner.scan(),b=h.scanner.scan();if(w.text==="n"||w.text==="-n"&&b.text==="of"){let y=[],A=u.slice(b.offset+2).split(",");for(let P of A){let T=h.internalParse(P,h._parseSelector);T&&y.push(T)}let I=t(y);a.id+=I.id,a.attr+=I.attr,a.tag+=I.tag;continue e}continue e}a.attr++;continue e}if(l.getChildren().length>0){let o=r(l);a.id+=o.id,a.attr+=o.attr,a.tag+=o.tag}}return a},i=r(e);return`[${p("Selector Specificity")}](https://developer.mozilla.org/docs/Web/CSS/Specificity): (${i.id}, ${i.attr}, ${i.tag})`}},Si=class{constructor(e){this.prev=null,this.element=e}processSelector(e){let t=null;if(!(this.element instanceof Ye)&&e.getChildren().some(r=>r.hasChildren()&&r.getChild(0).type===m.SelectorCombinator)){let r=this.element.findRoot();r.parent instanceof Ye&&(t=this.element,this.element=r.parent,this.element.removeChild(r),this.prev=null)}for(let r of e.getChildren()){if(r instanceof he){if(this.prev instanceof he){let a=new sn("\u2026");this.element.addChild(a),this.element=a}else this.prev&&(this.prev.matches("+")||this.prev.matches("~"))&&this.element.parent&&(this.element=this.element.parent);this.prev&&this.prev.matches("~")&&this.element.addChild(new sn("\u22EE"));let i=Ys(r,t),s=i.findRoot();this.element.addChild(s),this.element=i}(r instanceof he||r.type===m.SelectorCombinatorParent||r.type===m.SelectorCombinatorShadowPiercingDescendant||r.type===m.SelectorCombinatorSibling||r.type===m.SelectorCombinatorAllSiblings)&&(this.prev=r)}}};function ya(n){switch(n.type){case m.MixinDeclaration:case m.Stylesheet:return!0}return!1}function xa(n){if(n.matches("@at-root"))return null;let e=new Ye,t=[],r=n.getParent();if(r instanceof ae){let s=r.getParent();for(;s&&!ya(s);){if(s instanceof ae){if(s.getSelectors().matches("@at-root"))break;t.push(s)}s=s.getParent()}}let i=new Si(e);for(let s=t.length-1;s>=0;s--){let a=t[s].getSelectors().getChild(0);a&&i.processSelector(a)}return i.processSelector(n),e}var _t=class{constructor(e,t){this.clientCapabilities=e,this.cssDataManager=t,this.selectorPrinting=new pr(t)}configure(e){this.defaultSettings=e}doHover(e,t,r,i=this.defaultSettings){function s(h){return R.create(e.positionAt(h.offset),e.positionAt(h.end))}let a=e.offsetAt(t),l=vt(r,a),o=null,d;for(let h=0;htypeof t=="string"?t:t.value):e.value}doesSupportMarkdown(){if(!ie(this.supportsMarkdown)){if(!ie(this.clientCapabilities))return this.supportsMarkdown=!0,this.supportsMarkdown;let e=this.clientCapabilities.textDocument&&this.clientCapabilities.textDocument.hover;this.supportsMarkdown=e&&e.contentFormat&&Array.isArray(e.contentFormat)&&e.contentFormat.indexOf(se.Markdown)!==-1}return this.supportsMarkdown}};var Qs=/^\w+:\/\//,Zs=/^data:/,lt=class{constructor(e,t){this.fileSystemProvider=e,this.resolveModuleReferences=t}configure(e){this.defaultSettings=e}findDefinition(e,t,r){let i=new ot(r),s=e.offsetAt(t),a=Hn(r,s);if(!a)return null;let l=i.findSymbolFromNode(a);return l?{uri:e.uri,range:Pe(l.node,e)}:null}findReferences(e,t,r){return this.findDocumentHighlights(e,t,r).map(s=>({uri:e.uri,range:s.range}))}getHighlightNode(e,t,r){let i=e.offsetAt(t),s=Hn(r,i);if(!(!s||s.type===m.Stylesheet||s.type===m.Declarations))return s.type===m.Identifier&&s.parent&&s.parent.type===m.ClassSelector&&(s=s.parent),s}findDocumentHighlights(e,t,r){let i=[],s=this.getHighlightNode(e,t,r);if(!s)return i;let a=new ot(r),l=a.findSymbolFromNode(s),o=s.getText();return r.accept(d=>{if(l){if(a.matchesSymbol(d,l))return i.push({kind:to(d),range:Pe(d,e)}),!1}else s&&s.type===d.type&&d.matches(o)&&i.push({kind:to(d),range:Pe(d,e)});return!0}),i}isRawStringDocumentLinkNode(e){return e.type===m.Import}findDocumentLinks(e,t,r){let i=this.findUnresolvedLinks(e,t),s=[];for(let a of i){let l=a.link,o=l.target;if(!(!o||Zs.test(o)))if(Qs.test(o))s.push(l);else{let d=r.resolveReference(o,e.uri);d&&(l.target=d),s.push(l)}}return s}async findDocumentLinks2(e,t,r){let i=this.findUnresolvedLinks(e,t),s=[];for(let a of i){let l=a.link,o=l.target;if(!(!o||Zs.test(o)))if(Qs.test(o))s.push(l);else{let d=await this.resolveReference(o,e.uri,r,a.isRawLink);d!==void 0&&(l.target=d,s.push(l))}}return s}findUnresolvedLinks(e,t){let r=[],i=s=>{let a=s.getText(),l=Pe(s,e);if(l.start.line===l.end.line&&l.start.character===l.end.character)return;(V(a,"'")||V(a,'"'))&&(a=a.slice(1,-1));let o=s.parent?this.isRawStringDocumentLinkNode(s.parent):!1;r.push({link:{target:a,range:l},isRawLink:o})};return t.accept(s=>{if(s.type===m.URILiteral){let a=s.getChild(0);return a&&i(a),!1}if(s.parent&&this.isRawStringDocumentLinkNode(s.parent)){let a=s.getText();return(V(a,"'")||V(a,'"'))&&i(s),!1}return!0}),r}findSymbolInformations(e,t){let r=[],i=(s,a,l)=>{let o=l instanceof x?Pe(l,e):l,d={name:s||p(""),kind:a,location:it.create(e.uri,o)};r.push(d)};return this.collectDocumentSymbols(e,t,i),r}findDocumentSymbols(e,t){let r=[],i=[],s=(a,l,o,d,h)=>{let u=o instanceof x?Pe(o,e):o,w=d instanceof x?Pe(d,e):d;(!w||!eo(u,w))&&(w=R.create(u.start,u.start));let b={name:a||p(""),kind:l,range:u,selectionRange:w},y=i.pop();for(;y&&!eo(y[1],u);)y=i.pop();if(y){let E=y[0];E.children||(E.children=[]),E.children.push(b),i.push(y)}else r.push(b);h&&i.push([b,Pe(h,e)])};return this.collectDocumentSymbols(e,t,s),r}collectDocumentSymbols(e,t,r){t.accept(i=>{if(i instanceof ae){for(let s of i.getSelectors().getChildren())if(s instanceof de){let a=R.create(e.positionAt(s.offset),e.positionAt(i.end));r(s.getText(),ge.Class,a,s,i.getDeclarations())}}else if(i instanceof xe)r(i.getName(),ge.Variable,i,i.getVariable(),void 0);else if(i instanceof ue)r(i.getName(),ge.Method,i,i.getIdentifier(),i.getDeclarations());else if(i instanceof De)r(i.getName(),ge.Function,i,i.getIdentifier(),i.getDeclarations());else if(i instanceof mt){let s=p("@keyframes {0}",i.getName());r(s,ge.Class,i,i.getIdentifier(),i.getDeclarations())}else if(i instanceof pt){let s=p("@font-face");r(s,ge.Class,i,void 0,i.getDeclarations())}else if(i instanceof Be){let s=i.getChild(0);if(s instanceof ut){let a="@media "+s.getText();r(a,ge.Module,i,s,i.getDeclarations())}}return!0})}findDocumentColors(e,t){let r=[];return t.accept(i=>{let s=Sa(i,e);return s&&r.push(s),!0}),r}getColorPresentations(e,t,r,i){let s=[],a=Math.round(r.red*255),l=Math.round(r.green*255),o=Math.round(r.blue*255),d;r.alpha===1?d=`rgb(${a}, ${l}, ${o})`:d=`rgba(${a}, ${l}, ${o}, ${r.alpha})`,s.push({label:d,textEdit:_.replace(i,d)}),r.alpha===1?d=`#${at(a)}${at(l)}${at(o)}`:d=`#${at(a)}${at(l)}${at(o)}${at(Math.round(r.alpha*255))}`,s.push({label:d,textEdit:_.replace(i,d)});let h=si(r);h.a===1?d=`hsl(${h.h}, ${Math.round(h.s*100)}%, ${Math.round(h.l*100)}%)`:d=`hsla(${h.h}, ${Math.round(h.s*100)}%, ${Math.round(h.l*100)}%, ${h.a})`,s.push({label:d,textEdit:_.replace(i,d)});let u=Us(r);return u.a===1?d=`hwb(${u.h} ${Math.round(u.w*100)}% ${Math.round(u.b*100)}%)`:d=`hwb(${u.h} ${Math.round(u.w*100)}% ${Math.round(u.b*100)}% / ${u.a})`,s.push({label:d,textEdit:_.replace(i,d)}),s}prepareRename(e,t,r){let i=this.getHighlightNode(e,t,r);if(i)return R.create(e.positionAt(i.offset),e.positionAt(i.end))}doRename(e,t,r,i){let a=this.findDocumentHighlights(e,t,i).map(l=>_.replace(l.range,r));return{changes:{[e.uri]:a}}}async resolveModuleReference(e,t,r){if(V(t,"file://")){let i=Ca(e);if(i&&i!=="."&&i!==".."){let s=r.resolveReference("/",t),a=ar(t),l=await this.resolvePathToModule(i,a,s);if(l){let o=e.substring(i.length+1);return Je(l,o)}}}}async mapReference(e,t){return e}async resolveReference(e,t,r,i=!1,s=this.defaultSettings){if(e[0]==="~"&&e[1]!=="/"&&this.fileSystemProvider)return e=e.substring(1),this.mapReference(await this.resolveModuleReference(e,t,r),i);let a=await this.mapReference(r.resolveReference(e,t),i);if(this.resolveModuleReferences){if(a&&await this.fileExists(a))return a;let l=await this.mapReference(await this.resolveModuleReference(e,t,r),i);if(l)return l}if(a&&!await this.fileExists(a)){let l=r.resolveReference("/",t);if(s&&l){if(e in s)return this.mapReference(Je(l,s[e]),i);let o=e.indexOf("/"),d=`${e.substring(0,o)}/`;if(d in s){let h=s[d].slice(0,-1),u=Je(l,h);return this.mapReference(u=Je(u,e.substring(d.length-1)),i)}}}return a}async resolvePathToModule(e,t,r){let i=Je(t,"node_modules",e,"package.json");if(await this.fileExists(i))return ar(i);if(r&&t.startsWith(r)&&t.length!==r.length)return this.resolvePathToModule(e,ar(t),r)}async fileExists(e){if(!this.fileSystemProvider)return!1;try{let t=await this.fileSystemProvider.stat(e);return!(t.type===st.Unknown&&t.size===-1)}catch{return!1}}};function Sa(n,e){let t=Vs(n);if(t){let r=Pe(n,e);return{color:t,range:r}}return null}function Pe(n,e){return R.create(e.positionAt(n.offset),e.positionAt(n.end))}function eo(n,e){let t=e.start.line,r=e.end.line,i=n.start.line,s=n.end.line;return!(ts||r>s||t===i&&e.start.charactern.end.character)}function to(n){if(n.type===m.Selector)return Ge.Write;if(n instanceof G&&n.parent&&n.parent instanceof Ve&&n.isCustomProperty)return Ge.Write;if(n.parent)switch(n.parent.type){case m.FunctionDeclaration:case m.MixinDeclaration:case m.Keyframe:case m.VariableDeclaration:case m.FunctionParameter:return Ge.Write}return Ge.Read}function at(n){let e=n.toString(16);return e.length!==2?"0"+e:e}function Ca(n){let e=n.indexOf("/");if(e===-1)return"";if(n[0]==="@"){let t=n.indexOf("/",e+1);return t===-1?n:n.substring(0,t)}return n.substring(0,e)}var It=ee.Warning,no=ee.Error,be=ee.Ignore,q=class{constructor(e,t,r){this.id=e,this.message=t,this.defaultValue=r}},Ci=class{constructor(e,t,r){this.id=e,this.message=t,this.defaultValue=r}},W={AllVendorPrefixes:new q("compatibleVendorPrefixes",p("When using a vendor-specific prefix make sure to also include all other vendor-specific properties"),be),IncludeStandardPropertyWhenUsingVendorPrefix:new q("vendorPrefix",p("When using a vendor-specific prefix also include the standard property"),It),DuplicateDeclarations:new q("duplicateProperties",p("Do not use duplicate style definitions"),be),EmptyRuleSet:new q("emptyRules",p("Do not use empty rulesets"),It),ImportStatemement:new q("importStatement",p("Import statements do not load in parallel"),be),BewareOfBoxModelSize:new q("boxModel",p("Do not use width or height when using padding or border"),be),UniversalSelector:new q("universalSelector",p("The universal selector (*) is known to be slow"),be),ZeroWithUnit:new q("zeroUnits",p("No unit for zero needed"),be),RequiredPropertiesForFontFace:new q("fontFaceProperties",p("@font-face rule must define 'src' and 'font-family' properties"),It),HexColorLength:new q("hexColorLength",p("Hex colors must consist of three, four, six or eight hex numbers"),no),ArgsInColorFunction:new q("argumentsInColorFunction",p("Invalid number of parameters"),no),UnknownProperty:new q("unknownProperties",p("Unknown property."),It),UnknownAtRules:new q("unknownAtRules",p("Unknown at-rule."),It),IEStarHack:new q("ieHack",p("IE hacks are only necessary when supporting IE7 and older"),be),UnknownVendorSpecificProperty:new q("unknownVendorSpecificProperties",p("Unknown vendor specific property."),be),PropertyIgnoredDueToDisplay:new q("propertyIgnoredDueToDisplay",p("Property is ignored due to the display."),It),AvoidImportant:new q("important",p("Avoid using !important. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored."),be),AvoidFloat:new q("float",p("Avoid using 'float'. Floats lead to fragile CSS that is easy to break if one aspect of the layout changes."),be),AvoidIdSelector:new q("idSelector",p("Selectors should not contain IDs because these rules are too tightly coupled with the HTML."),be)},ro={ValidProperties:new Ci("validProperties",p("A list of properties that are not validated against the `unknownProperties` rule."),[])},mr=class{constructor(e={}){this.conf=e}getRule(e){if(this.conf.hasOwnProperty(e.id)){let t=ka(this.conf[e.id]);if(t)return t}return e.defaultValue}getSetting(e){return this.conf[e.id]}};function ka(n){switch(n){case"ignore":return ee.Ignore;case"warning":return ee.Warning;case"error":return ee.Error}return null}var Dt=class{constructor(e){this.cssDataManager=e}doCodeActions(e,t,r,i){return this.doCodeActions2(e,t,r,i).map(s=>{let a=s.edit&&s.edit.documentChanges&&s.edit.documentChanges[0];return Me.create(s.title,"_css.applyCodeAction",e.uri,e.version,a&&a.edits)})}doCodeActions2(e,t,r,i){let s=[];if(r.diagnostics)for(let a of r.diagnostics)this.appendFixesForMarker(e,i,a,s);return s}getFixesForUnknownProperty(e,t,r,i){let s=t.getName(),a=[];this.cssDataManager.getProperties().forEach(o=>{let d=Hi(s,o.name);d>=s.length/2&&a.push({property:o.name,score:d})}),a.sort((o,d)=>d.score-o.score||o.property.localeCompare(d.property));let l=3;for(let o of a){let d=o.property,h=p("Rename to '{0}'",d),u=_.replace(r.range,d),w=qt.create(e.uri,e.version),b={documentChanges:[St.create(w,[u])]},y=Ht.create(h,b,Gt.QuickFix);if(y.diagnostics=[r],i.push(y),--l<=0)return}}appendFixesForMarker(e,t,r,i){if(r.code!==W.UnknownProperty.id)return;let s=e.offsetAt(r.range.start),a=e.offsetAt(r.range.end),l=vt(t,s);for(let o=l.length-1;o>=0;o--){let d=l[o];if(d instanceof Q){let h=d.getProperty();if(h&&h.offset===s&&h.end===a){this.getFixesForUnknownProperty(e,h,r,i);return}}}}};var ur=class{constructor(e){this.fullPropertyName=e.getFullPropertyName().toLowerCase(),this.node=e}};function on(n,e,t,r){let i=n[e];i.value=t,t&&(gi(i.properties,r)||i.properties.push(r))}function Fa(n,e,t){on(n,"top",e,t),on(n,"right",e,t),on(n,"bottom",e,t),on(n,"left",e,t)}function ne(n,e,t,r){e==="top"||e==="right"||e==="bottom"||e==="left"?on(n,e,t,r):Fa(n,t,r)}function ki(n,e,t){switch(e.length){case 1:ne(n,void 0,e[0],t);break;case 2:ne(n,"top",e[0],t),ne(n,"bottom",e[0],t),ne(n,"right",e[1],t),ne(n,"left",e[1],t);break;case 3:ne(n,"top",e[0],t),ne(n,"right",e[1],t),ne(n,"left",e[1],t),ne(n,"bottom",e[2],t);break;case 4:ne(n,"top",e[0],t),ne(n,"right",e[1],t),ne(n,"bottom",e[2],t),ne(n,"left",e[3],t);break}}function Fi(n,e){for(let t of e)if(n.matches(t))return!0;return!1}function an(n,e=!0){return e&&Fi(n,["initial","unset"])?!1:parseFloat(n.getText())!==0}function io(n,e=!0){return n.map(t=>an(t,e))}function fr(n,e=!0){return!(Fi(n,["none","hidden"])||e&&Fi(n,["initial","unset"]))}function Ea(n,e=!0){return n.map(t=>fr(t,e))}function _a(n){let e=n.getChildren();if(e.length===1){let t=e[0];return an(t)&&fr(t)}for(let t of e){let r=t;if(!an(r,!1)||!fr(r,!1))return!1}return!0}function Ei(n){let e={top:{value:!1,properties:[]},right:{value:!1,properties:[]},bottom:{value:!1,properties:[]},left:{value:!1,properties:[]}};for(let t of n){let r=t.node.value;if(!(typeof r>"u"))switch(t.fullPropertyName){case"box-sizing":return{top:{value:!1,properties:[]},right:{value:!1,properties:[]},bottom:{value:!1,properties:[]},left:{value:!1,properties:[]}};case"width":e.width=t;break;case"height":e.height=t;break;default:let i=t.fullPropertyName.split("-");switch(i[0]){case"border":switch(i[1]){case void 0:case"top":case"right":case"bottom":case"left":switch(i[2]){case void 0:ne(e,i[1],_a(r),t);break;case"width":ne(e,i[1],an(r,!1),t);break;case"style":ne(e,i[1],fr(r,!0),t);break}break;case"width":ki(e,io(r.getChildren(),!1),t);break;case"style":ki(e,Ea(r.getChildren(),!0),t);break}break;case"padding":i.length===1?ki(e,io(r.getChildren(),!0),t):ne(e,i[1],an(r,!0),t);break}break}}return e}var gr=class{constructor(){this.data={}}add(e,t,r){let i=this.data[e];i||(i={nodes:[],names:[]},this.data[e]=i),i.names.push(t),r&&i.nodes.push(r)}},ln=class n{static entries(e,t,r,i,s){let a=new n(t,r,i);return e.acceptVisitor(a),a.completeValidations(),a.getEntries(s)}constructor(e,t,r){this.cssDataManager=r,this.warnings=[],this.settings=t,this.documentText=e.getText(),this.keyframes=new gr,this.validProperties={};let i=t.getSetting(ro.ValidProperties);Array.isArray(i)&&i.forEach(s=>{if(typeof s=="string"){let a=s.trim().toLowerCase();a.length&&(this.validProperties[a]=!0)}})}isValidPropertyDeclaration(e){let t=e.fullPropertyName;return this.validProperties[t]}fetch(e,t){let r=[];for(let i of e)i.fullPropertyName===t&&r.push(i);return r}fetchWithValue(e,t,r){let i=[];for(let s of e)if(s.fullPropertyName===t){let a=s.node.getValue();a&&this.findValueInExpression(a,r)&&i.push(s)}return i}findValueInExpression(e,t){let r=!1;return e.accept(i=>(i.type===m.Identifier&&i.matches(t)&&(r=!0),!r)),r}getEntries(e=ee.Warning|ee.Error){return this.warnings.filter(t=>(t.getLevel()&e)!==0)}addEntry(e,t,r){let i=new wt(e,t,this.settings.getRule(t),r);this.warnings.push(i)}getMissingNames(e,t){let r=e.slice(0);for(let s=0;s0){let o=this.fetch(r,"float");for(let d=0;d0){let o=this.fetch(r,"vertical-align");for(let d=0;d1)for(let w=0;wX.startsWith(j))&&y.delete(P)}}let E=[];for(let I=0,P=n.prefixes.length;Is instanceof qe?(i+=1,!1):!0),i!==r&&this.addEntry(e,W.ArgsInColorFunction)),!0}};ln.prefixes=["-ms-","-moz-","-o-","-webkit-"];var Rt=class{constructor(e){this.cssDataManager=e}configure(e){this.settings=e}doValidation(e,t,r=this.settings){if(r&&r.validate===!1)return[];let i=[];i.push.apply(i,Gn.entries(t)),i.push.apply(i,ln.entries(t,e,new mr(r&&r.lint),this.cssDataManager));let s=[];for(let l in W)s.push(W[l].id);function a(l){let o=R.create(e.positionAt(l.getOffset()),e.positionAt(l.getOffset()+l.getLength())),d=e.languageId;return{code:l.getRule().id,source:d,message:l.getMessage(),severity:l.getLevel()===ee.Warning?yt.Warning:yt.Error,range:o}}return i.filter(l=>l.getLevel()!==ee.Ignore).map(a)}};var so=47,Ia=10,Da=13,Ra=12,za=36,Ma=35,Ta=123,cn=61,Na=33,Oa=60,Pa=62,_i=46;var Ae=c.CustomToken,br=Ae++,Mt=Ae++,pc=Ae++,Ii=Ae++,Di=Ae++,wr=Ae++,vr=Ae++,dn=Ae++,mc=Ae++,zt=class extends ce{scanNext(e){if(this.stream.advanceIfChar(za)){let t=["$"];if(this.ident(t))return this.finishToken(e,br,t.join(""));this.stream.goBackTo(e)}return this.stream.advanceIfChars([Ma,Ta])?this.finishToken(e,Mt):this.stream.advanceIfChars([cn,cn])?this.finishToken(e,Ii):this.stream.advanceIfChars([Na,cn])?this.finishToken(e,Di):this.stream.advanceIfChar(Oa)?this.stream.advanceIfChar(cn)?this.finishToken(e,vr):this.finishToken(e,c.Delim):this.stream.advanceIfChar(Pa)?this.stream.advanceIfChar(cn)?this.finishToken(e,wr):this.finishToken(e,c.Delim):this.stream.advanceIfChars([_i,_i,_i])?this.finishToken(e,dn):super.scanNext(e)}comment(){return super.comment()?!0:!this.inURL&&this.stream.advanceIfChars([so,so])?(this.stream.advanceWhileChar(e=>{switch(e){case Ia:case Da:case Ra:return!1;default:return!0}}),!0):!1}};var hn=class{constructor(e,t){this.id=e,this.message=t}},yr={FromExpected:new hn("scss-fromexpected",p("'from' expected")),ThroughOrToExpected:new hn("scss-throughexpected",p("'through' or 'to' expected")),InExpected:new hn("scss-fromexpected",p("'in' expected"))};var xr=class extends ke{constructor(){super(new zt)}_parseStylesheetStatement(e=!1){return this.peek(c.AtKeyword)?this._parseWarnAndDebug()||this._parseControlStatement()||this._parseMixinDeclaration()||this._parseMixinContent()||this._parseMixinReference()||this._parseFunctionDeclaration()||this._parseForward()||this._parseUse()||this._parseRuleset(e)||super._parseStylesheetAtStatement(e):this._parseRuleset(!0)||this._parseVariableDeclaration()}_parseImport(){if(!this.peekKeyword("@import"))return null;let e=this.create(je);if(this.consumeToken(),!e.addChild(this._parseURILiteral())&&!e.addChild(this._parseStringLiteral()))return this.finish(e,f.URIOrStringExpected);for(;this.accept(c.Comma);)if(!e.addChild(this._parseURILiteral())&&!e.addChild(this._parseStringLiteral()))return this.finish(e,f.URIOrStringExpected);return this._completeParseImport(e)}_parseVariableDeclaration(e=[]){if(!this.peek(br))return null;let t=this.create(xe);if(!t.setVariable(this._parseVariable()))return null;if(!this.accept(c.Colon))return this.finish(t,f.ColonExpected);if(this.prevToken&&(t.colonPosition=this.prevToken.offset),!t.setValue(this._parseExpr()))return this.finish(t,f.VariableValueExpected,[],e);for(;this.peek(c.Exclamation);)if(!t.addChild(this._tryParsePrio())){if(this.consumeToken(),!this.peekRegExp(c.Ident,/^(default|global)$/))return this.finish(t,f.UnknownKeyword);this.consumeToken()}return this.peek(c.SemiColon)&&(t.semicolonPosition=this.token.offset),this.finish(t)}_parseMediaCondition(){return this._parseInterpolation()||super._parseMediaCondition()}_parseMediaFeatureRangeOperator(){return this.accept(vr)||this.accept(wr)||super._parseMediaFeatureRangeOperator()}_parseMediaFeatureName(){return this._parseModuleMember()||this._parseFunction()||this._parseIdent()||this._parseVariable()}_parseKeyframeSelector(){return this._tryParseKeyframeSelector()||this._parseControlStatement(this._parseKeyframeSelector.bind(this))||this._parseWarnAndDebug()||this._parseMixinReference()||this._parseFunctionDeclaration()||this._parseVariableDeclaration()||this._parseMixinContent()}_parseVariable(){if(!this.peek(br))return null;let e=this.create(Ke);return this.consumeToken(),e}_parseModuleMember(){let e=this.mark(),t=this.create(jt);return t.setIdentifier(this._parseIdent([z.Module]))?this.hasWhitespace()||!this.acceptDelim(".")||this.hasWhitespace()?(this.restoreAtMark(e),null):t.addChild(this._parseVariable()||this._parseFunction())?t:this.finish(t,f.IdentifierOrVariableExpected):null}_parseIdent(e){if(!this.peek(c.Ident)&&!this.peek(Mt)&&!this.peekDelim("-"))return null;let t=this.create(G);t.referenceTypes=e,t.isCustomProperty=this.peekRegExp(c.Ident,/^--/);let r=!1,i=()=>{let s=this.mark();return this.acceptDelim("-")&&(this.hasWhitespace()||this.acceptDelim("-"),this.hasWhitespace())?(this.restoreAtMark(s),null):this._parseInterpolation()};for(;(this.accept(c.Ident)||t.addChild(i())||r&&this.acceptRegexp(/^[\w-]/))&&(r=!0,!this.hasWhitespace()););return r?this.finish(t):null}_parseTermExpression(){return this._parseModuleMember()||this._parseVariable()||this._parseNestingSelector()||super._parseTermExpression()}_parseInterpolation(){if(this.peek(Mt)){let e=this.create(rt);return this.consumeToken(),!e.addChild(this._parseExpr())&&!this._parseNestingSelector()?this.accept(c.CurlyR)?this.finish(e):this.finish(e,f.ExpressionExpected):this.accept(c.CurlyR)?this.finish(e):this.finish(e,f.RightCurlyExpected)}return null}_parseOperator(){if(this.peek(Ii)||this.peek(Di)||this.peek(wr)||this.peek(vr)||this.peekDelim(">")||this.peekDelim("<")||this.peekIdent("and")||this.peekIdent("or")||this.peekDelim("%")){let e=this.createNode(m.Operator);return this.consumeToken(),this.finish(e)}return super._parseOperator()}_parseUnaryOperator(){if(this.peekIdent("not")){let e=this.create(x);return this.consumeToken(),this.finish(e)}return super._parseUnaryOperator()}_parseRuleSetDeclaration(){return this.peek(c.AtKeyword)?this._parseKeyframe()||this._parseImport()||this._parseMedia(!0)||this._parseFontFace()||this._parseWarnAndDebug()||this._parseControlStatement()||this._parseFunctionDeclaration()||this._parseExtends()||this._parseMixinReference()||this._parseMixinContent()||this._parseMixinDeclaration()||this._parseRuleset(!0)||this._parseSupports(!0)||this._parseLayer()||this._parsePropertyAtRule()||this._parseContainer(!0)||this._parseRuleSetDeclarationAtStatement():this._parseVariableDeclaration()||this._tryParseRuleset(!0)||this._parseDeclaration()}_parseDeclaration(e){let t=this._tryParseCustomPropertyDeclaration(e);if(t)return t;let r=this.create(Q);if(!r.setProperty(this._parseProperty()))return null;if(!this.accept(c.Colon))return this.finish(r,f.ColonExpected,[c.Colon],e||[c.SemiColon]);this.prevToken&&(r.colonPosition=this.prevToken.offset);let i=!1;if(r.setValue(this._parseExpr())&&(i=!0,r.addChild(this._parsePrio())),this.peek(c.CurlyL))r.setNestedProperties(this._parseNestedProperties());else if(!i)return this.finish(r,f.PropertyValueExpected);return this.peek(c.SemiColon)&&(r.semicolonPosition=this.token.offset),this.finish(r)}_parseNestedProperties(){let e=this.create(Ut);return this._parseBody(e,this._parseDeclaration.bind(this))}_parseExtends(){if(this.peekKeyword("@extend")){let e=this.create(Se);if(this.consumeToken(),!e.getSelectors().addChild(this._parseSimpleSelector()))return this.finish(e,f.SelectorExpected);for(;this.accept(c.Comma);)e.getSelectors().addChild(this._parseSimpleSelector());return this.accept(c.Exclamation)&&!this.acceptIdent("optional")?this.finish(e,f.UnknownKeyword):this.finish(e)}return null}_parseSimpleSelectorBody(){return this._parseSelectorPlaceholder()||super._parseSimpleSelectorBody()}_parseNestingSelector(){if(this.peekDelim("&")){let e=this.createNode(m.SelectorCombinator);for(this.consumeToken();!this.hasWhitespace()&&(this.acceptDelim("-")||this.accept(c.Num)||this.accept(c.Dimension)||e.addChild(this._parseIdent())||this.acceptDelim("&")););return this.finish(e)}return null}_parseSelectorPlaceholder(){if(this.peekDelim("%")){let e=this.createNode(m.SelectorPlaceholder);return this.consumeToken(),this._parseIdent(),this.finish(e)}else if(this.peekKeyword("@at-root")){let e=this.createNode(m.SelectorPlaceholder);if(this.consumeToken(),this.accept(c.ParenthesisL)){if(!this.acceptIdent("with")&&!this.acceptIdent("without"))return this.finish(e,f.IdentifierExpected);if(!this.accept(c.Colon))return this.finish(e,f.ColonExpected);if(!e.addChild(this._parseIdent()))return this.finish(e,f.IdentifierExpected);if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[c.CurlyR])}return this.finish(e)}return null}_parseElementName(){let e=this.mark(),t=super._parseElementName();return t&&!this.hasWhitespace()&&this.peek(c.ParenthesisL)?(this.restoreAtMark(e),null):t}_tryParsePseudoIdentifier(){return this._parseInterpolation()||super._tryParsePseudoIdentifier()}_parseWarnAndDebug(){if(!this.peekKeyword("@debug")&&!this.peekKeyword("@warn")&&!this.peekKeyword("@error"))return null;let e=this.createNode(m.Debug);return this.consumeToken(),e.addChild(this._parseExpr()),this.finish(e)}_parseControlStatement(e=this._parseRuleSetDeclaration.bind(this)){return this.peek(c.AtKeyword)?this._parseIfStatement(e)||this._parseForStatement(e)||this._parseEachStatement(e)||this._parseWhileStatement(e):null}_parseIfStatement(e){return this.peekKeyword("@if")?this._internalParseIfStatement(e):null}_internalParseIfStatement(e){let t=this.create(yn);if(this.consumeToken(),!t.setExpression(this._parseExpr(!0)))return this.finish(t,f.ExpressionExpected);if(this._parseBody(t,e),this.acceptKeyword("@else")){if(this.peekIdent("if"))t.setElseClause(this._internalParseIfStatement(e));else if(this.peek(c.CurlyL)){let r=this.create(kn);this._parseBody(r,e),t.setElseClause(r)}}return this.finish(t)}_parseForStatement(e){if(!this.peekKeyword("@for"))return null;let t=this.create(xn);return this.consumeToken(),t.setVariable(this._parseVariable())?this.acceptIdent("from")?t.addChild(this._parseBinaryExpr())?!this.acceptIdent("to")&&!this.acceptIdent("through")?this.finish(t,yr.ThroughOrToExpected,[c.CurlyR]):t.addChild(this._parseBinaryExpr())?this._parseBody(t,e):this.finish(t,f.ExpressionExpected,[c.CurlyR]):this.finish(t,f.ExpressionExpected,[c.CurlyR]):this.finish(t,yr.FromExpected,[c.CurlyR]):this.finish(t,f.VariableNameExpected,[c.CurlyR])}_parseEachStatement(e){if(!this.peekKeyword("@each"))return null;let t=this.create(Sn);this.consumeToken();let r=t.getVariables();if(!r.addChild(this._parseVariable()))return this.finish(t,f.VariableNameExpected,[c.CurlyR]);for(;this.accept(c.Comma);)if(!r.addChild(this._parseVariable()))return this.finish(t,f.VariableNameExpected,[c.CurlyR]);return this.finish(r),this.acceptIdent("in")?t.addChild(this._parseExpr())?this._parseBody(t,e):this.finish(t,f.ExpressionExpected,[c.CurlyR]):this.finish(t,yr.InExpected,[c.CurlyR])}_parseWhileStatement(e){if(!this.peekKeyword("@while"))return null;let t=this.create(Cn);return this.consumeToken(),t.addChild(this._parseBinaryExpr())?this._parseBody(t,e):this.finish(t,f.ExpressionExpected,[c.CurlyR])}_parseFunctionBodyDeclaration(){return this._parseVariableDeclaration()||this._parseReturnStatement()||this._parseWarnAndDebug()||this._parseControlStatement(this._parseFunctionBodyDeclaration.bind(this))}_parseFunctionDeclaration(){if(!this.peekKeyword("@function"))return null;let e=this.create(De);if(this.consumeToken(),!e.setIdentifier(this._parseIdent([z.Function])))return this.finish(e,f.IdentifierExpected,[c.CurlyR]);if(!this.accept(c.ParenthesisL))return this.finish(e,f.LeftParenthesisExpected,[c.CurlyR]);if(e.getParameters().addChild(this._parseParameterDeclaration())){for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)if(!e.getParameters().addChild(this._parseParameterDeclaration()))return this.finish(e,f.VariableNameExpected)}return this.accept(c.ParenthesisR)?this._parseBody(e,this._parseFunctionBodyDeclaration.bind(this)):this.finish(e,f.RightParenthesisExpected,[c.CurlyR])}_parseReturnStatement(){if(!this.peekKeyword("@return"))return null;let e=this.createNode(m.ReturnStatement);return this.consumeToken(),e.addChild(this._parseExpr())?this.finish(e):this.finish(e,f.ExpressionExpected)}_parseMixinDeclaration(){if(!this.peekKeyword("@mixin"))return null;let e=this.create(ue);if(this.consumeToken(),!e.setIdentifier(this._parseIdent([z.Mixin])))return this.finish(e,f.IdentifierExpected,[c.CurlyR]);if(this.accept(c.ParenthesisL)){if(e.getParameters().addChild(this._parseParameterDeclaration())){for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)if(!e.getParameters().addChild(this._parseParameterDeclaration()))return this.finish(e,f.VariableNameExpected)}if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[c.CurlyR])}return this._parseBody(e,this._parseRuleSetDeclaration.bind(this))}_parseParameterDeclaration(){let e=this.create(ye);return e.setIdentifier(this._parseVariable())?(this.accept(dn),this.accept(c.Colon)&&!e.setDefaultValue(this._parseExpr(!0))?this.finish(e,f.VariableValueExpected,[],[c.Comma,c.ParenthesisR]):this.finish(e)):null}_parseMixinContent(){if(!this.peekKeyword("@content"))return null;let e=this.create(Vn);if(this.consumeToken(),this.accept(c.ParenthesisL)){if(e.getArguments().addChild(this._parseFunctionArgument())){for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)if(!e.getArguments().addChild(this._parseFunctionArgument()))return this.finish(e,f.ExpressionExpected)}if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected)}return this.finish(e)}_parseMixinReference(){if(!this.peekKeyword("@include"))return null;let e=this.create(ze);this.consumeToken();let t=this._parseIdent([z.Mixin]);if(!e.setIdentifier(t))return this.finish(e,f.IdentifierExpected,[c.CurlyR]);if(!this.hasWhitespace()&&this.acceptDelim(".")&&!this.hasWhitespace()){let r=this._parseIdent([z.Mixin]);if(!r)return this.finish(e,f.IdentifierExpected,[c.CurlyR]);let i=this.create(jt);t.referenceTypes=[z.Module],i.setIdentifier(t),e.setIdentifier(r),e.addChild(i)}if(this.accept(c.ParenthesisL)){if(e.getArguments().addChild(this._parseFunctionArgument())){for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)if(!e.getArguments().addChild(this._parseFunctionArgument()))return this.finish(e,f.ExpressionExpected)}if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected)}return(this.peekIdent("using")||this.peek(c.CurlyL))&&e.setContent(this._parseMixinContentDeclaration()),this.finish(e)}_parseMixinContentDeclaration(){let e=this.create(jn);if(this.acceptIdent("using")){if(!this.accept(c.ParenthesisL))return this.finish(e,f.LeftParenthesisExpected,[c.CurlyL]);if(e.getParameters().addChild(this._parseParameterDeclaration())){for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)if(!e.getParameters().addChild(this._parseParameterDeclaration()))return this.finish(e,f.VariableNameExpected)}if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[c.CurlyL])}return this.peek(c.CurlyL)&&this._parseBody(e,this._parseMixinReferenceBodyStatement.bind(this)),this.finish(e)}_parseMixinReferenceBodyStatement(){return this._tryParseKeyframeSelector()||this._parseRuleSetDeclaration()}_parseFunctionArgument(){let e=this.create(le),t=this.mark(),r=this._parseVariable();if(r)if(this.accept(c.Colon))e.setIdentifier(r);else{if(this.accept(dn))return e.setValue(r),this.finish(e);this.restoreAtMark(t)}return e.setValue(this._parseExpr(!0))?(this.accept(dn),e.addChild(this._parsePrio()),this.finish(e)):e.setValue(this._tryParsePrio())?this.finish(e):null}_parseURLArgument(){let e=this.mark(),t=super._parseURLArgument();if(!t||!this.peek(c.ParenthesisR)){this.restoreAtMark(e);let r=this.create(x);return r.addChild(this._parseBinaryExpr()),this.finish(r)}return t}_parseOperation(){if(!this.peek(c.ParenthesisL))return null;let e=this.create(x);for(this.consumeToken();e.addChild(this._parseListElement());)this.accept(c.Comma);return this.accept(c.ParenthesisR)?this.finish(e):this.finish(e,f.RightParenthesisExpected)}_parseListElement(){let e=this.create(Bn),t=this._parseBinaryExpr();if(!t)return null;if(this.accept(c.Colon)){if(e.setKey(t),!e.setValue(this._parseBinaryExpr()))return this.finish(e,f.ExpressionExpected)}else e.setValue(t);return this.finish(e)}_parseUse(){if(!this.peekKeyword("@use"))return null;let e=this.create(En);if(this.consumeToken(),!e.addChild(this._parseStringLiteral()))return this.finish(e,f.StringLiteralExpected);if(!this.peek(c.SemiColon)&&!this.peek(c.EOF)){if(!this.peekRegExp(c.Ident,/as|with/))return this.finish(e,f.UnknownKeyword);if(this.acceptIdent("as")&&!e.setIdentifier(this._parseIdent([z.Module]))&&!this.acceptDelim("*"))return this.finish(e,f.IdentifierOrWildcardExpected);if(this.acceptIdent("with")){if(!this.accept(c.ParenthesisL))return this.finish(e,f.LeftParenthesisExpected,[c.ParenthesisR]);if(!e.getParameters().addChild(this._parseModuleConfigDeclaration()))return this.finish(e,f.VariableNameExpected);for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)if(!e.getParameters().addChild(this._parseModuleConfigDeclaration()))return this.finish(e,f.VariableNameExpected);if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected)}}return!this.accept(c.SemiColon)&&!this.accept(c.EOF)?this.finish(e,f.SemiColonExpected):this.finish(e)}_parseModuleConfigDeclaration(){let e=this.create(_n);return e.setIdentifier(this._parseVariable())?!this.accept(c.Colon)||!e.setValue(this._parseExpr(!0))?this.finish(e,f.VariableValueExpected,[],[c.Comma,c.ParenthesisR]):this.accept(c.Exclamation)&&(this.hasWhitespace()||!this.acceptIdent("default"))?this.finish(e,f.UnknownKeyword):this.finish(e):null}_parseForward(){if(!this.peekKeyword("@forward"))return null;let e=this.create(In);if(this.consumeToken(),!e.addChild(this._parseStringLiteral()))return this.finish(e,f.StringLiteralExpected);if(this.acceptIdent("as")){let t=this._parseIdent([z.Forward]);if(!e.setIdentifier(t))return this.finish(e,f.IdentifierExpected);if(this.hasWhitespace()||!this.acceptDelim("*"))return this.finish(e,f.WildcardExpected)}if(this.acceptIdent("with")){if(!this.accept(c.ParenthesisL))return this.finish(e,f.LeftParenthesisExpected,[c.ParenthesisR]);if(!e.getParameters().addChild(this._parseModuleConfigDeclaration()))return this.finish(e,f.VariableNameExpected);for(;this.accept(c.Comma)&&!this.peek(c.ParenthesisR);)if(!e.getParameters().addChild(this._parseModuleConfigDeclaration()))return this.finish(e,f.VariableNameExpected);if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected)}else if((this.peekIdent("hide")||this.peekIdent("show"))&&!e.addChild(this._parseForwardVisibility()))return this.finish(e,f.IdentifierOrVariableExpected);return!this.accept(c.SemiColon)&&!this.accept(c.EOF)?this.finish(e,f.SemiColonExpected):this.finish(e)}_parseForwardVisibility(){let e=this.create(Dn);for(e.setIdentifier(this._parseIdent());e.addChild(this._parseVariable()||this._parseIdent());)this.accept(c.Comma);return e.getChildren().length>1?e:null}_parseSupportsCondition(){return this._parseInterpolation()||super._parseSupportsCondition()}};var We=p("Sass documentation"),we=class n extends Xe{constructor(e,t){super("$",e,t),oo(n.scssModuleLoaders),oo(n.scssModuleBuiltIns)}isImportPathParent(e){return e===m.Forward||e===m.Use||super.isImportPathParent(e)}getCompletionForImportPath(e,t){let r=e.getParent().type;if(r===m.Forward||r===m.Use)for(let i of n.scssModuleBuiltIns){let s={label:i.label,documentation:i.documentation,textEdit:_.replace(this.getCompletionRange(e),`'${i.label}'`),kind:k.Module};t.items.push(s)}return super.getCompletionForImportPath(e,t)}createReplaceFunction(){let e=1;return(t,r)=>"\\"+r+": ${"+e+++":"+(n.variableDefaults[r]||"")+"}"}createFunctionProposals(e,t,r,i){for(let s of e){let a=s.func.replace(/\[?(\$\w+)\]?/g,this.createReplaceFunction()),o={label:s.func.substr(0,s.func.indexOf("(")),detail:s.func,documentation:s.desc,textEdit:_.replace(this.getCompletionRange(t),a),insertTextFormat:te.Snippet,kind:k.Function};r&&(o.sortText="z"),i.items.push(o)}return i}getCompletionsForSelector(e,t,r){return this.createFunctionProposals(n.selectorFuncs,null,!0,r),super.getCompletionsForSelector(e,t,r)}getTermProposals(e,t,r){let i=n.builtInFuncs;return e&&(i=i.filter(s=>!s.type||!e.restrictions||e.restrictions.indexOf(s.type)!==-1)),this.createFunctionProposals(i,t,!0,r),super.getTermProposals(e,t,r)}getColorProposals(e,t,r){return this.createFunctionProposals(n.colorProposals,t,!1,r),super.getColorProposals(e,t,r)}getCompletionsForDeclarationProperty(e,t){return this.getCompletionForAtDirectives(t),this.getCompletionsForSelector(null,!0,t),super.getCompletionsForDeclarationProperty(e,t)}getCompletionsForExtendsReference(e,t,r){let i=this.getSymbolContext().findSymbolsAtOffset(this.offset,z.Rule);for(let s of i){let a={label:s.name,textEdit:_.replace(this.getCompletionRange(t),s.name),kind:k.Function};r.items.push(a)}return r}getCompletionForAtDirectives(e){return e.items.push(...n.scssAtDirectives),e}getCompletionForTopLevel(e){return this.getCompletionForAtDirectives(e),this.getCompletionForModuleLoaders(e),super.getCompletionForTopLevel(e),e}getCompletionForModuleLoaders(e){return e.items.push(...n.scssModuleLoaders),e}};we.variableDefaults={$red:"1",$green:"2",$blue:"3",$alpha:"1.0",$color:"#000000",$weight:"0.5",$hue:"0",$saturation:"0%",$lightness:"0%",$degrees:"0",$amount:"0",$string:'""',$substring:'"s"',$number:"0",$limit:"1"};we.colorProposals=[{func:"red($color)",desc:p("Gets the red component of a color.")},{func:"green($color)",desc:p("Gets the green component of a color.")},{func:"blue($color)",desc:p("Gets the blue component of a color.")},{func:"mix($color, $color, [$weight])",desc:p("Mixes two colors together.")},{func:"hue($color)",desc:p("Gets the hue component of a color.")},{func:"saturation($color)",desc:p("Gets the saturation component of a color.")},{func:"lightness($color)",desc:p("Gets the lightness component of a color.")},{func:"adjust-hue($color, $degrees)",desc:p("Changes the hue of a color.")},{func:"lighten($color, $amount)",desc:p("Makes a color lighter.")},{func:"darken($color, $amount)",desc:p("Makes a color darker.")},{func:"saturate($color, $amount)",desc:p("Makes a color more saturated.")},{func:"desaturate($color, $amount)",desc:p("Makes a color less saturated.")},{func:"grayscale($color)",desc:p("Converts a color to grayscale.")},{func:"complement($color)",desc:p("Returns the complement of a color.")},{func:"invert($color)",desc:p("Returns the inverse of a color.")},{func:"alpha($color)",desc:p("Gets the opacity component of a color.")},{func:"opacity($color)",desc:"Gets the alpha component (opacity) of a color."},{func:"rgba($color, $alpha)",desc:p("Changes the alpha component for a color.")},{func:"opacify($color, $amount)",desc:p("Makes a color more opaque.")},{func:"fade-in($color, $amount)",desc:p("Makes a color more opaque.")},{func:"transparentize($color, $amount)",desc:p("Makes a color more transparent.")},{func:"fade-out($color, $amount)",desc:p("Makes a color more transparent.")},{func:"adjust-color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])",desc:p("Increases or decreases one or more components of a color.")},{func:"scale-color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])",desc:p("Fluidly scales one or more properties of a color.")},{func:"change-color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])",desc:p("Changes one or more properties of a color.")},{func:"ie-hex-str($color)",desc:p("Converts a color into the format understood by IE filters.")}];we.selectorFuncs=[{func:"selector-nest($selectors\u2026)",desc:p("Nests selector beneath one another like they would be nested in the stylesheet.")},{func:"selector-append($selectors\u2026)",desc:p("Appends selectors to one another without spaces in between.")},{func:"selector-extend($selector, $extendee, $extender)",desc:p("Extends $extendee with $extender within $selector.")},{func:"selector-replace($selector, $original, $replacement)",desc:p("Replaces $original with $replacement within $selector.")},{func:"selector-unify($selector1, $selector2)",desc:p("Unifies two selectors to produce a selector that matches elements matched by both.")},{func:"is-superselector($super, $sub)",desc:p("Returns whether $super matches all the elements $sub does, and possibly more.")},{func:"simple-selectors($selector)",desc:p("Returns the simple selectors that comprise a compound selector.")},{func:"selector-parse($selector)",desc:p("Parses a selector into the format returned by &.")}];we.builtInFuncs=[{func:"unquote($string)",desc:p("Removes quotes from a string.")},{func:"quote($string)",desc:p("Adds quotes to a string.")},{func:"str-length($string)",desc:p("Returns the number of characters in a string.")},{func:"str-insert($string, $insert, $index)",desc:p("Inserts $insert into $string at $index.")},{func:"str-index($string, $substring)",desc:p("Returns the index of the first occurance of $substring in $string.")},{func:"str-slice($string, $start-at, [$end-at])",desc:p("Extracts a substring from $string.")},{func:"to-upper-case($string)",desc:p("Converts a string to upper case.")},{func:"to-lower-case($string)",desc:p("Converts a string to lower case.")},{func:"percentage($number)",desc:p("Converts a unitless number to a percentage."),type:"percentage"},{func:"round($number)",desc:p("Rounds a number to the nearest whole number.")},{func:"ceil($number)",desc:p("Rounds a number up to the next whole number.")},{func:"floor($number)",desc:p("Rounds a number down to the previous whole number.")},{func:"abs($number)",desc:p("Returns the absolute value of a number.")},{func:"min($numbers)",desc:p("Finds the minimum of several numbers.")},{func:"max($numbers)",desc:p("Finds the maximum of several numbers.")},{func:"random([$limit])",desc:p("Returns a random number.")},{func:"length($list)",desc:p("Returns the length of a list.")},{func:"nth($list, $n)",desc:p("Returns a specific item in a list.")},{func:"set-nth($list, $n, $value)",desc:p("Replaces the nth item in a list.")},{func:"join($list1, $list2, [$separator])",desc:p("Joins together two lists into one.")},{func:"append($list1, $val, [$separator])",desc:p("Appends a single value onto the end of a list.")},{func:"zip($lists)",desc:p("Combines several lists into a single multidimensional list.")},{func:"index($list, $value)",desc:p("Returns the position of a value within a list.")},{func:"list-separator(#list)",desc:p("Returns the separator of a list.")},{func:"map-get($map, $key)",desc:p("Returns the value in a map associated with a given key.")},{func:"map-merge($map1, $map2)",desc:p("Merges two maps together into a new map.")},{func:"map-remove($map, $keys)",desc:p("Returns a new map with keys removed.")},{func:"map-keys($map)",desc:p("Returns a list of all keys in a map.")},{func:"map-values($map)",desc:p("Returns a list of all values in a map.")},{func:"map-has-key($map, $key)",desc:p("Returns whether a map has a value associated with a given key.")},{func:"keywords($args)",desc:p("Returns the keywords passed to a function that takes variable arguments.")},{func:"feature-exists($feature)",desc:p("Returns whether a feature exists in the current Sass runtime.")},{func:"variable-exists($name)",desc:p("Returns whether a variable with the given name exists in the current scope.")},{func:"global-variable-exists($name)",desc:p("Returns whether a variable with the given name exists in the global scope.")},{func:"function-exists($name)",desc:p("Returns whether a function with the given name exists.")},{func:"mixin-exists($name)",desc:p("Returns whether a mixin with the given name exists.")},{func:"inspect($value)",desc:p("Returns the string representation of a value as it would be represented in Sass.")},{func:"type-of($value)",desc:p("Returns the type of a value.")},{func:"unit($number)",desc:p("Returns the unit(s) associated with a number.")},{func:"unitless($number)",desc:p("Returns whether a number has units.")},{func:"comparable($number1, $number2)",desc:p("Returns whether two numbers can be added, subtracted, or compared.")},{func:"call($name, $args\u2026)",desc:p("Dynamically calls a Sass function.")}];we.scssAtDirectives=[{label:"@extend",documentation:p("Inherits the styles of another selector."),kind:k.Keyword},{label:"@at-root",documentation:p("Causes one or more rules to be emitted at the root of the document."),kind:k.Keyword},{label:"@debug",documentation:p("Prints the value of an expression to the standard error output stream. Useful for debugging complicated Sass files."),kind:k.Keyword},{label:"@warn",documentation:p("Prints the value of an expression to the standard error output stream. Useful for libraries that need to warn users of deprecations or recovering from minor mixin usage mistakes. Warnings can be turned off with the `--quiet` command-line option or the `:quiet` Sass option."),kind:k.Keyword},{label:"@error",documentation:p("Throws the value of an expression as a fatal error with stack trace. Useful for validating arguments to mixins and functions."),kind:k.Keyword},{label:"@if",documentation:p("Includes the body if the expression does not evaluate to `false` or `null`."),insertText:`@if \${1:expr} { $0 }`,insertTextFormat:te.Snippet,kind:k.Keyword},{label:"@for",documentation:p("For loop that repeatedly outputs a set of styles for each `$var` in the `from/through` or `from/to` clause."),insertText:"@for \\$${1:var} from ${2:start} ${3|to,through|} ${4:end} {\n $0\n}",insertTextFormat:te.Snippet,kind:k.Keyword},{label:"@each",documentation:p("Each loop that sets `$var` to each item in the list or map, then outputs the styles it contains using that value of `$var`."),insertText:"@each \\$${1:var} in ${2:list} {\n $0\n}",insertTextFormat:te.Snippet,kind:k.Keyword},{label:"@while",documentation:p("While loop that takes an expression and repeatedly outputs the nested styles until the statement evaluates to `false`."),insertText:`@while \${1:condition} { $0 }`,insertTextFormat:te.Snippet,kind:k.Keyword},{label:"@mixin",documentation:p("Defines styles that can be re-used throughout the stylesheet with `@include`."),insertText:`@mixin \${1:name} { $0 }`,insertTextFormat:te.Snippet,kind:k.Keyword},{label:"@include",documentation:p("Includes the styles defined by another mixin into the current rule."),kind:k.Keyword},{label:"@function",documentation:p("Defines complex operations that can be re-used throughout stylesheets."),kind:k.Keyword}];we.scssModuleLoaders=[{label:"@use",documentation:p("Loads mixins, functions, and variables from other Sass stylesheets as 'modules', and combines CSS from multiple stylesheets together."),references:[{name:We,url:"https://sass-lang.com/documentation/at-rules/use"}],insertText:"@use $0;",insertTextFormat:te.Snippet,kind:k.Keyword},{label:"@forward",documentation:p("Loads a Sass stylesheet and makes its mixins, functions, and variables available when this stylesheet is loaded with the @use rule."),references:[{name:We,url:"https://sass-lang.com/documentation/at-rules/forward"}],insertText:"@forward $0;",insertTextFormat:te.Snippet,kind:k.Keyword}];we.scssModuleBuiltIns=[{label:"sass:math",documentation:p("Provides functions that operate on numbers."),references:[{name:We,url:"https://sass-lang.com/documentation/modules/math"}]},{label:"sass:string",documentation:p("Makes it easy to combine, search, or split apart strings."),references:[{name:We,url:"https://sass-lang.com/documentation/modules/string"}]},{label:"sass:color",documentation:p("Generates new colors based on existing ones, making it easy to build color themes."),references:[{name:We,url:"https://sass-lang.com/documentation/modules/color"}]},{label:"sass:list",documentation:p("Lets you access and modify values in lists."),references:[{name:We,url:"https://sass-lang.com/documentation/modules/list"}]},{label:"sass:map",documentation:p("Makes it possible to look up the value associated with a key in a map, and much more."),references:[{name:We,url:"https://sass-lang.com/documentation/modules/map"}]},{label:"sass:selector",documentation:p("Provides access to Sass\u2019s powerful selector engine."),references:[{name:We,url:"https://sass-lang.com/documentation/modules/selector"}]},{label:"sass:meta",documentation:p("Exposes the details of Sass\u2019s inner workings."),references:[{name:We,url:"https://sass-lang.com/documentation/modules/meta"}]}];function oo(n){n.forEach(e=>{if(e.documentation&&e.references&&e.references.length>0){let t=typeof e.documentation=="string"?{kind:"markdown",value:e.documentation}:{kind:"markdown",value:e.documentation.value};t.value+=` `,t.value+=e.references.map(r=>`[${r.name}](${r.url})`).join(" | "),e.documentation=t}})}var ao=47,Wa=10,La=13,$a=12,Ri=96,zi=46,Ua=c.CustomToken,Sr=Ua++,Tt=class extends ce{scanNext(e){let t=this.escapedJavaScript();return t!==null?this.finishToken(e,t):this.stream.advanceIfChars([zi,zi,zi])?this.finishToken(e,Sr):super.scanNext(e)}comment(){return super.comment()?!0:!this.inURL&&this.stream.advanceIfChars([ao,ao])?(this.stream.advanceWhileChar(e=>{switch(e){case Wa:case La:case $a:return!1;default:return!0}}),!0):!1}escapedJavaScript(){return this.stream.peekChar()===Ri?(this.stream.advance(1),this.stream.advanceWhileChar(t=>t!==Ri),this.stream.advanceIfChar(Ri)?c.EscapedJavaScript:c.BadEscapedJavaScript):null}};var Cr=class extends ke{constructor(){super(new Tt)}_parseStylesheetStatement(e=!1){return this.peek(c.AtKeyword)?this._parseVariableDeclaration()||this._parsePlugin()||super._parseStylesheetAtStatement(e):this._tryParseMixinDeclaration()||this._tryParseMixinReference()||this._parseFunction()||this._parseRuleset(!0)}_parseImport(){if(!this.peekKeyword("@import")&&!this.peekKeyword("@import-once"))return null;let e=this.create(je);if(this.consumeToken(),this.accept(c.ParenthesisL)){if(!this.accept(c.Ident))return this.finish(e,f.IdentifierExpected,[c.SemiColon]);do if(!this.accept(c.Comma))break;while(this.accept(c.Ident));if(!this.accept(c.ParenthesisR))return this.finish(e,f.RightParenthesisExpected,[c.SemiColon])}return!e.addChild(this._parseURILiteral())&&!e.addChild(this._parseStringLiteral())?this.finish(e,f.URIOrStringExpected,[c.SemiColon]):(!this.peek(c.SemiColon)&&!this.peek(c.EOF)&&e.setMedialist(this._parseMediaQueryList()),this._completeParseImport(e))}_parsePlugin(){if(!this.peekKeyword("@plugin"))return null;let e=this.createNode(m.Plugin);return this.consumeToken(),e.addChild(this._parseStringLiteral())?this.accept(c.SemiColon)?this.finish(e):this.finish(e,f.SemiColonExpected):this.finish(e,f.StringLiteralExpected)}_parseMediaQuery(){let e=super._parseMediaQuery();if(!e){let t=this.create(ft);return t.addChild(this._parseVariable())?this.finish(t):null}return e}_parseMediaDeclaration(e=!1){return this._tryParseRuleset(e)||this._tryToParseDeclaration()||this._tryParseMixinDeclaration()||this._tryParseMixinReference()||this._parseDetachedRuleSetMixin()||this._parseStylesheetStatement(e)}_parseMediaFeatureName(){return this._parseIdent()||this._parseVariable()}_parseVariableDeclaration(e=[]){let t=this.create(xe),r=this.mark();if(!t.setVariable(this._parseVariable(!0)))return null;if(this.accept(c.Colon)){if(this.prevToken&&(t.colonPosition=this.prevToken.offset),t.setValue(this._parseDetachedRuleSet()))t.needsSemicolon=!1;else if(!t.setValue(this._parseExpr()))return this.finish(t,f.VariableValueExpected,[],e);t.addChild(this._parsePrio())}else return this.restoreAtMark(r),null;return this.peek(c.SemiColon)&&(t.semicolonPosition=this.token.offset),this.finish(t)}_parseDetachedRuleSet(){let e=this.mark();if(this.peekDelim("#")||this.peekDelim("."))if(this.consumeToken(),!this.hasWhitespace()&&this.accept(c.ParenthesisL)){let r=this.create(ue);if(r.getParameters().addChild(this._parseMixinParameter()))for(;(this.accept(c.Comma)||this.accept(c.SemiColon))&&!this.peek(c.ParenthesisR);)r.getParameters().addChild(this._parseMixinParameter())||this.markError(r,f.IdentifierExpected,[],[c.ParenthesisR]);if(!this.accept(c.ParenthesisR))return this.restoreAtMark(e),null}else return this.restoreAtMark(e),null;if(!this.peek(c.CurlyL))return null;let t=this.create(L);return this._parseBody(t,this._parseDetachedRuleSetBody.bind(this)),this.finish(t)}_parseDetachedRuleSetBody(){return this._tryParseKeyframeSelector()||this._parseRuleSetDeclaration()}_addLookupChildren(e){if(!e.addChild(this._parseLookupValue()))return!1;let t=!1;for(;this.peek(c.BracketL)&&(t=!0),!!e.addChild(this._parseLookupValue());)t=!1;return!t}_parseLookupValue(){let e=this.create(x),t=this.mark();return this.accept(c.BracketL)?(e.addChild(this._parseVariable(!1,!0))||e.addChild(this._parsePropertyIdentifier()))&&this.accept(c.BracketR)||this.accept(c.BracketR)?e:(this.restoreAtMark(t),null):(this.restoreAtMark(t),null)}_parseVariable(e=!1,t=!1){let r=!e&&this.peekDelim("$");if(!this.peekDelim("@")&&!r&&!this.peek(c.AtKeyword))return null;let i=this.create(Ke),s=this.mark();for(;this.acceptDelim("@")||!e&&this.acceptDelim("$");)if(this.hasWhitespace())return this.restoreAtMark(s),null;return!this.accept(c.AtKeyword)&&!this.accept(c.Ident)?(this.restoreAtMark(s),null):!t&&this.peek(c.BracketL)&&!this._addLookupChildren(i)?(this.restoreAtMark(s),null):i}_parseTermExpression(){return this._parseVariable()||this._parseEscaped()||super._parseTermExpression()||this._tryParseMixinReference(!1)}_parseEscaped(){if(this.peek(c.EscapedJavaScript)||this.peek(c.BadEscapedJavaScript)){let e=this.createNode(m.EscapedValue);return this.consumeToken(),this.finish(e)}if(this.peekDelim("~")){let e=this.createNode(m.EscapedValue);return this.consumeToken(),this.accept(c.String)||this.accept(c.EscapedJavaScript)?this.finish(e):this.finish(e,f.TermExpected)}return null}_parseOperator(){let e=this._parseGuardOperator();return e||super._parseOperator()}_parseGuardOperator(){if(this.peekDelim(">")){let e=this.createNode(m.Operator);return this.consumeToken(),this.acceptDelim("="),e}else if(this.peekDelim("=")){let e=this.createNode(m.Operator);return this.consumeToken(),this.acceptDelim("<"),e}else if(this.peekDelim("<")){let e=this.createNode(m.Operator);return this.consumeToken(),this.acceptDelim("="),e}return null}_parseRuleSetDeclaration(){return this.peek(c.AtKeyword)?this._parseKeyframe()||this._parseMedia(!0)||this._parseImport()||this._parseSupports(!0)||this._parseLayer()||this._parsePropertyAtRule()||this._parseContainer(!0)||this._parseDetachedRuleSetMixin()||this._parseVariableDeclaration()||this._parseRuleSetDeclarationAtStatement():this._tryParseMixinDeclaration()||this._tryParseRuleset(!0)||this._tryParseMixinReference()||this._parseFunction()||this._parseExtend()||this._parseDeclaration()}_parseKeyframeIdent(){return this._parseIdent([z.Keyframe])||this._parseVariable()}_parseKeyframeSelector(){return this._parseDetachedRuleSetMixin()||super._parseKeyframeSelector()}_parseSelector(e){let t=this.create(de),r=!1;for(e&&(r=t.addChild(this._parseCombinator()));t.addChild(this._parseSimpleSelector());){r=!0;let i=this.mark();if(t.addChild(this._parseGuard())&&this.peek(c.CurlyL))break;this.restoreAtMark(i),t.addChild(this._parseCombinator())}return r?this.finish(t):null}_parseNestingSelector(){if(this.peekDelim("&")){let e=this.createNode(m.SelectorCombinator);for(this.consumeToken();!this.hasWhitespace()&&(this.acceptDelim("-")||this.accept(c.Num)||this.accept(c.Dimension)||e.addChild(this._parseIdent())||this.acceptDelim("&")););return this.finish(e)}return null}_parseSelectorIdent(){if(!this.peekInterpolatedIdent())return null;let e=this.createNode(m.SelectorInterpolation);return this._acceptInterpolatedIdent(e)?this.finish(e):null}_parsePropertyIdentifier(e=!1){let t=/^[\w-]+/;if(!this.peekInterpolatedIdent()&&!this.peekRegExp(this.token.type,t))return null;let r=this.mark(),i=this.create(G);i.isCustomProperty=this.acceptDelim("-")&&this.acceptDelim("-");let s=!1;return e?i.isCustomProperty?s=i.addChild(this._parseIdent()):s=i.addChild(this._parseRegexp(t)):i.isCustomProperty?s=this._acceptInterpolatedIdent(i):s=this._acceptInterpolatedIdent(i,t),s?(!e&&!this.hasWhitespace()&&(this.acceptDelim("+"),this.hasWhitespace()||this.acceptIdent("_")),this.finish(i)):(this.restoreAtMark(r),null)}peekInterpolatedIdent(){return this.peek(c.Ident)||this.peekDelim("@")||this.peekDelim("$")||this.peekDelim("-")}_acceptInterpolatedIdent(e,t){let r=!1,i=()=>{let a=this.mark();return this.acceptDelim("-")&&(this.hasWhitespace()||this.acceptDelim("-"),this.hasWhitespace())?(this.restoreAtMark(a),null):this._parseInterpolation()},s=t?()=>this.acceptRegexp(t):()=>this.accept(c.Ident);for(;(s()||e.addChild(this._parseInterpolation()||this.try(i)))&&(r=!0,!this.hasWhitespace()););return r}_parseInterpolation(){let e=this.mark();if(this.peekDelim("@")||this.peekDelim("$")){let t=this.createNode(m.Interpolation);return this.consumeToken(),this.hasWhitespace()||!this.accept(c.CurlyL)?(this.restoreAtMark(e),null):t.addChild(this._parseIdent())?this.accept(c.CurlyR)?this.finish(t):this.finish(t,f.RightCurlyExpected):this.finish(t,f.IdentifierExpected)}return null}_tryParseMixinDeclaration(){let e=this.mark(),t=this.create(ue);if(!t.setIdentifier(this._parseMixinDeclarationIdentifier())||!this.accept(c.ParenthesisL))return this.restoreAtMark(e),null;if(t.getParameters().addChild(this._parseMixinParameter()))for(;(this.accept(c.Comma)||this.accept(c.SemiColon))&&!this.peek(c.ParenthesisR);)t.getParameters().addChild(this._parseMixinParameter())||this.markError(t,f.IdentifierExpected,[],[c.ParenthesisR]);return this.accept(c.ParenthesisR)?(t.setGuard(this._parseGuard()),this.peek(c.CurlyL)?this._parseBody(t,this._parseMixInBodyDeclaration.bind(this)):(this.restoreAtMark(e),null)):(this.restoreAtMark(e),null)}_parseMixInBodyDeclaration(){return this._parseFontFace()||this._parseRuleSetDeclaration()}_parseMixinDeclarationIdentifier(){let e;if(this.peekDelim("#")||this.peekDelim(".")){if(e=this.create(G),this.consumeToken(),this.hasWhitespace()||!e.addChild(this._parseIdent()))return null}else if(this.peek(c.Hash))e=this.create(G),this.consumeToken();else return null;return e.referenceTypes=[z.Mixin],this.finish(e)}_parsePseudo(){if(!this.peek(c.Colon))return null;let e=this.mark(),t=this.create(Se);return this.consumeToken(),this.acceptIdent("extend")?this._completeExtends(t):(this.restoreAtMark(e),super._parsePseudo())}_parseExtend(){if(!this.peekDelim("&"))return null;let e=this.mark(),t=this.create(Se);return this.consumeToken(),this.hasWhitespace()||!this.accept(c.Colon)||!this.acceptIdent("extend")?(this.restoreAtMark(e),null):this._completeExtends(t)}_completeExtends(e){if(!this.accept(c.ParenthesisL))return this.finish(e,f.LeftParenthesisExpected);let t=e.getSelectors();if(!t.addChild(this._parseSelector(!0)))return this.finish(e,f.SelectorExpected);for(;this.accept(c.Comma);)if(!t.addChild(this._parseSelector(!0)))return this.finish(e,f.SelectorExpected);return this.accept(c.ParenthesisR)?this.finish(e):this.finish(e,f.RightParenthesisExpected)}_parseDetachedRuleSetMixin(){if(!this.peek(c.AtKeyword))return null;let e=this.mark(),t=this.create(ze);return t.addChild(this._parseVariable(!0))&&(this.hasWhitespace()||!this.accept(c.ParenthesisL))?(this.restoreAtMark(e),null):this.accept(c.ParenthesisR)?this.finish(t):this.finish(t,f.RightParenthesisExpected)}_tryParseMixinReference(e=!0){let t=this.mark(),r=this.create(ze),i=this._parseMixinDeclarationIdentifier();for(;i;){this.acceptDelim(">");let a=this._parseMixinDeclarationIdentifier();if(a)r.getNamespaces().addChild(i),i=a;else break}if(!r.setIdentifier(i))return this.restoreAtMark(t),null;let s=!1;if(this.accept(c.ParenthesisL)){if(s=!0,r.getArguments().addChild(this._parseMixinArgument())){for(;(this.accept(c.Comma)||this.accept(c.SemiColon))&&!this.peek(c.ParenthesisR);)if(!r.getArguments().addChild(this._parseMixinArgument()))return this.finish(r,f.ExpressionExpected)}if(!this.accept(c.ParenthesisR))return this.finish(r,f.RightParenthesisExpected);i.referenceTypes=[z.Mixin]}else i.referenceTypes=[z.Mixin,z.Rule];return this.peek(c.BracketL)?e||this._addLookupChildren(r):r.addChild(this._parsePrio()),!s&&!this.peek(c.SemiColon)&&!this.peek(c.CurlyR)&&!this.peek(c.EOF)?(this.restoreAtMark(t),null):this.finish(r)}_parseMixinArgument(){let e=this.create(le),t=this.mark(),r=this._parseVariable();return r&&(this.accept(c.Colon)?e.setIdentifier(r):this.restoreAtMark(t)),e.setValue(this._parseDetachedRuleSet()||this._parseExpr(!0))?this.finish(e):(this.restoreAtMark(t),null)}_parseMixinParameter(){let e=this.create(ye);if(this.peekKeyword("@rest")){let r=this.create(x);return this.consumeToken(),this.accept(Sr)?(e.setIdentifier(this.finish(r)),this.finish(e)):this.finish(e,f.DotExpected,[],[c.Comma,c.ParenthesisR])}if(this.peek(Sr)){let r=this.create(x);return this.consumeToken(),e.setIdentifier(this.finish(r)),this.finish(e)}let t=!1;return e.setIdentifier(this._parseVariable())&&(this.accept(c.Colon),t=!0),!e.setDefaultValue(this._parseDetachedRuleSet()||this._parseExpr(!0))&&!t?null:this.finish(e)}_parseGuard(){if(!this.peekIdent("when"))return null;let e=this.create(qn);if(this.consumeToken(),!e.getConditions().addChild(this._parseGuardCondition()))return this.finish(e,f.ConditionExpected);for(;this.acceptIdent("and")||this.accept(c.Comma);)if(!e.getConditions().addChild(this._parseGuardCondition()))return this.finish(e,f.ConditionExpected);return this.finish(e)}_parseGuardCondition(){let e=this.create(Kn);return e.isNegated=this.acceptIdent("not"),this.accept(c.ParenthesisL)?(e.addChild(this._parseExpr()),this.accept(c.ParenthesisR)?this.finish(e):this.finish(e,f.RightParenthesisExpected)):e.isNegated?this.finish(e,f.LeftParenthesisExpected):null}_parseFunction(){let e=this.mark(),t=this.create(me);if(!t.setIdentifier(this._parseFunctionIdentifier()))return null;if(this.hasWhitespace()||!this.accept(c.ParenthesisL))return this.restoreAtMark(e),null;if(t.getArguments().addChild(this._parseMixinArgument())){for(;(this.accept(c.Comma)||this.accept(c.SemiColon))&&!this.peek(c.ParenthesisR);)if(!t.getArguments().addChild(this._parseMixinArgument()))return this.finish(t,f.ExpressionExpected)}return this.accept(c.ParenthesisR)?this.finish(t):this.finish(t,f.RightParenthesisExpected)}_parseFunctionIdentifier(){if(this.peekDelim("%")){let e=this.create(G);return e.referenceTypes=[z.Function],this.consumeToken(),this.finish(e)}return super._parseFunctionIdentifier()}_parseURLArgument(){let e=this.mark(),t=super._parseURLArgument();if(!t||!this.peek(c.ParenthesisR)){this.restoreAtMark(e);let r=this.create(x);return r.addChild(this._parseBinaryExpr()),this.finish(r)}return t}};var Nt=class n extends Xe{constructor(e,t){super("@",e,t)}createFunctionProposals(e,t,r,i){for(let s of e){let a={label:s.name,detail:s.example,documentation:s.description,textEdit:_.replace(this.getCompletionRange(t),s.name+"($0)"),insertTextFormat:te.Snippet,kind:k.Function};r&&(a.sortText="z"),i.items.push(a)}return i}getTermProposals(e,t,r){let i=n.builtInProposals;return e&&(i=i.filter(s=>!s.type||!e.restrictions||e.restrictions.indexOf(s.type)!==-1)),this.createFunctionProposals(i,t,!0,r),super.getTermProposals(e,t,r)}getColorProposals(e,t,r){return this.createFunctionProposals(n.colorProposals,t,!1,r),super.getColorProposals(e,t,r)}getCompletionsForDeclarationProperty(e,t){return this.getCompletionsForSelector(null,!0,t),super.getCompletionsForDeclarationProperty(e,t)}};Nt.builtInProposals=[{name:"if",example:"if(condition, trueValue [, falseValue]);",description:p("returns one of two values depending on a condition.")},{name:"boolean",example:"boolean(condition);",description:p('"store" a boolean test for later evaluation in a guard or if().')},{name:"length",example:"length(@list);",description:p("returns the number of elements in a value list")},{name:"extract",example:"extract(@list, index);",description:p("returns a value at the specified position in the list")},{name:"range",example:"range([start, ] end [, step]);",description:p("generate a list spanning a range of values")},{name:"each",example:"each(@list, ruleset);",description:p("bind the evaluation of a ruleset to each member of a list.")},{name:"escape",example:"escape(@string);",description:p("URL encodes a string")},{name:"e",example:"e(@string);",description:p("escape string content")},{name:"replace",example:"replace(@string, @pattern, @replacement[, @flags]);",description:p("string replace")},{name:"unit",example:"unit(@dimension, [@unit: '']);",description:p("remove or change the unit of a dimension")},{name:"color",example:"color(@string);",description:p("parses a string to a color"),type:"color"},{name:"convert",example:"convert(@value, unit);",description:p("converts numbers from one type into another")},{name:"data-uri",example:"data-uri([mimetype,] url);",description:p("inlines a resource and falls back to `url()`"),type:"url"},{name:"abs",description:p("absolute value of a number"),example:"abs(number);"},{name:"acos",description:p("arccosine - inverse of cosine function"),example:"acos(number);"},{name:"asin",description:p("arcsine - inverse of sine function"),example:"asin(number);"},{name:"ceil",example:"ceil(@number);",description:p("rounds up to an integer")},{name:"cos",description:p("cosine function"),example:"cos(number);"},{name:"floor",description:p("rounds down to an integer"),example:"floor(@number);"},{name:"percentage",description:p("converts to a %, e.g. 0.5 > 50%"),example:"percentage(@number);",type:"percentage"},{name:"round",description:p("rounds a number to a number of places"),example:"round(number, [places: 0]);"},{name:"sqrt",description:p("calculates square root of a number"),example:"sqrt(number);"},{name:"sin",description:p("sine function"),example:"sin(number);"},{name:"tan",description:p("tangent function"),example:"tan(number);"},{name:"atan",description:p("arctangent - inverse of tangent function"),example:"atan(number);"},{name:"pi",description:p("returns pi"),example:"pi();"},{name:"pow",description:p("first argument raised to the power of the second argument"),example:"pow(@base, @exponent);"},{name:"mod",description:p("first argument modulus second argument"),example:"mod(number, number);"},{name:"min",description:p("returns the lowest of one or more values"),example:"min(@x, @y);"},{name:"max",description:p("returns the lowest of one or more values"),example:"max(@x, @y);"}];Nt.colorProposals=[{name:"argb",example:"argb(@color);",description:p("creates a #AARRGGBB")},{name:"hsl",example:"hsl(@hue, @saturation, @lightness);",description:p("creates a color")},{name:"hsla",example:"hsla(@hue, @saturation, @lightness, @alpha);",description:p("creates a color")},{name:"hsv",example:"hsv(@hue, @saturation, @value);",description:p("creates a color")},{name:"hsva",example:"hsva(@hue, @saturation, @value, @alpha);",description:p("creates a color")},{name:"hue",example:"hue(@color);",description:p("returns the `hue` channel of `@color` in the HSL space")},{name:"saturation",example:"saturation(@color);",description:p("returns the `saturation` channel of `@color` in the HSL space")},{name:"lightness",example:"lightness(@color);",description:p("returns the `lightness` channel of `@color` in the HSL space")},{name:"hsvhue",example:"hsvhue(@color);",description:p("returns the `hue` channel of `@color` in the HSV space")},{name:"hsvsaturation",example:"hsvsaturation(@color);",description:p("returns the `saturation` channel of `@color` in the HSV space")},{name:"hsvvalue",example:"hsvvalue(@color);",description:p("returns the `value` channel of `@color` in the HSV space")},{name:"red",example:"red(@color);",description:p("returns the `red` channel of `@color`")},{name:"green",example:"green(@color);",description:p("returns the `green` channel of `@color`")},{name:"blue",example:"blue(@color);",description:p("returns the `blue` channel of `@color`")},{name:"alpha",example:"alpha(@color);",description:p("returns the `alpha` channel of `@color`")},{name:"luma",example:"luma(@color);",description:p("returns the `luma` value (perceptual brightness) of `@color`")},{name:"saturate",example:"saturate(@color, 10%);",description:p("return `@color` 10% points more saturated")},{name:"desaturate",example:"desaturate(@color, 10%);",description:p("return `@color` 10% points less saturated")},{name:"lighten",example:"lighten(@color, 10%);",description:p("return `@color` 10% points lighter")},{name:"darken",example:"darken(@color, 10%);",description:p("return `@color` 10% points darker")},{name:"fadein",example:"fadein(@color, 10%);",description:p("return `@color` 10% points less transparent")},{name:"fadeout",example:"fadeout(@color, 10%);",description:p("return `@color` 10% points more transparent")},{name:"fade",example:"fade(@color, 50%);",description:p("return `@color` with 50% transparency")},{name:"spin",example:"spin(@color, 10);",description:p("return `@color` with a 10 degree larger in hue")},{name:"mix",example:"mix(@color1, @color2, [@weight: 50%]);",description:p("return a mix of `@color1` and `@color2`")},{name:"greyscale",example:"greyscale(@color);",description:p("returns a grey, 100% desaturated color")},{name:"contrast",example:"contrast(@color1, [@darkcolor: black], [@lightcolor: white], [@threshold: 43%]);",description:p("return `@darkcolor` if `@color1 is> 43% luma` otherwise return `@lightcolor`, see notes")},{name:"multiply",example:"multiply(@color1, @color2);"},{name:"screen",example:"screen(@color1, @color2);"},{name:"overlay",example:"overlay(@color1, @color2);"},{name:"softlight",example:"softlight(@color1, @color2);"},{name:"hardlight",example:"hardlight(@color1, @color2);"},{name:"difference",example:"difference(@color1, @color2);"},{name:"exclusion",example:"exclusion(@color1, @color2);"},{name:"average",example:"average(@color1, @color2);"},{name:"negation",example:"negation(@color1, @color2);"}];function co(n,e){let t=ja(n);return Ba(t,e)}function ja(n){function e(h){return n.positionAt(h.offset).line}function t(h){return n.positionAt(h.offset+h.len).line}function r(){switch(n.languageId){case"scss":return new zt;case"less":return new Tt;default:return new ce}}function i(h,u){let w=e(h),b=t(h);return w!==b?{startLine:w,endLine:b,kind:u}:null}let s=[],a=[],l=r();l.ignoreComment=!1,l.setSource(n.getText());let o=l.scan(),d=null;for(;o.type!==c.EOF;){switch(o.type){case c.CurlyL:case Mt:{a.push({line:e(o),type:"brace",isStart:!0});break}case c.CurlyR:{if(a.length!==0){let h=lo(a,"brace");if(!h)break;let u=t(o);h.type==="brace"&&(d&&t(d)!==u&&u--,h.line!==u&&s.push({startLine:h.line,endLine:u,kind:void 0}))}break}case c.Comment:{let h=b=>b==="#region"?{line:e(o),type:"comment",isStart:!0}:{line:t(o),type:"comment",isStart:!1},w=(b=>{let y=b.text.match(/^\s*\/\*\s*(#region|#endregion)\b\s*(.*?)\s*\*\//);if(y)return h(y[1]);if(n.languageId==="scss"||n.languageId==="less"){let E=b.text.match(/^\s*\/\/\s*(#region|#endregion)\b\s*(.*?)\s*/);if(E)return h(E[1])}return null})(o);if(w)if(w.isStart)a.push(w);else{let b=lo(a,"comment");if(!b)break;b.type==="comment"&&b.line!==w.line&&s.push({startLine:b.line,endLine:w.line,kind:"region"})}else{let b=i(o,"comment");b&&s.push(b)}break}}d=o,o=l.scan()}return s}function lo(n,e){if(n.length===0)return null;for(let t=n.length-1;t>=0;t--)if(n[t].type===e&&n[t].isStart)return n.splice(t,1)[0];return null}function Ba(n,e){let t=e&&e.rangeLimit||Number.MAX_VALUE,r=n.sort((a,l)=>{let o=a.startLine-l.startLine;return o===0&&(o=a.endLine-l.endLine),o}),i=[],s=-1;return r.forEach(a=>{a.startLine=0;d--)if(this.__items[d].match(o))return!0;return!1},s.prototype.set_indent=function(o,d){this.is_empty()&&(this.__indent_count=o||0,this.__alignment_count=d||0,this.__character_count=this.__parent.get_indent_size(this.__indent_count,this.__alignment_count))},s.prototype._set_wrap_point=function(){this.__parent.wrap_line_length&&(this.__wrap_point_index=this.__items.length,this.__wrap_point_character_count=this.__character_count,this.__wrap_point_indent_count=this.__parent.next_line.__indent_count,this.__wrap_point_alignment_count=this.__parent.next_line.__alignment_count)},s.prototype._should_wrap=function(){return this.__wrap_point_index&&this.__character_count>this.__parent.wrap_line_length&&this.__wrap_point_character_count>this.__parent.next_line.__character_count},s.prototype._allow_wrap=function(){if(this._should_wrap()){this.__parent.add_new_line();var o=this.__parent.current_line;return o.set_indent(this.__wrap_point_indent_count,this.__wrap_point_alignment_count),o.__items=this.__items.slice(this.__wrap_point_index),this.__items=this.__items.slice(0,this.__wrap_point_index),o.__character_count+=this.__character_count-this.__wrap_point_character_count,this.__character_count=this.__wrap_point_character_count,o.__items[0]===" "&&(o.__items.splice(0,1),o.__character_count-=1),!0}return!1},s.prototype.is_empty=function(){return this.__items.length===0},s.prototype.last=function(){return this.is_empty()?null:this.__items[this.__items.length-1]},s.prototype.push=function(o){this.__items.push(o);var d=o.lastIndexOf(` `);d!==-1?this.__character_count=o.length-d:this.__character_count+=o.length},s.prototype.pop=function(){var o=null;return this.is_empty()||(o=this.__items.pop(),this.__character_count-=o.length),o},s.prototype._remove_indent=function(){this.__indent_count>0&&(this.__indent_count-=1,this.__character_count-=this.__parent.indent_size)},s.prototype._remove_wrap_indent=function(){this.__wrap_point_indent_count>0&&(this.__wrap_point_indent_count-=1)},s.prototype.trim=function(){for(;this.last()===" ";)this.__items.pop(),this.__character_count-=1},s.prototype.toString=function(){var o="";return this.is_empty()?this.__parent.indent_empty_lines&&(o=this.__parent.get_indent_string(this.__indent_count)):(o=this.__parent.get_indent_string(this.__indent_count,this.__alignment_count),o+=this.__items.join("")),o};function a(o,d){this.__cache=[""],this.__indent_size=o.indent_size,this.__indent_string=o.indent_char,o.indent_with_tabs||(this.__indent_string=new Array(o.indent_size+1).join(o.indent_char)),d=d||"",o.indent_level>0&&(d=new Array(o.indent_level+1).join(this.__indent_string)),this.__base_string=d,this.__base_string_length=d.length}a.prototype.get_indent_size=function(o,d){var h=this.__base_string_length;return d=d||0,o<0&&(h=0),h+=o*this.__indent_size,h+=d,h},a.prototype.get_indent_string=function(o,d){var h=this.__base_string;return d=d||0,o<0&&(o=0,h=""),d+=o*this.__indent_size,this.__ensure_cache(d),h+=this.__cache[d],h},a.prototype.__ensure_cache=function(o){for(;o>=this.__cache.length;)this.__add_column()},a.prototype.__add_column=function(){var o=this.__cache.length,d=0,h="";this.__indent_size&&o>=this.__indent_size&&(d=Math.floor(o/this.__indent_size),o-=d*this.__indent_size,h=new Array(d+1).join(this.__indent_string)),o&&(h+=new Array(o+1).join(" ")),this.__cache.push(h)};function l(o,d){this.__indent_cache=new a(o,d),this.raw=!1,this._end_with_newline=o.end_with_newline,this.indent_size=o.indent_size,this.wrap_line_length=o.wrap_line_length,this.indent_empty_lines=o.indent_empty_lines,this.__lines=[],this.previous_line=null,this.current_line=null,this.next_line=new s(this),this.space_before_token=!1,this.non_breaking_space=!1,this.previous_token_wrapped=!1,this.__add_outputline()}l.prototype.__add_outputline=function(){this.previous_line=this.current_line,this.current_line=this.next_line.clone_empty(),this.__lines.push(this.current_line)},l.prototype.get_line_number=function(){return this.__lines.length},l.prototype.get_indent_string=function(o,d){return this.__indent_cache.get_indent_string(o,d)},l.prototype.get_indent_size=function(o,d){return this.__indent_cache.get_indent_size(o,d)},l.prototype.is_empty=function(){return!this.previous_line&&this.current_line.is_empty()},l.prototype.add_new_line=function(o){return this.is_empty()||!o&&this.just_added_newline()?!1:(this.raw||this.__add_outputline(),!0)},l.prototype.get_code=function(o){this.trim(!0);var d=this.current_line.pop();d&&(d[d.length-1]===` `&&(d=d.replace(/\n+$/g,"")),this.current_line.push(d)),this._end_with_newline&&this.__add_outputline();var h=this.__lines.join(` `);return o!==` `&&(h=h.replace(/[\n]/g,o)),h},l.prototype.set_wrap_point=function(){this.current_line._set_wrap_point()},l.prototype.set_indent=function(o,d){return o=o||0,d=d||0,this.next_line.set_indent(o,d),this.__lines.length>1?(this.current_line.set_indent(o,d),!0):(this.current_line.set_indent(),!1)},l.prototype.add_raw_token=function(o){for(var d=0;d1&&this.current_line.is_empty();)this.__lines.pop(),this.current_line=this.__lines[this.__lines.length-1],this.current_line.trim();this.previous_line=this.__lines.length>1?this.__lines[this.__lines.length-2]:null},l.prototype.just_added_newline=function(){return this.current_line.is_empty()},l.prototype.just_added_blankline=function(){return this.is_empty()||this.current_line.is_empty()&&this.previous_line.is_empty()},l.prototype.ensure_empty_line_above=function(o,d){for(var h=this.__lines.length-2;h>=0;){var u=this.__lines[h];if(u.is_empty())break;if(u.item(0).indexOf(o)!==0&&u.item(-1)!==d){this.__lines.splice(h+1,0,new s(this)),this.previous_line=this.__lines[this.__lines.length-2];break}h--}},i.exports.Output=l},,,,function(i){function s(o,d){this.raw_options=a(o,d),this.disabled=this._get_boolean("disabled"),this.eol=this._get_characters("eol","auto"),this.end_with_newline=this._get_boolean("end_with_newline"),this.indent_size=this._get_number("indent_size",4),this.indent_char=this._get_characters("indent_char"," "),this.indent_level=this._get_number("indent_level"),this.preserve_newlines=this._get_boolean("preserve_newlines",!0),this.max_preserve_newlines=this._get_number("max_preserve_newlines",32786),this.preserve_newlines||(this.max_preserve_newlines=0),this.indent_with_tabs=this._get_boolean("indent_with_tabs",this.indent_char===" "),this.indent_with_tabs&&(this.indent_char=" ",this.indent_size===1&&(this.indent_size=4)),this.wrap_line_length=this._get_number("wrap_line_length",this._get_number("max_char")),this.indent_empty_lines=this._get_boolean("indent_empty_lines"),this.templating=this._get_selection_list("templating",["auto","none","angular","django","erb","handlebars","php","smarty"],["auto"])}s.prototype._get_array=function(o,d){var h=this.raw_options[o],u=d||[];return typeof h=="object"?h!==null&&typeof h.concat=="function"&&(u=h.concat()):typeof h=="string"&&(u=h.split(/[^a-zA-Z0-9_\/\-]+/)),u},s.prototype._get_boolean=function(o,d){var h=this.raw_options[o],u=h===void 0?!!d:!!h;return u},s.prototype._get_characters=function(o,d){var h=this.raw_options[o],u=d||"";return typeof h=="string"&&(u=h.replace(/\\r/,"\r").replace(/\\n/,` `).replace(/\\t/," ")),u},s.prototype._get_number=function(o,d){var h=this.raw_options[o];d=parseInt(d,10),isNaN(d)&&(d=0);var u=parseInt(h,10);return isNaN(u)&&(u=d),u},s.prototype._get_selection=function(o,d,h){var u=this._get_selection_list(o,d,h);if(u.length!==1)throw new Error("Invalid Option Value: The option '"+o+`' can only be one of the following values: `+d+` You passed in: '`+this.raw_options[o]+"'");return u[0]},s.prototype._get_selection_list=function(o,d,h){if(!d||d.length===0)throw new Error("Selection list cannot be empty.");if(h=h||[d[0]],!this._is_valid_selection(h,d))throw new Error("Invalid Default Value!");var u=this._get_array(o,h);if(!this._is_valid_selection(u,d))throw new Error("Invalid Option Value: The option '"+o+`' can contain only the following values: `+d+` You passed in: '`+this.raw_options[o]+"'");return u},s.prototype._is_valid_selection=function(o,d){return o.length&&d.length&&!o.some(function(h){return d.indexOf(h)===-1})};function a(o,d){var h={};o=l(o);var u;for(u in o)u!==d&&(h[u]=o[u]);if(d&&o[d])for(u in o[d])h[u]=o[d][u];return h}function l(o){var d={},h;for(h in o){var u=h.replace(/-/g,"_");d[u]=o[h]}return d}i.exports.Options=s,i.exports.normalizeOpts=l,i.exports.mergeOpts=a},,function(i){var s=RegExp.prototype.hasOwnProperty("sticky");function a(l){this.__input=l||"",this.__input_length=this.__input.length,this.__position=0}a.prototype.restart=function(){this.__position=0},a.prototype.back=function(){this.__position>0&&(this.__position-=1)},a.prototype.hasNext=function(){return this.__position=0&&l=0&&o=l.length&&this.__input.substring(o-l.length,o).toLowerCase()===l},i.exports.InputScanner=a},,,,,function(i){function s(a,l){a=typeof a=="string"?a:a.source,l=typeof l=="string"?l:l.source,this.__directives_block_pattern=new RegExp(a+/ beautify( \w+[:]\w+)+ /.source+l,"g"),this.__directive_pattern=/ (\w+)[:](\w+)/g,this.__directives_end_ignore_pattern=new RegExp(a+/\sbeautify\signore:end\s/.source+l,"g")}s.prototype.get_directives=function(a){if(!a.match(this.__directives_block_pattern))return null;var l={};this.__directive_pattern.lastIndex=0;for(var o=this.__directive_pattern.exec(a);o;)l[o[1]]=o[2],o=this.__directive_pattern.exec(a);return l},s.prototype.readIgnored=function(a){return a.readUntilAfter(this.__directives_end_ignore_pattern)},i.exports.Directives=s},,function(i,s,a){var l=a(16).Beautifier,o=a(17).Options;function d(h,u){var w=new l(h,u);return w.beautify()}i.exports=d,i.exports.defaultOptions=function(){return new o}},function(i,s,a){var l=a(17).Options,o=a(2).Output,d=a(8).InputScanner,h=a(13).Directives,u=new h(/\/\*/,/\*\//),w=/\r\n|[\r\n]/,b=/\r\n|[\r\n]/g,y=/\s/,E=/(?:\s|\n)+/g,A=/\/\*(?:[\s\S]*?)((?:\*\/)|$)/g,I=/\/\/(?:[^\n\r\u2028\u2029]*)/g;function P(T,j){this._source_text=T||"",this._options=new l(j),this._ch=null,this._input=null,this.NESTED_AT_RULE={page:!0,"font-face":!0,keyframes:!0,media:!0,supports:!0,document:!0},this.CONDITIONAL_GROUP_RULE={media:!0,supports:!0,document:!0},this.NON_SEMICOLON_NEWLINE_PROPERTY=["grid-template-areas","grid-template"]}P.prototype.eatString=function(T){var j="";for(this._ch=this._input.next();this._ch;){if(j+=this._ch,this._ch==="\\")j+=this._input.next();else if(T.indexOf(this._ch)!==-1||this._ch===` `)break;this._ch=this._input.next()}return j},P.prototype.eatWhitespace=function(T){for(var j=y.test(this._input.peek()),X=0;y.test(this._input.peek());)this._ch=this._input.next(),T&&this._ch===` `&&(X===0||X0&&this._indentLevel--},P.prototype.beautify=function(){if(this._options.disabled)return this._source_text;var T=this._source_text,j=this._options.eol;j==="auto"&&(j=` `,T&&w.test(T||"")&&(j=T.match(w)[0])),T=T.replace(b,` `);var X=T.match(/^[\t ]*/)[0];this._output=new o(this._options,X),this._input=new d(T),this._indentLevel=0,this._nestedLevel=0,this._ch=null;for(var Y=0,$e=!1,K=!1,_e=!1,Ie=!1,S=!1,v=this._ch,F=!1,C,N,D;C=this._input.read(E),N=C!=="",D=v,this._ch=this._input.next(),this._ch==="\\"&&this._input.hasNext()&&(this._ch+=this._input.next()),v=this._ch,this._ch;)if(this._ch==="/"&&this._input.peek()==="*"){this._output.add_new_line(),this._input.back();var M=this._input.read(A),oe=u.get_directives(M);oe&&oe.ignore==="start"&&(M+=u.readIgnored(this._input)),this.print_string(M),this.eatWhitespace(!0),this._output.add_new_line()}else if(this._ch==="/"&&this._input.peek()==="/")this._output.space_before_token=!0,this._input.back(),this.print_string(this._input.read(I)),this.eatWhitespace(!0);else if(this._ch==="$"){this.preserveSingleSpace(N),this.print_string(this._ch);var Z=this._input.peekUntilAfter(/[: ,;{}()[\]\/='"]/g);Z.match(/[ :]$/)&&(Z=this.eatString(": ").replace(/\s+$/,""),this.print_string(Z),this._output.space_before_token=!0),Y===0&&Z.indexOf(":")!==-1&&(K=!0,this.indent())}else if(this._ch==="@")if(this.preserveSingleSpace(N),this._input.peek()==="{")this.print_string(this._ch+this.eatString("}"));else{this.print_string(this._ch);var $=this._input.peekUntilAfter(/[: ,;{}()[\]\/='"]/g);$.match(/[ :]$/)&&($=this.eatString(": ").replace(/\s+$/,""),this.print_string($),this._output.space_before_token=!0),Y===0&&$.indexOf(":")!==-1?(K=!0,this.indent()):$ in this.NESTED_AT_RULE?(this._nestedLevel+=1,$ in this.CONDITIONAL_GROUP_RULE&&(_e=!0)):Y===0&&!K&&(Ie=!0)}else if(this._ch==="#"&&this._input.peek()==="{")this.preserveSingleSpace(N),this.print_string(this._ch+this.eatString("}"));else if(this._ch==="{")K&&(K=!1,this.outdent()),Ie=!1,_e?(_e=!1,$e=this._indentLevel>=this._nestedLevel):$e=this._indentLevel>=this._nestedLevel-1,this._options.newline_between_rules&&$e&&this._output.previous_line&&this._output.previous_line.item(-1)!=="{"&&this._output.ensure_empty_line_above("/",","),this._output.space_before_token=!0,this._options.brace_style==="expand"?(this._output.add_new_line(),this.print_string(this._ch),this.indent(),this._output.set_indent(this._indentLevel)):(D==="("?this._output.space_before_token=!1:D!==","&&this.indent(),this.print_string(this._ch)),this.eatWhitespace(!0),this._output.add_new_line();else if(this._ch==="}")this.outdent(),this._output.add_new_line(),D==="{"&&this._output.trim(!0),K&&(this.outdent(),K=!1),this.print_string(this._ch),$e=!1,this._nestedLevel&&this._nestedLevel--,this.eatWhitespace(!0),this._output.add_new_line(),this._options.newline_between_rules&&!this._output.just_added_blankline()&&this._input.peek()!=="}"&&this._output.add_new_line(!0),this._input.peek()===")"&&(this._output.trim(!0),this._options.brace_style==="expand"&&this._output.add_new_line(!0));else if(this._ch===":"){for(var Ue=0;Ue"||this._ch==="+"||this._ch==="~")&&!K&&Y===0)this._options.space_around_combinator?(this._output.space_before_token=!0,this.print_string(this._ch),this._output.space_before_token=!0):(this.print_string(this._ch),this.eatWhitespace(),this._ch&&y.test(this._ch)&&(this._ch=""));else if(this._ch==="]")this.print_string(this._ch);else if(this._ch==="[")this.preserveSingleSpace(N),this.print_string(this._ch);else if(this._ch==="=")this.eatWhitespace(),this.print_string("="),y.test(this._ch)&&(this._ch="");else if(this._ch==="!"&&!this._input.lookBack("\\"))this._output.space_before_token=!0,this.print_string(this._ch);else{var Co=D==='"'||D==="'";this.preserveSingleSpace(Co||N),this.print_string(this._ch),!this._output.just_added_newline()&&this._input.peek()===` `&&F&&this._output.add_new_line()}var ko=this._output.get_code(j);return ko},i.exports.Beautifier=P},function(i,s,a){var l=a(6).Options;function o(d){l.call(this,d,"css"),this.selector_separator_newline=this._get_boolean("selector_separator_newline",!0),this.newline_between_rules=this._get_boolean("newline_between_rules",!0);var h=this._get_boolean("space_around_selector_separator");this.space_around_combinator=this._get_boolean("space_around_combinator")||h;var u=this._get_selection_list("brace_style",["collapse","expand","end-expand","none","preserve-inline"]);this.brace_style="collapse";for(var w=0;w0&&fo(r,u-1);)u--;u===0||uo(r,u-1)?h=u:u0){let h=t.insertSpaces?Mr(" ",l*s):Mr(" ",s);d=d.split(` `).join(` `+h),e.start.character===0&&(d=h+d)}return[{range:e,newText:d}]}function mo(n){return n.replace(/^\s+/,"")}var qa=123,Ka=125;function Ga(n,e){for(;e>=0;){let t=n.charCodeAt(e);if(t===qa)return!0;if(t===Ka)return!1;e--}return!1}function Le(n,e,t){if(n&&n.hasOwnProperty(e)){let r=n[e];if(r!==null)return r}return t}function Ha(n,e,t){let r=e,i=0,s=t.tabSize||4;for(;r && ]#",relevance:50,description:"@counter-style descriptor. Specifies the symbols used by the marker-construction algorithm specified by the system descriptor. Needs to be specified if the counter system is 'additive'.",restrictions:["integer","string","image","identifier"]},{name:"align-content",browsers:["E12","FF28","S9","C29","IE11","O16"],values:[{name:"center",description:"Lines are packed toward the center of the flex container."},{name:"flex-end",description:"Lines are packed toward the end of the flex container."},{name:"flex-start",description:"Lines are packed toward the start of the flex container."},{name:"space-around",description:"Lines are evenly distributed in the flex container, with half-size spaces on either end."},{name:"space-between",description:"Lines are evenly distributed in the flex container."},{name:"stretch",description:"Lines stretch to take up the remaining space."},{name:"start"},{name:"end"},{name:"normal"},{name:"baseline"},{name:"first baseline"},{name:"last baseline"},{name:"space-around"},{name:"space-between"},{name:"space-evenly"},{name:"stretch"},{name:"safe"},{name:"unsafe"}],syntax:"normal | | | ? ",relevance:66,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/align-content"}],description:"Aligns a flex container's lines within the flex container when there is extra space in the cross-axis, similar to how 'justify-content' aligns individual items within the main-axis.",restrictions:["enum"]},{name:"align-items",browsers:["E12","FF20","S9","C29","IE11","O16"],values:[{name:"baseline",description:"If the flex item's inline axis is the same as the cross axis, this value is identical to 'flex-start'. Otherwise, it participates in baseline alignment."},{name:"center",description:"The flex item's margin box is centered in the cross axis within the line."},{name:"flex-end",description:"The cross-end margin edge of the flex item is placed flush with the cross-end edge of the line."},{name:"flex-start",description:"The cross-start margin edge of the flex item is placed flush with the cross-start edge of the line."},{name:"stretch",description:"If the cross size property of the flex item computes to auto, and neither of the cross-axis margins are auto, the flex item is stretched."},{name:"normal"},{name:"start"},{name:"end"},{name:"self-start"},{name:"self-end"},{name:"first baseline"},{name:"last baseline"},{name:"stretch"},{name:"safe"},{name:"unsafe"}],syntax:"normal | stretch | | [ ? ]",relevance:87,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/align-items"}],description:"Aligns flex items along the cross axis of the current line of the flex container.",restrictions:["enum"]},{name:"justify-items",browsers:["E12","FF20","S9","C52","IE11","O12.1"],values:[{name:"auto"},{name:"normal"},{name:"end"},{name:"start"},{name:"flex-end",description:'"Flex items are packed toward the end of the line."'},{name:"flex-start",description:'"Flex items are packed toward the start of the line."'},{name:"self-end",description:"The item is packed flush to the edge of the alignment container of the end side of the item, in the appropriate axis."},{name:"self-start",description:"The item is packed flush to the edge of the alignment container of the start side of the item, in the appropriate axis.."},{name:"center",description:"The items are packed flush to each other toward the center of the of the alignment container."},{name:"left"},{name:"right"},{name:"baseline"},{name:"first baseline"},{name:"last baseline"},{name:"stretch",description:"If the cross size property of the flex item computes to auto, and neither of the cross-axis margins are auto, the flex item is stretched."},{name:"safe"},{name:"unsafe"},{name:"legacy"}],syntax:"normal | stretch | | ? [ | left | right ] | legacy | legacy && [ left | right | center ]",relevance:53,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/justify-items"}],description:"Defines the default justify-self for all items of the box, giving them the default way of justifying each box along the appropriate axis",restrictions:["enum"]},{name:"justify-self",browsers:["E16","FF45","S10.1","C57","IE10","O44"],values:[{name:"auto"},{name:"normal"},{name:"end"},{name:"start"},{name:"flex-end",description:'"Flex items are packed toward the end of the line."'},{name:"flex-start",description:'"Flex items are packed toward the start of the line."'},{name:"self-end",description:"The item is packed flush to the edge of the alignment container of the end side of the item, in the appropriate axis."},{name:"self-start",description:"The item is packed flush to the edge of the alignment container of the start side of the item, in the appropriate axis.."},{name:"center",description:"The items are packed flush to each other toward the center of the of the alignment container."},{name:"left"},{name:"right"},{name:"baseline"},{name:"first baseline"},{name:"last baseline"},{name:"stretch",description:"If the cross size property of the flex item computes to auto, and neither of the cross-axis margins are auto, the flex item is stretched."},{name:"save"},{name:"unsave"}],syntax:"auto | normal | stretch | | ? [ | left | right ]",relevance:55,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/justify-self"}],description:"Defines the way of justifying a box inside its container along the appropriate axis.",restrictions:["enum"]},{name:"align-self",browsers:["E12","FF20","S9","C29","IE10","O12.1"],values:[{name:"auto",description:"Computes to the value of 'align-items' on the element's parent, or 'stretch' if the element has no parent. On absolutely positioned elements, it computes to itself."},{name:"normal"},{name:"self-end"},{name:"self-start"},{name:"baseline",description:"If the flex item's inline axis is the same as the cross axis, this value is identical to 'flex-start'. Otherwise, it participates in baseline alignment."},{name:"center",description:"The flex item's margin box is centered in the cross axis within the line."},{name:"flex-end",description:"The cross-end margin edge of the flex item is placed flush with the cross-end edge of the line."},{name:"flex-start",description:"The cross-start margin edge of the flex item is placed flush with the cross-start edge of the line."},{name:"stretch",description:"If the cross size property of the flex item computes to auto, and neither of the cross-axis margins are auto, the flex item is stretched."},{name:"baseline"},{name:"first baseline"},{name:"last baseline"},{name:"safe"},{name:"unsafe"}],syntax:"auto | normal | stretch | | ? ",relevance:73,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/align-self"}],description:"Allows the default alignment along the cross axis to be overridden for individual flex items.",restrictions:["enum"]},{name:"all",browsers:["E79","FF27","S9.1","C37","O24"],values:[],syntax:"initial | inherit | unset | revert | revert-layer",relevance:53,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/all"}],description:"Shorthand that resets all properties except 'direction' and 'unicode-bidi'.",restrictions:["enum"]},{name:"alt",browsers:["S9"],values:[],relevance:50,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/alt"}],description:"Provides alternative text for assistive technology to replace the generated content of a ::before or ::after element.",restrictions:["string","enum"]},{name:"animation",browsers:["E12","FF16","S9","C43","IE10","O30"],values:[{name:"alternate",description:"The animation cycle iterations that are odd counts are played in the normal direction, and the animation cycle iterations that are even counts are played in a reverse direction."},{name:"alternate-reverse",description:"The animation cycle iterations that are odd counts are played in the reverse direction, and the animation cycle iterations that are even counts are played in a normal direction."},{name:"backwards",description:"The beginning property value (as defined in the first @keyframes at-rule) is applied before the animation is displayed, during the period defined by 'animation-delay'."},{name:"both",description:"Both forwards and backwards fill modes are applied."},{name:"forwards",description:"The final property value (as defined in the last @keyframes at-rule) is maintained after the animation completes."},{name:"infinite",description:"Causes the animation to repeat forever."},{name:"none",description:"No animation is performed"},{name:"normal",description:"Normal playback."},{name:"reverse",description:"All iterations of the animation are played in the reverse direction from the way they were specified."}],syntax:"#",relevance:82,references:[{name:"MDN Reference",url:"https://developer.mozilla.org/docs/Web/CSS/animation"}],description:"Shorthand property combines six of the animation properties into a single property.",restrictions:["time","timing-function","enum","identifier","number"]},{name:"animation-delay",browsers:["E12","FF16","S9","C43","IE10","O30"],syntax:"